Blame view

drivers/regulator/bd70528-regulator.c 8.29 KB
99ea37bd1   Matti Vaittinen   regulator: bd7052...
1
2
3
4
5
6
  // SPDX-License-Identifier: GPL-2.0
  // Copyright (C) 2018 ROHM Semiconductors
  // bd70528-regulator.c ROHM BD70528MWV regulator driver
  
  #include <linux/delay.h>
  #include <linux/err.h>
99ea37bd1   Matti Vaittinen   regulator: bd7052...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
  #include <linux/mfd/rohm-bd70528.h>
  #include <linux/module.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/slab.h>
  
  #define BUCK_RAMPRATE_250MV 0
  #define BUCK_RAMPRATE_125MV 1
  #define BUCK_RAMP_MAX 250
60ab7f415   Matti Vaittinen   regulator: use li...
22
  static const struct linear_range bd70528_buck1_volts[] = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
23
24
25
  	REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
  	REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
  };
60ab7f415   Matti Vaittinen   regulator: use li...
26
  static const struct linear_range bd70528_buck2_volts[] = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
27
28
29
30
  	REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
  	REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
  	REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
  };
60ab7f415   Matti Vaittinen   regulator: use li...
31
  static const struct linear_range bd70528_buck3_volts[] = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
32
33
34
35
36
  	REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
  	REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
  };
  
  /* All LDOs have same voltage ranges */
60ab7f415   Matti Vaittinen   regulator: use li...
37
  static const struct linear_range bd70528_ldo_volts[] = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  	REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
  	REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
  	REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
  	REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0),
  };
  
  /* Also both LEDs support same voltages */
  static const unsigned int led_volts[] = {
  	20000, 30000
  };
  
  static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
  {
  	if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) {
  		unsigned int ramp_value = BUCK_RAMPRATE_250MV;
  
  		if (ramp_delay <= 125)
  			ramp_value = BUCK_RAMPRATE_125MV;
  
  		return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
  				  BD70528_MASK_BUCK_RAMP,
  				  ramp_value << BD70528_SIFT_BUCK_RAMP);
  	}
  	dev_err(&rdev->dev, "%s: ramp_delay: %d not supported
  ",
  		rdev->desc->name, ramp_delay);
  	return -EINVAL;
  }
  
  static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev,
  				       unsigned int sel)
  {
  	int ret;
  
  	ret = regulator_is_enabled_regmap(rdev);
  	if (ret < 0)
  		return ret;
  
  	if (ret == 0)
  		return regulator_set_voltage_sel_regmap(rdev, sel);
  
  	dev_err(&rdev->dev,
  		"LED voltage change not allowed when led is enabled
  ");
  
  	return -EBUSY;
  }
08f15f4a3   Axel Lin   regulator: bd7052...
85
  static const struct regulator_ops bd70528_buck_ops = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
86
87
88
89
90
91
92
93
94
  	.enable = regulator_enable_regmap,
  	.disable = regulator_disable_regmap,
  	.is_enabled = regulator_is_enabled_regmap,
  	.list_voltage = regulator_list_voltage_linear_range,
  	.set_voltage_sel = regulator_set_voltage_sel_regmap,
  	.get_voltage_sel = regulator_get_voltage_sel_regmap,
  	.set_voltage_time_sel = regulator_set_voltage_time_sel,
  	.set_ramp_delay = bd70528_set_ramp_delay,
  };
08f15f4a3   Axel Lin   regulator: bd7052...
95
  static const struct regulator_ops bd70528_ldo_ops = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
96
97
98
99
100
101
102
  	.enable = regulator_enable_regmap,
  	.disable = regulator_disable_regmap,
  	.is_enabled = regulator_is_enabled_regmap,
  	.list_voltage = regulator_list_voltage_linear_range,
  	.set_voltage_sel = regulator_set_voltage_sel_regmap,
  	.get_voltage_sel = regulator_get_voltage_sel_regmap,
  	.set_voltage_time_sel = regulator_set_voltage_time_sel,
99ea37bd1   Matti Vaittinen   regulator: bd7052...
103
  };
08f15f4a3   Axel Lin   regulator: bd7052...
104
  static const struct regulator_ops bd70528_led_ops = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
105
106
107
108
109
110
111
  	.enable = regulator_enable_regmap,
  	.disable = regulator_disable_regmap,
  	.is_enabled = regulator_is_enabled_regmap,
  	.list_voltage = regulator_list_voltage_table,
  	.set_voltage_sel = bd70528_led_set_voltage_sel,
  	.get_voltage_sel = regulator_get_voltage_sel_regmap,
  };
08f15f4a3   Axel Lin   regulator: bd7052...
112
  static const struct regulator_desc bd70528_desc[] = {
99ea37bd1   Matti Vaittinen   regulator: bd7052...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  	{
  		.name = "buck1",
  		.of_match = of_match_ptr("BUCK1"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_BUCK1,
  		.ops = &bd70528_buck_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_buck1_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts),
  		.n_voltages = BD70528_BUCK_VOLTS,
  		.enable_reg = BD70528_REG_BUCK1_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_BUCK1_VOLT,
  		.vsel_mask = BD70528_MASK_BUCK_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "buck2",
  		.of_match = of_match_ptr("BUCK2"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_BUCK2,
  		.ops = &bd70528_buck_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_buck2_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts),
  		.n_voltages = BD70528_BUCK_VOLTS,
  		.enable_reg = BD70528_REG_BUCK2_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_BUCK2_VOLT,
  		.vsel_mask = BD70528_MASK_BUCK_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "buck3",
  		.of_match = of_match_ptr("BUCK3"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_BUCK3,
  		.ops = &bd70528_buck_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_buck3_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts),
  		.n_voltages = BD70528_BUCK_VOLTS,
  		.enable_reg = BD70528_REG_BUCK3_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_BUCK3_VOLT,
  		.vsel_mask = BD70528_MASK_BUCK_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "ldo1",
  		.of_match = of_match_ptr("LDO1"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_LDO1,
  		.ops = &bd70528_ldo_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_ldo_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
  		.n_voltages = BD70528_LDO_VOLTS,
  		.enable_reg = BD70528_REG_LDO1_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_LDO1_VOLT,
  		.vsel_mask = BD70528_MASK_LDO_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "ldo2",
  		.of_match = of_match_ptr("LDO2"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_LDO2,
  		.ops = &bd70528_ldo_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_ldo_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
  		.n_voltages = BD70528_LDO_VOLTS,
  		.enable_reg = BD70528_REG_LDO2_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_LDO2_VOLT,
  		.vsel_mask = BD70528_MASK_LDO_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "ldo3",
  		.of_match = of_match_ptr("LDO3"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_LDO3,
  		.ops = &bd70528_ldo_ops,
  		.type = REGULATOR_VOLTAGE,
  		.linear_ranges = bd70528_ldo_volts,
  		.n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
  		.n_voltages = BD70528_LDO_VOLTS,
  		.enable_reg = BD70528_REG_LDO3_EN,
  		.enable_mask = BD70528_MASK_RUN_EN,
  		.vsel_reg = BD70528_REG_LDO3_VOLT,
  		.vsel_mask = BD70528_MASK_LDO_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "ldo_led1",
  		.of_match = of_match_ptr("LDO_LED1"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_LED1,
  		.ops = &bd70528_led_ops,
  		.type = REGULATOR_VOLTAGE,
  		.volt_table = &led_volts[0],
  		.n_voltages = ARRAY_SIZE(led_volts),
  		.enable_reg = BD70528_REG_LED_EN,
  		.enable_mask = BD70528_MASK_LED1_EN,
  		.vsel_reg = BD70528_REG_LED_VOLT,
  		.vsel_mask = BD70528_MASK_LED1_VOLT,
  		.owner = THIS_MODULE,
  	},
  	{
  		.name = "ldo_led2",
  		.of_match = of_match_ptr("LDO_LED2"),
  		.regulators_node = of_match_ptr("regulators"),
  		.id = BD70528_LED2,
  		.ops = &bd70528_led_ops,
  		.type = REGULATOR_VOLTAGE,
  		.volt_table = &led_volts[0],
  		.n_voltages = ARRAY_SIZE(led_volts),
  		.enable_reg = BD70528_REG_LED_EN,
  		.enable_mask = BD70528_MASK_LED2_EN,
  		.vsel_reg = BD70528_REG_LED_VOLT,
  		.vsel_mask = BD70528_MASK_LED2_VOLT,
  		.owner = THIS_MODULE,
  	},
  
  };
  
  static int bd70528_probe(struct platform_device *pdev)
  {
e3233d7f2   Matti Vaittinen   regulator: bd7052...
244
  	struct rohm_regmap_dev *bd70528;
99ea37bd1   Matti Vaittinen   regulator: bd7052...
245
246
247
248
249
250
251
252
253
254
255
  	int i;
  	struct regulator_config config = {
  		.dev = pdev->dev.parent,
  	};
  
  	bd70528 = dev_get_drvdata(pdev->dev.parent);
  	if (!bd70528) {
  		dev_err(&pdev->dev, "No MFD driver data
  ");
  		return -EINVAL;
  	}
e3233d7f2   Matti Vaittinen   regulator: bd7052...
256
  	config.regmap = bd70528->regmap;
99ea37bd1   Matti Vaittinen   regulator: bd7052...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  
  	for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) {
  		struct regulator_dev *rdev;
  
  		rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i],
  					       &config);
  		if (IS_ERR(rdev)) {
  			dev_err(&pdev->dev,
  				"failed to register %s regulator
  ",
  				bd70528_desc[i].name);
  			return PTR_ERR(rdev);
  		}
  	}
  	return 0;
  }
  
  static struct platform_driver bd70528_regulator = {
  	.driver = {
  		.name = "bd70528-pmic"
  	},
  	.probe = bd70528_probe,
  };
  
  module_platform_driver(bd70528_regulator);
  
  MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
  MODULE_DESCRIPTION("BD70528 voltage regulator driver");
  MODULE_LICENSE("GPL");
55d5f62c3   Matti Vaittinen   regulator: bd7052...
286
  MODULE_ALIAS("platform:bd70528-pmic");