uboot/drivers/power/regulator/pwm_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Rockchip Electronics Co., Ltd
   4 *
   5 * Based on kernel drivers/regulator/pwm-regulator.c
   6 * Copyright (C) 2014 - STMicroelectronics Inc.
   7 * Author: Lee Jones <lee.jones@linaro.org>
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <errno.h>
  13#include <pwm.h>
  14#include <power/regulator.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18struct pwm_regulator_info {
  19        /* pwm id corresponding to the PWM driver */
  20        int pwm_id;
  21        /* the period of one PWM cycle */
  22        int period_ns;
  23        /*
  24         * the polarity of one PWM
  25         * 0: normal polarity
  26         * 1: inverted polarity
  27         */
  28        bool polarity;
  29        struct udevice *pwm;
  30        /* initialize voltage of regulator */
  31        int init_voltage;
  32        /* the maximum voltage of regulator */
  33        int max_voltage;
  34        /* the minimum voltage of regulator */
  35        int min_voltage;
  36        /* the current voltage of regulator */
  37        int volt_uV;
  38};
  39
  40static int pwm_regulator_enable(struct udevice *dev, bool enable)
  41{
  42        struct pwm_regulator_info *priv = dev_get_priv(dev);
  43
  44        return pwm_set_enable(priv->pwm, priv->pwm_id, enable);
  45}
  46
  47static int pwm_voltage_to_duty_cycle_percentage(struct udevice *dev, int req_uV)
  48{
  49        struct pwm_regulator_info *priv = dev_get_priv(dev);
  50        int min_uV = priv->min_voltage;
  51        int max_uV = priv->max_voltage;
  52        int diff = max_uV - min_uV;
  53
  54        return ((req_uV * 100) - (min_uV * 100)) / diff;
  55}
  56
  57static int pwm_regulator_get_voltage(struct udevice *dev)
  58{
  59        struct pwm_regulator_info *priv = dev_get_priv(dev);
  60
  61        return priv->volt_uV;
  62}
  63
  64static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt)
  65{
  66        struct pwm_regulator_info *priv = dev_get_priv(dev);
  67        int duty_cycle;
  68        int ret = 0;
  69
  70        duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt);
  71
  72        ret = pwm_set_invert(priv->pwm, priv->pwm_id, priv->polarity);
  73        if (ret) {
  74                dev_err(dev, "Failed to init PWM\n");
  75                return ret;
  76        }
  77
  78        ret = pwm_set_config(priv->pwm, priv->pwm_id,
  79                        priv->period_ns, (priv->period_ns / 100) * duty_cycle);
  80        if (ret) {
  81                dev_err(dev, "Failed to configure PWM\n");
  82                return ret;
  83        }
  84
  85        priv->volt_uV = uvolt;
  86
  87        return ret;
  88}
  89
  90static int pwm_regulator_ofdata_to_platdata(struct udevice *dev)
  91{
  92        struct pwm_regulator_info *priv = dev_get_priv(dev);
  93        struct ofnode_phandle_args args;
  94        int ret;
  95
  96        ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, &args);
  97        if (ret) {
  98                debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
  99                return ret;
 100        }
 101
 102        priv->period_ns = args.args[1];
 103        priv->polarity = args.args[2];
 104
 105        priv->init_voltage = dev_read_u32_default(dev, "regulator-init-microvolt", -1);
 106        if (priv->init_voltage < 0) {
 107                printf("Cannot find regulator pwm init_voltage\n");
 108                return -EINVAL;
 109        }
 110
 111        ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm);
 112        if (ret) {
 113                debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
 114                return ret;
 115        }
 116
 117        return 0;
 118}
 119
 120static int pwm_regulator_probe(struct udevice *dev)
 121{
 122        struct pwm_regulator_info *priv = dev_get_priv(dev);
 123        struct dm_regulator_uclass_platdata *uc_pdata;
 124
 125        uc_pdata = dev_get_uclass_platdata(dev);
 126
 127        uc_pdata->type = REGULATOR_TYPE_BUCK;
 128        uc_pdata->mode_count = 0;
 129        priv->max_voltage = uc_pdata->max_uV;
 130        priv->min_voltage = uc_pdata->min_uV;
 131
 132        if (priv->init_voltage)
 133                pwm_regulator_set_voltage(dev, priv->init_voltage);
 134
 135        return 0;
 136}
 137
 138static const struct dm_regulator_ops pwm_regulator_ops = {
 139        .get_value  = pwm_regulator_get_voltage,
 140        .set_value  = pwm_regulator_set_voltage,
 141        .set_enable = pwm_regulator_enable,
 142};
 143
 144static const struct udevice_id pwm_regulator_ids[] = {
 145        { .compatible = "pwm-regulator" },
 146        { }
 147};
 148
 149U_BOOT_DRIVER(pwm_regulator) = {
 150        .name = "pwm_regulator",
 151        .id = UCLASS_REGULATOR,
 152        .ops = &pwm_regulator_ops,
 153        .probe = pwm_regulator_probe,
 154        .of_match = pwm_regulator_ids,
 155        .ofdata_to_platdata     = pwm_regulator_ofdata_to_platdata,
 156        .priv_auto_alloc_size   = sizeof(struct pwm_regulator_info),
 157};
 158