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 <[email protected]>
---
* Fixed nits pointed out by Lee.
---
drivers/mfd/sec-core.c | 45 +++++++-
include/linux/mfd/samsung/core.h | 16 ++-
include/linux/mfd/samsung/irq.h | 50 +++++++++
include/linux/mfd/samsung/s2mpa01.h | 192 +++++++++++++++++++++++++++++++++++
4 files changed, 295 insertions(+), 8 deletions(-)
create mode 100644 include/linux/mfd/samsung/s2mpa01.h
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index a139798b8065..564265c57fd9 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -26,6 +26,7 @@
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/rtc.h>
+#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
@@ -69,18 +70,40 @@ static const struct mfd_cell s2mps11_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,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) {
@@ -111,6 +134,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,
@@ -229,6 +261,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;
break;
@@ -283,6 +318,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 41c9bde410c5..db165f8712d3 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,
};
@@ -92,7 +93,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;
@@ -100,10 +101,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 d43b4f9e7fb2..2ca965948cd4 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 */
--
1.7.9.5
Add support for S2MPA01 voltage and current regulator.
Signed-off-by: Sachin Kamat <[email protected]>
---
* Addressed comments from Mark Brown
- Used module_platform_driver instead of subsys init call
---
drivers/regulator/Kconfig | 7 +
drivers/regulator/Makefile | 1 +
drivers/regulator/s2mpa01.c | 482 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 490 insertions(+)
create mode 100644 drivers/regulator/s2mpa01.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a7932822e37..8f8e6710bb45 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -416,6 +416,13 @@ config REGULATOR_RC5T583
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
+config REGULATOR_S2MPA01
+ tristate "Samsung S2MPA01 voltage regulator"
+ depends on MFD_SEC_CORE
+ help
+ This driver controls Samsung S2MPA01 voltage output regulator
+ via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
+
config REGULATOR_S2MPS11
tristate "Samsung S2MPS11 voltage regulator"
depends on MFD_SEC_CORE
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9ddcf259..b3ece84289cf 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
+obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
new file mode 100644
index 000000000000..2d544aeb3419
--- /dev/null
+++ b/drivers/regulator/s2mpa01.c
@@ -0,0 +1,482 @@
+/*
+ * 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.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mpa01.h>
+
+#define S2MPA01_REGULATOR_CNT ARRAY_SIZE(regulators)
+
+struct s2mpa01_info {
+ struct regulator_dev *rdev[S2MPA01_REGULATOR_MAX];
+
+ int ramp_delay24;
+ int ramp_delay3;
+ int ramp_delay5;
+ int ramp_delay16;
+ int ramp_delay7;
+ int ramp_delay8910;
+};
+
+static int get_ramp_delay(int ramp_delay)
+{
+ unsigned char cnt = 0;
+
+ ramp_delay /= 6250;
+
+ while (true) {
+ ramp_delay = ramp_delay >> 1;
+ if (ramp_delay == 0)
+ break;
+ cnt++;
+ }
+
+ if (cnt > 3)
+ cnt = 3;
+
+ return cnt;
+}
+
+static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
+ unsigned int ramp_delay = 0;
+ int old_volt, new_volt;
+
+ switch (rdev->desc->id) {
+ case S2MPA01_BUCK2:
+ case S2MPA01_BUCK4:
+ ramp_delay = s2mpa01->ramp_delay24;
+ break;
+ case S2MPA01_BUCK3:
+ ramp_delay = s2mpa01->ramp_delay3;
+ break;
+ case S2MPA01_BUCK5:
+ ramp_delay = s2mpa01->ramp_delay5;
+ break;
+ case S2MPA01_BUCK1:
+ case S2MPA01_BUCK6:
+ ramp_delay = s2mpa01->ramp_delay16;
+ break;
+ case S2MPA01_BUCK7:
+ ramp_delay = s2mpa01->ramp_delay7;
+ break;
+ case S2MPA01_BUCK8:
+ case S2MPA01_BUCK9:
+ case S2MPA01_BUCK10:
+ ramp_delay = s2mpa01->ramp_delay8910;
+ break;
+ }
+
+ if (ramp_delay == 0)
+ ramp_delay = rdev->desc->ramp_delay;
+
+ old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector);
+ new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector);
+
+ return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+
+static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev);
+ unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2;
+ unsigned int ramp_enable = 1, enable_shift = 0;
+ int ret;
+
+ switch (rdev->desc->id) {
+ case S2MPA01_BUCK1:
+ enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT;
+ if (!ramp_delay) {
+ ramp_enable = 0;
+ break;
+ }
+
+ if (ramp_delay > s2mpa01->ramp_delay16)
+ s2mpa01->ramp_delay16 = ramp_delay;
+ else
+ ramp_delay = s2mpa01->ramp_delay16;
+
+ ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
+ ramp_reg = S2MPA01_REG_RAMP1;
+ break;
+ case S2MPA01_BUCK2:
+ enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT;
+ if (!ramp_delay) {
+ ramp_enable = 0;
+ break;
+ }
+
+ if (ramp_delay > s2mpa01->ramp_delay24)
+ s2mpa01->ramp_delay24 = ramp_delay;
+ else
+ ramp_delay = s2mpa01->ramp_delay24;
+
+ ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
+ ramp_reg = S2MPA01_REG_RAMP1;
+ break;
+ case S2MPA01_BUCK3:
+ enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT;
+ if (!ramp_delay) {
+ ramp_enable = 0;
+ break;
+ }
+
+ s2mpa01->ramp_delay3 = ramp_delay;
+ ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT;
+ ramp_reg = S2MPA01_REG_RAMP1;
+ break;
+ case S2MPA01_BUCK4:
+ enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT;
+ if (!ramp_delay) {
+ ramp_enable = 0;
+ break;
+ }
+
+ if (ramp_delay > s2mpa01->ramp_delay24)
+ s2mpa01->ramp_delay24 = ramp_delay;
+ else
+ ramp_delay = s2mpa01->ramp_delay24;
+
+ ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT;
+ ramp_reg = S2MPA01_REG_RAMP1;
+ break;
+ case S2MPA01_BUCK5:
+ s2mpa01->ramp_delay5 = ramp_delay;
+ ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT;
+ break;
+ case S2MPA01_BUCK6:
+ if (ramp_delay > s2mpa01->ramp_delay16)
+ s2mpa01->ramp_delay16 = ramp_delay;
+ else
+ ramp_delay = s2mpa01->ramp_delay16;
+
+ ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
+ break;
+ case S2MPA01_BUCK7:
+ s2mpa01->ramp_delay7 = ramp_delay;
+ ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT;
+ break;
+ case S2MPA01_BUCK8:
+ case S2MPA01_BUCK9:
+ case S2MPA01_BUCK10:
+ if (ramp_delay > s2mpa01->ramp_delay8910)
+ s2mpa01->ramp_delay8910 = ramp_delay;
+ else
+ ramp_delay = s2mpa01->ramp_delay8910;
+
+ ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!ramp_enable)
+ goto ramp_disable;
+
+ if (enable_shift) {
+ ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
+ 1 << enable_shift, 1 << enable_shift);
+ if (ret) {
+ dev_err(&rdev->dev, "failed to enable ramp rate\n");
+ return ret;
+ }
+ }
+
+ ramp_val = get_ramp_delay(ramp_delay);
+
+ return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift,
+ ramp_val << ramp_shift);
+
+ramp_disable:
+ return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
+ 1 << enable_shift, 0);
+}
+
+static struct regulator_ops s2mpa01_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .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,
+};
+
+static struct regulator_ops s2mpa01_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .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 = s2mpa01_regulator_set_voltage_time_sel,
+ .set_ramp_delay = s2mpa01_set_ramp_delay,
+};
+
+#define regulator_desc_ldo1(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPA01_LDO##num, \
+ .ops = &s2mpa01_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_LDO_MIN, \
+ .uV_step = S2MPA01_LDO_STEP1, \
+ .n_voltages = S2MPA01_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \
+ .vsel_mask = S2MPA01_LDO_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+#define regulator_desc_ldo2(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPA01_LDO##num, \
+ .ops = &s2mpa01_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_LDO_MIN, \
+ .uV_step = S2MPA01_LDO_STEP2, \
+ .n_voltages = S2MPA01_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \
+ .vsel_mask = S2MPA01_LDO_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck1_4(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPA01_BUCK##num, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN1, \
+ .uV_step = S2MPA01_BUCK_STEP1, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B1CTRL2 + (num - 1) * 2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B1CTRL1 + (num - 1) * 2, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck5 { \
+ .name = "BUCK5", \
+ .id = S2MPA01_BUCK5, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN2, \
+ .uV_step = S2MPA01_BUCK_STEP1, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B5CTRL2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B5CTRL1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck6_7(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPA01_BUCK##num, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN1, \
+ .uV_step = S2MPA01_BUCK_STEP1, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B6CTRL2 + (num - 6) * 2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B6CTRL1 + (num - 6) * 2, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck8 { \
+ .name = "BUCK8", \
+ .id = S2MPA01_BUCK8, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN2, \
+ .uV_step = S2MPA01_BUCK_STEP2, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B8CTRL2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B8CTRL1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck9 { \
+ .name = "BUCK9", \
+ .id = S2MPA01_BUCK9, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN4, \
+ .uV_step = S2MPA01_BUCK_STEP2, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B9CTRL2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B9CTRL1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+#define regulator_desc_buck10 { \
+ .name = "BUCK10", \
+ .id = S2MPA01_BUCK10, \
+ .ops = &s2mpa01_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPA01_BUCK_MIN3, \
+ .uV_step = S2MPA01_BUCK_STEP2, \
+ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPA01_RAMP_DELAY, \
+ .vsel_reg = S2MPA01_REG_B10CTRL2, \
+ .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPA01_REG_B10CTRL1, \
+ .enable_mask = S2MPA01_ENABLE_MASK \
+}
+
+static struct regulator_desc regulators[] = {
+ regulator_desc_ldo2(1),
+ regulator_desc_ldo1(2),
+ regulator_desc_ldo1(3),
+ regulator_desc_ldo1(4),
+ regulator_desc_ldo1(5),
+ regulator_desc_ldo2(6),
+ regulator_desc_ldo1(7),
+ regulator_desc_ldo1(8),
+ regulator_desc_ldo1(9),
+ regulator_desc_ldo1(10),
+ regulator_desc_ldo2(11),
+ regulator_desc_ldo1(12),
+ regulator_desc_ldo1(13),
+ regulator_desc_ldo1(14),
+ regulator_desc_ldo1(15),
+ regulator_desc_ldo1(16),
+ regulator_desc_ldo1(17),
+ regulator_desc_ldo1(18),
+ regulator_desc_ldo1(19),
+ regulator_desc_ldo1(20),
+ regulator_desc_ldo1(21),
+ regulator_desc_ldo2(22),
+ regulator_desc_ldo2(23),
+ regulator_desc_ldo1(24),
+ regulator_desc_ldo1(25),
+ regulator_desc_ldo1(26),
+ regulator_desc_buck1_4(1),
+ regulator_desc_buck1_4(2),
+ regulator_desc_buck1_4(3),
+ regulator_desc_buck1_4(4),
+ regulator_desc_buck5,
+ regulator_desc_buck6_7(6),
+ regulator_desc_buck6_7(7),
+ regulator_desc_buck8,
+ regulator_desc_buck9,
+ regulator_desc_buck10,
+};
+
+static int s2mpa01_pmic_probe(struct platform_device *pdev)
+{
+ struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
+ struct device_node *reg_np = NULL;
+ struct regulator_config config = { };
+ struct s2mpa01_info *s2mpa01;
+ int i, ret;
+
+ s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL);
+ if (!s2mpa01)
+ return -ENOMEM;
+
+ for (i = 0; i < S2MPA01_REGULATOR_CNT; i++)
+ rdata[i].name = regulators[i].name;
+
+ if (iodev->dev->of_node) {
+ reg_np = of_find_node_by_name(iodev->dev->of_node,
+ "regulators");
+ if (!reg_np) {
+ dev_err(&pdev->dev,
+ "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ of_regulator_match(&pdev->dev, reg_np, rdata,
+ S2MPA01_REGULATOR_MAX);
+ }
+
+ platform_set_drvdata(pdev, s2mpa01);
+
+ config.dev = &pdev->dev;
+ config.regmap = iodev->regmap_pmic;
+ config.driver_data = s2mpa01;
+
+ for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) {
+ if (pdata)
+ config.init_data = pdata->regulators[i].initdata;
+ else
+ config.init_data = rdata[i].init_data;
+
+ if (reg_np)
+ config.of_node = rdata[i].of_node;
+
+ s2mpa01->rdev[i] = devm_regulator_register(&pdev->dev,
+ ®ulators[i], &config);
+ if (IS_ERR(s2mpa01->rdev[i])) {
+ ret = PTR_ERR(s2mpa01->rdev[i]);
+ dev_err(&pdev->dev, "regulator init failed for %d\n",
+ i);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id s2mpa01_pmic_id[] = {
+ { "s2mpa01-pmic", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id);
+
+static struct platform_driver s2mpa01_pmic_driver = {
+ .driver = {
+ .name = "s2mpa01-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = s2mpa01_pmic_probe,
+ .id_table = s2mpa01_pmic_id,
+};
+
+module_platform_driver(s2mpa01_pmic_driver);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <[email protected]>");
+MODULE_AUTHOR("Sachin Kamat <[email protected]>");
+MODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver");
+MODULE_LICENSE("GPL");
--
1.7.9.5
Added initial binding documentation for S2MPA01 MFD.
Signed-off-by: Sachin Kamat <[email protected]>
---
* Re-organised as suggested by Mark Rutland.
---
Documentation/devicetree/bindings/mfd/s2mpa01.txt | 86 +++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
new file mode 100644
index 000000000000..70879b92b24b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
@@ -0,0 +1,86 @@
+
+* Samsung S2MPA01 Voltage and Current Regulator
+
+The Samsung S2MPA01 is a multi-function device which includes high
+efficiency buck converters including Dual-Phase buck converter, various LDOs,
+and an RTC. It is interfaced to the host controller using an I2C interface.
+Each sub-block is addressed by the host system using different I2C slave
+addresses.
+
+Required properties:
+- compatible: Should be "samsung,s2mpa01-pmic".
+- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the interrupts from s2mpa01 are delivered to.
+- interrupts: Interrupt specifier for interrupt source (connected to SoC).
+
+Optional nodes:
+- regulators: The regulators of s2mpa01 that have to be instantiated should be
+ included in a sub-node named 'regulators'. Regulator nodes and constraints
+ included in this sub-node use the standard regulator bindings which are
+ documented elsewhere.
+
+Properties for BUCK regulator nodes:
+ regulator-ramp-delay for BUCKs = [6250/12500(default)/25000/50000] uV/us
+
+ BUCK[1/2/3/4] supports disabling ramp delay on hardware, so explictly
+ regulator-ramp-delay = <0> can be used for them to disable ramp delay.
+ In the absence of the regulator-ramp-delay property, the default ramp
+ delay will be used.
+
+ NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
+ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
+ Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
+ BUCK[2, 4], and BUCK[8, 9, 10]
+
+The following are the names of the regulators that the s2mpa01 PMIC block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of s2mpa01.
+
+ - LDOn
+ - valid values for n are 1 to 26
+ - Example: LDO1, LD02, LDO26
+ - BUCKn
+ - valid values for n are 1 to 10.
+ - Example: BUCK1, BUCK2, BUCK9
+
+Example:
+
+ s2mpa01_pmic@66 {
+ compatible = "samsung,s2mpa01-pmic";
+ reg = <0x66>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ALIVE";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDDQ_MMC2";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "vdd_mif";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-ramp-delay = <50000>;
+ };
+ };
+ };
--
1.7.9.5
On Thu, Jan 09, 2014 at 04:52:33PM +0530, Sachin Kamat wrote:
> Add support for S2MPA01 voltage and current regulator.
Acked-by: Mark Brown <[email protected]>
> 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 <[email protected]>
> ---
> * Fixed nits pointed out by Lee.
> ---
> drivers/mfd/sec-core.c | 45 +++++++-
> include/linux/mfd/samsung/core.h | 16 ++-
> include/linux/mfd/samsung/irq.h | 50 +++++++++
> include/linux/mfd/samsung/s2mpa01.h | 192 +++++++++++++++++++++++++++++++++++
> 4 files changed, 295 insertions(+), 8 deletions(-)
> create mode 100644 include/linux/mfd/samsung/s2mpa01.h
Acked-by: Lee Jones <[email protected]>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On 10 January 2014 15:33, Lee Jones <[email protected]> wrote:
>> 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 <[email protected]>
>> ---
>> * Fixed nits pointed out by Lee.
>> ---
>> drivers/mfd/sec-core.c | 45 +++++++-
>> include/linux/mfd/samsung/core.h | 16 ++-
>> include/linux/mfd/samsung/irq.h | 50 +++++++++
>> include/linux/mfd/samsung/s2mpa01.h | 192 +++++++++++++++++++++++++++++++++++
>> 4 files changed, 295 insertions(+), 8 deletions(-)
>> create mode 100644 include/linux/mfd/samsung/s2mpa01.h
>
> Acked-by: Lee Jones <[email protected]>
Thanks Lee.
Btw, how do you plan to handle these patches? Mark has already ack'd
the regulator patch.
--
With warm regards,
Sachin
On Fri, 10 Jan 2014, Sachin Kamat wrote:
> On 10 January 2014 15:33, Lee Jones <[email protected]> wrote:
> >> 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 <[email protected]>
> >> ---
> >> * Fixed nits pointed out by Lee.
> >> ---
> >> drivers/mfd/sec-core.c | 45 +++++++-
> >> include/linux/mfd/samsung/core.h | 16 ++-
> >> include/linux/mfd/samsung/irq.h | 50 +++++++++
> >> include/linux/mfd/samsung/s2mpa01.h | 192 +++++++++++++++++++++++++++++++++++
> >> 4 files changed, 295 insertions(+), 8 deletions(-)
> >> create mode 100644 include/linux/mfd/samsung/s2mpa01.h
> >
> > Acked-by: Lee Jones <[email protected]>
>
> Thanks Lee.
> Btw, how do you plan to handle these patches? Mark has already ack'd
> the regulator patch.
I will take them once we received the Device Tree Ack.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Hi Mark,
On 9 January 2014 16:52, Sachin Kamat <[email protected]> wrote:
> Added initial binding documentation for S2MPA01 MFD.
>
> Signed-off-by: Sachin Kamat <[email protected]>
> ---
> * Re-organised as suggested by Mark Rutland.
> ---
> Documentation/devicetree/bindings/mfd/s2mpa01.txt | 86 +++++++++++++++++++++
> 1 file changed, 86 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
>
Gentle Ping.
--
With warm regards,
Sachin
On 9 January 2014 16:52, Sachin Kamat <[email protected]> wrote:
> Added initial binding documentation for S2MPA01 MFD.
>
> Signed-off-by: Sachin Kamat <[email protected]>
> ---
> * Re-organised as suggested by Mark Rutland.
> ---
> Documentation/devicetree/bindings/mfd/s2mpa01.txt | 86 +++++++++++++++++++++
> 1 file changed, 86 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
> new file mode 100644
> index 000000000000..70879b92b24b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
> @@ -0,0 +1,86 @@
> +
> +* Samsung S2MPA01 Voltage and Current Regulator
> +
> +The Samsung S2MPA01 is a multi-function device which includes high
> +efficiency buck converters including Dual-Phase buck converter, various LDOs,
> +and an RTC. It is interfaced to the host controller using an I2C interface.
> +Each sub-block is addressed by the host system using different I2C slave
> +addresses.
> +
> +Required properties:
> +- compatible: Should be "samsung,s2mpa01-pmic".
> +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
> +
> +Optional properties:
> +- interrupt-parent: Specifies the phandle of the interrupt controller to which
> + the interrupts from s2mpa01 are delivered to.
> +- interrupts: Interrupt specifier for interrupt source (connected to SoC).
> +
> +Optional nodes:
> +- regulators: The regulators of s2mpa01 that have to be instantiated should be
> + included in a sub-node named 'regulators'. Regulator nodes and constraints
> + included in this sub-node use the standard regulator bindings which are
> + documented elsewhere.
> +
> +Properties for BUCK regulator nodes:
> + regulator-ramp-delay for BUCKs = [6250/12500(default)/25000/50000] uV/us
> +
> + BUCK[1/2/3/4] supports disabling ramp delay on hardware, so explictly
> + regulator-ramp-delay = <0> can be used for them to disable ramp delay.
> + In the absence of the regulator-ramp-delay property, the default ramp
> + delay will be used.
> +
> + NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
> + for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
> + Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
> + BUCK[2, 4], and BUCK[8, 9, 10]
> +
> +The following are the names of the regulators that the s2mpa01 PMIC block
> +supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
> +as per the datasheet of s2mpa01.
> +
> + - LDOn
> + - valid values for n are 1 to 26
> + - Example: LDO1, LD02, LDO26
> + - BUCKn
> + - valid values for n are 1 to 10.
> + - Example: BUCK1, BUCK2, BUCK9
> +
> +Example:
> +
> + s2mpa01_pmic@66 {
> + compatible = "samsung,s2mpa01-pmic";
> + reg = <0x66>;
> +
> + regulators {
> + ldo1_reg: LDO1 {
> + regulator-name = "VDD_ALIVE";
> + regulator-min-microvolt = <1000000>;
> + regulator-max-microvolt = <1000000>;
> + };
> +
> + ldo2_reg: LDO2 {
> + regulator-name = "VDDQ_MMC2";
> + regulator-min-microvolt = <2800000>;
> + regulator-max-microvolt = <2800000>;
> + regulator-always-on;
> + };
> +
> + buck1_reg: BUCK1 {
> + regulator-name = "vdd_mif";
> + regulator-min-microvolt = <950000>;
> + regulator-max-microvolt = <1350000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + buck2_reg: BUCK2 {
> + regulator-name = "vdd_arm";
> + regulator-min-microvolt = <950000>;
> + regulator-max-microvolt = <1350000>;
> + regulator-always-on;
> + regulator-boot-on;
> + regulator-ramp-delay = <50000>;
> + };
> + };
> + };
> --
> 1.7.9.5
>
Can I please have an ack from the DT maintainers so that this series
can be picked by Lee.
--
With warm regards,
Sachin
On Thu, Jan 09, 2014 at 11:22:33AM +0000, Sachin Kamat wrote:
> Add support for S2MPA01 voltage and current regulator.
>
> Signed-off-by: Sachin Kamat <[email protected]>
> ---
> * Addressed comments from Mark Brown
> - Used module_platform_driver instead of subsys init call
> ---
> drivers/regulator/Kconfig | 7 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/s2mpa01.c | 482 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 490 insertions(+)
> create mode 100644 drivers/regulator/s2mpa01.c
[...]
> +static int s2mpa01_pmic_probe(struct platform_device *pdev)
> +{
> + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> + struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
> + struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
> + struct device_node *reg_np = NULL;
> + struct regulator_config config = { };
> + struct s2mpa01_info *s2mpa01;
> + int i, ret;
> +
> + s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL);
> + if (!s2mpa01)
> + return -ENOMEM;
> +
> + for (i = 0; i < S2MPA01_REGULATOR_CNT; i++)
> + rdata[i].name = regulators[i].name;
> +
> + if (iodev->dev->of_node) {
> + reg_np = of_find_node_by_name(iodev->dev->of_node,
> + "regulators");
This walks the allnodes list, and can thus walk outside of the parent
node.
Use of_get_child_by_name instead.
> + if (!reg_np) {
> + dev_err(&pdev->dev,
> + "could not find regulators sub-node\n");
> + return -EINVAL;
> + }
> +
> + of_regulator_match(&pdev->dev, reg_np, rdata,
> + S2MPA01_REGULATOR_MAX);
Is a reference to reg_np held beyond this? Do you need an
of_node_put(reg_np)?
Thanks,
Mark.
Hi Sachin,
Apologies for the delay on this.
On Thu, Jan 09, 2014 at 11:22:34AM +0000, Sachin Kamat wrote:
> Added initial binding documentation for S2MPA01 MFD.
>
> Signed-off-by: Sachin Kamat <[email protected]>
> ---
> * Re-organised as suggested by Mark Rutland.
> ---
> Documentation/devicetree/bindings/mfd/s2mpa01.txt | 86 +++++++++++++++++++++
> 1 file changed, 86 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
> new file mode 100644
> index 000000000000..70879b92b24b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
> @@ -0,0 +1,86 @@
> +
> +* Samsung S2MPA01 Voltage and Current Regulator
> +
> +The Samsung S2MPA01 is a multi-function device which includes high
> +efficiency buck converters including Dual-Phase buck converter, various LDOs,
> +and an RTC. It is interfaced to the host controller using an I2C interface.
> +Each sub-block is addressed by the host system using different I2C slave
> +addresses.
> +
> +Required properties:
> +- compatible: Should be "samsung,s2mpa01-pmic".
> +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
Is the slave address not per-instance in I2C? If not why must is be 0x66?
> +
> +Optional properties:
> +- interrupt-parent: Specifies the phandle of the interrupt controller to which
> + the interrupts from s2mpa01 are delivered to.
> +- interrupts: Interrupt specifier for interrupt source (connected to SoC).
The part in brackets can go. Assuming this is a single interrupt:
- interrupts: An interrupt-specifier for the sole interrupt generated by
the device.
If the interrupt has a name it would be nice to mention that. If there
are more than one you should describe them.
> +
> +Optional nodes:
> +- regulators: The regulators of s2mpa01 that have to be instantiated should be
> + included in a sub-node named 'regulators'. Regulator nodes and constraints
> + included in this sub-node use the standard regulator bindings which are
> + documented elsewhere.
> +
> +Properties for BUCK regulator nodes:
> + regulator-ramp-delay for BUCKs = [6250/12500(default)/25000/50000] uV/us
This could be made easier to read:
- regulator-ramp-delay: ramp delay in uV/us. May be 6250, 12500
(default), 250000, or 50000. May be 0 for disabling the ramp delay on
BUCK{1,2,3,4}.
> +
> + BUCK[1/2/3/4] supports disabling ramp delay on hardware, so explictly
> + regulator-ramp-delay = <0> can be used for them to disable ramp delay.
> + In the absence of the regulator-ramp-delay property, the default ramp
> + delay will be used.
Can be folded into the above, as in my example.
> +
> + NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
> + for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
Missing '=' before <value>?
> + Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
> + BUCK[2, 4], and BUCK[8, 9, 10]
The following BUCKs share ramp settings:
* 1 and 6
* 2 and 4
* 8, 9, and 10
Thanks,
Mark.
On Wed, Feb 12, 2014 at 06:10:43PM +0000, Mark Rutland wrote:
> On Thu, Jan 09, 2014 at 11:22:34AM +0000, Sachin Kamat wrote:
> > +Required properties:
> > +- compatible: Should be "samsung,s2mpa01-pmic".
> > +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
> Is the slave address not per-instance in I2C? If not why must is be 0x66?
I2C devices tend to have a very limited selection of addresses they can
support, a small number selected by pin strapping is common but a single
fixed address is also common. Each device on the bus will have a unique
address but there may not be any selectability.
On 12 February 2014 23:32, Mark Rutland <[email protected]> wrote:
> On Thu, Jan 09, 2014 at 11:22:33AM +0000, Sachin Kamat wrote:
>> Add support for S2MPA01 voltage and current regulator.
>>
>> Signed-off-by: Sachin Kamat <[email protected]>
>> ---
>> * Addressed comments from Mark Brown
>> - Used module_platform_driver instead of subsys init call
>> ---
>> drivers/regulator/Kconfig | 7 +
>> drivers/regulator/Makefile | 1 +
>> drivers/regulator/s2mpa01.c | 482 +++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 490 insertions(+)
>> create mode 100644 drivers/regulator/s2mpa01.c
>
> [...]
>
>> +static int s2mpa01_pmic_probe(struct platform_device *pdev)
>> +{
>> + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
>> + struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
>> + struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
>> + struct device_node *reg_np = NULL;
>> + struct regulator_config config = { };
>> + struct s2mpa01_info *s2mpa01;
>> + int i, ret;
>> +
>> + s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL);
>> + if (!s2mpa01)
>> + return -ENOMEM;
>> +
>> + for (i = 0; i < S2MPA01_REGULATOR_CNT; i++)
>> + rdata[i].name = regulators[i].name;
>> +
>> + if (iodev->dev->of_node) {
>> + reg_np = of_find_node_by_name(iodev->dev->of_node,
>> + "regulators");
>
> This walks the allnodes list, and can thus walk outside of the parent
> node.
>
> Use of_get_child_by_name instead.
OK.
>
>> + if (!reg_np) {
>> + dev_err(&pdev->dev,
>> + "could not find regulators sub-node\n");
>> + return -EINVAL;
>> + }
>> +
>> + of_regulator_match(&pdev->dev, reg_np, rdata,
>> + S2MPA01_REGULATOR_MAX);
>
> Is a reference to reg_np held beyond this? Do you need an
> of_node_put(reg_np)?
Yes, you are right.
Thanks for the review.
--
With warm regards,
Sachin
Hi Mark,
On 12 February 2014 23:40, Mark Rutland <[email protected]> wrote:
> Hi Sachin,
>
> Apologies for the delay on this.
No problem :). Thank you for your review. Please see my comments inline.
>
> On Thu, Jan 09, 2014 at 11:22:34AM +0000, Sachin Kamat wrote:
>> Added initial binding documentation for S2MPA01 MFD.
>>
>> Signed-off-by: Sachin Kamat <[email protected]>
>> ---
>> * Re-organised as suggested by Mark Rutland.
>> ---
>> Documentation/devicetree/bindings/mfd/s2mpa01.txt | 86 +++++++++++++++++++++
>> 1 file changed, 86 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mfd/s2mpa01.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/s2mpa01.txt b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
>> new file mode 100644
>> index 000000000000..70879b92b24b
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/s2mpa01.txt
>> @@ -0,0 +1,86 @@
>> +
>> +* Samsung S2MPA01 Voltage and Current Regulator
>> +
>> +The Samsung S2MPA01 is a multi-function device which includes high
>> +efficiency buck converters including Dual-Phase buck converter, various LDOs,
>> +and an RTC. It is interfaced to the host controller using an I2C interface.
>> +Each sub-block is addressed by the host system using different I2C slave
>> +addresses.
>> +
>> +Required properties:
>> +- compatible: Should be "samsung,s2mpa01-pmic".
>> +- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
>
> Is the slave address not per-instance in I2C? If not why must is be 0x66?
Mark Brown already replied to this. Thanks Mark.
>
>> +
>> +Optional properties:
>> +- interrupt-parent: Specifies the phandle of the interrupt controller to which
>> + the interrupts from s2mpa01 are delivered to.
>> +- interrupts: Interrupt specifier for interrupt source (connected to SoC).
>
> The part in brackets can go. Assuming this is a single interrupt:
OK.
>
> - interrupts: An interrupt-specifier for the sole interrupt generated by
> the device.
>
> If the interrupt has a name it would be nice to mention that. If there
> are more than one you should describe them.
>
>> +
>> +Optional nodes:
>> +- regulators: The regulators of s2mpa01 that have to be instantiated should be
>> + included in a sub-node named 'regulators'. Regulator nodes and constraints
>> + included in this sub-node use the standard regulator bindings which are
>> + documented elsewhere.
>> +
>> +Properties for BUCK regulator nodes:
>> + regulator-ramp-delay for BUCKs = [6250/12500(default)/25000/50000] uV/us
>
> This could be made easier to read:
>
> - regulator-ramp-delay: ramp delay in uV/us. May be 6250, 12500
> (default), 250000, or 50000. May be 0 for disabling the ramp delay on
> BUCK{1,2,3,4}.
Yes. Will update.
>
>> +
>> + BUCK[1/2/3/4] supports disabling ramp delay on hardware, so explictly
>> + regulator-ramp-delay = <0> can be used for them to disable ramp delay.
>> + In the absence of the regulator-ramp-delay property, the default ramp
>> + delay will be used.
>
> Can be folded into the above, as in my example.
Right.
>
>> +
>> + NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
>> + for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
>
> Missing '=' before <value>?
Yes. Thanks for pointing out.
>
>> + Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
>> + BUCK[2, 4], and BUCK[8, 9, 10]
>
> The following BUCKs share ramp settings:
> * 1 and 6
> * 2 and 4
> * 8, 9, and 10
OK.
--
With warm regards,
Sachin