Skip to content

Commit

Permalink
regulator: bcm590xx: Add support for regulators on secondary I2C slave
Browse files Browse the repository at this point in the history
The bcm590xx MFD driver now exposes a secondary regmap descriptor
making the registers for regulators on the secondary I2C slave address
available.  Add support for GPLDO1-6 and VBUS regulators found within
this register range.

Signed-off-by: Matt Porter <mporter@linaro.org>
Acked-by: Mark Brown <broonie@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
  • Loading branch information
Matt Porter authored and Lee Jones committed May 21, 2014
1 parent 9e1e726 commit c646695
Showing 1 changed file with 82 additions and 10 deletions.
92 changes: 82 additions & 10 deletions drivers/regulator/bcm590xx-regulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>

/* Register defs */
/* I2C slave 0 registers */
#define BCM590XX_RFLDOPMCTRL1 0x60
#define BCM590XX_IOSR1PMCTRL1 0x7a
#define BCM590XX_IOSR2PMCTRL1 0x7c
Expand All @@ -31,13 +31,34 @@
#define BCM590XX_SDSR2PMCTRL1 0x86
#define BCM590XX_MSRPMCTRL1 0x8a
#define BCM590XX_VSRPMCTRL1 0x8e
#define BCM590XX_REG_ENABLE BIT(7)

#define BCM590XX_RFLDOCTRL 0x96
#define BCM590XX_CSRVOUT1 0xc0

/* I2C slave 1 registers */
#define BCM590XX_GPLDO5PMCTRL1 0x16
#define BCM590XX_GPLDO6PMCTRL1 0x18
#define BCM590XX_GPLDO1CTRL 0x1a
#define BCM590XX_GPLDO2CTRL 0x1b
#define BCM590XX_GPLDO3CTRL 0x1c
#define BCM590XX_GPLDO4CTRL 0x1d
#define BCM590XX_GPLDO5CTRL 0x1e
#define BCM590XX_GPLDO6CTRL 0x1f
#define BCM590XX_OTG_CTRL 0x40
#define BCM590XX_GPLDO1PMCTRL1 0x57
#define BCM590XX_GPLDO2PMCTRL1 0x59
#define BCM590XX_GPLDO3PMCTRL1 0x5b
#define BCM590XX_GPLDO4PMCTRL1 0x5d

#define BCM590XX_REG_ENABLE BIT(7)
#define BCM590XX_VBUS_ENABLE BIT(2)
#define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3)
#define BCM590XX_SR_VSEL_MASK GENMASK(5, 0)

/*
* RFLDO to VSR regulators are
* accessed via I2C slave 0
*/

/* LDO regulator IDs */
#define BCM590XX_REG_RFLDO 0
#define BCM590XX_REG_CAMLDO1 1
Expand All @@ -62,9 +83,25 @@
#define BCM590XX_REG_SDSR2 18
#define BCM590XX_REG_VSR 19

#define BCM590XX_NUM_REGS 20
/*
* GPLDO1 to VBUS regulators are
* accessed via I2C slave 1
*/

#define BCM590XX_REG_GPLDO1 20
#define BCM590XX_REG_GPLDO2 21
#define BCM590XX_REG_GPLDO3 22
#define BCM590XX_REG_GPLDO4 23
#define BCM590XX_REG_GPLDO5 24
#define BCM590XX_REG_GPLDO6 25
#define BCM590XX_REG_VBUS 26

#define BCM590XX_NUM_REGS 27

#define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR)
#define BCM590XX_REG_IS_GPLDO(n) \
((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
#define BCM590XX_REG_IS_VBUS(n) (n == BCM590XX_REG_VBUS)

struct bcm590xx_board {
struct regulator_init_data *bcm590xx_pmu_init_data[BCM590XX_NUM_REGS];
Expand Down Expand Up @@ -149,6 +186,12 @@ static struct bcm590xx_info bcm590xx_regs[] = {
BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
};

struct bcm590xx_reg {
Expand All @@ -161,6 +204,8 @@ static int bcm590xx_get_vsel_register(int id)
{
if (BCM590XX_REG_IS_LDO(id))
return BCM590XX_RFLDOCTRL + id;
else if (BCM590XX_REG_IS_GPLDO(id))
return BCM590XX_GPLDO1CTRL + id;
else
return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
}
Expand All @@ -171,6 +216,8 @@ static int bcm590xx_get_enable_register(int id)

if (BCM590XX_REG_IS_LDO(id))
reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
else if (BCM590XX_REG_IS_GPLDO(id))
reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
else
switch (id) {
case BCM590XX_REG_CSR:
Expand All @@ -191,8 +238,11 @@ static int bcm590xx_get_enable_register(int id)
case BCM590XX_REG_SDSR2:
reg = BCM590XX_SDSR2PMCTRL1;
break;
case BCM590XX_REG_VBUS:
reg = BCM590XX_OTG_CTRL;
};


return reg;
}

Expand All @@ -216,6 +266,12 @@ static struct regulator_ops bcm590xx_ops_dcdc = {
.map_voltage = regulator_map_voltage_linear_range,
};

static struct regulator_ops bcm590xx_ops_vbus = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};

#define BCM590XX_MATCH(_name, _id) \
{ \
.name = #_name, \
Expand Down Expand Up @@ -243,6 +299,13 @@ static struct of_regulator_match bcm590xx_matches[] = {
BCM590XX_MATCH(sdsr1, SDSR1),
BCM590XX_MATCH(sdsr2, SDSR2),
BCM590XX_MATCH(vsr, VSR),
BCM590XX_MATCH(gpldo1, GPLDO1),
BCM590XX_MATCH(gpldo2, GPLDO2),
BCM590XX_MATCH(gpldo3, GPLDO3),
BCM590XX_MATCH(gpldo4, GPLDO4),
BCM590XX_MATCH(gpldo5, GPLDO5),
BCM590XX_MATCH(gpldo6, GPLDO6),
BCM590XX_MATCH(vbus, VBUS),
};

static struct bcm590xx_board *bcm590xx_parse_dt_reg_data(
Expand Down Expand Up @@ -353,25 +416,34 @@ static int bcm590xx_probe(struct platform_device *pdev)
pmu->desc[i].linear_ranges = info->linear_ranges;
pmu->desc[i].n_linear_ranges = info->n_linear_ranges;

if (BCM590XX_REG_IS_LDO(i)) {
if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
pmu->desc[i].ops = &bcm590xx_ops_ldo;
pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
} else {
} else if (BCM590XX_REG_IS_VBUS(i))
pmu->desc[i].ops = &bcm590xx_ops_vbus;
else {
pmu->desc[i].ops = &bcm590xx_ops_dcdc;
pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
}

pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
pmu->desc[i].enable_is_inverted = true;
pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
if (BCM590XX_REG_IS_VBUS(i))
pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
else {
pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
pmu->desc[i].enable_is_inverted = true;
pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
}
pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
pmu->desc[i].type = REGULATOR_VOLTAGE;
pmu->desc[i].owner = THIS_MODULE;

config.dev = bcm590xx->dev;
config.init_data = reg_data;
config.driver_data = pmu;
config.regmap = bcm590xx->regmap;
if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
config.regmap = bcm590xx->regmap_sec;
else
config.regmap = bcm590xx->regmap_pri;

if (bcm590xx_reg_matches)
config.of_node = bcm590xx_reg_matches[i].of_node;
Expand Down

0 comments on commit c646695

Please sign in to comment.