From b07e2b70b9a1ff9f59af66fd0085c1c52178f440 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:41:41 +0100 Subject: mfd: sec-core: Add maximum RTC register for regmap config Add maximum register to the regmap used by rtc-s5m driver. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 714e2135210e..306b3a282c29 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -141,6 +141,8 @@ static const struct regmap_config s5m8767_regmap_config = { static const struct regmap_config sec_rtc_regmap_config = { .reg_bits = 8, .val_bits = 8, + + .max_register = SEC_RTC_REG_MAX, }; #ifdef CONFIG_OF -- cgit v1.2.3 From 3e5a45f7f16e9f71c0e2ce4f8f5827a8298a8362 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:41:42 +0100 Subject: mfd: sec-core: Select different RTC regmaps for devices This patch prepares for adding support for S2MPS14 RTC driver by selecting different regmaps for S2MPS1X/S5M876X RTC devices. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 306b3a282c29..9623899e6f7c 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -199,7 +199,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); - const struct regmap_config *regmap; + const struct regmap_config *regmap, *regmap_rtc; struct sec_pmic_dev *sec_pmic; int ret; @@ -233,15 +233,25 @@ 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 = &sec_rtc_regmap_config; break; case S5M8763X: regmap = &s5m8763_regmap_config; + regmap_rtc = &sec_rtc_regmap_config; break; case S5M8767X: regmap = &s5m8767_regmap_config; + regmap_rtc = &sec_rtc_regmap_config; break; default: regmap = &sec_regmap_config; + regmap_rtc = &sec_rtc_regmap_config; break; } @@ -256,8 +266,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); i2c_set_clientdata(sec_pmic->rtc, sec_pmic); - sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, - &sec_rtc_regmap_config); + sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc); if (IS_ERR(sec_pmic->regmap_rtc)) { ret = PTR_ERR(sec_pmic->regmap_rtc); dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", -- cgit v1.2.3 From 677620952a0fd1b1618bed57c1ebd94bf3c710f3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:41:43 +0100 Subject: mfd: sec-irq: Use consistent S2MPS11 RTC alarm interrupt indexes The S2MPS11 RTC has two alarms: alarm0 and alarm1 (corresponding interrupts are named similarly). Use consistent names for interrupts to limit possible errors. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-irq.c | 8 ++++---- include/linux/mfd/samsung/irq.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 4de494f51d40..e403c293b437 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -59,13 +59,13 @@ static const struct regmap_irq s2mps11_irqs[] = { .reg_offset = 1, .mask = S2MPS11_IRQ_RTC60S_MASK, }, - [S2MPS11_IRQ_RTCA1] = { + [S2MPS11_IRQ_RTCA0] = { .reg_offset = 1, - .mask = S2MPS11_IRQ_RTCA1_MASK, + .mask = S2MPS11_IRQ_RTCA0_MASK, }, - [S2MPS11_IRQ_RTCA2] = { + [S2MPS11_IRQ_RTCA1] = { .reg_offset = 1, - .mask = S2MPS11_IRQ_RTCA2_MASK, + .mask = S2MPS11_IRQ_RTCA1_MASK, }, [S2MPS11_IRQ_SMPL] = { .reg_offset = 1, diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h index d43b4f9e7fb2..abe1a6aae3b7 100644 --- a/include/linux/mfd/samsung/irq.h +++ b/include/linux/mfd/samsung/irq.h @@ -24,8 +24,8 @@ enum s2mps11_irq { S2MPS11_IRQ_MRB, S2MPS11_IRQ_RTC60S, + S2MPS11_IRQ_RTCA0, S2MPS11_IRQ_RTCA1, - S2MPS11_IRQ_RTCA2, S2MPS11_IRQ_SMPL, S2MPS11_IRQ_RTC1S, S2MPS11_IRQ_WTSR, @@ -47,7 +47,7 @@ enum s2mps11_irq { #define S2MPS11_IRQ_RTC60S_MASK (1 << 0) #define S2MPS11_IRQ_RTCA1_MASK (1 << 1) -#define S2MPS11_IRQ_RTCA2_MASK (1 << 2) +#define S2MPS11_IRQ_RTCA0_MASK (1 << 2) #define S2MPS11_IRQ_SMPL_MASK (1 << 3) #define S2MPS11_IRQ_RTC1S_MASK (1 << 4) #define S2MPS11_IRQ_WTSR_MASK (1 << 5) -- cgit v1.2.3 From dc6919663f7a02d02cc08d605a1f68d6cefe0042 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:41:44 +0100 Subject: mfd: sec: Add support for S2MPS14 Add support for S2MPS14 PMIC device to the MFD sec-core driver. The S2MPS14 is similar to S2MPS11 but it has fewer regulators, two clocks instead of three and a little different registers layout. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 48 ++++++++++-- drivers/mfd/sec-irq.c | 89 ++++++++++++++++++++- include/linux/mfd/samsung/core.h | 1 + include/linux/mfd/samsung/irq.h | 27 +++++++ include/linux/mfd/samsung/rtc.h | 55 +++++++++++-- include/linux/mfd/samsung/s2mps14.h | 152 ++++++++++++++++++++++++++++++++++++ 6 files changed, 360 insertions(+), 12 deletions(-) create mode 100644 include/linux/mfd/samsung/s2mps14.h (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 9623899e6f7c..a4df76c160f8 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,16 @@ static const struct mfd_cell s2mps11_devs[] = { } }; +static const struct mfd_cell s2mps14_devs[] = { + { + .name = "s2mps14-pmic", + }, { + .name = "s2mps14-rtc", + }, { + .name = "s2mps14-clk", + } +}; + #ifdef CONFIG_OF static struct of_device_id sec_dt_match[] = { { .compatible = "samsung,s5m8767-pmic", @@ -77,6 +88,9 @@ static struct of_device_id sec_dt_match[] = { { .compatible = "samsung,s2mps11-pmic", .data = (void *)S2MPS11X, }, + { .compatible = "samsung,s2mps14-pmic", + .data = (void *)S2MPS14X, + }, {}, }; #endif @@ -120,6 +134,15 @@ static const struct regmap_config s2mps11_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static const struct regmap_config s2mps14_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS14_REG_LDODSCH3, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + static const struct regmap_config s5m8763_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -138,13 +161,20 @@ static const struct regmap_config s5m8767_regmap_config = { .cache_type = REGCACHE_FLAT, }; -static const struct regmap_config sec_rtc_regmap_config = { +static const struct regmap_config s5m_rtc_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = SEC_RTC_REG_MAX, }; +static const struct regmap_config s2mps14_rtc_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS_RTC_REG_MAX, +}; + #ifdef CONFIG_OF /* * Only the common platform data elements for s5m8767 are parsed here from the @@ -239,19 +269,23 @@ static int sec_pmic_probe(struct i2c_client *i2c, * However we must pass something to devm_regmap_init_i2c() * so use S5M-like regmap config even though it wouldn't work. */ - regmap_rtc = &sec_rtc_regmap_config; + 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 = &sec_rtc_regmap_config; + regmap_rtc = &s5m_rtc_regmap_config; break; case S5M8767X: regmap = &s5m8767_regmap_config; - regmap_rtc = &sec_rtc_regmap_config; + regmap_rtc = &s5m_rtc_regmap_config; break; default: regmap = &sec_regmap_config; - regmap_rtc = &sec_rtc_regmap_config; + regmap_rtc = &s5m_rtc_regmap_config; break; } @@ -298,6 +332,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); break; + case S2MPS14X: + ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs, + ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL); + break; default: /* If this happens the probe function is problem */ BUG(); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index e403c293b437..64e7913aadc6 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -1,7 +1,7 @@ /* * sec-irq.c * - * Copyright (c) 2011 Samsung Electronics Co., Ltd + * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd * http://www.samsung.com * * This program is free software; you can redistribute it and/or modify it @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,76 @@ static const struct regmap_irq s2mps11_irqs[] = { }, }; +static const struct regmap_irq s2mps14_irqs[] = { + [S2MPS14_IRQ_PWRONF] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_PWRONF_MASK, + }, + [S2MPS14_IRQ_PWRONR] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_PWRONR_MASK, + }, + [S2MPS14_IRQ_JIGONBF] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_JIGONBF_MASK, + }, + [S2MPS14_IRQ_JIGONBR] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_JIGONBR_MASK, + }, + [S2MPS14_IRQ_ACOKBF] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_ACOKBF_MASK, + }, + [S2MPS14_IRQ_ACOKBR] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_ACOKBR_MASK, + }, + [S2MPS14_IRQ_PWRON1S] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_PWRON1S_MASK, + }, + [S2MPS14_IRQ_MRB] = { + .reg_offset = 0, + .mask = S2MPS11_IRQ_MRB_MASK, + }, + [S2MPS14_IRQ_RTC60S] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_RTC60S_MASK, + }, + [S2MPS14_IRQ_RTCA1] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_RTCA1_MASK, + }, + [S2MPS14_IRQ_RTCA0] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_RTCA0_MASK, + }, + [S2MPS14_IRQ_SMPL] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_SMPL_MASK, + }, + [S2MPS14_IRQ_RTC1S] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_RTC1S_MASK, + }, + [S2MPS14_IRQ_WTSR] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_WTSR_MASK, + }, + [S2MPS14_IRQ_INT120C] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_INT120C_MASK, + }, + [S2MPS14_IRQ_INT140C] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_INT140C_MASK, + }, + [S2MPS14_IRQ_TSD] = { + .reg_offset = 2, + .mask = S2MPS14_IRQ_TSD_MASK, + }, +}; static const struct regmap_irq s5m8767_irqs[] = { [S5M8767_IRQ_PWRR] = { @@ -246,6 +317,16 @@ static const struct regmap_irq_chip s2mps11_irq_chip = { .ack_base = S2MPS11_REG_INT1, }; +static const struct regmap_irq_chip s2mps14_irq_chip = { + .name = "s2mps14", + .irqs = s2mps14_irqs, + .num_irqs = ARRAY_SIZE(s2mps14_irqs), + .num_regs = 3, + .status_base = S2MPS14_REG_INT1, + .mask_base = S2MPS14_REG_INT1M, + .ack_base = S2MPS14_REG_INT1, +}; + static const struct regmap_irq_chip s5m8767_irq_chip = { .name = "s5m8767", .irqs = s5m8767_irqs, @@ -297,6 +378,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) sec_pmic->irq_base, &s2mps11_irq_chip, &sec_pmic->irq_data); break; + case S2MPS14X: + ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq_base, &s2mps14_irq_chip, + &sec_pmic->irq_data); + break; default: dev_err(sec_pmic->dev, "Unknown device type %d\n", sec_pmic->device_type); diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 41c9bde410c5..8e9bbb1083d4 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -19,6 +19,7 @@ enum sec_device_type { S5M8763X, S5M8767X, S2MPS11X, + S2MPS14X, }; /** diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h index abe1a6aae3b7..0065f6f1daf4 100644 --- a/include/linux/mfd/samsung/irq.h +++ b/include/linux/mfd/samsung/irq.h @@ -55,6 +55,33 @@ enum s2mps11_irq { #define S2MPS11_IRQ_INT120C_MASK (1 << 0) #define S2MPS11_IRQ_INT140C_MASK (1 << 1) +enum s2mps14_irq { + S2MPS14_IRQ_PWRONF, + S2MPS14_IRQ_PWRONR, + S2MPS14_IRQ_JIGONBF, + S2MPS14_IRQ_JIGONBR, + S2MPS14_IRQ_ACOKBF, + S2MPS14_IRQ_ACOKBR, + S2MPS14_IRQ_PWRON1S, + S2MPS14_IRQ_MRB, + + S2MPS14_IRQ_RTC60S, + S2MPS14_IRQ_RTCA1, + S2MPS14_IRQ_RTCA0, + S2MPS14_IRQ_SMPL, + S2MPS14_IRQ_RTC1S, + S2MPS14_IRQ_WTSR, + + S2MPS14_IRQ_INT120C, + S2MPS14_IRQ_INT140C, + S2MPS14_IRQ_TSD, + + S2MPS14_IRQ_NR, +}; + +/* Masks for interrupts are the same as in s2mps11 */ +#define S2MPS14_IRQ_TSD_MASK (1 << 2) + enum s5m8767_irq { S5M8767_IRQ_PWRR, S5M8767_IRQ_PWRF, diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index 4627f59ebd84..3e02b768d537 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -1,12 +1,17 @@ -/* rtc.h +/* rtc.h * - * Copyright (c) 2011 Samsung Electronics Co., Ltd + * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd * http://www.samsung.com * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * */ @@ -47,6 +52,37 @@ enum sec_rtc_reg { SEC_RTC_REG_MAX, }; +enum s2mps_rtc_reg { + S2MPS_RTC_CTRL, + S2MPS_WTSR_SMPL_CNTL, + S2MPS_RTC_UDR_CON, + S2MPS_RSVD, + S2MPS_RTC_SEC, + S2MPS_RTC_MIN, + S2MPS_RTC_HOUR, + S2MPS_RTC_WEEKDAY, + S2MPS_RTC_DATE, + S2MPS_RTC_MONTH, + S2MPS_RTC_YEAR, + S2MPS_ALARM0_SEC, + S2MPS_ALARM0_MIN, + S2MPS_ALARM0_HOUR, + S2MPS_ALARM0_WEEKDAY, + S2MPS_ALARM0_DATE, + S2MPS_ALARM0_MONTH, + S2MPS_ALARM0_YEAR, + S2MPS_ALARM1_SEC, + S2MPS_ALARM1_MIN, + S2MPS_ALARM1_HOUR, + S2MPS_ALARM1_WEEKDAY, + S2MPS_ALARM1_DATE, + S2MPS_ALARM1_MONTH, + S2MPS_ALARM1_YEAR, + S2MPS_OFFSRC, + + S2MPS_RTC_REG_MAX, +}; + #define RTC_I2C_ADDR (0x0C >> 1) #define HOUR_12 (1 << 7) @@ -56,6 +92,9 @@ enum sec_rtc_reg { #define ALARM1_STATUS (1 << 2) #define UPDATE_AD (1 << 0) +#define S2MPS_ALARM0_STATUS (1 << 2) +#define S2MPS_ALARM1_STATUS (1 << 1) + /* RTC Control Register */ #define BCD_EN_SHIFT 0 #define BCD_EN_MASK (1 << BCD_EN_SHIFT) @@ -64,6 +103,10 @@ enum sec_rtc_reg { /* RTC Update Register1 */ #define RTC_UDR_SHIFT 0 #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) +#define S2MPS_RTC_WUDR_SHIFT 4 +#define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) +#define S2MPS_RTC_RUDR_SHIFT 0 +#define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) #define RTC_TCON_SHIFT 1 #define RTC_TCON_MASK (1 << RTC_TCON_SHIFT) #define RTC_TIME_EN_SHIFT 3 diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h new file mode 100644 index 000000000000..ec1e0857ddde --- /dev/null +++ b/include/linux/mfd/samsung/s2mps14.h @@ -0,0 +1,152 @@ +/* + * s2mps14.h + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __LINUX_MFD_S2MPS14_H +#define __LINUX_MFD_S2MPS14_H + +/* S2MPS14 registers */ +enum s2mps14_reg { + S2MPS14_REG_ID, + S2MPS14_REG_INT1, + S2MPS14_REG_INT2, + S2MPS14_REG_INT3, + S2MPS14_REG_INT1M, + S2MPS14_REG_INT2M, + S2MPS14_REG_INT3M, + S2MPS14_REG_ST1, + S2MPS14_REG_ST2, + S2MPS14_REG_PWRONSRC, + S2MPS14_REG_OFFSRC, + S2MPS14_REG_BU_CHG, + S2MPS14_REG_RTCCTRL, + S2MPS14_REG_CTRL1, + S2MPS14_REG_CTRL2, + S2MPS14_REG_RSVD1, + S2MPS14_REG_RSVD2, + S2MPS14_REG_RSVD3, + S2MPS14_REG_RSVD4, + S2MPS14_REG_RSVD5, + S2MPS14_REG_RSVD6, + S2MPS14_REG_CTRL3, + S2MPS14_REG_RSVD7, + S2MPS14_REG_RSVD8, + S2MPS14_REG_WRSTBI, + S2MPS14_REG_B1CTRL1, + S2MPS14_REG_B1CTRL2, + S2MPS14_REG_B2CTRL1, + S2MPS14_REG_B2CTRL2, + S2MPS14_REG_B3CTRL1, + S2MPS14_REG_B3CTRL2, + S2MPS14_REG_B4CTRL1, + S2MPS14_REG_B4CTRL2, + S2MPS14_REG_B5CTRL1, + S2MPS14_REG_B5CTRL2, + S2MPS14_REG_L1CTRL, + S2MPS14_REG_L2CTRL, + S2MPS14_REG_L3CTRL, + S2MPS14_REG_L4CTRL, + S2MPS14_REG_L5CTRL, + S2MPS14_REG_L6CTRL, + S2MPS14_REG_L7CTRL, + S2MPS14_REG_L8CTRL, + S2MPS14_REG_L9CTRL, + S2MPS14_REG_L10CTRL, + S2MPS14_REG_L11CTRL, + S2MPS14_REG_L12CTRL, + S2MPS14_REG_L13CTRL, + S2MPS14_REG_L14CTRL, + S2MPS14_REG_L15CTRL, + S2MPS14_REG_L16CTRL, + S2MPS14_REG_L17CTRL, + S2MPS14_REG_L18CTRL, + S2MPS14_REG_L19CTRL, + S2MPS14_REG_L20CTRL, + S2MPS14_REG_L21CTRL, + S2MPS14_REG_L22CTRL, + S2MPS14_REG_L23CTRL, + S2MPS14_REG_L24CTRL, + S2MPS14_REG_L25CTRL, + S2MPS14_REG_LDODSCH1, + S2MPS14_REG_LDODSCH2, + S2MPS14_REG_LDODSCH3, +}; + +/* S2MPS14 regulator ids */ +enum s2mps14_regulators { + S2MPS14_LDO1, + S2MPS14_LDO2, + S2MPS14_LDO3, + S2MPS14_LDO4, + S2MPS14_LDO5, + S2MPS14_LDO6, + S2MPS14_LDO7, + S2MPS14_LDO8, + S2MPS14_LDO9, + S2MPS14_LDO10, + S2MPS14_LDO11, + S2MPS14_LDO12, + S2MPS14_LDO13, + S2MPS14_LDO14, + S2MPS14_LDO15, + S2MPS14_LDO16, + S2MPS14_LDO17, + S2MPS14_LDO18, + S2MPS14_LDO19, + S2MPS14_LDO20, + S2MPS14_LDO21, + S2MPS14_LDO22, + S2MPS14_LDO23, + S2MPS14_LDO24, + S2MPS14_LDO25, + S2MPS14_BUCK1, + S2MPS14_BUCK2, + S2MPS14_BUCK3, + S2MPS14_BUCK4, + S2MPS14_BUCK5, + + S2MPS14_REGULATOR_MAX, +}; + +/* Regulator constraints for BUCKx */ +#define S2MPS14_BUCK1235_MIN_600MV 600000 +#define S2MPS14_BUCK4_MIN_1400MV 1400000 +#define S2MPS14_BUCK1235_STEP_6_25MV 6250 +#define S2MPS14_BUCK4_STEP_12_5MV 12500 +#define S2MPS14_BUCK1235_START_SEL 0x20 +#define S2MPS14_BUCK4_START_SEL 0x40 +/* + * Default ramp delay in uv/us. Datasheet says that ramp delay can be + * controlled however it does not specify which register is used for that. + * Let's assume that default value will be set. + */ +#define S2MPS14_BUCK_RAMP_DELAY 12500 + +/* Regulator constraints for different types of LDOx */ +#define S2MPS14_LDO_MIN_800MV 800000 +#define S2MPS14_LDO_MIN_1800MV 1800000 +#define S2MPS14_LDO_STEP_12_5MV 12500 +#define S2MPS14_LDO_STEP_25MV 25000 + +#define S2MPS14_LDO_VSEL_MASK 0x3F +#define S2MPS14_BUCK_VSEL_MASK 0xFF +#define S2MPS14_ENABLE_MASK (0x03 << S2MPS14_ENABLE_SHIFT) +#define S2MPS14_ENABLE_SHIFT 6 +#define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) +#define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) + +#endif /* __LINUX_MFD_S2MPS14_H */ -- cgit v1.2.3 From 65aba1e04916d72b30c028730a1e31860c225412 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 11 Feb 2014 10:12:25 +0100 Subject: mfd: sec-core: Fix possible NULL pointer dereference when i2c_new_dummy error During probe the sec-core driver allocates dummy I2C device for RTC with i2c_new_dummy() but return value is not checked. In case of error (i2c_new_device(): memory allocation failure or I2C address cannot be used) this function returns NULL which is later used by devm_regmap_init_i2c() or i2c_unregister_device(). If i2c_new_dummy() fails for RTC device, fail also the probe for main MFD driver. Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index a4df76c160f8..d163c66edebb 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -298,6 +298,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, } sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); + if (!sec_pmic->rtc) { + dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n"); + return -ENODEV; + } i2c_set_clientdata(sec_pmic->rtc, sec_pmic); sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc); -- cgit v1.2.3 From 8f695de515b9e08e30c5b7fae48c0672c8361c51 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Thu, 13 Mar 2014 11:14:07 +0900 Subject: mfd: sec-core: Silence compiler warning When used 64bit compiler GCC warns as drivers/mfd/sec-core.c:199:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Pankaj Dubey Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 6 +++--- include/linux/mfd/samsung/core.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index d163c66edebb..3fc3ebdd7b8a 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -212,17 +212,17 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( } #endif -static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, +static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c, const struct i2c_device_id *id) { #ifdef CONFIG_OF if (i2c->dev.of_node) { const struct of_device_id *match; match = of_match_node(sec_dt_match, i2c->dev.of_node); - return (int)match->data; + return (unsigned long)match->data; } #endif - return (int)id->driver_data; + return id->driver_data; } static int sec_pmic_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 8e9bbb1083d4..5073d81660e7 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -51,7 +51,7 @@ struct sec_pmic_dev { struct regmap_irq_chip_data *irq_data; int ono; - int type; + unsigned long type; bool wakeup; bool wtsr_smpl; }; -- cgit v1.2.3 From ce24991e1e4d7bee05bcc0e156b0b1c2ef791dd3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 14 Mar 2014 17:21:57 +0530 Subject: mfd: Add support for S2MPA01 device Add the necessary entries required for S2MPA01 multi-function device. While at it also convert whitespaces to tabs in core.h. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 49 ++++++++- include/linux/mfd/samsung/core.h | 16 ++- include/linux/mfd/samsung/irq.h | 50 ++++++++++ include/linux/mfd/samsung/s2mpa01.h | 192 ++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+), 10 deletions(-) create mode 100644 include/linux/mfd/samsung/s2mpa01.h (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 3fc3ebdd7b8a..281a82747275 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -80,21 +81,43 @@ static const struct mfd_cell s2mps14_devs[] = { } }; +static const struct mfd_cell s2mpa01_devs[] = { + { + .name = "s2mpa01-pmic", + }, +}; + #ifdef CONFIG_OF static struct of_device_id sec_dt_match[] = { { .compatible = "samsung,s5m8767-pmic", .data = (void *)S5M8767X, - }, - { .compatible = "samsung,s2mps11-pmic", + }, { + .compatible = "samsung,s2mps11-pmic", .data = (void *)S2MPS11X, - }, - { .compatible = "samsung,s2mps14-pmic", + }, { + .compatible = "samsung,s2mps14-pmic", .data = (void *)S2MPS14X, + }, { + .compatible = "samsung,s2mpa01-pmic", + .data = (void *)S2MPA01, + }, { + /* Sentinel */ }, - {}, }; #endif +static bool s2mpa01_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case S2MPA01_REG_INT1M: + case S2MPA01_REG_INT2M: + case S2MPA01_REG_INT3M: + return false; + default: + return true; + } +} + static bool s2mps11_volatile(struct device *dev, unsigned int reg) { switch (reg) { @@ -125,6 +148,15 @@ static const struct regmap_config sec_regmap_config = { .val_bits = 8, }; +static const struct regmap_config s2mpa01_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPA01_REG_LDO_OVCB4, + .volatile_reg = s2mpa01_volatile, + .cache_type = REGCACHE_FLAT, +}; + static const struct regmap_config s2mps11_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -261,6 +293,9 @@ static int sec_pmic_probe(struct i2c_client *i2c, } switch (sec_pmic->device_type) { + case S2MPA01: + regmap = &s2mpa01_regmap_config; + break; case S2MPS11X: regmap = &s2mps11_regmap_config; /* @@ -332,6 +367,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); break; + case S2MPA01: + ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs, + ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL); + break; case S2MPS11X: ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 5073d81660e7..900bc9e1888b 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -18,6 +18,7 @@ enum sec_device_type { S5M8751X, S5M8763X, S5M8767X, + S2MPA01, S2MPS11X, S2MPS14X, }; @@ -93,7 +94,7 @@ struct sec_platform_data { int buck3_default_idx; int buck4_default_idx; - int buck_ramp_delay; + int buck_ramp_delay; int buck2_ramp_delay; int buck34_ramp_delay; @@ -101,10 +102,15 @@ struct sec_platform_data { int buck16_ramp_delay; int buck7810_ramp_delay; int buck9_ramp_delay; - - bool buck2_ramp_enable; - bool buck3_ramp_enable; - bool buck4_ramp_enable; + int buck24_ramp_delay; + int buck3_ramp_delay; + int buck7_ramp_delay; + int buck8910_ramp_delay; + + bool buck1_ramp_enable; + bool buck2_ramp_enable; + bool buck3_ramp_enable; + bool buck4_ramp_enable; bool buck6_ramp_enable; int buck2_init; diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h index 0065f6f1daf4..1224f447356b 100644 --- a/include/linux/mfd/samsung/irq.h +++ b/include/linux/mfd/samsung/irq.h @@ -13,6 +13,56 @@ #ifndef __LINUX_MFD_SEC_IRQ_H #define __LINUX_MFD_SEC_IRQ_H +enum s2mpa01_irq { + S2MPA01_IRQ_PWRONF, + S2MPA01_IRQ_PWRONR, + S2MPA01_IRQ_JIGONBF, + S2MPA01_IRQ_JIGONBR, + S2MPA01_IRQ_ACOKBF, + S2MPA01_IRQ_ACOKBR, + S2MPA01_IRQ_PWRON1S, + S2MPA01_IRQ_MRB, + + S2MPA01_IRQ_RTC60S, + S2MPA01_IRQ_RTCA1, + S2MPA01_IRQ_RTCA0, + S2MPA01_IRQ_SMPL, + S2MPA01_IRQ_RTC1S, + S2MPA01_IRQ_WTSR, + + S2MPA01_IRQ_INT120C, + S2MPA01_IRQ_INT140C, + S2MPA01_IRQ_LDO3_TSD, + S2MPA01_IRQ_B16_TSD, + S2MPA01_IRQ_B24_TSD, + S2MPA01_IRQ_B35_TSD, + + S2MPA01_IRQ_NR, +}; + +#define S2MPA01_IRQ_PWRONF_MASK (1 << 0) +#define S2MPA01_IRQ_PWRONR_MASK (1 << 1) +#define S2MPA01_IRQ_JIGONBF_MASK (1 << 2) +#define S2MPA01_IRQ_JIGONBR_MASK (1 << 3) +#define S2MPA01_IRQ_ACOKBF_MASK (1 << 4) +#define S2MPA01_IRQ_ACOKBR_MASK (1 << 5) +#define S2MPA01_IRQ_PWRON1S_MASK (1 << 6) +#define S2MPA01_IRQ_MRB_MASK (1 << 7) + +#define S2MPA01_IRQ_RTC60S_MASK (1 << 0) +#define S2MPA01_IRQ_RTCA1_MASK (1 << 1) +#define S2MPA01_IRQ_RTCA0_MASK (1 << 2) +#define S2MPA01_IRQ_SMPL_MASK (1 << 3) +#define S2MPA01_IRQ_RTC1S_MASK (1 << 4) +#define S2MPA01_IRQ_WTSR_MASK (1 << 5) + +#define S2MPA01_IRQ_INT120C_MASK (1 << 0) +#define S2MPA01_IRQ_INT140C_MASK (1 << 1) +#define S2MPA01_IRQ_LDO3_TSD_MASK (1 << 2) +#define S2MPA01_IRQ_B16_TSD_MASK (1 << 3) +#define S2MPA01_IRQ_B24_TSD_MASK (1 << 4) +#define S2MPA01_IRQ_B35_TSD_MASK (1 << 5) + enum s2mps11_irq { S2MPS11_IRQ_PWRONF, S2MPS11_IRQ_PWRONR, diff --git a/include/linux/mfd/samsung/s2mpa01.h b/include/linux/mfd/samsung/s2mpa01.h new file mode 100644 index 000000000000..fbc63bc0d6a2 --- /dev/null +++ b/include/linux/mfd/samsung/s2mpa01.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_S2MPA01_H +#define __LINUX_MFD_S2MPA01_H + +/* S2MPA01 registers */ +enum s2mpa01_reg { + S2MPA01_REG_ID, + S2MPA01_REG_INT1, + S2MPA01_REG_INT2, + S2MPA01_REG_INT3, + S2MPA01_REG_INT1M, + S2MPA01_REG_INT2M, + S2MPA01_REG_INT3M, + S2MPA01_REG_ST1, + S2MPA01_REG_ST2, + S2MPA01_REG_PWRONSRC, + S2MPA01_REG_OFFSRC, + S2MPA01_REG_RTC_BUF, + S2MPA01_REG_CTRL1, + S2MPA01_REG_ETC_TEST, + S2MPA01_REG_RSVD1, + S2MPA01_REG_BU_CHG, + S2MPA01_REG_RAMP1, + S2MPA01_REG_RAMP2, + S2MPA01_REG_LDO_DSCH1, + S2MPA01_REG_LDO_DSCH2, + S2MPA01_REG_LDO_DSCH3, + S2MPA01_REG_LDO_DSCH4, + S2MPA01_REG_OTP_ADRL, + S2MPA01_REG_OTP_ADRH, + S2MPA01_REG_OTP_DATA, + S2MPA01_REG_MON1SEL, + S2MPA01_REG_MON2SEL, + S2MPA01_REG_LEE, + S2MPA01_REG_RSVD2, + S2MPA01_REG_RSVD3, + S2MPA01_REG_RSVD4, + S2MPA01_REG_RSVD5, + S2MPA01_REG_RSVD6, + S2MPA01_REG_TOP_RSVD, + S2MPA01_REG_DVS_SEL, + S2MPA01_REG_DVS_PTR, + S2MPA01_REG_DVS_DATA, + S2MPA01_REG_RSVD_NO, + S2MPA01_REG_UVLO, + S2MPA01_REG_LEE_NO, + S2MPA01_REG_B1CTRL1, + S2MPA01_REG_B1CTRL2, + S2MPA01_REG_B2CTRL1, + S2MPA01_REG_B2CTRL2, + S2MPA01_REG_B3CTRL1, + S2MPA01_REG_B3CTRL2, + S2MPA01_REG_B4CTRL1, + S2MPA01_REG_B4CTRL2, + S2MPA01_REG_B5CTRL1, + S2MPA01_REG_B5CTRL2, + S2MPA01_REG_B5CTRL3, + S2MPA01_REG_B5CTRL4, + S2MPA01_REG_B5CTRL5, + S2MPA01_REG_B5CTRL6, + S2MPA01_REG_B6CTRL1, + S2MPA01_REG_B6CTRL2, + S2MPA01_REG_B7CTRL1, + S2MPA01_REG_B7CTRL2, + S2MPA01_REG_B8CTRL1, + S2MPA01_REG_B8CTRL2, + S2MPA01_REG_B9CTRL1, + S2MPA01_REG_B9CTRL2, + S2MPA01_REG_B10CTRL1, + S2MPA01_REG_B10CTRL2, + S2MPA01_REG_L1CTRL, + S2MPA01_REG_L2CTRL, + S2MPA01_REG_L3CTRL, + S2MPA01_REG_L4CTRL, + S2MPA01_REG_L5CTRL, + S2MPA01_REG_L6CTRL, + S2MPA01_REG_L7CTRL, + S2MPA01_REG_L8CTRL, + S2MPA01_REG_L9CTRL, + S2MPA01_REG_L10CTRL, + S2MPA01_REG_L11CTRL, + S2MPA01_REG_L12CTRL, + S2MPA01_REG_L13CTRL, + S2MPA01_REG_L14CTRL, + S2MPA01_REG_L15CTRL, + S2MPA01_REG_L16CTRL, + S2MPA01_REG_L17CTRL, + S2MPA01_REG_L18CTRL, + S2MPA01_REG_L19CTRL, + S2MPA01_REG_L20CTRL, + S2MPA01_REG_L21CTRL, + S2MPA01_REG_L22CTRL, + S2MPA01_REG_L23CTRL, + S2MPA01_REG_L24CTRL, + S2MPA01_REG_L25CTRL, + S2MPA01_REG_L26CTRL, + + S2MPA01_REG_LDO_OVCB1, + S2MPA01_REG_LDO_OVCB2, + S2MPA01_REG_LDO_OVCB3, + S2MPA01_REG_LDO_OVCB4, + +}; + +/* S2MPA01 regulator ids */ +enum s2mpa01_regulators { + S2MPA01_LDO1, + S2MPA01_LDO2, + S2MPA01_LDO3, + S2MPA01_LDO4, + S2MPA01_LDO5, + S2MPA01_LDO6, + S2MPA01_LDO7, + S2MPA01_LDO8, + S2MPA01_LDO9, + S2MPA01_LDO10, + S2MPA01_LDO11, + S2MPA01_LDO12, + S2MPA01_LDO13, + S2MPA01_LDO14, + S2MPA01_LDO15, + S2MPA01_LDO16, + S2MPA01_LDO17, + S2MPA01_LDO18, + S2MPA01_LDO19, + S2MPA01_LDO20, + S2MPA01_LDO21, + S2MPA01_LDO22, + S2MPA01_LDO23, + S2MPA01_LDO24, + S2MPA01_LDO25, + S2MPA01_LDO26, + + S2MPA01_BUCK1, + S2MPA01_BUCK2, + S2MPA01_BUCK3, + S2MPA01_BUCK4, + S2MPA01_BUCK5, + S2MPA01_BUCK6, + S2MPA01_BUCK7, + S2MPA01_BUCK8, + S2MPA01_BUCK9, + S2MPA01_BUCK10, + + S2MPA01_REGULATOR_MAX, +}; + +#define S2MPA01_BUCK_MIN1 600000 +#define S2MPA01_BUCK_MIN2 800000 +#define S2MPA01_BUCK_MIN3 1000000 +#define S2MPA01_BUCK_MIN4 1500000 +#define S2MPA01_LDO_MIN 800000 + +#define S2MPA01_BUCK_STEP1 6250 +#define S2MPA01_BUCK_STEP2 12500 + +#define S2MPA01_LDO_STEP1 50000 +#define S2MPA01_LDO_STEP2 25000 + +#define S2MPA01_LDO_VSEL_MASK 0x3F +#define S2MPA01_BUCK_VSEL_MASK 0xFF +#define S2MPA01_ENABLE_MASK (0x03 << S2MPA01_ENABLE_SHIFT) +#define S2MPA01_ENABLE_SHIFT 0x06 +#define S2MPA01_LDO_N_VOLTAGES (S2MPA01_LDO_VSEL_MASK + 1) +#define S2MPA01_BUCK_N_VOLTAGES (S2MPA01_BUCK_VSEL_MASK + 1) + +#define S2MPA01_RAMP_DELAY 12500 /* uV/us */ + +#define S2MPA01_BUCK16_RAMP_SHIFT 4 +#define S2MPA01_BUCK24_RAMP_SHIFT 6 +#define S2MPA01_BUCK3_RAMP_SHIFT 4 +#define S2MPA01_BUCK5_RAMP_SHIFT 6 +#define S2MPA01_BUCK7_RAMP_SHIFT 2 +#define S2MPA01_BUCK8910_RAMP_SHIFT 0 + +#define S2MPA01_BUCK1_RAMP_EN_SHIFT 3 +#define S2MPA01_BUCK2_RAMP_EN_SHIFT 2 +#define S2MPA01_BUCK3_RAMP_EN_SHIFT 1 +#define S2MPA01_BUCK4_RAMP_EN_SHIFT 0 +#define S2MPA01_PMIC_EN_SHIFT 6 + +#endif /*__LINUX_MFD_S2MPA01_H */ -- cgit v1.2.3