File Index
Files and directories
Sign in
FILE

fp9931.c

File preview with syntax highlighting.

linux-6.19.14/drivers/regulator/fp9931.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2// Copyright (C) 2025 Andreas Kemnade
  3
  4/* Datasheet: https://www.fitipower.com/dl/file/flXa6hIchVeu0W3K */
  5
  6#include <linux/cleanup.h>
  7#include <linux/completion.h>
  8#include <linux/gpio/consumer.h>
  9#include <linux/i2c.h>
 10#include <linux/module.h>
 11#include <linux/mutex.h>
 12#include <linux/hwmon.h>
 13#include <linux/pm_runtime.h>
 14#include <linux/property.h>
 15#include <linux/regulator/consumer.h>
 16#include <linux/regulator/driver.h>
 17#include <linux/regulator/machine.h>
 18#include <linux/regmap.h>
 19
 20#define FP9931_REG_TMST_VALUE 0
 21#define FP9931_REG_VCOM_SETTING 1
 22#define FP9931_REG_VPOSNEG_SETTING 2
 23#define FP9931_REG_PWRON_DELAY 3
 24#define FP9931_REG_CONTROL_REG1 11
 25
 26#define PGOOD_TIMEOUT_MSECS 200
 27
 28struct fp9931_data {
 29	struct device *dev;
 30	struct regmap *regmap;
 31	struct regulator *vin_reg;
 32	struct gpio_desc *pgood_gpio;
 33	struct gpio_desc *en_gpio;
 34	struct gpio_desc *en_ts_gpio;
 35	struct completion pgood_completion;
 36	int pgood_irq;
 37};
 38
 39static const unsigned int VPOSNEG_table[] = {
 40	7040000,
 41	7040000,
 42	7040000,
 43	7040000,
 44	7040000,
 45	7040000,
 46	7260000,
 47	7490000,
 48	7710000,
 49	7930000,
 50	8150000,
 51	8380000,
 52	8600000,
 53	8820000,
 54	9040000,
 55	9270000,
 56	9490000,
 57	9710000,
 58	9940000,
 59	10160000,
 60	10380000,
 61	10600000,
 62	10830000,
 63	11050000,
 64	11270000,
 65	11490000,
 66	11720000,
 67	11940000,
 68	12160000,
 69	12380000,
 70	12610000,
 71	12830000,
 72	13050000,
 73	13280000,
 74	13500000,
 75	13720000,
 76	13940000,
 77	14170000,
 78	14390000,
 79	14610000,
 80	14830000,
 81	15060000,
 82};
 83
 84static const struct hwmon_channel_info *fp9931_info[] = {
 85	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
 86	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
 87	NULL
 88};
 89
 90static int setup_timings(struct fp9931_data *data)
 91{
 92	u32 tdly[4];
 93	u8 tdlys = 0;
 94	int i;
 95	int ret;
 96
 97	ret = device_property_count_u32(data->dev, "fitipower,tdly-ms");
 98	if (ret == -EINVAL) /* property is optional */
 99		return 0;
100
101	if (ret < 0)
102		return ret;
103
104	if (ret != ARRAY_SIZE(tdly)) {
105		dev_err(data->dev, "invalid delay specification");
106		return -EINVAL;
107	}
108
109	ret = device_property_read_u32_array(data->dev, "fitipower,tdly-ms",
110					     tdly, ARRAY_SIZE(tdly));
111	if (ret)
112		return ret;
113
114	for (i = ARRAY_SIZE(tdly) - 1; i >= 0; i--) {
115		if (tdly[i] > 4 || tdly[i] == 3)
116			return -EINVAL;
117
118		if (tdly[i] == 4) /* convert from ms */
119			tdly[i] = 3;
120
121		tdlys <<= 2;
122		tdlys |= tdly[i];
123	}
124
125	ret = pm_runtime_resume_and_get(data->dev);
126	if (ret < 0)
127		return ret;
128
129	ret = regmap_write(data->regmap, FP9931_REG_PWRON_DELAY, tdlys);
130	pm_runtime_put_autosuspend(data->dev);
131
132	return ret;
133}
134
135static int fp9931_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
136			     u32 attr, int channel, long *temp)
137{
138	struct fp9931_data *data = dev_get_drvdata(dev);
139	unsigned int val;
140	int ret;
141
142	ret = pm_runtime_resume_and_get(data->dev);
143	if (ret < 0)
144		return ret;
145
146	ret = regmap_read(data->regmap, FP9931_REG_TMST_VALUE, &val);
147	if (!ret)
148		*temp = (s8)val * 1000;
149
150	pm_runtime_put_autosuspend(data->dev);
151
152	return ret;
153}
154
155static umode_t fp9931_hwmon_is_visible(const void *data,
156				       enum hwmon_sensor_types type,
157				       u32 attr, int channel)
158{
159	return 0444;
160}
161
162static const struct hwmon_ops fp9931_hwmon_ops = {
163	.is_visible = fp9931_hwmon_is_visible,
164	.read = fp9931_hwmon_read,
165};
166
167static const struct hwmon_chip_info fp9931_chip_info = {
168	.ops = &fp9931_hwmon_ops,
169	.info = fp9931_info,
170};
171
172static int fp9931_runtime_suspend(struct device *dev)
173{
174	int ret = 0;
175	struct fp9931_data *data = dev_get_drvdata(dev);
176
177	if (data->en_ts_gpio)
178		gpiod_set_value_cansleep(data->en_ts_gpio, 0);
179
180	if (data->vin_reg) {
181		ret = regulator_disable(data->vin_reg);
182		regcache_mark_dirty(data->regmap);
183	}
184
185	return ret;
186}
187
188static int fp9931_runtime_resume(struct device *dev)
189{
190	int ret = 0;
191	struct fp9931_data *data = dev_get_drvdata(dev);
192
193	if (data->vin_reg)
194		ret = regulator_enable(data->vin_reg);
195
196	if (ret)
197		return ret;
198
199	if (data->en_ts_gpio) {
200		gpiod_set_value_cansleep(data->en_ts_gpio, 1);
201		/* wait for one ADC conversion to have sane temperature */
202		usleep_range(10000, 15000);
203	}
204
205	ret = regcache_sync(data->regmap);
206
207	return ret;
208}
209
210static bool fp9931_volatile_reg(struct device *dev, unsigned int reg)
211{
212	return reg == FP9931_REG_TMST_VALUE;
213}
214
215static const struct reg_default fp9931_reg_default = {
216	.reg = FP9931_REG_VCOM_SETTING,
217	.def = 0x80,
218};
219
220static const struct regmap_config regmap_config = {
221	.reg_bits = 8,
222	.val_bits = 8,
223	.max_register = 12,
224	.cache_type = REGCACHE_FLAT,
225	.volatile_reg = fp9931_volatile_reg,
226	.reg_defaults = &fp9931_reg_default,
227	.num_reg_defaults = 1,
228};
229
230static void disable_nopm(void *d)
231{
232	struct fp9931_data *data = d;
233
234	fp9931_runtime_suspend(data->dev);
235}
236
237static int fp9931_v3p3_enable(struct regulator_dev *rdev)
238{
239	struct fp9931_data *data = rdev_get_drvdata(rdev);
240	int ret;
241
242	ret = pm_runtime_resume_and_get(data->dev);
243	if (ret < 0)
244		return ret;
245
246	ret = regulator_enable_regmap(rdev);
247	if (ret < 0)
248		pm_runtime_put_autosuspend(data->dev);
249
250	return ret;
251}
252
253static int fp9931_v3p3_disable(struct regulator_dev *rdev)
254{
255	struct fp9931_data *data = rdev_get_drvdata(rdev);
256	int ret;
257
258	ret = regulator_disable_regmap(rdev);
259	pm_runtime_put_autosuspend(data->dev);
260
261	return ret;
262}
263
264static int fp9931_v3p3_is_enabled(struct regulator_dev *rdev)
265{
266	struct fp9931_data *data = rdev_get_drvdata(rdev);
267	int ret;
268
269	if (pm_runtime_status_suspended(data->dev))
270		return 0;
271
272	ret = pm_runtime_resume_and_get(data->dev);
273	if (ret < 0)
274		return 0;
275
276	ret = regulator_is_enabled_regmap(rdev);
277
278	pm_runtime_put_autosuspend(data->dev);
279	return ret;
280}
281
282static const struct regulator_ops fp9931_v3p3ops = {
283	.list_voltage = regulator_list_voltage_linear,
284	.enable = fp9931_v3p3_enable,
285	.disable = fp9931_v3p3_disable,
286	.is_enabled = fp9931_v3p3_is_enabled,
287};
288
289static int fp9931_check_powergood(struct regulator_dev *rdev)
290{
291	struct fp9931_data *data = rdev_get_drvdata(rdev);
292
293	if (pm_runtime_status_suspended(data->dev))
294		return 0;
295
296	return gpiod_get_value_cansleep(data->pgood_gpio);
297}
298
299static int fp9931_get_voltage_sel(struct regulator_dev *rdev)
300{
301	struct fp9931_data *data = rdev_get_drvdata(rdev);
302	int ret;
303
304	ret = pm_runtime_resume_and_get(data->dev);
305	if (ret < 0)
306		return ret;
307
308	ret = regulator_get_voltage_sel_regmap(rdev);
309	pm_runtime_put_autosuspend(data->dev);
310
311	return ret;
312}
313
314static int fp9931_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
315{
316	struct fp9931_data *data = rdev_get_drvdata(rdev);
317	int ret;
318
319	ret = pm_runtime_resume_and_get(data->dev);
320	if (ret < 0)
321		return ret;
322
323	ret = regulator_set_voltage_sel_regmap(rdev, selector);
324	pm_runtime_put_autosuspend(data->dev);
325
326	return ret;
327}
328
329static irqreturn_t pgood_handler(int irq, void *dev_id)
330{
331	struct fp9931_data *data = dev_id;
332
333	complete(&data->pgood_completion);
334
335	return IRQ_HANDLED;
336}
337
338static int fp9931_set_enable(struct regulator_dev *rdev)
339{
340	struct fp9931_data *data = rdev_get_drvdata(rdev);
341	int ret;
342
343	ret = pm_runtime_resume_and_get(data->dev);
344	if (ret < 0)
345		return ret;
346
347	reinit_completion(&data->pgood_completion);
348	gpiod_set_value_cansleep(data->en_gpio, 1);
349	dev_dbg(data->dev, "turning on...");
350	wait_for_completion_timeout(&data->pgood_completion,
351				    msecs_to_jiffies(PGOOD_TIMEOUT_MSECS));
352	dev_dbg(data->dev, "turned on");
353	if (gpiod_get_value_cansleep(data->pgood_gpio) != 1) {
354		pm_runtime_put_autosuspend(data->dev);
355		return -ETIMEDOUT;
356	}
357
358	return 0;
359}
360
361static int fp9931_clear_enable(struct regulator_dev *rdev)
362{
363	struct fp9931_data *data = rdev_get_drvdata(rdev);
364
365	gpiod_set_value_cansleep(data->en_gpio, 0);
366	pm_runtime_put_autosuspend(data->dev);
367	return 0;
368}
369
370static const struct regulator_ops fp9931_vcom_ops = {
371	.list_voltage = regulator_list_voltage_linear,
372	.map_voltage = regulator_map_voltage_linear,
373	.enable = fp9931_set_enable,
374	.disable = fp9931_clear_enable,
375	.is_enabled = fp9931_check_powergood,
376	.set_voltage_sel = fp9931_set_voltage_sel,
377	.get_voltage_sel = fp9931_get_voltage_sel,
378};
379
380static const struct regulator_ops fp9931_vposneg_ops = {
381	.list_voltage = regulator_list_voltage_table,
382	.map_voltage = regulator_map_voltage_ascend,
383	/* gets enabled by enabling vcom, too */
384	.is_enabled = fp9931_check_powergood,
385	.set_voltage_sel = fp9931_set_voltage_sel,
386	.get_voltage_sel = fp9931_get_voltage_sel,
387};
388
389static const struct regulator_desc regulators[] = {
390	{
391		.name = "v3p3",
392		.of_match = of_match_ptr("v3p3"),
393		.regulators_node = of_match_ptr("regulators"),
394		.id = 0,
395		.ops = &fp9931_v3p3ops,
396		.type = REGULATOR_VOLTAGE,
397		.owner = THIS_MODULE,
398		.enable_reg = FP9931_REG_CONTROL_REG1,
399		.enable_mask = BIT(1),
400		.n_voltages = 1,
401		.min_uV = 3300000
402	},
403	{
404		.name = "vposneg",
405		.of_match = of_match_ptr("vposneg"),
406		.regulators_node = of_match_ptr("regulators"),
407		.id = 1,
408		.ops = &fp9931_vposneg_ops,
409		.type = REGULATOR_VOLTAGE,
410		.owner = THIS_MODULE,
411		.n_voltages = ARRAY_SIZE(VPOSNEG_table),
412		.vsel_reg = FP9931_REG_VPOSNEG_SETTING,
413		.vsel_mask = 0x3F,
414		.volt_table = VPOSNEG_table,
415	},
416	{
417		.name = "vcom",
418		.of_match = of_match_ptr("vcom"),
419		.regulators_node = of_match_ptr("regulators"),
420		.id = 2,
421		.ops = &fp9931_vcom_ops,
422		.type = REGULATOR_VOLTAGE,
423		.owner = THIS_MODULE,
424		.n_voltages = 255,
425		.min_uV = 0,
426		.uV_step = 5000000 / 255,
427		.vsel_reg = FP9931_REG_VCOM_SETTING,
428		.vsel_mask = 0xFF
429	},
430};
431
432static int fp9931_probe(struct i2c_client *client)
433{
434	struct fp9931_data *data;
435	struct regulator_config config = { };
436	struct regulator_dev *rdev;
437	int ret = 0;
438	int i;
439
440	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
441	if (!data)
442		return -ENOMEM;
443
444	data->regmap = devm_regmap_init_i2c(client, &regmap_config);
445	if (IS_ERR(data->regmap))
446		return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
447				     "failed to allocate regmap!\n");
448
449	data->vin_reg = devm_regulator_get_optional(&client->dev, "vin");
450	if (IS_ERR(data->vin_reg))
451		return dev_err_probe(&client->dev, PTR_ERR(data->vin_reg),
452				     "failed to get vin regulator\n");
453
454	data->pgood_gpio = devm_gpiod_get(&client->dev, "pg", GPIOD_IN);
455	if (IS_ERR(data->pgood_gpio))
456		return dev_err_probe(&client->dev,
457				     PTR_ERR(data->pgood_gpio),
458				     "failed to get power good gpio\n");
459
460	data->pgood_irq = gpiod_to_irq(data->pgood_gpio);
461	if (data->pgood_irq < 0)
462		return data->pgood_irq;
463
464	data->en_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
465	if (IS_ERR(data->en_gpio))
466		return dev_err_probe(&client->dev, PTR_ERR(data->en_gpio),
467				     "failed to get en gpio\n");
468
469	data->en_ts_gpio = devm_gpiod_get_optional(&client->dev, "en-ts", GPIOD_OUT_LOW);
470	if (IS_ERR(data->en_ts_gpio))
471		return dev_err_probe(&client->dev,
472				     PTR_ERR(data->en_ts_gpio),
473				     "failed to get en gpio\n");
474
475	data->dev = &client->dev;
476	i2c_set_clientdata(client, data);
477
478	init_completion(&data->pgood_completion);
479
480	ret = devm_request_threaded_irq(&client->dev, data->pgood_irq, NULL,
481					pgood_handler,
482					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
483					"PGOOD", data);
484	if (ret)
485		return dev_err_probe(&client->dev, ret,
486				     "failed to request irq\n");
487
488	if (IS_ENABLED(CONFIG_PM)) {
489		devm_pm_runtime_enable(&client->dev);
490		pm_runtime_set_autosuspend_delay(&client->dev, 4000);
491		pm_runtime_use_autosuspend(&client->dev);
492	} else {
493		ret = fp9931_runtime_resume(&client->dev);
494		if (ret < 0)
495			return ret;
496
497		devm_add_action_or_reset(&client->dev, disable_nopm, data);
498	}
499
500	ret = setup_timings(data);
501	if (ret)
502		return dev_err_probe(&client->dev, ret, "failed to setup timings\n");
503
504	config.driver_data = data;
505	config.dev = &client->dev;
506	config.regmap = data->regmap;
507
508	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
509		rdev = devm_regulator_register(&client->dev, &regulators[i],
510					       &config);
511		if (IS_ERR(rdev))
512			return dev_err_probe(&client->dev, PTR_ERR(rdev),
513					     "failed to register %s regulator\n",
514					     regulators[i].name);
515	}
516
517	if (IS_REACHABLE(CONFIG_HWMON)) {
518		struct device *hwmon_dev;
519
520		hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, "fp9931", data,
521								 &fp9931_chip_info, NULL);
522		if (IS_ERR(hwmon_dev))
523			dev_notice(&client->dev, "failed to register hwmon\n");
524	}
525
526	return 0;
527}
528
529static const struct dev_pm_ops fp9931_pm_ops = {
530	SET_RUNTIME_PM_OPS(fp9931_runtime_suspend, fp9931_runtime_resume, NULL)
531};
532
533static const struct of_device_id fp9931_dt_ids[] = {
534	{
535		.compatible = "fitipower,fp9931",
536	}, {
537		/* sentinel */
538	}
539};
540MODULE_DEVICE_TABLE(of, fp9931_dt_ids);
541
542static struct i2c_driver fp9931_i2c_driver = {
543	.driver = {
544		   .name = "fp9931",
545		   .of_match_table = fp9931_dt_ids,
546		   .pm = &fp9931_pm_ops,
547	},
548	.probe = fp9931_probe,
549};
550
551module_i2c_driver(fp9931_i2c_driver);
552
553/* Module information */
554MODULE_DESCRIPTION("FP9931 regulator driver");
555MODULE_LICENSE("GPL");
556
~/ Read-only file preview.