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/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/mfd/sy7636a.h>
16 #define SY7636A_POLL_ENABLED_TIME 500
18 static int sy7636a_get_vcom_voltage_op(struct regulator_dev
*rdev
)
21 unsigned int val
, val_h
;
23 ret
= regmap_read(rdev
->regmap
, SY7636A_REG_VCOM_ADJUST_CTRL_L
, &val
);
27 ret
= regmap_read(rdev
->regmap
, SY7636A_REG_VCOM_ADJUST_CTRL_H
, &val_h
);
31 val
|= (val_h
<< VCOM_ADJUST_CTRL_SHIFT
);
33 return (val
& VCOM_ADJUST_CTRL_MASK
) * VCOM_ADJUST_CTRL_SCAL
;
36 static int sy7636a_get_status(struct regulator_dev
*rdev
)
38 struct sy7636a
*sy7636a
= rdev_get_drvdata(rdev
);
41 ret
= gpiod_get_value_cansleep(sy7636a
->pgood_gpio
);
43 dev_err(&rdev
->dev
, "Failed to read pgood gpio: %d\n", ret
);
48 static const struct regulator_ops sy7636a_vcom_volt_ops
= {
49 .get_voltage
= sy7636a_get_vcom_voltage_op
,
50 .enable
= regulator_enable_regmap
,
51 .disable
= regulator_disable_regmap
,
52 .is_enabled
= regulator_is_enabled_regmap
,
53 .get_status
= sy7636a_get_status
,
56 static const struct regulator_desc desc
= {
59 .ops
= &sy7636a_vcom_volt_ops
,
60 .type
= REGULATOR_VOLTAGE
,
62 .enable_reg
= SY7636A_REG_OPERATION_MODE_CRL
,
63 .enable_mask
= SY7636A_OPERATION_MODE_CRL_ONOFF
,
64 .poll_enabled_time
= SY7636A_POLL_ENABLED_TIME
,
65 .regulators_node
= of_match_ptr("regulators"),
66 .of_match
= of_match_ptr("vcom"),
69 static int sy7636a_regulator_probe(struct platform_device
*pdev
)
71 struct sy7636a
*sy7636a
= dev_get_drvdata(pdev
->dev
.parent
);
72 struct regulator_config config
= { };
73 struct regulator_dev
*rdev
;
74 struct gpio_desc
*gdp
;
80 platform_set_drvdata(pdev
, sy7636a
);
82 gdp
= devm_gpiod_get(sy7636a
->dev
, "epd-pwr-good", GPIOD_IN
);
84 dev_err(sy7636a
->dev
, "Power good GPIO fault %ld\n", PTR_ERR(gdp
));
88 sy7636a
->pgood_gpio
= gdp
;
90 ret
= regmap_write(sy7636a
->regmap
, SY7636A_REG_POWER_ON_DELAY_TIME
, 0x0);
92 dev_err(sy7636a
->dev
, "Failed to initialize regulator: %d\n", ret
);
96 config
.dev
= &pdev
->dev
;
97 config
.dev
->of_node
= sy7636a
->dev
->of_node
;
98 config
.driver_data
= sy7636a
;
99 config
.regmap
= sy7636a
->regmap
;
101 rdev
= devm_regulator_register(&pdev
->dev
, &desc
, &config
);
103 dev_err(sy7636a
->dev
, "Failed to register %s regulator\n",
105 return PTR_ERR(rdev
);
111 static const struct platform_device_id sy7636a_regulator_id_table
[] = {
112 { "sy7636a-regulator", },
115 MODULE_DEVICE_TABLE(platform
, sy7636a_regulator_id_table
);
117 static struct platform_driver sy7636a_regulator_driver
= {
119 .name
= "sy7636a-regulator",
121 .probe
= sy7636a_regulator_probe
,
122 .id_table
= sy7636a_regulator_id_table
,
124 module_platform_driver(sy7636a_regulator_driver
);
126 MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
127 MODULE_DESCRIPTION("SY7636A voltage regulator driver");
128 MODULE_LICENSE("GPL v2");