218 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Device driver for regulators in Hi655x IC4//5// Copyright (c) 2016 HiSilicon Ltd.6//7// Authors:8// Chen Feng <puck.chen@hisilicon.com>9// Fei Wang <w.f@huawei.com>10 11#include <linux/bitops.h>12#include <linux/device.h>13#include <linux/err.h>14#include <linux/module.h>15#include <linux/io.h>16#include <linux/of.h>17#include <linux/platform_device.h>18#include <linux/regmap.h>19#include <linux/regulator/driver.h>20#include <linux/regulator/machine.h>21#include <linux/regulator/of_regulator.h>22#include <linux/mfd/hi655x-pmic.h>23 24struct hi655x_regulator {25 unsigned int disable_reg;26 unsigned int status_reg;27 struct regulator_desc rdesc;28};29 30/* LDO7 & LDO10 */31static const unsigned int ldo7_voltages[] = {32 1800000, 1850000, 2850000, 2900000,33 3000000, 3100000, 3200000, 3300000,34};35 36static const unsigned int ldo19_voltages[] = {37 1800000, 1850000, 1900000, 1750000,38 2800000, 2850000, 2900000, 3000000,39};40 41static const unsigned int ldo22_voltages[] = {42 900000, 1000000, 1050000, 1100000,43 1150000, 1175000, 1185000, 1200000,44};45 46enum hi655x_regulator_id {47 HI655X_LDO0,48 HI655X_LDO1,49 HI655X_LDO2,50 HI655X_LDO3,51 HI655X_LDO4,52 HI655X_LDO5,53 HI655X_LDO6,54 HI655X_LDO7,55 HI655X_LDO8,56 HI655X_LDO9,57 HI655X_LDO10,58 HI655X_LDO11,59 HI655X_LDO12,60 HI655X_LDO13,61 HI655X_LDO14,62 HI655X_LDO15,63 HI655X_LDO16,64 HI655X_LDO17,65 HI655X_LDO18,66 HI655X_LDO19,67 HI655X_LDO20,68 HI655X_LDO21,69 HI655X_LDO22,70};71 72static int hi655x_is_enabled(struct regulator_dev *rdev)73{74 unsigned int value = 0;75 const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);76 77 regmap_read(rdev->regmap, regulator->status_reg, &value);78 return (value & rdev->desc->enable_mask);79}80 81static int hi655x_disable(struct regulator_dev *rdev)82{83 const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);84 85 return regmap_write(rdev->regmap, regulator->disable_reg,86 rdev->desc->enable_mask);87}88 89static const struct regulator_ops hi655x_regulator_ops = {90 .enable = regulator_enable_regmap,91 .disable = hi655x_disable,92 .is_enabled = hi655x_is_enabled,93 .list_voltage = regulator_list_voltage_table,94 .get_voltage_sel = regulator_get_voltage_sel_regmap,95 .set_voltage_sel = regulator_set_voltage_sel_regmap,96};97 98static const struct regulator_ops hi655x_ldo_linear_ops = {99 .enable = regulator_enable_regmap,100 .disable = hi655x_disable,101 .is_enabled = hi655x_is_enabled,102 .list_voltage = regulator_list_voltage_linear,103 .get_voltage_sel = regulator_get_voltage_sel_regmap,104 .set_voltage_sel = regulator_set_voltage_sel_regmap,105};106 107#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \108 sreg, cmask, vtable) { \109 .rdesc = { \110 .name = #_ID, \111 .of_match = of_match_ptr(#_ID), \112 .ops = &hi655x_regulator_ops, \113 .regulators_node = of_match_ptr("regulators"), \114 .type = REGULATOR_VOLTAGE, \115 .id = HI655X_##_ID, \116 .owner = THIS_MODULE, \117 .n_voltages = ARRAY_SIZE(vtable), \118 .volt_table = vtable, \119 .vsel_reg = HI655X_BUS_ADDR(vreg), \120 .vsel_mask = vmask, \121 .enable_reg = HI655X_BUS_ADDR(ereg), \122 .enable_mask = BIT(cmask), \123 }, \124 .disable_reg = HI655X_BUS_ADDR(dreg), \125 .status_reg = HI655X_BUS_ADDR(sreg), \126}127 128#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \129 sreg, cmask, minv, nvolt, vstep) { \130 .rdesc = { \131 .name = #_ID, \132 .of_match = of_match_ptr(#_ID), \133 .ops = &hi655x_ldo_linear_ops, \134 .regulators_node = of_match_ptr("regulators"), \135 .type = REGULATOR_VOLTAGE, \136 .id = HI655X_##_ID, \137 .owner = THIS_MODULE, \138 .min_uV = minv, \139 .n_voltages = nvolt, \140 .uV_step = vstep, \141 .vsel_reg = HI655X_BUS_ADDR(vreg), \142 .vsel_mask = vmask, \143 .enable_reg = HI655X_BUS_ADDR(ereg), \144 .enable_mask = BIT(cmask), \145 }, \146 .disable_reg = HI655X_BUS_ADDR(dreg), \147 .status_reg = HI655X_BUS_ADDR(sreg), \148}149 150static const struct hi655x_regulator regulators[] = {151 HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,152 2500000, 8, 100000),153 HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),154 HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),155 HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,156 1600000, 8, 50000),157 HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,158 2500000, 8, 100000),159 HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,160 1600000, 8, 50000),161 HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,162 2500000, 8, 100000),163 HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),164 HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,165 1650000, 8, 50000),166 HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),167};168 169static int hi655x_regulator_probe(struct platform_device *pdev)170{171 unsigned int i;172 struct hi655x_pmic *pmic;173 struct regulator_config config = { };174 struct regulator_dev *rdev;175 176 pmic = dev_get_drvdata(pdev->dev.parent);177 if (!pmic) {178 dev_err(&pdev->dev, "no pmic in the regulator parent node\n");179 return -ENODEV;180 }181 182 config.dev = pdev->dev.parent;183 config.regmap = pmic->regmap;184 for (i = 0; i < ARRAY_SIZE(regulators); i++) {185 config.driver_data = (void *) ®ulators[i];186 187 rdev = devm_regulator_register(&pdev->dev,188 ®ulators[i].rdesc,189 &config);190 if (IS_ERR(rdev)) {191 dev_err(&pdev->dev, "failed to register regulator %s\n",192 regulators[i].rdesc.name);193 return PTR_ERR(rdev);194 }195 }196 return 0;197}198 199static const struct platform_device_id hi655x_regulator_table[] = {200 { .name = "hi655x-regulator" },201 {},202};203MODULE_DEVICE_TABLE(platform, hi655x_regulator_table);204 205static struct platform_driver hi655x_regulator_driver = {206 .id_table = hi655x_regulator_table,207 .driver = {208 .name = "hi655x-regulator",209 .probe_type = PROBE_PREFER_ASYNCHRONOUS,210 },211 .probe = hi655x_regulator_probe,212};213module_platform_driver(hi655x_regulator_driver);214 215MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");216MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");217MODULE_LICENSE("GPL v2");218