From f39b2dd9d065151a04f5996656d1f27a7eb32d45 Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Thu, 7 Jul 2011 09:04:55 -0700 Subject: mmc: core: Bus width testing needs to handle suspend/resume On reading the ext_csd for the first time (in 1 bit mode), save the ext_csd information needed for bus width compare. On every pass we make re-reading the ext_csd, compare the data against the saved ext_csd data. This fixes a regression introduced in 3.0-rc1 by 08ee80cc397ac1a3 ("mmc: core: eMMC bus width may not work on all platforms"), which incorrectly assumed we would be re-reading the ext_csd at resume- time. Signed-off-by: Philip Rakity Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- include/linux/mmc/card.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index c6927a4d157f..6ad43554ac05 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -64,6 +64,19 @@ struct mmc_ext_csd { unsigned long long enhanced_area_offset; /* Units: Byte */ unsigned int enhanced_area_size; /* Units: KB */ unsigned int boot_size; /* in bytes */ + u8 raw_partition_support; /* 160 */ + u8 raw_erased_mem_count; /* 181 */ + u8 raw_ext_csd_structure; /* 194 */ + u8 raw_card_type; /* 196 */ + u8 raw_s_a_timeout; /* 217 */ + u8 raw_hc_erase_gap_size; /* 221 */ + u8 raw_erase_timeout_mult; /* 223 */ + u8 raw_hc_erase_grp_size; /* 224 */ + u8 raw_sec_trim_mult; /* 229 */ + u8 raw_sec_erase_mult; /* 230 */ + u8 raw_sec_feature_support;/* 231 */ + u8 raw_trim_mult; /* 232 */ + u8 raw_sectors[4]; /* 212 - 4 bytes */ }; struct sd_scr { -- cgit v1.2.3 From 85d6509dc8ca24b2b652863ef7a75622ddca17d6 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 27 May 2011 23:48:12 +0800 Subject: mmc: sdhci: make sdhci-pltfm device drivers self registered The patch turns the common stuff in sdhci-pltfm.c into functions, and add device drivers their own .probe and .remove which in turn call into the common functions, so that those sdhci-pltfm device drivers register itself and keep all device specific things away from common sdhci-pltfm file. Signed-off-by: Shawn Guo Reviewed-by: Grant Likely Acked-by: Arnd Bergmann Acked-by: Anton Vorontsov Signed-off-by: Chris Ball --- include/linux/mmc/sdhci-pltfm.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h index 548d59d404cb..f1c2ac3fb300 100644 --- a/include/linux/mmc/sdhci-pltfm.h +++ b/include/linux/mmc/sdhci-pltfm.h @@ -15,21 +15,15 @@ #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 */ -- cgit v1.2.3 From 94cc6a86567cb3c2234807081a46ce5400c36b31 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 27 May 2011 23:48:15 +0800 Subject: mmc: sdhci: merge two sdhci-pltfm.h into one The structure sdhci_pltfm_data is not necessarily to be in a public header like include/linux/mmc/sdhci-pltfm.h, so the patch moves it into drivers/mmc/host/sdhci-pltfm.h and eliminates the former one. Signed-off-by: Shawn Guo Reviewed-by: Grant Likely Reviewed-by: Wolfram Sang Signed-off-by: Chris Ball --- include/linux/mmc/sdhci-pltfm.h | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 include/linux/mmc/sdhci-pltfm.h (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h deleted file mode 100644 index f1c2ac3fb300..000000000000 --- a/include/linux/mmc/sdhci-pltfm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Platform data declarations for the sdhci-pltfm driver. - * - * Copyright (c) 2010 MontaVista Software, LLC. - * - * Author: Anton Vorontsov - * - * 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_pltfm_data - SDHCI platform-specific information & hooks - * @ops: optional pointer to the platform-provided SDHCI ops - * @quirks: optional SDHCI quirks - */ -struct sdhci_pltfm_data { - struct sdhci_ops *ops; - unsigned int quirks; -}; - -#endif /* _SDHCI_PLTFM_H */ -- cgit v1.2.3 From 100e918610b7487fa18db97b3879cd8d1fdd5974 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Fri, 27 May 2011 16:04:03 -0400 Subject: mmc: Standardize header file inclusion checks. Standardize the checks for multiple MMC header file inclusion, including adding comments to terminating #endif's, and fixing one incorrect comment. Signed-off-by: Robert P. J. Day Signed-off-by: Chris Ball --- include/linux/mmc/boot.h | 6 +++--- include/linux/mmc/card.h | 2 +- include/linux/mmc/core.h | 2 +- include/linux/mmc/dw_mmc.h | 6 +++--- include/linux/mmc/host.h | 3 +-- include/linux/mmc/ioctl.h | 2 +- include/linux/mmc/mmc.h | 7 +++---- include/linux/mmc/pm.h | 2 +- include/linux/mmc/sd.h | 7 +++---- include/linux/mmc/sdhci-spear.h | 6 +++--- include/linux/mmc/sdhci.h | 6 +++--- include/linux/mmc/sdio.h | 7 +++---- include/linux/mmc/sdio_func.h | 7 +++---- include/linux/mmc/sdio_ids.h | 6 +++--- include/linux/mmc/sh_mmcif.h | 6 +++--- include/linux/mmc/sh_mobile_sdhi.h | 6 +++--- include/linux/mmc/tmio.h | 6 +++--- 17 files changed, 41 insertions(+), 46 deletions(-) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/boot.h b/include/linux/mmc/boot.h index 39d787c229cb..23acc3baa07d 100644 --- a/include/linux/mmc/boot.h +++ b/include/linux/mmc/boot.h @@ -1,7 +1,7 @@ -#ifndef MMC_BOOT_H -#define MMC_BOOT_H +#ifndef LINUX_MMC_BOOT_H +#define LINUX_MMC_BOOT_H enum { MMC_PROGRESS_ENTER, MMC_PROGRESS_INIT, MMC_PROGRESS_LOAD, MMC_PROGRESS_DONE }; -#endif +#endif /* LINUX_MMC_BOOT_H */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 6ad43554ac05..b460fc2af8a1 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -403,4 +403,4 @@ extern void mmc_unregister_driver(struct mmc_driver *); extern void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table); -#endif +#endif /* LINUX_MMC_CARD_H */ diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index b6718e549a51..791f060a6f1d 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -179,4 +179,4 @@ static inline void mmc_claim_host(struct mmc_host *host) extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max); -#endif +#endif /* LINUX_MMC_CORE_H */ diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index bdd7ceeb99e4..55d9909c7abd 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -11,8 +11,8 @@ * (at your option) any later version. */ -#ifndef _LINUX_MMC_DW_MMC_H_ -#define _LINUX_MMC_DW_MMC_H_ +#ifndef LINUX_MMC_DW_MMC_H +#define LINUX_MMC_DW_MMC_H #define MAX_MCI_SLOTS 2 @@ -219,4 +219,4 @@ struct dw_mci_board { struct block_settings *blk_settings; }; -#endif /* _LINUX_MMC_DW_MMC_H_ */ +#endif /* LINUX_MMC_DW_MMC_H */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 1ee4424462eb..fc24b38b48cb 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -373,5 +373,4 @@ static inline int mmc_host_cmd23(struct mmc_host *host) { return host->caps & MMC_CAP_CMD23; } -#endif - +#endif /* LINUX_MMC_HOST_H */ diff --git a/include/linux/mmc/ioctl.h b/include/linux/mmc/ioctl.h index 5baf2983a12f..8fa5bc5f8059 100644 --- a/include/linux/mmc/ioctl.h +++ b/include/linux/mmc/ioctl.h @@ -51,4 +51,4 @@ struct mmc_ioc_cmd { * block device operations. */ #define MMC_IOC_MAX_BYTES (512L * 256) -#endif /* LINUX_MMC_IOCTL_H */ +#endif /* LINUX_MMC_IOCTL_H */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index ac26a685cca8..5bade0605641 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -21,8 +21,8 @@ * 15 May 2002 */ -#ifndef MMC_MMC_H -#define MMC_MMC_H +#ifndef LINUX_MMC_MMC_H +#define LINUX_MMC_MMC_H /* Standard MMC commands (4.1) type argument response */ /* class 1 */ @@ -327,5 +327,4 @@ struct _mmc_csd { #define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ #define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ -#endif /* MMC_MMC_PROTOCOL_H */ - +#endif /* LINUX_MMC_MMC_H */ diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h index d37aac49cf9a..4a139204c20c 100644 --- a/include/linux/mmc/pm.h +++ b/include/linux/mmc/pm.h @@ -27,4 +27,4 @@ typedef unsigned int mmc_pm_flag_t; #define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */ #define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */ -#endif +#endif /* LINUX_MMC_PM_H */ diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 7d35d52c3df3..1ebcf9ba1256 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -9,8 +9,8 @@ * your option) any later version. */ -#ifndef MMC_SD_H -#define MMC_SD_H +#ifndef LINUX_MMC_SD_H +#define LINUX_MMC_SD_H /* SD commands type argument response */ /* class 0 */ @@ -91,5 +91,4 @@ #define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_HS 1 -#endif - +#endif /* LINUX_MMC_SD_H */ diff --git a/include/linux/mmc/sdhci-spear.h b/include/linux/mmc/sdhci-spear.h index 9188c973f3e1..5cdc96da9dd5 100644 --- a/include/linux/mmc/sdhci-spear.h +++ b/include/linux/mmc/sdhci-spear.h @@ -11,8 +11,8 @@ * warranty of any kind, whether express or implied. */ -#ifndef MMC_SDHCI_SPEAR_H -#define MMC_SDHCI_SPEAR_H +#ifndef LINUX_MMC_SDHCI_SPEAR_H +#define LINUX_MMC_SDHCI_SPEAR_H #include /* @@ -39,4 +39,4 @@ sdhci_set_plat_data(struct platform_device *pdev, struct sdhci_plat_data *data) pdev->dev.platform_data = data; } -#endif /* MMC_SDHCI_SPEAR_H */ +#endif /* LINUX_MMC_SDHCI_SPEAR_H */ diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 6a68c4eb4e44..5666f3abfab7 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -8,8 +8,8 @@ * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ -#ifndef __SDHCI_H -#define __SDHCI_H +#ifndef LINUX_MMC_SDHCI_H +#define LINUX_MMC_SDHCI_H #include #include @@ -162,4 +162,4 @@ struct sdhci_host { unsigned long private[0] ____cacheline_aligned; }; -#endif /* __SDHCI_H */ +#endif /* LINUX_MMC_SDHCI_H */ diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h index 245cdacee544..2a2e9905a247 100644 --- a/include/linux/mmc/sdio.h +++ b/include/linux/mmc/sdio.h @@ -9,8 +9,8 @@ * your option) any later version. */ -#ifndef MMC_SDIO_H -#define MMC_SDIO_H +#ifndef LINUX_MMC_SDIO_H +#define LINUX_MMC_SDIO_H /* SDIO commands type argument response */ #define SD_IO_SEND_OP_COND 5 /* bcr [23:0] OCR R4 */ @@ -161,5 +161,4 @@ #define SDIO_FBR_BLKSIZE 0x10 /* block size (2 bytes) */ -#endif - +#endif /* LINUX_MMC_SDIO_H */ diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index 31baaf82f458..50f0bc952328 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -9,8 +9,8 @@ * your option) any later version. */ -#ifndef MMC_SDIO_FUNC_H -#define MMC_SDIO_FUNC_H +#ifndef LINUX_MMC_SDIO_FUNC_H +#define LINUX_MMC_SDIO_FUNC_H #include #include @@ -161,5 +161,4 @@ extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b, extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func); extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags); -#endif - +#endif /* LINUX_MMC_SDIO_FUNC_H */ diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index a36ab3bc7b03..9f03feedc8e7 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -2,8 +2,8 @@ * SDIO Classes, Interface Types, Manufacturer IDs, etc. */ -#ifndef MMC_SDIO_IDS_H -#define MMC_SDIO_IDS_H +#ifndef LINUX_MMC_SDIO_IDS_H +#define LINUX_MMC_SDIO_IDS_H /* * Standard SDIO Function Interfaces @@ -44,4 +44,4 @@ #define SDIO_DEVICE_ID_SIANO_NOVA_A0 0x1100 #define SDIO_DEVICE_ID_SIANO_STELLAR 0x5347 -#endif +#endif /* LINUX_MMC_SDIO_IDS_H */ diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h index 9eb9b4b96f55..0222cd8ebe76 100644 --- a/include/linux/mmc/sh_mmcif.h +++ b/include/linux/mmc/sh_mmcif.h @@ -11,8 +11,8 @@ * */ -#ifndef __SH_MMCIF_H__ -#define __SH_MMCIF_H__ +#ifndef LINUX_MMC_SH_MMCIF_H +#define LINUX_MMC_SH_MMCIF_H #include #include @@ -220,4 +220,4 @@ static inline void sh_mmcif_boot_init(void __iomem *base) sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); } -#endif /* __SH_MMCIF_H__ */ +#endif /* LINUX_MMC_SH_MMCIF_H */ diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h index faf32b6ec185..bd50b365167f 100644 --- a/include/linux/mmc/sh_mobile_sdhi.h +++ b/include/linux/mmc/sh_mobile_sdhi.h @@ -1,5 +1,5 @@ -#ifndef __SH_MOBILE_SDHI_H__ -#define __SH_MOBILE_SDHI_H__ +#ifndef LINUX_MMC_SH_MOBILE_SDHI_H +#define LINUX_MMC_SH_MOBILE_SDHI_H #include @@ -17,4 +17,4 @@ struct sh_mobile_sdhi_info { int (*get_cd)(struct platform_device *pdev); }; -#endif /* __SH_MOBILE_SDHI_H__ */ +#endif /* LINUX_MMC_SH_MOBILE_SDHI_H */ diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h index 19490b942db0..551490f0613d 100644 --- a/include/linux/mmc/tmio.h +++ b/include/linux/mmc/tmio.h @@ -12,8 +12,8 @@ * * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3 */ -#ifndef _LINUX_MMC_TMIO_H_ -#define _LINUX_MMC_TMIO_H_ +#ifndef LINUX_MMC_TMIO_H +#define LINUX_MMC_TMIO_H #define CTL_SD_CMD 0x00 #define CTL_ARG_REG 0x04 @@ -60,4 +60,4 @@ #define TMIO_BBS 512 /* Boot block size */ -#endif /* _LINUX_MMC_TMIO_H_ */ +#endif /* LINUX_MMC_TMIO_H */ -- cgit v1.2.3 From 0a2d4048a22079d7e79d6654bbacbef57bd5728a Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Mon, 20 Jun 2011 20:10:08 +0100 Subject: mmc: block: allow get_card_status() to return error status If the MMC_SEND_STATUS command is not successful, we should not return a zero status word, but instead allow the caller to know positively that an error occurred. Convert the open-coded get_card_status() to use the helper function, and provide definitions for the card state field. Signed-off-by: Russell King Acked-by: Linus Walleij Tested-by: Pawel Moll Signed-off-by: Chris Ball --- include/linux/mmc/mmc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 5bade0605641..5a794cb503ea 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -140,6 +140,16 @@ static inline bool mmc_op_multi(u32 opcode) #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ #define R1_APP_CMD (1 << 5) /* sr, c */ +#define R1_STATE_IDLE 0 +#define R1_STATE_READY 1 +#define R1_STATE_IDENT 2 +#define R1_STATE_STBY 3 +#define R1_STATE_TRAN 4 +#define R1_STATE_DATA 5 +#define R1_STATE_RCV 6 +#define R1_STATE_PRG 7 +#define R1_STATE_DIS 8 + /* * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS * R1 is the low order byte; R2 is the next highest byte, when present. -- cgit v1.2.3 From 95c7348d948dc4832434ddfaeba804ac14732f02 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 21 Jun 2011 08:00:08 +0900 Subject: mmc: tmio: name 0xd8 as CTL_DMA_ENABLE This reflects at least the current usage of this register and I think it improves the readability of the code ever so slightly. Cc: Guennadi Liakhovetski Cc: Magnus Damm Signed-off-by: Simon Horman Signed-off-by: Chris Ball --- include/linux/mmc/tmio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h index 551490f0613d..3ae377623db0 100644 --- a/include/linux/mmc/tmio.h +++ b/include/linux/mmc/tmio.h @@ -30,6 +30,7 @@ #define CTL_TRANSACTION_CTL 0x34 #define CTL_SDIO_STATUS 0x36 #define CTL_SDIO_IRQ_MASK 0x38 +#define CTL_DMA_ENABLE 0xd8 #define CTL_RESET_SD 0xe0 #define CTL_SDIO_REGS 0x100 #define CTL_CLK_AND_WAIT_CTL 0x138 -- cgit v1.2.3 From 973ed3af1a570612771ed10dec6506c757767668 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 21 Jun 2011 08:00:10 +0900 Subject: mmc: sdhi: Add write16_hook Some controllers require waiting for the bus to become idle before writing to some registers. I have implemented this by adding a hook to sd_ctrl_write16() and implementing a hook for SDHI which waits for the bus to become idle. Cc: Guennadi Liakhovetski Cc: Magnus Damm Signed-off-by: Simon Horman Signed-off-by: Chris Ball --- include/linux/mmc/tmio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h index 3ae377623db0..a1c1f321e519 100644 --- a/include/linux/mmc/tmio.h +++ b/include/linux/mmc/tmio.h @@ -21,6 +21,7 @@ #define CTL_XFER_BLK_COUNT 0xa #define CTL_RESPONSE 0x0c #define CTL_STATUS 0x1c +#define CTL_STATUS2 0x1e #define CTL_IRQ_MASK 0x20 #define CTL_SD_CARD_CLK_CTL 0x24 #define CTL_SD_XFER_LEN 0x26 -- cgit v1.2.3 From 1791b13ea4d97a6a7c162edd54485e932ad92f1b Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 24 Jun 2011 13:55:55 +0100 Subject: mmc: dw_mmc: convert card tasklet to workqueue Convert the card insert/remove tasklet to a workqueue, and call the setpower platform specific callback without the spinlock held. This means neither of the setpower or get_cd callbacks are called from atomic context which allows them to sleep. Signed-off-by: James Hogan Acked-by: Will Newton Signed-off-by: Chris Ball --- include/linux/mmc/dw_mmc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 55d9909c7abd..dea48475c436 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -131,7 +131,7 @@ struct dw_mci { u32 stop_cmdr; u32 dir_status; struct tasklet_struct tasklet; - struct tasklet_struct card_tasklet; + struct work_struct card_work; unsigned long pending_events; unsigned long completed_events; enum dw_mci_state state; -- cgit v1.2.3 From b86d825323b4c5d0c406e5b1a85af614acf0cf5a Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 24 Jun 2011 13:57:18 +0100 Subject: mmc: dw_mmc: don't hard code fifo depth, fix usage The FIFO_DEPTH hardware configuration parameter can be found from the power-on value of RX_WMark in the FIFOTH register. This is used to initialise the watermarks, but when calculating the number of free fifo spaces a preprocessor definition is used which is hard coded to 32. Fix reading the value out of FIFOTH (the default value in the RX_WMark field is FIFO_DEPTH-1 not FIFO_DEPTH). Allow the fifo depth to be overriden by platform data (since a bootloader may have changed FIFOTH making auto-detection unreliable). Store the fifo_depth for later use. Also fix the calculation to find the number of free bytes in the fifo to include the fifo depth in the left shift by the data shift, since the fifo depth is measured in fifo items not bytes. Signed-off-by: James Hogan Acked-by: Will Newton Signed-off-by: Chris Ball --- include/linux/mmc/dw_mmc.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index dea48475c436..01db1a0b3dd1 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -74,6 +74,7 @@ struct mmc_data; * @pdev: Platform device associated with the MMC controller. * @pdata: Platform data associated with the MMC controller. * @slot: Slots sharing this MMC controller. + * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. * @push_data: Pointer to FIFO push function. * @pull_data: Pointer to FIFO pull function. @@ -146,6 +147,7 @@ struct dw_mci { struct dw_mci_slot *slot[MAX_MCI_SLOTS]; /* FIFO push and pull */ + int fifo_depth; 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); @@ -196,6 +198,12 @@ struct dw_mci_board { unsigned int bus_hz; /* Bus speed */ unsigned int caps; /* Capabilities */ + /* + * Override fifo depth. If 0, autodetect it from the FIFOTH register, + * but note that this may not be reliable after a bootloader has used + * it. + */ + unsigned int fifo_depth; /* delay in mS before detecting cards after interrupt */ u32 detect_delay_ms; -- cgit v1.2.3 From 34b664a20e2664de0d0d7990ca60276b96c08c75 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 24 Jun 2011 13:57:56 +0100 Subject: mmc: dw_mmc: handle unaligned buffers and sizes Update functions for PIO pushing and pulling data to and from the FIFO so that they can handle unaligned output buffers and unaligned buffer lengths. This makes more of the tests in mmc_test pass. Unaligned lengths in pulls are handled by reading the full FIFO item, and storing the remaining bytes in a small internal buffer (part_buf). The next data pull will copy data out of this buffer first before accessing the FIFO again. Similarly, for pushes the final bytes that don't fill a FIFO item are stored in the part_buf (or sent anyway if it's the last transfer), and then the part_buf is included at the beginning of the next buffer pushed. Unaligned buffers in pulls are handled specially if the architecture cannot do efficient unaligned accesses, by reading FIFO items into a aligned local buffer, and memcpy'ing them into the output buffer, again storing any remaining bytes in the internal buffer. Similarly for pushes the buffer is memcpy'd into an aligned local buffer then written to the FIFO. Signed-off-by: James Hogan Acked-by: Will Newton Signed-off-by: Chris Ball --- include/linux/mmc/dw_mmc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 01db1a0b3dd1..f3f68ee08a1e 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -76,6 +76,9 @@ struct mmc_data; * @slot: Slots sharing this MMC controller. * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. + * @part_buf_start: Start index in part_buf. + * @part_buf_count: Bytes of partial data in part_buf. + * @part_buf: Simple buffer for partial fifo reads/writes. * @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. @@ -149,6 +152,13 @@ struct dw_mci { /* FIFO push and pull */ int fifo_depth; int data_shift; + u8 part_buf_start; + u8 part_buf_count; + union { + u16 part_buf16; + u32 part_buf32; + u64 part_buf; + }; void (*push_data)(struct dw_mci *host, void *buf, int cnt); void (*pull_data)(struct dw_mci *host, void *buf, int cnt); -- cgit v1.2.3 From e056a1b5b67b4e4bfad00bf143ab14f634777705 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 28 Jun 2011 17:16:02 +0300 Subject: mmc: queue: let host controllers specify maximum discard timeout Some host controllers will not operate without a hardware timeout that is limited in value. However large discards require large timeouts, so there needs to be a way to specify the maximum discard size. A host controller driver may now specify the maximum discard timeout possible so that max_discard_sectors can be calculated. However, for eMMC when the High Capacity Erase Group Size is not in use, the timeout calculation depends on clock rate which may change. For that case Preferred Erase Size is used instead. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- include/linux/mmc/core.h | 1 + include/linux/mmc/host.h | 1 + 2 files changed, 2 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 791f060a6f1d..86d81cf75b70 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -155,6 +155,7 @@ extern int mmc_can_trim(struct mmc_card *card); 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 unsigned int mmc_calc_max_discard(struct mmc_card *card); extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index fc24b38b48cb..c67d19b5542a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -231,6 +231,7 @@ struct mmc_host { unsigned int max_req_size; /* maximum number of bytes in one req */ 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_discard_to; /* max. discard timeout in ms */ /* private data */ spinlock_t lock; /* lock for claim and bus ops */ -- cgit v1.2.3 From 03e8cb534e7cc3f71a07528a44da7ce68e5b5708 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 29 Jun 2011 09:28:43 +0100 Subject: mmc: dw_mmc: fix stop when fallen back to PIO There are several situations when dw_mci_submit_data_dma() decides to fall back to PIO mode instead of using DMA, due to a short (to avoid overhead) or "complex" (e.g. with unaligned buffers) transaction, even though host->use_dma is set. However dw_mci_stop_dma() decides whether to stop DMA or set the EVENT_XFER_COMPLETE event based on host->use_dma. When falling back to PIO mode this results in data timeout errors getting missed and the driver locking up. Therefore add host->using_dma to indicate whether the current transaction is using dma or not, and adjust dw_mci_stop_dma() to use that instead. Signed-off-by: James Hogan Acked-by: Will Newton Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- include/linux/mmc/dw_mmc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index f3f68ee08a1e..6b46819705d1 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -48,6 +48,7 @@ struct mmc_data; * @data: The data currently being transferred, or NULL if no data * transfer is in progress. * @use_dma: Whether DMA channel is initialized or not. + * @using_dma: Whether DMA is in use for the current transfer. * @sg_dma: Bus address of DMA buffer. * @sg_cpu: Virtual address of DMA buffer. * @dma_ops: Pointer to platform-specific DMA callbacks. @@ -121,6 +122,7 @@ struct dw_mci { /* DMA interface members*/ int use_dma; + int using_dma; dma_addr_t sg_dma; void *sg_cpu; -- cgit v1.2.3 From aa8b683a7d392271ed349c6ab9f36b8c313794b7 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Fri, 1 Jul 2011 18:55:22 +0200 Subject: mmc: core: add non-blocking mmc request function Previously there has only been one function mmc_wait_for_req() to start and wait for a request. This patch adds: * mmc_start_req() - starts a request wihtout waiting If there is on ongoing request wait for completion of that request and start the new one and return. Does not wait for the new command to complete. This patch also adds new function members in struct mmc_host_ops only called from core.c: * pre_req - asks the host driver to prepare for the next job * post_req - asks the host driver to clean up after a completed job The intention is to use pre_req() and post_req() to do cache maintenance while a request is active. pre_req() can be called while a request is active to minimize latency to start next job. post_req() can be used after the next job is started to clean up the request. This will minimize the host driver request end latency. post_req() is typically used before ending the block request and handing over the buffer to the block layer. Add a host-private member in mmc_data to be used by pre_req to mark the data. The host driver will then check this mark to see if the data is prepared or not. Signed-off-by: Per Forlin Acked-by: Kyungmin Park Acked-by: Arnd Bergmann Reviewed-by: Venkatraman S Tested-by: Sourav Poddar Tested-by: Linus Walleij Signed-off-by: Chris Ball --- include/linux/mmc/core.h | 6 +++++- include/linux/mmc/host.h | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 86d81cf75b70..b8b1b7a311f1 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -117,6 +117,7 @@ struct mmc_data { unsigned int sg_len; /* size of scatter list */ struct scatterlist *sg; /* I/O scatter list */ + s32 host_cookie; /* host private data */ }; struct mmc_request { @@ -125,13 +126,16 @@ struct mmc_request { struct mmc_data *data; struct mmc_command *stop; - void *done_data; /* completion data */ + struct completion completion; void (*done)(struct mmc_request *);/* completion function */ }; struct mmc_host; struct mmc_card; +struct mmc_async_req; +extern struct mmc_async_req *mmc_start_req(struct mmc_host *, + struct mmc_async_req *, int *); extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *); extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c67d19b5542a..9f9a4c64cde7 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -106,6 +106,15 @@ struct mmc_host_ops { */ int (*enable)(struct mmc_host *host); int (*disable)(struct mmc_host *host, int lazy); + /* + * It is optional for the host to implement pre_req and post_req in + * order to support double buffering of requests (prepare one + * request while another request is active). + */ + void (*post_req)(struct mmc_host *host, struct mmc_request *req, + int err); + void (*pre_req)(struct mmc_host *host, struct mmc_request *req, + bool is_first_req); void (*request)(struct mmc_host *host, struct mmc_request *req); /* * Avoid calling these three functions too often or in a "fast path", @@ -144,6 +153,16 @@ struct mmc_host_ops { struct mmc_card; struct device; +struct mmc_async_req { + /* active mmc request */ + struct mmc_request *mrq; + /* + * Check error status of completed mmc request. + * Returns 0 if success otherwise non zero. + */ + int (*err_check) (struct mmc_card *, struct mmc_async_req *); +}; + struct mmc_host { struct device *parent; struct device class_dev; @@ -282,6 +301,8 @@ struct mmc_host { struct dentry *debugfs_root; + struct mmc_async_req *areq; /* active async req */ + unsigned long private[0] ____cacheline_aligned; }; -- cgit v1.2.3 From ca8e99b32e3863c98ac958617cc157a00bf445b8 Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Wed, 6 Jul 2011 08:51:32 -0700 Subject: mmc: core: Set non-default Drive Strength via platform hook Non default Drive Strength cannot be set automatically. It is a function of the board design and only if there is a specific platform handler can it be set. The platform handler needs to take into account the board design. Pass to the platform code the necessary information. For example: The card and host controller may indicate they support HIGH and LOW drive strength. There is no way to know what should be chosen without specific board knowledge. Setting HIGH may lead to reflections and setting LOW may not suffice. There is no mechanism (like ethernet duplex or speed pulses) to determine what should be done automatically. If no platform handler is defined -- use the default value. Signed-off-by: Philip Rakity Reviewed-by: Arindam Nath Signed-off-by: Chris Ball --- include/linux/mmc/host.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/mmc') diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9f9a4c64cde7..0f83858147a6 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -148,6 +148,7 @@ struct mmc_host_ops { int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios); int (*execute_tuning)(struct mmc_host *host); void (*enable_preset_value)(struct mmc_host *host, bool enable); + int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv); }; struct mmc_card; -- cgit v1.2.3