2009/9/26 Ian Molton <ian@xxxxxxxxxxxxxx>: Hi guys, This is the tmio based part of the tmio-mmc driver update that removes the CNF area (clock and power control) from the driver and abstracts it so that more users can share the MMC driver itself. Its compilable, runs on my hardware, and is checkpatch clean. I havent updated ASIC3 as I cannot test it here - please could someone with hardware do this. It should only require a few lines of code similar to that in the other drivers. I expect it can share the code in tmio-core.c Magnus, please base your driver on this patchset, since its tested and shows no regressions on my hardware (something else seems to have stopped my tc6393xb device reading some cards, but this must have happened prior to this patch (from a quick bisect). It will read other cards, and so I dont think this patch is related. I'll look into this when I get time, but dont want to delay other peoples drivers getting updated / merged. Once someone sends me a patch for ASIC3 I will prepare this patchset for submission upstream. -- Ian Molton Linux, Automotive, and other hacking: http://www.mnementh.co.uk/
From 46909530b67a1c83c1e22ac5fcfcada27d4fab54 Mon Sep 17 00:00:00 2001 From: Ian Molton <ian@xxxxxxxxxxxxxx> Date: Thu, 24 Sep 2009 23:24:18 +0100 Subject: [PATCH 1/2] MMC: hardware abstraction for CNF area This patch abstracts out the CNF area code from tmio_mmc which is not present in all hardware that can use this driver. This is required so that we can suppot non-toshiba based hardware. Signed-off-by: Ian Molton <ian@xxxxxxxxxxxxxx> --- drivers/mfd/Makefile | 6 +- drivers/mfd/t7l66xb.c | 31 +++++++++++-- drivers/mfd/tc6387xb.c | 97 ++++++++++++++++++++++++++++++++++-------- drivers/mfd/tc6393xb.c | 56 +++++++++++++++++++++---- drivers/mfd/tmio_core.c | 54 ++++++++++++++++++++++++ drivers/mmc/host/tmio_mmc.c | 63 +++++++++------------------ drivers/mmc/host/tmio_mmc.h | 46 +++------------------ include/linux/mfd/tmio.h | 33 +++++++++++++++ 8 files changed, 268 insertions(+), 118 deletions(-) create mode 100644 drivers/mfd/tmio_core.c diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 6f8a9a1..9be344a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -10,9 +10,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o -obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o -obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o -obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o +obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 0a255c1..2fa0703 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -38,6 +38,8 @@ enum { T7L66XB_CELL_MMC, }; +static const struct resource t7l66xb_mmc_resources[]; + #define SCR_REVID 0x08 /* b Revision ID */ #define SCR_IMR 0x42 /* b Interrupt Mask */ #define SCR_DEV_CTL 0xe0 /* b Device control */ @@ -83,6 +85,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) spin_unlock_irqrestore(&t7l66xb->lock, flags); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } @@ -106,10 +111,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) return 0; } +static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(t7l66xb->scr + 0x200, state); +} + +static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, state); +} + /*--------------------------------------------------------------------------*/ static struct tmio_mmc_data t7166xb_mmc_data = { .hclk = 24000000, + .set_pwr = t7l66xb_mmc_pwr, + .set_no_clk_div = t7l66xb_mmc_clk_div, }; static const struct resource t7l66xb_mmc_resources[] = { @@ -119,11 +142,6 @@ static const struct resource t7l66xb_mmc_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { .start = IRQ_T7L66XB_MMC, .end = IRQ_T7L66XB_MMC, .flags = IORESOURCE_IRQ, @@ -282,6 +300,9 @@ static int t7l66xb_resume(struct platform_device *dev) if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } #else diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 3280ab3..fa8da02 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -22,28 +22,41 @@ enum { TC6387XB_CELL_MMC, }; +struct tc6387xb { + void __iomem *scr; + struct clk *clk32k; + struct resource rscr; +}; + +static struct resource tc6387xb_mmc_resources[]; + +/*--------------------------------------------------------------------------*/ + #ifdef CONFIG_PM static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; if (pdata && pdata->suspend) pdata->suspend(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } static int tc6387xb_resume(struct platform_device *dev) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_resume(tc6387xb->scr + 0x200, + tc6387xb_mmc_resources[0].start & 0xfffe); + return 0; } #else @@ -53,12 +66,32 @@ static int tc6387xb_resume(struct platform_device *dev) /*--------------------------------------------------------------------------*/ +static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6387xb->scr + 0x200, state); +} + +static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, state); +} + + static int tc6387xb_mmc_enable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); + + tmio_core_mmc_enable(tc6387xb->scr + 0x200, + tc6387xb_mmc_resources[0].start & 0xfffe); return 0; } @@ -66,19 +99,21 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) static int tc6387xb_mmc_disable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } -/*--------------------------------------------------------------------------*/ - static struct tmio_mmc_data tc6387xb_mmc_data = { .hclk = 24000000, + .set_pwr = tc6387xb_mmc_pwr, + .set_no_clk_div = tc6387xb_mmc_clk_div, }; +/*--------------------------------------------------------------------------*/ + static struct resource tc6387xb_mmc_resources[] = { { .start = 0x800, @@ -86,11 +121,6 @@ static struct resource tc6387xb_mmc_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { .start = 0, .end = 0, .flags = IORESOURCE_IRQ, @@ -111,8 +141,9 @@ static struct mfd_cell tc6387xb_cells[] = { static int tc6387xb_probe(struct platform_device *dev) { struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - struct resource *iomem; + struct resource *iomem, *rscr; struct clk *clk32k; + struct tc6387xb *tc6387xb; int irq, ret; iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -120,18 +151,40 @@ static int tc6387xb_probe(struct platform_device *dev) return -EINVAL; } + tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL); + if (!tc6387xb) + return -ENOMEM; + ret = platform_get_irq(dev, 0); if (ret >= 0) irq = ret; else - goto err_resource; + goto err_no_irq; clk32k = clk_get(&dev->dev, "CLK_CK32K"); if (IS_ERR(clk32k)) { ret = PTR_ERR(clk32k); + goto err_no_clk; + } + + rscr = &tc6387xb->rscr; + rscr->name = "tc6387xb-core"; + rscr->start = iomem->start; + rscr->end = iomem->start + 0xff; + rscr->flags = IORESOURCE_MEM; + + ret = request_resource(iomem, rscr); + if (ret) goto err_resource; + + tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); + if (!tc6387xb->scr) { + ret = -ENOMEM; + goto err_ioremap; } - platform_set_drvdata(dev, clk32k); + + tc6387xb->clk32k = clk32k; + platform_set_drvdata(dev, tc6387xb); if (pdata && pdata->enable) pdata->enable(dev); @@ -149,8 +202,13 @@ static int tc6387xb_probe(struct platform_device *dev) if (!ret) return 0; - clk_put(clk32k); +err_ioremap: + release_resource(&tc6387xb->rscr); err_resource: + clk_put(clk32k); +err_no_clk: +err_no_irq: + kfree(tc6387xb); return ret; } @@ -195,3 +253,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton"); MODULE_ALIAS("platform:tc6387xb"); + diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1429a73..a44b6b0 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand) return 0; } -static struct tmio_mmc_data tc6393xb_mmc_data = { - .hclk = 24000000, -}; - static struct resource __devinitdata tc6393xb_nand_resources[] = { { .start = 0x1000, @@ -165,11 +161,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { .start = IRQ_TC6393_MMC, .end = IRQ_TC6393_MMC, .flags = IORESOURCE_IRQ, @@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb, } EXPORT_SYMBOL(tc6393xb_lcd_mode); +static int tc6393xb_mmc_enable(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_enable(tc6393xb->scr + 0x200, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static int tc6393xb_mmc_resume(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_resume(tc6393xb->scr + 0x200, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6393xb->scr + 0x200, state); +} + +static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, state); +} + +static struct tmio_mmc_data tc6393xb_mmc_data = { + .hclk = 24000000, + .set_pwr = tc6393xb_mmc_pwr, + .set_no_clk_div = tc6393xb_mmc_clk_div, +}; + static struct mfd_cell __devinitdata tc6393xb_cells[] = { [TC6393XB_CELL_NAND] = { .name = "tmio-nand", @@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { }, [TC6393XB_CELL_MMC] = { .name = "tmio-mmc", + .enable = tc6393xb_mmc_enable, + .resume = tc6393xb_mmc_resume, .driver_data = &tc6393xb_mmc_data, .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .resources = tc6393xb_mmc_resources, @@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer"); MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller"); MODULE_ALIAS("platform:tc6393xb"); + diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c new file mode 100644 index 0000000..483fbbb --- /dev/null +++ b/drivers/mfd/tmio_core.c @@ -0,0 +1,54 @@ +/* + * Toshiba TC6393XB SoC support + * + * Copyright(c) 2009 Ian Molton <spyro@xxxxxxx> + * + * 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. + */ + +#include <linux/mfd/tmio.h> + +int tmio_core_mmc_enable(void __iomem *cnf, unsigned long base) +{ + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf + CNF_CMD, SDCREN); + sd_config_write32(cnf + CNF_CTL_BASE, base & 0xfffe); + + /* Disable SD power during suspend */ + sd_config_write8(cnf + CNF_PWR_CTL_3, 0x01); + + /* The below is required but why? FIXME */ + sd_config_write8(cnf + CNF_STOP_CLK_CTL, 0x1f); + + /* Power down SD bus*/ + sd_config_write8(cnf + CNF_PWR_CTL_2, 0x00); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_enable); + +int tmio_core_mmc_resume(void __iomem *cnf, unsigned long base) +{ + + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf + CNF_CMD, SDCREN); + sd_config_write32(cnf + CNF_CTL_BASE, base & 0xfffe); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_resume); + +void tmio_core_mmc_pwr(void __iomem *cnf, int state) +{ + sd_config_write8(cnf + CNF_PWR_CTL_2, state ? 0x02 : 0x00); +} +EXPORT_SYMBOL(tmio_core_mmc_pwr); + +void tmio_core_mmc_clk_div(void __iomem *cnf, int state) +{ + sd_config_write8(cnf + CNF_SD_CLK_MODE, state ? 1 : 0); +} +EXPORT_SYMBOL(tmio_core_mmc_clk_div); + diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 91991b4..e701732 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) clk |= 0x100; } - sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22); + if (host->set_no_clk_div) + host->set_no_clk_div(host->pdev, (clk>>22) & 1); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); } @@ -427,12 +429,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Power sequence - OFF -> ON -> UP */ switch (ios->power_mode) { case MMC_POWER_OFF: /* power down SD bus */ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); + if (host->set_pwr) + host->set_pwr(host->pdev, 0); tmio_mmc_clk_stop(host); break; case MMC_POWER_ON: /* power up SD bus */ - - sd_config_write8(host, CNF_PWR_CTL_2, 0x02); + if (host->set_pwr) + host->set_pwr(host->pdev, 1); break; case MMC_POWER_UP: /* start bus clock */ tmio_mmc_clk_start(host); @@ -475,8 +478,8 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) ret = mmc_suspend_host(mmc, state); /* Tell MFD core it can disable us now.*/ - if (!ret && cell->disable) - cell->disable(dev); + if (!ret && cell->suspend) + cell->suspend(dev); return ret; } @@ -485,21 +488,15 @@ static int tmio_mmc_resume(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct mmc_host *mmc = platform_get_drvdata(dev); - struct tmio_mmc_host *host = mmc_priv(mmc); int ret = 0; /* Tell the MFD core we are ready to be enabled */ - if (cell->enable) { - ret = cell->enable(dev); + if (cell->resume) { + ret = cell->resume(dev); if (ret) goto out; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - mmc_resume_host(mmc); out: @@ -514,17 +511,16 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct tmio_mmc_data *pdata; - struct resource *res_ctl, *res_cnf; + struct resource *res_ctl; struct tmio_mmc_host *host; struct mmc_host *mmc; int ret = -EINVAL; - if (dev->num_resources != 3) + if (dev->num_resources != 2) goto out; res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0); - res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1); - if (!res_ctl || !res_cnf) + if (!res_ctl) goto out; pdata = cell->driver_data; @@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) host = mmc_priv(mmc); host->mmc = mmc; + host->pdev = dev; platform_set_drvdata(dev, mmc); + host->set_pwr = pdata->set_pwr; + host->set_no_clk_div = pdata->set_no_clk_div; + /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ host->bus_shift = resource_size(res_ctl) >> 10; @@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (!host->ctl) goto host_free; - host->cnf = ioremap(res_cnf->start, resource_size(res_cnf)); - if (!host->cnf) - goto unmap_ctl; - mmc->ops = &tmio_mmc_ops; mmc->caps = MMC_CAP_4_BIT_DATA; mmc->f_max = pdata->hclk; @@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (cell->enable) { ret = cell->enable(dev); if (ret) - goto unmap_cnf; + goto unmap_ctl; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - - /* Disable SD power during suspend */ - sd_config_write8(host, CNF_PWR_CTL_3, 0x01); - - /* The below is required but why? FIXME */ - sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f); - - /* Power down SD bus*/ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); - tmio_mmc_clk_stop(host); reset(host); @@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (ret >= 0) host->irq = ret; else - goto unmap_cnf; + goto unmap_ctl; disable_mmc_irqs(host, TMIO_MASK_ALL); ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "tmio-mmc", host); if (ret) - goto unmap_cnf; + goto unmap_ctl; mmc_add_host(mmc); @@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) return 0; -unmap_cnf: - iounmap(host->cnf); unmap_ctl: iounmap(host->ctl); host_free: @@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) mmc_remove_host(mmc); free_irq(host->irq, host); iounmap(host->ctl); - iounmap(host->cnf); mmc_free_host(mmc); } diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9fa9985..c676767 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -11,26 +11,6 @@ #include <linux/highmem.h> -#define CNF_CMD 0x04 -#define CNF_CTL_BASE 0x10 -#define CNF_INT_PIN 0x3d -#define CNF_STOP_CLK_CTL 0x40 -#define CNF_GCLK_CTL 0x41 -#define CNF_SD_CLK_MODE 0x42 -#define CNF_PIN_STATUS 0x44 -#define CNF_PWR_CTL_1 0x48 -#define CNF_PWR_CTL_2 0x49 -#define CNF_PWR_CTL_3 0x4a -#define CNF_CARD_DETECT_MODE 0x4c -#define CNF_SD_SLOT 0x50 -#define CNF_EXT_GCLK_CTL_1 0xf0 -#define CNF_EXT_GCLK_CTL_2 0xf1 -#define CNF_EXT_GCLK_CTL_3 0xf9 -#define CNF_SD_LED_EN_1 0xfa -#define CNF_SD_LED_EN_2 0xfe - -#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/ - #define CTL_SD_CMD 0x00 #define CTL_ARG_REG 0x04 #define CTL_STOP_INTERNAL_ACTION 0x08 @@ -110,7 +90,6 @@ struct tmio_mmc_host { - void __iomem *cnf; void __iomem *ctl; unsigned long bus_shift; struct mmc_command *cmd; @@ -119,10 +98,16 @@ struct tmio_mmc_host { struct mmc_host *mmc; int irq; + /* Callbacks for clock / power control */ + void (*set_pwr)(struct platform_device *host, int state); + void (*set_no_clk_div)(struct platform_device *host, int state); + /* pio related stuff */ struct scatterlist *sg_ptr; unsigned int sg_len; unsigned int sg_off; + + struct platform_device *pdev; }; #include <linux/io.h> @@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); } -static inline void sd_config_write8(struct tmio_mmc_host *host, int addr, - u8 val) -{ - writeb(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write16(struct tmio_mmc_host *host, int addr, - u16 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write32(struct tmio_mmc_host *host, int addr, - u32 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); - writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift)); -} - #include <linux/scatterlist.h> #include <linux/blkdev.h> diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 6b9c5d0..a206a8d 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -2,6 +2,8 @@ #define MFD_TMIO_H #include <linux/fb.h> +#include <linux/io.h> +#include <linux/platform_device.h> #define tmio_ioread8(addr) readb(addr) #define tmio_ioread16(addr) readw(addr) @@ -18,11 +20,42 @@ writew((val) >> 16, (addr) + 2); \ } while (0) +#define CNF_CMD 0x04 +#define CNF_CTL_BASE 0x10 +#define CNF_INT_PIN 0x3d +#define CNF_STOP_CLK_CTL 0x40 +#define CNF_GCLK_CTL 0x41 +#define CNF_SD_CLK_MODE 0x42 +#define CNF_PIN_STATUS 0x44 +#define CNF_PWR_CTL_1 0x48 +#define CNF_PWR_CTL_2 0x49 +#define CNF_PWR_CTL_3 0x4a +#define CNF_CARD_DETECT_MODE 0x4c +#define CNF_SD_SLOT 0x50 +#define CNF_EXT_GCLK_CTL_1 0xf0 +#define CNF_EXT_GCLK_CTL_2 0xf1 +#define CNF_EXT_GCLK_CTL_3 0xf9 +#define CNF_SD_LED_EN_1 0xfa +#define CNF_SD_LED_EN_2 0xfe + +#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/ + +#define sd_config_write8(a, b) tmio_iowrite8((b), (a)) +#define sd_config_write16(a, b) tmio_iowrite16((b), (a)) +#define sd_config_write32(a, b) tmio_iowrite32((b), (a)) + +int tmio_core_mmc_enable(void __iomem *cnf, unsigned long base); +int tmio_core_mmc_resume(void __iomem *cnf, unsigned long base); +void tmio_core_mmc_pwr(void __iomem *cnf, int state); +void tmio_core_mmc_clk_div(void __iomem *cnf, int state); + /* * data for the MMC controller */ struct tmio_mmc_data { const unsigned int hclk; + void (*set_pwr)(struct platform_device *host, int state); + void (*set_no_clk_div)(struct platform_device *host, int state); }; /* -- 1.6.3.3