Merge remote-tracking branches 'regulator/topic/max8973', 'regulator/topic/max8997', 'regulator/topic/max8998', 'regulator/topic/mc13xxx', 'regulator/topic/pfuze100', 'regulator/topic/rc5t583' and 'regulator/topic/s2mps11' into regulator-next

This commit is contained in:
Mark Brown 2014-03-26 16:58:11 +00:00
21 changed files with 1843 additions and 227 deletions

View File

@ -0,0 +1,90 @@
* 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: An interrupt specifier for the sole interrupt generated by the
device.
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: ramp delay in uV/us. May be 6250, 12500
(default), 25000, or 50000. May be 0 for disabling the ramp delay on
BUCK{1,2,3,4}.
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>.
The following BUCKs share ramp settings:
* 1 and 6
* 2 and 4
* 8, 9, and 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>;
};
};
};

View File

@ -1,5 +1,5 @@
* Samsung S2MPS11 Voltage and Current Regulator * Samsung S2MPS11 and S2MPS14 Voltage and Current Regulator
The Samsung S2MPS11 is a multi-function device which includes voltage and The Samsung S2MPS11 is a multi-function device which includes voltage and
current regulators, RTC, charger controller and other sub-blocks. It is current regulators, RTC, charger controller and other sub-blocks. It is
@ -7,7 +7,7 @@ interfaced to the host controller using an I2C interface. Each sub-block is
addressed by the host system using different I2C slave addresses. addressed by the host system using different I2C slave addresses.
Required properties: Required properties:
- compatible: Should be "samsung,s2mps11-pmic". - compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66. - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties: Optional properties:
@ -59,10 +59,14 @@ supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
as per the datasheet of s2mps11. as per the datasheet of s2mps11.
- LDOn - LDOn
- valid values for n are 1 to 38 - valid values for n are:
- S2MPS11: 1 to 38
- S2MPS14: 1 to 25
- Example: LDO1, LD02, LDO28 - Example: LDO1, LD02, LDO28
- BUCKn - BUCKn
- valid values for n are 1 to 10. - valid values for n are:
- S2MPS11: 1 to 10
- S2MPS14: 1 to 5
- Example: BUCK1, BUCK2, BUCK9 - Example: BUCK1, BUCK2, BUCK9
Example: Example:

View File

@ -1,7 +1,7 @@
PFUZE100 family of regulators PFUZE100 family of regulators
Required properties: Required properties:
- compatible: "fsl,pfuze100" - compatible: "fsl,pfuze100" or "fsl,pfuze200"
- reg: I2C slave address - reg: I2C slave address
Required child node: Required child node:
@ -10,11 +10,14 @@ Required child node:
Documentation/devicetree/bindings/regulator/regulator.txt. Documentation/devicetree/bindings/regulator/regulator.txt.
The valid names for regulators are: The valid names for regulators are:
--PFUZE100
sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6 sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
--PFUZE200
sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6
Each regulator is defined using the standard binding for regulators. Each regulator is defined using the standard binding for regulators.
Example: Example 1: PFUZE100
pmic: pfuze100@08 { pmic: pfuze100@08 {
compatible = "fsl,pfuze100"; compatible = "fsl,pfuze100";
@ -113,3 +116,92 @@ Example:
}; };
}; };
}; };
Example 2: PFUZE200
pmic: pfuze200@08 {
compatible = "fsl,pfuze200";
reg = <0x08>;
regulators {
sw1a_reg: sw1ab {
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1875000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <6250>;
};
sw2_reg: sw2 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
sw3a_reg: sw3a {
regulator-min-microvolt = <400000>;
regulator-max-microvolt = <1975000>;
regulator-boot-on;
regulator-always-on;
};
sw3b_reg: sw3b {
regulator-min-microvolt = <400000>;
regulator-max-microvolt = <1975000>;
regulator-boot-on;
regulator-always-on;
};
swbst_reg: swbst {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5150000>;
};
snvs_reg: vsnvs {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3000000>;
regulator-boot-on;
regulator-always-on;
};
vref_reg: vrefddr {
regulator-boot-on;
regulator-always-on;
};
vgen1_reg: vgen1 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
};
vgen2_reg: vgen2 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
};
vgen3_reg: vgen3 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
vgen4_reg: vgen4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vgen5_reg: vgen5 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vgen6_reg: vgen6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};

View File

@ -26,7 +26,9 @@
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/rtc.h> #include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8763.h> #include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h> #include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -69,18 +71,53 @@ static const struct mfd_cell s2mps11_devs[] = {
} }
}; };
static const struct mfd_cell s2mps14_devs[] = {
{
.name = "s2mps14-pmic",
}, {
.name = "s2mps14-rtc",
}, {
.name = "s2mps14-clk",
}
};
static const struct mfd_cell s2mpa01_devs[] = {
{
.name = "s2mpa01-pmic",
},
};
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id sec_dt_match[] = { static struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic", { .compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X, .data = (void *)S5M8767X,
}, }, {
{ .compatible = "samsung,s2mps11-pmic", .compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X, .data = (void *)S2MPS11X,
}, {
.compatible = "samsung,s2mps14-pmic",
.data = (void *)S2MPS14X,
}, {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
/* Sentinel */
}, },
{},
}; };
#endif #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) static bool s2mps11_volatile(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
@ -111,6 +148,15 @@ static const struct regmap_config sec_regmap_config = {
.val_bits = 8, .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 = { static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
@ -120,6 +166,15 @@ static const struct regmap_config s2mps11_regmap_config = {
.cache_type = REGCACHE_FLAT, .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 = { static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
@ -138,9 +193,18 @@ static const struct regmap_config s5m8767_regmap_config = {
.cache_type = REGCACHE_FLAT, .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, .reg_bits = 8,
.val_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 #ifdef CONFIG_OF
@ -180,24 +244,24 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
} }
#endif #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) const struct i2c_device_id *id)
{ {
#ifdef CONFIG_OF #ifdef CONFIG_OF
if (i2c->dev.of_node) { if (i2c->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(sec_dt_match, i2c->dev.of_node); match = of_match_node(sec_dt_match, i2c->dev.of_node);
return (int)match->data; return (unsigned long)match->data;
} }
#endif #endif
return (int)id->driver_data; return id->driver_data;
} }
static int sec_pmic_probe(struct i2c_client *i2c, static int sec_pmic_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); 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; struct sec_pmic_dev *sec_pmic;
int ret; int ret;
@ -229,17 +293,34 @@ static int sec_pmic_probe(struct i2c_client *i2c,
} }
switch (sec_pmic->device_type) { switch (sec_pmic->device_type) {
case S2MPA01:
regmap = &s2mpa01_regmap_config;
break;
case S2MPS11X: case S2MPS11X:
regmap = &s2mps11_regmap_config; regmap = &s2mps11_regmap_config;
/*
* The rtc-s5m driver does not support S2MPS11 and there
* is no mfd_cell for S2MPS11 RTC device.
* However we must pass something to devm_regmap_init_i2c()
* so use S5M-like regmap config even though it wouldn't work.
*/
regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
regmap_rtc = &s2mps14_rtc_regmap_config;
break; break;
case S5M8763X: case S5M8763X:
regmap = &s5m8763_regmap_config; regmap = &s5m8763_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
case S5M8767X: case S5M8767X:
regmap = &s5m8767_regmap_config; regmap = &s5m8767_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
default: default:
regmap = &sec_regmap_config; regmap = &sec_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
} }
@ -252,10 +333,13 @@ static int sec_pmic_probe(struct i2c_client *i2c,
} }
sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); 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); i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc);
&sec_rtc_regmap_config);
if (IS_ERR(sec_pmic->regmap_rtc)) { if (IS_ERR(sec_pmic->regmap_rtc)) {
ret = PTR_ERR(sec_pmic->regmap_rtc); ret = PTR_ERR(sec_pmic->regmap_rtc);
dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
@ -283,10 +367,18 @@ static int sec_pmic_probe(struct i2c_client *i2c,
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
break; break;
case S2MPA01:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
break;
case S2MPS11X: case S2MPS11X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
break; break;
case S2MPS14X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
break;
default: default:
/* If this happens the probe function is problem */ /* If this happens the probe function is problem */
BUG(); BUG();

View File

@ -1,7 +1,7 @@
/* /*
* sec-irq.c * sec-irq.c
* *
* Copyright (c) 2011 Samsung Electronics Co., Ltd * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
* http://www.samsung.com * http://www.samsung.com
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -19,6 +19,7 @@
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8763.h> #include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h> #include <linux/mfd/samsung/s5m8767.h>
@ -59,14 +60,14 @@ static const struct regmap_irq s2mps11_irqs[] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK, .mask = S2MPS11_IRQ_RTC60S_MASK,
}, },
[S2MPS11_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS11_IRQ_RTCA1] = { [S2MPS11_IRQ_RTCA1] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK, .mask = S2MPS11_IRQ_RTCA1_MASK,
}, },
[S2MPS11_IRQ_RTCA2] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA2_MASK,
},
[S2MPS11_IRQ_SMPL] = { [S2MPS11_IRQ_SMPL] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK, .mask = S2MPS11_IRQ_SMPL_MASK,
@ -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[] = { static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = { [S5M8767_IRQ_PWRR] = {
@ -246,6 +317,16 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
.ack_base = S2MPS11_REG_INT1, .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 = { static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767", .name = "s5m8767",
.irqs = s5m8767_irqs, .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_base, &s2mps11_irq_chip,
&sec_pmic->irq_data); &sec_pmic->irq_data);
break; 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: default:
dev_err(sec_pmic->dev, "Unknown device type %d\n", dev_err(sec_pmic->dev, "Unknown device type %d\n",
sec_pmic->device_type); sec_pmic->device_type);

View File

@ -407,12 +407,12 @@ config REGULATOR_PCF50633
on PCF50633 on PCF50633
config REGULATOR_PFUZE100 config REGULATOR_PFUZE100
tristate "Freescale PFUZE100 regulator driver" tristate "Freescale PFUZE100/PFUZE200 regulator driver"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
help help
Say y here to support the regulators found on the Freescale PFUZE100 Say y here to support the regulators found on the Freescale
PMIC. PFUZE100/PFUZE200 PMIC.
config REGULATOR_RC5T583 config REGULATOR_RC5T583
tristate "RICOH RC5T583 Power regulators" tristate "RICOH RC5T583 Power regulators"
@ -424,13 +424,21 @@ config REGULATOR_RC5T583
through regulator interface. The device supports multiple DCDC/LDO through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication. outputs which can be controlled by i2c communication.
config REGULATOR_S2MPS11 config REGULATOR_S2MPA01
tristate "Samsung S2MPS11 voltage regulator" tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE depends on MFD_SEC_CORE
help help
This driver supports a Samsung S2MPS11 voltage output regulator This driver controls Samsung S2MPA01 voltage output regulator
via I2C bus. S2MPS11 is comprised of high efficient Buck converters via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
including Dual-Phase Buck converter, Buck-Boost converter, various LDOs.
config REGULATOR_S2MPS11
tristate "Samsung S2MPS11/S2MPS14 voltage regulator"
depends on MFD_SEC_CORE
help
This driver supports a Samsung S2MPS11/S2MPS14 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.
config REGULATOR_S5M8767 config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator" tristate "Samsung S5M8767A voltage regulator"

View File

@ -58,6 +58,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o

View File

@ -93,7 +93,6 @@
struct max8973_chip { struct max8973_chip {
struct device *dev; struct device *dev;
struct regulator_desc desc; struct regulator_desc desc;
struct regulator_dev *rdev;
struct regmap *regmap; struct regmap *regmap;
bool enable_external_control; bool enable_external_control;
int dvs_gpio; int dvs_gpio;
@ -379,10 +378,8 @@ static int max8973_probe(struct i2c_client *client,
} }
max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
if (!max) { if (!max)
dev_err(&client->dev, "Memory allocation for max failed\n");
return -ENOMEM; return -ENOMEM;
}
max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config); max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
if (IS_ERR(max->regmap)) { if (IS_ERR(max->regmap)) {
@ -474,7 +471,6 @@ static int max8973_probe(struct i2c_client *client,
return ret; return ret;
} }
max->rdev = rdev;
return 0; return 0;
} }

View File

@ -38,7 +38,6 @@ struct max8997_data {
struct device *dev; struct device *dev;
struct max8997_dev *iodev; struct max8997_dev *iodev;
int num_regulators; int num_regulators;
struct regulator_dev **rdev;
int ramp_delay; /* in mV/us */ int ramp_delay; /* in mV/us */
bool buck1_gpiodvs; bool buck1_gpiodvs;
@ -924,7 +923,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
return -ENODEV; return -ENODEV;
} }
regulators_np = of_find_node_by_name(pmic_np, "regulators"); regulators_np = of_get_child_by_name(pmic_np, "regulators");
if (!regulators_np) { if (!regulators_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n"); dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL; return -EINVAL;
@ -937,7 +936,6 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) { if (!rdata) {
of_node_put(regulators_np); of_node_put(regulators_np);
dev_err(&pdev->dev, "could not allocate memory for regulator data\n");
return -ENOMEM; return -ENOMEM;
} }
@ -1030,10 +1028,10 @@ static int max8997_pmic_probe(struct platform_device *pdev)
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8997_platform_data *pdata = iodev->pdata; struct max8997_platform_data *pdata = iodev->pdata;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev **rdev; struct regulator_dev *rdev;
struct max8997_data *max8997; struct max8997_data *max8997;
struct i2c_client *i2c; struct i2c_client *i2c;
int i, ret, size, nr_dvs; int i, ret, nr_dvs;
u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0; u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
if (!pdata) { if (!pdata) {
@ -1052,12 +1050,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
if (!max8997) if (!max8997)
return -ENOMEM; return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
max8997->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!max8997->rdev)
return -ENOMEM;
rdev = max8997->rdev;
max8997->dev = &pdev->dev; max8997->dev = &pdev->dev;
max8997->iodev = iodev; max8997->iodev = iodev;
max8997->num_regulators = pdata->num_regulators; max8997->num_regulators = pdata->num_regulators;
@ -1205,12 +1197,12 @@ static int max8997_pmic_probe(struct platform_device *pdev)
config.driver_data = max8997; config.driver_data = max8997;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id], rdev = devm_regulator_register(&pdev->dev, &regulators[id],
&config); &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
dev_err(max8997->dev, "regulator init failed for %d\n", dev_err(max8997->dev, "regulator init failed for %d\n",
id); id);
return PTR_ERR(rdev[i]); return PTR_ERR(rdev);
} }
} }

View File

@ -40,7 +40,6 @@ struct max8998_data {
struct device *dev; struct device *dev;
struct max8998_dev *iodev; struct max8998_dev *iodev;
int num_regulators; int num_regulators;
struct regulator_dev **rdev;
u8 buck1_vol[4]; /* voltages for selection */ u8 buck1_vol[4]; /* voltages for selection */
u8 buck2_vol[2]; u8 buck2_vol[2];
unsigned int buck1_idx; /* index to last changed voltage */ unsigned int buck1_idx; /* index to last changed voltage */
@ -674,8 +673,10 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM; return -ENOMEM;
}
pdata->regulators = rdata; pdata->regulators = rdata;
for (i = 0; i < ARRAY_SIZE(regulators); ++i) { for (i = 0; i < ARRAY_SIZE(regulators); ++i) {
@ -692,6 +693,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
} }
pdata->num_regulators = rdata - pdata->regulators; pdata->num_regulators = rdata - pdata->regulators;
of_node_put(reg_np);
of_node_put(regulators_np);
ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
@ -741,10 +745,10 @@ static int max8998_pmic_probe(struct platform_device *pdev)
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = iodev->pdata; struct max8998_platform_data *pdata = iodev->pdata;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev **rdev; struct regulator_dev *rdev;
struct max8998_data *max8998; struct max8998_data *max8998;
struct i2c_client *i2c; struct i2c_client *i2c;
int i, ret, size; int i, ret;
unsigned int v; unsigned int v;
if (!pdata) { if (!pdata) {
@ -763,12 +767,6 @@ static int max8998_pmic_probe(struct platform_device *pdev)
if (!max8998) if (!max8998)
return -ENOMEM; return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
max8998->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!max8998->rdev)
return -ENOMEM;
rdev = max8998->rdev;
max8998->dev = &pdev->dev; max8998->dev = &pdev->dev;
max8998->iodev = iodev; max8998->iodev = iodev;
max8998->num_regulators = pdata->num_regulators; max8998->num_regulators = pdata->num_regulators;
@ -872,13 +870,12 @@ static int max8998_pmic_probe(struct platform_device *pdev)
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8998; config.driver_data = max8998;
rdev[i] = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev, &regulators[index],
&regulators[index], &config); &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev[i]); ret = PTR_ERR(rdev);
dev_err(max8998->dev, "regulator %s init failed (%d)\n", dev_err(max8998->dev, "regulator %s init failed (%d)\n",
regulators[index].name, ret); regulators[index].name, ret);
rdev[i] = NULL;
return ret; return ret;
} }
} }

View File

@ -167,8 +167,10 @@ int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
struct device_node *parent; struct device_node *parent;
int num; int num;
of_node_get(pdev->dev.parent->of_node); if (!pdev->dev.parent->of_node)
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); return -ENODEV;
parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!parent) if (!parent)
return -ENODEV; return -ENODEV;
@ -187,8 +189,10 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct device_node *parent, *child; struct device_node *parent, *child;
int i, parsed = 0; int i, parsed = 0;
of_node_get(pdev->dev.parent->of_node); if (!pdev->dev.parent->of_node)
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); return NULL;
parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!parent) if (!parent)
return NULL; return NULL;

View File

@ -56,6 +56,8 @@
#define PFUZE100_VGEN5VOL 0x70 #define PFUZE100_VGEN5VOL 0x70
#define PFUZE100_VGEN6VOL 0x71 #define PFUZE100_VGEN6VOL 0x71
enum chips { PFUZE100, PFUZE200 };
struct pfuze_regulator { struct pfuze_regulator {
struct regulator_desc desc; struct regulator_desc desc;
unsigned char stby_reg; unsigned char stby_reg;
@ -63,6 +65,7 @@ struct pfuze_regulator {
}; };
struct pfuze_chip { struct pfuze_chip {
int chip_id;
struct regmap *regmap; struct regmap *regmap;
struct device *dev; struct device *dev;
struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
@ -78,14 +81,16 @@ static const int pfuze100_vsnvs[] = {
}; };
static const struct i2c_device_id pfuze_device_id[] = { static const struct i2c_device_id pfuze_device_id[] = {
{.name = "pfuze100"}, {.name = "pfuze100", .driver_data = PFUZE100},
{}, {.name = "pfuze200", .driver_data = PFUZE200},
{ }
}; };
MODULE_DEVICE_TABLE(i2c, pfuze_device_id); MODULE_DEVICE_TABLE(i2c, pfuze_device_id);
static const struct of_device_id pfuze_dt_ids[] = { static const struct of_device_id pfuze_dt_ids[] = {
{ .compatible = "fsl,pfuze100" }, { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100},
{}, { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200},
{ }
}; };
MODULE_DEVICE_TABLE(of, pfuze_dt_ids); MODULE_DEVICE_TABLE(of, pfuze_dt_ids);
@ -139,14 +144,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
}; };
#define PFUZE100_FIXED_REG(_name, base, voltage) \ #define PFUZE100_FIXED_REG(_chip, _name, base, voltage) \
[PFUZE100_ ## _name] = { \ [_chip ## _ ## _name] = { \
.desc = { \ .desc = { \
.name = #_name, \ .name = #_name, \
.n_voltages = 1, \ .n_voltages = 1, \
.ops = &pfuze100_fixed_regulator_ops, \ .ops = &pfuze100_fixed_regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = PFUZE100_ ## _name, \ .id = _chip ## _ ## _name, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.min_uV = (voltage), \ .min_uV = (voltage), \
.enable_reg = (base), \ .enable_reg = (base), \
@ -154,14 +159,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
}, \ }, \
} }
#define PFUZE100_SW_REG(_name, base, min, max, step) \ #define PFUZE100_SW_REG(_chip, _name, base, min, max, step) \
[PFUZE100_ ## _name] = { \ [_chip ## _ ## _name] = { \
.desc = { \ .desc = { \
.name = #_name,\ .name = #_name,\
.n_voltages = ((max) - (min)) / (step) + 1, \ .n_voltages = ((max) - (min)) / (step) + 1, \
.ops = &pfuze100_sw_regulator_ops, \ .ops = &pfuze100_sw_regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = PFUZE100_ ## _name, \ .id = _chip ## _ ## _name, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.min_uV = (min), \ .min_uV = (min), \
.uV_step = (step), \ .uV_step = (step), \
@ -172,14 +177,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
.stby_mask = 0x3f, \ .stby_mask = 0x3f, \
} }
#define PFUZE100_SWB_REG(_name, base, mask, voltages) \ #define PFUZE100_SWB_REG(_chip, _name, base, mask, voltages) \
[PFUZE100_ ## _name] = { \ [_chip ## _ ## _name] = { \
.desc = { \ .desc = { \
.name = #_name, \ .name = #_name, \
.n_voltages = ARRAY_SIZE(voltages), \ .n_voltages = ARRAY_SIZE(voltages), \
.ops = &pfuze100_swb_regulator_ops, \ .ops = &pfuze100_swb_regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = PFUZE100_ ## _name, \ .id = _chip ## _ ## _name, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.volt_table = voltages, \ .volt_table = voltages, \
.vsel_reg = (base), \ .vsel_reg = (base), \
@ -187,14 +192,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
}, \ }, \
} }
#define PFUZE100_VGEN_REG(_name, base, min, max, step) \ #define PFUZE100_VGEN_REG(_chip, _name, base, min, max, step) \
[PFUZE100_ ## _name] = { \ [_chip ## _ ## _name] = { \
.desc = { \ .desc = { \
.name = #_name, \ .name = #_name, \
.n_voltages = ((max) - (min)) / (step) + 1, \ .n_voltages = ((max) - (min)) / (step) + 1, \
.ops = &pfuze100_ldo_regulator_ops, \ .ops = &pfuze100_ldo_regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = PFUZE100_ ## _name, \ .id = _chip ## _ ## _name, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.min_uV = (min), \ .min_uV = (min), \
.uV_step = (step), \ .uV_step = (step), \
@ -207,25 +212,45 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
.stby_mask = 0x20, \ .stby_mask = 0x20, \
} }
/* PFUZE100 */
static struct pfuze_regulator pfuze100_regulators[] = { static struct pfuze_regulator pfuze100_regulators[] = {
PFUZE100_SW_REG(SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000), PFUZE100_SW_REG(PFUZE100, SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
PFUZE100_SW_REG(SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000), PFUZE100_SW_REG(PFUZE100, SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000),
PFUZE100_SW_REG(SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000), PFUZE100_SW_REG(PFUZE100, SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
PFUZE100_SW_REG(SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000), PFUZE100_SW_REG(PFUZE100, SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
PFUZE100_SW_REG(SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000), PFUZE100_SW_REG(PFUZE100, SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
PFUZE100_SW_REG(SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000), PFUZE100_SW_REG(PFUZE100, SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000),
PFUZE100_SWB_REG(SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst), PFUZE100_SWB_REG(PFUZE100, SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
PFUZE100_SWB_REG(VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), PFUZE100_SWB_REG(PFUZE100, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
PFUZE100_FIXED_REG(VREFDDR, PFUZE100_VREFDDRCON, 750000), PFUZE100_FIXED_REG(PFUZE100, VREFDDR, PFUZE100_VREFDDRCON, 750000),
PFUZE100_VGEN_REG(VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000), PFUZE100_VGEN_REG(PFUZE100, VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
PFUZE100_VGEN_REG(VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000), PFUZE100_VGEN_REG(PFUZE100, VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
PFUZE100_VGEN_REG(VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000), PFUZE100_VGEN_REG(PFUZE100, VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000), PFUZE100_VGEN_REG(PFUZE100, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000), PFUZE100_VGEN_REG(PFUZE100, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), PFUZE100_VGEN_REG(PFUZE100, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
}; };
static struct pfuze_regulator pfuze200_regulators[] = {
PFUZE100_SW_REG(PFUZE200, SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
PFUZE100_SW_REG(PFUZE200, SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
PFUZE100_SW_REG(PFUZE200, SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
PFUZE100_SW_REG(PFUZE200, SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
PFUZE100_SWB_REG(PFUZE200, SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
PFUZE100_SWB_REG(PFUZE200, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
PFUZE100_FIXED_REG(PFUZE200, VREFDDR, PFUZE100_VREFDDRCON, 750000),
PFUZE100_VGEN_REG(PFUZE200, VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
PFUZE100_VGEN_REG(PFUZE200, VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
PFUZE100_VGEN_REG(PFUZE200, VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(PFUZE200, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(PFUZE200, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(PFUZE200, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
};
static struct pfuze_regulator *pfuze_regulators;
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* PFUZE100 */
static struct of_regulator_match pfuze100_matches[] = { static struct of_regulator_match pfuze100_matches[] = {
{ .name = "sw1ab", }, { .name = "sw1ab", },
{ .name = "sw1c", }, { .name = "sw1c", },
@ -244,24 +269,56 @@ static struct of_regulator_match pfuze100_matches[] = {
{ .name = "vgen6", }, { .name = "vgen6", },
}; };
/* PFUZE200 */
static struct of_regulator_match pfuze200_matches[] = {
{ .name = "sw1ab", },
{ .name = "sw2", },
{ .name = "sw3a", },
{ .name = "sw3b", },
{ .name = "swbst", },
{ .name = "vsnvs", },
{ .name = "vrefddr", },
{ .name = "vgen1", },
{ .name = "vgen2", },
{ .name = "vgen3", },
{ .name = "vgen4", },
{ .name = "vgen5", },
{ .name = "vgen6", },
};
static struct of_regulator_match *pfuze_matches;
static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
{ {
struct device *dev = chip->dev; struct device *dev = chip->dev;
struct device_node *np, *parent; struct device_node *np, *parent;
int ret; int ret;
np = of_node_get(dev->parent->of_node); np = of_node_get(dev->of_node);
if (!np) if (!np)
return 0; return -EINVAL;
parent = of_find_node_by_name(np, "regulators"); parent = of_get_child_by_name(np, "regulators");
if (!parent) { if (!parent) {
dev_err(dev, "regulators node not found\n"); dev_err(dev, "regulators node not found\n");
return -EINVAL; return -EINVAL;
} }
ret = of_regulator_match(dev, parent, pfuze100_matches, switch (chip->chip_id) {
ARRAY_SIZE(pfuze100_matches)); case PFUZE200:
pfuze_matches = pfuze200_matches;
ret = of_regulator_match(dev, parent, pfuze200_matches,
ARRAY_SIZE(pfuze200_matches));
break;
case PFUZE100:
default:
pfuze_matches = pfuze100_matches;
ret = of_regulator_match(dev, parent, pfuze100_matches,
ARRAY_SIZE(pfuze100_matches));
break;
}
of_node_put(parent); of_node_put(parent);
if (ret < 0) { if (ret < 0) {
@ -275,12 +332,12 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
static inline struct regulator_init_data *match_init_data(int index) static inline struct regulator_init_data *match_init_data(int index)
{ {
return pfuze100_matches[index].init_data; return pfuze_matches[index].init_data;
} }
static inline struct device_node *match_of_node(int index) static inline struct device_node *match_of_node(int index)
{ {
return pfuze100_matches[index].of_node; return pfuze_matches[index].of_node;
} }
#else #else
static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
@ -308,16 +365,14 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip)
if (ret) if (ret)
return ret; return ret;
switch (value & 0x0f) { if (((value & 0x0f) == 0x8) && (pfuze_chip->chip_id == PFUZE100)) {
/* /*
* Freescale misprogrammed 1-3% of parts prior to week 8 of 2013 * Freescale misprogrammed 1-3% of parts prior to week 8 of 2013
* as ID=8 * as ID=8 in PFUZE100
*/ */
case 0x8:
dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8"); dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8");
case 0x0: } else if ((value & 0x0f) != pfuze_chip->chip_id) {
break; /* device id NOT match with your setting */
default:
dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value);
return -ENODEV; return -ENODEV;
} }
@ -353,17 +408,31 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
dev_get_platdata(&client->dev); dev_get_platdata(&client->dev);
struct regulator_config config = { }; struct regulator_config config = { };
int i, ret; int i, ret;
const struct of_device_id *match;
u32 regulator_num;
u32 sw_check_start, sw_check_end;
pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip), pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip),
GFP_KERNEL); GFP_KERNEL);
if (!pfuze_chip) if (!pfuze_chip)
return -ENOMEM; return -ENOMEM;
if (client->dev.of_node) {
match = of_match_device(of_match_ptr(pfuze_dt_ids),
&client->dev);
if (!match) {
dev_err(&client->dev, "Error: No device match found\n");
return -ENODEV;
}
pfuze_chip->chip_id = (int)(long)match->data;
} else if (id) {
pfuze_chip->chip_id = id->driver_data;
} else {
dev_err(&client->dev, "No dts match or id table match found\n");
return -ENODEV;
}
i2c_set_clientdata(client, pfuze_chip); i2c_set_clientdata(client, pfuze_chip);
memcpy(pfuze_chip->regulator_descs, pfuze100_regulators,
sizeof(pfuze_chip->regulator_descs));
pfuze_chip->dev = &client->dev; pfuze_chip->dev = &client->dev;
pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config); pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config);
@ -380,11 +449,34 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
return ret; return ret;
} }
/* use the right regulators after identify the right device */
switch (pfuze_chip->chip_id) {
case PFUZE200:
pfuze_regulators = pfuze200_regulators;
regulator_num = ARRAY_SIZE(pfuze200_regulators);
sw_check_start = PFUZE200_SW2;
sw_check_end = PFUZE200_SW3B;
break;
case PFUZE100:
default:
pfuze_regulators = pfuze100_regulators;
regulator_num = ARRAY_SIZE(pfuze100_regulators);
sw_check_start = PFUZE100_SW2;
sw_check_end = PFUZE100_SW4;
break;
}
dev_info(&client->dev, "pfuze%s found.\n",
(pfuze_chip->chip_id == PFUZE100) ? "100" : "200");
memcpy(pfuze_chip->regulator_descs, pfuze_regulators,
sizeof(pfuze_chip->regulator_descs));
ret = pfuze_parse_regulators_dt(pfuze_chip); ret = pfuze_parse_regulators_dt(pfuze_chip);
if (ret) if (ret)
return ret; return ret;
for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) { for (i = 0; i < regulator_num; i++) {
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
struct regulator_desc *desc; struct regulator_desc *desc;
int val; int val;
@ -397,7 +489,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
init_data = match_init_data(i); init_data = match_init_data(i);
/* SW2~SW4 high bit check and modify the voltage value table */ /* SW2~SW4 high bit check and modify the voltage value table */
if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) { if (i >= sw_check_start && i <= sw_check_end) {
regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
if (val & 0x40) { if (val & 0x40) {
desc->min_uV = 800000; desc->min_uV = 800000;
@ -415,7 +507,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
devm_regulator_register(&client->dev, desc, &config); devm_regulator_register(&client->dev, desc, &config);
if (IS_ERR(pfuze_chip->regulators[i])) { if (IS_ERR(pfuze_chip->regulators[i])) {
dev_err(&client->dev, "register regulator%s failed\n", dev_err(&client->dev, "register regulator%s failed\n",
pfuze100_regulators[i].desc.name); pfuze_regulators[i].desc.name);
return PTR_ERR(pfuze_chip->regulators[i]); return PTR_ERR(pfuze_chip->regulators[i]);
} }
} }
@ -435,6 +527,6 @@ static struct i2c_driver pfuze_driver = {
module_i2c_driver(pfuze_driver); module_i2c_driver(pfuze_driver);
MODULE_AUTHOR("Robin Gong <b38343@freescale.com>"); MODULE_AUTHOR("Robin Gong <b38343@freescale.com>");
MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/PFUZE200 PMIC");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("i2c:pfuze100-regulator"); MODULE_ALIAS("i2c:pfuze100-regulator");

View File

@ -119,7 +119,6 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
{ {
struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
struct regulator_init_data *reg_data;
struct regulator_config config = { }; struct regulator_config config = { };
struct rc5t583_regulator *reg = NULL; struct rc5t583_regulator *reg = NULL;
struct rc5t583_regulator *regs; struct rc5t583_regulator *regs;
@ -135,19 +134,11 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX * regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
sizeof(struct rc5t583_regulator), GFP_KERNEL); sizeof(struct rc5t583_regulator), GFP_KERNEL);
if (!regs) { if (!regs)
dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
return -ENOMEM; return -ENOMEM;
}
for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) { for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
reg_data = pdata->reg_init_data[id];
/* No need to register if there is no regulator data */
if (!reg_data)
continue;
reg = &regs[id]; reg = &regs[id];
ri = &rc5t583_reg_info[id]; ri = &rc5t583_reg_info[id];
reg->reg_info = ri; reg->reg_info = ri;
@ -169,7 +160,7 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
skip_ext_pwr_config: skip_ext_pwr_config:
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.init_data = reg_data; config.init_data = pdata->reg_init_data[id];
config.driver_data = reg; config.driver_data = reg;
config.regmap = rc5t583->regmap; config.regmap = rc5t583->regmap;

481
drivers/regulator/s2mpa01.c Normal file
View File

@ -0,0 +1,481 @@
/*
* 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 {
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;
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_get_child_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);
of_node_put(reg_np);
}
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++) {
struct regulator_dev *rdev;
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;
rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "regulator init failed for %d\n",
i);
return PTR_ERR(rdev);
}
}
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 <sbkim73@samsung.com>");
MODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>");
MODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver");
MODULE_LICENSE("GPL");

View File

@ -1,13 +1,18 @@
/* /*
* s2mps11.c * s2mps11.c
* *
* Copyright (c) 2012 Samsung Electronics Co., Ltd * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd
* http://www.samsung.com * http://www.samsung.com
* *
* This program is free software; you can redistribute it and/or modify it * 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 * 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 * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * 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.
* *
*/ */
@ -24,18 +29,21 @@
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
struct s2mps11_info { struct s2mps11_info {
struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX]; unsigned int rdev_num;
int ramp_delay2; int ramp_delay2;
int ramp_delay34; int ramp_delay34;
int ramp_delay5; int ramp_delay5;
int ramp_delay16; int ramp_delay16;
int ramp_delay7810; int ramp_delay7810;
int ramp_delay9; int ramp_delay9;
/*
* One bit for each S2MPS14 regulator whether the suspend mode
* was enabled.
*/
unsigned int s2mps14_suspend_state:30;
}; };
static int get_ramp_delay(int ramp_delay) static int get_ramp_delay(int ramp_delay)
@ -236,7 +244,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.set_ramp_delay = s2mps11_set_ramp_delay, .set_ramp_delay = s2mps11_set_ramp_delay,
}; };
#define regulator_desc_ldo1(num) { \ #define regulator_desc_s2mps11_ldo1(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.id = S2MPS11_LDO##num, \ .id = S2MPS11_LDO##num, \
.ops = &s2mps11_ldo_ops, \ .ops = &s2mps11_ldo_ops, \
@ -250,7 +258,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_ldo2(num) { \ #define regulator_desc_s2mps11_ldo2(num) { \
.name = "LDO"#num, \ .name = "LDO"#num, \
.id = S2MPS11_LDO##num, \ .id = S2MPS11_LDO##num, \
.ops = &s2mps11_ldo_ops, \ .ops = &s2mps11_ldo_ops, \
@ -265,7 +273,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_buck1_4(num) { \ #define regulator_desc_s2mps11_buck1_4(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.id = S2MPS11_BUCK##num, \ .id = S2MPS11_BUCK##num, \
.ops = &s2mps11_buck_ops, \ .ops = &s2mps11_buck_ops, \
@ -281,7 +289,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_buck5 { \ #define regulator_desc_s2mps11_buck5 { \
.name = "BUCK5", \ .name = "BUCK5", \
.id = S2MPS11_BUCK5, \ .id = S2MPS11_BUCK5, \
.ops = &s2mps11_buck_ops, \ .ops = &s2mps11_buck_ops, \
@ -297,7 +305,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_buck6_8(num) { \ #define regulator_desc_s2mps11_buck6_8(num) { \
.name = "BUCK"#num, \ .name = "BUCK"#num, \
.id = S2MPS11_BUCK##num, \ .id = S2MPS11_BUCK##num, \
.ops = &s2mps11_buck_ops, \ .ops = &s2mps11_buck_ops, \
@ -313,7 +321,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_buck9 { \ #define regulator_desc_s2mps11_buck9 { \
.name = "BUCK9", \ .name = "BUCK9", \
.id = S2MPS11_BUCK9, \ .id = S2MPS11_BUCK9, \
.ops = &s2mps11_buck_ops, \ .ops = &s2mps11_buck_ops, \
@ -329,7 +337,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
#define regulator_desc_buck10 { \ #define regulator_desc_s2mps11_buck10 { \
.name = "BUCK10", \ .name = "BUCK10", \
.id = S2MPS11_BUCK10, \ .id = S2MPS11_BUCK10, \
.ops = &s2mps11_buck_ops, \ .ops = &s2mps11_buck_ops, \
@ -345,72 +353,252 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \ .enable_mask = S2MPS11_ENABLE_MASK \
} }
static struct regulator_desc regulators[] = { static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_ldo2(1), regulator_desc_s2mps11_ldo2(1),
regulator_desc_ldo1(2), regulator_desc_s2mps11_ldo1(2),
regulator_desc_ldo1(3), regulator_desc_s2mps11_ldo1(3),
regulator_desc_ldo1(4), regulator_desc_s2mps11_ldo1(4),
regulator_desc_ldo1(5), regulator_desc_s2mps11_ldo1(5),
regulator_desc_ldo2(6), regulator_desc_s2mps11_ldo2(6),
regulator_desc_ldo1(7), regulator_desc_s2mps11_ldo1(7),
regulator_desc_ldo1(8), regulator_desc_s2mps11_ldo1(8),
regulator_desc_ldo1(9), regulator_desc_s2mps11_ldo1(9),
regulator_desc_ldo1(10), regulator_desc_s2mps11_ldo1(10),
regulator_desc_ldo2(11), regulator_desc_s2mps11_ldo2(11),
regulator_desc_ldo1(12), regulator_desc_s2mps11_ldo1(12),
regulator_desc_ldo1(13), regulator_desc_s2mps11_ldo1(13),
regulator_desc_ldo1(14), regulator_desc_s2mps11_ldo1(14),
regulator_desc_ldo1(15), regulator_desc_s2mps11_ldo1(15),
regulator_desc_ldo1(16), regulator_desc_s2mps11_ldo1(16),
regulator_desc_ldo1(17), regulator_desc_s2mps11_ldo1(17),
regulator_desc_ldo1(18), regulator_desc_s2mps11_ldo1(18),
regulator_desc_ldo1(19), regulator_desc_s2mps11_ldo1(19),
regulator_desc_ldo1(20), regulator_desc_s2mps11_ldo1(20),
regulator_desc_ldo1(21), regulator_desc_s2mps11_ldo1(21),
regulator_desc_ldo2(22), regulator_desc_s2mps11_ldo2(22),
regulator_desc_ldo2(23), regulator_desc_s2mps11_ldo2(23),
regulator_desc_ldo1(24), regulator_desc_s2mps11_ldo1(24),
regulator_desc_ldo1(25), regulator_desc_s2mps11_ldo1(25),
regulator_desc_ldo1(26), regulator_desc_s2mps11_ldo1(26),
regulator_desc_ldo2(27), regulator_desc_s2mps11_ldo2(27),
regulator_desc_ldo1(28), regulator_desc_s2mps11_ldo1(28),
regulator_desc_ldo1(29), regulator_desc_s2mps11_ldo1(29),
regulator_desc_ldo1(30), regulator_desc_s2mps11_ldo1(30),
regulator_desc_ldo1(31), regulator_desc_s2mps11_ldo1(31),
regulator_desc_ldo1(32), regulator_desc_s2mps11_ldo1(32),
regulator_desc_ldo1(33), regulator_desc_s2mps11_ldo1(33),
regulator_desc_ldo1(34), regulator_desc_s2mps11_ldo1(34),
regulator_desc_ldo1(35), regulator_desc_s2mps11_ldo1(35),
regulator_desc_ldo1(36), regulator_desc_s2mps11_ldo1(36),
regulator_desc_ldo1(37), regulator_desc_s2mps11_ldo1(37),
regulator_desc_ldo1(38), regulator_desc_s2mps11_ldo1(38),
regulator_desc_buck1_4(1), regulator_desc_s2mps11_buck1_4(1),
regulator_desc_buck1_4(2), regulator_desc_s2mps11_buck1_4(2),
regulator_desc_buck1_4(3), regulator_desc_s2mps11_buck1_4(3),
regulator_desc_buck1_4(4), regulator_desc_s2mps11_buck1_4(4),
regulator_desc_buck5, regulator_desc_s2mps11_buck5,
regulator_desc_buck6_8(6), regulator_desc_s2mps11_buck6_8(6),
regulator_desc_buck6_8(7), regulator_desc_s2mps11_buck6_8(7),
regulator_desc_buck6_8(8), regulator_desc_s2mps11_buck6_8(8),
regulator_desc_buck9, regulator_desc_s2mps11_buck9,
regulator_desc_buck10, regulator_desc_s2mps11_buck10,
};
static int s2mps14_regulator_enable(struct regulator_dev *rdev)
{
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
val = S2MPS14_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val);
}
static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
{
int ret;
unsigned int val;
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
/* LDO3 should be always on and does not support suspend mode */
if (rdev_get_id(rdev) == S2MPS14_LDO3)
return 0;
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret < 0)
return ret;
s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev));
/*
* Don't enable suspend mode if regulator is already disabled because
* this would effectively for a short time turn on the regulator after
* resuming.
* However we still want to toggle the suspend_state bit for regulator
* in case if it got enabled before suspending the system.
*/
if (!(val & rdev->desc->enable_mask))
return 0;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND);
}
static struct regulator_ops s2mps14_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap,
.enable = s2mps14_regulator_enable,
.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,
.set_suspend_disable = s2mps14_regulator_set_suspend_disable,
};
#define regulator_desc_s2mps14_ldo1(num) { \
.name = "LDO"#num, \
.id = S2MPS14_LDO##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPS14_LDO_MIN_800MV, \
.uV_step = S2MPS14_LDO_STEP_25MV, \
.n_voltages = S2MPS14_LDO_N_VOLTAGES, \
.vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \
.vsel_mask = S2MPS14_LDO_VSEL_MASK, \
.enable_reg = S2MPS14_REG_L1CTRL + num - 1, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
#define regulator_desc_s2mps14_ldo2(num) { \
.name = "LDO"#num, \
.id = S2MPS14_LDO##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPS14_LDO_MIN_1800MV, \
.uV_step = S2MPS14_LDO_STEP_25MV, \
.n_voltages = S2MPS14_LDO_N_VOLTAGES, \
.vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \
.vsel_mask = S2MPS14_LDO_VSEL_MASK, \
.enable_reg = S2MPS14_REG_L1CTRL + num - 1, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
#define regulator_desc_s2mps14_ldo3(num) { \
.name = "LDO"#num, \
.id = S2MPS14_LDO##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPS14_LDO_MIN_800MV, \
.uV_step = S2MPS14_LDO_STEP_12_5MV, \
.n_voltages = S2MPS14_LDO_N_VOLTAGES, \
.vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \
.vsel_mask = S2MPS14_LDO_VSEL_MASK, \
.enable_reg = S2MPS14_REG_L1CTRL + num - 1, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
#define regulator_desc_s2mps14_buck1235(num) { \
.name = "BUCK"#num, \
.id = S2MPS14_BUCK##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPS14_BUCK1235_MIN_600MV, \
.uV_step = S2MPS14_BUCK1235_STEP_6_25MV, \
.n_voltages = S2MPS14_BUCK_N_VOLTAGES, \
.linear_min_sel = S2MPS14_BUCK1235_START_SEL, \
.ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \
.vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \
.vsel_mask = S2MPS14_BUCK_VSEL_MASK, \
.enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
#define regulator_desc_s2mps14_buck4(num) { \
.name = "BUCK"#num, \
.id = S2MPS14_BUCK##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = S2MPS14_BUCK4_MIN_1400MV, \
.uV_step = S2MPS14_BUCK4_STEP_12_5MV, \
.n_voltages = S2MPS14_BUCK_N_VOLTAGES, \
.linear_min_sel = S2MPS14_BUCK4_START_SEL, \
.ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \
.vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \
.vsel_mask = S2MPS14_BUCK_VSEL_MASK, \
.enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
static const struct regulator_desc s2mps14_regulators[] = {
regulator_desc_s2mps14_ldo3(1),
regulator_desc_s2mps14_ldo3(2),
regulator_desc_s2mps14_ldo1(3),
regulator_desc_s2mps14_ldo1(4),
regulator_desc_s2mps14_ldo3(5),
regulator_desc_s2mps14_ldo3(6),
regulator_desc_s2mps14_ldo1(7),
regulator_desc_s2mps14_ldo2(8),
regulator_desc_s2mps14_ldo3(9),
regulator_desc_s2mps14_ldo3(10),
regulator_desc_s2mps14_ldo1(11),
regulator_desc_s2mps14_ldo2(12),
regulator_desc_s2mps14_ldo2(13),
regulator_desc_s2mps14_ldo2(14),
regulator_desc_s2mps14_ldo2(15),
regulator_desc_s2mps14_ldo2(16),
regulator_desc_s2mps14_ldo2(17),
regulator_desc_s2mps14_ldo2(18),
regulator_desc_s2mps14_ldo1(19),
regulator_desc_s2mps14_ldo1(20),
regulator_desc_s2mps14_ldo1(21),
regulator_desc_s2mps14_ldo3(22),
regulator_desc_s2mps14_ldo1(23),
regulator_desc_s2mps14_ldo2(24),
regulator_desc_s2mps14_ldo2(25),
regulator_desc_s2mps14_buck1235(1),
regulator_desc_s2mps14_buck1235(2),
regulator_desc_s2mps14_buck1235(3),
regulator_desc_s2mps14_buck4(4),
regulator_desc_s2mps14_buck1235(5),
}; };
static int s2mps11_pmic_probe(struct platform_device *pdev) static int s2mps11_pmic_probe(struct platform_device *pdev)
{ {
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); struct sec_platform_data *pdata = iodev->pdata;
struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX]; struct of_regulator_match *rdata = NULL;
struct device_node *reg_np = NULL; struct device_node *reg_np = NULL;
struct regulator_config config = { }; struct regulator_config config = { };
struct s2mps11_info *s2mps11; struct s2mps11_info *s2mps11;
int i, ret; int i, ret = 0;
const struct regulator_desc *regulators;
enum sec_device_type dev_type;
s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
GFP_KERNEL); GFP_KERNEL);
if (!s2mps11) if (!s2mps11)
return -ENOMEM; return -ENOMEM;
dev_type = platform_get_device_id(pdev)->driver_data;
switch (dev_type) {
case S2MPS11X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
break;
case S2MPS14X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
break;
default:
dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
return -EINVAL;
};
if (!iodev->dev->of_node) { if (!iodev->dev->of_node) {
if (pdata) { if (pdata) {
goto common_reg; goto common_reg;
@ -421,16 +609,22 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
} }
} }
for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) rdata = kzalloc(sizeof(*rdata) * s2mps11->rdev_num, GFP_KERNEL);
if (!rdata)
return -ENOMEM;
for (i = 0; i < s2mps11->rdev_num; i++)
rdata[i].name = regulators[i].name; rdata[i].name = regulators[i].name;
reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators");
if (!reg_np) { if (!reg_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n"); dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL; ret = -EINVAL;
goto out;
} }
of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
of_node_put(reg_np);
common_reg: common_reg:
platform_set_drvdata(pdev, s2mps11); platform_set_drvdata(pdev, s2mps11);
@ -438,7 +632,9 @@ common_reg:
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.regmap = iodev->regmap_pmic; config.regmap = iodev->regmap_pmic;
config.driver_data = s2mps11; config.driver_data = s2mps11;
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { for (i = 0; i < s2mps11->rdev_num; i++) {
struct regulator_dev *regulator;
if (!reg_np) { if (!reg_np) {
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
@ -447,21 +643,25 @@ common_reg:
config.of_node = rdata[i].of_node; config.of_node = rdata[i].of_node;
} }
s2mps11->rdev[i] = devm_regulator_register(&pdev->dev, regulator = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
if (IS_ERR(s2mps11->rdev[i])) { if (IS_ERR(regulator)) {
ret = PTR_ERR(s2mps11->rdev[i]); ret = PTR_ERR(regulator);
dev_err(&pdev->dev, "regulator init failed for %d\n", dev_err(&pdev->dev, "regulator init failed for %d\n",
i); i);
return ret; goto out;
} }
} }
return 0; out:
kfree(rdata);
return ret;
} }
static const struct platform_device_id s2mps11_pmic_id[] = { static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps11-pmic", 0}, { "s2mps11-pmic", S2MPS11X},
{ "s2mps14-pmic", S2MPS14X},
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
@ -489,5 +689,5 @@ module_exit(s2mps11_pmic_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver"); MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14 Regulator Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -18,7 +18,9 @@ enum sec_device_type {
S5M8751X, S5M8751X,
S5M8763X, S5M8763X,
S5M8767X, S5M8767X,
S2MPA01,
S2MPS11X, S2MPS11X,
S2MPS14X,
}; };
/** /**
@ -50,7 +52,7 @@ struct sec_pmic_dev {
struct regmap_irq_chip_data *irq_data; struct regmap_irq_chip_data *irq_data;
int ono; int ono;
int type; unsigned long type;
bool wakeup; bool wakeup;
bool wtsr_smpl; bool wtsr_smpl;
}; };
@ -92,7 +94,7 @@ struct sec_platform_data {
int buck3_default_idx; int buck3_default_idx;
int buck4_default_idx; int buck4_default_idx;
int buck_ramp_delay; int buck_ramp_delay;
int buck2_ramp_delay; int buck2_ramp_delay;
int buck34_ramp_delay; int buck34_ramp_delay;
@ -100,10 +102,15 @@ struct sec_platform_data {
int buck16_ramp_delay; int buck16_ramp_delay;
int buck7810_ramp_delay; int buck7810_ramp_delay;
int buck9_ramp_delay; int buck9_ramp_delay;
int buck24_ramp_delay;
int buck3_ramp_delay;
int buck7_ramp_delay;
int buck8910_ramp_delay;
bool buck2_ramp_enable; bool buck1_ramp_enable;
bool buck3_ramp_enable; bool buck2_ramp_enable;
bool buck4_ramp_enable; bool buck3_ramp_enable;
bool buck4_ramp_enable;
bool buck6_ramp_enable; bool buck6_ramp_enable;
int buck2_init; int buck2_init;

View File

@ -13,6 +13,56 @@
#ifndef __LINUX_MFD_SEC_IRQ_H #ifndef __LINUX_MFD_SEC_IRQ_H
#define __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 { enum s2mps11_irq {
S2MPS11_IRQ_PWRONF, S2MPS11_IRQ_PWRONF,
S2MPS11_IRQ_PWRONR, S2MPS11_IRQ_PWRONR,
@ -24,8 +74,8 @@ enum s2mps11_irq {
S2MPS11_IRQ_MRB, S2MPS11_IRQ_MRB,
S2MPS11_IRQ_RTC60S, S2MPS11_IRQ_RTC60S,
S2MPS11_IRQ_RTCA0,
S2MPS11_IRQ_RTCA1, S2MPS11_IRQ_RTCA1,
S2MPS11_IRQ_RTCA2,
S2MPS11_IRQ_SMPL, S2MPS11_IRQ_SMPL,
S2MPS11_IRQ_RTC1S, S2MPS11_IRQ_RTC1S,
S2MPS11_IRQ_WTSR, S2MPS11_IRQ_WTSR,
@ -47,7 +97,7 @@ enum s2mps11_irq {
#define S2MPS11_IRQ_RTC60S_MASK (1 << 0) #define S2MPS11_IRQ_RTC60S_MASK (1 << 0)
#define S2MPS11_IRQ_RTCA1_MASK (1 << 1) #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_SMPL_MASK (1 << 3)
#define S2MPS11_IRQ_RTC1S_MASK (1 << 4) #define S2MPS11_IRQ_RTC1S_MASK (1 << 4)
#define S2MPS11_IRQ_WTSR_MASK (1 << 5) #define S2MPS11_IRQ_WTSR_MASK (1 << 5)
@ -55,6 +105,33 @@ enum s2mps11_irq {
#define S2MPS11_IRQ_INT120C_MASK (1 << 0) #define S2MPS11_IRQ_INT120C_MASK (1 << 0)
#define S2MPS11_IRQ_INT140C_MASK (1 << 1) #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 { enum s5m8767_irq {
S5M8767_IRQ_PWRR, S5M8767_IRQ_PWRR,
S5M8767_IRQ_PWRF, S5M8767_IRQ_PWRF,

View File

@ -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 * http://www.samsung.com
* *
* This program is free software; you can redistribute it and/or modify it * 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 * 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 * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * 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.
* *
*/ */
@ -43,6 +48,39 @@ enum sec_rtc_reg {
SEC_RTC_STATUS, SEC_RTC_STATUS,
SEC_WTSR_SMPL_CNTL, SEC_WTSR_SMPL_CNTL,
SEC_RTC_UDR_CON, SEC_RTC_UDR_CON,
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 RTC_I2C_ADDR (0x0C >> 1)
@ -54,6 +92,9 @@ enum sec_rtc_reg {
#define ALARM1_STATUS (1 << 2) #define ALARM1_STATUS (1 << 2)
#define UPDATE_AD (1 << 0) #define UPDATE_AD (1 << 0)
#define S2MPS_ALARM0_STATUS (1 << 2)
#define S2MPS_ALARM1_STATUS (1 << 1)
/* RTC Control Register */ /* RTC Control Register */
#define BCD_EN_SHIFT 0 #define BCD_EN_SHIFT 0
#define BCD_EN_MASK (1 << BCD_EN_SHIFT) #define BCD_EN_MASK (1 << BCD_EN_SHIFT)
@ -62,6 +103,10 @@ enum sec_rtc_reg {
/* RTC Update Register1 */ /* RTC Update Register1 */
#define RTC_UDR_SHIFT 0 #define RTC_UDR_SHIFT 0
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) #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_SHIFT 1
#define RTC_TCON_MASK (1 << RTC_TCON_SHIFT) #define RTC_TCON_MASK (1 << RTC_TCON_SHIFT)
#define RTC_TIME_EN_SHIFT 3 #define RTC_TIME_EN_SHIFT 3

View File

@ -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 */

View File

@ -0,0 +1,154 @@
/*
* 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
/* On/Off controlled by PWREN */
#define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT)
#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 */

View File

@ -35,6 +35,20 @@
#define PFUZE100_VGEN6 14 #define PFUZE100_VGEN6 14
#define PFUZE100_MAX_REGULATOR 15 #define PFUZE100_MAX_REGULATOR 15
#define PFUZE200_SW1AB 0
#define PFUZE200_SW2 1
#define PFUZE200_SW3A 2
#define PFUZE200_SW3B 3
#define PFUZE200_SWBST 4
#define PFUZE200_VSNVS 5
#define PFUZE200_VREFDDR 6
#define PFUZE200_VGEN1 7
#define PFUZE200_VGEN2 8
#define PFUZE200_VGEN3 9
#define PFUZE200_VGEN4 10
#define PFUZE200_VGEN5 11
#define PFUZE200_VGEN6 12
struct regulator_init_data; struct regulator_init_data;
struct pfuze_regulator_platform_data { struct pfuze_regulator_platform_data {