-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
regulator: hi655x: enable regulator for hi655x PMIC
Add the regulator driver for hi655x PMIC. Signed-off-by: Chen Feng <puck.chen@hisilicon.com> Signed-off-by: Fei Wang <w.f@huawei.com> Signed-off-by: Xinwei Kong <kong.kongxinwei@hisilicon.com> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org> Signed-off-by: Mark Brown <broonie@kernel.org>
- Loading branch information
Chen Feng
authored and
Mark Brown
committed
Feb 15, 2016
1 parent
16dc661
commit 4618119
Showing
3 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
/* | ||
* Device driver for regulators in Hi655x IC | ||
* | ||
* Copyright (c) 2016 Hisilicon. | ||
* | ||
* Authors: | ||
* Chen Feng <puck.chen@hisilicon.com> | ||
* Fei Wang <w.f@huawei.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/bitops.h> | ||
#include <linux/device.h> | ||
#include <linux/err.h> | ||
#include <linux/module.h> | ||
#include <linux/io.h> | ||
#include <linux/of.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/regmap.h> | ||
#include <linux/regulator/driver.h> | ||
#include <linux/regulator/machine.h> | ||
#include <linux/regulator/of_regulator.h> | ||
#include <linux/mfd/hi655x-pmic.h> | ||
|
||
struct hi655x_regulator { | ||
unsigned int disable_reg; | ||
unsigned int status_reg; | ||
unsigned int ctrl_regs; | ||
unsigned int ctrl_mask; | ||
struct regulator_desc rdesc; | ||
}; | ||
|
||
/* LDO7 & LDO10 */ | ||
static const unsigned int ldo7_voltages[] = { | ||
1800000, 1850000, 2850000, 2900000, | ||
3000000, 3100000, 3200000, 3300000, | ||
}; | ||
|
||
static const unsigned int ldo19_voltages[] = { | ||
1800000, 1850000, 1900000, 1750000, | ||
2800000, 2850000, 2900000, 3000000, | ||
}; | ||
|
||
static const unsigned int ldo22_voltages[] = { | ||
900000, 1000000, 1050000, 1100000, | ||
1150000, 1175000, 1185000, 1200000, | ||
}; | ||
|
||
enum hi655x_regulator_id { | ||
HI655X_LDO0, | ||
HI655X_LDO1, | ||
HI655X_LDO2, | ||
HI655X_LDO3, | ||
HI655X_LDO4, | ||
HI655X_LDO5, | ||
HI655X_LDO6, | ||
HI655X_LDO7, | ||
HI655X_LDO8, | ||
HI655X_LDO9, | ||
HI655X_LDO10, | ||
HI655X_LDO11, | ||
HI655X_LDO12, | ||
HI655X_LDO13, | ||
HI655X_LDO14, | ||
HI655X_LDO15, | ||
HI655X_LDO16, | ||
HI655X_LDO17, | ||
HI655X_LDO18, | ||
HI655X_LDO19, | ||
HI655X_LDO20, | ||
HI655X_LDO21, | ||
HI655X_LDO22, | ||
}; | ||
|
||
static int hi655x_is_enabled(struct regulator_dev *rdev) | ||
{ | ||
unsigned int value = 0; | ||
|
||
struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); | ||
|
||
regmap_read(rdev->regmap, regulator->status_reg, &value); | ||
return (value & BIT(regulator->ctrl_mask)); | ||
} | ||
|
||
static int hi655x_disable(struct regulator_dev *rdev) | ||
{ | ||
int ret = 0; | ||
|
||
struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); | ||
|
||
ret = regmap_write(rdev->regmap, regulator->disable_reg, | ||
BIT(regulator->ctrl_mask)); | ||
return ret; | ||
} | ||
|
||
static struct regulator_ops hi655x_regulator_ops = { | ||
.enable = regulator_enable_regmap, | ||
.disable = hi655x_disable, | ||
.is_enabled = hi655x_is_enabled, | ||
.list_voltage = regulator_list_voltage_table, | ||
.get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
.set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
}; | ||
|
||
static struct regulator_ops hi655x_ldo_linear_ops = { | ||
.enable = regulator_enable_regmap, | ||
.disable = hi655x_disable, | ||
.is_enabled = hi655x_is_enabled, | ||
.list_voltage = regulator_list_voltage_linear, | ||
.get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
.set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
}; | ||
|
||
#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \ | ||
sreg, cmask, vtable) { \ | ||
.rdesc = { \ | ||
.name = #_ID, \ | ||
.of_match = of_match_ptr(#_ID), \ | ||
.ops = &hi655x_regulator_ops, \ | ||
.regulators_node = of_match_ptr("regulators"), \ | ||
.type = REGULATOR_VOLTAGE, \ | ||
.id = HI655X_##_ID, \ | ||
.owner = THIS_MODULE, \ | ||
.n_voltages = ARRAY_SIZE(vtable), \ | ||
.volt_table = vtable, \ | ||
.vsel_reg = HI655X_BUS_ADDR(vreg), \ | ||
.vsel_mask = vmask, \ | ||
.enable_reg = HI655X_BUS_ADDR(ereg), \ | ||
.enable_mask = BIT(cmask), \ | ||
}, \ | ||
.disable_reg = HI655X_BUS_ADDR(dreg), \ | ||
.status_reg = HI655X_BUS_ADDR(sreg), \ | ||
.ctrl_mask = cmask, \ | ||
} | ||
|
||
#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \ | ||
sreg, cmask, minv, nvolt, vstep) { \ | ||
.rdesc = { \ | ||
.name = #_ID, \ | ||
.of_match = of_match_ptr(#_ID), \ | ||
.ops = &hi655x_ldo_linear_ops, \ | ||
.regulators_node = of_match_ptr("regulators"), \ | ||
.type = REGULATOR_VOLTAGE, \ | ||
.id = HI655X_##_ID, \ | ||
.owner = THIS_MODULE, \ | ||
.min_uV = minv, \ | ||
.n_voltages = nvolt, \ | ||
.uV_step = vstep, \ | ||
.vsel_reg = HI655X_BUS_ADDR(vreg), \ | ||
.vsel_mask = vmask, \ | ||
.enable_reg = HI655X_BUS_ADDR(ereg), \ | ||
.enable_mask = BIT(cmask), \ | ||
}, \ | ||
.disable_reg = HI655X_BUS_ADDR(dreg), \ | ||
.status_reg = HI655X_BUS_ADDR(sreg), \ | ||
.ctrl_mask = cmask, \ | ||
} | ||
|
||
static struct hi655x_regulator regulators[] = { | ||
HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01, | ||
2500000, 8, 100000), | ||
HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages), | ||
HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages), | ||
HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04, | ||
1600000, 8, 50000), | ||
HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05, | ||
2500000, 8, 100000), | ||
HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06, | ||
1600000, 8, 50000), | ||
HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00, | ||
2500000, 8, 100000), | ||
HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages), | ||
HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04, | ||
1650000, 8, 50000), | ||
HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages), | ||
}; | ||
|
||
static int hi655x_regulator_probe(struct platform_device *pdev) | ||
{ | ||
unsigned int i; | ||
struct hi655x_regulator *regulator; | ||
struct hi655x_pmic *pmic; | ||
struct regulator_config config = { }; | ||
struct regulator_dev *rdev; | ||
|
||
pmic = dev_get_drvdata(pdev->dev.parent); | ||
if (!pmic) { | ||
dev_err(&pdev->dev, "no pmic in the regulator parent node\n"); | ||
return -ENODEV; | ||
} | ||
|
||
regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL); | ||
if (!regulator) | ||
return -ENOMEM; | ||
|
||
platform_set_drvdata(pdev, regulator); | ||
|
||
config.dev = pdev->dev.parent; | ||
config.regmap = pmic->regmap; | ||
config.driver_data = regulator; | ||
for (i = 0; i < ARRAY_SIZE(regulators); i++) { | ||
rdev = devm_regulator_register(&pdev->dev, | ||
®ulators[i].rdesc, | ||
&config); | ||
if (IS_ERR(rdev)) { | ||
dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
regulator->rdesc.name); | ||
return PTR_ERR(rdev); | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
static struct platform_driver hi655x_regulator_driver = { | ||
.driver = { | ||
.name = "hi655x-regulator", | ||
}, | ||
.probe = hi655x_regulator_probe, | ||
}; | ||
module_platform_driver(hi655x_regulator_driver); | ||
|
||
MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>"); | ||
MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver"); | ||
MODULE_LICENSE("GPL v2"); |