mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-27 22:24:30 +08:00
power: pmic/regulator: Add basic support for TPS65910
Texas Instrument's TPS65910 PMIC contains 3 buck DC-DC converts, one boost DC-DC converter and 8 LDOs. This patch implements driver model support for the TPS65910 PMIC and its regulators making the get/set API for regulator value/enable available. This patch depends on the patch "am33xx: Add a function to query MPU voltage in uV" to build correctly. For boards relying on the DT include file tps65910.dtsi the v3 patch "power: extend prefix match to regulator-name property" and an appropriate regulator naming is also required. Signed-off-by: Felix Brack <fb@ltec.ch> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
8a5cbc065d
commit
854dfbf99b
@ -201,3 +201,11 @@ config POWER_MC34VR500
|
||||
The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
|
||||
SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
|
||||
via an I2C interface.
|
||||
|
||||
config DM_PMIC_TPS65910
|
||||
bool "Enable driver for Texas Instruments TPS65910 PMIC"
|
||||
depends on DM_PMIC
|
||||
---help---
|
||||
The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost
|
||||
DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
|
||||
pmic children.
|
||||
|
@ -19,6 +19,7 @@ obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
|
||||
obj-$(CONFIG_PMIC_RN5T567) += rn5t567.o
|
||||
obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
|
||||
obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
|
||||
obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
|
||||
obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
|
||||
|
98
drivers/power/pmic/pmic_tps65910_dm.c
Normal file
98
drivers/power/pmic/pmic_tps65910_dm.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/tps65910_pmic.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static const struct pmic_child_info pmic_children_info[] = {
|
||||
{ .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER },
|
||||
{ .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER },
|
||||
{ .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int pmic_tps65910_reg_count(struct udevice *dev)
|
||||
{
|
||||
return TPS65910_NUM_REGS;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_write(struct udevice *dev, uint reg, const u8 *buffer,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, buffer, len);
|
||||
if (ret)
|
||||
error("%s write error on register %02x\n", dev->name, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer,
|
||||
int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, reg, buffer, len);
|
||||
if (ret)
|
||||
error("%s read error on register %02x\n", dev->name, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
int children;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
debug("%s regulators subnode not found\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
children = pmic_bind_children(dev, regulators_node, pmic_children_info);
|
||||
if (!children)
|
||||
debug("%s has no children (regulators)\n", dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_tps65910_probe(struct udevice *dev)
|
||||
{
|
||||
/* use I2C control interface instead of I2C smartreflex interface to
|
||||
* access smartrefelex registers VDD1_OP_REG, VDD1_SR_REG, VDD2_OP_REG
|
||||
* and VDD2_SR_REG
|
||||
*/
|
||||
return pmic_clrsetbits(dev, TPS65910_REG_DEVICE_CTRL, 0,
|
||||
TPS65910_I2C_SEL_MASK);
|
||||
}
|
||||
|
||||
static struct dm_pmic_ops pmic_tps65910_ops = {
|
||||
.reg_count = pmic_tps65910_reg_count,
|
||||
.read = pmic_tps65910_read,
|
||||
.write = pmic_tps65910_write,
|
||||
};
|
||||
|
||||
static const struct udevice_id pmic_tps65910_match[] = {
|
||||
{ .compatible = "ti,tps65910" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pmic_tps65910) = {
|
||||
.name = "pmic_tps65910",
|
||||
.id = UCLASS_PMIC,
|
||||
.of_match = pmic_tps65910_match,
|
||||
.bind = pmic_tps65910_bind,
|
||||
.probe = pmic_tps65910_probe,
|
||||
.ops = &pmic_tps65910_ops,
|
||||
};
|
@ -188,3 +188,11 @@ config DM_REGULATOR_LP87565
|
||||
LP87565 series of PMICs have 4 single phase BUCKs that can also
|
||||
be configured in multi phase modes. The driver implements
|
||||
get/set api for value and enable.
|
||||
|
||||
config DM_REGULATOR_TPS65910
|
||||
bool "Enable driver for TPS65910 PMIC regulators"
|
||||
depends on DM_PMIC_TPS65910
|
||||
---help---
|
||||
The TPS65910 PMIC provides 4 SMPSs and 8 LDOs. This driver supports all
|
||||
regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
|
||||
the get/set api for value and enable.
|
||||
|
@ -21,3 +21,4 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_PBIAS) += pbias_regulator.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
|
||||
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
|
||||
obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
|
||||
|
459
drivers/power/regulator/tps65910_regulator.c
Normal file
459
drivers/power/regulator/tps65910_regulator.c
Normal file
@ -0,0 +1,459 @@
|
||||
/*
|
||||
* Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/tps65910_pmic.h>
|
||||
|
||||
#define VOUT_CHOICE_COUNT 4
|
||||
|
||||
/*
|
||||
* struct regulator_props - Properties of a LDO and VIO SMPS regulator
|
||||
*
|
||||
* All of these regulators allow setting one out of four output voltages.
|
||||
* These output voltages are only achievable when supplying the regulator
|
||||
* with a minimum input voltage.
|
||||
*
|
||||
* @vin_min[]: minimum supply input voltage in uV required to achieve the
|
||||
* corresponding vout[] voltage
|
||||
* @vout[]: regulator output voltage in uV
|
||||
* @reg: I2C register used to set regulator voltage
|
||||
*/
|
||||
struct regulator_props {
|
||||
int vin_min[VOUT_CHOICE_COUNT];
|
||||
int vout[VOUT_CHOICE_COUNT];
|
||||
int reg;
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vdig1 = {
|
||||
.vin_min = { 1700000, 2100000, 2700000, 3200000 },
|
||||
.vout = { 1200000, 1500000, 1800000, 2700000 },
|
||||
.reg = TPS65910_REG_VDIG1
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vdig2 = {
|
||||
.vin_min = { 1700000, 1700000, 1700000, 2700000 },
|
||||
.vout = { 1000000, 1100000, 1200000, 1800000 },
|
||||
.reg = TPS65910_REG_VDIG2
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vpll = {
|
||||
.vin_min = { 2700000, 2700000, 2700000, 3000000 },
|
||||
.vout = { 1000000, 1100000, 1800000, 2500000 },
|
||||
.reg = TPS65910_REG_VPLL
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vdac = {
|
||||
.vin_min = { 2700000, 3000000, 3200000, 3200000 },
|
||||
.vout = { 1800000, 2600000, 2800000, 2850000 },
|
||||
.reg = TPS65910_REG_VDAC
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vaux1 = {
|
||||
.vin_min = { 2700000, 3200000, 3200000, 3200000 },
|
||||
.vout = { 1800000, 2500000, 2800000, 2850000 },
|
||||
.reg = TPS65910_REG_VAUX1
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vaux2 = {
|
||||
.vin_min = { 2700000, 3200000, 3200000, 3600000 },
|
||||
.vout = { 1800000, 2800000, 2900000, 3300000 },
|
||||
.reg = TPS65910_REG_VAUX2
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vaux33 = {
|
||||
.vin_min = { 2700000, 2700000, 3200000, 3600000 },
|
||||
.vout = { 1800000, 2000000, 2800000, 3300000 },
|
||||
.reg = TPS65910_REG_VAUX33
|
||||
};
|
||||
|
||||
static const struct regulator_props ldo_props_vmmc = {
|
||||
.vin_min = { 2700000, 3200000, 3200000, 3600000 },
|
||||
.vout = { 1800000, 2800000, 3000000, 3300000 },
|
||||
.reg = TPS65910_REG_VMMC
|
||||
};
|
||||
|
||||
static const struct regulator_props smps_props_vio = {
|
||||
.vin_min = { 3200000, 3200000, 4000000, 4400000 },
|
||||
.vout = { 1500000, 1800000, 2500000, 3300000 },
|
||||
.reg = TPS65910_REG_VIO
|
||||
};
|
||||
|
||||
/* lookup table of control registers indexed by regulator unit number */
|
||||
static const int ctrl_regs[] = {
|
||||
TPS65910_REG_VRTC,
|
||||
TPS65910_REG_VIO,
|
||||
TPS65910_REG_VDD1,
|
||||
TPS65910_REG_VDD2,
|
||||
TPS65910_REG_VDD3,
|
||||
TPS65910_REG_VDIG1,
|
||||
TPS65910_REG_VDIG2,
|
||||
TPS65910_REG_VPLL,
|
||||
TPS65910_REG_VDAC,
|
||||
TPS65910_REG_VAUX1,
|
||||
TPS65910_REG_VAUX2,
|
||||
TPS65910_REG_VAUX33,
|
||||
TPS65910_REG_VMMC
|
||||
};
|
||||
|
||||
/* supply names as used in DT */
|
||||
static const char * const supply_names[] = {
|
||||
"vccio-supply",
|
||||
"vcc1-supply",
|
||||
"vcc2-supply",
|
||||
"vcc3-supply",
|
||||
"vcc4-supply",
|
||||
"vcc5-supply",
|
||||
"vcc6-supply",
|
||||
"vcc7-supply"
|
||||
};
|
||||
|
||||
/* lookup table of regulator supplies indexed by regulator unit number */
|
||||
static const int regulator_supplies[] = {
|
||||
TPS65910_SUPPLY_VCC7,
|
||||
TPS65910_SUPPLY_VCCIO,
|
||||
TPS65910_SUPPLY_VCC1,
|
||||
TPS65910_SUPPLY_VCC2,
|
||||
TPS65910_SUPPLY_VCC7,
|
||||
TPS65910_SUPPLY_VCC6,
|
||||
TPS65910_SUPPLY_VCC6,
|
||||
TPS65910_SUPPLY_VCC5,
|
||||
TPS65910_SUPPLY_VCC5,
|
||||
TPS65910_SUPPLY_VCC4,
|
||||
TPS65910_SUPPLY_VCC4,
|
||||
TPS65910_SUPPLY_VCC3,
|
||||
TPS65910_SUPPLY_VCC3
|
||||
};
|
||||
|
||||
static int get_ctrl_reg_from_unit_addr(const uint unit_addr)
|
||||
{
|
||||
if (unit_addr < ARRAY_SIZE(ctrl_regs))
|
||||
return ctrl_regs[unit_addr];
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int tps65910_regulator_get_value(struct udevice *dev,
|
||||
const struct regulator_props *rgp)
|
||||
{
|
||||
int sel, val, vout;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
int vin = pdata->supply;
|
||||
|
||||
val = pmic_reg_read(dev->parent, rgp->reg);
|
||||
if (val < 0)
|
||||
return val;
|
||||
sel = (val & TPS65910_SEL_MASK) >> 2;
|
||||
vout = (vin >= *(rgp->vin_min + sel)) ? *(rgp->vout + sel) : 0;
|
||||
vout = ((val & TPS65910_SUPPLY_STATE_MASK) == 1) ? vout : 0;
|
||||
|
||||
return vout;
|
||||
}
|
||||
|
||||
static int tps65910_ldo_get_value(struct udevice *dev)
|
||||
{
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
int vin;
|
||||
|
||||
if (!pdata)
|
||||
return 0;
|
||||
vin = pdata->supply;
|
||||
|
||||
switch (pdata->unit) {
|
||||
case TPS65910_UNIT_VRTC:
|
||||
/* VRTC is fixed and can't be turned off */
|
||||
return (vin >= 2500000) ? 1830000 : 0;
|
||||
case TPS65910_UNIT_VDIG1:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vdig1);
|
||||
case TPS65910_UNIT_VDIG2:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vdig2);
|
||||
case TPS65910_UNIT_VPLL:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vpll);
|
||||
case TPS65910_UNIT_VDAC:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vdac);
|
||||
case TPS65910_UNIT_VAUX1:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vaux1);
|
||||
case TPS65910_UNIT_VAUX2:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vaux2);
|
||||
case TPS65910_UNIT_VAUX33:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vaux33);
|
||||
case TPS65910_UNIT_VMMC:
|
||||
return tps65910_regulator_get_value(dev, &ldo_props_vmmc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tps65910_regulator_set_value(struct udevice *dev,
|
||||
const struct regulator_props *ldo,
|
||||
int uV)
|
||||
{
|
||||
int val;
|
||||
int sel = 0;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
do {
|
||||
/* we only allow exact voltage matches */
|
||||
if (uV == *(ldo->vout + sel))
|
||||
break;
|
||||
} while (++sel < VOUT_CHOICE_COUNT);
|
||||
if (sel == VOUT_CHOICE_COUNT)
|
||||
return -EINVAL;
|
||||
if (pdata->supply < *(ldo->vin_min + sel))
|
||||
return -EINVAL;
|
||||
|
||||
val = pmic_reg_read(dev->parent, ldo->reg);
|
||||
if (val < 0)
|
||||
return val;
|
||||
val &= ~TPS65910_SEL_MASK;
|
||||
val |= sel << 2;
|
||||
return pmic_reg_write(dev->parent, ldo->reg, val);
|
||||
}
|
||||
|
||||
static int tps65910_ldo_set_value(struct udevice *dev, int uV)
|
||||
{
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
int vin = pdata->supply;
|
||||
|
||||
switch (pdata->unit) {
|
||||
case TPS65910_UNIT_VRTC:
|
||||
/* VRTC is fixed to 1.83V and can't be turned off */
|
||||
if (vin < 2500000)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
case TPS65910_UNIT_VDIG1:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vdig1, uV);
|
||||
case TPS65910_UNIT_VDIG2:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vdig2, uV);
|
||||
case TPS65910_UNIT_VPLL:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vpll, uV);
|
||||
case TPS65910_UNIT_VDAC:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vdac, uV);
|
||||
case TPS65910_UNIT_VAUX1:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vaux1, uV);
|
||||
case TPS65910_UNIT_VAUX2:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vaux2, uV);
|
||||
case TPS65910_UNIT_VAUX33:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vaux33, uV);
|
||||
case TPS65910_UNIT_VMMC:
|
||||
return tps65910_regulator_set_value(dev, &ldo_props_vmmc, uV);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int tps65910_get_enable(struct udevice *dev)
|
||||
{
|
||||
int reg, val;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
reg = get_ctrl_reg_from_unit_addr(pdata->unit);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
val = pmic_reg_read(dev->parent, reg);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
/* bits 1:0 of regulator control register define state */
|
||||
return ((val & TPS65910_SUPPLY_STATE_MASK) == 1);
|
||||
}
|
||||
|
||||
static int tps65910_set_enable(struct udevice *dev, bool enable)
|
||||
{
|
||||
int reg;
|
||||
uint clr, set;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
reg = get_ctrl_reg_from_unit_addr(pdata->unit);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
if (enable) {
|
||||
clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_ON;
|
||||
set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_ON;
|
||||
} else {
|
||||
clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_OFF;
|
||||
set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_OFF;
|
||||
}
|
||||
return pmic_clrsetbits(dev->parent, reg, clr, set);
|
||||
}
|
||||
|
||||
static int buck_get_vdd1_vdd2_value(struct udevice *dev, int reg_vdd)
|
||||
{
|
||||
int gain;
|
||||
int val = pmic_reg_read(dev, reg_vdd);
|
||||
|
||||
if (val < 0)
|
||||
return val;
|
||||
gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
|
||||
gain = (gain == 0) ? 1 : gain;
|
||||
val = pmic_reg_read(dev, reg_vdd + 1);
|
||||
if (val < 0)
|
||||
return val;
|
||||
if (val & TPS65910_VDD_SR_MASK)
|
||||
/* use smart reflex value instead */
|
||||
val = pmic_reg_read(dev, reg_vdd + 2);
|
||||
if (val < 0)
|
||||
return val;
|
||||
return (562500 + (val & TPS65910_VDD_SEL_MASK) * 12500) * gain;
|
||||
}
|
||||
|
||||
static int tps65910_buck_get_value(struct udevice *dev)
|
||||
{
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
switch (pdata->unit) {
|
||||
case TPS65910_UNIT_VIO:
|
||||
return tps65910_regulator_get_value(dev, &smps_props_vio);
|
||||
case TPS65910_UNIT_VDD1:
|
||||
return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD1);
|
||||
case TPS65910_UNIT_VDD2:
|
||||
return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD2);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int buck_set_vdd1_vdd2_value(struct udevice *dev, int uV)
|
||||
{
|
||||
int ret, reg_vdd, gain;
|
||||
int val;
|
||||
struct dm_regulator_uclass_platdata *uc_pdata;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
switch (pdata->unit) {
|
||||
case TPS65910_UNIT_VDD1:
|
||||
reg_vdd = TPS65910_REG_VDD1;
|
||||
break;
|
||||
case TPS65910_UNIT_VDD2:
|
||||
reg_vdd = TPS65910_REG_VDD2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
uc_pdata = dev_get_uclass_platdata(dev);
|
||||
|
||||
/* check setpoint is within limits */
|
||||
if (uV < uc_pdata->min_uV) {
|
||||
error("voltage %duV for %s too low\n", uV, dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (uV > uc_pdata->max_uV) {
|
||||
error("voltage %duV for %s too high\n", uV, dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = pmic_reg_read(dev->parent, reg_vdd);
|
||||
if (val < 0)
|
||||
return val;
|
||||
gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
|
||||
gain = (gain == 0) ? 1 : gain;
|
||||
val = ((uV / gain) - 562500) / 12500;
|
||||
if (val < TPS65910_VDD_SEL_MIN || val > TPS65910_VDD_SEL_MAX)
|
||||
/*
|
||||
* Neither do we change the gain, nor do we allow shutdown or
|
||||
* any approximate value (for now)
|
||||
*/
|
||||
return -EPERM;
|
||||
val &= TPS65910_VDD_SEL_MASK;
|
||||
ret = pmic_reg_write(dev->parent, reg_vdd + 1, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65910_buck_set_value(struct udevice *dev, int uV)
|
||||
{
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
if (pdata->unit == TPS65910_UNIT_VIO)
|
||||
return tps65910_regulator_set_value(dev, &smps_props_vio, uV);
|
||||
|
||||
return buck_set_vdd1_vdd2_value(dev, uV);
|
||||
}
|
||||
|
||||
static int tps65910_boost_get_value(struct udevice *dev)
|
||||
{
|
||||
int vout;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
vout = (pdata->supply >= 3000000) ? 5000000 : 0;
|
||||
return vout;
|
||||
}
|
||||
|
||||
static int tps65910_regulator_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct udevice *supply;
|
||||
int ret;
|
||||
const char *supply_name;
|
||||
struct tps65910_regulator_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
pdata->unit = dev_get_driver_data(dev);
|
||||
if (pdata->unit > TPS65910_UNIT_VMMC)
|
||||
return -EINVAL;
|
||||
supply_name = supply_names[regulator_supplies[pdata->unit]];
|
||||
|
||||
debug("Looking up supply power %s\n", supply_name);
|
||||
ret = device_get_supply_regulator(dev->parent, supply_name, &supply);
|
||||
if (ret) {
|
||||
debug(" missing supply power %s\n", supply_name);
|
||||
return ret;
|
||||
}
|
||||
pdata->supply = regulator_get_value(supply);
|
||||
if (pdata->supply < 0) {
|
||||
debug(" invalid supply voltage for regulator %s\n",
|
||||
supply->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_regulator_ops tps65910_boost_ops = {
|
||||
.get_value = tps65910_boost_get_value,
|
||||
.get_enable = tps65910_get_enable,
|
||||
.set_enable = tps65910_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(tps65910_boost) = {
|
||||
.name = TPS65910_BOOST_DRIVER,
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &tps65910_boost_ops,
|
||||
.platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
|
||||
.ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
|
||||
};
|
||||
|
||||
static const struct dm_regulator_ops tps65910_buck_ops = {
|
||||
.get_value = tps65910_buck_get_value,
|
||||
.set_value = tps65910_buck_set_value,
|
||||
.get_enable = tps65910_get_enable,
|
||||
.set_enable = tps65910_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(tps65910_buck) = {
|
||||
.name = TPS65910_BUCK_DRIVER,
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &tps65910_buck_ops,
|
||||
.platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
|
||||
.ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
|
||||
};
|
||||
|
||||
static const struct dm_regulator_ops tps65910_ldo_ops = {
|
||||
.get_value = tps65910_ldo_get_value,
|
||||
.set_value = tps65910_ldo_set_value,
|
||||
.get_enable = tps65910_get_enable,
|
||||
.set_enable = tps65910_set_enable,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(tps65910_ldo) = {
|
||||
.name = TPS65910_LDO_DRIVER,
|
||||
.id = UCLASS_REGULATOR,
|
||||
.ops = &tps65910_ldo_ops,
|
||||
.platdata_auto_alloc_size = sizeof(struct tps65910_regulator_pdata),
|
||||
.ofdata_to_platdata = tps65910_regulator_ofdata_to_platdata,
|
||||
};
|
130
include/power/tps65910_pmic.h
Normal file
130
include/power/tps65910_pmic.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __TPS65910_PMIC_H_
|
||||
#define __TPS65910_PMIC_H_
|
||||
|
||||
#define TPS65910_I2C_SEL_MASK (0x1 << 4)
|
||||
#define TPS65910_VDD_SR_MASK (0x1 << 7)
|
||||
#define TPS65910_GAIN_SEL_MASK (0x3 << 6)
|
||||
#define TPS65910_VDD_SEL_MASK 0x7f
|
||||
#define TPS65910_VDD_SEL_MIN 3
|
||||
#define TPS65910_VDD_SEL_MAX 75
|
||||
#define TPS65910_SEL_MASK (0x3 << 2)
|
||||
#define TPS65910_SUPPLY_STATE_MASK 0x3
|
||||
#define TPS65910_SUPPLY_STATE_OFF 0x0
|
||||
#define TPS65910_SUPPLY_STATE_ON 0x1
|
||||
|
||||
/* i2c registers */
|
||||
enum {
|
||||
TPS65910_REG_RTC_SEC = 0x00,
|
||||
TPS65910_REG_RTC_MIN,
|
||||
TPS65910_REG_RTC_HOUR,
|
||||
TPS65910_REG_RTC_DAY,
|
||||
TPS65910_REG_RTC_MONTH,
|
||||
TPS65910_REG_RTC_YEAR,
|
||||
TPS65910_REG_RTC_WEEK,
|
||||
TPS65910_REG_RTC_ALARM_SEC = 0x08,
|
||||
TPS65910_REG_RTC_ALARM_MIN,
|
||||
TPS65910_REG_RTC_ALARM_HOUR,
|
||||
TPS65910_REG_RTC_ALARM_DAY,
|
||||
TPS65910_REG_RTC_ALARM_MONTH,
|
||||
TPS65910_REG_RTC_ALARM_YEAR,
|
||||
TPS65910_REG_RTC_CTRL = 0x10,
|
||||
TPS65910_REG_RTC_STAT,
|
||||
TPS65910_REG_RTC_INT,
|
||||
TPS65910_REG_RTC_COMP_LSB,
|
||||
TPS65910_REG_RTC_COMP_MSB,
|
||||
TPS65910_REG_RTC_RESISTOR_PRG,
|
||||
TPS65910_REG_RTC_RESET_STAT,
|
||||
TPS65910_REG_BACKUP1,
|
||||
TPS65910_REG_BACKUP2,
|
||||
TPS65910_REG_BACKUP3,
|
||||
TPS65910_REG_BACKUP4,
|
||||
TPS65910_REG_BACKUP5,
|
||||
TPS65910_REG_PUADEN,
|
||||
TPS65910_REG_REF,
|
||||
TPS65910_REG_VRTC,
|
||||
TPS65910_REG_VIO = 0x20,
|
||||
TPS65910_REG_VDD1,
|
||||
TPS65910_REG_VDD1_VAL,
|
||||
TPS65910_REG_VDD1_VAL_SR,
|
||||
TPS65910_REG_VDD2,
|
||||
TPS65910_REG_VDD2_VAL,
|
||||
TPS65910_REG_VDD2_VAL_SR,
|
||||
TPS65910_REG_VDD3,
|
||||
TPS65910_REG_VDIG1 = 0x30,
|
||||
TPS65910_REG_VDIG2,
|
||||
TPS65910_REG_VAUX1,
|
||||
TPS65910_REG_VAUX2,
|
||||
TPS65910_REG_VAUX33,
|
||||
TPS65910_REG_VMMC,
|
||||
TPS65910_REG_VPLL,
|
||||
TPS65910_REG_VDAC,
|
||||
TPS65910_REG_THERM,
|
||||
TPS65910_REG_BATTERY_BACKUP_CHARGE,
|
||||
TPS65910_REG_DCDC_CTRL = 0x3e,
|
||||
TPS65910_REG_DEVICE_CTRL,
|
||||
TPS65910_REG_DEVICE_CTRL2,
|
||||
TPS65910_REG_SLEEP_KEEP_LDO_ON,
|
||||
TPS65910_REG_SLEEP_KEEP_RES_ON,
|
||||
TPS65910_REG_SLEEP_SET_LDO_OFF,
|
||||
TPS65910_REG_SLEEP_SET_RES_OFF,
|
||||
TPS65910_REG_EN1_LDO_ASS,
|
||||
TPS65910_REG_EM1_SMPS_ASS,
|
||||
TPS65910_REG_EN2_LDO_ASS,
|
||||
TPS65910_REG_EM2_SMPS_ASS,
|
||||
TPS65910_REG_INT_STAT = 0x50,
|
||||
TPS65910_REG_INT_MASK,
|
||||
TPS65910_REG_INT_STAT2,
|
||||
TPS65910_REG_INT_MASK2,
|
||||
TPS65910_REG_GPIO = 0x60,
|
||||
TPS65910_REG_JTAGREVNUM = 0x80,
|
||||
TPS65910_NUM_REGS
|
||||
};
|
||||
|
||||
/* chip supplies */
|
||||
enum {
|
||||
TPS65910_SUPPLY_VCCIO = 0x00,
|
||||
TPS65910_SUPPLY_VCC1,
|
||||
TPS65910_SUPPLY_VCC2,
|
||||
TPS65910_SUPPLY_VCC3,
|
||||
TPS65910_SUPPLY_VCC4,
|
||||
TPS65910_SUPPLY_VCC5,
|
||||
TPS65910_SUPPLY_VCC6,
|
||||
TPS65910_SUPPLY_VCC7,
|
||||
TPS65910_NUM_SUPPLIES
|
||||
};
|
||||
|
||||
/* regulator unit numbers */
|
||||
enum {
|
||||
TPS65910_UNIT_VRTC = 0x00,
|
||||
TPS65910_UNIT_VIO,
|
||||
TPS65910_UNIT_VDD1,
|
||||
TPS65910_UNIT_VDD2,
|
||||
TPS65910_UNIT_VDD3,
|
||||
TPS65910_UNIT_VDIG1,
|
||||
TPS65910_UNIT_VDIG2,
|
||||
TPS65910_UNIT_VPLL,
|
||||
TPS65910_UNIT_VDAC,
|
||||
TPS65910_UNIT_VAUX1,
|
||||
TPS65910_UNIT_VAUX2,
|
||||
TPS65910_UNIT_VAUX33,
|
||||
TPS65910_UNIT_VMMC,
|
||||
};
|
||||
|
||||
/* platform data */
|
||||
struct tps65910_regulator_pdata {
|
||||
u32 supply; /* regulator supply voltage in uV */
|
||||
uint unit; /* unit-address according to DT */
|
||||
};
|
||||
|
||||
/* driver names */
|
||||
#define TPS65910_BUCK_DRIVER "tps65910_buck"
|
||||
#define TPS65910_BOOST_DRIVER "tps65910_boost"
|
||||
#define TPS65910_LDO_DRIVER "tps65910_ldo"
|
||||
|
||||
#endif /* __TPS65910_PMIC_H_ */
|
Loading…
Reference in New Issue
Block a user