aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-04-14 03:40:45 -0400
committerLee Jones <lee.jones@linaro.org>2014-06-03 03:11:16 -0400
commite349c910e2398cbff59d7c58851503191a8e9157 (patch)
tree0d54685f5ea382b6b99e6a7d9e2d536e2b6d06db
parenta865a589144da6dbf26750b7193a9748da159305 (diff)
mfd/rtc: s5m: Do not allocate RTC I2C dummy and regmap for unsupported chipsets
The rtc-s5m driver does not support all of S2M and S5M chipsets supported by main MFD sec-core driver. For such chipsets unsupported by rtc-s5m, the MFD sec-core driver initialized regmap with default config. This config in such cases wouldn't work at all. The main MFD sec-core driver shouldn't initialize regmap for child drivers which is not used by them and even not valid. Move the allocation of RTC I2C dummy device and initialization of RTC regmap from main MFD sec-core driver to the rtc-s5m driver. The rtc-s5m driver will use proper regmap config for supported devices. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/sec-core.c53
-rw-r--r--drivers/rtc/rtc-s5m.c75
-rw-r--r--include/linux/mfd/samsung/core.h3
3 files changed, 71 insertions, 60 deletions
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 1cf27521fff4..d4682c6cbff5 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -25,7 +25,6 @@
25#include <linux/mfd/core.h> 25#include <linux/mfd/core.h>
26#include <linux/mfd/samsung/core.h> 26#include <linux/mfd/samsung/core.h>
27#include <linux/mfd/samsung/irq.h> 27#include <linux/mfd/samsung/irq.h>
28#include <linux/mfd/samsung/rtc.h>
29#include <linux/mfd/samsung/s2mpa01.h> 28#include <linux/mfd/samsung/s2mpa01.h>
30#include <linux/mfd/samsung/s2mps11.h> 29#include <linux/mfd/samsung/s2mps11.h>
31#include <linux/mfd/samsung/s2mps14.h> 30#include <linux/mfd/samsung/s2mps14.h>
@@ -196,20 +195,6 @@ static const struct regmap_config s5m8767_regmap_config = {
196 .cache_type = REGCACHE_FLAT, 195 .cache_type = REGCACHE_FLAT,
197}; 196};
198 197
199static const struct regmap_config s5m_rtc_regmap_config = {
200 .reg_bits = 8,
201 .val_bits = 8,
202
203 .max_register = SEC_RTC_REG_MAX,
204};
205
206static const struct regmap_config s2mps14_rtc_regmap_config = {
207 .reg_bits = 8,
208 .val_bits = 8,
209
210 .max_register = S2MPS_RTC_REG_MAX,
211};
212
213#ifdef CONFIG_OF 198#ifdef CONFIG_OF
214/* 199/*
215 * Only the common platform data elements for s5m8767 are parsed here from the 200 * Only the common platform data elements for s5m8767 are parsed here from the
@@ -264,7 +249,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
264 const struct i2c_device_id *id) 249 const struct i2c_device_id *id)
265{ 250{
266 struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); 251 struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
267 const struct regmap_config *regmap, *regmap_rtc; 252 const struct regmap_config *regmap;
268 struct sec_pmic_dev *sec_pmic; 253 struct sec_pmic_dev *sec_pmic;
269 int ret; 254 int ret;
270 255
@@ -298,39 +283,21 @@ static int sec_pmic_probe(struct i2c_client *i2c,
298 switch (sec_pmic->device_type) { 283 switch (sec_pmic->device_type) {
299 case S2MPA01: 284 case S2MPA01:
300 regmap = &s2mpa01_regmap_config; 285 regmap = &s2mpa01_regmap_config;
301 /*
302 * The rtc-s5m driver does not support S2MPA01 and there
303 * is no mfd_cell for S2MPA01 RTC device.
304 * However we must pass something to devm_regmap_init_i2c()
305 * so use S5M-like regmap config even though it wouldn't work.
306 */
307 regmap_rtc = &s5m_rtc_regmap_config;
308 break; 286 break;
309 case S2MPS11X: 287 case S2MPS11X:
310 regmap = &s2mps11_regmap_config; 288 regmap = &s2mps11_regmap_config;
311 /*
312 * The rtc-s5m driver does not support S2MPS11 and there
313 * is no mfd_cell for S2MPS11 RTC device.
314 * However we must pass something to devm_regmap_init_i2c()
315 * so use S5M-like regmap config even though it wouldn't work.
316 */
317 regmap_rtc = &s5m_rtc_regmap_config;
318 break; 289 break;
319 case S2MPS14X: 290 case S2MPS14X:
320 regmap = &s2mps14_regmap_config; 291 regmap = &s2mps14_regmap_config;
321 regmap_rtc = &s2mps14_rtc_regmap_config;
322 break; 292 break;
323 case S5M8763X: 293 case S5M8763X:
324 regmap = &s5m8763_regmap_config; 294 regmap = &s5m8763_regmap_config;
325 regmap_rtc = &s5m_rtc_regmap_config;
326 break; 295 break;
327 case S5M8767X: 296 case S5M8767X:
328 regmap = &s5m8767_regmap_config; 297 regmap = &s5m8767_regmap_config;
329 regmap_rtc = &s5m_rtc_regmap_config;
330 break; 298 break;
331 default: 299 default:
332 regmap = &sec_regmap_config; 300 regmap = &sec_regmap_config;
333 regmap_rtc = &s5m_rtc_regmap_config;
334 break; 301 break;
335 } 302 }
336 303
@@ -342,21 +309,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
342 return ret; 309 return ret;
343 } 310 }
344 311
345 sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
346 if (!sec_pmic->rtc) {
347 dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n");
348 return -ENODEV;
349 }
350 i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
351
352 sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc);
353 if (IS_ERR(sec_pmic->regmap_rtc)) {
354 ret = PTR_ERR(sec_pmic->regmap_rtc);
355 dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
356 ret);
357 goto err_regmap_rtc;
358 }
359
360 if (pdata && pdata->cfg_pmic_irq) 312 if (pdata && pdata->cfg_pmic_irq)
361 pdata->cfg_pmic_irq(); 313 pdata->cfg_pmic_irq();
362 314
@@ -403,8 +355,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
403 355
404err_mfd: 356err_mfd:
405 sec_irq_exit(sec_pmic); 357 sec_irq_exit(sec_pmic);
406err_regmap_rtc:
407 i2c_unregister_device(sec_pmic->rtc);
408 return ret; 358 return ret;
409} 359}
410 360
@@ -414,7 +364,6 @@ static int sec_pmic_remove(struct i2c_client *i2c)
414 364
415 mfd_remove_devices(sec_pmic->dev); 365 mfd_remove_devices(sec_pmic->dev);
416 sec_irq_exit(sec_pmic); 366 sec_irq_exit(sec_pmic);
417 i2c_unregister_device(sec_pmic->rtc);
418 return 0; 367 return 0;
419} 368}
420 369
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 476af93543f6..8ec2d6a1dbe1 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -40,6 +40,7 @@
40 40
41struct s5m_rtc_info { 41struct s5m_rtc_info {
42 struct device *dev; 42 struct device *dev;
43 struct i2c_client *i2c;
43 struct sec_pmic_dev *s5m87xx; 44 struct sec_pmic_dev *s5m87xx;
44 struct regmap *regmap; 45 struct regmap *regmap;
45 struct rtc_device *rtc_dev; 46 struct rtc_device *rtc_dev;
@@ -49,6 +50,20 @@ struct s5m_rtc_info {
49 bool wtsr_smpl; 50 bool wtsr_smpl;
50}; 51};
51 52
53static const struct regmap_config s5m_rtc_regmap_config = {
54 .reg_bits = 8,
55 .val_bits = 8,
56
57 .max_register = SEC_RTC_REG_MAX,
58};
59
60static const struct regmap_config s2mps14_rtc_regmap_config = {
61 .reg_bits = 8,
62 .val_bits = 8,
63
64 .max_register = S2MPS_RTC_REG_MAX,
65};
66
52static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm, 67static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm,
53 int rtc_24hr_mode) 68 int rtc_24hr_mode)
54{ 69{
@@ -554,6 +569,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
554 struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); 569 struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
555 struct sec_platform_data *pdata = s5m87xx->pdata; 570 struct sec_platform_data *pdata = s5m87xx->pdata;
556 struct s5m_rtc_info *info; 571 struct s5m_rtc_info *info;
572 const struct regmap_config *regmap_cfg;
557 int ret; 573 int ret;
558 574
559 if (!pdata) { 575 if (!pdata) {
@@ -565,9 +581,37 @@ static int s5m_rtc_probe(struct platform_device *pdev)
565 if (!info) 581 if (!info)
566 return -ENOMEM; 582 return -ENOMEM;
567 583
584 switch (pdata->device_type) {
585 case S2MPS14X:
586 regmap_cfg = &s2mps14_rtc_regmap_config;
587 break;
588 case S5M8763X:
589 regmap_cfg = &s5m_rtc_regmap_config;
590 break;
591 case S5M8767X:
592 regmap_cfg = &s5m_rtc_regmap_config;
593 break;
594 default:
595 dev_err(&pdev->dev, "Device type is not supported by RTC driver\n");
596 return -ENODEV;
597 }
598
599 info->i2c = i2c_new_dummy(s5m87xx->i2c->adapter, RTC_I2C_ADDR);
600 if (!info->i2c) {
601 dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
602 return -ENODEV;
603 }
604
605 info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg);
606 if (IS_ERR(info->regmap)) {
607 ret = PTR_ERR(info->regmap);
608 dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
609 ret);
610 goto err;
611 }
612
568 info->dev = &pdev->dev; 613 info->dev = &pdev->dev;
569 info->s5m87xx = s5m87xx; 614 info->s5m87xx = s5m87xx;
570 info->regmap = s5m87xx->regmap_rtc;
571 info->device_type = s5m87xx->device_type; 615 info->device_type = s5m87xx->device_type;
572 info->wtsr_smpl = s5m87xx->wtsr_smpl; 616 info->wtsr_smpl = s5m87xx->wtsr_smpl;
573 617
@@ -585,7 +629,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
585 default: 629 default:
586 ret = -EINVAL; 630 ret = -EINVAL;
587 dev_err(&pdev->dev, "Unsupported device type: %d\n", ret); 631 dev_err(&pdev->dev, "Unsupported device type: %d\n", ret);
588 return ret; 632 goto err;
589 } 633 }
590 634
591 platform_set_drvdata(pdev, info); 635 platform_set_drvdata(pdev, info);
@@ -602,15 +646,24 @@ static int s5m_rtc_probe(struct platform_device *pdev)
602 info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc", 646 info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc",
603 &s5m_rtc_ops, THIS_MODULE); 647 &s5m_rtc_ops, THIS_MODULE);
604 648
605 if (IS_ERR(info->rtc_dev)) 649 if (IS_ERR(info->rtc_dev)) {
606 return PTR_ERR(info->rtc_dev); 650 ret = PTR_ERR(info->rtc_dev);
651 goto err;
652 }
607 653
608 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 654 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
609 s5m_rtc_alarm_irq, 0, "rtc-alarm0", 655 s5m_rtc_alarm_irq, 0, "rtc-alarm0",
610 info); 656 info);
611 if (ret < 0) 657 if (ret < 0) {
612 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 658 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
613 info->irq, ret); 659 info->irq, ret);
660 goto err;
661 }
662
663 return 0;
664
665err:
666 i2c_unregister_device(info->i2c);
614 667
615 return ret; 668 return ret;
616} 669}
@@ -639,6 +692,17 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
639 s5m_rtc_enable_smpl(info, false); 692 s5m_rtc_enable_smpl(info, false);
640} 693}
641 694
695static int s5m_rtc_remove(struct platform_device *pdev)
696{
697 struct s5m_rtc_info *info = platform_get_drvdata(pdev);
698
699 /* Perform also all shutdown steps when removing */
700 s5m_rtc_shutdown(pdev);
701 i2c_unregister_device(info->i2c);
702
703 return 0;
704}
705
642#ifdef CONFIG_PM_SLEEP 706#ifdef CONFIG_PM_SLEEP
643static int s5m_rtc_resume(struct device *dev) 707static int s5m_rtc_resume(struct device *dev)
644{ 708{
@@ -676,6 +740,7 @@ static struct platform_driver s5m_rtc_driver = {
676 .pm = &s5m_rtc_pm_ops, 740 .pm = &s5m_rtc_pm_ops,
677 }, 741 },
678 .probe = s5m_rtc_probe, 742 .probe = s5m_rtc_probe,
743 .remove = s5m_rtc_remove,
679 .shutdown = s5m_rtc_shutdown, 744 .shutdown = s5m_rtc_shutdown,
680 .id_table = s5m_rtc_id, 745 .id_table = s5m_rtc_id,
681}; 746};
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 157e32b6ca28..84aaf6c25794 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -28,7 +28,6 @@ enum sec_device_type {
28 * @dev: master device of the chip (can be used to access platform data) 28 * @dev: master device of the chip (can be used to access platform data)
29 * @pdata: pointer to private data used to pass platform data to child 29 * @pdata: pointer to private data used to pass platform data to child
30 * @i2c: i2c client private data for regulator 30 * @i2c: i2c client private data for regulator
31 * @rtc: i2c client private data for rtc
32 * @iolock: mutex for serializing io access 31 * @iolock: mutex for serializing io access
33 * @irqlock: mutex for buslock 32 * @irqlock: mutex for buslock
34 * @irq_base: base IRQ number for sec-pmic, required for IRQs 33 * @irq_base: base IRQ number for sec-pmic, required for IRQs
@@ -42,9 +41,7 @@ struct sec_pmic_dev {
42 struct device *dev; 41 struct device *dev;
43 struct sec_platform_data *pdata; 42 struct sec_platform_data *pdata;
44 struct regmap *regmap_pmic; 43 struct regmap *regmap_pmic;
45 struct regmap *regmap_rtc;
46 struct i2c_client *i2c; 44 struct i2c_client *i2c;
47 struct i2c_client *rtc;
48 45
49 int device_type; 46 int device_type;
50 int irq_base; 47 int irq_base;