linux/drivers/regulator/sy7636a-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// Functions to access SY3686A power management chip voltages
   4//
   5// Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
   6//
   7// Authors: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
   8//          Alistair Francis <alistair@alistair23.me>
   9
  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>
  15
  16#define SY7636A_POLL_ENABLED_TIME 500
  17
  18static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
  19{
  20        int ret;
  21        unsigned int val, val_h;
  22
  23        ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, &val);
  24        if (ret)
  25                return ret;
  26
  27        ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_H, &val_h);
  28        if (ret)
  29                return ret;
  30
  31        val |= (val_h << VCOM_ADJUST_CTRL_SHIFT);
  32
  33        return (val & VCOM_ADJUST_CTRL_MASK) * VCOM_ADJUST_CTRL_SCAL;
  34}
  35
  36static int sy7636a_get_status(struct regulator_dev *rdev)
  37{
  38        struct sy7636a *sy7636a = rdev_get_drvdata(rdev);
  39        int ret = 0;
  40
  41        ret = gpiod_get_value_cansleep(sy7636a->pgood_gpio);
  42        if (ret < 0)
  43                dev_err(&rdev->dev, "Failed to read pgood gpio: %d\n", ret);
  44
  45        return ret;
  46}
  47
  48static 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,
  54};
  55
  56static const struct regulator_desc desc = {
  57        .name = "vcom",
  58        .id = 0,
  59        .ops = &sy7636a_vcom_volt_ops,
  60        .type = REGULATOR_VOLTAGE,
  61        .owner = THIS_MODULE,
  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"),
  67};
  68
  69static int sy7636a_regulator_probe(struct platform_device *pdev)
  70{
  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;
  75        int ret;
  76
  77        if (!sy7636a)
  78                return -EPROBE_DEFER;
  79
  80        platform_set_drvdata(pdev, sy7636a);
  81
  82        gdp = devm_gpiod_get(sy7636a->dev, "epd-pwr-good", GPIOD_IN);
  83        if (IS_ERR(gdp)) {
  84                dev_err(sy7636a->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp));
  85                return PTR_ERR(gdp);
  86        }
  87
  88        sy7636a->pgood_gpio = gdp;
  89
  90        ret = regmap_write(sy7636a->regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
  91        if (ret) {
  92                dev_err(sy7636a->dev, "Failed to initialize regulator: %d\n", ret);
  93                return ret;
  94        }
  95
  96        config.dev = &pdev->dev;
  97        config.dev->of_node = sy7636a->dev->of_node;
  98        config.driver_data = sy7636a;
  99        config.regmap = sy7636a->regmap;
 100
 101        rdev = devm_regulator_register(&pdev->dev, &desc, &config);
 102        if (IS_ERR(rdev)) {
 103                dev_err(sy7636a->dev, "Failed to register %s regulator\n",
 104                        pdev->name);
 105                return PTR_ERR(rdev);
 106        }
 107
 108        return 0;
 109}
 110
 111static const struct platform_device_id sy7636a_regulator_id_table[] = {
 112        { "sy7636a-regulator", },
 113        { }
 114};
 115MODULE_DEVICE_TABLE(platform, sy7636a_regulator_id_table);
 116
 117static struct platform_driver sy7636a_regulator_driver = {
 118        .driver = {
 119                .name = "sy7636a-regulator",
 120        },
 121        .probe = sy7636a_regulator_probe,
 122        .id_table = sy7636a_regulator_id_table,
 123};
 124module_platform_driver(sy7636a_regulator_driver);
 125
 126MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
 127MODULE_DESCRIPTION("SY7636A voltage regulator driver");
 128MODULE_LICENSE("GPL v2");
 129