summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-04-14 07:40:45 (GMT)
committerHyungwon Hwang <human.hwang@samsung.com>2014-12-23 02:09:29 (GMT)
commit5d5ac10f81d5610ad4fcf5aa351541186ca0e22e (patch)
tree49d8cd75604114da79ccd75cb03981974c4a01c3
parentcfd71b860551426311be216e3b3ab0447a3645b7 (diff)
downloadlinux-3.10-5d5ac10f81d5610ad4fcf5aa351541186ca0e22e.zip
linux-3.10-5d5ac10f81d5610ad4fcf5aa351541186ca0e22e.tar.gz
linux-3.10-5d5ac10f81d5610ad4fcf5aa351541186ca0e22e.tar.bz2
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. Change-Id: Id158436deaed33ac2dafca06b818bd0518108084 Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Acked-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/sec-core.c44
-rw-r--r--drivers/rtc/rtc-s5m.c53
-rw-r--r--include/linux/mfd/samsung/core.h3
3 files changed, 49 insertions, 51 deletions
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 15d8326..468a49a 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -25,7 +25,6 @@
#include <linux/mfd/core.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
-#include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8763.h>
@@ -165,18 +164,6 @@ static const struct regmap_config sec_regmap_config = {
.val_bits = 8,
};
-static const struct regmap_config s5m_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = S5M_RTC_REG_MAX,
-};
-
-static const struct regmap_config s2mps14_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = S2MPS_RTC_REG_MAX,
-};
-
static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -271,7 +258,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct sec_platform_data *pdata = i2c->dev.platform_data;
- const struct regmap_config *regmap, *regmap_rtc;
+ const struct regmap_config *regmap;
struct sec_pmic_dev *sec_pmic;
int ret;
@@ -305,29 +292,18 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S2MPS11X:
regmap = &s2mps11_regmap_config;
- /*
- * The rtc-s5m driver does not support S2MPS11 and there
- * is no mfd_cell for S2MPS11 RTC device.
- * However we must pass something to devm_regmap_init_i2c()
- * so use S5M-like regmap config even though it wouldn't work.
- */
- regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
- regmap_rtc = &s2mps14_rtc_regmap_config;
break;
case S5M8763X:
regmap = &s5m8763_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
default:
regmap = &sec_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
}
@@ -339,22 +315,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
return ret;
}
- sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
- if (IS_ERR_OR_NULL(sec_pmic->rtc)) {
- ret = PTR_ERR(sec_pmic->rtc);
- dev_err(&i2c->dev, "Failed to allocate i2c : %d\n", ret);
- return ret;
- }
- i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
-
- sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc);
- if (IS_ERR_OR_NULL(sec_pmic->regmap_rtc)) {
- ret = PTR_ERR(sec_pmic->regmap_rtc);
- dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
- ret);
- return ret;
- }
-
if (pdata && pdata->cfg_pmic_irq)
pdata->cfg_pmic_irq();
@@ -397,7 +357,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
err:
sec_irq_exit(sec_pmic);
- i2c_unregister_device(sec_pmic->rtc);
return ret;
}
@@ -407,7 +366,6 @@ static int sec_pmic_remove(struct i2c_client *i2c)
mfd_remove_devices(sec_pmic->dev);
sec_irq_exit(sec_pmic);
- i2c_unregister_device(sec_pmic->rtc);
return 0;
}
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index f211fbf..a5dc32a 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -155,6 +155,20 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
return 0;
}
+static const struct regmap_config s5m_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S5M_RTC_REG_MAX,
+};
+
+static const struct regmap_config s2mps14_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S2MPS_RTC_REG_MAX,
+};
+
static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
@@ -817,7 +831,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
static struct sec_wtsr_smpl default_wtsr_smpl_data = {
.wtsr_en = true,
#if defined(CONFIG_SEC_FACTORY_MODE)
- .smpl_en = false,
+ .smpl_en = false,
#endif
};
@@ -826,6 +840,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = iodev->pdata;
struct s5m_rtc_info *info;
+ const struct regmap_config *regmap_cfg;
int ret;
if (!pdata) {
@@ -840,8 +855,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->iodev = iodev;
- info->rtc = iodev->rtc;
- info->regmap_rtc = iodev->regmap_rtc;
info->device_type = iodev->device_type;
if (pdata->wtsr_smpl)
info->wtsr_smpl = pdata->wtsr_smpl;
@@ -849,22 +862,34 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->wtsr_smpl = &default_wtsr_smpl_data;
switch (pdata->device_type) {
+ case S2MPS11X:
+ /*
+ * The rtc-s5m driver does not support S2MPS11 and there
+ * is no mfd_cell for S2MPS11 RTC device.
+ * However we must pass something to devm_regmap_init_i2c()
+ * so use S5M-like regmap config even though it wouldn't work.
+ */
+ regmap_cfg = &s5m_rtc_regmap_config;
+ break;
case S5M8763X:
info->irq = regmap_irq_get_virq(iodev->irq_data,
S5M8763_IRQ_ALARM0);
info->regs = &s5m_rtc_regs;
+ regmap_cfg = &s5m_rtc_regmap_config;
break;
case S5M8767X:
info->irq = regmap_irq_get_virq(iodev->irq_data,
S5M8767_IRQ_RTCA1);
info->regs = &s5m_rtc_regs;
+ regmap_cfg = &s5m_rtc_regmap_config;
break;
case S2MPS14X:
info->irq = regmap_irq_get_virq(iodev->irq_data,
S2MPS14_IRQ_RTCA0);
info->regs = &s2mps_rtc_regs;
+ regmap_cfg = &s2mps14_rtc_regmap_config;
break;
default:
ret = -EINVAL;
@@ -872,6 +897,20 @@ static int s5m_rtc_probe(struct platform_device *pdev)
goto out_rtc;
}
+ info->rtc = i2c_new_dummy(iodev->i2c->adapter, RTC_I2C_ADDR);
+ if (IS_ERR_OR_NULL(info->rtc)) {
+ dev_err(&pdev->dev, "Failed to allocate i2c for RTC\n");
+ return -ENODEV;
+ }
+
+ info->regmap_rtc = devm_regmap_init_i2c(info->rtc, regmap_cfg);
+ if (IS_ERR(info->regmap_rtc)) {
+ ret = PTR_ERR(info->regmap_rtc);
+ dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
+ ret);
+ goto err;
+ }
+
platform_set_drvdata(pdev, info);
ret = s5m8767_rtc_init_reg(info);
@@ -891,19 +930,23 @@ static int s5m_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_dev)) {
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
- goto out_rtc;
+ goto err;
}
ret = request_threaded_irq(info->irq, NULL, s5m_rtc_alarm_irq,
pdata->irqflags, "rtc-alarm0", info);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret);
+ goto err;
+ }
dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
return 0;
+err:
+ i2c_unregister_device(info->rtc);
out_rtc:
platform_set_drvdata(pdev, NULL);
return ret;
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 1f5f5f0..180cc0a 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -29,7 +29,6 @@ enum sec_device_type {
* @dev: master device of the chip (can be used to access platform data)
* @pdata: pointer to private data used to pass platform data to child
* @i2c: i2c client private data for regulator
- * @rtc: i2c client private data for rtc
* @iolock: mutex for serializing io access
* @irqlock: mutex for buslock
* @irq_base: base IRQ number for sec-pmic, required for IRQs
@@ -43,9 +42,7 @@ struct sec_pmic_dev {
struct device *dev;
struct sec_platform_data *pdata;
struct regmap *regmap_pmic;
- struct regmap *regmap_rtc;
struct i2c_client *i2c;
- struct i2c_client *rtc;
struct mutex iolock;
struct mutex irqlock;