From 9e4808d2c6a6660d5d2cd572e689570df14a8472 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 20 Nov 2015 16:07:51 +0530 Subject: [PATCH 1/3] mfd: sec: Add support for S2MPS15 PMIC Add support for S2MPS15 PMIC which is similar to S2MPS11 PMIC. The S2MPS15 PMIC supports 27 LDO regulators, 10 buck regulators, RTC, three 32.768KHz clock outputs and battery charger. This patch adds initial support for LDO and buck regulators of S2MPS15 device. Signed-off-by: Thomas Abraham Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski [Alim: Added s2mps15_devs like rtc and clk and related changes] Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 31 ++++++ drivers/mfd/sec-irq.c | 8 ++ include/linux/mfd/samsung/core.h | 1 + include/linux/mfd/samsung/s2mps15.h | 158 ++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 include/linux/mfd/samsung/s2mps15.h diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 989076d6cb83..7c4e7be17f1e 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,17 @@ static const struct mfd_cell s2mps14_devs[] = { } }; +static const struct mfd_cell s2mps15_devs[] = { + { + .name = "s2mps15-regulator", + }, { + .name = "s2mps15-rtc", + }, { + .name = "s2mps13-clk", + .of_compatible = "samsung,s2mps13-clk", + }, +}; + static const struct mfd_cell s2mpa01_devs[] = { { .name = "s2mpa01-pmic", @@ -121,6 +133,9 @@ static const struct of_device_id sec_dt_match[] = { }, { .compatible = "samsung,s2mps14-pmic", .data = (void *)S2MPS14X, + }, { + .compatible = "samsung,s2mps15-pmic", + .data = (void *)S2MPS15X, }, { .compatible = "samsung,s2mpa01-pmic", .data = (void *)S2MPA01, @@ -223,6 +238,15 @@ static const struct regmap_config s2mps14_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static const struct regmap_config s2mps15_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS15_REG_LDODSCH4, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + static const struct regmap_config s2mpu02_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -384,6 +408,9 @@ static int sec_pmic_probe(struct i2c_client *i2c, case S2MPS14X: regmap = &s2mps14_regmap_config; break; + case S2MPS15X: + regmap = &s2mps15_regmap_config; + break; case S5M8763X: regmap = &s5m8763_regmap_config; break; @@ -442,6 +469,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_devs = s2mps14_devs; num_sec_devs = ARRAY_SIZE(s2mps14_devs); break; + case S2MPS15X: + sec_devs = s2mps15_devs; + num_sec_devs = ARRAY_SIZE(s2mps15_devs); + break; case S2MPU02: sec_devs = s2mpu02_devs; num_sec_devs = ARRAY_SIZE(s2mpu02_devs); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 806fa8dbb22d..d77de431cc50 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -407,6 +407,11 @@ static const struct regmap_irq_chip s2mps14_irq_chip = { S2MPS1X_IRQ_CHIP_COMMON_DATA, }; +static const struct regmap_irq_chip s2mps15_irq_chip = { + .name = "s2mps15", + S2MPS1X_IRQ_CHIP_COMMON_DATA, +}; + static const struct regmap_irq_chip s2mpu02_irq_chip = { .name = "s2mpu02", .irqs = s2mpu02_irqs, @@ -466,6 +471,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) case S2MPS14X: sec_irq_chip = &s2mps14_irq_chip; break; + case S2MPS15X: + sec_irq_chip = &s2mps15_irq_chip; + break; case S2MPU02: sec_irq_chip = &s2mpu02_irq_chip; break; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index a06098639399..6bc4bcd488ac 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -44,6 +44,7 @@ enum sec_device_type { S2MPS11X, S2MPS13X, S2MPS14X, + S2MPS15X, S2MPU02, }; diff --git a/include/linux/mfd/samsung/s2mps15.h b/include/linux/mfd/samsung/s2mps15.h new file mode 100644 index 000000000000..36d35287c3c0 --- /dev/null +++ b/include/linux/mfd/samsung/s2mps15.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015 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_S2MPS15_H +#define __LINUX_MFD_S2MPS15_H + +/* S2MPS15 registers */ +enum s2mps15_reg { + S2MPS15_REG_ID, + S2MPS15_REG_INT1, + S2MPS15_REG_INT2, + S2MPS15_REG_INT3, + S2MPS15_REG_INT1M, + S2MPS15_REG_INT2M, + S2MPS15_REG_INT3M, + S2MPS15_REG_ST1, + S2MPS15_REG_ST2, + S2MPS15_REG_PWRONSRC, + S2MPS15_REG_OFFSRC, + S2MPS15_REG_BU_CHG, + S2MPS15_REG_RTC_BUF, + S2MPS15_REG_CTRL1, + S2MPS15_REG_CTRL2, + S2MPS15_REG_RSVD1, + S2MPS15_REG_RSVD2, + S2MPS15_REG_RSVD3, + S2MPS15_REG_RSVD4, + S2MPS15_REG_RSVD5, + S2MPS15_REG_RSVD6, + S2MPS15_REG_CTRL3, + S2MPS15_REG_RSVD7, + S2MPS15_REG_RSVD8, + S2MPS15_REG_RSVD9, + S2MPS15_REG_B1CTRL1, + S2MPS15_REG_B1CTRL2, + S2MPS15_REG_B2CTRL1, + S2MPS15_REG_B2CTRL2, + S2MPS15_REG_B3CTRL1, + S2MPS15_REG_B3CTRL2, + S2MPS15_REG_B4CTRL1, + S2MPS15_REG_B4CTRL2, + S2MPS15_REG_B5CTRL1, + S2MPS15_REG_B5CTRL2, + S2MPS15_REG_B6CTRL1, + S2MPS15_REG_B6CTRL2, + S2MPS15_REG_B7CTRL1, + S2MPS15_REG_B7CTRL2, + S2MPS15_REG_B8CTRL1, + S2MPS15_REG_B8CTRL2, + S2MPS15_REG_B9CTRL1, + S2MPS15_REG_B9CTRL2, + S2MPS15_REG_B10CTRL1, + S2MPS15_REG_B10CTRL2, + S2MPS15_REG_BBCTRL1, + S2MPS15_REG_BBCTRL2, + S2MPS15_REG_BRAMP, + S2MPS15_REG_LDODVS1, + S2MPS15_REG_LDODVS2, + S2MPS15_REG_LDODVS3, + S2MPS15_REG_LDODVS4, + S2MPS15_REG_L1CTRL, + S2MPS15_REG_L2CTRL, + S2MPS15_REG_L3CTRL, + S2MPS15_REG_L4CTRL, + S2MPS15_REG_L5CTRL, + S2MPS15_REG_L6CTRL, + S2MPS15_REG_L7CTRL, + S2MPS15_REG_L8CTRL, + S2MPS15_REG_L9CTRL, + S2MPS15_REG_L10CTRL, + S2MPS15_REG_L11CTRL, + S2MPS15_REG_L12CTRL, + S2MPS15_REG_L13CTRL, + S2MPS15_REG_L14CTRL, + S2MPS15_REG_L15CTRL, + S2MPS15_REG_L16CTRL, + S2MPS15_REG_L17CTRL, + S2MPS15_REG_L18CTRL, + S2MPS15_REG_L19CTRL, + S2MPS15_REG_L20CTRL, + S2MPS15_REG_L21CTRL, + S2MPS15_REG_L22CTRL, + S2MPS15_REG_L23CTRL, + S2MPS15_REG_L24CTRL, + S2MPS15_REG_L25CTRL, + S2MPS15_REG_L26CTRL, + S2MPS15_REG_L27CTRL, + S2MPS15_REG_LDODSCH1, + S2MPS15_REG_LDODSCH2, + S2MPS15_REG_LDODSCH3, + S2MPS15_REG_LDODSCH4, +}; + +/* S2MPS15 regulator ids */ +enum s2mps15_regulators { + S2MPS15_LDO1, + S2MPS15_LDO2, + S2MPS15_LDO3, + S2MPS15_LDO4, + S2MPS15_LDO5, + S2MPS15_LDO6, + S2MPS15_LDO7, + S2MPS15_LDO8, + S2MPS15_LDO9, + S2MPS15_LDO10, + S2MPS15_LDO11, + S2MPS15_LDO12, + S2MPS15_LDO13, + S2MPS15_LDO14, + S2MPS15_LDO15, + S2MPS15_LDO16, + S2MPS15_LDO17, + S2MPS15_LDO18, + S2MPS15_LDO19, + S2MPS15_LDO20, + S2MPS15_LDO21, + S2MPS15_LDO22, + S2MPS15_LDO23, + S2MPS15_LDO24, + S2MPS15_LDO25, + S2MPS15_LDO26, + S2MPS15_LDO27, + S2MPS15_BUCK1, + S2MPS15_BUCK2, + S2MPS15_BUCK3, + S2MPS15_BUCK4, + S2MPS15_BUCK5, + S2MPS15_BUCK6, + S2MPS15_BUCK7, + S2MPS15_BUCK8, + S2MPS15_BUCK9, + S2MPS15_BUCK10, + S2MPS15_BUCK11, + S2MPS15_REGULATOR_MAX, +}; + +#define S2MPS15_LDO_VSEL_MASK (0x3F) +#define S2MPS15_BUCK_VSEL_MASK (0xFF) + +#define S2MPS15_ENABLE_SHIFT (0x06) +#define S2MPS15_ENABLE_MASK (0x03 << S2MPS15_ENABLE_SHIFT) + +#define S2MPS15_LDO_N_VOLTAGES (S2MPS15_LDO_VSEL_MASK + 1) +#define S2MPS15_BUCK_N_VOLTAGES (S2MPS15_BUCK_VSEL_MASK + 1) + +#endif /* __LINUX_MFD_S2MPS15_H */ From 51af20675800ffbd97bd48363a06e00f83de44c4 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 20 Nov 2015 16:07:52 +0530 Subject: [PATCH 2/3] regulator: s2mps11: Add support for S2MPS15 regulators The S2MPS15 PMIC is similar in functionality to S2MPS11/14 PMIC. It contains 27 LDO and 10 Buck regulators and allows programming these regulators via a I2C interface. This patch adds initial support for LDO/Buck regulators of S2MPS15 PMIC. Signed-off-by: Thomas Abraham Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Acked-by: Mark Brown Signed-off-by: Lee Jones --- drivers/regulator/Kconfig | 4 +- drivers/regulator/s2mps11.c | 135 +++++++++++++++++++++++++++++++++++- 2 files changed, 136 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8df0b0e62976..2805b014ae31 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -588,10 +588,10 @@ config REGULATOR_S2MPA01 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. config REGULATOR_S2MPS11 - tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator" + tristate "Samsung S2MPS11/13/14/15/S2MPU02 voltage regulator" depends on MFD_SEC_CORE help - This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage + This driver supports a Samsung S2MPS11/13/14/15/S2MPU02 voltage output regulator via I2C bus. The chip is comprised of high efficient Buck converters including Dual-Phase Buck converter, Buck-Boost converter, various LDOs. diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 72fc3c32db49..b2f3a28e720c 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -32,6 +32,7 @@ #include #include #include +#include #include /* The highest number of possible regulators for supported devices. */ @@ -661,6 +662,133 @@ static const struct regulator_desc s2mps14_regulators[] = { S2MPS14_BUCK1235_START_SEL), }; +static struct regulator_ops s2mps15_reg_ldo_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static struct regulator_ops s2mps15_reg_buck_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +#define regulator_desc_s2mps15_ldo(num, range) { \ + .name = "LDO"#num, \ + .id = S2MPS15_LDO##num, \ + .ops = &s2mps15_reg_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .linear_ranges = range, \ + .n_linear_ranges = ARRAY_SIZE(range), \ + .n_voltages = S2MPS15_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS15_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS15_LDO_VSEL_MASK, \ + .enable_reg = S2MPS15_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS15_ENABLE_MASK \ +} + +#define regulator_desc_s2mps15_buck(num, range) { \ + .name = "BUCK"#num, \ + .id = S2MPS15_BUCK##num, \ + .ops = &s2mps15_reg_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .linear_ranges = range, \ + .n_linear_ranges = ARRAY_SIZE(range), \ + .ramp_delay = 12500, \ + .n_voltages = S2MPS15_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPS15_REG_B1CTRL2 + ((num - 1) * 2), \ + .vsel_mask = S2MPS15_BUCK_VSEL_MASK, \ + .enable_reg = S2MPS15_REG_B1CTRL1 + ((num - 1) * 2), \ + .enable_mask = S2MPS15_ENABLE_MASK \ +} + +/* voltage range for s2mps15 LDO 3, 5, 15, 16, 18, 20, 23 and 27 */ +static const struct regulator_linear_range s2mps15_ldo_voltage_ranges1[] = { + REGULATOR_LINEAR_RANGE(1000000, 0xc, 0x38, 25000), +}; + +/* voltage range for s2mps15 LDO 2, 6, 14, 17, 19, 21, 24 and 25 */ +static const struct regulator_linear_range s2mps15_ldo_voltage_ranges2[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x0, 0x3f, 25000), +}; + +/* voltage range for s2mps15 LDO 4, 11, 12, 13, 22 and 26 */ +static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = { + REGULATOR_LINEAR_RANGE(700000, 0x0, 0x34, 12500), +}; + +/* voltage range for s2mps15 LDO 7, 8, 9 and 10 */ +static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = { + REGULATOR_LINEAR_RANGE(700000, 0xc, 0x18, 25000), +}; + +/* voltage range for s2mps15 LDO 1 */ +static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = { + REGULATOR_LINEAR_RANGE(500000, 0x0, 0x20, 12500), +}; + +/* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */ +static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = { + REGULATOR_LINEAR_RANGE(500000, 0x20, 0xb0, 6250), +}; + +/* voltage range for s2mps15 BUCK 8, 9 and 10 */ +static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = { + REGULATOR_LINEAR_RANGE(1000000, 0x20, 0xc0, 12500), +}; + +static const struct regulator_desc s2mps15_regulators[] = { + regulator_desc_s2mps15_ldo(1, s2mps15_ldo_voltage_ranges5), + regulator_desc_s2mps15_ldo(2, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(3, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(4, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(5, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(6, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(7, s2mps15_ldo_voltage_ranges4), + regulator_desc_s2mps15_ldo(8, s2mps15_ldo_voltage_ranges4), + regulator_desc_s2mps15_ldo(9, s2mps15_ldo_voltage_ranges4), + regulator_desc_s2mps15_ldo(10, s2mps15_ldo_voltage_ranges4), + regulator_desc_s2mps15_ldo(11, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(12, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(13, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(14, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(15, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(16, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(17, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(18, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(19, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(20, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(21, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(22, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(23, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_ldo(24, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(25, s2mps15_ldo_voltage_ranges2), + regulator_desc_s2mps15_ldo(26, s2mps15_ldo_voltage_ranges3), + regulator_desc_s2mps15_ldo(27, s2mps15_ldo_voltage_ranges1), + regulator_desc_s2mps15_buck(1, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(2, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(3, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(4, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(5, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(6, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(7, s2mps15_buck_voltage_ranges1), + regulator_desc_s2mps15_buck(8, s2mps15_buck_voltage_ranges2), + regulator_desc_s2mps15_buck(9, s2mps15_buck_voltage_ranges2), + regulator_desc_s2mps15_buck(10, s2mps15_buck_voltage_ranges2), +}; + static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, struct regulator_dev *rdev) { @@ -974,6 +1102,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) regulators = s2mps14_regulators; BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; + case S2MPS15X: + s2mps11->rdev_num = ARRAY_SIZE(s2mps15_regulators); + regulators = s2mps15_regulators; + break; case S2MPU02: s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators); regulators = s2mpu02_regulators; @@ -1070,6 +1202,7 @@ static const struct platform_device_id s2mps11_pmic_id[] = { { "s2mps11-pmic", S2MPS11X}, { "s2mps13-pmic", S2MPS13X}, { "s2mps14-pmic", S2MPS14X}, + { "s2mps15-regulator", S2MPS15X}, { "s2mpu02-pmic", S2MPU02}, { }, }; @@ -1097,5 +1230,5 @@ module_exit(s2mps11_pmic_exit); /* Module information */ MODULE_AUTHOR("Sangbeom Kim "); -MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPU02 Regulator Driver"); +MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver"); MODULE_LICENSE("GPL"); From a65e5efa7c5faa8c320fe56cc351d47fcd006749 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Fri, 20 Nov 2015 16:07:53 +0530 Subject: [PATCH 3/3] rtc: s5m.c: Add support for S2MPS15 RTC RTC found in s2mps15 is almost same as one found on s2mps13 with few differences in RTC_UPDATE register fields, like: 1> Bit[4] and Bit[1] are reversed - On s2mps13 WUDR -> bit[4], AUDR -> bit[1] - On s2mps15 WUDR -> bit[1], AUDR -> bit[4] 2> In case of s2mps13, for alarm register, need to set both WDUR and ADUR high, whereas for s2mps15 only set AUDR to high. 3> On s2mps15, WUDR, RUDR and AUDR functions should never be used at the same time. This patch add required changes to enable s2mps15 rtc timer. Signed-off-by: Alim Akhtar Reviewed-by: Krzysztof Kozlowski Acked-by: Alexandre Belloni Signed-off-by: Lee Jones --- drivers/rtc/rtc-s5m.c | 37 +++++++++++++++++++++++++++++---- include/linux/mfd/samsung/rtc.h | 2 ++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index f2504b4eef34..0d68a85dd429 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -188,6 +188,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); val &= S5M_ALARM0_STATUS; break; + case S2MPS15X: case S2MPS14X: case S2MPS13X: ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, @@ -219,9 +220,22 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) return ret; } - data |= info->regs->rtc_udr_mask; - if (info->device_type == S5M8763X || info->device_type == S5M8767X) - data |= S5M_RTC_TIME_EN_MASK; + switch (info->device_type) { + case S5M8763X: + case S5M8767X: + data |= info->regs->rtc_udr_mask | S5M_RTC_TIME_EN_MASK; + case S2MPS15X: + /* As per UM, for write time register, set WUDR bit to high */ + data |= S2MPS15_RTC_WUDR_MASK; + break; + case S2MPS14X: + case S2MPS13X: + data |= info->regs->rtc_udr_mask; + break; + default: + return -EINVAL; + } + ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data); if (ret < 0) { @@ -252,6 +266,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) case S5M8767X: data &= ~S5M_RTC_TIME_EN_MASK; break; + case S2MPS15X: + /* As per UM, for write alarm, set A_UDR(bit[4]) to high + * rtc_udr_mask above sets bit[4] + */ + break; case S2MPS14X: data |= S2MPS_RTC_RUDR_MASK; break; @@ -317,7 +336,8 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 data[info->regs->regs_count]; int ret; - if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) { + if (info->device_type == S2MPS15X || info->device_type == S2MPS14X || + info->device_type == S2MPS13X) { ret = regmap_update_bits(info->regmap, info->regs->rtc_udr_update, S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK); @@ -339,6 +359,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); @@ -366,6 +387,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) s5m8763_tm_to_data(tm, data); break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: ret = s5m8767_tm_to_data(tm, data); @@ -414,6 +436,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); @@ -463,6 +486,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: for (i = 0; i < info->regs->regs_count; i++) @@ -508,6 +532,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: data[RTC_SEC] |= ALARM_ENABLE_MASK; @@ -548,6 +573,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) break; case S5M8767X: + case S2MPS15X: case S2MPS14X: case S2MPS13X: s5m8767_tm_to_data(&alrm->time, data); @@ -631,6 +657,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2); break; + case S2MPS15X: case S2MPS14X: case S2MPS13X: data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); @@ -679,6 +706,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) return -ENOMEM; switch (platform_get_device_id(pdev)->driver_data) { + case S2MPS15X: case S2MPS14X: case S2MPS13X: regmap_cfg = &s2mps14_rtc_regmap_config; @@ -805,6 +833,7 @@ static const struct platform_device_id s5m_rtc_id[] = { { "s5m-rtc", S5M8767X }, { "s2mps13-rtc", S2MPS13X }, { "s2mps14-rtc", S2MPS14X }, + { "s2mps15-rtc", S2MPS15X }, { }, }; MODULE_DEVICE_TABLE(platform, s5m_rtc_id); diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index 29c30ac36020..a65e4655d470 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -107,6 +107,8 @@ enum s2mps_rtc_reg { #define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) #define S2MPS13_RTC_AUDR_SHIFT 1 #define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT) +#define S2MPS15_RTC_WUDR_SHIFT 1 +#define S2MPS15_RTC_WUDR_MASK (1 << S2MPS15_RTC_WUDR_SHIFT) #define S2MPS_RTC_RUDR_SHIFT 0 #define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) #define RTC_TCON_SHIFT 1