1 // SPDX-License-Identifier: GPL-2.0+
3 // Functions to access SY3686A power management chip voltages
5 // Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
7 // Authors: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
8 // Alistair Francis <alistair@alistair23.me>
10 #include <linux/gpio/consumer.h>
11 #include <linux/i2c.h>
12 #include <linux/mfd/sy7636a.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/regulator/driver.h>
16 #include <linux/regulator/machine.h>
17 #include <linux/regmap.h>
20 struct regmap
*regmap
;
21 struct gpio_desc
*pgood_gpio
;
24 static int sy7636a_get_vcom_voltage_op(struct regulator_dev
*rdev
)
27 unsigned int val
, val_h
;
29 ret
= regmap_read(rdev
->regmap
, SY7636A_REG_VCOM_ADJUST_CTRL_L
, &val
);
33 ret
= regmap_read(rdev
->regmap
, SY7636A_REG_VCOM_ADJUST_CTRL_H
, &val_h
);
37 val
|= (val_h
<< VCOM_ADJUST_CTRL_SHIFT
);
39 return (val
& VCOM_ADJUST_CTRL_MASK
) * VCOM_ADJUST_CTRL_SCAL
;
42 static int sy7636a_get_status(struct regulator_dev
*rdev
)
44 struct sy7636a_data
*data
= dev_get_drvdata(rdev
->dev
.parent
);
47 ret
= gpiod_get_value_cansleep(data
->pgood_gpio
);
49 dev_err(&rdev
->dev
, "Failed to read pgood gpio: %d\n", ret
);
54 static const struct regulator_ops sy7636a_vcom_volt_ops
= {
55 .get_voltage
= sy7636a_get_vcom_voltage_op
,
56 .enable
= regulator_enable_regmap
,
57 .disable
= regulator_disable_regmap
,
58 .is_enabled
= regulator_is_enabled_regmap
,
59 .get_status
= sy7636a_get_status
,
62 static const struct regulator_desc desc
= {
65 .ops
= &sy7636a_vcom_volt_ops
,
66 .type
= REGULATOR_VOLTAGE
,
68 .enable_reg
= SY7636A_REG_OPERATION_MODE_CRL
,
69 .enable_mask
= SY7636A_OPERATION_MODE_CRL_ONOFF
,
70 .regulators_node
= of_match_ptr("regulators"),
71 .of_match
= of_match_ptr("vcom"),
74 static int sy7636a_regulator_probe(struct platform_device
*pdev
)
76 struct regmap
*regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
77 struct regulator_config config
= { };
78 struct regulator_dev
*rdev
;
79 struct gpio_desc
*gdp
;
80 struct sy7636a_data
*data
;
86 gdp
= devm_gpiod_get(pdev
->dev
.parent
, "epd-pwr-good", GPIOD_IN
);
88 dev_err(pdev
->dev
.parent
, "Power good GPIO fault %ld\n", PTR_ERR(gdp
));
92 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct sy7636a_data
), GFP_KERNEL
);
96 data
->regmap
= regmap
;
97 data
->pgood_gpio
= gdp
;
99 platform_set_drvdata(pdev
, data
);
101 ret
= regmap_write(regmap
, SY7636A_REG_POWER_ON_DELAY_TIME
, 0x0);
103 dev_err(pdev
->dev
.parent
, "Failed to initialize regulator: %d\n", ret
);
107 config
.dev
= &pdev
->dev
;
108 config
.dev
->of_node
= pdev
->dev
.parent
->of_node
;
109 config
.regmap
= regmap
;
111 rdev
= devm_regulator_register(&pdev
->dev
, &desc
, &config
);
113 dev_err(pdev
->dev
.parent
, "Failed to register %s regulator\n",
115 return PTR_ERR(rdev
);
121 static const struct platform_device_id sy7636a_regulator_id_table
[] = {
122 { "sy7636a-regulator", },
125 MODULE_DEVICE_TABLE(platform
, sy7636a_regulator_id_table
);
127 static struct platform_driver sy7636a_regulator_driver
= {
129 .name
= "sy7636a-regulator",
130 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
132 .probe
= sy7636a_regulator_probe
,
133 .id_table
= sy7636a_regulator_id_table
,
135 module_platform_driver(sy7636a_regulator_driver
);
137 MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
138 MODULE_DESCRIPTION("SY7636A voltage regulator driver");
139 MODULE_LICENSE("GPL v2");