mfd: tmio_mmc hardware abstraction for CNF area
authorIan Molton <ian@mnementh.co.uk>
Wed, 6 Jan 2010 12:51:48 +0000 (13:51 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Mon, 18 Jan 2010 11:30:27 +0000 (12:30 +0100)
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 support non-toshiba based hardware.

ASIC3 support by Philipp Zabel

Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
drivers/mfd/Makefile
drivers/mfd/asic3.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/tmio_core.c [new file with mode: 0644]
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/tmio_mmc.h
include/linux/mfd/tmio.h

index ca2f2c4ff05e70e2ac207516f4a215df3401136a..8f0d18409edef598ce5e31d9eda84a788e5b0948 100644 (file)
@@ -11,9 +11,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
 wm831x-objs                    := wm831x-core.o wm831x-irq.o wm831x-otp.o
index e22128c3e9a8a426825337eb5f2aadb5945f6ad2..95c1e6bd1729d84c3e176f3990a95655628f6c17 100644 (file)
@@ -80,6 +80,7 @@ struct asic3 {
        u16 irq_bothedge[4];
        struct gpio_chip gpio;
        struct device *dev;
+       void __iomem *tmio_cnf;
 
        struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
 };
@@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = {
        .resources     = ds1wm_resources,
 };
 
+static void asic3_mmc_pwr(struct platform_device *pdev, int state)
+{
+       struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+       tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state);
+}
+
+static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
+{
+       struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+       tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state);
+}
+
 static struct tmio_mmc_data asic3_mmc_data = {
-       .hclk = 24576000,
+       .hclk           = 24576000,
+       .set_pwr        = asic3_mmc_pwr,
+       .set_clk_div    = asic3_mmc_clk_div,
 };
 
 static struct resource asic3_mmc_resources[] = {
@@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = {
                .end   = ASIC3_SD_CTRL_BASE + 0x3ff,
                .flags = IORESOURCE_MEM,
        },
-       {
-               .start = ASIC3_SD_CONFIG_BASE,
-               .end   = ASIC3_SD_CONFIG_BASE + 0x1ff,
-               .flags = IORESOURCE_MEM,
-       },
        {
                .start = 0,
                .end   = 0,
@@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev)
        asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
                           ASIC3_SDHWCTRL_SDPWR, 1);
 
+       /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */
+       tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift,
+                            ASIC3_SD_CTRL_BASE >> 1);
+
        return 0;
 }
 
@@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
        asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
 
        /* MMC */
+       asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
+                                mem_sdio->start, 0x400 >> asic->bus_shift);
+       if (!asic->tmio_cnf) {
+               ret = -ENOMEM;
+               dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
+               goto out;
+       }
        asic3_mmc_resources[0].start >>= asic->bus_shift;
        asic3_mmc_resources[0].end   >>= asic->bus_shift;
-       asic3_mmc_resources[1].start >>= asic->bus_shift;
-       asic3_mmc_resources[1].end   >>= asic->bus_shift;
 
        asic3_cell_mmc.platform_data = &asic3_cell_mmc;
        asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
@@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
 
 static void asic3_mfd_remove(struct platform_device *pdev)
 {
+       struct asic3 *asic = platform_get_drvdata(pdev);
+
        mfd_remove_devices(&pdev->dev);
+       iounmap(asic->tmio_cnf);
 }
 
 /* Core */
index 0a255c1f1ce7b60a3633b487ecaa18797eda43aa..bcf4687d4af5686132c5a155027b595588cf8390 100644 (file)
@@ -38,6 +38,19 @@ enum {
        T7L66XB_CELL_MMC,
 };
 
+static const struct resource t7l66xb_mmc_resources[] = {
+       {
+               .start = 0x800,
+               .end    = 0x9ff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_T7L66XB_MMC,
+               .end    = IRQ_T7L66XB_MMC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
 #define SCR_REVID      0x08            /* b Revision ID        */
 #define SCR_IMR                0x42            /* b Interrupt Mask     */
 #define SCR_DEV_CTL    0xe0            /* b Device control     */
@@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
 
        spin_unlock_irqrestore(&t7l66xb->lock, flags);
 
+       tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
+               t7l66xb_mmc_resources[0].start & 0xfffe);
+
        return 0;
 }
 
@@ -106,28 +122,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, 0, 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, 0, state);
+}
+
 /*--------------------------------------------------------------------------*/
 
 static struct tmio_mmc_data t7166xb_mmc_data = {
        .hclk = 24000000,
-};
-
-static const struct resource t7l66xb_mmc_resources[] = {
-       {
-               .start = 0x800,
-               .end    = 0x9ff,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = 0x200,
-               .end    = 0x2ff,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = IRQ_T7L66XB_MMC,
-               .end    = IRQ_T7L66XB_MMC,
-               .flags = IORESOURCE_IRQ,
-       },
+       .set_pwr = t7l66xb_mmc_pwr,
+       .set_clk_div = t7l66xb_mmc_clk_div,
 };
 
 static const struct resource t7l66xb_nand_resources[] = {
@@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev)
        if (pdata && pdata->resume)
                pdata->resume(dev);
 
+       tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
+               t7l66xb_mmc_resources[0].start & 0xfffe);
+
        return 0;
 }
 #else
index 3280ab33f88ab20944e0ec15018236d73f207f5e..5c7f04343d5c3be1d8ce446d1b2d206df4044915 100644 (file)
@@ -22,28 +22,52 @@ enum {
        TC6387XB_CELL_MMC,
 };
 
+struct tc6387xb {
+       void __iomem *scr;
+       struct clk *clk32k;
+       struct resource rscr;
+};
+
+static struct resource tc6387xb_mmc_resources[] = {
+       {
+               .start = 0x800,
+               .end   = 0x9ff,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = 0,
+               .end   = 0,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+/*--------------------------------------------------------------------------*/
+
 #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, 0,
+               tc6387xb_mmc_resources[0].start & 0xfffe);
+
        return 0;
 }
 #else
@@ -53,12 +77,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, 0, 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, 0, 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, 0,
+               tc6387xb_mmc_resources[0].start & 0xfffe);
 
        return 0;
 }
@@ -66,36 +110,20 @@ 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_clk_div = tc6387xb_mmc_clk_div,
 };
 
-static struct resource tc6387xb_mmc_resources[] = {
-       {
-               .start = 0x800,
-               .end   = 0x9ff,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = 0x200,
-               .end   = 0x2ff,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = 0,
-               .end   = 0,
-               .flags = IORESOURCE_IRQ,
-       },
-};
+/*--------------------------------------------------------------------------*/
 
 static struct mfd_cell tc6387xb_cells[] = {
        [TC6387XB_CELL_MMC] = {
@@ -111,8 +139,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 +149,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 +200,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 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Ian Molton");
 MODULE_ALIAS("platform:tc6387xb");
+
index 1429a7341a9a976481b2ba11ad29258ba2cc6ac2..4bc5a08a2b09e8421548aaa5a0a99ecfa70370eb 100644 (file)
@@ -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,
@@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
                .end    = 0x9ff,
                .flags  = IORESOURCE_MEM,
        },
-       {
-               .start  = 0x200,
-               .end    = 0x2ff,
-               .flags  = IORESOURCE_MEM,
-       },
        {
                .start  = IRQ_TC6393_MMC,
                .end    = IRQ_TC6393_MMC,
@@ -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, 0,
+               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, 0,
+               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, 0, 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, 0, state);
+}
+
+static struct tmio_mmc_data tc6393xb_mmc_data = {
+       .hclk = 24000000,
+       .set_pwr = tc6393xb_mmc_pwr,
+       .set_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 (file)
index 0000000..eddc19a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright(c) 2009 Ian Molton <spyro@f2s.com>
+ *
+ * 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, int shift, unsigned long base)
+{
+       /* Enable the MMC/SD Control registers */
+       sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
+       sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
+
+       /* Disable SD power during suspend */
+       sd_config_write8(cnf, shift, CNF_PWR_CTL_3, 0x01);
+
+       /* The below is required but why? FIXME */
+       sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f);
+
+       /* Power down SD bus */
+       sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00);
+
+       return 0;
+}
+EXPORT_SYMBOL(tmio_core_mmc_enable);
+
+int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base)
+{
+
+       /* Enable the MMC/SD Control registers */
+       sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
+       sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
+
+       return 0;
+}
+EXPORT_SYMBOL(tmio_core_mmc_resume);
+
+void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state)
+{
+       sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00);
+}
+EXPORT_SYMBOL(tmio_core_mmc_pwr);
+
+void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state)
+{
+       sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0);
+}
+EXPORT_SYMBOL(tmio_core_mmc_clk_div);
+
index 7cccc852374772d4d2479e4eb9f681a5bdb74bb5..e22c3fa3516a733d51ab87b83eaf6c728f81a896 100644 (file)
@@ -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_clk_div)
+               host->set_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);
@@ -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_clk_div = pdata->set_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, dev_name(&dev->dev), 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);
        }
 
index 9fa9985949743be7920eccb0a1627036ea8dcc37..692dc23363b9f7718c6f3ff9bb42033fd8251867 100644 (file)
 
 #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
 
 
 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_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>
 
index 6b9c5d06690c8d9f82bd99a19e215b9fc8e1a683..9cb1834deffae2a6a028409009f7222c71801711 100644 (file)
@@ -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)
        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(base, shift, reg, val) \
+       tmio_iowrite8((val), (base) + ((reg) << (shift)))
+#define sd_config_write16(base, shift, reg, val) \
+       tmio_iowrite16((val), (base) + ((reg) << (shift)))
+#define sd_config_write32(base, shift, reg, val) \
+       do { \
+               tmio_iowrite16((val), (base) + ((reg) << (shift)));   \
+               tmio_iowrite16((val) >> 16, (base) + ((reg + 2) << (shift))); \
+       } while (0)
+
+int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
+int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
+void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state);
+void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, 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_clk_div)(struct platform_device *host, int state);
 };
 
 /*