aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1/masters/ds1wm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1/masters/ds1wm.c')
-rw-r--r--drivers/w1/masters/ds1wm.c58
1 files changed, 27 insertions, 31 deletions
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);