Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Functions to access SY3686A power management chip voltages
0004 //
0005 // Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
0006 //
0007 // Authors: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
0008 //          Alistair Francis <alistair@alistair23.me>
0009 
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/i2c.h>
0012 #include <linux/mfd/sy7636a.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regulator/driver.h>
0016 #include <linux/regulator/machine.h>
0017 #include <linux/regmap.h>
0018 
0019 struct sy7636a_data {
0020     struct regmap *regmap;
0021     struct gpio_desc *pgood_gpio;
0022 };
0023 
0024 static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
0025 {
0026     int ret;
0027     unsigned int val, val_h;
0028 
0029     ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, &val);
0030     if (ret)
0031         return ret;
0032 
0033     ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_H, &val_h);
0034     if (ret)
0035         return ret;
0036 
0037     val |= (val_h << VCOM_ADJUST_CTRL_SHIFT);
0038 
0039     return (val & VCOM_ADJUST_CTRL_MASK) * VCOM_ADJUST_CTRL_SCAL;
0040 }
0041 
0042 static int sy7636a_get_status(struct regulator_dev *rdev)
0043 {
0044     struct sy7636a_data *data = dev_get_drvdata(rdev->dev.parent);
0045     int ret = 0;
0046 
0047     ret = gpiod_get_value_cansleep(data->pgood_gpio);
0048     if (ret < 0)
0049         dev_err(&rdev->dev, "Failed to read pgood gpio: %d\n", ret);
0050 
0051     return ret;
0052 }
0053 
0054 static const struct regulator_ops sy7636a_vcom_volt_ops = {
0055     .get_voltage = sy7636a_get_vcom_voltage_op,
0056     .enable = regulator_enable_regmap,
0057     .disable = regulator_disable_regmap,
0058     .is_enabled = regulator_is_enabled_regmap,
0059     .get_status = sy7636a_get_status,
0060 };
0061 
0062 static const struct regulator_desc desc = {
0063     .name = "vcom",
0064     .id = 0,
0065     .ops = &sy7636a_vcom_volt_ops,
0066     .type = REGULATOR_VOLTAGE,
0067     .owner = THIS_MODULE,
0068     .enable_reg = SY7636A_REG_OPERATION_MODE_CRL,
0069     .enable_mask = SY7636A_OPERATION_MODE_CRL_ONOFF,
0070     .regulators_node = of_match_ptr("regulators"),
0071     .of_match = of_match_ptr("vcom"),
0072 };
0073 
0074 static int sy7636a_regulator_probe(struct platform_device *pdev)
0075 {
0076     struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL);
0077     struct regulator_config config = { };
0078     struct regulator_dev *rdev;
0079     struct gpio_desc *gdp;
0080     struct sy7636a_data *data;
0081     int ret;
0082 
0083     if (!regmap)
0084         return -EPROBE_DEFER;
0085 
0086     gdp = devm_gpiod_get(pdev->dev.parent, "epd-pwr-good", GPIOD_IN);
0087     if (IS_ERR(gdp)) {
0088         dev_err(pdev->dev.parent, "Power good GPIO fault %ld\n", PTR_ERR(gdp));
0089         return PTR_ERR(gdp);
0090     }
0091 
0092     data = devm_kzalloc(&pdev->dev, sizeof(struct sy7636a_data), GFP_KERNEL);
0093     if (!data)
0094         return -ENOMEM;
0095 
0096     data->regmap = regmap;
0097     data->pgood_gpio = gdp;
0098 
0099     platform_set_drvdata(pdev, data);
0100 
0101     ret = regmap_write(regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
0102     if (ret) {
0103         dev_err(pdev->dev.parent, "Failed to initialize regulator: %d\n", ret);
0104         return ret;
0105     }
0106 
0107     config.dev = &pdev->dev;
0108     config.dev->of_node = pdev->dev.parent->of_node;
0109     config.regmap = regmap;
0110 
0111     rdev = devm_regulator_register(&pdev->dev, &desc, &config);
0112     if (IS_ERR(rdev)) {
0113         dev_err(pdev->dev.parent, "Failed to register %s regulator\n",
0114             pdev->name);
0115         return PTR_ERR(rdev);
0116     }
0117 
0118     return 0;
0119 }
0120 
0121 static const struct platform_device_id sy7636a_regulator_id_table[] = {
0122     { "sy7636a-regulator", },
0123     { }
0124 };
0125 MODULE_DEVICE_TABLE(platform, sy7636a_regulator_id_table);
0126 
0127 static struct platform_driver sy7636a_regulator_driver = {
0128     .driver = {
0129         .name = "sy7636a-regulator",
0130     },
0131     .probe = sy7636a_regulator_probe,
0132     .id_table = sy7636a_regulator_id_table,
0133 };
0134 module_platform_driver(sy7636a_regulator_driver);
0135 
0136 MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
0137 MODULE_DESCRIPTION("SY7636A voltage regulator driver");
0138 MODULE_LICENSE("GPL v2");