mmc: tmio: convert the SDHI MMC driver from MFD to a platform driver

On sh-mobile platforms the SDHI driver was using the tmio_mmc SD/SDIO
MFD cell driver. Now that the tmio_mmc driver has been split into a
core and a separate MFD glue, we can support SDHI natively without the
need to emulate an MFD controller. This also allows to support systems
with an on-SoC SDHI controller and a separate MFD with a TMIO core.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by Guennadi Liakhovetski and committed by Chris Ball 42051e8a 4fbc5ece

+68 -95
-14
drivers/mfd/Kconfig
··· 60 This driver supports the ASIC3 multifunction chip found on many 61 PDAs (mainly iPAQ and HTC based ones) 62 63 - config MFD_SH_MOBILE_SDHI 64 - bool "Support for SuperH Mobile SDHI" 65 - depends on SUPERH || ARCH_SHMOBILE 66 - select MFD_CORE 67 - select TMIO_MMC_DMA 68 - ---help--- 69 - This driver supports the SDHI hardware block found in many 70 - SuperH Mobile SoCs. 71 - 72 config MFD_DAVINCI_VOICECODEC 73 tristate 74 select MFD_CORE ··· 255 config MFD_TMIO 256 bool 257 default n 258 - 259 - config TMIO_MMC_DMA 260 - bool 261 - select DMA_ENGINE 262 - select DMADEVICES 263 264 config MFD_T7L66XB 265 bool "Support Toshiba T7L66XB"
··· 60 This driver supports the ASIC3 multifunction chip found on many 61 PDAs (mainly iPAQ and HTC based ones) 62 63 config MFD_DAVINCI_VOICECODEC 64 tristate 65 select MFD_CORE ··· 264 config MFD_TMIO 265 bool 266 default n 267 268 config MFD_T7L66XB 269 bool "Support Toshiba T7L66XB"
-1
drivers/mfd/Makefile
··· 6 obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o 7 obj-$(CONFIG_MFD_SM501) += sm501.o 8 obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 9 - obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o 10 11 obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 12 obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
··· 6 obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o 7 obj-$(CONFIG_MFD_SM501) += sm501.o 8 obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o 9 10 obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 11 obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+33 -62
drivers/mfd/sh_mobile_sdhi.c drivers/mmc/host/sh_mobile_sdhi.c
··· 23 #include <linux/slab.h> 24 #include <linux/platform_device.h> 25 #include <linux/mmc/host.h> 26 - #include <linux/mfd/core.h> 27 #include <linux/mfd/tmio.h> 28 - #include <linux/mfd/sh_mobile_sdhi.h> 29 #include <linux/sh_dma.h> 30 31 struct sh_mobile_sdhi { 32 struct clk *clk; 33 struct tmio_mmc_data mmc_data; 34 - struct mfd_cell cell_mmc; 35 struct sh_dmae_slave param_tx; 36 struct sh_dmae_slave param_rx; 37 struct tmio_mmc_dma dma_priv; 38 }; 39 40 - static struct resource sh_mobile_sdhi_resources[] = { 41 - { 42 - .start = 0x000, 43 - .end = 0x1ff, 44 - .flags = IORESOURCE_MEM, 45 - }, 46 - { 47 - .start = 0, 48 - .end = 0, 49 - .flags = IORESOURCE_IRQ, 50 - }, 51 - }; 52 - 53 - static struct mfd_cell sh_mobile_sdhi_cell = { 54 - .name = "tmio-mmc", 55 - .num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources), 56 - .resources = sh_mobile_sdhi_resources, 57 - }; 58 - 59 - static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state) 60 { 61 - struct platform_device *pdev = to_platform_device(tmio->dev.parent); 62 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 63 64 if (p && p->set_pwr) 65 p->set_pwr(pdev, state); 66 } 67 68 - static int sh_mobile_sdhi_get_cd(struct platform_device *tmio) 69 { 70 - struct platform_device *pdev = to_platform_device(tmio->dev.parent); 71 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 72 73 if (p && p->get_cd) ··· 60 struct sh_mobile_sdhi *priv; 61 struct tmio_mmc_data *mmc_data; 62 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 63 - struct resource *mem; 64 char clk_name[8]; 65 - int ret, irq; 66 - 67 - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 68 - if (!mem) 69 - dev_err(&pdev->dev, "missing MEM resource\n"); 70 - 71 - irq = platform_get_irq(pdev, 0); 72 - if (irq < 0) 73 - dev_err(&pdev->dev, "missing IRQ resource\n"); 74 - 75 - if (!mem || (irq < 0)) 76 - return -EINVAL; 77 78 priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); 79 if (priv == NULL) { ··· 77 if (IS_ERR(priv->clk)) { 78 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); 79 ret = PTR_ERR(priv->clk); 80 - kfree(priv); 81 - return ret; 82 } 83 84 clk_enable(priv->clk); ··· 90 mmc_data->flags = p->tmio_flags; 91 mmc_data->ocr_mask = p->tmio_ocr_mask; 92 mmc_data->capabilities |= p->tmio_caps; 93 } 94 95 /* ··· 112 */ 113 mmc_data->flags |= TMIO_MMC_SDIO_IRQ; 114 115 - if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { 116 - priv->param_tx.slave_id = p->dma_slave_tx; 117 - priv->param_rx.slave_id = p->dma_slave_rx; 118 - priv->dma_priv.chan_priv_tx = &priv->param_tx; 119 - priv->dma_priv.chan_priv_rx = &priv->param_rx; 120 - priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ 121 - mmc_data->dma = &priv->dma_priv; 122 - } 123 124 - memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); 125 - priv->cell_mmc.mfd_data = mmc_data; 126 127 - platform_set_drvdata(pdev, priv); 128 129 - ret = mfd_add_devices(&pdev->dev, pdev->id, 130 - &priv->cell_mmc, 1, mem, irq); 131 - if (ret) { 132 - clk_disable(priv->clk); 133 - clk_put(priv->clk); 134 - kfree(priv); 135 - } 136 - 137 return ret; 138 } 139 140 static int sh_mobile_sdhi_remove(struct platform_device *pdev) 141 { 142 - struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev); 143 144 - mfd_remove_devices(&pdev->dev); 145 clk_disable(priv->clk); 146 clk_put(priv->clk); 147 kfree(priv); ··· 168 MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); 169 MODULE_AUTHOR("Magnus Damm"); 170 MODULE_LICENSE("GPL v2");
··· 23 #include <linux/slab.h> 24 #include <linux/platform_device.h> 25 #include <linux/mmc/host.h> 26 + #include <linux/mmc/sh_mobile_sdhi.h> 27 #include <linux/mfd/tmio.h> 28 #include <linux/sh_dma.h> 29 + 30 + #include "tmio_mmc.h" 31 32 struct sh_mobile_sdhi { 33 struct clk *clk; 34 struct tmio_mmc_data mmc_data; 35 struct sh_dmae_slave param_tx; 36 struct sh_dmae_slave param_rx; 37 struct tmio_mmc_dma dma_priv; 38 }; 39 40 + static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state) 41 { 42 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 43 44 if (p && p->set_pwr) 45 p->set_pwr(pdev, state); 46 } 47 48 + static int sh_mobile_sdhi_get_cd(struct platform_device *pdev) 49 { 50 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 51 52 if (p && p->get_cd) ··· 81 struct sh_mobile_sdhi *priv; 82 struct tmio_mmc_data *mmc_data; 83 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; 84 + struct tmio_mmc_host *host; 85 char clk_name[8]; 86 + int ret; 87 88 priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); 89 if (priv == NULL) { ··· 109 if (IS_ERR(priv->clk)) { 110 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); 111 ret = PTR_ERR(priv->clk); 112 + goto eclkget; 113 } 114 115 clk_enable(priv->clk); ··· 123 mmc_data->flags = p->tmio_flags; 124 mmc_data->ocr_mask = p->tmio_ocr_mask; 125 mmc_data->capabilities |= p->tmio_caps; 126 + 127 + if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { 128 + priv->param_tx.slave_id = p->dma_slave_tx; 129 + priv->param_rx.slave_id = p->dma_slave_rx; 130 + priv->dma_priv.chan_priv_tx = &priv->param_tx; 131 + priv->dma_priv.chan_priv_rx = &priv->param_rx; 132 + priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ 133 + mmc_data->dma = &priv->dma_priv; 134 + } 135 } 136 137 /* ··· 136 */ 137 mmc_data->flags |= TMIO_MMC_SDIO_IRQ; 138 139 + ret = tmio_mmc_host_probe(&host, pdev, mmc_data); 140 + if (ret < 0) 141 + goto eprobe; 142 143 + pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc), 144 + (unsigned long)host->ctl, host->irq); 145 146 + return ret; 147 148 + eprobe: 149 + clk_disable(priv->clk); 150 + clk_put(priv->clk); 151 + eclkget: 152 + kfree(priv); 153 return ret; 154 } 155 156 static int sh_mobile_sdhi_remove(struct platform_device *pdev) 157 { 158 + struct mmc_host *mmc = platform_get_drvdata(pdev); 159 + struct tmio_mmc_host *host = mmc_priv(mmc); 160 + struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); 161 162 + tmio_mmc_host_remove(host); 163 clk_disable(priv->clk); 164 clk_put(priv->clk); 165 kfree(priv); ··· 198 MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); 199 MODULE_AUTHOR("Magnus Damm"); 200 MODULE_LICENSE("GPL v2"); 201 + MODULE_ALIAS("platform:sh_mobile_sdhi");
+8 -1
drivers/mmc/host/Kconfig
··· 444 445 config MMC_TMIO 446 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" 447 - depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI 448 select MMC_TMIO_CORE 449 help 450 This provides support for the SD/MMC cell found in TC6393XB, 451 T7L66XB and also HTC ASIC3 452 453 config MMC_CB710 454 tristate "ENE CB710 MMC/SD Interface support"
··· 444 445 config MMC_TMIO 446 tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" 447 + depends on MFD_TMIO || MFD_ASIC3 448 select MMC_TMIO_CORE 449 help 450 This provides support for the SD/MMC cell found in TC6393XB, 451 T7L66XB and also HTC ASIC3 452 + 453 + config MMC_SDHI 454 + tristate "SH-Mobile SDHI SD/SDIO controller support" 455 + select MMC_TMIO_CORE 456 + help 457 + This provides support for the SDHI SD/SDIO controller found in 458 + SuperH and ARM SH-Mobile SoCs 459 460 config MMC_CB710 461 tristate "ENE CB710 MMC/SD Interface support"
+5 -2
drivers/mmc/host/Makefile
··· 31 obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o 32 obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o 33 tmio_mmc_core-y := tmio_mmc_pio.o 34 - tmio_mmc_core-$(CONFIG_TMIO_MMC_DMA) += tmio_mmc_dma.o 35 - obj-$(CONFIG_MMC_CB710) += cb710-mmc.o 36 obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o 37 obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o 38 obj-$(CONFIG_MMC_DW) += dw_mmc.o
··· 31 obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o 32 obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o 33 tmio_mmc_core-y := tmio_mmc_pio.o 34 + ifneq ($(CONFIG_MMC_SDHI),n) 35 + tmio_mmc_core-y += tmio_mmc_dma.o 36 + endif 37 + obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o 38 + obj-$(CONFIG_MMC_CB710) += cb710-mmc.o 39 obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o 40 obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o 41 obj-$(CONFIG_MMC_DW) += dw_mmc.o
+1 -1
drivers/mmc/host/tmio_mmc.h
··· 120 local_irq_restore(*flags); 121 } 122 123 - #ifdef CONFIG_TMIO_MMC_DMA 124 void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); 125 void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); 126 void tmio_mmc_release_dma(struct tmio_mmc_host *host);
··· 120 local_irq_restore(*flags); 121 } 122 123 + #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) 124 void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); 125 void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); 126 void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+5 -14
include/linux/mfd/sh_mobile_sdhi.h
··· 1 - #ifndef __SH_MOBILE_SDHI_H__ 2 - #define __SH_MOBILE_SDHI_H__ 3 4 - #include <linux/types.h> 5 6 - struct sh_mobile_sdhi_info { 7 - int dma_slave_tx; 8 - int dma_slave_rx; 9 - unsigned long tmio_flags; 10 - unsigned long tmio_caps; 11 - u32 tmio_ocr_mask; /* available MMC voltages */ 12 - void (*set_pwr)(struct platform_device *pdev, int state); 13 - int (*get_cd)(struct platform_device *pdev); 14 - }; 15 - 16 - #endif /* __SH_MOBILE_SDHI_H__ */
··· 1 + #ifndef MFD_SH_MOBILE_SDHI_H 2 + #define MFD_SH_MOBILE_SDHI_H 3 4 + /* Compatibility header - will disappear once all platforms are converted */ 5 + #include <linux/mmc/sh_mobile_sdhi.h> 6 7 + #endif /* MFD_SH_MOBILE_SDHI_H */
+16
include/linux/mmc/sh_mobile_sdhi.h
···
··· 1 + #ifndef __SH_MOBILE_SDHI_H__ 2 + #define __SH_MOBILE_SDHI_H__ 3 + 4 + #include <linux/types.h> 5 + 6 + struct sh_mobile_sdhi_info { 7 + int dma_slave_tx; 8 + int dma_slave_rx; 9 + unsigned long tmio_flags; 10 + unsigned long tmio_caps; 11 + u32 tmio_ocr_mask; /* available MMC voltages */ 12 + void (*set_pwr)(struct platform_device *pdev, int state); 13 + int (*get_cd)(struct platform_device *pdev); 14 + }; 15 + 16 + #endif /* __SH_MOBILE_SDHI_H__ */