#include <linux/mfd/s5m87xx/s5m-core.h>
#include <linux/mfd/s5m87xx/s5m-pmic.h>
-#define S5M8767_OPMODE_MASK 0x3
+#define S5M8767_OPMODE_MASK 0x3
+#define S5M8767_OPMODE_SHIFT 6
+#define S5M8767_OPMODE_SM (S5M8767_OPMODE_MASK << S5M8767_OPMODE_SHIFT)
struct s5m8767_info {
struct device *dev;
[S5M8767_BUCK7] = NULL,
[S5M8767_BUCK8] = NULL,
[S5M8767_BUCK9] = &buck_voltage_val3,
+ [S5M8767_EN32KHZ_AP] = NULL,
+ [S5M8767_EN32KHZ_CP] = NULL,
+ [S5M8767_EN32KHZ_BT] = NULL,
};
static int s5m8767_list_voltage(struct regulator_dev *rdev,
return val;
}
-static int s5m8767_get_register(struct regulator_dev *rdev, int *reg)
+static int s5m8767_get_register(struct regulator_dev *rdev,
+ int *reg, int *mask, int *pattern)
{
int reg_id = rdev_get_id(rdev);
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int i;
+ int op_mode = 0x3;
+ for (i = 0; i < s5m8767->iodev->pdata->num_regulators; i++)
+ if (reg_id == s5m8767->iodev->pdata->regulators[i].id)
+ break;
+
+ if (i == s5m8767->iodev->pdata->num_regulators) {
+ dev_err(s5m8767->iodev->dev, "No matching regulators\n");
+ return -ENODEV;
+ }
+#ifdef CONFIG_OF
+ op_mode = s5m8767->iodev->pdata->regulators[i].reg_op_mode;
+#endif
+ *pattern = op_mode << S5M8767_OPMODE_SHIFT;
+ *mask = S5M8767_OPMODE_SM;
switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO2:
case S5M8767_BUCK6 ... S5M8767_BUCK9:
*reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2;
break;
+ case S5M8767_EN32KHZ_AP...S5M8767_EN32KHZ_BT:
+ *reg = S5M8767_REG_CTRL1;
+ *pattern = 1 << (reg_id - S5M8767_EN32KHZ_AP);
+ *mask = 1 << (reg_id - S5M8767_EN32KHZ_AP);
+ break;
default:
return -EINVAL;
}
static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
- u8 val;
+ int ret, reg, mask, pattern;
+ unsigned int val;
- ret = s5m8767_get_register(rdev, ®);
+ ret = s5m8767_get_register(rdev, ®, &mask, &pattern);
if (ret == -EINVAL)
return 1;
else if (ret)
static int s5m8767_reg_enable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
+ int ret, reg, mask, pattern;
- ret = s5m8767_get_register(rdev, ®);
+ ret = s5m8767_get_register(rdev, ®, &mask, &pattern);
if (ret)
return ret;
static int s5m8767_reg_disable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- int ret, reg;
- int mask = 0xc0, pattern = 0xc0;
+ int ret, reg, mask, pattern;
- ret = s5m8767_get_register(rdev, ®);
+ ret = s5m8767_get_register(rdev, ®, &mask, &pattern);
if (ret)
return ret;
- return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask);
+ return s5m_reg_update(s5m8767->iodev, reg, ~mask, mask);
}
static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int reg, mask, ret;
int reg_id = rdev_get_id(rdev);
- u8 val;
+ unsigned int val;
ret = s5m8767_get_voltage_register(rdev, ®);
if (ret)
const struct s5m_voltage_desc *desc;
int reg_id = rdev_get_id(rdev);
int sel, reg, mask, ret;
- u8 val;
+ unsigned int val;
switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO28:
.set_voltage_time_sel = s5m8767_set_voltage_time_sel,
};
+static struct regulator_ops s5m8767_32k_ops = {
+ .list_voltage = s5m8767_list_voltage,
+ .is_enabled = s5m8767_reg_is_enabled,
+ .enable = s5m8767_reg_enable,
+ .disable = s5m8767_reg_disable,
+};
+
#define regulator_desc_ldo(num) { \
.name = "LDO"#num, \
.id = S5M8767_LDO##num, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
+#define regulator_desc_32khz(x) { \
+ .name = "EN32KHZ_" __stringify(x), \
+ .id = S5M8767_EN32KHZ_##x, \
+ .ops = &s5m8767_32k_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+}
static struct regulator_desc regulators[] = {
regulator_desc_ldo(1),
regulator_desc_buck(7),
regulator_desc_buck(8),
regulator_desc_buck(9),
+ regulator_desc_32khz(AP),
+ regulator_desc_32khz(CP),
+ regulator_desc_32khz(BT),
};
#ifdef CONFIG_OF