Blame view

drivers/regulator/max77693-regulator.c 8.56 KB
5e9384c70   Krzysztof Kozlowski   regulator: maxim:...
1
2
3
4
5
6
7
8
9
  // SPDX-License-Identifier: GPL-2.0+
  //
  // max77693.c - Regulator driver for the Maxim 77693 and 77843
  //
  // Copyright (C) 2013-2015 Samsung Electronics
  // Jonghwa Lee <jonghwa3.lee@samsung.com>
  // Krzysztof Kozlowski <krzk@kernel.org>
  //
  // This driver is based on max77686.c
80b022e29   Jonghwa Lee   regulator: max776...
10
11
12
13
14
15
16
17
18
  
  #include <linux/err.h>
  #include <linux/slab.h>
  #include <linux/platform_device.h>
  #include <linux/module.h>
  #include <linux/export.h>
  #include <linux/regulator/driver.h>
  #include <linux/regulator/machine.h>
  #include <linux/mfd/max77693.h>
61b305cd2   Krzysztof Kozlowski   drivers: max77693...
19
  #include <linux/mfd/max77693-common.h>
80b022e29   Jonghwa Lee   regulator: max776...
20
  #include <linux/mfd/max77693-private.h>
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
21
  #include <linux/mfd/max77843-private.h>
80b022e29   Jonghwa Lee   regulator: max776...
22
  #include <linux/regulator/of_regulator.h>
d0540f91c   Robert Baldyga   mfd: max77693: Re...
23
  #include <linux/regmap.h>
80b022e29   Jonghwa Lee   regulator: max776...
24

9e9a08e86   Krzysztof Kozlowski   regulator: max776...
25
26
27
28
29
30
31
32
33
34
35
36
37
  /*
   * ID for MAX77843 regulators.
   * There is no need for such for MAX77693.
   */
  enum max77843_regulator_type {
  	MAX77843_SAFEOUT1 = 0,
  	MAX77843_SAFEOUT2,
  	MAX77843_CHARGER,
  
  	MAX77843_NUM,
  };
  
  /* Register differences between chargers: MAX77693 and MAX77843 */
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
38
39
40
41
42
43
  struct chg_reg_data {
  	unsigned int linear_reg;
  	unsigned int linear_mask;
  	unsigned int uA_step;
  	unsigned int min_sel;
  };
80b022e29   Jonghwa Lee   regulator: max776...
44

80b022e29   Jonghwa Lee   regulator: max776...
45
  /*
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
46
   * MAX77693 CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA
80b022e29   Jonghwa Lee   regulator: max776...
47
48
   * 0x00, 0x01, 0x2, 0x03	= 60 mA
   * 0x04 ~ 0x7E			= (60 + (X - 3) * 20) mA
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
49
50
51
52
53
   * Actually for MAX77693 the driver manipulates the maximum input current,
   * not the fast charge current (output). This should be fixed.
   *
   * On MAX77843 the calculation formula is the same (except values).
   * Fortunately it properly manipulates the fast charge current.
80b022e29   Jonghwa Lee   regulator: max776...
54
55
56
   */
  static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
  {
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
57
  	const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev);
80b022e29   Jonghwa Lee   regulator: max776...
58
59
  	unsigned int chg_min_uA = rdev->constraints->min_uA;
  	unsigned int chg_max_uA = rdev->constraints->max_uA;
d0540f91c   Robert Baldyga   mfd: max77693: Re...
60
  	unsigned int reg, sel;
80b022e29   Jonghwa Lee   regulator: max776...
61
62
  	unsigned int val;
  	int ret;
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
63
  	ret = regmap_read(rdev->regmap, reg_data->linear_reg, &reg);
80b022e29   Jonghwa Lee   regulator: max776...
64
65
  	if (ret < 0)
  		return ret;
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
66
  	sel = reg & reg_data->linear_mask;
80b022e29   Jonghwa Lee   regulator: max776...
67
68
  
  	/* the first four codes for charger current are all 60mA */
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
69
  	if (sel <= reg_data->min_sel)
80b022e29   Jonghwa Lee   regulator: max776...
70
71
  		sel = 0;
  	else
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
72
  		sel -= reg_data->min_sel;
80b022e29   Jonghwa Lee   regulator: max776...
73

5b5e771fb   Krzysztof Kozlowski   regulator: max776...
74
  	val = chg_min_uA + reg_data->uA_step * sel;
80b022e29   Jonghwa Lee   regulator: max776...
75
76
77
78
79
80
81
82
83
  	if (val > chg_max_uA)
  		return -EINVAL;
  
  	return val;
  }
  
  static int max77693_chg_set_current_limit(struct regulator_dev *rdev,
  						int min_uA, int max_uA)
  {
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
84
  	const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev);
80b022e29   Jonghwa Lee   regulator: max776...
85
86
  	unsigned int chg_min_uA = rdev->constraints->min_uA;
  	int sel = 0;
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
87
  	while (chg_min_uA + reg_data->uA_step * sel < min_uA)
80b022e29   Jonghwa Lee   regulator: max776...
88
  		sel++;
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
89
  	if (chg_min_uA + reg_data->uA_step * sel > max_uA)
80b022e29   Jonghwa Lee   regulator: max776...
90
91
92
  		return -EINVAL;
  
  	/* the first four codes for charger current are all 60mA */
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
93
  	sel += reg_data->min_sel;
80b022e29   Jonghwa Lee   regulator: max776...
94

5b5e771fb   Krzysztof Kozlowski   regulator: max776...
95
  	return regmap_write(rdev->regmap, reg_data->linear_reg, sel);
80b022e29   Jonghwa Lee   regulator: max776...
96
97
  }
  /* end of CHARGER regulator ops */
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  /* Returns regmap suitable for given regulator on chosen device */
  static struct regmap *max77693_get_regmap(enum max77693_types type,
  					  struct max77693_dev *max77693,
  					  int reg_id)
  {
  	if (type == TYPE_MAX77693)
  		return max77693->regmap;
  
  	/* Else: TYPE_MAX77843 */
  	switch (reg_id) {
  	case MAX77843_SAFEOUT1:
  	case MAX77843_SAFEOUT2:
  		return max77693->regmap;
  	case MAX77843_CHARGER:
  		return max77693->regmap_chg;
  	default:
  		return max77693->regmap;
  	}
  }
80b022e29   Jonghwa Lee   regulator: max776...
117
118
119
120
121
122
  static const unsigned int max77693_safeout_table[] = {
  	4850000,
  	4900000,
  	4950000,
  	3300000,
  };
b68f90783   Bhumika Goyal   regulator: max776...
123
  static const struct regulator_ops max77693_safeout_ops = {
80b022e29   Jonghwa Lee   regulator: max776...
124
125
126
127
128
129
130
  	.list_voltage		= regulator_list_voltage_table,
  	.is_enabled		= regulator_is_enabled_regmap,
  	.enable			= regulator_enable_regmap,
  	.disable		= regulator_disable_regmap,
  	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
  	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
  };
a08904fdb   Krzysztof Kozlowski   regulator: max776...
131
  static const struct regulator_ops max77693_charger_ops = {
39d233086   Krzysztof Kozlowski   regulator: max776...
132
  	.is_enabled		= regulator_is_enabled_regmap,
80b022e29   Jonghwa Lee   regulator: max776...
133
134
135
136
137
  	.enable			= regulator_enable_regmap,
  	.disable		= regulator_disable_regmap,
  	.get_current_limit	= max77693_chg_get_current_limit,
  	.set_current_limit	= max77693_chg_set_current_limit,
  };
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
138
  #define max77693_regulator_desc_esafeout(_num)	{		\
80b022e29   Jonghwa Lee   regulator: max776...
139
140
  	.name		= "ESAFEOUT"#_num,			\
  	.id		= MAX77693_ESAFEOUT##_num,		\
222d0f043   Krzysztof Kozlowski   regulator: max776...
141
142
  	.of_match	= of_match_ptr("ESAFEOUT"#_num),	\
  	.regulators_node	= of_match_ptr("regulators"),	\
80b022e29   Jonghwa Lee   regulator: max776...
143
144
145
  	.n_voltages	= 4,					\
  	.ops		= &max77693_safeout_ops,		\
  	.type		= REGULATOR_VOLTAGE,			\
52f48bf33   Axel Lin   regulator: max776...
146
  	.owner		= THIS_MODULE,				\
80b022e29   Jonghwa Lee   regulator: max776...
147
148
149
150
151
152
  	.volt_table	= max77693_safeout_table,		\
  	.vsel_reg	= MAX77693_CHG_REG_SAFEOUT_CTRL,	\
  	.vsel_mask	= SAFEOUT_CTRL_SAFEOUT##_num##_MASK,	\
  	.enable_reg	= MAX77693_CHG_REG_SAFEOUT_CTRL,	\
  	.enable_mask	= SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK ,	\
  }
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
153
154
155
  static const struct regulator_desc max77693_supported_regulators[] = {
  	max77693_regulator_desc_esafeout(1),
  	max77693_regulator_desc_esafeout(2),
80b022e29   Jonghwa Lee   regulator: max776...
156
157
158
  	{
  		.name = "CHARGER",
  		.id = MAX77693_CHARGER,
222d0f043   Krzysztof Kozlowski   regulator: max776...
159
160
  		.of_match = of_match_ptr("CHARGER"),
  		.regulators_node = of_match_ptr("regulators"),
80b022e29   Jonghwa Lee   regulator: max776...
161
162
163
164
165
166
  		.ops = &max77693_charger_ops,
  		.type = REGULATOR_CURRENT,
  		.owner = THIS_MODULE,
  		.enable_reg = MAX77693_CHG_REG_CHG_CNFG_00,
  		.enable_mask = CHG_CNFG_00_CHG_MASK |
  				CHG_CNFG_00_BUCK_MASK,
39d233086   Krzysztof Kozlowski   regulator: max776...
167
  		.enable_val = CHG_CNFG_00_CHG_MASK | CHG_CNFG_00_BUCK_MASK,
80b022e29   Jonghwa Lee   regulator: max776...
168
169
  	},
  };
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
170
171
172
173
174
175
  static const struct chg_reg_data max77693_chg_reg_data = {
  	.linear_reg	= MAX77693_CHG_REG_CHG_CNFG_09,
  	.linear_mask	= CHG_CNFG_09_CHGIN_ILIM_MASK,
  	.uA_step	= 20000,
  	.min_sel	= 3,
  };
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
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
  #define	max77843_regulator_desc_esafeout(num)	{			\
  	.name		= "SAFEOUT" # num,				\
  	.id		= MAX77843_SAFEOUT ## num,			\
  	.ops		= &max77693_safeout_ops,			\
  	.of_match	= of_match_ptr("SAFEOUT" # num),		\
  	.regulators_node = of_match_ptr("regulators"),			\
  	.type		= REGULATOR_VOLTAGE,				\
  	.owner		= THIS_MODULE,					\
  	.n_voltages	= ARRAY_SIZE(max77693_safeout_table),		\
  	.volt_table	= max77693_safeout_table,			\
  	.enable_reg	= MAX77843_SYS_REG_SAFEOUTCTRL,			\
  	.enable_mask	= MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num,	\
  	.vsel_reg	= MAX77843_SYS_REG_SAFEOUTCTRL,			\
  	.vsel_mask	= MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \
  }
  
  static const struct regulator_desc max77843_supported_regulators[] = {
  	[MAX77843_SAFEOUT1] = max77843_regulator_desc_esafeout(1),
  	[MAX77843_SAFEOUT2] = max77843_regulator_desc_esafeout(2),
  	[MAX77843_CHARGER] = {
  		.name		= "CHARGER",
  		.id		= MAX77843_CHARGER,
  		.ops		= &max77693_charger_ops,
  		.of_match	= of_match_ptr("CHARGER"),
  		.regulators_node = of_match_ptr("regulators"),
  		.type		= REGULATOR_CURRENT,
  		.owner		= THIS_MODULE,
  		.enable_reg	= MAX77843_CHG_REG_CHG_CNFG_00,
  		.enable_mask	= MAX77843_CHG_MASK,
  		.enable_val	= MAX77843_CHG_MASK,
  	},
  };
  
  static const struct chg_reg_data max77843_chg_reg_data = {
  	.linear_reg	= MAX77843_CHG_REG_CHG_CNFG_02,
  	.linear_mask	= MAX77843_CHG_FAST_CHG_CURRENT_MASK,
  	.uA_step	= MAX77843_CHG_FAST_CHG_CURRENT_STEP,
  	.min_sel	= 2,
  };
80b022e29   Jonghwa Lee   regulator: max776...
215
216
  static int max77693_pmic_probe(struct platform_device *pdev)
  {
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
217
  	enum max77693_types type = platform_get_device_id(pdev)->driver_data;
80b022e29   Jonghwa Lee   regulator: max776...
218
  	struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
219
220
  	const struct regulator_desc *regulators;
  	unsigned int regulators_size;
222d0f043   Krzysztof Kozlowski   regulator: max776...
221
  	int i;
ca0c37a0b   Krzysztof Kozlowski   regulator: max776...
222
  	struct regulator_config config = { };
80b022e29   Jonghwa Lee   regulator: max776...
223

222d0f043   Krzysztof Kozlowski   regulator: max776...
224
  	config.dev = iodev->dev;
80b022e29   Jonghwa Lee   regulator: max776...
225

9e9a08e86   Krzysztof Kozlowski   regulator: max776...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  	switch (type) {
  	case TYPE_MAX77693:
  		regulators = max77693_supported_regulators;
  		regulators_size = ARRAY_SIZE(max77693_supported_regulators);
  		config.driver_data = (void *)&max77693_chg_reg_data;
  		break;
  	case TYPE_MAX77843:
  		regulators = max77843_supported_regulators;
  		regulators_size = ARRAY_SIZE(max77843_supported_regulators);
  		config.driver_data = (void *)&max77843_chg_reg_data;
  		break;
  	default:
  		dev_err(&pdev->dev, "Unsupported device type: %u
  ", type);
  		return -ENODEV;
  	}
  
  	for (i = 0; i < regulators_size; i++) {
640c24a77   Krzysztof Kozlowski   regulator: max776...
244
  		struct regulator_dev *rdev;
80b022e29   Jonghwa Lee   regulator: max776...
245

9e9a08e86   Krzysztof Kozlowski   regulator: max776...
246
247
  		config.regmap = max77693_get_regmap(type, iodev,
  						    regulators[i].id);
640c24a77   Krzysztof Kozlowski   regulator: max776...
248
  		rdev = devm_regulator_register(&pdev->dev,
222d0f043   Krzysztof Kozlowski   regulator: max776...
249
  						&regulators[i], &config);
640c24a77   Krzysztof Kozlowski   regulator: max776...
250
251
  		if (IS_ERR(rdev)) {
  			dev_err(&pdev->dev,
222d0f043   Krzysztof Kozlowski   regulator: max776...
252
253
  				"Failed to initialize regulator-%d
  ", i);
640c24a77   Krzysztof Kozlowski   regulator: max776...
254
  			return PTR_ERR(rdev);
80b022e29   Jonghwa Lee   regulator: max776...
255
256
257
258
  		}
  	}
  
  	return 0;
80b022e29   Jonghwa Lee   regulator: max776...
259
260
261
  }
  
  static const struct platform_device_id max77693_pmic_id[] = {
5b5e771fb   Krzysztof Kozlowski   regulator: max776...
262
  	{ "max77693-pmic", TYPE_MAX77693 },
9e9a08e86   Krzysztof Kozlowski   regulator: max776...
263
  	{ "max77843-regulator", TYPE_MAX77843 },
80b022e29   Jonghwa Lee   regulator: max776...
264
265
266
267
268
269
270
271
  	{},
  };
  
  MODULE_DEVICE_TABLE(platform, max77693_pmic_id);
  
  static struct platform_driver max77693_pmic_driver = {
  	.driver = {
  		   .name = "max77693-pmic",
80b022e29   Jonghwa Lee   regulator: max776...
272
273
  		   },
  	.probe = max77693_pmic_probe,
80b022e29   Jonghwa Lee   regulator: max776...
274
275
  	.id_table = max77693_pmic_id,
  };
ee3010d0a   Marek Szyprowski   regulators: max77...
276
277
278
279
280
281
282
283
284
285
286
  static int __init max77693_pmic_init(void)
  {
  	return platform_driver_register(&max77693_pmic_driver);
  }
  subsys_initcall(max77693_pmic_init);
  
  static void __exit max77693_pmic_cleanup(void)
  {
  	platform_driver_unregister(&max77693_pmic_driver);
  }
  module_exit(max77693_pmic_cleanup);
80b022e29   Jonghwa Lee   regulator: max776...
287

9e9a08e86   Krzysztof Kozlowski   regulator: max776...
288
  MODULE_DESCRIPTION("MAXIM 77693/77843 regulator driver");
80b022e29   Jonghwa Lee   regulator: max776...
289
  MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
cea8aa3a9   Krzysztof Kozlowski   regulator: Change...
290
  MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
80b022e29   Jonghwa Lee   regulator: max776...
291
  MODULE_LICENSE("GPL");