aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/arm/mach-pxa/magician.c1
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/da903x.c2
-rw-r--r--drivers/mfd/htc-pasic3.c169
-rw-r--r--drivers/mfd/pcf50633-core.c1
-rw-r--r--drivers/mfd/t7l66xb.c4
-rw-r--r--drivers/mfd/tc6393xb.c2
-rw-r--r--drivers/mfd/twl4030-irq.c2
-rw-r--r--drivers/mfd/wm8350-core.c39
-rw-r--r--drivers/w1/masters/ds1wm.c58
-rw-r--r--include/linux/ds1wm.h12
-rw-r--r--include/linux/mfd/ds1wm.h6
-rw-r--r--include/linux/mfd/htc-pasic3.h1
-rw-r--r--include/linux/mfd/wm8350/core.h2
15 files changed, 139 insertions, 164 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 60c970685833..9673cd28a69b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3051,8 +3051,9 @@ S: Maintained
3051 3051
3052MULTIFUNCTION DEVICES (MFD) 3052MULTIFUNCTION DEVICES (MFD)
3053P: Samuel Ortiz 3053P: Samuel Ortiz
3054M: sameo@openedhand.com 3054M: sameo@linux.intel.com
3055L: linux-kernel@vger.kernel.org 3055L: linux-kernel@vger.kernel.org
3056T: git kernel.org:/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
3056S: Supported 3057S: Supported
3057 3058
3058MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM 3059MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index d46b36746be2..deeea1c2782b 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -507,7 +507,6 @@ static struct resource pasic3_resources[] = {
507}; 507};
508 508
509static struct pasic3_platform_data pasic3_platform_data = { 509static struct pasic3_platform_data pasic3_platform_data = {
510 .bus_shift = 2,
511 .led_pdata = &pasic3_leds_info, 510 .led_pdata = &pasic3_leds_info,
512 .clock_rate = 4000000, 511 .clock_rate = 4000000,
513}; 512};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 75f35dbb11dc..ee3927ab11e0 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -52,6 +52,7 @@ config HTC_EGPIO
52 52
53config HTC_PASIC3 53config HTC_PASIC3
54 tristate "HTC PASIC3 LED/DS1WM chip support" 54 tristate "HTC PASIC3 LED/DS1WM chip support"
55 select MFD_CORE
55 help 56 help
56 This core driver provides register access for the LED/DS1WM 57 This core driver provides register access for the LED/DS1WM
57 chips labeled "AIC2" and "AIC3", found on HTC Blueangel and 58 chips labeled "AIC2" and "AIC3", found on HTC Blueangel and
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 99f8dcfe3d98..7283d88656af 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -413,7 +413,7 @@ static void da903x_irq_work(struct work_struct *work)
413 enable_irq(chip->client->irq); 413 enable_irq(chip->client->irq);
414} 414}
415 415
416static int da903x_irq_handler(int irq, void *data) 416static irqreturn_t da903x_irq_handler(int irq, void *data)
417{ 417{
418 struct da903x_chip *chip = data; 418 struct da903x_chip *chip = data;
419 419
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 91b294dcc133..386da1566fcc 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -12,18 +12,17 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14 14
15#include <linux/ds1wm.h>
16#include <linux/gpio.h> 15#include <linux/gpio.h>
17#include <linux/io.h> 16#include <linux/io.h>
18#include <linux/irq.h> 17#include <linux/irq.h>
19#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/mfd/core.h>
20#include <linux/mfd/ds1wm.h>
20#include <linux/mfd/htc-pasic3.h> 21#include <linux/mfd/htc-pasic3.h>
21 22
22struct pasic3_data { 23struct pasic3_data {
23 void __iomem *mapping; 24 void __iomem *mapping;
24 unsigned int bus_shift; 25 unsigned int bus_shift;
25 struct platform_device *ds1wm_pdev;
26 struct platform_device *led_pdev;
27}; 26};
28 27
29#define REG_ADDR 5 28#define REG_ADDR 5
@@ -65,46 +64,15 @@ EXPORT_SYMBOL(pasic3_read_register); /* for leds-pasic3 */
65 * LEDs 64 * LEDs
66 */ 65 */
67 66
68static int led_device_add(struct device *pasic3_dev, 67static struct mfd_cell led_cell __initdata = {
69 const struct pasic3_leds_machinfo *pdata) 68 .name = "leds-pasic3",
70{ 69};
71 struct pasic3_data *asic = pasic3_dev->driver_data;
72 struct platform_device *pdev;
73 int ret;
74
75 pdev = platform_device_alloc("pasic3-led", -1);
76 if (!pdev) {
77 dev_dbg(pasic3_dev, "failed to allocate LED platform device\n");
78 return -ENOMEM;
79 }
80
81 ret = platform_device_add_data(pdev, pdata,
82 sizeof(struct pasic3_leds_machinfo));
83 if (ret < 0) {
84 dev_dbg(pasic3_dev, "failed to add LED platform data\n");
85 goto exit_pdev_put;
86 }
87
88 pdev->dev.parent = pasic3_dev;
89 ret = platform_device_add(pdev);
90 if (ret < 0) {
91 dev_dbg(pasic3_dev, "failed to add LED platform device\n");
92 goto exit_pdev_put;
93 }
94
95 asic->led_pdev = pdev;
96 return 0;
97
98exit_pdev_put:
99 platform_device_put(pdev);
100 return ret;
101}
102 70
103/* 71/*
104 * DS1WM 72 * DS1WM
105 */ 73 */
106 74
107static void ds1wm_enable(struct platform_device *pdev) 75static int ds1wm_enable(struct platform_device *pdev)
108{ 76{
109 struct device *dev = pdev->dev.parent; 77 struct device *dev = pdev->dev.parent;
110 int c; 78 int c;
@@ -113,9 +81,10 @@ static void ds1wm_enable(struct platform_device *pdev)
113 pasic3_write_register(dev, 0x28, c & 0x7f); 81 pasic3_write_register(dev, 0x28, c & 0x7f);
114 82
115 dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f); 83 dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f);
84 return 0;
116} 85}
117 86
118static void ds1wm_disable(struct platform_device *pdev) 87static int ds1wm_disable(struct platform_device *pdev)
119{ 88{
120 struct device *dev = pdev->dev.parent; 89 struct device *dev = pdev->dev.parent;
121 int c; 90 int c;
@@ -124,56 +93,33 @@ static void ds1wm_disable(struct platform_device *pdev)
124 pasic3_write_register(dev, 0x28, c | 0x80); 93 pasic3_write_register(dev, 0x28, c | 0x80);
125 94
126 dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80); 95 dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80);
96 return 0;
127} 97}
128 98
129static struct ds1wm_platform_data ds1wm_pdata = { 99static struct ds1wm_driver_data ds1wm_pdata = {
130 .bus_shift = 2, 100 .active_high = 0,
131 .enable = ds1wm_enable,
132 .disable = ds1wm_disable,
133}; 101};
134 102
135static int ds1wm_device_add(struct platform_device *pasic3_pdev, int bus_shift) 103static struct resource ds1wm_resources[] __initdata = {
136{ 104 [0] = {
137 struct device *pasic3_dev = &pasic3_pdev->dev; 105 .start = 0,
138 struct pasic3_data *asic = pasic3_dev->driver_data; 106 .flags = IORESOURCE_MEM,
139 struct platform_device *pdev; 107 },
140 int ret; 108 [1] = {
141 109 .start = 0,
142 pdev = platform_device_alloc("ds1wm", -1); 110 .end = 0,
143 if (!pdev) { 111 .flags = IORESOURCE_IRQ,
144 dev_dbg(pasic3_dev, "failed to allocate DS1WM platform device\n"); 112 },
145 return -ENOMEM; 113};
146 }
147
148 ret = platform_device_add_resources(pdev, pasic3_pdev->resource,
149 pasic3_pdev->num_resources);
150 if (ret < 0) {
151 dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
152 goto exit_pdev_put;
153 }
154
155 ds1wm_pdata.bus_shift = asic->bus_shift;
156 ret = platform_device_add_data(pdev, &ds1wm_pdata,
157 sizeof(struct ds1wm_platform_data));
158 if (ret < 0) {
159 dev_dbg(pasic3_dev, "failed to add DS1WM platform data\n");
160 goto exit_pdev_put;
161 }
162
163 pdev->dev.parent = pasic3_dev;
164 ret = platform_device_add(pdev);
165 if (ret < 0) {
166 dev_dbg(pasic3_dev, "failed to add DS1WM platform device\n");
167 goto exit_pdev_put;
168 }
169
170 asic->ds1wm_pdev = pdev;
171 return 0;
172 114
173exit_pdev_put: 115static struct mfd_cell ds1wm_cell __initdata = {
174 platform_device_put(pdev); 116 .name = "ds1wm",
175 return ret; 117 .enable = ds1wm_enable,
176} 118 .disable = ds1wm_disable,
119 .driver_data = &ds1wm_pdata,
120 .num_resources = 2,
121 .resources = ds1wm_resources,
122};
177 123
178static int __init pasic3_probe(struct platform_device *pdev) 124static int __init pasic3_probe(struct platform_device *pdev)
179{ 125{
@@ -182,12 +128,27 @@ static int __init pasic3_probe(struct platform_device *pdev)
182 struct pasic3_data *asic; 128 struct pasic3_data *asic;
183 struct resource *r; 129 struct resource *r;
184 int ret; 130 int ret;
131 int irq = 0;
132
133 r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
134 if (r) {
135 ds1wm_resources[1].flags = IORESOURCE_IRQ | (r->flags &
136 (IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE));
137 irq = r->start;
138 }
139
140 r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
141 if (r) {
142 ds1wm_resources[1].flags = IORESOURCE_IRQ | (r->flags &
143 (IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE));
144 irq = r->start;
145 }
185 146
186 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 147 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
187 if (!r) 148 if (!r)
188 return -ENXIO; 149 return -ENXIO;
189 150
190 if (!request_mem_region(r->start, r->end - r->start + 1, "pasic3")) 151 if (!request_mem_region(r->start, resource_size(r), "pasic3"))
191 return -EBUSY; 152 return -EBUSY;
192 153
193 asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL); 154 asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
@@ -196,24 +157,33 @@ static int __init pasic3_probe(struct platform_device *pdev)
196 157
197 platform_set_drvdata(pdev, asic); 158 platform_set_drvdata(pdev, asic);
198 159
199 if (pdata && pdata->bus_shift) 160 asic->mapping = ioremap(r->start, resource_size(r));
200 asic->bus_shift = pdata->bus_shift;
201 else
202 asic->bus_shift = 2;
203
204 asic->mapping = ioremap(r->start, r->end - r->start + 1);
205 if (!asic->mapping) { 161 if (!asic->mapping) {
206 dev_err(dev, "couldn't ioremap PASIC3\n"); 162 dev_err(dev, "couldn't ioremap PASIC3\n");
207 kfree(asic); 163 kfree(asic);
208 return -ENOMEM; 164 return -ENOMEM;
209 } 165 }
210 166
211 ret = ds1wm_device_add(pdev, asic->bus_shift); 167 /* calculate bus shift from mem resource */
212 if (ret < 0) 168 asic->bus_shift = (resource_size(r) - 5) >> 3;
213 dev_warn(dev, "failed to register DS1WM\n"); 169
170 if (pdata && pdata->clock_rate) {
171 ds1wm_pdata.clock_rate = pdata->clock_rate;
172 /* the first 5 PASIC3 registers control the DS1WM */
173 ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
174 ds1wm_cell.platform_data = &ds1wm_cell;
175 ds1wm_cell.data_size = sizeof(ds1wm_cell);
176 ret = mfd_add_devices(&pdev->dev, pdev->id,
177 &ds1wm_cell, 1, r, irq);
178 if (ret < 0)
179 dev_warn(dev, "failed to register DS1WM\n");
180 }
214 181
215 if (pdata->led_pdata) { 182 if (pdata && pdata->led_pdata) {
216 ret = led_device_add(dev, pdata->led_pdata); 183 led_cell.driver_data = pdata->led_pdata;
184 led_cell.platform_data = &led_cell;
185 led_cell.data_size = sizeof(ds1wm_cell);
186 ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
217 if (ret < 0) 187 if (ret < 0)
218 dev_warn(dev, "failed to register LED device\n"); 188 dev_warn(dev, "failed to register LED device\n");
219 } 189 }
@@ -226,14 +196,11 @@ static int pasic3_remove(struct platform_device *pdev)
226 struct pasic3_data *asic = platform_get_drvdata(pdev); 196 struct pasic3_data *asic = platform_get_drvdata(pdev);
227 struct resource *r; 197 struct resource *r;
228 198
229 if (asic->led_pdev) 199 mfd_remove_devices(&pdev->dev);
230 platform_device_unregister(asic->led_pdev);
231 if (asic->ds1wm_pdev)
232 platform_device_unregister(asic->ds1wm_pdev);
233 200
234 iounmap(asic->mapping); 201 iounmap(asic->mapping);
235 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 202 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
236 release_mem_region(r->start, r->end - r->start + 1); 203 release_mem_region(r->start, resource_size(r));
237 kfree(asic); 204 kfree(asic);
238 return 0; 205 return 0;
239} 206}
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 2e36057659e1..7793932a513b 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -15,7 +15,6 @@
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/sysfs.h> 17#include <linux/sysfs.h>
18#include <linux/device.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <linux/types.h> 19#include <linux/types.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 9f7024c0f8ec..e9f4323dd2cb 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -108,7 +108,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
108 108
109/*--------------------------------------------------------------------------*/ 109/*--------------------------------------------------------------------------*/
110 110
111const static struct resource t7l66xb_mmc_resources[] = { 111static const struct resource t7l66xb_mmc_resources[] = {
112 { 112 {
113 .start = 0x800, 113 .start = 0x800,
114 .end = 0x9ff, 114 .end = 0x9ff,
@@ -126,7 +126,7 @@ const static struct resource t7l66xb_mmc_resources[] = {
126 }, 126 },
127}; 127};
128 128
129const static struct resource t7l66xb_nand_resources[] = { 129static const struct resource t7l66xb_nand_resources[] = {
130 { 130 {
131 .start = 0xc00, 131 .start = 0xc00,
132 .end = 0xc07, 132 .end = 0xc07,
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index f856e9463a9f..77a12fc8045e 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -172,7 +172,7 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
172 }, 172 },
173}; 173};
174 174
175const static struct resource tc6393xb_ohci_resources[] = { 175static const struct resource tc6393xb_ohci_resources[] = {
176 { 176 {
177 .start = 0x3000, 177 .start = 0x3000,
178 .end = 0x31ff, 178 .end = 0x31ff,
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index b10876036983..aca2670afd78 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -182,7 +182,7 @@ static int twl4030_irq_thread(void *data)
182 long irq = (long)data; 182 long irq = (long)data;
183 struct irq_desc *desc = irq_to_desc(irq); 183 struct irq_desc *desc = irq_to_desc(irq);
184 static unsigned i2c_errors; 184 static unsigned i2c_errors;
185 const static unsigned max_i2c_errors = 100; 185 static const unsigned max_i2c_errors = 100;
186 186
187 if (!desc) { 187 if (!desc) {
188 pr_err("twl4030: Invalid IRQ: %ld\n", irq); 188 pr_err("twl4030: Invalid IRQ: %ld\n", irq);
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index b457a05b28d9..c2be3088e2e1 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -1111,7 +1111,7 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
1111 do { 1111 do {
1112 schedule_timeout_interruptible(1); 1112 schedule_timeout_interruptible(1);
1113 reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); 1113 reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
1114 } while (--tries && (reg & WM8350_AUXADC_POLL)); 1114 } while ((reg & WM8350_AUXADC_POLL) && --tries);
1115 1115
1116 if (!tries) 1116 if (!tries)
1117 dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); 1117 dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
@@ -1238,7 +1238,7 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
1238 } 1238 }
1239 1239
1240 wm8350->reg_cache = 1240 wm8350->reg_cache =
1241 kzalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); 1241 kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
1242 if (wm8350->reg_cache == NULL) 1242 if (wm8350->reg_cache == NULL)
1243 return -ENOMEM; 1243 return -ENOMEM;
1244 1244
@@ -1246,17 +1246,20 @@ static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
1246 * a PMIC so the device many not be in a virgin state and we 1246 * a PMIC so the device many not be in a virgin state and we
1247 * can't rely on the silicon values. 1247 * can't rely on the silicon values.
1248 */ 1248 */
1249 ret = wm8350->read_dev(wm8350, 0,
1250 sizeof(u16) * (WM8350_MAX_REGISTER + 1),
1251 wm8350->reg_cache);
1252 if (ret < 0) {
1253 dev_err(wm8350->dev,
1254 "failed to read initial cache values\n");
1255 goto out;
1256 }
1257
1258 /* Mask out uncacheable/unreadable bits and the audio. */
1249 for (i = 0; i < WM8350_MAX_REGISTER; i++) { 1259 for (i = 0; i < WM8350_MAX_REGISTER; i++) {
1250 /* audio register range */
1251 if (wm8350_reg_io_map[i].readable && 1260 if (wm8350_reg_io_map[i].readable &&
1252 (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { 1261 (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
1253 ret = wm8350->read_dev(wm8350, i, 2, (char *)&value); 1262 value = be16_to_cpu(wm8350->reg_cache[i]);
1254 if (ret < 0) {
1255 dev_err(wm8350->dev,
1256 "failed to read initial cache value\n");
1257 goto out;
1258 }
1259 value = be16_to_cpu(value);
1260 value &= wm8350_reg_io_map[i].readable; 1263 value &= wm8350_reg_io_map[i].readable;
1261 value &= ~wm8350_reg_io_map[i].vol; 1264 value &= ~wm8350_reg_io_map[i].vol;
1262 wm8350->reg_cache[i] = value; 1265 wm8350->reg_cache[i] = value;
@@ -1435,7 +1438,21 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
1435 mutex_init(&wm8350->irq_mutex); 1438 mutex_init(&wm8350->irq_mutex);
1436 INIT_WORK(&wm8350->irq_work, wm8350_irq_worker); 1439 INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
1437 if (irq) { 1440 if (irq) {
1438 ret = request_irq(irq, wm8350_irq, 0, 1441 int flags = 0;
1442
1443 if (pdata && pdata->irq_high) {
1444 flags |= IRQF_TRIGGER_HIGH;
1445
1446 wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
1447 WM8350_IRQ_POL);
1448 } else {
1449 flags |= IRQF_TRIGGER_LOW;
1450
1451 wm8350_clear_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
1452 WM8350_IRQ_POL);
1453 }
1454
1455 ret = request_irq(irq, wm8350_irq, flags,
1439 "wm8350", wm8350); 1456 "wm8350", wm8350);
1440 if (ret != 0) { 1457 if (ret != 0) {
1441 dev_err(wm8350->dev, "Failed to request IRQ: %d\n", 1458 dev_err(wm8350->dev, "Failed to request IRQ: %d\n",
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 29e144f81cbe..37f08c850608 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -16,10 +16,10 @@
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/pm.h> 17#include <linux/pm.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/clk.h>
20#include <linux/err.h> 19#include <linux/err.h>
21#include <linux/delay.h> 20#include <linux/delay.h>
22#include <linux/ds1wm.h> 21#include <linux/mfd/core.h>
22#include <linux/mfd/ds1wm.h>
23 23
24#include <asm/io.h> 24#include <asm/io.h>
25 25
@@ -89,10 +89,9 @@ struct ds1wm_data {
89 void __iomem *map; 89 void __iomem *map;
90 int bus_shift; /* # of shifts to calc register offsets */ 90 int bus_shift; /* # of shifts to calc register offsets */
91 struct platform_device *pdev; 91 struct platform_device *pdev;
92 struct ds1wm_platform_data *pdata; 92 struct mfd_cell *cell;
93 int irq; 93 int irq;
94 int active_high; 94 int active_high;
95 struct clk *clk;
96 int slave_present; 95 int slave_present;
97 void *reset_complete; 96 void *reset_complete;
98 void *read_complete; 97 void *read_complete;
@@ -215,17 +214,17 @@ static int ds1wm_find_divisor(int gclk)
215 214
216static void ds1wm_up(struct ds1wm_data *ds1wm_data) 215static void ds1wm_up(struct ds1wm_data *ds1wm_data)
217{ 216{
218 int gclk, divisor; 217 int divisor;
218 struct ds1wm_driver_data *plat = ds1wm_data->cell->driver_data;
219 219
220 if (ds1wm_data->pdata->enable) 220 if (ds1wm_data->cell->enable)
221 ds1wm_data->pdata->enable(ds1wm_data->pdev); 221 ds1wm_data->cell->enable(ds1wm_data->pdev);
222 222
223 gclk = clk_get_rate(ds1wm_data->clk); 223 divisor = ds1wm_find_divisor(plat->clock_rate);
224 clk_enable(ds1wm_data->clk);
225 divisor = ds1wm_find_divisor(gclk);
226 if (divisor == 0) { 224 if (divisor == 0) {
227 dev_err(&ds1wm_data->pdev->dev, 225 dev_err(&ds1wm_data->pdev->dev,
228 "no suitable divisor for %dHz clock\n", gclk); 226 "no suitable divisor for %dHz clock\n",
227 plat->clock_rate);
229 return; 228 return;
230 } 229 }
231 ds1wm_write_register(ds1wm_data, DS1WM_CLKDIV, divisor); 230 ds1wm_write_register(ds1wm_data, DS1WM_CLKDIV, divisor);
@@ -244,10 +243,8 @@ static void ds1wm_down(struct ds1wm_data *ds1wm_data)
244 ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, 243 ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
245 ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0); 244 ds1wm_data->active_high ? DS1WM_INTEN_IAS : 0);
246 245
247 if (ds1wm_data->pdata->disable) 246 if (ds1wm_data->cell->disable)
248 ds1wm_data->pdata->disable(ds1wm_data->pdev); 247 ds1wm_data->cell->disable(ds1wm_data->pdev);
249
250 clk_disable(ds1wm_data->clk);
251} 248}
252 249
253/* --------------------------------------------------------------------- */ 250/* --------------------------------------------------------------------- */
@@ -330,13 +327,18 @@ static struct w1_bus_master ds1wm_master = {
330static int ds1wm_probe(struct platform_device *pdev) 327static int ds1wm_probe(struct platform_device *pdev)
331{ 328{
332 struct ds1wm_data *ds1wm_data; 329 struct ds1wm_data *ds1wm_data;
333 struct ds1wm_platform_data *plat; 330 struct ds1wm_driver_data *plat;
334 struct resource *res; 331 struct resource *res;
332 struct mfd_cell *cell;
335 int ret; 333 int ret;
336 334
337 if (!pdev) 335 if (!pdev)
338 return -ENODEV; 336 return -ENODEV;
339 337
338 cell = pdev->dev.platform_data;
339 if (!cell)
340 return -ENODEV;
341
340 ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL); 342 ds1wm_data = kzalloc(sizeof(*ds1wm_data), GFP_KERNEL);
341 if (!ds1wm_data) 343 if (!ds1wm_data)
342 return -ENOMEM; 344 return -ENOMEM;
@@ -348,15 +350,18 @@ static int ds1wm_probe(struct platform_device *pdev)
348 ret = -ENXIO; 350 ret = -ENXIO;
349 goto err0; 351 goto err0;
350 } 352 }
351 ds1wm_data->map = ioremap(res->start, res->end - res->start + 1); 353 ds1wm_data->map = ioremap(res->start, resource_size(res));
352 if (!ds1wm_data->map) { 354 if (!ds1wm_data->map) {
353 ret = -ENOMEM; 355 ret = -ENOMEM;
354 goto err0; 356 goto err0;
355 } 357 }
356 plat = pdev->dev.platform_data; 358 plat = cell->driver_data;
357 ds1wm_data->bus_shift = plat->bus_shift; 359
360 /* calculate bus shift from mem resource */
361 ds1wm_data->bus_shift = resource_size(res) >> 3;
362
358 ds1wm_data->pdev = pdev; 363 ds1wm_data->pdev = pdev;
359 ds1wm_data->pdata = plat; 364 ds1wm_data->cell = cell;
360 365
361 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 366 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
362 if (!res) { 367 if (!res) {
@@ -376,26 +381,18 @@ static int ds1wm_probe(struct platform_device *pdev)
376 if (ret) 381 if (ret)
377 goto err1; 382 goto err1;
378 383
379 ds1wm_data->clk = clk_get(&pdev->dev, "ds1wm");
380 if (IS_ERR(ds1wm_data->clk)) {
381 ret = PTR_ERR(ds1wm_data->clk);
382 goto err2;
383 }
384
385 ds1wm_up(ds1wm_data); 384 ds1wm_up(ds1wm_data);
386 385
387 ds1wm_master.data = (void *)ds1wm_data; 386 ds1wm_master.data = (void *)ds1wm_data;
388 387
389 ret = w1_add_master_device(&ds1wm_master); 388 ret = w1_add_master_device(&ds1wm_master);
390 if (ret) 389 if (ret)
391 goto err3; 390 goto err2;
392 391
393 return 0; 392 return 0;
394 393
395err3:
396 ds1wm_down(ds1wm_data);
397 clk_put(ds1wm_data->clk);
398err2: 394err2:
395 ds1wm_down(ds1wm_data);
399 free_irq(ds1wm_data->irq, ds1wm_data); 396 free_irq(ds1wm_data->irq, ds1wm_data);
400err1: 397err1:
401 iounmap(ds1wm_data->map); 398 iounmap(ds1wm_data->map);
@@ -434,7 +431,6 @@ static int ds1wm_remove(struct platform_device *pdev)
434 431
435 w1_remove_master_device(&ds1wm_master); 432 w1_remove_master_device(&ds1wm_master);
436 ds1wm_down(ds1wm_data); 433 ds1wm_down(ds1wm_data);
437 clk_put(ds1wm_data->clk);
438 free_irq(ds1wm_data->irq, ds1wm_data); 434 free_irq(ds1wm_data->irq, ds1wm_data);
439 iounmap(ds1wm_data->map); 435 iounmap(ds1wm_data->map);
440 kfree(ds1wm_data); 436 kfree(ds1wm_data);
diff --git a/include/linux/ds1wm.h b/include/linux/ds1wm.h
deleted file mode 100644
index d3c65e48a2e7..000000000000
--- a/include/linux/ds1wm.h
+++ /dev/null
@@ -1,12 +0,0 @@
1/* platform data for the DS1WM driver */
2
3struct ds1wm_platform_data {
4 int bus_shift; /* number of shifts needed to calculate the
5 * offset between DS1WM registers;
6 * e.g. on h5xxx and h2200 this is 2
7 * (registers aligned to 4-byte boundaries),
8 * while on hx4700 this is 1 */
9 int active_high;
10 void (*enable)(struct platform_device *pdev);
11 void (*disable)(struct platform_device *pdev);
12};
diff --git a/include/linux/mfd/ds1wm.h b/include/linux/mfd/ds1wm.h
new file mode 100644
index 000000000000..be469a357cbb
--- /dev/null
+++ b/include/linux/mfd/ds1wm.h
@@ -0,0 +1,6 @@
1/* MFD cell driver data for the DS1WM driver */
2
3struct ds1wm_driver_data {
4 int active_high;
5 int clock_rate;
6};
diff --git a/include/linux/mfd/htc-pasic3.h b/include/linux/mfd/htc-pasic3.h
index b4294f12c4f8..3d3ed67bd969 100644
--- a/include/linux/mfd/htc-pasic3.h
+++ b/include/linux/mfd/htc-pasic3.h
@@ -48,7 +48,6 @@ struct pasic3_leds_machinfo {
48 48
49struct pasic3_platform_data { 49struct pasic3_platform_data {
50 struct pasic3_leds_machinfo *led_pdata; 50 struct pasic3_leds_machinfo *led_pdata;
51 unsigned int bus_shift;
52 unsigned int clock_rate; 51 unsigned int clock_rate;
53}; 52};
54 53
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
index 980669d50dca..42cca672f340 100644
--- a/include/linux/mfd/wm8350/core.h
+++ b/include/linux/mfd/wm8350/core.h
@@ -640,9 +640,11 @@ struct wm8350 {
640 * 640 *
641 * @init: Function called during driver initialisation. Should be 641 * @init: Function called during driver initialisation. Should be
642 * used by the platform to configure GPIO functions and similar. 642 * used by the platform to configure GPIO functions and similar.
643 * @irq_high: Set if WM8350 IRQ is active high.
643 */ 644 */
644struct wm8350_platform_data { 645struct wm8350_platform_data {
645 int (*init)(struct wm8350 *wm8350); 646 int (*init)(struct wm8350 *wm8350);
647 int irq_high;
646}; 648};
647 649
648 650