Commit 64e8867ba8098b69889c1af94997a5ba2348fb26

Authored by Ian Molton
Committed by Samuel Ortiz
1 parent 6f2af72a24

mfd: tmio_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 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>

Showing 9 changed files with 323 additions and 149 deletions Side-by-side Diff

drivers/mfd/Makefile
... ... @@ -11,9 +11,9 @@
11 11  
12 12 obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
13 13  
14   -obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o
15   -obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o
16   -obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
  14 +obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
  15 +obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
  16 +obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
17 17  
18 18 obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
19 19 wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
... ... @@ -80,6 +80,7 @@
80 80 u16 irq_bothedge[4];
81 81 struct gpio_chip gpio;
82 82 struct device *dev;
  83 + void __iomem *tmio_cnf;
83 84  
84 85 struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
85 86 };
86 87  
... ... @@ -685,8 +686,24 @@
685 686 .resources = ds1wm_resources,
686 687 };
687 688  
  689 +static void asic3_mmc_pwr(struct platform_device *pdev, int state)
  690 +{
  691 + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  692 +
  693 + tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state);
  694 +}
  695 +
  696 +static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
  697 +{
  698 + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  699 +
  700 + tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state);
  701 +}
  702 +
688 703 static struct tmio_mmc_data asic3_mmc_data = {
689   - .hclk = 24576000,
  704 + .hclk = 24576000,
  705 + .set_pwr = asic3_mmc_pwr,
  706 + .set_clk_div = asic3_mmc_clk_div,
690 707 };
691 708  
692 709 static struct resource asic3_mmc_resources[] = {
... ... @@ -696,11 +713,6 @@
696 713 .flags = IORESOURCE_MEM,
697 714 },
698 715 {
699   - .start = ASIC3_SD_CONFIG_BASE,
700   - .end = ASIC3_SD_CONFIG_BASE + 0x1ff,
701   - .flags = IORESOURCE_MEM,
702   - },
703   - {
704 716 .start = 0,
705 717 .end = 0,
706 718 .flags = IORESOURCE_IRQ,
... ... @@ -743,6 +755,10 @@
743 755 asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
744 756 ASIC3_SDHWCTRL_SDPWR, 1);
745 757  
  758 + /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */
  759 + tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift,
  760 + ASIC3_SD_CTRL_BASE >> 1);
  761 +
746 762 return 0;
747 763 }
748 764  
749 765  
... ... @@ -797,10 +813,15 @@
797 813 asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
798 814  
799 815 /* MMC */
  816 + asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
  817 + mem_sdio->start, 0x400 >> asic->bus_shift);
  818 + if (!asic->tmio_cnf) {
  819 + ret = -ENOMEM;
  820 + dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
  821 + goto out;
  822 + }
800 823 asic3_mmc_resources[0].start >>= asic->bus_shift;
801 824 asic3_mmc_resources[0].end >>= asic->bus_shift;
802   - asic3_mmc_resources[1].start >>= asic->bus_shift;
803   - asic3_mmc_resources[1].end >>= asic->bus_shift;
804 825  
805 826 asic3_cell_mmc.platform_data = &asic3_cell_mmc;
806 827 asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
807 828  
... ... @@ -820,7 +841,10 @@
820 841  
821 842 static void asic3_mfd_remove(struct platform_device *pdev)
822 843 {
  844 + struct asic3 *asic = platform_get_drvdata(pdev);
  845 +
823 846 mfd_remove_devices(&pdev->dev);
  847 + iounmap(asic->tmio_cnf);
824 848 }
825 849  
826 850 /* Core */
drivers/mfd/t7l66xb.c
... ... @@ -38,6 +38,19 @@
38 38 T7L66XB_CELL_MMC,
39 39 };
40 40  
  41 +static const struct resource t7l66xb_mmc_resources[] = {
  42 + {
  43 + .start = 0x800,
  44 + .end = 0x9ff,
  45 + .flags = IORESOURCE_MEM,
  46 + },
  47 + {
  48 + .start = IRQ_T7L66XB_MMC,
  49 + .end = IRQ_T7L66XB_MMC,
  50 + .flags = IORESOURCE_IRQ,
  51 + },
  52 +};
  53 +
41 54 #define SCR_REVID 0x08 /* b Revision ID */
42 55 #define SCR_IMR 0x42 /* b Interrupt Mask */
43 56 #define SCR_DEV_CTL 0xe0 /* b Device control */
... ... @@ -83,6 +96,9 @@
83 96  
84 97 spin_unlock_irqrestore(&t7l66xb->lock, flags);
85 98  
  99 + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
  100 + t7l66xb_mmc_resources[0].start & 0xfffe);
  101 +
86 102 return 0;
87 103 }
88 104  
89 105  
90 106  
... ... @@ -106,30 +122,30 @@
106 122 return 0;
107 123 }
108 124  
  125 +static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state)
  126 +{
  127 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  128 + struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
  129 +
  130 + tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state);
  131 +}
  132 +
  133 +static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state)
  134 +{
  135 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  136 + struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
  137 +
  138 + tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state);
  139 +}
  140 +
109 141 /*--------------------------------------------------------------------------*/
110 142  
111 143 static struct tmio_mmc_data t7166xb_mmc_data = {
112 144 .hclk = 24000000,
  145 + .set_pwr = t7l66xb_mmc_pwr,
  146 + .set_clk_div = t7l66xb_mmc_clk_div,
113 147 };
114 148  
115   -static const struct resource t7l66xb_mmc_resources[] = {
116   - {
117   - .start = 0x800,
118   - .end = 0x9ff,
119   - .flags = IORESOURCE_MEM,
120   - },
121   - {
122   - .start = 0x200,
123   - .end = 0x2ff,
124   - .flags = IORESOURCE_MEM,
125   - },
126   - {
127   - .start = IRQ_T7L66XB_MMC,
128   - .end = IRQ_T7L66XB_MMC,
129   - .flags = IORESOURCE_IRQ,
130   - },
131   -};
132   -
133 149 static const struct resource t7l66xb_nand_resources[] = {
134 150 {
135 151 .start = 0xc00,
... ... @@ -281,6 +297,9 @@
281 297 clk_enable(t7l66xb->clk48m);
282 298 if (pdata && pdata->resume)
283 299 pdata->resume(dev);
  300 +
  301 + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
  302 + t7l66xb_mmc_resources[0].start & 0xfffe);
284 303  
285 304 return 0;
286 305 }
drivers/mfd/tc6387xb.c
... ... @@ -22,28 +22,52 @@
22 22 TC6387XB_CELL_MMC,
23 23 };
24 24  
  25 +struct tc6387xb {
  26 + void __iomem *scr;
  27 + struct clk *clk32k;
  28 + struct resource rscr;
  29 +};
  30 +
  31 +static struct resource tc6387xb_mmc_resources[] = {
  32 + {
  33 + .start = 0x800,
  34 + .end = 0x9ff,
  35 + .flags = IORESOURCE_MEM,
  36 + },
  37 + {
  38 + .start = 0,
  39 + .end = 0,
  40 + .flags = IORESOURCE_IRQ,
  41 + },
  42 +};
  43 +
  44 +/*--------------------------------------------------------------------------*/
  45 +
25 46 #ifdef CONFIG_PM
26 47 static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
27 48 {
28   - struct clk *clk32k = platform_get_drvdata(dev);
  49 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
29 50 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
30 51  
31 52 if (pdata && pdata->suspend)
32 53 pdata->suspend(dev);
33   - clk_disable(clk32k);
  54 + clk_disable(tc6387xb->clk32k);
34 55  
35 56 return 0;
36 57 }
37 58  
38 59 static int tc6387xb_resume(struct platform_device *dev)
39 60 {
40   - struct clk *clk32k = platform_get_drvdata(dev);
  61 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
41 62 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
42 63  
43   - clk_enable(clk32k);
  64 + clk_enable(tc6387xb->clk32k);
44 65 if (pdata && pdata->resume)
45 66 pdata->resume(dev);
46 67  
  68 + tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0,
  69 + tc6387xb_mmc_resources[0].start & 0xfffe);
  70 +
47 71 return 0;
48 72 }
49 73 #else
50 74  
51 75  
52 76  
53 77  
54 78  
55 79  
56 80  
57 81  
... ... @@ -53,49 +77,53 @@
53 77  
54 78 /*--------------------------------------------------------------------------*/
55 79  
  80 +static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state)
  81 +{
  82 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  83 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
  84 +
  85 + tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state);
  86 +}
  87 +
  88 +static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state)
  89 +{
  90 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  91 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
  92 +
  93 + tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state);
  94 +}
  95 +
  96 +
56 97 static int tc6387xb_mmc_enable(struct platform_device *mmc)
57 98 {
58 99 struct platform_device *dev = to_platform_device(mmc->dev.parent);
59   - struct clk *clk32k = platform_get_drvdata(dev);
  100 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
60 101  
61   - clk_enable(clk32k);
  102 + clk_enable(tc6387xb->clk32k);
62 103  
  104 + tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
  105 + tc6387xb_mmc_resources[0].start & 0xfffe);
  106 +
63 107 return 0;
64 108 }
65 109  
66 110 static int tc6387xb_mmc_disable(struct platform_device *mmc)
67 111 {
68 112 struct platform_device *dev = to_platform_device(mmc->dev.parent);
69   - struct clk *clk32k = platform_get_drvdata(dev);
  113 + struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
70 114  
71   - clk_disable(clk32k);
  115 + clk_disable(tc6387xb->clk32k);
72 116  
73 117 return 0;
74 118 }
75 119  
76   -/*--------------------------------------------------------------------------*/
77   -
78 120 static struct tmio_mmc_data tc6387xb_mmc_data = {
79 121 .hclk = 24000000,
  122 + .set_pwr = tc6387xb_mmc_pwr,
  123 + .set_clk_div = tc6387xb_mmc_clk_div,
80 124 };
81 125  
82   -static struct resource tc6387xb_mmc_resources[] = {
83   - {
84   - .start = 0x800,
85   - .end = 0x9ff,
86   - .flags = IORESOURCE_MEM,
87   - },
88   - {
89   - .start = 0x200,
90   - .end = 0x2ff,
91   - .flags = IORESOURCE_MEM,
92   - },
93   - {
94   - .start = 0,
95   - .end = 0,
96   - .flags = IORESOURCE_IRQ,
97   - },
98   -};
  126 +/*--------------------------------------------------------------------------*/
99 127  
100 128 static struct mfd_cell tc6387xb_cells[] = {
101 129 [TC6387XB_CELL_MMC] = {
102 130  
... ... @@ -111,8 +139,9 @@
111 139 static int tc6387xb_probe(struct platform_device *dev)
112 140 {
113 141 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
114   - struct resource *iomem;
  142 + struct resource *iomem, *rscr;
115 143 struct clk *clk32k;
  144 + struct tc6387xb *tc6387xb;
116 145 int irq, ret;
117 146  
118 147 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
119 148  
120 149  
121 150  
122 151  
123 152  
... ... @@ -120,19 +149,41 @@
120 149 return -EINVAL;
121 150 }
122 151  
  152 + tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
  153 + if (!tc6387xb)
  154 + return -ENOMEM;
  155 +
123 156 ret = platform_get_irq(dev, 0);
124 157 if (ret >= 0)
125 158 irq = ret;
126 159 else
127   - goto err_resource;
  160 + goto err_no_irq;
128 161  
129 162 clk32k = clk_get(&dev->dev, "CLK_CK32K");
130 163 if (IS_ERR(clk32k)) {
131 164 ret = PTR_ERR(clk32k);
  165 + goto err_no_clk;
  166 + }
  167 +
  168 + rscr = &tc6387xb->rscr;
  169 + rscr->name = "tc6387xb-core";
  170 + rscr->start = iomem->start;
  171 + rscr->end = iomem->start + 0xff;
  172 + rscr->flags = IORESOURCE_MEM;
  173 +
  174 + ret = request_resource(iomem, rscr);
  175 + if (ret)
132 176 goto err_resource;
  177 +
  178 + tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
  179 + if (!tc6387xb->scr) {
  180 + ret = -ENOMEM;
  181 + goto err_ioremap;
133 182 }
134   - platform_set_drvdata(dev, clk32k);
135 183  
  184 + tc6387xb->clk32k = clk32k;
  185 + platform_set_drvdata(dev, tc6387xb);
  186 +
136 187 if (pdata && pdata->enable)
137 188 pdata->enable(dev);
138 189  
139 190  
... ... @@ -149,8 +200,13 @@
149 200 if (!ret)
150 201 return 0;
151 202  
152   - clk_put(clk32k);
  203 +err_ioremap:
  204 + release_resource(&tc6387xb->rscr);
153 205 err_resource:
  206 + clk_put(clk32k);
  207 +err_no_clk:
  208 +err_no_irq:
  209 + kfree(tc6387xb);
154 210 return ret;
155 211 }
156 212  
drivers/mfd/tc6393xb.c
... ... @@ -136,10 +136,6 @@
136 136 return 0;
137 137 }
138 138  
139   -static struct tmio_mmc_data tc6393xb_mmc_data = {
140   - .hclk = 24000000,
141   -};
142   -
143 139 static struct resource __devinitdata tc6393xb_nand_resources[] = {
144 140 {
145 141 .start = 0x1000,
... ... @@ -165,11 +161,6 @@
165 161 .flags = IORESOURCE_MEM,
166 162 },
167 163 {
168   - .start = 0x200,
169   - .end = 0x2ff,
170   - .flags = IORESOURCE_MEM,
171   - },
172   - {
173 164 .start = IRQ_TC6393_MMC,
174 165 .end = IRQ_TC6393_MMC,
175 166 .flags = IORESOURCE_IRQ,
... ... @@ -346,6 +337,50 @@
346 337 }
347 338 EXPORT_SYMBOL(tc6393xb_lcd_mode);
348 339  
  340 +static int tc6393xb_mmc_enable(struct platform_device *mmc)
  341 +{
  342 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  343 + struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
  344 +
  345 + tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0,
  346 + tc6393xb_mmc_resources[0].start & 0xfffe);
  347 +
  348 + return 0;
  349 +}
  350 +
  351 +static int tc6393xb_mmc_resume(struct platform_device *mmc)
  352 +{
  353 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  354 + struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
  355 +
  356 + tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0,
  357 + tc6393xb_mmc_resources[0].start & 0xfffe);
  358 +
  359 + return 0;
  360 +}
  361 +
  362 +static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state)
  363 +{
  364 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  365 + struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
  366 +
  367 + tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state);
  368 +}
  369 +
  370 +static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state)
  371 +{
  372 + struct platform_device *dev = to_platform_device(mmc->dev.parent);
  373 + struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
  374 +
  375 + tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state);
  376 +}
  377 +
  378 +static struct tmio_mmc_data tc6393xb_mmc_data = {
  379 + .hclk = 24000000,
  380 + .set_pwr = tc6393xb_mmc_pwr,
  381 + .set_clk_div = tc6393xb_mmc_clk_div,
  382 +};
  383 +
349 384 static struct mfd_cell __devinitdata tc6393xb_cells[] = {
350 385 [TC6393XB_CELL_NAND] = {
351 386 .name = "tmio-nand",
... ... @@ -355,6 +390,8 @@
355 390 },
356 391 [TC6393XB_CELL_MMC] = {
357 392 .name = "tmio-mmc",
  393 + .enable = tc6393xb_mmc_enable,
  394 + .resume = tc6393xb_mmc_resume,
358 395 .driver_data = &tc6393xb_mmc_data,
359 396 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
360 397 .resources = tc6393xb_mmc_resources,
drivers/mfd/tmio_core.c
  1 +/*
  2 + * Copyright(c) 2009 Ian Molton <spyro@f2s.com>
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License version 2 as
  6 + * published by the Free Software Foundation.
  7 + */
  8 +
  9 +#include <linux/mfd/tmio.h>
  10 +
  11 +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base)
  12 +{
  13 + /* Enable the MMC/SD Control registers */
  14 + sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
  15 + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
  16 +
  17 + /* Disable SD power during suspend */
  18 + sd_config_write8(cnf, shift, CNF_PWR_CTL_3, 0x01);
  19 +
  20 + /* The below is required but why? FIXME */
  21 + sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f);
  22 +
  23 + /* Power down SD bus */
  24 + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00);
  25 +
  26 + return 0;
  27 +}
  28 +EXPORT_SYMBOL(tmio_core_mmc_enable);
  29 +
  30 +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base)
  31 +{
  32 +
  33 + /* Enable the MMC/SD Control registers */
  34 + sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
  35 + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
  36 +
  37 + return 0;
  38 +}
  39 +EXPORT_SYMBOL(tmio_core_mmc_resume);
  40 +
  41 +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state)
  42 +{
  43 + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00);
  44 +}
  45 +EXPORT_SYMBOL(tmio_core_mmc_pwr);
  46 +
  47 +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state)
  48 +{
  49 + sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0);
  50 +}
  51 +EXPORT_SYMBOL(tmio_core_mmc_clk_div);
drivers/mmc/host/tmio_mmc.c
... ... @@ -46,7 +46,9 @@
46 46 clk |= 0x100;
47 47 }
48 48  
49   - sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22);
  49 + if (host->set_clk_div)
  50 + host->set_clk_div(host->pdev, (clk>>22) & 1);
  51 +
50 52 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
51 53 }
52 54  
53 55  
... ... @@ -427,12 +429,13 @@
427 429 /* Power sequence - OFF -> ON -> UP */
428 430 switch (ios->power_mode) {
429 431 case MMC_POWER_OFF: /* power down SD bus */
430   - sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
  432 + if (host->set_pwr)
  433 + host->set_pwr(host->pdev, 0);
431 434 tmio_mmc_clk_stop(host);
432 435 break;
433 436 case MMC_POWER_ON: /* power up SD bus */
434   -
435   - sd_config_write8(host, CNF_PWR_CTL_2, 0x02);
  437 + if (host->set_pwr)
  438 + host->set_pwr(host->pdev, 1);
436 439 break;
437 440 case MMC_POWER_UP: /* start bus clock */
438 441 tmio_mmc_clk_start(host);
439 442  
440 443  
... ... @@ -485,21 +488,15 @@
485 488 {
486 489 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
487 490 struct mmc_host *mmc = platform_get_drvdata(dev);
488   - struct tmio_mmc_host *host = mmc_priv(mmc);
489 491 int ret = 0;
490 492  
491 493 /* Tell the MFD core we are ready to be enabled */
492   - if (cell->enable) {
493   - ret = cell->enable(dev);
  494 + if (cell->resume) {
  495 + ret = cell->resume(dev);
494 496 if (ret)
495 497 goto out;
496 498 }
497 499  
498   - /* Enable the MMC/SD Control registers */
499   - sd_config_write16(host, CNF_CMD, SDCREN);
500   - sd_config_write32(host, CNF_CTL_BASE,
501   - (dev->resource[0].start >> host->bus_shift) & 0xfffe);
502   -
503 500 mmc_resume_host(mmc);
504 501  
505 502 out:
506 503  
507 504  
... ... @@ -514,17 +511,16 @@
514 511 {
515 512 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
516 513 struct tmio_mmc_data *pdata;
517   - struct resource *res_ctl, *res_cnf;
  514 + struct resource *res_ctl;
518 515 struct tmio_mmc_host *host;
519 516 struct mmc_host *mmc;
520 517 int ret = -EINVAL;
521 518  
522   - if (dev->num_resources != 3)
  519 + if (dev->num_resources != 2)
523 520 goto out;
524 521  
525 522 res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
526   - res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1);
527   - if (!res_ctl || !res_cnf)
  523 + if (!res_ctl)
528 524 goto out;
529 525  
530 526 pdata = cell->driver_data;
531 527  
... ... @@ -539,8 +535,12 @@
539 535  
540 536 host = mmc_priv(mmc);
541 537 host->mmc = mmc;
  538 + host->pdev = dev;
542 539 platform_set_drvdata(dev, mmc);
543 540  
  541 + host->set_pwr = pdata->set_pwr;
  542 + host->set_clk_div = pdata->set_clk_div;
  543 +
544 544 /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
545 545 host->bus_shift = resource_size(res_ctl) >> 10;
546 546  
... ... @@ -548,10 +548,6 @@
548 548 if (!host->ctl)
549 549 goto host_free;
550 550  
551   - host->cnf = ioremap(res_cnf->start, resource_size(res_cnf));
552   - if (!host->cnf)
553   - goto unmap_ctl;
554   -
555 551 mmc->ops = &tmio_mmc_ops;
556 552 mmc->caps = MMC_CAP_4_BIT_DATA;
557 553 mmc->f_max = pdata->hclk;
558 554  
... ... @@ -562,23 +558,9 @@
562 558 if (cell->enable) {
563 559 ret = cell->enable(dev);
564 560 if (ret)
565   - goto unmap_cnf;
  561 + goto unmap_ctl;
566 562 }
567 563  
568   - /* Enable the MMC/SD Control registers */
569   - sd_config_write16(host, CNF_CMD, SDCREN);
570   - sd_config_write32(host, CNF_CTL_BASE,
571   - (dev->resource[0].start >> host->bus_shift) & 0xfffe);
572   -
573   - /* Disable SD power during suspend */
574   - sd_config_write8(host, CNF_PWR_CTL_3, 0x01);
575   -
576   - /* The below is required but why? FIXME */
577   - sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f);
578   -
579   - /* Power down SD bus*/
580   - sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
581   -
582 564 tmio_mmc_clk_stop(host);
583 565 reset(host);
584 566  
585 567  
... ... @@ -586,14 +568,14 @@
586 568 if (ret >= 0)
587 569 host->irq = ret;
588 570 else
589   - goto unmap_cnf;
  571 + goto unmap_ctl;
590 572  
591 573 disable_mmc_irqs(host, TMIO_MASK_ALL);
592 574  
593 575 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
594 576 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
595 577 if (ret)
596   - goto unmap_cnf;
  578 + goto unmap_ctl;
597 579  
598 580 mmc_add_host(mmc);
599 581  
... ... @@ -605,8 +587,6 @@
605 587  
606 588 return 0;
607 589  
608   -unmap_cnf:
609   - iounmap(host->cnf);
610 590 unmap_ctl:
611 591 iounmap(host->ctl);
612 592 host_free:
... ... @@ -626,7 +606,6 @@
626 606 mmc_remove_host(mmc);
627 607 free_irq(host->irq, host);
628 608 iounmap(host->ctl);
629   - iounmap(host->cnf);
630 609 mmc_free_host(mmc);
631 610 }
632 611  
drivers/mmc/host/tmio_mmc.h
... ... @@ -11,26 +11,6 @@
11 11  
12 12 #include <linux/highmem.h>
13 13  
14   -#define CNF_CMD 0x04
15   -#define CNF_CTL_BASE 0x10
16   -#define CNF_INT_PIN 0x3d
17   -#define CNF_STOP_CLK_CTL 0x40
18   -#define CNF_GCLK_CTL 0x41
19   -#define CNF_SD_CLK_MODE 0x42
20   -#define CNF_PIN_STATUS 0x44
21   -#define CNF_PWR_CTL_1 0x48
22   -#define CNF_PWR_CTL_2 0x49
23   -#define CNF_PWR_CTL_3 0x4a
24   -#define CNF_CARD_DETECT_MODE 0x4c
25   -#define CNF_SD_SLOT 0x50
26   -#define CNF_EXT_GCLK_CTL_1 0xf0
27   -#define CNF_EXT_GCLK_CTL_2 0xf1
28   -#define CNF_EXT_GCLK_CTL_3 0xf9
29   -#define CNF_SD_LED_EN_1 0xfa
30   -#define CNF_SD_LED_EN_2 0xfe
31   -
32   -#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
33   -
34 14 #define CTL_SD_CMD 0x00
35 15 #define CTL_ARG_REG 0x04
36 16 #define CTL_STOP_INTERNAL_ACTION 0x08
... ... @@ -110,7 +90,6 @@
110 90  
111 91  
112 92 struct tmio_mmc_host {
113   - void __iomem *cnf;
114 93 void __iomem *ctl;
115 94 unsigned long bus_shift;
116 95 struct mmc_command *cmd;
117 96  
... ... @@ -119,10 +98,16 @@
119 98 struct mmc_host *mmc;
120 99 int irq;
121 100  
  101 + /* Callbacks for clock / power control */
  102 + void (*set_pwr)(struct platform_device *host, int state);
  103 + void (*set_clk_div)(struct platform_device *host, int state);
  104 +
122 105 /* pio related stuff */
123 106 struct scatterlist *sg_ptr;
124 107 unsigned int sg_len;
125 108 unsigned int sg_off;
  109 +
  110 + struct platform_device *pdev;
126 111 };
127 112  
128 113 #include <linux/io.h>
... ... @@ -161,25 +146,6 @@
161 146 {
162 147 writew(val, host->ctl + (addr << host->bus_shift));
163 148 writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
164   -}
165   -
166   -static inline void sd_config_write8(struct tmio_mmc_host *host, int addr,
167   - u8 val)
168   -{
169   - writeb(val, host->cnf + (addr << host->bus_shift));
170   -}
171   -
172   -static inline void sd_config_write16(struct tmio_mmc_host *host, int addr,
173   - u16 val)
174   -{
175   - writew(val, host->cnf + (addr << host->bus_shift));
176   -}
177   -
178   -static inline void sd_config_write32(struct tmio_mmc_host *host, int addr,
179   - u32 val)
180   -{
181   - writew(val, host->cnf + (addr << host->bus_shift));
182   - writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift));
183 149 }
184 150  
185 151 #include <linux/scatterlist.h>
include/linux/mfd/tmio.h
... ... @@ -2,6 +2,8 @@
2 2 #define MFD_TMIO_H
3 3  
4 4 #include <linux/fb.h>
  5 +#include <linux/io.h>
  6 +#include <linux/platform_device.h>
5 7  
6 8 #define tmio_ioread8(addr) readb(addr)
7 9 #define tmio_ioread16(addr) readw(addr)
8 10  
... ... @@ -18,11 +20,48 @@
18 20 writew((val) >> 16, (addr) + 2); \
19 21 } while (0)
20 22  
  23 +#define CNF_CMD 0x04
  24 +#define CNF_CTL_BASE 0x10
  25 +#define CNF_INT_PIN 0x3d
  26 +#define CNF_STOP_CLK_CTL 0x40
  27 +#define CNF_GCLK_CTL 0x41
  28 +#define CNF_SD_CLK_MODE 0x42
  29 +#define CNF_PIN_STATUS 0x44
  30 +#define CNF_PWR_CTL_1 0x48
  31 +#define CNF_PWR_CTL_2 0x49
  32 +#define CNF_PWR_CTL_3 0x4a
  33 +#define CNF_CARD_DETECT_MODE 0x4c
  34 +#define CNF_SD_SLOT 0x50
  35 +#define CNF_EXT_GCLK_CTL_1 0xf0
  36 +#define CNF_EXT_GCLK_CTL_2 0xf1
  37 +#define CNF_EXT_GCLK_CTL_3 0xf9
  38 +#define CNF_SD_LED_EN_1 0xfa
  39 +#define CNF_SD_LED_EN_2 0xfe
  40 +
  41 +#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
  42 +
  43 +#define sd_config_write8(base, shift, reg, val) \
  44 + tmio_iowrite8((val), (base) + ((reg) << (shift)))
  45 +#define sd_config_write16(base, shift, reg, val) \
  46 + tmio_iowrite16((val), (base) + ((reg) << (shift)))
  47 +#define sd_config_write32(base, shift, reg, val) \
  48 + do { \
  49 + tmio_iowrite16((val), (base) + ((reg) << (shift))); \
  50 + tmio_iowrite16((val) >> 16, (base) + ((reg + 2) << (shift))); \
  51 + } while (0)
  52 +
  53 +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
  54 +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
  55 +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state);
  56 +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state);
  57 +
21 58 /*
22 59 * data for the MMC controller
23 60 */
24 61 struct tmio_mmc_data {
25 62 const unsigned int hclk;
  63 + void (*set_pwr)(struct platform_device *host, int state);
  64 + void (*set_clk_div)(struct platform_device *host, int state);
26 65 };
27 66  
28 67 /*