提交 c99f21c2 编写于 作者: M Mark Brown

Merge remote-tracking branch 'regulator/topic/mc13892' into regulator-next

上级 e11c4515 2c8a5dca
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -164,6 +164,14 @@ static const unsigned int mc13892_sw1[] = {
1350000, 1375000
};
/*
* Note: this table is used to derive SWxVSEL by index into
* the array. Offset the values by the index of 1100000uV
* to get the actual register value for that voltage selector
* if the HI bit is to be set as well.
*/
#define MC13892_SWxHI_SEL_OFFSET 20
static const unsigned int mc13892_sw[] = {
600000, 625000, 650000, 675000, 700000, 725000,
750000, 775000, 800000, 825000, 850000, 875000,
......@@ -239,7 +247,6 @@ static const unsigned int mc13892_pwgtdrv[] = {
};
static struct regulator_ops mc13892_gpo_regulator_ops;
/* sw regulators need special care due to the "hi bit" */
static struct regulator_ops mc13892_sw_regulator_ops;
......@@ -396,7 +403,7 @@ static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val;
unsigned int val, selector;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
......@@ -407,12 +414,28 @@ static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev)
if (ret)
return ret;
val = (val & mc13892_regulators[id].vsel_mask)
>> mc13892_regulators[id].vsel_shift;
/*
* Figure out if the HI bit is set inside the switcher mode register
* since this means the selector value we return is at a different
* offset into the selector table.
*
* According to the MC13892 documentation note 59 (Table 47) the SW1
* buck switcher does not support output range programming therefore
* the HI bit must always remain 0. So do not do anything strange if
* our register is MC13892_SWITCHERS0.
*/
selector = val & mc13892_regulators[id].vsel_mask;
if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) &&
(val & MC13892_SWITCHERS0_SWxHI)) {
selector += MC13892_SWxHI_SEL_OFFSET;
}
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d\n",
__func__, id, val, selector);
return val;
return selector;
}
static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
......@@ -425,18 +448,35 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
volt = rdev->desc->volt_table[selector];
mask = mc13892_regulators[id].vsel_mask;
reg_value = selector << mc13892_regulators[id].vsel_shift;
if (volt > 1375000) {
mask |= MC13892_SWITCHERS0_SWxHI;
reg_value |= MC13892_SWITCHERS0_SWxHI;
} else if (volt < 1100000) {
mask |= MC13892_SWITCHERS0_SWxHI;
reg_value &= ~MC13892_SWITCHERS0_SWxHI;
reg_value = selector;
/*
* Don't mess with the HI bit or support HI voltage offsets for SW1.
*
* Since the get_voltage_sel callback has given a fudged value for
* the selector offset, we need to back out that offset if HI is
* to be set so we write the correct value to the register.
*
* The HI bit addition and selector offset handling COULD be more
* complicated by shifting and masking off the voltage selector part
* of the register then logical OR it back in, but since the selector
* is at bits 4:0 there is very little point. This makes the whole
* thing more readable and we do far less work.
*/
if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) {
if (volt > 1375000) {
reg_value -= MC13892_SWxHI_SEL_OFFSET;
reg_value |= MC13892_SWITCHERS0_SWxHI;
mask |= MC13892_SWITCHERS0_SWxHI;
} else if (volt < 1100000) {
reg_value &= ~MC13892_SWITCHERS0_SWxHI;
mask |= MC13892_SWITCHERS0_SWxHI;
}
}
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask,
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, mask,
reg_value);
mc13xxx_unlock(priv->mc13xxx);
......@@ -495,15 +535,18 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
struct mc13xxx_regulator_init_data *mc13xxx_data;
struct regulator_config config = { };
int i, ret;
int num_regulators = 0;
int num_regulators = 0, num_parsed;
u32 val;
num_regulators = mc13xxx_get_num_regulators_dt(pdev);
if (num_regulators <= 0 && pdata)
num_regulators = pdata->num_regulators;
if (num_regulators <= 0)
return -EINVAL;
num_parsed = num_regulators;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
num_regulators * sizeof(priv->regulators[0]),
GFP_KERNEL);
......@@ -520,7 +563,7 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
if (ret)
goto err_unlock;
/* enable switch auto mode */
/* enable switch auto mode (on 2.0A silicon only) */
if ((val & 0x0000FFFF) == 0x45d0) {
ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4,
MC13892_SWITCHERS4_SW1MODE_M |
......@@ -546,7 +589,39 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
= mc13892_vcam_get_mode;
mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators,
ARRAY_SIZE(mc13892_regulators));
ARRAY_SIZE(mc13892_regulators),
&num_parsed);
/*
* Perform a little sanity check on the regulator tree - if we found
* a number of regulators from mc13xxx_get_num_regulators_dt and
* then parsed a smaller number in mc13xxx_parse_regulators_dt then
* there is a regulator defined in the regulators node which has
* not matched any usable regulator in the driver. In this case,
* there is one missing and what will happen is the first regulator
* will get registered again.
*
* Fix this by basically making our number of registerable regulators
* equal to the number of regulators we parsed. We are allocating
* too much memory for priv, but this is unavoidable at this point.
*
* As an example of how this can happen, try making a typo in your
* regulators node (vviohi {} instead of viohi {}) so that the name
* does not match..
*
* The check will basically pass for platform data (non-DT) because
* mc13xxx_parse_regulators_dt for !CONFIG_OF will not touch num_parsed.
*
*/
if (num_parsed != num_regulators) {
dev_warn(&pdev->dev,
"parsed %d != regulators %d - check your device tree!\n",
num_parsed, num_regulators);
num_regulators = num_parsed;
priv->num_regulators = num_regulators;
}
for (i = 0; i < num_regulators; i++) {
struct regulator_init_data *init_data;
struct regulator_desc *desc;
......
......@@ -181,12 +181,14 @@ EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
int num_regulators)
int num_regulators, int *num_parsed)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13xxx_regulator_init_data *data, *p;
struct device_node *parent, *child;
int i;
int i, parsed = 0;
*num_parsed = 0;
of_node_get(pdev->dev.parent->of_node);
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
......@@ -203,16 +205,20 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
for (i = 0; i < num_regulators; i++) {
if (!of_node_cmp(child->name,
regulators[i].desc.name)) {
p->id = i;
p->init_data = of_get_regulator_init_data(
&pdev->dev, child);
p->node = child;
p++;
parsed++;
break;
}
}
}
*num_parsed = parsed;
return data;
}
EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt);
......
......@@ -39,7 +39,7 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev);
extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
int num_regulators);
int num_regulators, int *num_parsed);
#else
static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
{
......@@ -48,7 +48,7 @@ static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
int num_regulators)
int num_regulators, int *num_parsed)
{
return NULL;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部