diff options
Diffstat (limited to 'include/linux/mmc')
-rw-r--r-- | include/linux/mmc/boot.h | 7 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 12 | ||||
-rw-r--r-- | include/linux/mmc/core.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/dw_mmc.h | 222 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 68 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 15 | ||||
-rw-r--r-- | include/linux/mmc/sdhci-pltfm.h | 35 | ||||
-rw-r--r-- | include/linux/mmc/sdhci.h | 150 | ||||
-rw-r--r-- | include/linux/mmc/sh_mmcif.h | 109 | ||||
-rw-r--r-- | include/linux/mmc/sh_mobile_sdhi.h | 16 | ||||
-rw-r--r-- | include/linux/mmc/tmio.h | 63 |
11 files changed, 651 insertions, 49 deletions
diff --git a/include/linux/mmc/boot.h b/include/linux/mmc/boot.h new file mode 100644 index 000000000000..39d787c229cb --- /dev/null +++ b/include/linux/mmc/boot.h @@ -0,0 +1,7 @@ +#ifndef MMC_BOOT_H +#define MMC_BOOT_H + +enum { MMC_PROGRESS_ENTER, MMC_PROGRESS_INIT, + MMC_PROGRESS_LOAD, MMC_PROGRESS_DONE }; + +#endif diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 6b7525099e56..adb4888248be 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -48,11 +48,15 @@ struct mmc_ext_csd { unsigned int sa_timeout; /* Units: 100ns */ unsigned int hs_max_dtr; unsigned int sectors; + unsigned int card_type; unsigned int hc_erase_size; /* In sectors */ unsigned int hc_erase_timeout; /* In milliseconds */ unsigned int sec_trim_mult; /* Secure trim multiplier */ unsigned int sec_erase_mult; /* Secure erase multiplier */ unsigned int trim_timeout; /* In milliseconds */ + bool enhanced_area_en; /* enable bit */ + unsigned long long enhanced_area_offset; /* Units: Byte */ + unsigned int enhanced_area_size; /* Units: KB */ }; struct sd_scr { @@ -113,12 +117,14 @@ struct mmc_card { #define MMC_STATE_READONLY (1<<1) /* card is read-only */ #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ +#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ unsigned int quirks; /* card quirks */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ /* for byte mode */ #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */ /* (missing CIA registers) */ +#define MMC_QUIRK_BROKEN_CLK_GATING (1<<3) /* clock gating the sdio bus will make card fail */ unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ @@ -146,6 +152,8 @@ struct mmc_card { struct dentry *debugfs_root; }; +void mmc_fixup_device(struct mmc_card *dev); + #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) #define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) #define mmc_card_sdio(c) ((c)->type == MMC_TYPE_SDIO) @@ -154,11 +162,13 @@ struct mmc_card { #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) +#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) +#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) static inline int mmc_card_lenient_fn0(const struct mmc_card *c) { @@ -173,6 +183,8 @@ static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c) #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) +#define mmc_dev_to_card(d) container_of(d, struct mmc_card, dev) + #define mmc_list_to_card(l) container_of(l, struct mmc_card, node) #define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) #define mmc_set_drvdata(c,d) dev_set_drvdata(&(c)->dev, d) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 7429033acb66..07f27af4dba5 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -153,11 +153,14 @@ extern int mmc_can_secure_erase_trim(struct mmc_card *card); extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, unsigned int nr); +extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); + extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); +extern void mmc_do_release_host(struct mmc_host *host); extern int mmc_try_claim_host(struct mmc_host *host); /** diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h new file mode 100644 index 000000000000..bdd7ceeb99e4 --- /dev/null +++ b/include/linux/mmc/dw_mmc.h @@ -0,0 +1,222 @@ +/* + * Synopsys DesignWare Multimedia Card Interface driver + * (Based on NXP driver for lpc 31xx) + * + * Copyright (C) 2009 NXP Semiconductors + * Copyright (C) 2009, 2010 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _LINUX_MMC_DW_MMC_H_ +#define _LINUX_MMC_DW_MMC_H_ + +#define MAX_MCI_SLOTS 2 + +enum dw_mci_state { + STATE_IDLE = 0, + STATE_SENDING_CMD, + STATE_SENDING_DATA, + STATE_DATA_BUSY, + STATE_SENDING_STOP, + STATE_DATA_ERROR, +}; + +enum { + EVENT_CMD_COMPLETE = 0, + EVENT_XFER_COMPLETE, + EVENT_DATA_COMPLETE, + EVENT_DATA_ERROR, + EVENT_XFER_ERROR +}; + +struct mmc_data; + +/** + * struct dw_mci - MMC controller state shared between all slots + * @lock: Spinlock protecting the queue and associated data. + * @regs: Pointer to MMIO registers. + * @sg: Scatterlist entry currently being processed by PIO code, if any. + * @pio_offset: Offset into the current scatterlist entry. + * @cur_slot: The slot which is currently using the controller. + * @mrq: The request currently being processed on @cur_slot, + * or NULL if the controller is idle. + * @cmd: The command currently being sent to the card, or NULL. + * @data: The data currently being transferred, or NULL if no data + * transfer is in progress. + * @use_dma: Whether DMA channel is initialized or not. + * @sg_dma: Bus address of DMA buffer. + * @sg_cpu: Virtual address of DMA buffer. + * @dma_ops: Pointer to platform-specific DMA callbacks. + * @cmd_status: Snapshot of SR taken upon completion of the current + * command. Only valid when EVENT_CMD_COMPLETE is pending. + * @data_status: Snapshot of SR taken upon completion of the current + * data transfer. Only valid when EVENT_DATA_COMPLETE or + * EVENT_DATA_ERROR is pending. + * @stop_cmdr: Value to be loaded into CMDR when the stop command is + * to be sent. + * @dir_status: Direction of current transfer. + * @tasklet: Tasklet running the request state machine. + * @card_tasklet: Tasklet handling card detect. + * @pending_events: Bitmask of events flagged by the interrupt handler + * to be processed by the tasklet. + * @completed_events: Bitmask of events which the state machine has + * processed. + * @state: Tasklet state. + * @queue: List of slots waiting for access to the controller. + * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus + * rate and timeout calculations. + * @current_speed: Configured rate of the controller. + * @num_slots: Number of slots available. + * @pdev: Platform device associated with the MMC controller. + * @pdata: Platform data associated with the MMC controller. + * @slot: Slots sharing this MMC controller. + * @data_shift: log2 of FIFO item size. + * @push_data: Pointer to FIFO push function. + * @pull_data: Pointer to FIFO pull function. + * @quirks: Set of quirks that apply to specific versions of the IP. + * + * Locking + * ======= + * + * @lock is a softirq-safe spinlock protecting @queue as well as + * @cur_slot, @mrq and @state. These must always be updated + * at the same time while holding @lock. + * + * The @mrq field of struct dw_mci_slot is also protected by @lock, + * and must always be written at the same time as the slot is added to + * @queue. + * + * @pending_events and @completed_events are accessed using atomic bit + * operations, so they don't need any locking. + * + * None of the fields touched by the interrupt handler need any + * locking. However, ordering is important: Before EVENT_DATA_ERROR or + * EVENT_DATA_COMPLETE is set in @pending_events, all data-related + * interrupts must be disabled and @data_status updated with a + * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the + * CMDRDY interrupt must be disabled and @cmd_status updated with a + * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the + * bytes_xfered field of @data must be written. This is ensured by + * using barriers. + */ +struct dw_mci { + spinlock_t lock; + void __iomem *regs; + + struct scatterlist *sg; + unsigned int pio_offset; + + struct dw_mci_slot *cur_slot; + struct mmc_request *mrq; + struct mmc_command *cmd; + struct mmc_data *data; + + /* DMA interface members*/ + int use_dma; + + dma_addr_t sg_dma; + void *sg_cpu; + struct dw_mci_dma_ops *dma_ops; +#ifdef CONFIG_MMC_DW_IDMAC + unsigned int ring_size; +#else + struct dw_mci_dma_data *dma_data; +#endif + u32 cmd_status; + u32 data_status; + u32 stop_cmdr; + u32 dir_status; + struct tasklet_struct tasklet; + struct tasklet_struct card_tasklet; + unsigned long pending_events; + unsigned long completed_events; + enum dw_mci_state state; + struct list_head queue; + + u32 bus_hz; + u32 current_speed; + u32 num_slots; + u32 fifoth_val; + struct platform_device *pdev; + struct dw_mci_board *pdata; + struct dw_mci_slot *slot[MAX_MCI_SLOTS]; + + /* FIFO push and pull */ + int data_shift; + void (*push_data)(struct dw_mci *host, void *buf, int cnt); + void (*pull_data)(struct dw_mci *host, void *buf, int cnt); + + /* Workaround flags */ + u32 quirks; + + struct regulator *vmmc; /* Power regulator */ +}; + +/* DMA ops for Internal/External DMAC interface */ +struct dw_mci_dma_ops { + /* DMA Ops */ + int (*init)(struct dw_mci *host); + void (*start)(struct dw_mci *host, unsigned int sg_len); + void (*complete)(struct dw_mci *host); + void (*stop)(struct dw_mci *host); + void (*cleanup)(struct dw_mci *host); + void (*exit)(struct dw_mci *host); +}; + +/* IP Quirks/flags. */ +/* DTO fix for command transmission with IDMAC configured */ +#define DW_MCI_QUIRK_IDMAC_DTO BIT(0) +/* delay needed between retries on some 2.11a implementations */ +#define DW_MCI_QUIRK_RETRY_DELAY BIT(1) +/* High Speed Capable - Supports HS cards (up to 50MHz) */ +#define DW_MCI_QUIRK_HIGHSPEED BIT(2) +/* Unreliable card detection */ +#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) + + +struct dma_pdata; + +struct block_settings { + unsigned short max_segs; /* see blk_queue_max_segments */ + unsigned int max_blk_size; /* maximum size of one mmc block */ + unsigned int max_blk_count; /* maximum number of blocks in one req*/ + unsigned int max_req_size; /* maximum number of bytes in one req*/ + unsigned int max_seg_size; /* see blk_queue_max_segment_size */ +}; + +/* Board platform data */ +struct dw_mci_board { + u32 num_slots; + + u32 quirks; /* Workaround / Quirk flags */ + unsigned int bus_hz; /* Bus speed */ + + unsigned int caps; /* Capabilities */ + + /* delay in mS before detecting cards after interrupt */ + u32 detect_delay_ms; + + int (*init)(u32 slot_id, irq_handler_t , void *); + int (*get_ro)(u32 slot_id); + int (*get_cd)(u32 slot_id); + int (*get_ocr)(u32 slot_id); + int (*get_bus_wd)(u32 slot_id); + /* + * Enable power to selected slot and set voltage to desired level. + * Voltage levels are specified using MMC_VDD_xxx defines defined + * in linux/mmc/host.h file. + */ + void (*setpower)(u32 slot_id, u32 volt); + void (*exit)(u32 slot_id); + void (*select_slot)(u32 slot_id); + + struct dw_mci_dma_ops *dma_ops; + struct dma_pdata *data; + struct block_settings *blk_settings; +}; + +#endif /* _LINUX_MMC_DW_MMC_H_ */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 1575b52c3bfa..bcb793ec7374 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -50,6 +50,12 @@ struct mmc_ios { #define MMC_TIMING_LEGACY 0 #define MMC_TIMING_MMC_HS 1 #define MMC_TIMING_SD_HS 2 + + unsigned char ddr; /* dual data rate used */ + +#define MMC_SDR_MODE 0 +#define MMC_1_2V_DDR_MODE 1 +#define MMC_1_8V_DDR_MODE 2 }; struct mmc_host_ops { @@ -123,7 +129,11 @@ struct mmc_host { const struct mmc_host_ops *ops; unsigned int f_min; unsigned int f_max; + unsigned int f_init; u32 ocr_avail; + u32 ocr_avail_sdio; /* SDIO-specific OCR */ + u32 ocr_avail_sd; /* SD-specific OCR */ + u32 ocr_avail_mmc; /* MMC-specific OCR */ struct notifier_block pm_notify; #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ @@ -157,13 +167,28 @@ struct mmc_host { #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ +#define MMC_CAP_1_8V_DDR (1 << 11) /* can support */ + /* DDR mode at 1.8V */ +#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ + /* DDR mode at 1.2V */ +#define MMC_CAP_POWER_OFF_CARD (1 << 13) /* Can power off after boot */ +#define MMC_CAP_BUS_WIDTH_TEST (1 << 14) /* CMD14/CMD19 bus width ok */ mmc_pm_flag_t pm_caps; /* supported pm features */ +#ifdef CONFIG_MMC_CLKGATE + int clk_requests; /* internal reference counter */ + unsigned int clk_delay; /* number of MCI clk hold cycles */ + bool clk_gated; /* clock gated */ + struct work_struct clk_gate_work; /* delayed clock gate */ + unsigned int clk_old; /* old clock value cache */ + spinlock_t clk_lock; /* lock for clk fields */ + struct mutex clk_gate_mutex; /* mutex for clock gating */ +#endif + /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ - unsigned short max_hw_segs; /* see blk_queue_max_hw_segments */ - unsigned short max_phys_segs; /* see blk_queue_max_phys_segments */ + unsigned short max_segs; /* see blk_queue_max_segments */ unsigned short unused; unsigned int max_req_size; /* maximum number of bytes in one req */ unsigned int max_blk_size; /* maximum size of one mmc block */ @@ -212,6 +237,10 @@ struct mmc_host { struct led_trigger *led; /* activity led */ #endif +#ifdef CONFIG_REGULATOR + bool regulator_enabled; /* regulator state */ +#endif + struct dentry *debugfs_root; unsigned long private[0] ____cacheline_aligned; @@ -236,8 +265,8 @@ static inline void *mmc_priv(struct mmc_host *host) extern int mmc_suspend_host(struct mmc_host *); extern int mmc_resume_host(struct mmc_host *); -extern void mmc_power_save_host(struct mmc_host *host); -extern void mmc_power_restore_host(struct mmc_host *host); +extern int mmc_power_save_host(struct mmc_host *host); +extern int mmc_power_restore_host(struct mmc_host *host); extern void mmc_detect_change(struct mmc_host *, unsigned long delay); extern void mmc_request_done(struct mmc_host *, struct mmc_request *); @@ -250,8 +279,24 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) struct regulator; +#ifdef CONFIG_REGULATOR int mmc_regulator_get_ocrmask(struct regulator *supply); -int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit); +int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit); +#else +static inline int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + return 0; +} + +static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit) +{ + return 0; +} +#endif int mmc_card_awake(struct mmc_host *host); int mmc_card_sleep(struct mmc_host *host); @@ -268,5 +313,18 @@ static inline void mmc_set_disable_delay(struct mmc_host *host, host->disable_delay = disable_delay; } +/* Module parameter */ +extern int mmc_assume_removable; + +static inline int mmc_card_is_removable(struct mmc_host *host) +{ + return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable; +} + +static inline int mmc_card_is_powered_resumed(struct mmc_host *host) +{ + return host->pm_flags & MMC_PM_KEEP_POWER; +} + #endif diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index dd11ae51fb68..264ba5451e3b 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -40,7 +40,9 @@ #define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ #define MMC_STOP_TRANSMISSION 12 /* ac R1b */ #define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ +#define MMC_BUS_TEST_R 14 /* adtc R1 */ #define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ +#define MMC_BUS_TEST_W 19 /* adtc R1 */ #define MMC_SPI_READ_OCR 58 /* spi spi_R3 */ #define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */ @@ -251,6 +253,8 @@ struct _mmc_csd { * EXT_CSD fields */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ @@ -260,6 +264,7 @@ struct _mmc_csd { #define EXT_CSD_CARD_TYPE 196 /* RO */ #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ @@ -277,11 +282,19 @@ struct _mmc_csd { #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ -#define EXT_CSD_CARD_TYPE_MASK 0x3 /* Mask out reserved and DDR bits */ +#define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */ +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ +#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ #define EXT_CSD_SEC_ER_EN BIT(0) #define EXT_CSD_SEC_BD_BLK_EN BIT(2) diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h new file mode 100644 index 000000000000..548d59d404cb --- /dev/null +++ b/include/linux/mmc/sdhci-pltfm.h @@ -0,0 +1,35 @@ +/* + * Platform data declarations for the sdhci-pltfm driver. + * + * Copyright (c) 2010 MontaVista Software, LLC. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#ifndef _SDHCI_PLTFM_H +#define _SDHCI_PLTFM_H + +struct sdhci_ops; +struct sdhci_host; + +/** + * struct sdhci_pltfm_data - SDHCI platform-specific information & hooks + * @ops: optional pointer to the platform-provided SDHCI ops + * @quirks: optional SDHCI quirks + * @init: optional hook that is called during device probe, before the + * driver tries to access any SDHCI registers + * @exit: optional hook that is called during device removal + */ +struct sdhci_pltfm_data { + struct sdhci_ops *ops; + unsigned int quirks; + int (*init)(struct sdhci_host *host, struct sdhci_pltfm_data *pdata); + void (*exit)(struct sdhci_host *host); +}; + +#endif /* _SDHCI_PLTFM_H */ diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h new file mode 100644 index 000000000000..83bd9f76709a --- /dev/null +++ b/include/linux/mmc/sdhci.h @@ -0,0 +1,150 @@ +/* + * linux/include/linux/mmc/sdhci.h - Secure Digital Host Controller Interface + * + * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ +#ifndef __SDHCI_H +#define __SDHCI_H + +#include <linux/scatterlist.h> +#include <linux/compiler.h> +#include <linux/types.h> +#include <linux/io.h> +#include <linux/mmc/host.h> + +struct sdhci_host { + /* Data set by hardware interface driver */ + const char *hw_name; /* Hardware bus name */ + + unsigned int quirks; /* Deviations from spec. */ + +/* Controller doesn't honor resets unless we touch the clock register */ +#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) +/* Controller has bad caps bits, but really supports DMA */ +#define SDHCI_QUIRK_FORCE_DMA (1<<1) +/* Controller doesn't like to be reset when there is no card inserted. */ +#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) +/* Controller doesn't like clearing the power reg before a change */ +#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) +/* Controller has flaky internal state so reset it on each ios change */ +#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) +/* Controller has an unusable DMA engine */ +#define SDHCI_QUIRK_BROKEN_DMA (1<<5) +/* Controller has an unusable ADMA engine */ +#define SDHCI_QUIRK_BROKEN_ADMA (1<<6) +/* Controller can only DMA from 32-bit aligned addresses */ +#define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) +/* Controller can only DMA chunk sizes that are a multiple of 32 bits */ +#define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) +/* Controller can only ADMA chunks that are a multiple of 32 bits */ +#define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) +/* Controller needs to be reset after each request to stay stable */ +#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10) +/* Controller needs voltage and power writes to happen separately */ +#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) +/* Controller provides an incorrect timeout value for transfers */ +#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) +/* Controller has an issue with buffer bits for small transfers */ +#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) +/* Controller does not provide transfer-complete interrupt when not busy */ +#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) +/* Controller has unreliable card detection */ +#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) +/* Controller reports inverted write-protect state */ +#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) +/* Controller has nonstandard clock management */ +#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17) +/* Controller does not like fast PIO transfers */ +#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) +/* Controller losing signal/interrupt enable states after reset */ +#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) +/* Controller has to be forced to use block size of 2048 bytes */ +#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) +/* Controller cannot do multi-block transfers */ +#define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) +/* Controller can only handle 1-bit data transfers */ +#define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) +/* Controller needs 10ms delay between applying power and clock */ +#define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) +/* Controller uses SDCLK instead of TMCLK for data timeouts */ +#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) +/* Controller reports wrong base clock capability */ +#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) +/* Controller cannot support End Attribute in NOP ADMA descriptor */ +#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) +/* Controller is missing device caps. Use caps provided by host */ +#define SDHCI_QUIRK_MISSING_CAPS (1<<27) +/* Controller uses Auto CMD12 command to stop the transfer */ +#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) +/* Controller doesn't have HISPD bit field in HI-SPEED SD card */ +#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) +/* Controller treats ADMA descriptors with length 0000h incorrectly */ +#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30) + + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + + const struct sdhci_ops *ops; /* Low level hw interface */ + + struct regulator *vmmc; /* Power regulator */ + + /* Internal data */ + struct mmc_host *mmc; /* MMC structure */ + u64 dma_mask; /* custom DMA mask */ + +#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) + struct led_classdev led; /* LED control */ + char led_name[32]; +#endif + + spinlock_t lock; /* Mutex */ + + int flags; /* Host attributes */ +#define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ +#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ +#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ +#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ + + unsigned int version; /* SDHCI spec. version */ + + unsigned int max_clk; /* Max possible freq (MHz) */ + unsigned int timeout_clk; /* Timeout freq (KHz) */ + + unsigned int clock; /* Current clock (MHz) */ + u8 pwr; /* Current voltage */ + + struct mmc_request *mrq; /* Current request */ + struct mmc_command *cmd; /* Current command */ + struct mmc_data *data; /* Current data request */ + unsigned int data_early:1; /* Data finished before cmd */ + + struct sg_mapping_iter sg_miter; /* SG state for PIO */ + unsigned int blocks; /* remaining PIO blocks */ + + int sg_count; /* Mapped sg entries */ + + u8 *adma_desc; /* ADMA descriptor table */ + u8 *align_buffer; /* Bounce buffer */ + + dma_addr_t adma_addr; /* Mapped ADMA descr. table */ + dma_addr_t align_addr; /* Mapped bounce buffer */ + + struct tasklet_struct card_tasklet; /* Tasklet structures */ + struct tasklet_struct finish_tasklet; + + struct timer_list timer; /* Timer for timeouts */ + + unsigned int caps; /* Alternative capabilities */ + + unsigned int ocr_avail_sdio; /* OCR bit masks */ + unsigned int ocr_avail_sd; + unsigned int ocr_avail_mmc; + + unsigned long private[0] ____cacheline_aligned; +}; +#endif /* __SDHCI_H */ diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h index d4a2ebbdab4b..9eb9b4b96f55 100644 --- a/include/linux/mmc/sh_mmcif.h +++ b/include/linux/mmc/sh_mmcif.h @@ -14,8 +14,9 @@ #ifndef __SH_MMCIF_H__ #define __SH_MMCIF_H__ -#include <linux/platform_device.h> #include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/sh_dma.h> /* * MMCIF : CE_CLK_CTRL [19:16] @@ -31,12 +32,19 @@ * 1111 : Peripheral clock (sup_pclk set '1') */ +struct sh_mmcif_dma { + struct sh_dmae_slave chan_priv_tx; + struct sh_dmae_slave chan_priv_rx; +}; + struct sh_mmcif_plat_data { void (*set_pwr)(struct platform_device *pdev, int state); void (*down_pwr)(struct platform_device *pdev); - u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ - unsigned long caps; - u32 ocr; + int (*get_cd)(struct platform_device *pdef); + struct sh_mmcif_dma *dma; + u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ + unsigned long caps; + u32 ocr; }; #define MMCIF_CE_CMD_SET 0x00000000 @@ -58,19 +66,45 @@ struct sh_mmcif_plat_data { #define MMCIF_CE_HOST_STS2 0x0000004C #define MMCIF_CE_VERSION 0x0000007C -extern inline u32 sh_mmcif_readl(void __iomem *addr, int reg) +/* CE_BUF_ACC */ +#define BUF_ACC_DMAWEN (1 << 25) +#define BUF_ACC_DMAREN (1 << 24) +#define BUF_ACC_BUSW_32 (0 << 17) +#define BUF_ACC_BUSW_16 (1 << 17) +#define BUF_ACC_ATYP (1 << 16) + +/* CE_CLK_CTRL */ +#define CLK_ENABLE (1 << 24) /* 1: output mmc clock */ +#define CLK_CLEAR ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) +#define CLK_SUP_PCLK ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) +#define CLKDIV_4 (1<<16) /* mmc clock frequency. + * n: bus clock/(2^(n+1)) */ +#define CLKDIV_256 (7<<16) /* mmc clock frequency. (see above) */ +#define SRSPTO_256 ((1 << 13) | (0 << 12)) /* resp timeout */ +#define SRBSYTO_29 ((1 << 11) | (1 << 10) | \ + (1 << 9) | (1 << 8)) /* resp busy timeout */ +#define SRWDTO_29 ((1 << 7) | (1 << 6) | \ + (1 << 5) | (1 << 4)) /* read/write timeout */ +#define SCCSTO_29 ((1 << 3) | (1 << 2) | \ + (1 << 1) | (1 << 0)) /* ccs timeout */ + +/* CE_VERSION */ +#define SOFT_RST_ON (1 << 31) +#define SOFT_RST_OFF 0 + +static inline u32 sh_mmcif_readl(void __iomem *addr, int reg) { - return readl(addr + reg); + return __raw_readl(addr + reg); } -extern inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) +static inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) { - writel(val, addr + reg); + __raw_writel(val, addr + reg); } #define SH_MMCIF_BBS 512 /* boot block size */ -extern inline void sh_mmcif_boot_cmd_send(void __iomem *base, +static inline void sh_mmcif_boot_cmd_send(void __iomem *base, unsigned long cmd, unsigned long arg) { sh_mmcif_writel(base, MMCIF_CE_INT, 0); @@ -78,7 +112,7 @@ extern inline void sh_mmcif_boot_cmd_send(void __iomem *base, sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd); } -extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) +static inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) { unsigned long tmp; int cnt; @@ -94,14 +128,14 @@ extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) return -1; } -extern inline int sh_mmcif_boot_cmd(void __iomem *base, +static inline int sh_mmcif_boot_cmd(void __iomem *base, unsigned long cmd, unsigned long arg) { sh_mmcif_boot_cmd_send(base, cmd, arg); return sh_mmcif_boot_cmd_poll(base, 0x00010000); } -extern inline int sh_mmcif_boot_do_read_single(void __iomem *base, +static inline int sh_mmcif_boot_do_read_single(void __iomem *base, unsigned int block_nr, unsigned long *buf) { @@ -124,7 +158,7 @@ extern inline int sh_mmcif_boot_do_read_single(void __iomem *base, return 0; } -extern inline int sh_mmcif_boot_do_read(void __iomem *base, +static inline int sh_mmcif_boot_do_read(void __iomem *base, unsigned long first_block, unsigned long nr_blocks, void *buf) @@ -132,6 +166,17 @@ extern inline int sh_mmcif_boot_do_read(void __iomem *base, unsigned long k; int ret = 0; + /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */ + sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, + CLK_ENABLE | CLKDIV_4 | SRSPTO_256 | + SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); + + /* CMD9 - Get CSD */ + sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000); + + /* CMD7 - Select the card */ + sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000); + /* CMD16 - Set the block size */ sh_mmcif_boot_cmd(base, 0x10400000, SH_MMCIF_BBS); @@ -142,23 +187,22 @@ extern inline int sh_mmcif_boot_do_read(void __iomem *base, return ret; } -extern inline void sh_mmcif_boot_init(void __iomem *base) +static inline void sh_mmcif_boot_init(void __iomem *base) { - unsigned long tmp; - /* reset */ - tmp = sh_mmcif_readl(base, MMCIF_CE_VERSION); - sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp | 0x80000000); - sh_mmcif_writel(base, MMCIF_CE_VERSION, tmp & ~0x80000000); + sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_ON); + sh_mmcif_writel(base, MMCIF_CE_VERSION, SOFT_RST_OFF); /* byte swap */ - sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, 0x00010000); + sh_mmcif_writel(base, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); /* Set block size in MMCIF hardware */ sh_mmcif_writel(base, MMCIF_CE_BLOCK_SET, SH_MMCIF_BBS); - /* Enable the clock, set it to Bus clock/256 (about 325Khz)*/ - sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01072fff); + /* Enable the clock, set it to Bus clock/256 (about 325Khz). */ + sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, + CLK_ENABLE | CLKDIV_256 | SRSPTO_256 | + SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); /* CMD0 */ sh_mmcif_boot_cmd(base, 0x00000040, 0); @@ -176,25 +220,4 @@ extern inline void sh_mmcif_boot_init(void __iomem *base) sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); } -extern inline void sh_mmcif_boot_slurp(void __iomem *base, - unsigned char *buf, - unsigned long no_bytes) -{ - unsigned long tmp; - - /* In data transfer mode: Set clock to Bus clock/4 (about 20Mhz) */ - sh_mmcif_writel(base, MMCIF_CE_CLK_CTRL, 0x01012fff); - - /* CMD9 - Get CSD */ - sh_mmcif_boot_cmd(base, 0x09806000, 0x00010000); - - /* CMD7 - Select the card */ - sh_mmcif_boot_cmd(base, 0x07400000, 0x00010000); - - tmp = no_bytes / SH_MMCIF_BBS; - tmp += (no_bytes % SH_MMCIF_BBS) ? 1 : 0; - - sh_mmcif_boot_do_read(base, 512, tmp, buf); -} - #endif /* __SH_MMCIF_H__ */ diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h new file mode 100644 index 000000000000..c981b959760f --- /dev/null +++ b/include/linux/mmc/sh_mobile_sdhi.h @@ -0,0 +1,16 @@ +#ifndef __SH_MOBILE_SDHI_H__ +#define __SH_MOBILE_SDHI_H__ + +#include <linux/types.h> + +struct sh_mobile_sdhi_info { + int dma_slave_tx; + int dma_slave_rx; + unsigned long tmio_flags; + unsigned long tmio_caps; + u32 tmio_ocr_mask; /* available MMC voltages */ + void (*set_pwr)(struct platform_device *pdev, int state); + int (*get_cd)(struct platform_device *pdev); +}; + +#endif /* __SH_MOBILE_SDHI_H__ */ diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h new file mode 100644 index 000000000000..19490b942db0 --- /dev/null +++ b/include/linux/mmc/tmio.h @@ -0,0 +1,63 @@ +/* + * include/linux/mmc/tmio.h + * + * Copyright (C) 2007 Ian Molton + * Copyright (C) 2004 Ian Molton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the MMC / SD / SDIO cell found in: + * + * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3 + */ +#ifndef _LINUX_MMC_TMIO_H_ +#define _LINUX_MMC_TMIO_H_ + +#define CTL_SD_CMD 0x00 +#define CTL_ARG_REG 0x04 +#define CTL_STOP_INTERNAL_ACTION 0x08 +#define CTL_XFER_BLK_COUNT 0xa +#define CTL_RESPONSE 0x0c +#define CTL_STATUS 0x1c +#define CTL_IRQ_MASK 0x20 +#define CTL_SD_CARD_CLK_CTL 0x24 +#define CTL_SD_XFER_LEN 0x26 +#define CTL_SD_MEM_CARD_OPT 0x28 +#define CTL_SD_ERROR_DETAIL_STATUS 0x2c +#define CTL_SD_DATA_PORT 0x30 +#define CTL_TRANSACTION_CTL 0x34 +#define CTL_SDIO_STATUS 0x36 +#define CTL_SDIO_IRQ_MASK 0x38 +#define CTL_RESET_SD 0xe0 +#define CTL_SDIO_REGS 0x100 +#define CTL_CLK_AND_WAIT_CTL 0x138 +#define CTL_RESET_SDIO 0x1e0 + +/* Definitions for values the CTRL_STATUS register can take. */ +#define TMIO_STAT_CMDRESPEND 0x00000001 +#define TMIO_STAT_DATAEND 0x00000004 +#define TMIO_STAT_CARD_REMOVE 0x00000008 +#define TMIO_STAT_CARD_INSERT 0x00000010 +#define TMIO_STAT_SIGSTATE 0x00000020 +#define TMIO_STAT_WRPROTECT 0x00000080 +#define TMIO_STAT_CARD_REMOVE_A 0x00000100 +#define TMIO_STAT_CARD_INSERT_A 0x00000200 +#define TMIO_STAT_SIGSTATE_A 0x00000400 +#define TMIO_STAT_CMD_IDX_ERR 0x00010000 +#define TMIO_STAT_CRCFAIL 0x00020000 +#define TMIO_STAT_STOPBIT_ERR 0x00040000 +#define TMIO_STAT_DATATIMEOUT 0x00080000 +#define TMIO_STAT_RXOVERFLOW 0x00100000 +#define TMIO_STAT_TXUNDERRUN 0x00200000 +#define TMIO_STAT_CMDTIMEOUT 0x00400000 +#define TMIO_STAT_RXRDY 0x01000000 +#define TMIO_STAT_TXRQ 0x02000000 +#define TMIO_STAT_ILL_FUNC 0x20000000 +#define TMIO_STAT_CMD_BUSY 0x40000000 +#define TMIO_STAT_ILL_ACCESS 0x80000000 + +#define TMIO_BBS 512 /* Boot block size */ + +#endif /* _LINUX_MMC_TMIO_H_ */ |