Re: [PATCH 07/19] clk: tegra: dfll: support PWM regulator control

Jon Hunter
2018-12-07T15:09:10Z

On 04/12/2018 09:25, Joseph Lo wrote:
> The DFLL hardware supports two modes (I2C and PWM) for voltage control
> when requesting a frequency. In this patch, we introduce PWM mode support.
>
> To support that, we re-organize the LUT for unifying the table for both
> cases of I2C and PWM mode. And generate that based on regulator info.
> For the PWM-based regulator, we get this info from DT. And do the same as
> the case of I2C LUT, which can help to map the PMIC voltage ID and voltages
> that the regulator supported.
>
> The other parts are the support code for initializing the DFLL hardware
> to support PWM mode. Also, the register debugfs file is slightly
> reworked to only show the i2c registers when I2C mode is in use.
>
> Based on the work of Peter De Schrijver <pdeschrijver@nvidia.com>.
>
> Signed-off-by: Joseph Lo <josephl@nvidia.com>
> ---
> drivers/clk/tegra/clk-dfll.c | 431 ++++++++++++++++++++++++++++++-----
> 1 file changed, 368 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
> index 609e363dabf8..c294a2989f31 100644
> --- a/drivers/clk/tegra/clk-dfll.c
> +++ b/drivers/clk/tegra/clk-dfll.c
> @@ -1,7 +1,7 @@
> /*
> * clk-dfll.c - Tegra DFLL clock source common code
> *
> - * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
> + * Copyright (C) 2012-2018 NVIDIA Corporation. All rights reserved.
> *
> * Aleksandr Frid <afrid@nvidia.com>
> * Paul Walmsley <pwalmsley@nvidia.com>
> @@ -47,6 +47,7 @@
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/pinctrl/consumer.h>
> #include <linux/pm_opp.h>
> #include <linux/pm_runtime.h>
> #include <linux/regmap.h>
> @@ -243,6 +244,12 @@ enum dfll_tune_range {
> DFLL_TUNE_LOW = 1,
> };
>
> +
> +enum tegra_dfll_pmu_if {
> + TEGRA_DFLL_PMU_I2C = 0,
> + TEGRA_DFLL_PMU_PWM = 1,
> +};
> +
> /**
> * struct dfll_rate_req - target DFLL rate request data
> * @rate: target frequency, after the postscaling
> @@ -294,16 +301,25 @@ struct tegra_dfll {
> u32 ci;
> u32 cg;
> bool cg_scale;
> + u32 reg_init_uV;
>
> /* I2C interface parameters */
> u32 i2c_fs_rate;
> u32 i2c_reg;
> u32 i2c_slave_addr;
>
> - /* i2c_lut array entries are regulator framework selectors */
> - unsigned i2c_lut[MAX_DFLL_VOLTAGES];
> - int i2c_lut_size;
> - u8 lut_min, lut_max, lut_safe;
> + /* lut array entries are regulator framework selectors or PWM values*/
> + unsigned lut[MAX_DFLL_VOLTAGES];
> + unsigned lut_uv[MAX_DFLL_VOLTAGES];
> + int lut_size;
> + u8 lut_bottom, lut_min, lut_max, lut_safe;
> +
> + /* PWM interface */
> + enum tegra_dfll_pmu_if pmu_if;
> + unsigned long pwm_rate;
> + struct pinctrl *pwm_pin;
> + struct pinctrl_state *pwm_enable_state;
> + struct pinctrl_state *pwm_disable_state;
> };
>
> #define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
> @@ -489,6 +505,34 @@ static void dfll_set_mode(struct tegra_dfll *td,
> dfll_wmb(td);
> }
>
> +/*
> + * DVCO rate control
> + */
> +
> +static unsigned long get_dvco_rate_below(struct tegra_dfll *td, u8 out_min)
> +{
> + struct dev_pm_opp *opp;
> + unsigned long rate, prev_rate;
> + int uv, min_uv;
> +
> + min_uv = td->lut_uv[out_min];
> + for (rate = 0, prev_rate = 0; ; rate++) {
> + opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
> + if (IS_ERR(opp))
> + break;
> +
> + uv = dev_pm_opp_get_voltage(opp);

Can you fix the type of 'uv' here? It should be unsigned long.

Cheers
Jon

--
nvpublic