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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/7/18 11:09 PM, Jon Hunter wrote:

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@xxxxxxxxxx>.

Signed-off-by: Joseph Lo <josephl@xxxxxxxxxx>
---
  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@xxxxxxxxxx>
   * Paul Walmsley <pwalmsley@xxxxxxxxxx>
@@ -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.

Okay, will fix it. Thanks.




[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux