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>
This commit is contained in:
Guennadi Liakhovetski 2011-03-14 09:52:33 +01:00 committed by Chris Ball
parent 4fbc5ece43
commit 42051e8a7b
8 changed files with 68 additions and 95 deletions

View File

@ -60,15 +60,6 @@ config MFD_ASIC3
This driver supports the ASIC3 multifunction chip found on many This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones) PDAs (mainly iPAQ and HTC based ones)
config MFD_SH_MOBILE_SDHI
bool "Support for SuperH Mobile SDHI"
depends on SUPERH || ARCH_SHMOBILE
select MFD_CORE
select TMIO_MMC_DMA
---help---
This driver supports the SDHI hardware block found in many
SuperH Mobile SoCs.
config MFD_DAVINCI_VOICECODEC config MFD_DAVINCI_VOICECODEC
tristate tristate
select MFD_CORE select MFD_CORE
@ -265,11 +256,6 @@ config MFD_TMIO
bool bool
default n default n
config TMIO_MMC_DMA
bool
select DMA_ENGINE
select DMADEVICES
config MFD_T7L66XB config MFD_T7L66XB
bool "Support Toshiba T7L66XB" bool "Support Toshiba T7L66XB"
depends on ARM && HAVE_CLK depends on ARM && HAVE_CLK

View File

@ -6,7 +6,6 @@
obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o

View File

@ -444,12 +444,19 @@ config MMC_TMIO_CORE
config MMC_TMIO config MMC_TMIO
tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI depends on MFD_TMIO || MFD_ASIC3
select MMC_TMIO_CORE select MMC_TMIO_CORE
help help
This provides support for the SD/MMC cell found in TC6393XB, This provides support for the SD/MMC cell found in TC6393XB,
T7L66XB and also HTC ASIC3 T7L66XB and also HTC ASIC3
config MMC_SDHI
tristate "SH-Mobile SDHI SD/SDIO controller support"
select MMC_TMIO_CORE
help
This provides support for the SDHI SD/SDIO controller found in
SuperH and ARM SH-Mobile SoCs
config MMC_CB710 config MMC_CB710
tristate "ENE CB710 MMC/SD Interface support" tristate "ENE CB710 MMC/SD Interface support"
depends on PCI depends on PCI

View File

@ -31,8 +31,11 @@ obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o obj-$(CONFIG_MMC_TMIO_CORE) += tmio_mmc_core.o
tmio_mmc_core-y := tmio_mmc_pio.o tmio_mmc_core-y := tmio_mmc_pio.o
tmio_mmc_core-$(CONFIG_TMIO_MMC_DMA) += tmio_mmc_dma.o ifneq ($(CONFIG_MMC_SDHI),n)
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o tmio_mmc_core-y += tmio_mmc_dma.o
endif
obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW) += dw_mmc.o

View File

@ -23,51 +23,30 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mfd/core.h> #include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h> #include <linux/mfd/tmio.h>
#include <linux/mfd/sh_mobile_sdhi.h>
#include <linux/sh_dma.h> #include <linux/sh_dma.h>
#include "tmio_mmc.h"
struct sh_mobile_sdhi { struct sh_mobile_sdhi {
struct clk *clk; struct clk *clk;
struct tmio_mmc_data mmc_data; struct tmio_mmc_data mmc_data;
struct mfd_cell cell_mmc;
struct sh_dmae_slave param_tx; struct sh_dmae_slave param_tx;
struct sh_dmae_slave param_rx; struct sh_dmae_slave param_rx;
struct tmio_mmc_dma dma_priv; struct tmio_mmc_dma dma_priv;
}; };
static struct resource sh_mobile_sdhi_resources[] = { static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
{
.start = 0x000,
.end = 0x1ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0,
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell sh_mobile_sdhi_cell = {
.name = "tmio-mmc",
.num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources),
.resources = sh_mobile_sdhi_resources,
};
static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state)
{ {
struct platform_device *pdev = to_platform_device(tmio->dev.parent);
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
if (p && p->set_pwr) if (p && p->set_pwr)
p->set_pwr(pdev, state); p->set_pwr(pdev, state);
} }
static int sh_mobile_sdhi_get_cd(struct platform_device *tmio) static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
{ {
struct platform_device *pdev = to_platform_device(tmio->dev.parent);
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
if (p && p->get_cd) if (p && p->get_cd)
@ -81,20 +60,9 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
struct sh_mobile_sdhi *priv; struct sh_mobile_sdhi *priv;
struct tmio_mmc_data *mmc_data; struct tmio_mmc_data *mmc_data;
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
struct resource *mem; struct tmio_mmc_host *host;
char clk_name[8]; char clk_name[8];
int ret, irq; int ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem)
dev_err(&pdev->dev, "missing MEM resource\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0)
dev_err(&pdev->dev, "missing IRQ resource\n");
if (!mem || (irq < 0))
return -EINVAL;
priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
if (priv == NULL) { if (priv == NULL) {
@ -109,8 +77,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk)) { if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
ret = PTR_ERR(priv->clk); ret = PTR_ERR(priv->clk);
kfree(priv); goto eclkget;
return ret;
} }
clk_enable(priv->clk); clk_enable(priv->clk);
@ -123,6 +90,15 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
mmc_data->flags = p->tmio_flags; mmc_data->flags = p->tmio_flags;
mmc_data->ocr_mask = p->tmio_ocr_mask; mmc_data->ocr_mask = p->tmio_ocr_mask;
mmc_data->capabilities |= p->tmio_caps; mmc_data->capabilities |= p->tmio_caps;
if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
priv->param_tx.slave_id = p->dma_slave_tx;
priv->param_rx.slave_id = p->dma_slave_rx;
priv->dma_priv.chan_priv_tx = &priv->param_tx;
priv->dma_priv.chan_priv_rx = &priv->param_rx;
priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
mmc_data->dma = &priv->dma_priv;
}
} }
/* /*
@ -136,36 +112,30 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
*/ */
mmc_data->flags |= TMIO_MMC_SDIO_IRQ; mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { ret = tmio_mmc_host_probe(&host, pdev, mmc_data);
priv->param_tx.slave_id = p->dma_slave_tx; if (ret < 0)
priv->param_rx.slave_id = p->dma_slave_rx; goto eprobe;
priv->dma_priv.chan_priv_tx = &priv->param_tx;
priv->dma_priv.chan_priv_rx = &priv->param_rx;
priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
mmc_data->dma = &priv->dma_priv;
}
memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
priv->cell_mmc.mfd_data = mmc_data; (unsigned long)host->ctl, host->irq);
platform_set_drvdata(pdev, priv); return ret;
ret = mfd_add_devices(&pdev->dev, pdev->id,
&priv->cell_mmc, 1, mem, irq);
if (ret) {
clk_disable(priv->clk);
clk_put(priv->clk);
kfree(priv);
}
eprobe:
clk_disable(priv->clk);
clk_put(priv->clk);
eclkget:
kfree(priv);
return ret; return ret;
} }
static int sh_mobile_sdhi_remove(struct platform_device *pdev) static int sh_mobile_sdhi_remove(struct platform_device *pdev)
{ {
struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev); struct mmc_host *mmc = platform_get_drvdata(pdev);
struct tmio_mmc_host *host = mmc_priv(mmc);
struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
mfd_remove_devices(&pdev->dev); tmio_mmc_host_remove(host);
clk_disable(priv->clk); clk_disable(priv->clk);
clk_put(priv->clk); clk_put(priv->clk);
kfree(priv); kfree(priv);
@ -198,3 +168,4 @@ module_exit(sh_mobile_sdhi_exit);
MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
MODULE_AUTHOR("Magnus Damm"); MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:sh_mobile_sdhi");

View File

@ -120,7 +120,7 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
local_irq_restore(*flags); local_irq_restore(*flags);
} }
#ifdef CONFIG_TMIO_MMC_DMA #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
void tmio_mmc_release_dma(struct tmio_mmc_host *host); void tmio_mmc_release_dma(struct tmio_mmc_host *host);

View File

@ -1,16 +1,7 @@
#ifndef __SH_MOBILE_SDHI_H__ #ifndef MFD_SH_MOBILE_SDHI_H
#define __SH_MOBILE_SDHI_H__ #define MFD_SH_MOBILE_SDHI_H
#include <linux/types.h> /* Compatibility header - will disappear once all platforms are converted */
#include <linux/mmc/sh_mobile_sdhi.h>
struct sh_mobile_sdhi_info { #endif /* MFD_SH_MOBILE_SDHI_H */
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__ */

View File

@ -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__ */