]> Git Repo - linux.git/blob - drivers/regulator/hi6421v530-regulator.c
Linux 6.14-rc3
[linux.git] / drivers / regulator / hi6421v530-regulator.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Device driver for regulators in Hi6421V530 IC
4 //
5 // Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
6 //              http://www.hisilicon.com
7 // Copyright (c) <2017> Linaro Ltd.
8 //              https://www.linaro.org
9 //
10 // Author: Wang Xiaoyin <[email protected]>
11 //         Guodong Xu <[email protected]>
12
13 #include <linux/mfd/hi6421-pmic.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/regulator/driver.h>
19
20 /*
21  * struct hi6421v530_regulator_info - hi6421v530 regulator information
22  * @desc: regulator description
23  * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
24  */
25 struct hi6421v530_regulator_info {
26         struct regulator_desc rdesc;
27         u8 mode_mask;
28 };
29
30 /* HI6421v530 regulators */
31 enum hi6421v530_regulator_id {
32         HI6421V530_LDO3,
33         HI6421V530_LDO9,
34         HI6421V530_LDO11,
35         HI6421V530_LDO15,
36         HI6421V530_LDO16,
37 };
38
39 static const unsigned int ldo_3_voltages[] = {
40         1800000, 1825000, 1850000, 1875000,
41         1900000, 1925000, 1950000, 1975000,
42         2000000, 2025000, 2050000, 2075000,
43         2100000, 2125000, 2150000, 2200000,
44 };
45
46 static const unsigned int ldo_9_11_voltages[] = {
47         1750000, 1800000, 1825000, 2800000,
48         2850000, 2950000, 3000000, 3300000,
49 };
50
51 static const unsigned int ldo_15_16_voltages[] = {
52         1750000, 1800000, 2400000, 2600000,
53         2700000, 2850000, 2950000, 3000000,
54 };
55
56 static const struct regulator_ops hi6421v530_ldo_ops;
57
58 #define HI6421V530_LDO_ENABLE_TIME (350)
59
60 /*
61  * _id - LDO id name string
62  * v_table - voltage table
63  * vreg - voltage select register
64  * vmask - voltage select mask
65  * ereg - enable register
66  * emask - enable mask
67  * odelay - off/on delay time in uS
68  * ecomask - eco mode mask
69  */
70 #define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask,          \
71                    odelay, ecomask) {                                   \
72         .rdesc = {                                                      \
73                 .name            = #_ID,                                \
74                 .of_match        = of_match_ptr(#_ID),                  \
75                 .regulators_node = of_match_ptr("regulators"),          \
76                 .ops             = &hi6421v530_ldo_ops,                 \
77                 .type            = REGULATOR_VOLTAGE,                   \
78                 .id              = HI6421V530_##_ID,                    \
79                 .owner           = THIS_MODULE,                         \
80                 .n_voltages      = ARRAY_SIZE(v_table),                 \
81                 .volt_table      = v_table,                             \
82                 .vsel_reg        = HI6421_REG_TO_BUS_ADDR(vreg),        \
83                 .vsel_mask       = vmask,                               \
84                 .enable_reg      = HI6421_REG_TO_BUS_ADDR(ereg),        \
85                 .enable_mask     = emask,                               \
86                 .enable_time     = HI6421V530_LDO_ENABLE_TIME,          \
87                 .off_on_delay    = odelay,                              \
88         },                                                              \
89         .mode_mask      = ecomask,                                      \
90 }
91
92 /* HI6421V530 regulator information */
93
94 static const struct hi6421v530_regulator_info hi6421v530_regulator_info[] = {
95         HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2,
96                    20000, 0x6),
97         HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2,
98                    40000, 0x6),
99         HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2,
100                    40000, 0x6),
101         HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2,
102                    40000, 0x6),
103         HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2,
104                    40000, 0x6),
105 };
106
107 static unsigned int hi6421v530_regulator_ldo_get_mode(
108                                         struct regulator_dev *rdev)
109 {
110         const struct hi6421v530_regulator_info *info;
111         unsigned int reg_val;
112
113         info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
114         regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
115
116         if (reg_val & (info->mode_mask))
117                 return REGULATOR_MODE_IDLE;
118
119         return REGULATOR_MODE_NORMAL;
120 }
121
122 static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
123                                                 unsigned int mode)
124 {
125         const struct hi6421v530_regulator_info *info;
126         unsigned int new_mode;
127
128         info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
129         switch (mode) {
130         case REGULATOR_MODE_NORMAL:
131                 new_mode = 0;
132                 break;
133         case REGULATOR_MODE_IDLE:
134                 new_mode = info->mode_mask;
135                 break;
136         default:
137                 return -EINVAL;
138         }
139
140         regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
141                            info->mode_mask, new_mode);
142
143         return 0;
144 }
145
146
147 static const struct regulator_ops hi6421v530_ldo_ops = {
148         .is_enabled = regulator_is_enabled_regmap,
149         .enable = regulator_enable_regmap,
150         .disable = regulator_disable_regmap,
151         .list_voltage = regulator_list_voltage_table,
152         .map_voltage = regulator_map_voltage_ascend,
153         .get_voltage_sel = regulator_get_voltage_sel_regmap,
154         .set_voltage_sel = regulator_set_voltage_sel_regmap,
155         .get_mode = hi6421v530_regulator_ldo_get_mode,
156         .set_mode = hi6421v530_regulator_ldo_set_mode,
157 };
158
159 static int hi6421v530_regulator_probe(struct platform_device *pdev)
160 {
161         struct hi6421_pmic *pmic;
162         struct regulator_dev *rdev;
163         struct regulator_config config = { };
164         unsigned int i;
165
166         pmic = dev_get_drvdata(pdev->dev.parent);
167         if (!pmic) {
168                 dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
169                 return -ENODEV;
170         }
171
172         for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) {
173                 config.dev = pdev->dev.parent;
174                 config.regmap = pmic->regmap;
175
176                 rdev = devm_regulator_register(&pdev->dev,
177                                 &hi6421v530_regulator_info[i].rdesc,
178                                 &config);
179                 if (IS_ERR(rdev)) {
180                         dev_err(&pdev->dev, "failed to register regulator %s\n",
181                                 hi6421v530_regulator_info[i].rdesc.name);
182                         return PTR_ERR(rdev);
183                 }
184         }
185         return 0;
186 }
187
188 static const struct platform_device_id hi6421v530_regulator_table[] = {
189         { .name = "hi6421v530-regulator" },
190         {},
191 };
192 MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table);
193
194 static struct platform_driver hi6421v530_regulator_driver = {
195         .id_table = hi6421v530_regulator_table,
196         .driver = {
197                 .name   = "hi6421v530-regulator",
198                 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
199         },
200         .probe  = hi6421v530_regulator_probe,
201 };
202 module_platform_driver(hi6421v530_regulator_driver);
203
204 MODULE_AUTHOR("Wang Xiaoyin <[email protected]>");
205 MODULE_DESCRIPTION("Hi6421v530 regulator driver");
206 MODULE_LICENSE("GPL v2");
This page took 0.051292 seconds and 4 git commands to generate.