aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorIan Molton <ian@mnementh.co.uk>2010-01-06 07:51:48 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2010-01-18 06:30:27 -0500
commit64e8867ba8098b69889c1af94997a5ba2348fb26 (patch)
tree3391806575ec3435a26043a22ba45c9d76f0b791 /drivers/mfd
parent6f2af72a2451b7491fba820b1d1b0b91c6a84027 (diff)
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>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/asic3.c40
-rw-r--r--drivers/mfd/t7l66xb.c55
-rw-r--r--drivers/mfd/tc6387xb.c119
-rw-r--r--drivers/mfd/tc6393xb.c56
-rw-r--r--drivers/mfd/tmio_core.c52
6 files changed, 259 insertions, 69 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ca2f2c4ff05e..8f0d18409ede 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
11 11
12obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o 12obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
13 13
14obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o 14obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
15obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o 15obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
16obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o 16obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
17 17
18obj-$(CONFIG_MFD_WM8400) += wm8400-core.o 18obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
19wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o 19wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index e22128c3e9a8..95c1e6bd1729 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -80,6 +80,7 @@ struct asic3 {
80 u16 irq_bothedge[4]; 80 u16 irq_bothedge[4];
81 struct gpio_chip gpio; 81 struct gpio_chip gpio;
82 struct device *dev; 82 struct device *dev;
83 void __iomem *tmio_cnf;
83 84
84 struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)]; 85 struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
85}; 86};
@@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = {
685 .resources = ds1wm_resources, 686 .resources = ds1wm_resources,
686}; 687};
687 688
689static 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
696static 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
688static struct tmio_mmc_data asic3_mmc_data = { 703static 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
692static struct resource asic3_mmc_resources[] = { 709static struct resource asic3_mmc_resources[] = {
@@ -696,11 +713,6 @@ static struct resource asic3_mmc_resources[] = {
696 .flags = IORESOURCE_MEM, 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 .start = 0, 716 .start = 0,
705 .end = 0, 717 .end = 0,
706 .flags = IORESOURCE_IRQ, 718 .flags = IORESOURCE_IRQ,
@@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev)
743 asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), 755 asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
744 ASIC3_SDHWCTRL_SDPWR, 1); 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 return 0; 762 return 0;
747} 763}
748 764
@@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
797 asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); 813 asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
798 814
799 /* MMC */ 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 asic3_mmc_resources[0].start >>= asic->bus_shift; 823 asic3_mmc_resources[0].start >>= asic->bus_shift;
801 asic3_mmc_resources[0].end >>= asic->bus_shift; 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 asic3_cell_mmc.platform_data = &asic3_cell_mmc; 826 asic3_cell_mmc.platform_data = &asic3_cell_mmc;
806 asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc); 827 asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
@@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
820 841
821static void asic3_mfd_remove(struct platform_device *pdev) 842static void asic3_mfd_remove(struct platform_device *pdev)
822{ 843{
844 struct asic3 *asic = platform_get_drvdata(pdev);
845
823 mfd_remove_devices(&pdev->dev); 846 mfd_remove_devices(&pdev->dev);
847 iounmap(asic->tmio_cnf);
824} 848}
825 849
826/* Core */ 850/* Core */
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 0a255c1f1ce7..bcf4687d4af5 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -38,6 +38,19 @@ enum {
38 T7L66XB_CELL_MMC, 38 T7L66XB_CELL_MMC,
39}; 39};
40 40
41static 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#define SCR_REVID 0x08 /* b Revision ID */ 54#define SCR_REVID 0x08 /* b Revision ID */
42#define SCR_IMR 0x42 /* b Interrupt Mask */ 55#define SCR_IMR 0x42 /* b Interrupt Mask */
43#define SCR_DEV_CTL 0xe0 /* b Device control */ 56#define SCR_DEV_CTL 0xe0 /* b Device control */
@@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
83 96
84 spin_unlock_irqrestore(&t7l66xb->lock, flags); 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 return 0; 102 return 0;
87} 103}
88 104
@@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
106 return 0; 122 return 0;
107} 123}
108 124
125static 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
133static 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
111static struct tmio_mmc_data t7166xb_mmc_data = { 143static struct tmio_mmc_data t7166xb_mmc_data = {
112 .hclk = 24000000, 144 .hclk = 24000000,
113}; 145 .set_pwr = t7l66xb_mmc_pwr,
114 146 .set_clk_div = t7l66xb_mmc_clk_div,
115static 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}; 147};
132 148
133static const struct resource t7l66xb_nand_resources[] = { 149static const struct resource t7l66xb_nand_resources[] = {
@@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev)
282 if (pdata && pdata->resume) 298 if (pdata && pdata->resume)
283 pdata->resume(dev); 299 pdata->resume(dev);
284 300
301 tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
302 t7l66xb_mmc_resources[0].start & 0xfffe);
303
285 return 0; 304 return 0;
286} 305}
287#else 306#else
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 3280ab33f88a..5c7f04343d5c 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -22,28 +22,52 @@ enum {
22 TC6387XB_CELL_MMC, 22 TC6387XB_CELL_MMC,
23}; 23};
24 24
25struct tc6387xb {
26 void __iomem *scr;
27 struct clk *clk32k;
28 struct resource rscr;
29};
30
31static 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#ifdef CONFIG_PM 46#ifdef CONFIG_PM
26static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) 47static 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 struct tc6387xb_platform_data *pdata = dev->dev.platform_data; 50 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
30 51
31 if (pdata && pdata->suspend) 52 if (pdata && pdata->suspend)
32 pdata->suspend(dev); 53 pdata->suspend(dev);
33 clk_disable(clk32k); 54 clk_disable(tc6387xb->clk32k);
34 55
35 return 0; 56 return 0;
36} 57}
37 58
38static int tc6387xb_resume(struct platform_device *dev) 59static 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 struct tc6387xb_platform_data *pdata = dev->dev.platform_data; 62 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
42 63
43 clk_enable(clk32k); 64 clk_enable(tc6387xb->clk32k);
44 if (pdata && pdata->resume) 65 if (pdata && pdata->resume)
45 pdata->resume(dev); 66 pdata->resume(dev);
46 67
68 tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0,
69 tc6387xb_mmc_resources[0].start & 0xfffe);
70
47 return 0; 71 return 0;
48} 72}
49#else 73#else
@@ -53,12 +77,32 @@ static int tc6387xb_resume(struct platform_device *dev)
53 77
54/*--------------------------------------------------------------------------*/ 78/*--------------------------------------------------------------------------*/
55 79
80static 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
88static 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
56static int tc6387xb_mmc_enable(struct platform_device *mmc) 97static int tc6387xb_mmc_enable(struct platform_device *mmc)
57{ 98{
58 struct platform_device *dev = to_platform_device(mmc->dev.parent); 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);
103
104 tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
105 tc6387xb_mmc_resources[0].start & 0xfffe);
62 106
63 return 0; 107 return 0;
64} 108}
@@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
66static int tc6387xb_mmc_disable(struct platform_device *mmc) 110static int tc6387xb_mmc_disable(struct platform_device *mmc)
67{ 111{
68 struct platform_device *dev = to_platform_device(mmc->dev.parent); 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 return 0; 117 return 0;
74} 118}
75 119
76/*--------------------------------------------------------------------------*/
77
78static struct tmio_mmc_data tc6387xb_mmc_data = { 120static struct tmio_mmc_data tc6387xb_mmc_data = {
79 .hclk = 24000000, 121 .hclk = 24000000,
122 .set_pwr = tc6387xb_mmc_pwr,
123 .set_clk_div = tc6387xb_mmc_clk_div,
80}; 124};
81 125
82static struct resource tc6387xb_mmc_resources[] = { 126/*--------------------------------------------------------------------------*/
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};
99 127
100static struct mfd_cell tc6387xb_cells[] = { 128static struct mfd_cell tc6387xb_cells[] = {
101 [TC6387XB_CELL_MMC] = { 129 [TC6387XB_CELL_MMC] = {
@@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = {
111static int tc6387xb_probe(struct platform_device *dev) 139static int tc6387xb_probe(struct platform_device *dev)
112{ 140{
113 struct tc6387xb_platform_data *pdata = dev->dev.platform_data; 141 struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
114 struct resource *iomem; 142 struct resource *iomem, *rscr;
115 struct clk *clk32k; 143 struct clk *clk32k;
144 struct tc6387xb *tc6387xb;
116 int irq, ret; 145 int irq, ret;
117 146
118 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 147 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
@@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev)
120 return -EINVAL; 149 return -EINVAL;
121 } 150 }
122 151
152 tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
153 if (!tc6387xb)
154 return -ENOMEM;
155
123 ret = platform_get_irq(dev, 0); 156 ret = platform_get_irq(dev, 0);
124 if (ret >= 0) 157 if (ret >= 0)
125 irq = ret; 158 irq = ret;
126 else 159 else
127 goto err_resource; 160 goto err_no_irq;
128 161
129 clk32k = clk_get(&dev->dev, "CLK_CK32K"); 162 clk32k = clk_get(&dev->dev, "CLK_CK32K");
130 if (IS_ERR(clk32k)) { 163 if (IS_ERR(clk32k)) {
131 ret = PTR_ERR(clk32k); 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 goto err_resource; 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); 183
184 tc6387xb->clk32k = clk32k;
185 platform_set_drvdata(dev, tc6387xb);
135 186
136 if (pdata && pdata->enable) 187 if (pdata && pdata->enable)
137 pdata->enable(dev); 188 pdata->enable(dev);
@@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev)
149 if (!ret) 200 if (!ret)
150 return 0; 201 return 0;
151 202
152 clk_put(clk32k); 203err_ioremap:
204 release_resource(&tc6387xb->rscr);
153err_resource: 205err_resource:
206 clk_put(clk32k);
207err_no_clk:
208err_no_irq:
209 kfree(tc6387xb);
154 return ret; 210 return ret;
155} 211}
156 212
@@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
195MODULE_LICENSE("GPL v2"); 251MODULE_LICENSE("GPL v2");
196MODULE_AUTHOR("Ian Molton"); 252MODULE_AUTHOR("Ian Molton");
197MODULE_ALIAS("platform:tc6387xb"); 253MODULE_ALIAS("platform:tc6387xb");
254
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 1429a7341a9a..4bc5a08a2b09 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
136 return 0; 136 return 0;
137} 137}
138 138
139static struct tmio_mmc_data tc6393xb_mmc_data = {
140 .hclk = 24000000,
141};
142
143static struct resource __devinitdata tc6393xb_nand_resources[] = { 139static struct resource __devinitdata tc6393xb_nand_resources[] = {
144 { 140 {
145 .start = 0x1000, 141 .start = 0x1000,
@@ -165,11 +161,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
165 .flags = IORESOURCE_MEM, 161 .flags = IORESOURCE_MEM,
166 }, 162 },
167 { 163 {
168 .start = 0x200,
169 .end = 0x2ff,
170 .flags = IORESOURCE_MEM,
171 },
172 {
173 .start = IRQ_TC6393_MMC, 164 .start = IRQ_TC6393_MMC,
174 .end = IRQ_TC6393_MMC, 165 .end = IRQ_TC6393_MMC,
175 .flags = IORESOURCE_IRQ, 166 .flags = IORESOURCE_IRQ,
@@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb,
346} 337}
347EXPORT_SYMBOL(tc6393xb_lcd_mode); 338EXPORT_SYMBOL(tc6393xb_lcd_mode);
348 339
340static 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
351static 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
362static 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
370static 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
378static 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
349static struct mfd_cell __devinitdata tc6393xb_cells[] = { 384static struct mfd_cell __devinitdata tc6393xb_cells[] = {
350 [TC6393XB_CELL_NAND] = { 385 [TC6393XB_CELL_NAND] = {
351 .name = "tmio-nand", 386 .name = "tmio-nand",
@@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
355 }, 390 },
356 [TC6393XB_CELL_MMC] = { 391 [TC6393XB_CELL_MMC] = {
357 .name = "tmio-mmc", 392 .name = "tmio-mmc",
393 .enable = tc6393xb_mmc_enable,
394 .resume = tc6393xb_mmc_resume,
358 .driver_data = &tc6393xb_mmc_data, 395 .driver_data = &tc6393xb_mmc_data,
359 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), 396 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
360 .resources = tc6393xb_mmc_resources, 397 .resources = tc6393xb_mmc_resources,
@@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2");
836MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer"); 873MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
837MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller"); 874MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
838MODULE_ALIAS("platform:tc6393xb"); 875MODULE_ALIAS("platform:tc6393xb");
876
diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c
new file mode 100644
index 000000000000..eddc19ae464b
--- /dev/null
+++ b/drivers/mfd/tmio_core.c
@@ -0,0 +1,52 @@
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
11int 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}
28EXPORT_SYMBOL(tmio_core_mmc_enable);
29
30int 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}
39EXPORT_SYMBOL(tmio_core_mmc_resume);
40
41void 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}
45EXPORT_SYMBOL(tmio_core_mmc_pwr);
46
47void 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}
51EXPORT_SYMBOL(tmio_core_mmc_clk_div);
52