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