[PATCH v8 09/18] clk: tegra: Add the DFLL as a possible parent of the cclk_g clock

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The DFLL clocksource was missing from the list of possible parents for
the fast CPU cluster. Add it to the list.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 drivers/clk/tegra/clk-tegra-super-gen4.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c 
b/drivers/clk/tegra/clk-tegra-super-gen4.c
index feb3201..f1f4410 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -44,7 +44,9 @@ static const char *sclk_parents[] = { clk_m, pll_c_out1, 
pll_p_out4,
 
 static const char *cclk_g_parents[] = { clk_m, pll_c, clk_32k, pll_m,
pll_p, pll_p_out4, unused,
-   unused, pll_x };
+   unused, pll_x, unused, unused,
+   unused, unused, unused, unused,
+   dfllCPU_out };
 
 static const char *cclk_lp_parents[] = { clk_m, pll_c, clk_32k, pll_m,
 pll_p, pll_p_out4, unused,
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 17/18] ARM: tegra: Add CPU regulator to the Jetson TK1 device tree

2015-03-01 Thread Mikko Perttunen
Specify the CPU voltage regulator for the cpufreq driver.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts 
b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index f0888dd..e723759 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1782,6 +1782,12 @@
};
};
 
+   cpus {
+   cpu@0 {
+   vdd-cpu-supply = vdd_cpu;
+   };
+   };
+
gpio-keys {
compatible = gpio-keys;
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 11/18] ARM: tegra: Add the DFLL to Tegra124 device tree

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The DFLL clocksource is a separate IP block from the usual
clock-and-reset controller, so it gets its own device tree node.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
v8:
- Changed dfll@ - clock@
- Added dvco reset control

 arch/arm/boot/dts/tegra124.dtsi | 25 +
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 4be06c6..b0f860e 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -4,6 +4,7 @@
 #include dt-bindings/pinctrl/pinctrl-tegra.h
 #include dt-bindings/pinctrl/pinctrl-tegra-xusb.h
 #include dt-bindings/interrupt-controller/arm-gic.h
+#include dt-bindings/reset/tegra124-car.h
 #include dt-bindings/thermal/tegra124-soctherm.h
 
 #include skeleton.dtsi
@@ -670,6 +671,30 @@
#thermal-sensor-cells = 1;
};
 
+   dfll: clock@0,7011 {
+   compatible = nvidia,tegra124-dfll;
+   reg = 0 0x7011 0 0x100, /* DFLL control */
+ 0 0x7011 0 0x100, /* I2C output control */
+ 0 0x70110100 0 0x100, /* Integrated I2C controller */
+ 0 0x70110200 0 0x100; /* Look-up table RAM */
+   interrupts = GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH;
+   clocks = tegra_car TEGRA124_CLK_DFLL_SOC,
+tegra_car TEGRA124_CLK_DFLL_REF,
+tegra_car TEGRA124_CLK_I2C5;
+   clock-names = soc, ref, i2c;
+   resets = tegra_car TEGRA124_RST_DFLL_DVCO;
+   reset-names = dvco;
+   #clock-cells = 0;
+   clock-output-names = dfllCPU_out;
+   nvidia,sample-rate = 12500;
+   nvidia,droop-ctrl = 0x0f00;
+   nvidia,force-mode = 1;
+   nvidia,cf = 10;
+   nvidia,ci = 0;
+   nvidia,cg = 2;
+   status = disabled;
+   };
+
ahub@0,7030 {
compatible = nvidia,tegra124-ahub;
reg = 0x0 0x7030 0x0 0x200,
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 12/18] ARM: tegra: Enable the DFLL on the Jetson TK1

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Add the board-specific properties of the DFLL for the Jetson TK1 board.
On this board, the DFLL will take control of the sd0 regulator on the
on-board AS3722 PMIC.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
v8:
- Changed dfll@ - clock@

 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts 
b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index dbfaba0..f0888dd 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1509,7 +1509,7 @@
vin-ldo9-10-supply = vdd_5v0_sys;
vin-ldo11-supply = vdd_3v3_run;
 
-   sd0 {
+   vdd_cpu: sd0 {
regulator-name = +VDD_CPU_AP;
regulator-min-microvolt = 70;
regulator-max-microvolt = 140;
@@ -1737,6 +1737,13 @@
non-removable;
};
 
+   /* CPU DFLL clock */
+   clock@0,7011 {
+   status = okay;
+   vdd-cpu-supply = vdd_cpu;
+   nvidia,i2c-fs-rate = 40;
+   };
+
ahub@0,7030 {
i2s@0,70301100 {
status = okay;
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 04/18] clk: tegra: Add functions for parsing CVB tables

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Tegra CVB tables encode the relationship between operating voltage
and optimal frequency as a function of the so-called speedo value.
The speedo value is written to the on-chip fuses at the factory,
which allows the voltage-frequency operating points to be calculated
on an per-chip basis.

Add utility functions to parse the Tegra-specific tables and export the
voltage-frequency pairs to the generic OPP framework for other drivers
to use.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Peter De Schrijver pdeschrij...@nvidia.com
---
 arch/arm/mach-tegra/Kconfig |   1 +
 drivers/clk/tegra/cvb.c | 133 
 drivers/clk/tegra/cvb.h |  67 ++
 3 files changed, 201 insertions(+)
 create mode 100644 drivers/clk/tegra/cvb.c
 create mode 100644 drivers/clk/tegra/cvb.h

diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 5d1a318..0fa4c5f 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL
+   select PM_OPP
select ARCH_HAS_RESET_CONTROLLER
select RESET_CONTROLLER
select SOC_BUS
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
new file mode 100644
index 000..69c74ee
--- /dev/null
+++ b/drivers/clk/tegra/cvb.c
@@ -0,0 +1,133 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include linux/err.h
+#include linux/kernel.h
+#include linux/pm_opp.h
+
+#include cvb.h
+
+/* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */
+static inline int get_cvb_voltage(int speedo, int s_scale,
+ const struct cvb_coefficients *cvb)
+{
+   int mv;
+
+   /* apply only speedo scale: output mv = cvb_mv * v_scale */
+   mv = DIV_ROUND_CLOSEST(cvb-c2 * speedo, s_scale);
+   mv = DIV_ROUND_CLOSEST((mv + cvb-c1) * speedo, s_scale) + cvb-c0;
+   return mv;
+}
+
+static int round_cvb_voltage(int mv, int v_scale,
+const struct rail_alignment *align)
+{
+   /* combined: apply voltage scale and round to cvb alignment step */
+   int uv;
+   int step = (align-step_uv ? : 1000) * v_scale;
+   int offset = align-offset_uv * v_scale;
+
+   uv = max(mv * 1000, offset) - offset;
+   uv = DIV_ROUND_UP(uv, step) * align-step_uv + align-offset_uv;
+   return uv / 1000;
+}
+
+enum {
+   DOWN,
+   UP
+};
+
+static int round_voltage(int mv, const struct rail_alignment *align, int up)
+{
+   if (align-step_uv) {
+   int uv;
+
+   uv = max(mv * 1000, align-offset_uv) - align-offset_uv;
+   uv = (uv + (up ? align-step_uv - 1 : 0)) / align-step_uv;
+   return (uv * align-step_uv + align-offset_uv) / 1000;
+   }
+   return mv;
+}
+
+static int build_opp_table(const struct cvb_table *d,
+  int speedo_value,
+  unsigned long max_freq,
+  struct device *opp_dev)
+{
+   int i, ret, dfll_mv, min_mv, max_mv;
+   const struct cvb_table_freq_entry *table = NULL;
+   const struct rail_alignment *align = d-alignment;
+
+   min_mv = round_voltage(d-min_millivolts, align, UP);
+   max_mv = round_voltage(d-max_millivolts, align, DOWN);
+
+   for (i = 0; i  MAX_DVFS_FREQS; i++) {
+   table = d-cvb_table[i];
+   if (!table-freq || (table-freq  max_freq))
+   break;
+
+   dfll_mv = get_cvb_voltage(
+   speedo_value, d-speedo_scale, table-coefficients);
+   dfll_mv = round_cvb_voltage(dfll_mv, d-voltage_scale, align);
+   dfll_mv = clamp(dfll_mv, min_mv, max_mv);
+
+   ret = dev_pm_opp_add(opp_dev, table-freq, dfll_mv * 1000);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+/**
+ * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables
+ * @cvb_tables: array of CVB tables
+ * @sz: size of the previously mentioned array
+ * @process_id: process id of the HW module
+ * @speedo_id: speedo id of the HW module
+ * @speedo_value: speedo value of the HW module
+ * @max_rate: highest safe clock rate

[PATCH v8 18/18] ARM: tegra: enable Tegra124 cpufreq driver by default

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The Tegra124 cpufreq driver depends on CONFIG_CPUFREQ_DT, so
enable it to get the Tegra driver to build by default.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 arch/arm/configs/tegra_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index d199eb2..5eb4bad 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -42,6 +42,7 @@ CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
--
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 14/18] cpufreq: tegra: Rename tegra-cpufreq to tegra20-cpufreq

2015-03-01 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The Tegra124 will use a different driver for frequency scaling, so
rename the old driver (which handles only Tegra20) appropriately.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 drivers/cpufreq/Kconfig.arm| 6 +++---
 drivers/cpufreq/Makefile   | 2 +-
 drivers/cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} | 0
 3 files changed, 4 insertions(+), 4 deletions(-)
 rename drivers/cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} (100%)

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 1b06fc4..08d88ba 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -249,12 +249,12 @@ config ARM_SPEAR_CPUFREQ
help
  This adds the CPUFreq driver support for SPEAr SOCs.
 
-config ARM_TEGRA_CPUFREQ
-   bool TEGRA CPUFreq support
+config ARM_TEGRA20_CPUFREQ
+   bool Tegra20 CPUFreq support
depends on ARCH_TEGRA
default y
help
- This adds the CPUFreq driver support for TEGRA SOCs.
+ This adds the CPUFreq driver support for Tegra20 SOCs.
 
 config ARM_PXA2xx_CPUFREQ
tristate Intel PXA2xx CPUfreq driver
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 82a1821..312d9c3 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -76,7 +76,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
 obj-$(CONFIG_ARM_SA1100_CPUFREQ)   += sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)   += sa1110-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o
-obj-$(CONFIG_ARM_TEGRA_CPUFREQ)+= tegra-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 
 
##
diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
similarity index 100%
rename from drivers/cpufreq/tegra-cpufreq.c
rename to drivers/cpufreq/tegra20-cpufreq.c
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 15/18] cpufreq: Add cpufreq driver for Tegra124

2015-03-03 Thread Mikko Perttunen

On 03/02/2015 10:49 AM, Paul Bolle wrote:

On Sun, 2015-03-01 at 14:44 +0200, Mikko Perttunen wrote:

--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -256,6 +256,13 @@ config ARM_TEGRA20_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra20 SOCs.

+config ARM_TEGRA124_CPUFREQ
+   bool Tegra124 CPUFreq support


This adds a bool Kconfig symbol...


+   depends on ARCH_TEGRA  CPUFREQ_DT
+   default y
+   help
+ This adds the CPUFreq driver support for Tegra124 SOCs.
+
  config ARM_PXA2xx_CPUFREQ
tristate Intel PXA2xx CPUfreq driver
depends on PXA27x || PXA25x
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 312d9c3..d478b83 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)  += sa1100-cpufreq.o
  obj-$(CONFIG_ARM_SA1110_CPUFREQ)  += sa1110-cpufreq.o
  obj-$(CONFIG_ARM_SPEAR_CPUFREQ)   += spear-cpufreq.o
  obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o


... so this object will either not be built or be built-in.


  obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)+= vexpress-spc-cpufreq.o

  
##
diff --git a/drivers/cpufreq/tegra124-cpufreq.c 
b/drivers/cpufreq/tegra124-cpufreq.c
new file mode 100644
index 000..45778ce
--- /dev/null
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -0,0 +1,217 @@
+/*
+ * Tegra 124 cpufreq driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)KBUILD_MODNAME :  fmt
+
+#include linux/clk.h
+#include linux/cpufreq-dt.h
+#include linux/err.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h


Is linux/module.h needed?


+#include linux/of_device.h
+#include linux/of.h
+#include linux/platform_device.h
+#include linux/pm_opp.h
+#include linux/regulator/consumer.h
+#include linux/types.h


[...]


+static struct platform_driver tegra124_cpufreq_platdrv = {
+   .driver = {
+   .name   = cpufreq-tegra124,
+   .owner  = THIS_MODULE,


.owner will always be, in short, NULL.


+   },
+   .probe  = tegra124_cpufreq_probe,
+   .remove = tegra124_cpufreq_remove,
+};


[...]


+module_init(tegra_cpufreq_init);


This might as well be, I think, device_initcall().


+MODULE_AUTHOR(Tuomas Tynkkynen ttynkky...@nvidia.com);
+MODULE_DESCRIPTION(cpufreq driver for NVIDIA Tegra124);
+MODULE_LICENSE(GPL v2);


The strings in these macros will always be preprocessed away, because
this driver cannot become a module.


Paul Bolle



Well noticed! I changed the config symbol to be tristate.

Thanks,
Mikko Perttunen

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3] ARM: tegra: Correct which USB controller has the UTMI pad registers

2015-04-03 Thread Mikko Perttunen

On 04/03/2015 10:21 AM, Tomeu Vizoso wrote:

It should be the first controller, not the second. The indexes of the
usb resets were also wrong and have been fixed.

The issue was caused by the changes in 308efde (ARM: tegra: Add resets
 has-utmi-pad-registers flag to all USB PHYs) being misapplied by git
due to the patch context being insufficient.

This broke USB after 6261b06 (regulator: Defer lookup of supply to
regulator_get), because it changed the order in which the controllers
were probed.

The fix for this issue was suggested by Mikko Perttunen and Tuomas
Tynkkynen.

Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com
Cc: Mikko Perttunen mikko.perttu...@kapsi.fi
Cc: Tuomas Tynkkynen ttynkky...@nvidia.com
---
Hi,

hope I have gotten it right this time, but please do check :)


Yeah, this seems correct to me :)



Thanks,

Tomeu
---
  arch/arm/boot/dts/tegra124.dtsi | 8 
  1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index cf01c81..13cc7ca 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -809,114 +809,114 @@
compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci, 
usb-ehci;
reg = 0x0 0x7d00 0x0 0x4000;
interrupts = GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USBD;
resets = tegra_car 22;
reset-names = usb;
nvidia,phy = phy1;
status = disabled;
};

phy1: usb-phy@0,7d00 {
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d00 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USBD,
 tegra_car TEGRA124_CLK_PLL_U,
 tegra_car TEGRA124_CLK_USBD;
clock-names = reg, pll_u, utmi-pads;
-   resets = tegra_car 59, tegra_car 22;
+   resets = tegra_car 22, tegra_car 22;
reset-names = usb, utmi-pads;
nvidia,hssync-start-delay = 0;
nvidia,idle-wait-delay = 17;
nvidia,elastic-limit = 16;
nvidia,term-range-adj = 6;
nvidia,xcvr-setup = 9;
nvidia,xcvr-lsfslew = 0;
nvidia,xcvr-lsrslew = 3;
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
+   nvidia,has-utmi-pad-registers;
status = disabled;
};

usb@0,7d004000 {
compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci, 
usb-ehci;
reg = 0x0 0x7d004000 0x0 0x4000;
interrupts = GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB2;
resets = tegra_car 58;
reset-names = usb;
nvidia,phy = phy2;
status = disabled;
};

phy2: usb-phy@0,7d004000 {
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d004000 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB2,
 tegra_car TEGRA124_CLK_PLL_U,
 tegra_car TEGRA124_CLK_USBD;
clock-names = reg, pll_u, utmi-pads;
-   resets = tegra_car 22, tegra_car 22;
+   resets = tegra_car 58, tegra_car 22;
reset-names = usb, utmi-pads;
nvidia,hssync-start-delay = 0;
nvidia,idle-wait-delay = 17;
nvidia,elastic-limit = 16;
nvidia,term-range-adj = 6;
nvidia,xcvr-setup = 9;
nvidia,xcvr-lsfslew = 0;
nvidia,xcvr-lsrslew = 3;
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
-   nvidia,has-utmi-pad-registers;
status = disabled;
};

usb@0,7d008000 {
compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci, 
usb-ehci;
reg = 0x0 0x7d008000 0x0 0x4000;
interrupts = GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB3;
resets = tegra_car 59;
reset-names = usb;
nvidia,phy = phy3;
status = disabled;
};

phy3: usb-phy@0,7d008000 {
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d008000 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000

Re: [PATCH v8 10/18] clk: tegra: Initialize PLL_X before CCLK_G to ensure it has a parent

2015-04-13 Thread Mikko Perttunen

On 04/13/2015 10:31 PM, Michael Turquette wrote:

Quoting Tomeu Vizoso (2015-04-13 05:17:01)

On 11 April 2015 at 13:00, Mikko Perttunen mikko.perttu...@kapsi.fi wrote:

On 04/11/2015 12:08 AM, Michael Turquette wrote:


Quoting Mikko Perttunen (2015-03-01 04:44:33)


This patch moves the initialization of PLL_X to be slightly before
that of CCLK_G. This ensures that at boot, CCLK_G will immediately
have a parent and the common clock framework can determine its
clock rate correctly.

Without this patch, calling clk_put on CCLK_G could cause the CCF
to set its rate to zero, hanging the system.



Hi Mikko,

Patch looks fine to me but I wanted to get more info on the behavior you
mentioned above about clk_put. Is there some special circumstance that
causes this for you? Why does calling clk_put adjust the rate of your
clock?

Thanks,
Mike



Hi Mike,

this is the chain of events:
- CCLK_G is registered. CCF stores its current rate, but since it doesn't
have a parent at this point, the rate is assumed zero.
- tegra cpufreq driver tries to probe, and clk_gets CCLK_G
- tegra dfll driver tries to probe, but fails
- tegra cpufreq driver's probe fails, and during unwinding clk_puts CCLK_G
- CCF attempts to restore CCLK_G's rate to what it was prior to the clk_get
(to revert possible changes due to clock constraints)


The CCF will currently only do so if any constraints were set in the
per-user clk that was destroyed, so this particular problem shouldn't
happen any more: ec02ace clk: Only recalculate the rate if needed


Precisely. clk_put shouldn't be setting rates unless we're releasing a
constraint. Can this re-ordering patch be dropped?


Yes.

I'll try to post a (hopefully) final version of the series tomorrow.

Thanks, Mikko.






- the stored rate was zero, so CCLK_G is set to zero.

We did discuss it a bit on IRC with Tomeu and Peter and agreed that some fix
in CCF should be done, but we didn't get much further than that.


Wonder if we could somehow make sure that the rate in the CCF matches
the current state of the HW.


If there is no constraint expressed by Linux software then we
should not care.

Probably we need to track a few more things in the framework. Stephen
and I were discussing struct clk.hw_en which tracks the enable/disable
state of the hardware independently of the enable_count (e.g. gate clock
is enabled by bootloader but not enabled by Linux ccf).

Tracking something like is_clk_initialized would be helpful. It is an
abstract concept but knowing that clock has been successfully hooked up
to its parent and that its rate has been properly calculated would be
very helpful for some corner cases.

Regards,
Mike



Regards,

Tomeu


Mikko






Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
v8:
- Added

   drivers/clk/tegra/clk-tegra-super-gen4.c | 46
++--
   1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c
b/drivers/clk/tegra/clk-tegra-super-gen4.c
index f1f4410..c5ea9ee 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -104,6 +104,32 @@ void __init tegra_super_clk_gen4_init(void __iomem
*clk_base,
  struct clk *clk;
  struct clk **dt_clk;

+   /*
+* Register PLL_X first so that CCLK_G has a parent at
registration
+* time. This ensures that the common clock framework knows
CCLK_G's
+* rate.
+*/
+
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) ||
defined(CONFIG_ARCH_TEGRA_124_SOC)
+   /* PLLX */
+   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
+   if (!dt_clk)
+   return;
+
+   clk = tegra_clk_register_pllxc(pll_x, pll_ref, clk_base,
+   pmc_base, CLK_IGNORE_UNUSED, params, NULL);
+   *dt_clk = clk;
+
+   /* PLLX_OUT0 */
+
+   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
+   if (!dt_clk)
+   return;
+   clk = clk_register_fixed_factor(NULL, pll_x_out0, pll_x,
+   CLK_SET_RATE_PARENT, 1, 2);
+   *dt_clk = clk;
+#endif
+
  /* CCLKG */
  dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
  if (dt_clk) {
@@ -127,25 +153,5 @@ void __init tegra_super_clk_gen4_init(void __iomem
*clk_base,
  }

  tegra_sclk_init(clk_base, tegra_clks);
-
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) ||
defined(CONFIG_ARCH_TEGRA_124_SOC)
-   /* PLLX */
-   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
-   if (!dt_clk)
-   return;
-
-   clk = tegra_clk_register_pllxc(pll_x, pll_ref, clk_base,
-   pmc_base, CLK_IGNORE_UNUSED, params, NULL);
-   *dt_clk = clk;
-
-   /* PLLX_OUT0 */
-
-   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
-   if (!dt_clk)
-   return;
-   clk = clk_register_fixed_factor(NULL, pll_x_out0, pll_x

Re: [PATCH v8 00/18] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-04-14 Thread Mikko Perttunen

On 04/11/2015 12:11 AM, Michael Turquette wrote:

Quoting Thierry Reding (2015-03-11 03:07:43)

Hi Mike,

Have you had a chance to look at these changes to the Tegra clock
driver? If you're fine with it, I'd like to take these patches through
the Tegra tree because the rest of the series depends on them. I can
provide a stable branch in case we need to base other Tegra clock
changes on top of this.


Hi Thierry,

Clock patches (and corresponding DT binding descriptions and changes to
DTS) look fine to me. Please add:

Acked-by: Michael Turquette mturque...@linaro.org

I did have a question about the beahvior of clk_put in one of Mikko's
patches but it should not gate this series. I'm just trying to find out
if we have a bug in the framework or if the Tegra driver is a special
case.

Also I do not think a stable branch is necessary.

Regards,
Mike



Looks like in the meantime, this has been partially broken by
03bc10ab5b0f clk: check -determine/round_rate() return value in 
clk_calc_new_rates. The highest rates supported by the DFLL clock have 
1 in the MSB, so those cannot be entered after the aforementioned patch, 
as the return value of round_rate is interpreted as an error. Avenues 
that I can see: 1) revert the above patch 2) restrict the cpu clock rate 
to those with 0 in the MSB 3) move to 64-bit clock rates.


Cheers,
Mikko.



Thierry

On Sun, Mar 01, 2015 at 02:44:23PM +0200, Mikko Perttunen wrote:

Hi, this is v8 of the Tegra124 cpufreq series. Aside rebasing on latest -next,
the following changes have been done:

clk: tegra: Add binding for the Tegra124 DFLL clocksource
- Changed dfll@ - clock@
- Changed compatibility string to nvidia,tegra124-dfll
- Clarified how the vdd-cpu-supply property is used
- Marked nvidia,cg-scale as optional since it is a boolean property
- Expanded the 'FS mode' term to 'full speed mode'
- Added dvco reset control

ARM: tegra: Add the DFLL to Tegra124 device tree
- Changed dfll@ - clock@
- Added dvco reset control

ARM: tegra: Enable the DFLL on the Jetson TK1
- Changed dfll@ - clock@

clk: tegra: Initialize PLL_X before CCLK_G to ensure it has a parent
- Added

clk: tegra: Introduce ability for SoC-specific reset control callbacks
- Added

clk: tegra: Add DFLL DVCO reset control for Tegra124
- Changed to use SoC-specific reset control callback

clk: tegra: Add Tegra124 DFLL clocksource platform driver
- Don't set DVCO reset handlers

clk: tegra: Add library for the DFLL clock source (open-loop mode)
- Use reset control instead of function pointers

also added acks from v7.

The series is available in a git repository at
   git://github.com/cyndis/linux.git cldvfs-v8

Tested by me on Jetson-TK1 (rev. D).

Original cover letter:

This series implements the DFLL/CL-DVFS clock source for the fast CPU
cluster on Tegra124, and a cpufreq driver that uses the DFLL for
clocking the CPU. Most of this is based on Paul Walmsley's public patch
set from December 2013, which is available at
http://comments.gmane.org/gmane.linux.ports.tegra/15273

The DFLL clock hardware is a voltage-controlled oscillator plus
control logic that compares the generated output clock with a
51 MHz reference clock, and can make decisions to either lower
or raise the DFLL voltage to keep the output rate close to the
software-requested rate. The voltage changes are done by
communicating with an off-chip PMIC via either I2C or PWM.
As the DFLL oscillator is powered via the CPU rail, using
the DFLL as the CPU clocksource also gives us dynamic CPU
voltage scaling.

This series has been tested on the Jetson TK1 (Rev C). Porting this to
the Venice2 should be simple, though do note that it does not have
active cooling.

Thanks,
Tuomas

Mikko Perttunen (3):
   clk: tegra: Introduce ability for SoC-specific reset control callbacks
   clk: tegra: Initialize PLL_X before CCLK_G to ensure it has a parent
   ARM: tegra: Add CPU regulator to the Jetson TK1 device tree

Paul Walmsley (1):
   clk: tegra: Add DFLL DVCO reset control for Tegra124

Tuomas Tynkkynen (14):
   clk: tegra: Add binding for the Tegra124 DFLL clocksource
   clk: tegra: Add library for the DFLL clock source (open-loop mode)
   clk: tegra: Add closed loop support for the DFLL
   clk: tegra: Add functions for parsing CVB tables
   clk: tegra: Add Tegra124 DFLL clocksource platform driver
   clk: tegra: Save/restore CCLKG_BURST_POLICY on suspend
   clk: tegra: Add the DFLL as a possible parent of the cclk_g clock
   ARM: tegra: Add the DFLL to Tegra124 device tree
   ARM: tegra: Enable the DFLL on the Jetson TK1
   cpufreq: tegra124: Add device tree bindings
   cpufreq: tegra: Rename tegra-cpufreq to tegra20-cpufreq
   cpufreq: Add cpufreq driver for Tegra124
   ARM: tegra: Add entries for cpufreq on Tegra124
   ARM: tegra: enable Tegra124 cpufreq driver by default

  .../bindings/clock/nvidia,tegra124-dfll.txt|   79 +
  .../bindings/cpufreq/tegra124-cpufreq.txt  |   44 +
  arch/arm/boot/dts/tegra124-jetson-tk1.dts  |   15

Re: [PATCH 1/2] clk: change clk_ops' -round_rate() prototype

2015-04-28 Thread Mikko Perttunen

The series

Tested-by: Mikko Perttunen mikko.perttu...@kapsi.fi

on Jetson-TK1.

I rebased my cpufreq series on top of this and everything's working well 
now. :)


Thanks,
Mikko.

On 04/17/2015 10:29 AM, Boris Brezillon wrote:

...

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 13/17] cpufreq: tegra: Rename tegra-cpufreq to tegra20-cpufreq

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The Tegra124 will use a different driver for frequency scaling, so
rename the old driver (which handles only Tegra20) appropriately.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 drivers/cpufreq/Kconfig.arm| 6 +++---
 drivers/cpufreq/Makefile   | 2 +-
 drivers/cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} | 0
 3 files changed, 4 insertions(+), 4 deletions(-)
 rename drivers/cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} (100%)

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 4f3dbc8..4674299 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -258,12 +258,12 @@ config ARM_SPEAR_CPUFREQ
help
  This adds the CPUFreq driver support for SPEAr SOCs.
 
-config ARM_TEGRA_CPUFREQ
-   bool TEGRA CPUFreq support
+config ARM_TEGRA20_CPUFREQ
+   bool Tegra20 CPUFreq support
depends on ARCH_TEGRA
default y
help
- This adds the CPUFreq driver support for TEGRA SOCs.
+ This adds the CPUFreq driver support for Tegra20 SOCs.
 
 config ARM_PXA2xx_CPUFREQ
tristate Intel PXA2xx CPUfreq driver
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index cdce92a..92391c0 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,7 +77,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
 obj-$(CONFIG_ARM_SA1100_CPUFREQ)   += sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)   += sa1110-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o
-obj-$(CONFIG_ARM_TEGRA_CPUFREQ)+= tegra-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 
 
##
diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
similarity index 100%
rename from drivers/cpufreq/tegra-cpufreq.c
rename to drivers/cpufreq/tegra20-cpufreq.c
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 08/17] clk: tegra: Save/restore CCLKG_BURST_POLICY on suspend

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Save and restore this register since the LP1 restore assembly routines
fiddle with it. Otherwise the CPU would keep running on PLLX after
resume from suspend even when DFLL was the original clocksource.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Peter De Schrijver pdeschrij...@nvidia.com
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk-tegra124.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 42ba3d9..ef9c161 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -98,6 +98,8 @@
 #define PMC_PLLM_WB0_OVERRIDE 0x1dc
 #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
 
+#define CCLKG_BURST_POLICY 0x368
+
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x)  0x)  6)
 #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x)  0x3f)  18)
@@ -130,6 +132,8 @@
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
u32 clk_csite_src;
+   u32 cclkg_burst;
+   u32 cclkg_divider;
 } tegra124_cpu_clk_sctx;
 #endif
 
@@ -1323,12 +1327,22 @@ static void tegra124_cpu_clock_suspend(void)
tegra124_cpu_clk_sctx.clk_csite_src =
readl(clk_base + CLK_SOURCE_CSITE);
writel(3  30, clk_base + CLK_SOURCE_CSITE);
+
+   tegra124_cpu_clk_sctx.cclkg_burst =
+   readl(clk_base + CCLKG_BURST_POLICY);
+   tegra124_cpu_clk_sctx.cclkg_divider =
+   readl(clk_base + CCLKG_BURST_POLICY + 4);
 }
 
 static void tegra124_cpu_clock_resume(void)
 {
writel(tegra124_cpu_clk_sctx.clk_csite_src,
clk_base + CLK_SOURCE_CSITE);
+
+   writel(tegra124_cpu_clk_sctx.cclkg_burst,
+   clk_base + CCLKG_BURST_POLICY);
+   writel(tegra124_cpu_clk_sctx.cclkg_divider,
+   clk_base + CCLKG_BURST_POLICY + 4);
 }
 #endif
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 04/17] clk: tegra: Add functions for parsing CVB tables

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Tegra CVB tables encode the relationship between operating voltage
and optimal frequency as a function of the so-called speedo value.
The speedo value is written to the on-chip fuses at the factory,
which allows the voltage-frequency operating points to be calculated
on an per-chip basis.

Add utility functions to parse the Tegra-specific tables and export the
voltage-frequency pairs to the generic OPP framework for other drivers
to use.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Peter De Schrijver pdeschrij...@nvidia.com
Acked-by: Michael Turquette mturque...@linaro.org
---
 arch/arm/mach-tegra/Kconfig |   1 +
 drivers/clk/tegra/cvb.c | 140 
 drivers/clk/tegra/cvb.h |  67 +
 3 files changed, 208 insertions(+)
 create mode 100644 drivers/clk/tegra/cvb.c
 create mode 100644 drivers/clk/tegra/cvb.h

diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 5d1a318..0fa4c5f 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL
+   select PM_OPP
select ARCH_HAS_RESET_CONTROLLER
select RESET_CONTROLLER
select SOC_BUS
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
new file mode 100644
index 000..0204e08
--- /dev/null
+++ b/drivers/clk/tegra/cvb.c
@@ -0,0 +1,140 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include linux/err.h
+#include linux/kernel.h
+#include linux/pm_opp.h
+
+#include cvb.h
+
+/* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */
+static inline int get_cvb_voltage(int speedo, int s_scale,
+ const struct cvb_coefficients *cvb)
+{
+   int mv;
+
+   /* apply only speedo scale: output mv = cvb_mv * v_scale */
+   mv = DIV_ROUND_CLOSEST(cvb-c2 * speedo, s_scale);
+   mv = DIV_ROUND_CLOSEST((mv + cvb-c1) * speedo, s_scale) + cvb-c0;
+   return mv;
+}
+
+static int round_cvb_voltage(int mv, int v_scale,
+const struct rail_alignment *align)
+{
+   /* combined: apply voltage scale and round to cvb alignment step */
+   int uv;
+   int step = (align-step_uv ? : 1000) * v_scale;
+   int offset = align-offset_uv * v_scale;
+
+   uv = max(mv * 1000, offset) - offset;
+   uv = DIV_ROUND_UP(uv, step) * align-step_uv + align-offset_uv;
+   return uv / 1000;
+}
+
+enum {
+   DOWN,
+   UP
+};
+
+static int round_voltage(int mv, const struct rail_alignment *align, int up)
+{
+   if (align-step_uv) {
+   int uv;
+
+   uv = max(mv * 1000, align-offset_uv) - align-offset_uv;
+   uv = (uv + (up ? align-step_uv - 1 : 0)) / align-step_uv;
+   return (uv * align-step_uv + align-offset_uv) / 1000;
+   }
+   return mv;
+}
+
+static int build_opp_table(const struct cvb_table *d,
+  int speedo_value,
+  unsigned long max_freq,
+  struct device *opp_dev)
+{
+   int i, ret, dfll_mv, min_mv, max_mv;
+   const struct cvb_table_freq_entry *table = NULL;
+   const struct rail_alignment *align = d-alignment;
+
+   min_mv = round_voltage(d-min_millivolts, align, UP);
+   max_mv = round_voltage(d-max_millivolts, align, DOWN);
+
+   for (i = 0; i  MAX_DVFS_FREQS; i++) {
+   table = d-cvb_table[i];
+   if (!table-freq || (table-freq  max_freq))
+   break;
+
+   /*
+* FIXME after clk_round_rate/clk_determine_rate prototypes
+* have been updated
+*/
+   if (table-freq  (131))
+   continue;
+
+   dfll_mv = get_cvb_voltage(
+   speedo_value, d-speedo_scale, table-coefficients);
+   dfll_mv = round_cvb_voltage(dfll_mv, d-voltage_scale, align);
+   dfll_mv = clamp(dfll_mv, min_mv, max_mv);
+
+   ret = dev_pm_opp_add(opp_dev, table-freq, dfll_mv * 1000);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+/**
+ * tegra_cvb_build_opp_table - build OPP table from

[PATCH v9 11/17] ARM: tegra: Enable the DFLL on the Jetson TK1

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Add the board-specific properties of the DFLL for the Jetson TK1 board.
On this board, the DFLL will take control of the sd0 regulator on the
on-board AS3722 PMIC.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts 
b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index bd43ed6..192111a 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1462,7 +1462,7 @@
vin-ldo9-10-supply = vdd_5v0_sys;
vin-ldo11-supply = vdd_3v3_run;
 
-   sd0 {
+   vdd_cpu: sd0 {
regulator-name = +VDD_CPU_AP;
regulator-min-microvolt = 70;
regulator-max-microvolt = 140;
@@ -1694,6 +1694,13 @@
non-removable;
};
 
+   /* CPU DFLL clock */
+   clock@0,7011 {
+   status = okay;
+   vdd-cpu-supply = vdd_cpu;
+   nvidia,i2c-fs-rate = 40;
+   };
+
ahub@0,7030 {
i2s@0,70301100 {
status = okay;
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 17/17] ARM: tegra: enable Tegra124 cpufreq driver by default

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The Tegra124 cpufreq driver depends on CONFIG_CPUFREQ_DT, so
enable it to get the Tegra driver to build by default.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 arch/arm/configs/tegra_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index cdf9abb..f4d8711 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -42,6 +42,7 @@ CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 03/17] clk: tegra: Add closed loop support for the DFLL

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

With closed loop support, the clock rate of the DFLL can be adjusted.

The oscillator itself in the DFLL is a free-running oscillator whose
rate is directly determined the supply voltage. However, the DFLL
module contains logic to compare the DFLL output rate to a fixed
reference clock (51 MHz) and make a decision to either lower or raise
the DFLL supply voltage. The DFLL module can then autonomously change
the supply voltage by communicating with an off-chip PMIC via either I2C
or PWM signals. This driver currently supports only I2C.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Peter De Schrijver pdeschrij...@nvidia.com
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk-dfll.c | 666 ++-
 1 file changed, 663 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index fb138bf..6ec64577 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -206,12 +206,16 @@
  */
 #define REF_CLOCK_RATE 5100UL
 
+#define DVCO_RATE_TO_MULT(rate, ref_rate)  ((rate) / ((ref_rate) / 2))
+#define MULT_TO_DVCO_RATE(mult, ref_rate)  ((mult) * ((ref_rate) / 2))
 
 /**
  * enum dfll_ctrl_mode - DFLL hardware operating mode
  * @DFLL_UNINITIALIZED: (uninitialized state - not in hardware bitfield)
  * @DFLL_DISABLED: DFLL not generating an output clock
  * @DFLL_OPEN_LOOP: DVCO running, but DFLL not adjusting voltage
+ * @DFLL_CLOSED_LOOP: DVCO running, and DFLL adjusting voltage to match
+ *   the requested rate
  *
  * The integer corresponding to the last two states, minus one, is
  * written to the DFLL hardware to change operating modes.
@@ -220,6 +224,7 @@ enum dfll_ctrl_mode {
DFLL_UNINITIALIZED = 0,
DFLL_DISABLED = 1,
DFLL_OPEN_LOOP = 2,
+   DFLL_CLOSED_LOOP = 3,
 };
 
 /**
@@ -237,6 +242,22 @@ enum dfll_tune_range {
DFLL_TUNE_LOW = 1,
 };
 
+/**
+ * struct dfll_rate_req - target DFLL rate request data
+ * @rate: target frequency, after the postscaling
+ * @dvco_target_rate: target frequency, after the postscaling
+ * @lut_index: LUT index at which voltage the dvco_target_rate will be reached
+ * @mult_bits: value to program to the MULT bits of the DFLL_FREQ_REQ register
+ * @scale_bits: value to program to the SCALE bits of the DFLL_FREQ_REQ 
register
+ */
+struct dfll_rate_req {
+   unsigned long rate;
+   unsigned long dvco_target_rate;
+   int lut_index;
+   u8 mult_bits;
+   u8 scale_bits;
+};
+
 struct tegra_dfll {
struct device   *dev;
struct tegra_dfll_soc_data  *soc;
@@ -261,9 +282,27 @@ struct tegra_dfll {
struct dentry   *debugfs_dir;
struct clk_hw   dfll_clk_hw;
const char  *output_clock_name;
+   struct dfll_rate_reqlast_req;
+   unsigned long   last_unrounded_rate;
 
/* Parameters from DT */
u32 droop_ctrl;
+   u32 sample_rate;
+   u32 force_mode;
+   u32 cf;
+   u32 ci;
+   u32 cg;
+   boolcg_scale;
+
+   /* I2C interface parameters */
+   u32 i2c_fs_rate;
+   u32 i2c_reg;
+   u32 i2c_slave_addr;
+
+   /* i2c_lut array entries are regulator framework selectors */
+   unsignedi2c_lut[MAX_DFLL_VOLTAGES];
+   int i2c_lut_size;
+   u8  lut_min, lut_max, lut_safe;
 };
 
 #define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -273,6 +312,7 @@ static const char * const mode_name[] = {
[DFLL_UNINITIALIZED] = uninitialized,
[DFLL_DISABLED] = disabled,
[DFLL_OPEN_LOOP] = open_loop,
+   [DFLL_CLOSED_LOOP] = closed_loop,
 };
 
 /*
@@ -499,6 +539,283 @@ static void dfll_set_mode(struct tegra_dfll *td,
 }
 
 /*
+ * DFLL-to-I2C controller interface
+ */
+
+/**
+ * dfll_i2c_set_output_enabled - enable/disable I2C PMIC voltage requests
+ * @td: DFLL instance
+ * @enable: whether to enable or disable the I2C voltage requests
+ *
+ * Set the master enable control for I2C control value updates. If disabled,
+ * then I2C control messages are inhibited, regardless of the DFLL mode.
+ */
+static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
+{
+   u32 val;
+
+   val = dfll_i2c_readl(td, DFLL_OUTPUT_CFG);
+
+   if (enable)
+   val |= DFLL_OUTPUT_CFG_I2C_ENABLE;
+   else
+   val

[PATCH v9 01/17] clk: tegra: Add binding for the Tegra124 DFLL clocksource

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The DFLL is the main clocksource for the fast CPU cluster on Tegra124
and also provides automatic CPU rail voltage scaling as well. The DFLL
is a separate IP block from the usual Tegra124 clock-and-reset
controller, so it gets its own node in the device tree.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 .../bindings/clock/nvidia,tegra124-dfll.txt| 79 ++
 1 file changed, 79 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt 
b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
new file mode 100644
index 000..ee7e5fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
@@ -0,0 +1,79 @@
+NVIDIA Tegra124 DFLL FCPU clocksource
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The DFLL IP block on Tegra is a root clocksource designed for clocking
+the fast CPU cluster. It consists of a free-running voltage controlled
+oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop
+control module that will automatically adjust the VDD_CPU voltage by
+communicating with an off-chip PMIC either via an I2C bus or via PWM signals.
+Currently only the I2C mode is supported by these bindings.
+
+Required properties:
+- compatible : should be nvidia,tegra124-dfll
+- reg : Defines the following set of registers, in the order listed:
+- registers for the DFLL control logic.
+- registers for the I2C output logic.
+- registers for the integrated I2C master controller.
+- look-up table RAM for voltage register values.
+- interrupts: Should contain the DFLL block interrupt.
+- clocks: Must contain an entry for each entry in clock-names.
+  See clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - soc: Clock source for the DFLL control logic.
+  - ref: The closed loop reference clock
+  - i2c: Clock source for the integrated I2C master.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - dvco: Reset control for the DFLL DVCO.
+- #clock-cells: Must be 0.
+- clock-output-names: Name of the clock output.
+- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL
+  hardware will start controlling. The regulator will be queried for
+  the I2C register, control values and supported voltages.
+
+Required properties for the control loop parameters:
+- nvidia,sample-rate: Sample rate of the DFLL control loop.
+- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM.
+- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM.
+- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM.
+- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM.
+- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM.
+
+Optional properties for the control loop parameters:
+- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the 
TRM.
+
+Required properties for I2C mode:
+- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
+
+Example:
+
+clock@0,7011 {
+compatible = nvidia,tegra124-dfll;
+reg = 0 0x7011 0 0x100, /* DFLL control */
+  0 0x7011 0 0x100, /* I2C output control */
+  0 0x70110100 0 0x100, /* Integrated I2C controller */
+  0 0x70110200 0 0x100; /* Look-up table RAM */
+interrupts = GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH;
+clocks = tegra_car TEGRA124_CLK_DFLL_SOC,
+ tegra_car TEGRA124_CLK_DFLL_REF,
+ tegra_car TEGRA124_CLK_I2C5;
+clock-names = soc, ref, i2c;
+resets = tegra_car TEGRA124_RST_DFLL_DVCO;
+reset-names = dvco;
+#clock-cells = 0;
+clock-output-names = dfllCPU_out;
+vdd-cpu-supply = vdd_cpu;
+status = okay;
+
+nvidia,sample-rate = 12500;
+nvidia,droop-ctrl = 0x0f00;
+nvidia,force-mode = 1;
+nvidia,cf = 10;
+nvidia,ci = 0;
+nvidia,cg = 2;
+
+nvidia,i2c-fs-rate = 40;
+};
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 07/17] clk: tegra: Add Tegra124 DFLL clocksource platform driver

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Add basic platform driver support for the fast CPU cluster DFLL
clocksource found on Tegra124 SoCs. This small driver selects the
appropriate Tegra124-specific characterization data and integration
code. It relies on the DFLL common code to do most of the work.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/Makefile |   2 +
 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 161 +
 2 files changed, 163 insertions(+)
 create mode 100644 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index ec2e516..826c325 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -17,4 +17,6 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)   += clk-tegra114.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)   += clk-tegra124.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)   += clk-tegra124-dfll-fcpu.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)   += clk-tegra124.o
+obj-y  += cvb.o
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c 
b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
new file mode 100644
index 000..b10a501
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -0,0 +1,161 @@
+/*
+ * Tegra124 DFLL FCPU clock source driver
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * Aleksandr Frid af...@nvidia.com
+ * Paul Walmsley pwalms...@nvidia.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include linux/cpu.h
+#include linux/err.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/platform_device.h
+#include soc/tegra/fuse.h
+
+#include clk.h
+#include clk-dfll.h
+#include cvb.h
+
+/* Maximum CPU frequency, indexed by CPU speedo id */
+static const unsigned long cpu_max_freq_table[] = {
+   [0] = 201450UL,
+   [1] = 232050UL,
+   [2] = 211650UL,
+   [3] = 252450UL,
+};
+
+static const struct cvb_table tegra124_cpu_cvb_tables[] = {
+   {
+   .speedo_id = -1,
+   .process_id = -1,
+   .min_millivolts = 900,
+   .max_millivolts = 1260,
+   .alignment = {
+   .step_uv = 1, /* 10mV */
+   },
+   .speedo_scale = 100,
+   .voltage_scale = 1000,
+   .cvb_table = {
+   {20400UL,   {1112619, -29295, 402} },
+   {30600UL,   {1150460, -30585, 402} },
+   {40800UL,   {1190122, -31865, 402} },
+   {51000UL,   {1231606, -33155, 402} },
+   {61200UL,   {1274912, -34435, 402} },
+   {71400UL,   {1320040, -35725, 402} },
+   {81600UL,   {1366990, -37005, 402} },
+   {91800UL,   {1415762, -38295, 402} },
+   {102000UL,  {1466355, -39575, 402} },
+   {112200UL,  {1518771, -40865, 402} },
+   {122400UL,  {1573009, -42145, 402} },
+   {132600UL,  {1629068, -43435, 402} },
+   {142800UL,  {1686950, -44715, 402} },
+   {153000UL,  {1746653, -46005, 402} },
+   {163200UL,  {1808179, -47285, 402} },
+   {173400UL,  {1871526, -48575, 402} },
+   {183600UL,  {1936696, -49855, 402} },
+   {193800UL,  {2003687, -51145, 402} },
+   {201450UL,  {2054787, -52095, 402} },
+   {211650UL,  {2124957, -53385, 402} },
+   {221850UL,  {2196950, -54665, 402} },
+   {232050UL,  {2270765, -55955, 402} },
+   {242250UL,  {2346401, -57235, 402} },
+   {252450UL,  {2437299, -58535, 402} },
+   {0, {  0,  0,   0} },
+   },
+   .cpu_dfll_data = {
+   .tune0_low = 0x005020ff,
+   .tune0_high = 0x005040ff,
+   .tune1 = 0x0060,
+   }
+   },
+};
+
+static struct tegra_dfll_soc_data soc;
+
+static int

[PATCH v9 12/17] cpufreq: tegra124: Add device tree bindings

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The cpufreq driver for Tegra124 will be a different one than the old
Tegra20 cpufreq driver (tegra-cpufreq), which does not use the device
tree.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 .../bindings/cpufreq/tegra124-cpufreq.txt  | 44 ++
 1 file changed, 44 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt 
b/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
new file mode 100644
index 000..b1669fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
@@ -0,0 +1,44 @@
+Tegra124 CPU frequency scaling driver bindings
+--
+
+Both required and optional properties listed below must be defined
+under node /cpus/cpu@0.
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - cpu_g: Clock mux for the fast CPU cluster.
+  - cpu_lp: Clock mux for the low-power CPU cluster.
+  - pll_x: Fast PLL clocksource.
+  - pll_p: Auxiliary PLL used during fast PLL rate changes.
+  - dfll: Fast DFLL clocksource that also automatically scales CPU voltage.
+- vdd-cpu-supply: Regulator for CPU voltage
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock,
+  in unit of nanoseconds.
+
+Example:
+
+cpus {
+   #address-cells = 1;
+   #size-cells = 0;
+
+   cpu@0 {
+   device_type = cpu;
+   compatible = arm,cortex-a15;
+   reg = 0;
+
+   clocks = tegra_car TEGRA124_CLK_CCLK_G,
+tegra_car TEGRA124_CLK_CCLK_LP,
+tegra_car TEGRA124_CLK_PLL_X,
+tegra_car TEGRA124_CLK_PLL_P,
+dfll;
+   clock-names = cpu_g, cpu_lp, pll_x, pll_p, dfll;
+   clock-latency = 30;
+   vdd-cpu-supply: vdd_cpu;
+   };
+
+   ...
+};
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 16/17] ARM: tegra: Add CPU regulator to the Jetson TK1 device tree

2015-05-13 Thread Mikko Perttunen
Specify the CPU voltage regulator for the cpufreq driver.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts 
b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 192111a..ce5961c 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1739,6 +1739,12 @@
};
};
 
+   cpus {
+   cpu@0 {
+   vdd-cpu-supply = vdd_cpu;
+   };
+   };
+
gpio-keys {
compatible = gpio-keys;
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 15/17] ARM: tegra: Add entries for cpufreq on Tegra124

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The Tegra124 cpufreq driver relies on certain clocks being present
in the /cpus/cpu@0 node.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 arch/arm/boot/dts/tegra124.dtsi | 9 +
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 5b8177a..87318a7 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -947,6 +947,15 @@
device_type = cpu;
compatible = arm,cortex-a15;
reg = 0;
+
+   clocks = tegra_car TEGRA124_CLK_CCLK_G,
+tegra_car TEGRA124_CLK_CCLK_LP,
+tegra_car TEGRA124_CLK_PLL_X,
+tegra_car TEGRA124_CLK_PLL_P,
+dfll;
+   clock-names = cpu_g, cpu_lp, pll_x, pll_p, 
dfll;
+   /* FIXME: what's the actual transition time? */
+   clock-latency = 30;
};
 
cpu@1 {
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 00/17] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-05-13 Thread Mikko Perttunen
v9 of the Tegra124 cpufreq series. Changes:

- Dropped PLLX reordering patch since it is no longer needed
- Removed a couple of unused lines from the DFLL clocksource platform driver
- Made the cpufreq driver tristate and removed .owned = THIS_MODULE (as it's 
not needed for
  platform devices)
- Made the OPP generation code in the CVB parser ignore OPPs where the 
frequency has the most
  significant bit set. This can be dropped once Boris Brezillon's patch finds 
its
  way into the tree.
- Added Acks.

The only patches without Acks are the following:
  ARM: tegra: enable Tegra124 cpufreq driver by default
  ARM: tegra: Add CPU regulator to the Jetson TK1 device tree
  ARM: tegra: Add entries for cpufreq on Tegra124
  cpufreq: tegra: Rename tegra-cpufreq to tegra20-cpufreq
  cpufreq: tegra124: Add device tree bindings

These are very minor (4/5 of them are DT patches and the fifth just renames a 
driver),
so hopefully we can get this merged.

Mikko Perttunen (2):
  clk: tegra: Introduce ability for SoC-specific reset control callbacks
  ARM: tegra: Add CPU regulator to the Jetson TK1 device tree

Paul Walmsley (1):
  clk: tegra: Add DFLL DVCO reset control for Tegra124

Tuomas Tynkkynen (14):
  clk: tegra: Add binding for the Tegra124 DFLL clocksource
  clk: tegra: Add library for the DFLL clock source (open-loop mode)
  clk: tegra: Add closed loop support for the DFLL
  clk: tegra: Add functions for parsing CVB tables
  clk: tegra: Add Tegra124 DFLL clocksource platform driver
  clk: tegra: Save/restore CCLKG_BURST_POLICY on suspend
  clk: tegra: Add the DFLL as a possible parent of the cclk_g clock
  ARM: tegra: Add the DFLL to Tegra124 device tree
  ARM: tegra: Enable the DFLL on the Jetson TK1
  cpufreq: tegra124: Add device tree bindings
  cpufreq: tegra: Rename tegra-cpufreq to tegra20-cpufreq
  cpufreq: Add cpufreq driver for Tegra124
  ARM: tegra: Add entries for cpufreq on Tegra124
  ARM: tegra: enable Tegra124 cpufreq driver by default

 .../bindings/clock/nvidia,tegra124-dfll.txt|   79 +
 .../bindings/cpufreq/tegra124-cpufreq.txt  |   44 +
 arch/arm/boot/dts/tegra124-jetson-tk1.dts  |   15 +-
 arch/arm/boot/dts/tegra124.dtsi|   34 +
 arch/arm/configs/tegra_defconfig   |1 +
 arch/arm/mach-tegra/Kconfig|1 +
 drivers/clk/tegra/Makefile |3 +
 drivers/clk/tegra/clk-dfll.c   | 1755 
 drivers/clk/tegra/clk-dfll.h   |   54 +
 drivers/clk/tegra/clk-tegra-super-gen4.c   |4 +-
 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c |  161 ++
 drivers/clk/tegra/clk-tegra124.c   |   82 +
 drivers/clk/tegra/clk.c|   36 +-
 drivers/clk/tegra/clk.h|3 +
 drivers/clk/tegra/cvb.c|  140 ++
 drivers/clk/tegra/cvb.h|   67 +
 drivers/cpufreq/Kconfig.arm|   13 +-
 drivers/cpufreq/Makefile   |3 +-
 drivers/cpufreq/tegra124-cpufreq.c |  214 +++
 .../cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} |0
 include/dt-bindings/reset/tegra124-car.h   |   11 +
 21 files changed, 2706 insertions(+), 14 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
 create mode 100644 
Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
 create mode 100644 drivers/clk/tegra/clk-dfll.c
 create mode 100644 drivers/clk/tegra/clk-dfll.h
 create mode 100644 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
 create mode 100644 drivers/clk/tegra/cvb.c
 create mode 100644 drivers/clk/tegra/cvb.h
 create mode 100644 drivers/cpufreq/tegra124-cpufreq.c
 rename drivers/cpufreq/{tegra-cpufreq.c = tegra20-cpufreq.c} (100%)
 create mode 100644 include/dt-bindings/reset/tegra124-car.h

-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 05/17] clk: tegra: Introduce ability for SoC-specific reset control callbacks

2015-05-13 Thread Mikko Perttunen
This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number = 0x4000 is attempted to be asserted or
deasserted respectively. The callback should return -EINVAL if the number
of the reset control is invalid. Numbers greater than or equal to 0x4000
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines. Furthermore, numbers with the most significant bit
set should not be used, as some functions interpret these as negative error
codes.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.

Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk.c | 36 
 drivers/clk/tegra/clk.h |  3 +++
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 41cd87c..d4e4c31 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -49,7 +49,6 @@
 #define RST_DEVICES_L  0x004
 #define RST_DEVICES_H  0x008
 #define RST_DEVICES_U  0x00C
-#define RST_DFLL_DVCO  0x2F4
 #define RST_DEVICES_V  0x358
 #define RST_DEVICES_W  0x35C
 #define RST_DEVICES_X  0x28C
@@ -79,6 +78,10 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*reset_assert)(unsigned long);
+static int (*reset_deassert)(unsigned long);
+
 static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +155,29 @@ static int tegra_clk_rst_assert(struct 
reset_controller_dev *rcdev,
 */
tegra_read_chipid();
 
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_set_reg);
+   if (id = 0x4000  reset_assert) {
+   return reset_assert(id);
+   } else if (id  clk_num * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_set_reg);
+   return 0;
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
 {
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_clr_reg);
+   if (id = 0x4000  reset_deassert) {
+   return reset_deassert(id);
+   } else if (id  clk_num * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_clr_reg);
+   return 0;
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +299,17 @@ void __init tegra_add_of_provider(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
 
rst_ctlr.of_node = np;
-   rst_ctlr.nr_resets = periph_banks * 32;
+   rst_ctlr.nr_resets = 0x8000;
reset_controller_register(rst_ctlr);
 }
 
+void __init tegra_init_special_resets(int (*assert)(unsigned long),
+ int (*deassert)(unsigned long))
+{
+   reset_assert = assert;
+   reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
int i;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 75ddc8ff..5f88c9d 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -591,6 +591,9 @@ struct tegra_devclk {
char*con_id;
 };
 
+void tegra_init_special_resets(int (*assert)(unsigned long),
+  int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
struct clk *clks[], int clk_max);
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v9 00/17] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-05-14 Thread Mikko Perttunen

On 05/15/2015 05:09 AM, Viresh Kumar wrote:

On 15 May 2015 at 01:45, Rafael J. Wysocki r...@rjwysocki.net wrote:

You need ACKs from Viresh for those two, then.  He's officially responsible
for ARM cpufreq drivers.


I thought an Ack for 14th is enough :)

For: 12/13/14.
Acked-by: Viresh Kumar viresh.ku...@linaro.org



Thanks! :)

It probably was, but after almost one year of this series, I'm not sure 
about anything anymore ;)


Mikko

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/2] clk: change clk_ops' -round_rate() prototype

2015-05-16 Thread Mikko Perttunen

On 05/15/2015 06:40 PM, Boris Brezillon wrote:

Hi Stephen,

Adding Mikko in the loop (after all, he was the one complaining about
this signed long limitation in the first place, and I forgot to add
him in the Cc list :-/).


I think I got it through linux-tegra anyway, but thanks :)



Mikko, are you okay with the approach proposed by Stephen (adding a
new method) ?


Yes, sounds good to me. If a driver uses the existing methods with too 
large frequencies, the issue is pretty discoverable anyway. I think 
adjust_rate sounds a bit too much like it sets the clock's rate, 
though; perhaps adjust_rate_request or something like that?


Thanks,
Mikko



On Thu, 7 May 2015 09:37:02 +0200
Boris Brezillon boris.brezil...@free-electrons.com wrote:


Hi Stephen,

On Wed, 6 May 2015 23:39:53 -0700
Stephen Boyd sb...@codeaurora.org wrote:


On 04/30, Boris Brezillon wrote:

Clock rates are stored in an unsigned long field, but -round_rate()
(which returns a rounded rate from a requested one) returns a long
value (errors are reported using negative error codes), which can lead
to long overflow if the clock rate exceed 2Ghz.

Change -round_rate() prototype to return 0 or an error code, and pass the
requested rate as a pointer so that it can be adjusted depending on
hardware capabilities.

Signed-off-by: Boris Brezillon boris.brezil...@free-electrons.com
Tested-by: Heiko Stuebner he...@sntech.de
Tested-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Reviewed-by: Heiko Stuebner he...@sntech.de


This patch is fairly invasive, and it probably doesn't even
matter for most of these clock providers to be able to round a
rate above 2GHz.


Fair enough.


I've been trying to remove the .round_rate op
from the framework by encouraging new features via the
.determine_rate op.


Oh, I wasn't aware of that (BTW, that's a good thing).
Maybe this should be clearly stated (both in the struct clk_ops
kerneldoc header and in Documentation/clk.txt).


Sadly, we still have to do a flag day and
change all the .determine_rate ops when we want to add things.


Yes, but the number of clk drivers implementing -determine_rate() is
still quite limited compared to those implementing -round_rate().



What if we changed determine_rate ops to take a struct
clk_determine_info (or some better named structure) instead of
the current list of arguments that it currently takes? Then when
we want to make these sorts of framework wide changes we can just
throw a new member into that structure and be done.


I really like this idea, especially since I was wondering if we could
pass other 'clk rate requirements' like the rounding policy (down,
closest, up), or the maximum clk inaccuracy.



It doesn't solve the unsigned long to int return value problem
though. We can solve that by gradually introducing a new op and
handling another case in the rounding path. If we can come up
with some good name for that new op like .decide_rate or
something then it makes things nicer in the long run. I like the
name .determine_rate though :/


Okay, if you want a new method, how about this one:

struct clk_adjust_rate_req {
/* fields filled by the caller */
unsigned long rate; /* rate is updated by the clk driver */
unsigned long min;
unsigned long max;

/* fields filled by the clk driver */
struct clk_hw *best_parent;
unsigned long best_parent_rate;

/*
 * new fields I'd like to add at some point:
 * unsigned long max_inaccuracy;
 * something about the power consumption constraints :-)
 */
};

int (*adjust_rate)(struct clk_hw *hw, struct clk_adjust_rate_req *req);



Why not changing the -determine_rate() prototype. As said above, the
number of clk drivers implementing this function is still quite
limited, and I guess we can have an ack for all of them.



The benefit of all this is that we don't have to worry about
finding the random clk providers that get added into other
subsystems and fixing them up. If drivers actually care about
this problem then they'll be fixed to use the proper op. FYI,
last time we updated the function signature of .determine_rate we
broke a couple drivers along the way.



Hm, IMHO, adding a new op is not a good thing. I agree that it eases
the transition, but ITOH you'll have to live with old/deprecated ops in
your clk_ops structure with people introducing new drivers still using
the old ops (see the number of clk drivers implementing -round_rate()
instead of -determine_rate()).

Best Regards,

Boris







--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 11/15] thermal: thermal: Add support for hardware-tracked trip points

2015-05-18 Thread Mikko Perttunen

On 05/18/2015 09:44 PM, Brian Norris wrote:

On Mon, May 18, 2015 at 02:09:44PM +0200, Sascha Hauer wrote:

On Mon, May 18, 2015 at 12:06:50PM +0300, Mikko Perttunen wrote:

One interesting thing I noticed was that at least the bang-bang
governor only acts if the temperature is properly smaller than (trip
temp - hysteresis). So perhaps we should specify the non-tripping
range as [low, high)? Or we could change bang-bang.


I wonder how we can protect against such off-by-one errors anyway.
Generally a hardware might operate on raw values rather than directly
in temperature values in °C. This means a driver for this must have
celsius_to_raw and raw_to_celsius conversion functions. Now it can
happen that due to rounding errors celsius_to_raw(Tcrit) returns a raw
value that when converted back to celsius is different from the
original value in °C. This would mean the hardware triggers an interrupt
for a trip point and the thermal core does not react because get_temp
actually returns a different temperature than previously programmed as
interrupt trigger. This way we would lose hot (or cold) events.


This also highlights another fact: there's a race between interrupt
generation and temperature reading (-get_temp()). I would expect any
hardware interrupt thermal sensor would also have a latched temperature
reading to correspond with it, and there would be no guarantee that this
latched temperature will match the polled reading seen once you reach
thermal_zone_device_update(). So a hardware driver might report a
thermal update, but the temperature reported to the core won't
necessarily match what interrupt was meant for.


Does this actually matter? The thermal core will reset trips and apply 
cooling using the new - most recent - value. Using bang bang as example, 
if the temperature has risen since the interrupt fired, the cooling 
device will correctly not be switched off. If the temperature has 
fallen, it will again be correctly switched off. The only issue is then 
if the temperature is exactly 'trip temp - trip hyst' which will cause 
set_trips to load the trip points below, but not cause bang bang to turn 
off the cooling device, and the next chance it will have will only be at 
the next below trip point. Well, this is still safe (at least until you 
replace cooling device with heating device), so maybe it isn't that 
big of an issue.


Please point out if there's a problem with my line of reasoning.

FWIW - at least Tegra doesn't have a latched register like this. There's 
just a bit indicating that an interrupt was raised and a temperature 
register that updates according to the sensor's input clock.




I have a patch that adds a thermal_zone_device_update_temp() API, so
drivers can report the temperature along with the interrupt
notification. (Such a patch also helps so that the driver can choose to
round down on cold events and up on hot events, resolving your rounding
issue too.)

Brian



Cheers,
Mikko

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 02/17] clk: tegra: Add library for the DFLL clock source (open-loop mode)

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Add shared code to support the Tegra DFLL clocksource in open-loop
mode. This root clocksource is present on the Tegra124 SoCs. The
DFLL is the intended primary clock source for the fast CPU cluster.

This code is very closely based on a patch by Paul Walmsley from
December (http://comments.gmane.org/gmane.linux.ports.tegra/15273),
which in turn comes from the internal driver by originally created
by Aleksandr Frid af...@nvidia.com.

Subsequent patches will add support for closed loop mode and drivers
for the Tegra124 fast CPU cluster DFLL devices, which rely on this
code.

Signed-off-by: Paul Walmsley pwalms...@nvidia.com
Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Peter De Schrijver pdeschrij...@nvidia.com
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/Makefile   |1 +
 drivers/clk/tegra/clk-dfll.c | 1095 ++
 drivers/clk/tegra/clk-dfll.h |   54 +++
 3 files changed, 1150 insertions(+)
 create mode 100644 drivers/clk/tegra/clk-dfll.c
 create mode 100644 drivers/clk/tegra/clk-dfll.h

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index aec862b..ec2e516 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -1,5 +1,6 @@
 obj-y  += clk.o
 obj-y  += clk-audio-sync.o
+obj-y  += clk-dfll.o
 obj-y  += clk-divider.o
 obj-y  += clk-periph.o
 obj-y  += clk-periph-gate.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
new file mode 100644
index 000..fb138bf
--- /dev/null
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -0,0 +1,1095 @@
+/*
+ * clk-dfll.c - Tegra DFLL clock source common code
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ *
+ * Aleksandr Frid af...@nvidia.com
+ * Paul Walmsley pwalms...@nvidia.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * This library is for the DVCO and DFLL IP blocks on the Tegra124
+ * SoC. These IP blocks together are also known at NVIDIA as
+ * CL-DVFS. To try to avoid confusion, this code refers to them
+ * collectively as the DFLL.
+ *
+ * The DFLL is a root clocksource which tolerates some amount of
+ * supply voltage noise. Tegra124 uses it to clock the fast CPU
+ * complex when the target CPU speed is above a particular rate. The
+ * DFLL can be operated in either open-loop mode or closed-loop mode.
+ * In open-loop mode, the DFLL generates an output clock appropriate
+ * to the supply voltage. In closed-loop mode, when configured with a
+ * target frequency, the DFLL minimizes supply voltage while
+ * delivering an average frequency equal to the target.
+ *
+ * Devices clocked by the DFLL must be able to tolerate frequency
+ * variation. In the case of the CPU, it's important to note that the
+ * CPU cycle time will vary. This has implications for
+ * performance-measurement code and any code that relies on the CPU
+ * cycle time to delay for a certain length of time.
+ *
+ */
+
+#include linux/clk.h
+#include linux/clk-provider.h
+#include linux/debugfs.h
+#include linux/device.h
+#include linux/err.h
+#include linux/i2c.h
+#include linux/io.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/pm_opp.h
+#include linux/pm_runtime.h
+#include linux/regmap.h
+#include linux/regulator/consumer.h
+#include linux/reset.h
+#include linux/seq_file.h
+
+#include clk-dfll.h
+
+/*
+ * DFLL control registers - access via dfll_{readl,writel}
+ */
+
+/* DFLL_CTRL: DFLL control register */
+#define DFLL_CTRL  0x00
+#define DFLL_CTRL_MODE_MASK0x03
+
+/* DFLL_CONFIG: DFLL sample rate control */
+#define DFLL_CONFIG0x04
+#define DFLL_CONFIG_DIV_MASK   0xff
+#define DFLL_CONFIG_DIV_PRESCALE   32
+
+/* DFLL_PARAMS: tuning coefficients for closed loop integrator */
+#define DFLL_PARAMS0x08
+#define DFLL_PARAMS_CG_SCALE   (0x1  24)
+#define DFLL_PARAMS_FORCE_MODE_SHIFT   22
+#define DFLL_PARAMS_FORCE_MODE_MASK(0x3  DFLL_PARAMS_FORCE_MODE_SHIFT)
+#define DFLL_PARAMS_CF_PARAM_SHIFT 16
+#define DFLL_PARAMS_CF_PARAM_MASK  (0x3f  DFLL_PARAMS_CF_PARAM_SHIFT)
+#define DFLL_PARAMS_CI_PARAM_SHIFT 8
+#define DFLL_PARAMS_CI_PARAM_MASK  (0x7  DFLL_PARAMS_CI_PARAM_SHIFT)
+#define

[PATCH v9 10/17] ARM: tegra: Add the DFLL to Tegra124 device tree

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The DFLL clocksource is a separate IP block from the usual
clock-and-reset controller, so it gets its own device tree node.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 arch/arm/boot/dts/tegra124.dtsi | 25 +
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 01a9f74..5b8177a 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -4,6 +4,7 @@
 #include dt-bindings/pinctrl/pinctrl-tegra.h
 #include dt-bindings/pinctrl/pinctrl-tegra-xusb.h
 #include dt-bindings/interrupt-controller/arm-gic.h
+#include dt-bindings/reset/tegra124-car.h
 #include dt-bindings/thermal/tegra124-soctherm.h
 
 #include skeleton.dtsi
@@ -702,6 +703,30 @@
#thermal-sensor-cells = 1;
};
 
+   dfll: clock@0,7011 {
+   compatible = nvidia,tegra124-dfll;
+   reg = 0 0x7011 0 0x100, /* DFLL control */
+ 0 0x7011 0 0x100, /* I2C output control */
+ 0 0x70110100 0 0x100, /* Integrated I2C controller */
+ 0 0x70110200 0 0x100; /* Look-up table RAM */
+   interrupts = GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH;
+   clocks = tegra_car TEGRA124_CLK_DFLL_SOC,
+tegra_car TEGRA124_CLK_DFLL_REF,
+tegra_car TEGRA124_CLK_I2C5;
+   clock-names = soc, ref, i2c;
+   resets = tegra_car TEGRA124_RST_DFLL_DVCO;
+   reset-names = dvco;
+   #clock-cells = 0;
+   clock-output-names = dfllCPU_out;
+   nvidia,sample-rate = 12500;
+   nvidia,droop-ctrl = 0x0f00;
+   nvidia,force-mode = 1;
+   nvidia,cf = 10;
+   nvidia,ci = 0;
+   nvidia,cg = 2;
+   status = disabled;
+   };
+
ahub@0,7030 {
compatible = nvidia,tegra124-ahub;
reg = 0x0 0x7030 0x0 0x200,
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 09/17] clk: tegra: Add the DFLL as a possible parent of the cclk_g clock

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

The DFLL clocksource was missing from the list of possible parents for
the fast CPU cluster. Add it to the list.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk-tegra-super-gen4.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c 
b/drivers/clk/tegra/clk-tegra-super-gen4.c
index feb3201..f1f4410 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -44,7 +44,9 @@ static const char *sclk_parents[] = { clk_m, pll_c_out1, 
pll_p_out4,
 
 static const char *cclk_g_parents[] = { clk_m, pll_c, clk_32k, pll_m,
pll_p, pll_p_out4, unused,
-   unused, pll_x };
+   unused, pll_x, unused, unused,
+   unused, unused, unused, unused,
+   dfllCPU_out };
 
 static const char *cclk_lp_parents[] = { clk_m, pll_c, clk_32k, pll_m,
 pll_p, pll_p_out4, unused,
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 14/17] cpufreq: Add cpufreq driver for Tegra124

2015-05-13 Thread Mikko Perttunen
From: Tuomas Tynkkynen ttynkky...@nvidia.com

Add a new cpufreq driver for Tegra124. Instead of using the PLLX as
the CPU clocksource, switch immediately to the DFLL. It allows the use
of higher clock rates, and will automatically scale the CPU voltage as
well. Besides the CPU clocksource switch, we let the cpufreq-dt driver
for all the cpufreq operations.

This driver also relies on the DFLL driver to fill the OPP table for the
CPU0 device, so that the cpufreq-dt driver knows what frequencies to
use.

Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
Acked-by: Viresh Kumar viresh.ku...@linaro.org
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
 drivers/cpufreq/Kconfig.arm|   7 ++
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra124-cpufreq.c | 214 +
 3 files changed, 222 insertions(+)
 create mode 100644 drivers/cpufreq/tegra124-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 4674299..4428ebd 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -265,6 +265,13 @@ config ARM_TEGRA20_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra20 SOCs.
 
+config ARM_TEGRA124_CPUFREQ
+   tristate Tegra124 CPUFreq support
+   depends on ARCH_TEGRA  CPUFREQ_DT
+   default y
+   help
+ This adds the CPUFreq driver support for Tegra124 SOCs.
+
 config ARM_PXA2xx_CPUFREQ
tristate Intel PXA2xx CPUfreq driver
depends on PXA27x || PXA25x
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 92391c0..5e9fa41 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ)  += sa1100-cpufreq.o
 obj-$(CONFIG_ARM_SA1110_CPUFREQ)   += sa1110-cpufreq.o
 obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 
 
##
diff --git a/drivers/cpufreq/tegra124-cpufreq.c 
b/drivers/cpufreq/tegra124-cpufreq.c
new file mode 100644
index 000..20bcceb
--- /dev/null
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -0,0 +1,214 @@
+/*
+ * Tegra 124 cpufreq driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)KBUILD_MODNAME :  fmt
+
+#include linux/clk.h
+#include linux/cpufreq-dt.h
+#include linux/err.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of_device.h
+#include linux/of.h
+#include linux/platform_device.h
+#include linux/pm_opp.h
+#include linux/regulator/consumer.h
+#include linux/types.h
+
+struct tegra124_cpufreq_priv {
+   struct regulator *vdd_cpu_reg;
+   struct clk *cpu_clk;
+   struct clk *pllp_clk;
+   struct clk *pllx_clk;
+   struct clk *dfll_clk;
+   struct platform_device *cpufreq_dt_pdev;
+};
+
+static int tegra124_cpu_switch_to_dfll(struct tegra124_cpufreq_priv *priv)
+{
+   struct clk *orig_parent;
+   int ret;
+
+   ret = clk_set_rate(priv-dfll_clk, clk_get_rate(priv-cpu_clk));
+   if (ret)
+   return ret;
+
+   orig_parent = clk_get_parent(priv-cpu_clk);
+   clk_set_parent(priv-cpu_clk, priv-pllp_clk);
+
+   ret = clk_prepare_enable(priv-dfll_clk);
+   if (ret)
+   goto out;
+
+   clk_set_parent(priv-cpu_clk, priv-dfll_clk);
+
+   return 0;
+
+out:
+   clk_set_parent(priv-cpu_clk, orig_parent);
+
+   return ret;
+}
+
+static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv)
+{
+   clk_set_parent(priv-cpu_clk, priv-pllp_clk);
+   clk_disable_unprepare(priv-dfll_clk);
+   regulator_sync_voltage(priv-vdd_cpu_reg);
+   clk_set_parent(priv-cpu_clk, priv-pllx_clk);
+}
+
+static struct cpufreq_dt_platform_data cpufreq_dt_pd = {
+   .independent_clocks = false,
+};
+
+static int tegra124_cpufreq_probe(struct platform_device *pdev)
+{
+   struct tegra124_cpufreq_priv *priv;
+   struct device_node *np;
+   struct device *cpu_dev;
+   struct platform_device_info cpufreq_dt_devinfo = {};
+   int ret;
+
+   priv = devm_kzalloc(pdev-dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   cpu_dev = get_cpu_device(0);
+   if (!cpu_dev)
+   return -ENODEV;
+
+   np

Re: [PATCH v9 00/17] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-05-14 Thread Mikko Perttunen

On 05/14/2015 01:47 AM, Rafael J. Wysocki wrote:
 ...


If I'm supposed to apply this, I need ACKs from the appropriate people on
all the patches where they are still missing.  Thanks!




I believe Thierry Reding will apply the series; your ACK as cpufreq 
maintainer for patch 13, and maybe also 12, would be welcome, though :)


Patch 13 just renames the old tegra-cpufreq driver that only applies to 
Tegra20 chips to tegra20-cpufreq.


Patch 12 adds device tree bindings. Maybe these can also be acked by 
Thierry? I'm not completely sure what's the convention.


Thanks,
Mikko.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9 06/17] clk: tegra: Add DFLL DVCO reset control for Tegra124

2015-05-13 Thread Mikko Perttunen
From: Paul Walmsley pwalms...@nvidia.com

The DVCO present in the DFLL IP block has a separate reset line,
exposed via the CAR IP block.  This reset line is asserted upon SoC
reset.  Unless something (such as the DFLL driver) deasserts this
line, the DVCO will not oscillate, although reads and writes to the
DFLL IP block will complete.

Thanks to Aleksandr Frid af...@nvidia.com for identifying this and
saving hours of debugging time.

Signed-off-by: Paul Walmsley pwalms...@nvidia.com
[ttynkkynen: ported to tegra124 from tegra114]
Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
[mikko.perttunen: ported to special reset callback]
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk-tegra124.c | 68 
 include/dt-bindings/reset/tegra124-car.h | 11 ++
 2 files changed, 79 insertions(+)
 create mode 100644 include/dt-bindings/reset/tegra124-car.h

diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index e8cca3e..42ba3d9 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -24,6 +24,7 @@
 #include linux/export.h
 #include linux/clk/tegra.h
 #include dt-bindings/clock/tegra124-car.h
+#include dt-bindings/reset/tegra124-car.h
 
 #include clk.h
 #include clk-id.h
@@ -39,6 +40,9 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
+#define RST_DFLL_DVCO  0x2f4
+#define DVFS_DFLL_RESET_SHIFT  0
+
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define PLLC_MISC2 0x88
@@ -1415,6 +1419,68 @@ static void __init tegra124_clock_apply_init_table(void)
 }
 
 /**
+ * tegra124_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra124_car_barrier(void)
+{
+   readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+void tegra124_clock_assert_dfll_dvco_reset(void)
+{
+   u32 v;
+
+   v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+   v |= (1  DVFS_DFLL_RESET_SHIFT);
+   writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+   tegra124_car_barrier();
+}
+
+/**
+ * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+void tegra124_clock_deassert_dfll_dvco_reset(void)
+{
+   u32 v;
+
+   v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+   v = ~(1  DVFS_DFLL_RESET_SHIFT);
+   writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+   tegra124_car_barrier();
+}
+
+int tegra124_reset_assert(unsigned long id)
+{
+   if (id == TEGRA124_RST_DFLL_DVCO)
+   tegra124_clock_assert_dfll_dvco_reset();
+   else
+   return -EINVAL;
+
+   return 0;
+}
+
+int tegra124_reset_deassert(unsigned long id)
+{
+   if (id == TEGRA124_RST_DFLL_DVCO)
+   tegra124_clock_deassert_dfll_dvco_reset();
+   else
+   return -EINVAL;
+
+   return 0;
+}
+
+/**
  * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
  *
  * Program an initial clock rate and enable or disable clocks needed
@@ -1499,6 +1565,8 @@ static void __init tegra124_132_clock_init_post(struct 
device_node *np)
 {
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
  pll_x_params);
+   tegra_init_special_resets(tegra124_reset_assert,
+ tegra124_reset_deassert);
tegra_add_of_provider(np);
 
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
diff --git a/include/dt-bindings/reset/tegra124-car.h 
b/include/dt-bindings/reset/tegra124-car.h
new file mode 100644
index 000..1cc771f
--- /dev/null
+++ b/include/dt-bindings/reset/tegra124-car.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides Tegra124-specific constants for binding
+ * nvidia,tegra124-car.
+ */
+
+#ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H
+#define _DT_BINDINGS_RESET_TEGRA124_CAR_H
+
+#define TEGRA124_RST_DFLL_DVCO  0x4000
+
+#endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v10 05/17] clk: tegra: Introduce ability for SoC-specific reset control callbacks

2015-05-19 Thread Mikko Perttunen
This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number = num_periph_banks * 32 is attempted to be asserted 
or deasserted respectively. Numbers greater than or equal to num_periph_banks * 
32
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.

Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk.c | 39 +++
 drivers/clk/tegra/clk.h |  3 +++
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 41cd87c..c093ed9 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -49,7 +49,6 @@
 #define RST_DEVICES_L  0x004
 #define RST_DEVICES_H  0x008
 #define RST_DEVICES_U  0x00C
-#define RST_DFLL_DVCO  0x2F4
 #define RST_DEVICES_V  0x358
 #define RST_DEVICES_W  0x35C
 #define RST_DEVICES_X  0x28C
@@ -79,6 +78,11 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static int special_reset_num;
+
 static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +156,29 @@ static int tegra_clk_rst_assert(struct 
reset_controller_dev *rcdev,
 */
tegra_read_chipid();
 
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_set_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_set_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + special_reset_num) {
+   return special_reset_assert(id);
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
 {
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_clr_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_clr_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + special_reset_num) {
+   return special_reset_deassert(id);
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +300,19 @@ void __init tegra_add_of_provider(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
 
rst_ctlr.of_node = np;
-   rst_ctlr.nr_resets = periph_banks * 32;
+   rst_ctlr.nr_resets = periph_banks * 32 + special_reset_num;
reset_controller_register(rst_ctlr);
 }
 
+void __init tegra_init_special_resets(int num,
+ int (*assert)(unsigned long),
+ int (*deassert)(unsigned long))
+{
+   special_reset_num = num;
+   special_reset_assert = assert;
+   special_reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
int i;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 75ddc8ff..f42cbbe 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -591,6 +591,9 @@ struct tegra_devclk {
char*con_id;
 };
 
+void tegra_init_special_resets(int num, int (*assert)(unsigned long),
+  int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
struct clk *clks[], int clk_max);
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v10 06/17] clk: tegra: Add DFLL DVCO reset control for Tegra124

2015-05-19 Thread Mikko Perttunen
From: Paul Walmsley pwalms...@nvidia.com

The DVCO present in the DFLL IP block has a separate reset line,
exposed via the CAR IP block.  This reset line is asserted upon SoC
reset.  Unless something (such as the DFLL driver) deasserts this
line, the DVCO will not oscillate, although reads and writes to the
DFLL IP block will complete.

Thanks to Aleksandr Frid af...@nvidia.com for identifying this and
saving hours of debugging time.

Signed-off-by: Paul Walmsley pwalms...@nvidia.com
[ttynkkynen: ported to tegra124 from tegra114]
Signed-off-by: Tuomas Tynkkynen ttynkky...@nvidia.com
[mikko.perttunen: ported to special reset callback]
Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk-tegra124.c | 68 
 include/dt-bindings/reset/tegra124-car.h | 12 ++
 2 files changed, 80 insertions(+)
 create mode 100644 include/dt-bindings/reset/tegra124-car.h

diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index e8cca3e..106ec45 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -24,6 +24,7 @@
 #include linux/export.h
 #include linux/clk/tegra.h
 #include dt-bindings/clock/tegra124-car.h
+#include dt-bindings/reset/tegra124-car.h
 
 #include clk.h
 #include clk-id.h
@@ -39,6 +40,9 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
+#define RST_DFLL_DVCO  0x2f4
+#define DVFS_DFLL_RESET_SHIFT  0
+
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define PLLC_MISC2 0x88
@@ -1415,6 +1419,68 @@ static void __init tegra124_clock_apply_init_table(void)
 }
 
 /**
+ * tegra124_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra124_car_barrier(void)
+{
+   readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+void tegra124_clock_assert_dfll_dvco_reset(void)
+{
+   u32 v;
+
+   v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+   v |= (1  DVFS_DFLL_RESET_SHIFT);
+   writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+   tegra124_car_barrier();
+}
+
+/**
+ * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+void tegra124_clock_deassert_dfll_dvco_reset(void)
+{
+   u32 v;
+
+   v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+   v = ~(1  DVFS_DFLL_RESET_SHIFT);
+   writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+   tegra124_car_barrier();
+}
+
+int tegra124_reset_assert(unsigned long id)
+{
+   if (id == TEGRA124_RST_DFLL_DVCO)
+   tegra124_clock_assert_dfll_dvco_reset();
+   else
+   return -EINVAL;
+
+   return 0;
+}
+
+int tegra124_reset_deassert(unsigned long id)
+{
+   if (id == TEGRA124_RST_DFLL_DVCO)
+   tegra124_clock_deassert_dfll_dvco_reset();
+   else
+   return -EINVAL;
+
+   return 0;
+}
+
+/**
  * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
  *
  * Program an initial clock rate and enable or disable clocks needed
@@ -1499,6 +1565,8 @@ static void __init tegra124_132_clock_init_post(struct 
device_node *np)
 {
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
  pll_x_params);
+   tegra_init_special_resets(1, tegra124_reset_assert,
+ tegra124_reset_deassert);
tegra_add_of_provider(np);
 
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
diff --git a/include/dt-bindings/reset/tegra124-car.h 
b/include/dt-bindings/reset/tegra124-car.h
new file mode 100644
index 000..070e4f6
--- /dev/null
+++ b/include/dt-bindings/reset/tegra124-car.h
@@ -0,0 +1,12 @@
+/*
+ * This header provides Tegra124-specific constants for binding
+ * nvidia,tegra124-car.
+ */
+
+#ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H
+#define _DT_BINDINGS_RESET_TEGRA124_CAR_H
+
+#define TEGRA124_RESET(x)  (6 * 32 + (x))
+#define TEGRA124_RST_DFLL_DVCO TEGRA124_RESET(0)
+
+#endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v10 05/17] clk: tegra: Introduce ability for SoC-specific reset control callbacks

2015-05-19 Thread Mikko Perttunen
Forgot to write it in the patch description, but v10 for patches 5 and 6 
changes the base for custom resets from 0x4000 to periph_banks * 32 
and also makes the SoC-specific code tell the core how many special 
resets it has. This is quite a bit cleaner than the previous version.


Thanks to Thierry for the idea.

Mikko

On 05/19/15 14:39, Mikko Perttunen wrote:

This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number = num_periph_banks * 32 is attempted to be asserted
or deasserted respectively. Numbers greater than or equal to num_periph_banks * 
32
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.

Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
  drivers/clk/tegra/clk.c | 39 +++
  drivers/clk/tegra/clk.h |  3 +++
  2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 41cd87c..c093ed9 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -49,7 +49,6 @@
  #define RST_DEVICES_L 0x004
  #define RST_DEVICES_H 0x008
  #define RST_DEVICES_U 0x00C
-#define RST_DFLL_DVCO  0x2F4
  #define RST_DEVICES_V 0x358
  #define RST_DEVICES_W 0x35C
  #define RST_DEVICES_X 0x28C
@@ -79,6 +78,11 @@ static struct clk **clks;
  static int clk_num;
  static struct clk_onecell_data clk_data;

+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static int special_reset_num;
+
  static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +156,29 @@ static int tegra_clk_rst_assert(struct 
reset_controller_dev *rcdev,
 */
tegra_read_chipid();

-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_set_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_set_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + special_reset_num) {
+   return special_reset_assert(id);
+   }

-   return 0;
+   return -EINVAL;
  }

  static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
  {
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_clr_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_clr_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + special_reset_num) {
+   return special_reset_deassert(id);
+   }

-   return 0;
+   return -EINVAL;
  }

  struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +300,19 @@ void __init tegra_add_of_provider(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);

rst_ctlr.of_node = np;
-   rst_ctlr.nr_resets = periph_banks * 32;
+   rst_ctlr.nr_resets = periph_banks * 32 + special_reset_num;
reset_controller_register(rst_ctlr);
  }

+void __init tegra_init_special_resets(int num,
+ int (*assert)(unsigned long),
+ int (*deassert)(unsigned long))
+{
+   special_reset_num = num;
+   special_reset_assert = assert;
+   special_reset_deassert = deassert;
+}
+
  void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
  {
int i;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 75ddc8ff..f42cbbe 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -591,6 +591,9 @@ struct tegra_devclk {
char*con_id;
  };

+void tegra_init_special_resets(int num, int (*assert)(unsigned long),
+  int (*deassert)(unsigned long));
+
  void tegra_init_from_table(struct tegra_clk_init_table *tbl,
struct clk *clks[], int clk_max);




--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 11/15] thermal: thermal: Add support for hardware-tracked trip points

2015-05-18 Thread Mikko Perttunen

Thanks for picking up this patch :)

Sorry for being late with these, but here's a few comments..

On 05/13/2015 11:52 AM, Sascha Hauer wrote:
 This adds support for hardware-tracked trip points to the device tree
 thermal sensor framework.

 The framework supports an arbitrary number of trip points. Whenever
 the current temperature is updated, the trip points immediately
 below and above the current temperature are found. A .set_trips
 callback is then called with the temperatures. If there is no trip
 point above or below the current temperature, the passed trip
 temperature will be -INT_MAX or INT_MAX respectively. In this callback,
 the driver should program the hardware such that it is notified
 when either of these trip points are triggered. When a trip point
 is triggered, the driver should call `thermal_zone_device_update'
 for the respective thermal zone. This will cause the trip points
 to be updated again.

 If .set_trips is not implemented, the framework behaves as before.

 This patch is based on an earlier version from Mikko Perttunen
 mikko.perttu...@kapsi.fi

 Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
 ---
  drivers/thermal/thermal_core.c | 43 
++

  include/linux/thermal.h|  3 +++
  2 files changed, 46 insertions(+)

 diff --git a/drivers/thermal/thermal_core.c 
b/drivers/thermal/thermal_core.c

 index 6bbf61f..3ae1795 100644
 --- a/drivers/thermal/thermal_core.c
 +++ b/drivers/thermal/thermal_core.c
 @@ -453,6 +453,45 @@ int thermal_zone_get_temp(struct 
thermal_zone_device *tz, int *temp)

  }
  EXPORT_SYMBOL_GPL(thermal_zone_get_temp);

 +static void thermal_zone_set_trips(struct thermal_zone_device *tz)
 +{
 +  int low = -INT_MAX;
 +  int high = INT_MAX;
 +  int trip_temp, hysteresis;
 +  int temp = tz-temperature;
 +  int i;
 +
 +  if (!tz-ops-set_trips)
 +  return;
 +
 +  /* No need to change trip points */
 +  if (temp  tz-prev_low_trip  temp  tz-prev_high_trip)
 +  return;
 +
 +  for (i = 0; i  tz-trips; i++) {
 +  int trip_low;
 +
 +  tz-ops-get_trip_temp(tz, i, trip_temp);
 +  tz-ops-get_trip_hyst(tz, i, hysteresis);
 +
 +  trip_low = trip_temp - hysteresis;
 +
 +  if (trip_low  temp  trip_low  low)
 +  low = trip_low;
 +
 +  if (trip_temp  temp  trip_temp  high)
 +  high = trip_temp;
 +  }
 +
 +  tz-prev_low_trip = low;
 +  tz-prev_high_trip = high;
 +
 +  dev_dbg(tz-device, new temperature boundaries: %d  x  %d\n,
 +  low, high);
 +
 +  tz-ops-set_trips(tz, low, high);

This should probably do something if set_trips returns an error code; at 
least an error message, perhaps enable polling? I'm not exactly sure 
what safety features the thermal framework has in general if errors happen..


One interesting thing I noticed was that at least the bang-bang governor 
only acts if the temperature is properly smaller than (trip temp - 
hysteresis). So perhaps we should specify the non-tripping range as 
[low, high)? Or we could change bang-bang.


 +}
 +
  void thermal_zone_device_update(struct thermal_zone_device *tz)
  {
int temp, ret, count;
 @@ -479,6 +518,8 @@ void thermal_zone_device_update(struct 
thermal_zone_device *tz)

dev_dbg(tz-device, last_temperature=%d, current_temperature=%d\n,
tz-last_temperature, tz-temperature);

 +  thermal_zone_set_trips(tz);
 +
for (count = 0; count  tz-trips; count++)
handle_thermal_trip(tz, count);
  }

set_trips should also be called from temp_store and other places that 
modify values that affect the trip points.


 @@ -1494,6 +1535,8 @@ struct thermal_zone_device 
*thermal_zone_device_register(const char *type,

tz-trips = trips;
tz-passive_delay = passive_delay;
tz-polling_delay = polling_delay;
 +  tz-prev_low_trip = INT_MAX;
 +  tz-prev_high_trip = -INT_MAX;

dev_set_name(tz-device, thermal_zone%d, tz-id);
result = device_register(tz-device);
 diff --git a/include/linux/thermal.h b/include/linux/thermal.h
 index 07bd5e8..aef6e13 100644
 --- a/include/linux/thermal.h
 +++ b/include/linux/thermal.h
 @@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
int (*unbind) (struct thermal_zone_device *,
   struct thermal_cooling_device *);
int (*get_temp) (struct thermal_zone_device *, int *);
 +  int (*set_trips) (struct thermal_zone_device *, int, int);
int (*get_mode) (struct thermal_zone_device *,
 enum thermal_device_mode *);
int (*set_mode) (struct thermal_zone_device *,
 @@ -180,6 +181,8 @@ struct thermal_zone_device {
int last_temperature;
int emul_temperature;
int passive;
 +  int prev_low_trip;
 +  int prev_high_trip;
unsigned int forced_passive;
const struct thermal_zone_device_ops *ops;
const struct thermal_zone_params *tzp;

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message

Re: [PATCH 12/15] thermal: of: implement .set_trips for device tree thermal zones

2015-05-18 Thread Mikko Perttunen

On 05/13/15 11:52, Sascha Hauer wrote:

Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
---
  drivers/thermal/of-thermal.c | 12 
  include/linux/thermal.h  |  3 +++
  2 files changed, 15 insertions(+)

diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index bd3185e..f8dd847 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -97,6 +97,17 @@ static int of_thermal_get_temp(struct thermal_zone_device 
*tz,
return data-ops-get_temp(data-sensor_data, temp);
  }

+static int of_thermal_set_trips(struct thermal_zone_device *tz,
+  int low, int high)
+{
+   struct __thermal_zone *data = tz-devdata;
+
+   if (!data-ops || !data-ops-set_trips)
+   return -ENOSYS;
+
+   return data-ops-set_trips(data-sensor_data, low, high);
+}
+
  /**
   * of_thermal_get_ntrips - function to export number of available trip
   *   points.
@@ -367,6 +378,7 @@ static int of_thermal_get_crit_temp(struct 
thermal_zone_device *tz,

  static const struct thermal_zone_device_ops of_thermal_ops = {
.get_temp = of_thermal_get_temp,
+   .set_trips = of_thermal_set_trips,
.get_trend = of_thermal_get_trend,
.set_emul_temp = of_thermal_set_emul_temp,

diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index aef6e13..b751f6b 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -267,12 +267,15 @@ struct thermal_genl_event {
   *
   * Optional:
   * @get_trend: a pointer to a function that reads the sensor temperature 
trend.
+ * @set_trips: a pointer to a function that sets a temperature window which 
shall
+ * trigger an interrupt when it is left.


Perhaps this documentation should be expanded a little; the commit 
message in the previous patch looked pretty good. The fact that the 
driver needs to call thermal_zone_device_update should be mentioned 
somewhere.



   * @set_emul_temp: a pointer to a function that sets sensor emulated
   *   temperature.
   */
  struct thermal_zone_of_device_ops {
int (*get_temp)(void *, int *);
int (*get_trend)(void *, int, enum thermal_trend *);
+   int (*set_trips)(void *, int, int);
int (*set_emul_temp)(void *, int);
  };




Thanks,
Mikko.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 10/18] clk: tegra: Initialize PLL_X before CCLK_G to ensure it has a parent

2015-04-11 Thread Mikko Perttunen

On 04/11/2015 12:08 AM, Michael Turquette wrote:

Quoting Mikko Perttunen (2015-03-01 04:44:33)

This patch moves the initialization of PLL_X to be slightly before
that of CCLK_G. This ensures that at boot, CCLK_G will immediately
have a parent and the common clock framework can determine its
clock rate correctly.

Without this patch, calling clk_put on CCLK_G could cause the CCF
to set its rate to zero, hanging the system.


Hi Mikko,

Patch looks fine to me but I wanted to get more info on the behavior you
mentioned above about clk_put. Is there some special circumstance that
causes this for you? Why does calling clk_put adjust the rate of your
clock?

Thanks,
Mike


Hi Mike,

this is the chain of events:
- CCLK_G is registered. CCF stores its current rate, but since it 
doesn't have a parent at this point, the rate is assumed zero.

- tegra cpufreq driver tries to probe, and clk_gets CCLK_G
- tegra dfll driver tries to probe, but fails
- tegra cpufreq driver's probe fails, and during unwinding clk_puts CCLK_G
- CCF attempts to restore CCLK_G's rate to what it was prior to the 
clk_get (to revert possible changes due to clock constraints)

- the stored rate was zero, so CCLK_G is set to zero.

We did discuss it a bit on IRC with Tomeu and Peter and agreed that some 
fix in CCF should be done, but we didn't get much further than that.


Mikko





Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
---
v8:
- Added

  drivers/clk/tegra/clk-tegra-super-gen4.c | 46 ++--
  1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c 
b/drivers/clk/tegra/clk-tegra-super-gen4.c
index f1f4410..c5ea9ee 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -104,6 +104,32 @@ void __init tegra_super_clk_gen4_init(void __iomem 
*clk_base,
 struct clk *clk;
 struct clk **dt_clk;

+   /*
+* Register PLL_X first so that CCLK_G has a parent at registration
+* time. This ensures that the common clock framework knows CCLK_G's
+* rate.
+*/
+
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
+   /* PLLX */
+   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
+   if (!dt_clk)
+   return;
+
+   clk = tegra_clk_register_pllxc(pll_x, pll_ref, clk_base,
+   pmc_base, CLK_IGNORE_UNUSED, params, NULL);
+   *dt_clk = clk;
+
+   /* PLLX_OUT0 */
+
+   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
+   if (!dt_clk)
+   return;
+   clk = clk_register_fixed_factor(NULL, pll_x_out0, pll_x,
+   CLK_SET_RATE_PARENT, 1, 2);
+   *dt_clk = clk;
+#endif
+
 /* CCLKG */
 dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
 if (dt_clk) {
@@ -127,25 +153,5 @@ void __init tegra_super_clk_gen4_init(void __iomem 
*clk_base,
 }

 tegra_sclk_init(clk_base, tegra_clks);
-
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
-   /* PLLX */
-   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
-   if (!dt_clk)
-   return;
-
-   clk = tegra_clk_register_pllxc(pll_x, pll_ref, clk_base,
-   pmc_base, CLK_IGNORE_UNUSED, params, NULL);
-   *dt_clk = clk;
-
-   /* PLLX_OUT0 */
-
-   dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
-   if (!dt_clk)
-   return;
-   clk = clk_register_fixed_factor(NULL, pll_x_out0, pll_x,
-   CLK_SET_RATE_PARENT, 1, 2);
-   *dt_clk = clk;
-#endif
  }

--
2.3.0



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 00/18] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-04-14 Thread Mikko Perttunen

On 04/14/2015 08:21 PM, Boris Brezillon wrote:

Hi Mikko,

On Tue, 14 Apr 2015 14:25:59 +0300
Mikko Perttunen mikko.perttu...@kapsi.fi wrote:


On 04/11/2015 12:11 AM, Michael Turquette wrote:

Quoting Thierry Reding (2015-03-11 03:07:43)

Hi Mike,

Have you had a chance to look at these changes to the Tegra clock
driver? If you're fine with it, I'd like to take these patches through
the Tegra tree because the rest of the series depends on them. I can
provide a stable branch in case we need to base other Tegra clock
changes on top of this.


Hi Thierry,

Clock patches (and corresponding DT binding descriptions and changes to
DTS) look fine to me. Please add:

Acked-by: Michael Turquette mturque...@linaro.org

I did have a question about the beahvior of clk_put in one of Mikko's
patches but it should not gate this series. I'm just trying to find out
if we have a bug in the framework or if the Tegra driver is a special
case.

Also I do not think a stable branch is necessary.

Regards,
Mike



Looks like in the meantime, this has been partially broken by
03bc10ab5b0f clk: check -determine/round_rate() return value in
clk_calc_new_rates. The highest rates supported by the DFLL clock have
1 in the MSB, so those cannot be entered after the aforementioned patch,
as the return value of round_rate is interpreted as an error. Avenues
that I can see: 1) revert the above patch 2) restrict the cpu clock rate
to those with 0 in the MSB 3) move to 64-bit clock rates.


How about changing -determine_rate() and -round_rate() prototypes so
that they always return 0 or an error code and passing the adjusted_rate
as an argument ?

Something like that:

int (*round_rate)(struct clk_hw *hw, unsigned long *rate,
  unsigned long *parent_rate);
int (*determine_rate)(struct clk_hw *hw, unsigned long *rate,
  unsigned long min_rate,
  unsigned long max_rate,
  unsigned long *best_parent_rate,
  struct clk_hw **best_parent_hw);

I know this implies a lot of changes (in all clock drivers and in the
core infrastructure), but I really think we should not mix error codes
and clock frequencies (even if we decide to move to a 64 bits rate
approach).


This sounds like a good idea, too.



Anyway, IMHO the only alternative to this solution is solution #3,
because #1 implies re-introducing another bug where
-round_rate()/-determine_rate() are silently ignored, and #2 implies
lying about your DFLL capabilities.



Yeah, #1 and #2 weren't really meant as realistic options to end up with :)


Mike, what's your opinion ?

Best Regards,

Boris



Cheers,
Mikko.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 00/18] Tegra124 CL-DVFS / DFLL clocksource + cpufreq

2015-04-14 Thread Mikko Perttunen

On 04/15/2015 12:06 AM, Michael Turquette wrote:

Quoting Mikko Perttunen (2015-04-14 12:40:36)

On 04/14/2015 08:21 PM, Boris Brezillon wrote:

Hi Mikko,

On Tue, 14 Apr 2015 14:25:59 +0300
Mikko Perttunen mikko.perttu...@kapsi.fi wrote:


On 04/11/2015 12:11 AM, Michael Turquette wrote:

Quoting Thierry Reding (2015-03-11 03:07:43)

Hi Mike,

Have you had a chance to look at these changes to the Tegra clock
driver? If you're fine with it, I'd like to take these patches through
the Tegra tree because the rest of the series depends on them. I can
provide a stable branch in case we need to base other Tegra clock
changes on top of this.


Hi Thierry,

Clock patches (and corresponding DT binding descriptions and changes to
DTS) look fine to me. Please add:

Acked-by: Michael Turquette mturque...@linaro.org

I did have a question about the beahvior of clk_put in one of Mikko's
patches but it should not gate this series. I'm just trying to find out
if we have a bug in the framework or if the Tegra driver is a special
case.

Also I do not think a stable branch is necessary.

Regards,
Mike



Looks like in the meantime, this has been partially broken by
03bc10ab5b0f clk: check -determine/round_rate() return value in
clk_calc_new_rates. The highest rates supported by the DFLL clock have
1 in the MSB, so those cannot be entered after the aforementioned patch,
as the return value of round_rate is interpreted as an error. Avenues
that I can see: 1) revert the above patch 2) restrict the cpu clock rate
to those with 0 in the MSB 3) move to 64-bit clock rates.


How about changing -determine_rate() and -round_rate() prototypes so
that they always return 0 or an error code and passing the adjusted_rate
as an argument ?

Something like that:

   int (*round_rate)(struct clk_hw *hw, unsigned long *rate,
 unsigned long *parent_rate);
   int (*determine_rate)(struct clk_hw *hw, unsigned long *rate,
 unsigned long min_rate,
 unsigned long max_rate,
 unsigned long *best_parent_rate,
 struct clk_hw **best_parent_hw);

I know this implies a lot of changes (in all clock drivers and in the
core infrastructure), but I really think we should not mix error codes
and clock frequencies (even if we decide to move to a 64 bits rate
approach).


This sounds like a good idea, too.


I've had this idea as well, which is to never return rates but only
error codes, and rates are passed by reference like in your example
above. Clearly the *best_parent_rate stuff already functions this way.
Would be cool to use a programming language that supported complex
return types ;-)


Algebraic data type pipe dreams.. :)







Anyway, IMHO the only alternative to this solution is solution #3,
because #1 implies re-introducing another bug where
-round_rate()/-determine_rate() are silently ignored, and #2 implies
lying about your DFLL capabilities.



Yeah, #1 and #2 weren't really meant as realistic options to end up with :)


Yes, seems that we're heading towards #3. In the mean time option #1.5
(the one where we change the round_rate/determine_rate semantics) is
probably a good idea and can resolve this issue in the shorter term
compared to signed 64-bit rates (and will be necessary anyhow if we use
unsigned 64-bit rates).

I'll add this to the high priority todo list since the Tegra EMC stuff
won't go for 4.1 but will very likely go for 4.2.


Wonderful :)

Thanks,
Mikko



Regards,
Mike




Mike, what's your opinion ?

Best Regards,

Boris



Cheers,
Mikko.



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] ARM: tegra: Correct which USB controller has the UTMI pad registers

2015-04-02 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen mikko.perttu...@kapsi.fi

On 04/02/2015 06:00 PM, Tomeu Vizoso wrote:

It should be the first controller, not the second.

This broke USB after 6261b06 (regulator: Defer lookup of supply to
regulator_get), because it changed the order in which the controllers
were probed.

The fix for this issue was suggested by Mikko Perttunen.

Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com
Cc: Mikko Perttunen mikko.perttu...@kapsi.fi
---

I think that the line numbers should be enough in this case, as I expect this 
to be merged soon, but just in case I'm sending the same patch with plenty of 
context.

Regards,

Tomeu

---
  arch/arm/boot/dts/tegra124.dtsi | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index cf01c81..cb786a9 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -821,77 +821,77 @@
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d00 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USBD,
 tegra_car TEGRA124_CLK_PLL_U,
 tegra_car TEGRA124_CLK_USBD;
clock-names = reg, pll_u, utmi-pads;
resets = tegra_car 59, tegra_car 22;
reset-names = usb, utmi-pads;
nvidia,hssync-start-delay = 0;
nvidia,idle-wait-delay = 17;
nvidia,elastic-limit = 16;
nvidia,term-range-adj = 6;
nvidia,xcvr-setup = 9;
nvidia,xcvr-lsfslew = 0;
nvidia,xcvr-lsrslew = 3;
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
+   nvidia,has-utmi-pad-registers;
status = disabled;
};

usb@0,7d004000 {
compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci, 
usb-ehci;
reg = 0x0 0x7d004000 0x0 0x4000;
interrupts = GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB2;
resets = tegra_car 58;
reset-names = usb;
nvidia,phy = phy2;
status = disabled;
};

phy2: usb-phy@0,7d004000 {
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d004000 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB2,
 tegra_car TEGRA124_CLK_PLL_U,
 tegra_car TEGRA124_CLK_USBD;
clock-names = reg, pll_u, utmi-pads;
resets = tegra_car 22, tegra_car 22;
reset-names = usb, utmi-pads;
nvidia,hssync-start-delay = 0;
nvidia,idle-wait-delay = 17;
nvidia,elastic-limit = 16;
nvidia,term-range-adj = 6;
nvidia,xcvr-setup = 9;
nvidia,xcvr-lsfslew = 0;
nvidia,xcvr-lsrslew = 3;
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
-   nvidia,has-utmi-pad-registers;
status = disabled;
};

usb@0,7d008000 {
compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci, 
usb-ehci;
reg = 0x0 0x7d008000 0x0 0x4000;
interrupts = GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH;
phy_type = utmi;
clocks = tegra_car TEGRA124_CLK_USB3;
resets = tegra_car 59;
reset-names = usb;
nvidia,phy = phy3;
status = disabled;
};

phy3: usb-phy@0,7d008000 {
compatible = nvidia,tegra124-usb-phy, 
nvidia,tegra30-usb-phy;
reg = 0x0 0x7d008000 0x0 0x4000,
  0x0 0x7d00 0x0 0x4000;
phy_type = utmi;



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] ARM: tegra: Correct which USB controller has the UTMI pad registers

2015-04-02 Thread Mikko Perttunen

On 04/02/2015 06:20 PM, Mikko Perttunen wrote:

Reviewed-by: Mikko Perttunen mikko.perttu...@kapsi.fi


Scratch that;

as Tuomas noted on IRC, the reset numbers here are still wrong.
phy1 should have 22 and phy2 58.



On 04/02/2015 06:00 PM, Tomeu Vizoso wrote:

It should be the first controller, not the second.

This broke USB after 6261b06 (regulator: Defer lookup of supply to
regulator_get), because it changed the order in which the controllers
were probed.

The fix for this issue was suggested by Mikko Perttunen.

Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com
Cc: Mikko Perttunen mikko.perttu...@kapsi.fi
---

I think that the line numbers should be enough in this case, as I
expect this to be merged soon, but just in case I'm sending the same
patch with plenty of context.

Regards,

Tomeu

---
  arch/arm/boot/dts/tegra124.dtsi | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra124.dtsi
b/arch/arm/boot/dts/tegra124.dtsi
index cf01c81..cb786a9 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -821,77 +821,77 @@
  compatible = nvidia,tegra124-usb-phy,
nvidia,tegra30-usb-phy;
  reg = 0x0 0x7d00 0x0 0x4000,
0x0 0x7d00 0x0 0x4000;
  phy_type = utmi;
  clocks = tegra_car TEGRA124_CLK_USBD,
   tegra_car TEGRA124_CLK_PLL_U,
   tegra_car TEGRA124_CLK_USBD;
  clock-names = reg, pll_u, utmi-pads;
  resets = tegra_car 59, tegra_car 22;
  reset-names = usb, utmi-pads;
  nvidia,hssync-start-delay = 0;
  nvidia,idle-wait-delay = 17;
  nvidia,elastic-limit = 16;
  nvidia,term-range-adj = 6;
  nvidia,xcvr-setup = 9;
  nvidia,xcvr-lsfslew = 0;
  nvidia,xcvr-lsrslew = 3;
  nvidia,hssquelch-level = 2;
  nvidia,hsdiscon-level = 5;
  nvidia,xcvr-hsslew = 12;
+nvidia,has-utmi-pad-registers;
  status = disabled;
  };

  usb@0,7d004000 {
  compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci,
usb-ehci;
  reg = 0x0 0x7d004000 0x0 0x4000;
  interrupts = GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH;
  phy_type = utmi;
  clocks = tegra_car TEGRA124_CLK_USB2;
  resets = tegra_car 58;
  reset-names = usb;
  nvidia,phy = phy2;
  status = disabled;
  };

  phy2: usb-phy@0,7d004000 {
  compatible = nvidia,tegra124-usb-phy,
nvidia,tegra30-usb-phy;
  reg = 0x0 0x7d004000 0x0 0x4000,
0x0 0x7d00 0x0 0x4000;
  phy_type = utmi;
  clocks = tegra_car TEGRA124_CLK_USB2,
   tegra_car TEGRA124_CLK_PLL_U,
   tegra_car TEGRA124_CLK_USBD;
  clock-names = reg, pll_u, utmi-pads;
  resets = tegra_car 22, tegra_car 22;
  reset-names = usb, utmi-pads;
  nvidia,hssync-start-delay = 0;
  nvidia,idle-wait-delay = 17;
  nvidia,elastic-limit = 16;
  nvidia,term-range-adj = 6;
  nvidia,xcvr-setup = 9;
  nvidia,xcvr-lsfslew = 0;
  nvidia,xcvr-lsrslew = 3;
  nvidia,hssquelch-level = 2;
  nvidia,hsdiscon-level = 5;
  nvidia,xcvr-hsslew = 12;
-nvidia,has-utmi-pad-registers;
  status = disabled;
  };

  usb@0,7d008000 {
  compatible = nvidia,tegra124-ehci, nvidia,tegra30-ehci,
usb-ehci;
  reg = 0x0 0x7d008000 0x0 0x4000;
  interrupts = GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH;
  phy_type = utmi;
  clocks = tegra_car TEGRA124_CLK_USB3;
  resets = tegra_car 59;
  reset-names = usb;
  nvidia,phy = phy3;
  status = disabled;
  };

  phy3: usb-phy@0,7d008000 {
  compatible = nvidia,tegra124-usb-phy,
nvidia,tegra30-usb-phy;
  reg = 0x0 0x7d008000 0x0 0x4000,
0x0 0x7d00 0x0 0x4000;
  phy_type = utmi;



--
To unsubscribe from this list: send the line unsubscribe linux-tegra in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ARM: tegra: Correct which USB controller has the UTMI pad registers

2015-04-02 Thread Mikko Perttunen
Have you checked that this patch applies correctly, considering that the 
chunks are still ambiguous? :)


Mikko

On 04/02/2015 05:31 PM, Tomeu Vizoso wrote:

It should be the first controller, not the second.

This broke USB after 6261b06 (regulator: Defer lookup of supply to
regulator_get), because it changed the order in which the controllers
were probed.

The fix for this issue was suggested by Mikko Perttunen.

Signed-off-by: Tomeu Vizoso tomeu.viz...@collabora.com
Cc: Mikko Perttunen mikko.perttu...@kapsi.fi
---
  arch/arm/boot/dts/tegra124.dtsi | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index cf01c81..cb786a9 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -838,6 +838,7 @@
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
+   nvidia,has-utmi-pad-registers;
status = disabled;
};

@@ -874,7 +875,6 @@
nvidia,hssquelch-level = 2;
nvidia,hsdiscon-level = 5;
nvidia,xcvr-hsslew = 12;
-   nvidia,has-utmi-pad-registers;
status = disabled;
};




--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 05/15] thermal: Add comment explaining test for critical temperature

2015-05-20 Thread Mikko Perttunen

On 05/13/15 11:52, Sascha Hauer wrote:

The code testing if a temperature should be emulated or not is
not obvious. Add a comment explaining why this test is done.

Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
---
  drivers/thermal/thermal_core.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 3e0fe55..e204deb 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -435,6 +435,11 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, 
int *temp)
}
}

+   /*
+* Only allow emulating a temperature when the real temperature
+* is below the critical temperature so that the emulation code
+* cannot hide critical conditions.
+*/
if (!ret  *temp  crit_temp)
*temp = tz-emul_temperature;
}



Reviewed-by: Mikko Perttunen mperttu...@nvidia.com

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 06/15] thermal: inline only once used function

2015-05-20 Thread Mikko Perttunen

On 05/13/15 11:52, Sascha Hauer wrote:

Inline update_temperature into its only caller to make the code
more readable.

Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
---
  drivers/thermal/thermal_core.c | 17 +
  1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index e204deb..19da022 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -450,9 +450,12 @@ exit:
  }
  EXPORT_SYMBOL_GPL(thermal_zone_get_temp);

-static void update_temperature(struct thermal_zone_device *tz)
+void thermal_zone_device_update(struct thermal_zone_device *tz)
  {
-   int temp, ret;
+   int temp, ret, count;
+
+   if (!tz-ops-get_temp)
+   return;

ret = thermal_zone_get_temp(tz, temp);
if (ret) {
@@ -471,16 +474,6 @@ static void update_temperature(struct thermal_zone_device 
*tz)
trace_thermal_temperature(tz);
dev_dbg(tz-device, last_temperature=%d, current_temperature=%d\n,
tz-last_temperature, tz-temperature);
-}
-
-void thermal_zone_device_update(struct thermal_zone_device *tz)
-{
-   int count;
-
-   if (!tz-ops-get_temp)
-   return;
-
-   update_temperature(tz);

for (count = 0; count  tz-trips; count++)
handle_thermal_trip(tz, count);



This is a slight change in that if get_temp fails, governors were 
updated before but aren't now. But I don't know why that would matter.


Reviewed-by: Mikko Perttunen mperttu...@nvidia.com

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 01/15] thermal: consistently use int for temperatures

2015-05-20 Thread Mikko Perttunen

On 05/13/15 11:52, Sascha Hauer wrote:

The thermal code uses int, long and unsigned long for temperatures
in different places. Using an unsigned type limits the thermal framework
to positive temperatures without need. 'long' is 64bit on several
architectures which is not needed. Consistently use a plain 'int'
for temperatures.

Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
---
...


It looks like some longs remain in db8500_thermal.c, int340x_thermal/*,
intel_soc_dts_thermal.c, kirkwood_thermal.c, rockchip_thermal.c and 
samsung/exynos_tmu.c. (found by 'grep -R long drivers/thermal/*)


Cheers,
Mikko.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v11 05/17] clk: tegra: Introduce ability for SoC-specific reset control callbacks

2015-05-20 Thread Mikko Perttunen
This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number = num_periph_banks * 32 is attempted to be asserted
or deasserted respectively. Numbers greater than or equal to num_periph_banks * 
32
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.

Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
 drivers/clk/tegra/clk.c | 39 +++
 drivers/clk/tegra/clk.h |  3 +++
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 41cd87c..3290fd6 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -49,7 +49,6 @@
 #define RST_DEVICES_L  0x004
 #define RST_DEVICES_H  0x008
 #define RST_DEVICES_U  0x00C
-#define RST_DFLL_DVCO  0x2F4
 #define RST_DEVICES_V  0x358
 #define RST_DEVICES_W  0x35C
 #define RST_DEVICES_X  0x28C
@@ -79,6 +78,11 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static unsigned int num_special_reset;
+
 static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +156,29 @@ static int tegra_clk_rst_assert(struct 
reset_controller_dev *rcdev,
 */
tegra_read_chipid();
 
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_set_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_set_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + num_special_reset) {
+   return special_reset_assert(id);
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
 {
-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_clr_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_clr_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + num_special_reset) {
+   return special_reset_deassert(id);
+   }
 
-   return 0;
+   return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +300,19 @@ void __init tegra_add_of_provider(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
 
rst_ctlr.of_node = np;
-   rst_ctlr.nr_resets = periph_banks * 32;
+   rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
reset_controller_register(rst_ctlr);
 }
 
+void __init tegra_init_special_resets(unsigned int num,
+ int (*assert)(unsigned long),
+ int (*deassert)(unsigned long))
+{
+   num_special_reset = num;
+   special_reset_assert = assert;
+   special_reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
int i;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 75ddc8ff..0621887 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -591,6 +591,9 @@ struct tegra_devclk {
char*con_id;
 };
 
+void tegra_init_special_resets(unsigned int num, int (*assert)(unsigned long),
+  int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
struct clk *clks[], int clk_max);
 
-- 
2.3.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 11/15] thermal: thermal: Add support for hardware-tracked trip points

2015-05-19 Thread Mikko Perttunen

On 05/18/15 23:28, Brian Norris wrote:

On Mon, May 18, 2015 at 10:13:46PM +0300, Mikko Perttunen wrote:

On 05/18/2015 09:44 PM, Brian Norris wrote:

On Mon, May 18, 2015 at 02:09:44PM +0200, Sascha Hauer wrote:

On Mon, May 18, 2015 at 12:06:50PM +0300, Mikko Perttunen wrote:

One interesting thing I noticed was that at least the bang-bang
governor only acts if the temperature is properly smaller than (trip
temp - hysteresis). So perhaps we should specify the non-tripping
range as [low, high)? Or we could change bang-bang.


I wonder how we can protect against such off-by-one errors anyway.
Generally a hardware might operate on raw values rather than directly
in temperature values in °C. This means a driver for this must have
celsius_to_raw and raw_to_celsius conversion functions. Now it can
happen that due to rounding errors celsius_to_raw(Tcrit) returns a raw
value that when converted back to celsius is different from the
original value in °C. This would mean the hardware triggers an interrupt
for a trip point and the thermal core does not react because get_temp
actually returns a different temperature than previously programmed as
interrupt trigger. This way we would lose hot (or cold) events.


This also highlights another fact: there's a race between interrupt
generation and temperature reading (-get_temp()). I would expect any
hardware interrupt thermal sensor would also have a latched temperature
reading to correspond with it, and there would be no guarantee that this
latched temperature will match the polled reading seen once you reach
thermal_zone_device_update(). So a hardware driver might report a
thermal update, but the temperature reported to the core won't
necessarily match what interrupt was meant for.


Does this actually matter? The thermal core will reset trips and
apply cooling using the new - most recent - value. Using bang bang
as example, if the temperature has risen since the interrupt fired,
the cooling device will correctly not be switched off. If the
temperature has fallen, it will again be correctly switched off. The
only issue is then if the temperature is exactly 'trip temp - trip
hyst' which will cause set_trips to load the trip points below, but
not cause bang bang to turn off the cooling device, and the next
chance it will have will only be at the next below trip point. Well,
this is still safe (at least until you replace cooling device with
heating device), so maybe it isn't that big of an issue.

Please point out if there's a problem with my line of reasoning.


I'm not sure I followed exactly the reason for the low-temp/hyst corner
case, but otherwise I guess that makes sense. The only problem IMO, is
that you're encouraging the generation of spurious notifications; if the
temperature is constantly changing right around 'trip temp', but it
never settles above 'trip temp' long enough for the core to re-capture
the high temperature scenario, you'll just keep making useless calls to
thermal_zone_device_update(). This kind of defeats the purpose of the
hysteresis, right?


The corner case with bang bang is as follows:
- Say we have trip points as 50C and 80C, both with 5C hysteresis, and 
these are programmed into hardware. So the actual hardware trip points 
are 45C and 80C.

- Currently the temperature is, say, 60C and the fan is turned on.
- Temperature drops to 45C, the lower trip point is triggered.
- 45C = 50C - 5C, so the fan is not turned off.

If we said that the hysteresis was 0C, then bang bang is certainly 
correct in that if the trip point was at 50C, it shouldn't turn the fan 
off, since that is greater than or equal to the requested temperature 
for cooling.


The function you describe would certainly be useful for eliminating 
possible superfluous interrupts due to temperature wobble, though I'm 
not sure how much of a problem that even would be.




I'd really rather have a high temperature interrupt generate exactly one
notification to the core framework, and that the sensor driver can rely
on that one interrupt being handled as a high temperature situation,
allowing it to disable the high-temp interrupt.

One of my biggest problems with the thermal subsystem so far is that
thermal_zone_device_update() doesn't actually seem to have any specific
semantic meaning. It just means that there was some reason to update
something. So then, you have to reason about a particular thermal
governor (bang bang) in order to make something sensible. If I want to
use a different sort of user-space governor, then I have to reevaluate
all these same assumptions, and it seems like I end up with a sub-par
solution.


Yeah, though I'm not sure if you can ever be sure that the governor is 
fine not getting regular temperature updates, so I imagine you might 
always end up needing to pick your governors with that in mind. In 
practice, this might not be so horrible.




As a side note: I have patches to extend some of the uevent information
passed by the user-space governor too

Re: [PATCH v10 05/17] clk: tegra: Introduce ability for SoC-specific reset control callbacks

2015-05-19 Thread Mikko Perttunen

On 05/19/2015 05:59 PM, Thierry Reding wrote:

On Tue, May 19, 2015 at 02:39:27PM +0300, Mikko Perttunen wrote:

This patch allows SoC-specific CAR initialization routines to register
their own reset_assert and reset_deassert callbacks with the common Tegra
CAR code. If defined, the common code will call these callbacks when a
reset control with number = num_periph_banks * 32 is attempted to be asserted
or deasserted respectively. Numbers greater than or equal to num_periph_banks * 
32
are used to avoid clashes with low numbers that are automatically mapped to
standard CAR reset lines.

Each SoC with these special resets should specify the defined reset control
numbers in a device tree header file.


This is looking pretty good, but I think we can simplify a wee bit
more...


Signed-off-by: Mikko Perttunen mikko.perttu...@kapsi.fi
Acked-by: Michael Turquette mturque...@linaro.org
---
  drivers/clk/tegra/clk.c | 39 +++
  drivers/clk/tegra/clk.h |  3 +++
  2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 41cd87c..c093ed9 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -49,7 +49,6 @@
  #define RST_DEVICES_L 0x004
  #define RST_DEVICES_H 0x008
  #define RST_DEVICES_U 0x00C
-#define RST_DFLL_DVCO  0x2F4
  #define RST_DEVICES_V 0x358
  #define RST_DEVICES_W 0x35C
  #define RST_DEVICES_X 0x28C
@@ -79,6 +78,11 @@ static struct clk **clks;
  static int clk_num;
  static struct clk_onecell_data clk_data;

+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static int special_reset_num;


I think we can get rid of this if we...


+
  static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +156,29 @@ static int tegra_clk_rst_assert(struct 
reset_controller_dev *rcdev,
 */
tegra_read_chipid();

-   writel_relaxed(BIT(id % 32),
-   clk_base + periph_regs[id / 32].rst_set_reg);
+   if (id  periph_banks * 32) {
+   writel_relaxed(BIT(id % 32),
+  clk_base + periph_regs[id / 32].rst_set_reg);
+   return 0;
+   } else if (id  periph_banks * 32 + special_reset_num) {
+   return special_reset_assert(id);
+   }


... pass id - periph_banks * 32 into special_reset_assert(). Oh, but
then...


The reason I don't subtract periph_banks * 32 is because this way the 
code in the SoC-specific callback can just include the dt-bindings 
header and use the same defines used in the device tree.





@@ -286,10 +300,19 @@ void __init tegra_add_of_provider(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);

rst_ctlr.of_node = np;
-   rst_ctlr.nr_resets = periph_banks * 32;
+   rst_ctlr.nr_resets = periph_banks * 32 + special_reset_num;


... this is no longer going to work. We could keep special_reset_num,
though obviously it should be an unsigned int and renamed to
num_special_reset, yet still pass the relative ID into the SoC-specific
callbacks, after all that's what they care about and each implementation
would have to subtract periph_banks * 32 anyway.


Mostly agreed, but see above :)




reset_controller_register(rst_ctlr);
  }

+void __init tegra_init_special_resets(int num,
+ int (*assert)(unsigned long),
+ int (*deassert)(unsigned long))
+{
+   special_reset_num = num;
+   special_reset_assert = assert;
+   special_reset_deassert = deassert;
+}
+


I think we could possibly improve this interface somewhat by turning it
upside-down, that is, make SoC-specific drivers call this in a helper
fashion. But this is good enough for now, I can always take a stab at
refactoring if I get bored.

Thierry



Thanks,
Mikko

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 01/15] thermal: consistently use int for temperatures

2015-05-20 Thread Mikko Perttunen

On 05/20/15 11:34, Sascha Hauer wrote:

On Wed, May 20, 2015 at 10:12:44AM +0300, Mikko Perttunen wrote:

On 05/13/15 11:52, Sascha Hauer wrote:

The thermal code uses int, long and unsigned long for temperatures
in different places. Using an unsigned type limits the thermal framework
to positive temperatures without need. 'long' is 64bit on several
architectures which is not needed. Consistently use a plain 'int'
for temperatures.

Signed-off-by: Sascha Hauer s.ha...@pengutronix.de
---
...


It looks like some longs remain in db8500_thermal.c, int340x_thermal/*,
intel_soc_dts_thermal.c, kirkwood_thermal.c, rockchip_thermal.c and
samsung/exynos_tmu.c. (found by 'grep -R long drivers/thermal/*)


I looked over it again and found the following. Sorry, I really thought
I had compile tested all drivers. I found nothing in db8500_thermal.c,
intel_soc_dts_thermal.c and rockchip_thermal.c though. There are some
(unsigned)longs used as temperatures in these files, but I haven't
changed them on purpose to not make the patch bigger as necessary. I
only changed the places where (unsigned)longs are used as pointers.
Do you think it's necessary to change all temperatures, even the ones
only used internally in drivers?

Sascha


I guess changing just the framework interface would be fine for now,
though I don't think there are that many internal uses remaining either.

Reviewed-by: Mikko Perttunen mperttu...@nvidia.com

Cheers,
Mikko.



---8--


From 4cf8fe3b3ef1bd9db6090305ea2b9995f0dbffa4 Mon Sep 17 00:00:00 2001

From: Sascha Hauer s.ha...@pengutronix.de
Date: Wed, 20 May 2015 10:28:39 +0200
Subject: [PATCH] fixup! thermal: consistently use int for temperatures

---
  drivers/thermal/int340x_thermal/int3400_thermal.c  | 4 ++--
  drivers/thermal/int340x_thermal/processor_thermal_device.c | 4 ++--
  drivers/thermal/kirkwood_thermal.c | 2 +-
  drivers/thermal/samsung/exynos_tmu.c   | 2 +-
  4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c 
b/drivers/thermal/int340x_thermal/int3400_thermal.c
index 96bdf8a..5836e55 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
@@ -186,7 +186,7 @@ static int int3400_thermal_run_osc(acpi_handle handle,
  }

  static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
-   unsigned long *temp)
+   int *temp)
  {
*temp = 20 * 1000; /* faked temp sensor with 20C */
return 0;
@@ -231,7 +231,7 @@ static int int3400_thermal_set_mode(struct 
thermal_zone_device *thermal,
return result;
  }

-static const struct thermal_zone_device_ops int3400_thermal_ops = {
+static struct thermal_zone_device_ops int3400_thermal_ops = {
.get_temp = int3400_thermal_get_temp,
  };

diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c 
b/drivers/thermal/int340x_thermal/processor_thermal_device.c
index 5e8d8e9..c8afd34 100644
--- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c
@@ -139,7 +139,7 @@ static int get_tjmax(void)
return -EINVAL;
  }

-static int read_temp_msr(unsigned long *temp)
+static int read_temp_msr(int *temp)
  {
int cpu;
u32 eax, edx;
@@ -171,7 +171,7 @@ err_ret:
  }

  static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
-unsigned long *temp)
+int *temp)
  {
int ret;

diff --git a/drivers/thermal/kirkwood_thermal.c 
b/drivers/thermal/kirkwood_thermal.c
index abba3e2..5bcdbd6 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -33,7 +33,7 @@ struct kirkwood_thermal_priv {
  };

  static int kirkwood_get_temp(struct thermal_zone_device *thermal,
- unsigned long *temp)
+ int *temp)
  {
unsigned long reg;
struct kirkwood_thermal_priv *priv = thermal-devdata;
diff --git a/drivers/thermal/samsung/exynos_tmu.c 
b/drivers/thermal/samsung/exynos_tmu.c
index 29eaf4d..ed55fd9 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -812,7 +812,7 @@ out:
  #else
  #define exynos4412_tmu_set_emulation NULL
  #define exynos5440_tmu_set_emulation NULL
-static int exynos_tmu_set_emulation(void *drv_data,unsigned long temp)
+static int exynos_tmu_set_emulation(void *drv_data, int temp)
{ return -EINVAL; }
  #endif /* CONFIG_THERMAL_EMULATION */




--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 11/15] thermal: thermal: Add support for hardware-tracked trip points

2015-05-19 Thread Mikko Perttunen

On 05/19/15 16:58, Sascha Hauer wrote:

On Mon, May 18, 2015 at 02:09:44PM +0200, Sascha Hauer wrote:

Hi Mikko,

On Mon, May 18, 2015 at 12:06:50PM +0300, Mikko Perttunen wrote:

+   for (i = 0; i  tz-trips; i++) {
+   int trip_low;
+
+   tz-ops-get_trip_temp(tz, i, trip_temp);
+   tz-ops-get_trip_hyst(tz, i, hysteresis);
+
+   trip_low = trip_temp - hysteresis;
+
+   if (trip_low  temp  trip_low  low)
+   low = trip_low;
+
+   if (trip_temp  temp  trip_temp  high)
+   high = trip_temp;
+   }
+
+   tz-prev_low_trip = low;
+   tz-prev_high_trip = high;
+
+   dev_dbg(tz-device, new temperature boundaries: %d  x  %d\n,
+   low, high);
+
+   tz-ops-set_trips(tz, low, high);


This should probably do something if set_trips returns an error
code; at least an error message, perhaps enable polling? I'm not
exactly sure what safety features the thermal framework has in
general if errors happen..


Currently a thermal zone has the passive_delay and polling_delay
variables. If these are nonzero the thermal core will always poll. A
purely interrupt driven thermal zone would set these values to zero.
In this case the thermal core has no basis for polling, so we would
have to make up polling intervals when set_trips fails. Another
possibility would be to interpret the *_delay variables as 'when
set_trips is available, do not poll. When something goes wrong, use
*_delay as polling intervals'



One interesting thing I noticed was that at least the bang-bang
governor only acts if the temperature is properly smaller than (trip
temp - hysteresis). So perhaps we should specify the non-tripping
range as [low, high)? Or we could change bang-bang.


I wonder how we can protect against such off-by-one errors anyway.
Generally a hardware might operate on raw values rather than directly
in temperature values in °C. This means a driver for this must have
celsius_to_raw and raw_to_celsius conversion functions. Now it can
happen that due to rounding errors celsius_to_raw(Tcrit) returns a raw
value that when converted back to celsius is different from the
original value in °C. This would mean the hardware triggers an interrupt
for a trip point and the thermal core does not react because get_temp
actually returns a different temperature than previously programmed as
interrupt trigger. This way we would lose hot (or cold) events.


As a simple example we could imagine a 12bit adc which has:

u32 mcelsius_to_raw(int temp)
{
return temp / 30;
}

int raw_to_mcelsius(u32 raw)
{
return temp * 30;
}

Now if the thermal framework requests an interrupt at 77000mC we
would program a raw value of 77000 / 30 = 2566.67, due to integer
rounding we would program 2566. Now when the interrupt is triggered with
this exact raw value we would convert it back to 2566 * 30 = 76980. The
thermal framework would realize that this is below the threshold, do
nothing and go back to sleep.
I am beginning to think that implementing interrupts like this is not a
good idea, at least I found no convenient way out of this situation.


Couldn't you just specify that the driver should do the best it can? 
That is, in this case, the driver would program the hardware for the 
least possible value x for which raw_to_mcelsius(x) = 77000.




Sascha



Cheers,
Mikko.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] drm/tegra: Add VIC support

2015-05-21 Thread Mikko Perttunen
Hi, very good patch!

Here are a few small comments. Aside those, you should also add a
section to
Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt in a
separate patch.

Thanks,
Mikko.

On 05/21/2015 04:20 PM, Arto Merilainen wrote:
 This patch adds support for Video Image Compositor engine which
 can be used for 2d operations.
 
 The engine has a microcontroller (Falcon) that acts as a frontend
 for the rest of the unit. In order to properly utilize the engine,
 the frontend must be booted before pushing any commands.
 
 Signed-off-by: Andrew Chew ac...@nvidia.com
 Signed-off-by: Arto Merilainen amerilai...@nvidia.com
 ---
  drivers/gpu/drm/tegra/Makefile |   3 +-
  drivers/gpu/drm/tegra/drm.c|   9 +-
  drivers/gpu/drm/tegra/drm.h|   1 +
  drivers/gpu/drm/tegra/vic.c| 593 
 +
  drivers/gpu/drm/tegra/vic.h| 116 
  include/linux/host1x.h |   1 +
  6 files changed, 721 insertions(+), 2 deletions(-)
  create mode 100644 drivers/gpu/drm/tegra/vic.c
  create mode 100644 drivers/gpu/drm/tegra/vic.h
 
 diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
 index 2c66a8db9da4..3bc3566e00b6 100644
 --- a/drivers/gpu/drm/tegra/Makefile
 +++ b/drivers/gpu/drm/tegra/Makefile
 @@ -13,6 +13,7 @@ tegra-drm-y := \
   sor.o \
   dpaux.o \
   gr2d.o \
 - gr3d.o
 + gr3d.o \
 + vic.o
  
  obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
 diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
 index bfad15a913a0..d947f5f4d801 100644
 --- a/drivers/gpu/drm/tegra/drm.c
 +++ b/drivers/gpu/drm/tegra/drm.c
 @@ -1,6 +1,6 @@
  /*
   * Copyright (C) 2012 Avionic Design GmbH
 - * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
 + * Copyright (C) 2012-2015 NVIDIA CORPORATION.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
 @@ -1048,6 +1048,7 @@ static const struct of_device_id host1x_drm_subdevs[] = 
 {
   { .compatible = nvidia,tegra124-dc, },
   { .compatible = nvidia,tegra124-sor, },
   { .compatible = nvidia,tegra124-hdmi, },
 + { .compatible = nvidia,tegra124-vic, },
   { /* sentinel */ }
  };
  
 @@ -1097,8 +1098,14 @@ static int __init host1x_drm_init(void)
   if (err  0)
   goto unregister_gr2d;
  
 + err = platform_driver_register(tegra_vic_driver);
 + if (err  0)
 + goto unregister_gr3d;
 +
   return 0;
  
 +unregister_gr3d:
 + platform_driver_unregister(tegra_gr3d_driver);
  unregister_gr2d:
   platform_driver_unregister(tegra_gr2d_driver);
  unregister_dpaux:
 diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
 index 0e7756e720c5..a9c02a80d6bf 100644
 --- a/drivers/gpu/drm/tegra/drm.h
 +++ b/drivers/gpu/drm/tegra/drm.h
 @@ -275,5 +275,6 @@ extern struct platform_driver tegra_hdmi_driver;
  extern struct platform_driver tegra_dpaux_driver;
  extern struct platform_driver tegra_gr2d_driver;
  extern struct platform_driver tegra_gr3d_driver;
 +extern struct platform_driver tegra_vic_driver;
  
  #endif /* HOST1X_DRM_H */
 diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
 new file mode 100644
 index ..b7c5a96697ed
 --- /dev/null
 +++ b/drivers/gpu/drm/tegra/vic.c
 @@ -0,0 +1,593 @@
 +/*
 + * Copyright (c) 2015, NVIDIA Corporation.
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include linux/of.h
 +#include linux/of_device.h
 +#include linux/of_platform.h
 +#include linux/clk.h
 +#include linux/host1x.h
 +#include linux/module.h
 +#include linux/firmware.h
 +#include linux/platform_device.h
 +#include linux/reset.h
 +#include soc/tegra/pmc.h
 +#include linux/iommu.h
 +
 +#include drm.h
 +#include gem.h
 +#include vic.h
 +
 +#define VIC_IDLE_TIMEOUT_DEFAULT 1   /* 10 milliseconds */
 +#define VIC_IDLE_CHECK_PERIOD10  /* 10 usec */
 +
 +struct vic;

This doesn't seem to be needed here.

 +
 +struct vic_config {
 + /* firmware name */
 + char *ucode_name;
 +
 + /* class id */
 + u32 class_id;
 +
 + /* powergate id */
 + int powergate_id;
 +};
 +
 +struct vic {
 + struct {
 + u32 bin_data_offset;
 + u32 data_offset;
 + u32 data_size;
 + u32 code_offset;
 + u32 size;
 + } os, fce;
 +
 + struct tegra_bo *ucode_bo;
 + bool ucode_valid;
 + void *ucode_vaddr;
 +
 + bool booted;
 +
 + void __iomem *regs;
 + struct tegra_drm_client client;
 + struct host1x_channel *channel;
 + struct iommu_domain *domain;
 + struct device *dev;
 + struct clk *clk;
 + struct reset_control *rst;
 +
 + /* Platform configuration */
 + 

Re: [PATCH 3/4] drm/tegra: Add VIC support

2015-05-21 Thread Mikko Perttunen

On 05/21/2015 06:10 PM, Arto Merilainen wrote:

...

+
+vic-rst = devm_reset_control_get(dev, vic03);


I might prefer just vic as the clock/reset name. The name is often
used as a sort of role for the clock/reset for the device, not
necessarily the raw name of the correct clock/reset.



I considered that - but I then noticed that
drivers/clk/tegra/clk-tegra124.c was already using vic03 variant. I can
write a patch for changing that too.


Well, the two can be different; the clock-name in device tree kind of 
means string that i use to refer to a clock that powers the VIC unit. 
It's not really a big deal though, both ways are used in DT bindings.


Mikko

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] regulator: max8973: Set VSEL regmap ops if DVS GPIO is not set

2015-07-28 Thread Mikko Perttunen
Use regmap helpers for get_voltage_sel and set_voltage_sel ops
if the DVS GPIO is not set.

The DVS GPIO allows on the fly selection of the VSEL register
from two choices. However, if it is not set, the VSEL register
will stay fixed and we can use the regmap ops. This allows use
of the *hardware_vsel* regulator APIs.

Signed-off-by: Mikko Perttunen mperttu...@nvidia.com
---
This was just compile-tested as I don't have a board with this regulator.

 drivers/regulator/max8973-regulator.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/regulator/max8973-regulator.c 
b/drivers/regulator/max8973-regulator.c
index a3e0bccb3f7d..5b75b7c2e3ea 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -637,6 +637,15 @@ static int max8973_probe(struct i2c_client *client,
max-lru_index[i] = i;
max-lru_index[0] = max-curr_vout_reg;
max-lru_index[max-curr_vout_reg] = 0;
+   } else {
+   /*
+* If there is no DVS GPIO, the VOUT register
+* address is fixed.
+*/
+   max-ops.set_voltage_sel = regulator_set_voltage_sel_regmap;
+   max-ops.get_voltage_sel = regulator_get_voltage_sel_regmap;
+   max-desc.vsel_reg = max-curr_vout_reg;
+   max-desc.vsel_mask = MAX8973_VOUT_MASK;
}
 
if (pdata_from_dt)
-- 
2.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH] dt: Tegra XUSB padctl: per-lane PHYs and USB lane map

2015-10-22 Thread Mikko Perttunen

On 10/20/2015 06:56 PM, Stephen Warren wrote:

...

In drivers/pci/host/pci-tegra.c tegra_pcie_get_resources() I see a call
to devm_phy_optional_get().

The SATA driver doesn't seem to do anything with phys at the moment,
although tegra124.dtsi does put phy-related properties into the SATA DT
node.


FWIW, the SATA driver does use the PHY - just through the 
ahci_platform_{get,enable,...}_resources API. (so is life..)


Mikko



So, we can either:
a) Just ignore DT ABI for these cases claiming the DT binding is not yet
declared stable.

b) Continue to support those specifier values for ABI reasons, which
needs the "_LEGACY" values shown above.

(a) is certainly simpler.
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] clk: tegra: Unlock top rates for Tegra124 DFLL clock

2015-09-15 Thread Mikko Perttunen
The new determine_rate prototype allows for clock rates exceeding
2^31-1 Hz to be used. Switch the DFLL clock to use determine_rate
instead of round_rate and unlock the top rates supported by the
Tegra124.

Signed-off-by: Mikko Perttunen <mikko.perttu...@kapsi.fi>
---
 drivers/clk/tegra/clk-dfll.c | 15 ---
 drivers/clk/tegra/cvb.c  |  7 ---
 2 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index 4adff56..7bd309c 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -1004,24 +1004,25 @@ static unsigned long dfll_clk_recalc_rate(struct clk_hw 
*hw,
return td->last_unrounded_rate;
 }
 
-static long dfll_clk_round_rate(struct clk_hw *hw,
-   unsigned long rate,
-   unsigned long *parent_rate)
+/* Must use determine_rate since it allows for rates exceeding 2^31-1 */
+static int dfll_clk_determine_rate(struct clk_hw *hw,
+  struct clk_rate_request *clk_req)
 {
struct tegra_dfll *td = clk_hw_to_dfll(hw);
struct dfll_rate_req req;
int ret;
 
-   ret = dfll_calculate_rate_request(td, , rate);
+   ret = dfll_calculate_rate_request(td, , clk_req->rate);
if (ret)
return ret;
 
/*
-* Don't return the rounded rate, since it doesn't really matter as
+* Don't set the rounded rate, since it doesn't really matter as
 * the output rate will be voltage controlled anyway, and cpufreq
 * freaks out if any rounding happens.
 */
-   return rate;
+
+   return 0;
 }
 
 static int dfll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1037,7 +1038,7 @@ static const struct clk_ops dfll_clk_ops = {
.enable = dfll_clk_enable,
.disable= dfll_clk_disable,
.recalc_rate= dfll_clk_recalc_rate,
-   .round_rate = dfll_clk_round_rate,
+   .determine_rate = dfll_clk_determine_rate,
.set_rate   = dfll_clk_set_rate,
 };
 
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index 0204e08..69c74ee 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -78,13 +78,6 @@ static int build_opp_table(const struct cvb_table *d,
if (!table->freq || (table->freq > max_freq))
break;
 
-   /*
-* FIXME after clk_round_rate/clk_determine_rate prototypes
-* have been updated
-*/
-   if (table->freq & (1<<31))
-   continue;
-
dfll_mv = get_cvb_voltage(
speedo_value, d->speedo_scale, >coefficients);
dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-25 Thread Mikko Perttunen

On 07/25/16 14:05, Antonio Ospite wrote:

On Mon, 25 Jul 2016 11:14:04 +0200
Benjamin Tissoires  wrote:


On Jul 21 2016 or thereabouts, Antonio Ospite wrote:

[...]

It would be interesting to understand why some (supposedly) compatible
devices break, maybe they rely on the fact that the PS3 would use the
original report?


[just speculating]
I would be *really* surprised if the Sony software were to overwrite the
report descriptor of their own sony controllers. My guess is that their
HID stack or their Playstation driver is compatible with the original
report descriptors and so they can handle the differences between
original and weirdo controllers.



That's basically what I was thinking too, in my last sentence I meant
to write report _descriptor_ :)

Mikko, if you have some time, could you post the original report
descriptor for your device?


Sure, here's the output from hidrd-convert:

0x05, 0x01, /*  Usage Page (Desktop),   */
0x09, 0x04, /*  Usage (Joystick),   */
0xA1, 0x01, /*  Collection (Application),   */
0x09, 0x01, /*  Usage (Pointer),*/
0xA1, 0x00, /*  Collection (Physical),  */
0x05, 0x09, /*  Usage Page (Button),*/
0x19, 0x01, /*  Usage Minimum (01h),*/
0x29, 0x0A, /*  Usage Maximum (0Ah),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x25, 0x01, /*  Logical Maximum (1),*/
0x75, 0x01, /*  Report Size (1),*/
0x95, 0x0A, /*  Report Count (10),  */
0x81, 0x02, /*  Input (Variable),   */
0x95, 0x06, /*  Report Count (6),   */
0x81, 0x03, /*  Input (Constant, Variable), */
0xC0,   /*  End Collection, */
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x15, 0x00, /*  Logical Minimum (0),*/
0x25, 0x01, /*  Logical Maximum (1),*/
0x25, 0x01, /*  Logical Maximum (1),*/
0x25, 0x01, /*  Logical Maximum (1),*/
0xC0/*  End Collection  */




$ hexdump /sys/bus/hid/devices/\:\:.0001/report_descriptor

or

$ hidrd-convert -i natv -o code 
/sys/bus/hid/devices/\:\:.0001/report_descriptor

You can also find out the length of the raw output report with trial and
error, start with a line like this:

$ sudo hexdump -v -e '49/1 "%02x " "\n"' /dev/hidraw0

and increase/decrease the value (49 works with original controllers)
until you see a regular pattern when comparing lines.



/dev/hidraw0 seems to be all zeroes straight from the beginning


Anyways this is just for curiosity, we are not going to spend too much
time on that... or are we? :)


At least it's some reference information.. :)



Thanks,
   Antonio



Cheers,
Mikko.



Re: [PATCH] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-25 Thread Mikko Perttunen

On 07/25/16 18:23, Mikko Perttunen wrote:

On 07/25/16 14:05, Antonio Ospite wrote:

You can also find out the length of the raw output report with trial and
error, start with a line like this:

$ sudo hexdump -v -e '49/1 "%02x " "\n"' /dev/hidraw0

and increase/decrease the value (49 works with original controllers)
until you see a regular pattern when comparing lines.



/dev/hidraw0 seems to be all zeroes straight from the beginning


Actually, pressing some buttons on the pad, it seems that the report 
length is two bytes





Anyways this is just for curiosity, we are not going to spend too much
time on that... or are we? :)


At least it's some reference information.. :)



Thanks,
   Antonio



Cheers,
Mikko.





Re: [PATCH v2] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-25 Thread Mikko Perttunen

Reviewed-by: Benjamin Tissoires 
Acked-by: Antonio Ospite 


Thanks!

Mikko




[PATCH v2] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-21 Thread Mikko Perttunen
From: Mikko Perttunen <mperttu...@nvidia.com>

The FutureMax Dance Mat claims to be a SixAxis controller
but breaks if descriptor fixups are applied. Detect the
device using its USB product string and disable fixups
when it is detected.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2: don't use usb device properties

 drivers/hid/hid-sony.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 310436a..29a1aa9 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -51,6 +51,7 @@
 #define NAVIGATION_CONTROLLER_USB BIT(9)
 #define NAVIGATION_CONTROLLER_BT  BIT(10)
 #define SINO_LITE_CONTROLLER  BIT(11)
+#define FUTUREMAX_DANCE_MAT   BIT(12)
 
 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -1125,7 +1126,7 @@ static u8 *sony_report_fixup(struct hid_device *hdev, u8 
*rdesc,
 {
struct sony_sc *sc = hid_get_drvdata(hdev);
 
-   if (sc->quirks & SINO_LITE_CONTROLLER)
+   if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
return rdesc;
 
/*
@@ -2289,6 +2290,9 @@ static int sony_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
struct sony_sc *sc;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
 
+   if (!strcmp(hdev->name, "FutureMax Dance Mat"))
+   quirks |= FUTUREMAX_DANCE_MAT;
+
sc = devm_kzalloc(>dev, sizeof(*sc), GFP_KERNEL);
if (sc == NULL) {
hid_err(hdev, "can't alloc sony descriptor\n");
-- 
2.9.0



[PATCH] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-17 Thread Mikko Perttunen
From: Mikko Perttunen <mperttu...@nvidia.com>

The FutureMax Dance Mat claims to be a SixAxis controller
but breaks if descriptor fixups are applied. Detect the
device using its USB product string and disable fixups
when it is detected.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/hid/hid-sony.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 310436a..4c976f7 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -36,6 +36,9 @@
 #include 
 #include 
 #include 
+#include 
+
+#include "usbhid/usbhid.h"
 
 #include "hid-ids.h"
 
@@ -51,6 +54,7 @@
 #define NAVIGATION_CONTROLLER_USB BIT(9)
 #define NAVIGATION_CONTROLLER_BT  BIT(10)
 #define SINO_LITE_CONTROLLER  BIT(11)
+#define FUTUREMAX_DANCE_MAT   BIT(12)
 
 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -1125,7 +1129,7 @@ static u8 *sony_report_fixup(struct hid_device *hdev, u8 
*rdesc,
 {
struct sony_sc *sc = hid_get_drvdata(hdev);
 
-   if (sc->quirks & SINO_LITE_CONTROLLER)
+   if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
return rdesc;
 
/*
@@ -2288,6 +2292,15 @@ static int sony_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
unsigned long quirks = id->driver_data;
struct sony_sc *sc;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
+   struct usb_device *usb_dev;
+
+   if (quirks & SIXAXIS_CONTROLLER_USB) {
+   usb_dev = hid_to_usb_dev(hdev);
+   if (usb_dev && usb_dev->product &&
+   !strcmp(usb_dev->product, "FutureMax Dance Mat")) {
+   quirks |= FUTUREMAX_DANCE_MAT;
+   }
+   }
 
sc = devm_kzalloc(>dev, sizeof(*sc), GFP_KERNEL);
if (sc == NULL) {
-- 
2.8.2



Re: [PATCH] HID: sony: disable descriptor fixup for FutureMax Dance Mat

2016-07-19 Thread Mikko Perttunen

On 07/18/16 17:28, Benjamin Tissoires wrote:

On Jul 17 2016 or thereabouts, Mikko Perttunen wrote:

From: Mikko Perttunen <mperttu...@nvidia.com>
...
 #include 
 #include 
 #include 
+#include 
+
+#include "usbhid/usbhid.h"


I spent a lot of effort 2 years ago to remove the usb dependency, I'd
prefer not adding a strong deps on it again.



I see, I'll remove it.



 #include "hid-ids.h"

@@ -51,6 +54,7 @@
 #define NAVIGATION_CONTROLLER_USB BIT(9)
 #define NAVIGATION_CONTROLLER_BT  BIT(10)
 #define SINO_LITE_CONTROLLER  BIT(11)
+#define FUTUREMAX_DANCE_MAT   BIT(12)

 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -1125,7 +1129,7 @@ static u8 *sony_report_fixup(struct hid_device *hdev, u8 
*rdesc,
 {
struct sony_sc *sc = hid_get_drvdata(hdev);

-   if (sc->quirks & SINO_LITE_CONTROLLER)
+   if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT))
return rdesc;

/*
@@ -2288,6 +2292,15 @@ static int sony_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
unsigned long quirks = id->driver_data;
struct sony_sc *sc;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
+   struct usb_device *usb_dev;
+
+   if (quirks & SIXAXIS_CONTROLLER_USB) {
+   usb_dev = hid_to_usb_dev(hdev);
+   if (usb_dev && usb_dev->product &&
+   !strcmp(usb_dev->product, "FutureMax Dance Mat")) {i


If they decided to reuse the same PID than one existing, and you have no
other choice but to rely on the name, you can simply have a match on
hdev->name instead of adding the USB dependency.


Ah, didn't notice this!



Also, I think it would be better to have a check on the existing report
descriptor instead of blindly fixing it. Other drivers make sure they
are fixing the correct region before overriding it, but I think using a
md5sum might be just easier (though that's not required for your patch I
think).


I agree. In fact, the mat used to work back in 3.15 when the driver did 
some rudimentary checks before overwriting the descriptor. In any case, 
it would be difficult for me to add the checks since the mat is the only 
piece of hardware I own that is handled by this driver.




Cheers,
Benjamin


 ...


Cheers, and thanks for the review! I'll post a v2 once I get the chance.

Mikko



Re: [PATCH 4/7] clk: tegra: remove non-existing pll_m_out1 clock

2017-02-22 Thread Mikko Perttunen

Missing commit message

Cheers,
Mikko.

On 02/22/2017 05:13 PM, Peter De Schrijver wrote:

Signed-off-by: Peter De Schrijver 
---
 drivers/clk/tegra/clk-tegra210.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 7bda8ba..b7ef8a7 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2115,7 +2115,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
[tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true },
[tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true },
[tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true },
-   [tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = 
true },
[tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true },
[tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = 
true },
[tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = 
true },
@@ -2229,7 +2228,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
{ .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
{ .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
{ .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
-   { .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
{ .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
{ .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
{ .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
@@ -2404,9 +2402,6 @@ static void __init tegra210_pll_init(void __iomem 
*clk_base,
clk_register_clkdev(clk, "pll_mb", NULL);
clks[TEGRA210_CLK_PLL_MB] = clk;

-   clk_register_clkdev(clk, "pll_m_out1", NULL);
-   clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
-
/* PLLM_UD */
clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
CLK_SET_RATE_PARENT, 1, 1);



Re: [PATCH 1/7] clk: tegra: fix pll_a1 iddq register, add pll_a1

2017-02-22 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 02/22/2017 05:13 PM, Peter De Schrijver wrote:

pll_a1 was using CLK_RST_CONTROLLER_PLLA1_MISC_0 for IDDQ control rather
than the correct register CLK_RST_CONTROLLER_PLLA1_MISC_1. Also add pll_a1
to the set of clocks defined for Tegra210.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 2896d2e..2ef8d49 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -1772,7 +1772,7 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
.misc_reg = PLLA1_MISC0,
.lock_mask = PLLCX_BASE_LOCK,
.lock_delay = 300,
-   .iddq_reg = PLLA1_MISC0,
+   .iddq_reg = PLLA1_MISC1,
.iddq_bit_idx = PLLCX_IDDQ_BIT,
.reset_reg = PLLA1_MISC0,
.reset_bit_idx = PLLCX_RESET_BIT,
@@ -2209,6 +2209,7 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
[tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present 
= true },
[tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present 
= true },
[tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true 
},
+   [tegra_clk_pll_a1] = { .dt_id = TEGRA210_CLK_PLL_A1, .present = true },
 };

 static struct tegra_devclk devclks[] __initdata = {



Re: [PATCH 6/7] clk: tegra: correct tegra210_pll_fixed_mdiv_cfg rate calculation

2017-02-23 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:14, Peter De Schrijver wrote:

Return the actually achieved rate in cfg->output_rate rather than just the
requested rate. This is important to make clk_round_rate return the correct
result.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index fe698d2..58d7f9c 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -1222,6 +1222,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
cfg->n = p_rate / cf;

cfg->sdm_data = 0;
+   cfg->output_rate = input_rate;
if (params->sdm_ctrl_reg) {
unsigned long rem = p_rate - cf * cfg->n;
/* If ssc is enabled SDM enabled as well, even for integer n */
@@ -1232,10 +1233,15 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw 
*hw,
s -= PLL_SDM_COEFF / 2;
cfg->sdm_data = sdin_din_to_data(s);
}
+   cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 +
+   sdin_data_to_din(cfg->sdm_data);
+   cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF;
+   } else {
+   cfg->output_rate *= cfg->n;
+   cfg->output_rate /= p * cfg->m;
}

cfg->input_rate = input_rate;
-   cfg->output_rate = rate;

return 0;
 }



Re: [PATCH 7/7] clk: tegra: fix type for m field

2017-02-23 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:14, Peter De Schrijver wrote:

When used as part of fractional ndiv calculations, the current range is not
enough because the denominator of the fraction is multiplied with m.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 6ba82ec..a62ea73 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -116,7 +116,7 @@ struct tegra_clk_pll_freq_table {
unsigned long   input_rate;
unsigned long   output_rate;
u32 n;
-   u16 m;
+   u32 m;
u8  p;
u8  cpcon;
u16 sdm_data;



Re: [PATCH 2/7] clk: tegra: fix isp clock modelling

2017-02-22 Thread Mikko Perttunen
The TRM shows a CLK_SOURCE_ISPB register, but after some discussion, it 
seems like that is a documentation generation bug, so this should be 
correct.


Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:13, Peter De Schrijver wrote:

The 2 isp clocks (ispa and ispb) share a mux/divider control. So model
this as 1 mux/divider clock and child gate clocks.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-id.h   |  1 +
 drivers/clk/tegra/clk-tegra-periph.c | 11 +--
 drivers/clk/tegra/clk-tegra210.c |  1 +
 include/dt-bindings/clock/tegra210-car.h |  4 ++--
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index 5738635..1019eb8 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -307,6 +307,7 @@ enum clk_id {
tegra_clk_xusb_ssp_src,
tegra_clk_sclk_mux,
tegra_clk_sor_safe,
+   tegra_clk_ispa,
tegra_clk_max,
 };

diff --git a/drivers/clk/tegra/clk-tegra-periph.c 
b/drivers/clk/tegra/clk-tegra-periph.c
index 4ce4e7f..19b00b7 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -168,6 +168,12 @@
  0, TEGRA_PERIPH_NO_GATE, _clk_id,\
  _parents##_idx, 0, _lock)

+#define MUX8_NOGATE(_name, _parents, _offset, _clk_id) \
+   TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
+ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+ 0, TEGRA_PERIPH_NO_GATE, _clk_id,\
+ _parents##_idx, 0, NULL)
+
 #define INT(_name, _parents, _offset,  \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
@@ -739,7 +745,7 @@
MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, 
TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 
164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, 
TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
-   MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 
23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9),
+   MUX8_NOGATE("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, 
CLK_SOURCE_ISP, tegra_clk_isp_9),
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149,  0, 
tegra_clk_entropy),
MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149,  0, 
tegra_clk_entropy_8),
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, 
TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
@@ -819,7 +825,8 @@
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, 
tegra_clk_sata_cold, 0),
-   GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
+   GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0),
+   GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0),
GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 2ef8d49..7bda8ba 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2210,6 +2210,7 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
[tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present 
= true },
[tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true 
},
[tegra_clk_pll_a1] = { .dt_id = TEGRA210_CLK_PLL_A1, .present = true },
+   [tegra_clk_ispa] = { .dt_id = TEGRA210_CLK_ISPA, .present = true },
 };

 static struct tegra_devclk devclks[] __initdata = {
diff --git a/include/dt-bindings/clock/tegra210-car.h 
b/include/dt-bindings/clock/tegra210-car.h
index 35288b2..f5c6563 100644
--- a/include/dt-bindings/clock/tegra210-car.h
+++ b/include/dt-bindings/clock/tegra210-car.h
@@ -39,7 +39,7 @@
 /* 20 (register bit affects vi and vi_sensor) */
 /* 21 */
 #define TEGRA210_CLK_USBD 22
-#define TEGRA210_CLK_ISP 23
+#define TEGRA210_CLK_ISPA 23
 /* 24 */
 /* 25 */
 #define TEGRA210_CLK_DISP2 26
@@ -349,7 +349,7 @@
 #define TEGRA210_CLK_PLL_RE_OUT1 319
 /* 320 */
 /* 321 */
-/* 322 */
+#define TEGRA210_CLK_ISP 322
 /* 323 */
 /* 324 */
 /* 325 */



Re: [PATCH 4/7] clk: tegra: remove non-existing pll_m_out1 clock

2017-02-23 Thread Mikko Perttunen

Whoops, that is, after a commit message is added.

On 23.02.2017 10:17, Mikko Perttunen wrote:

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:13, Peter De Schrijver wrote:

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c
b/drivers/clk/tegra/clk-tegra210.c
index 7bda8ba..b7ef8a7 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2115,7 +2115,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
 [tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present =
true },
 [tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present =
true },
 [tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present =
true },
-[tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1,
.present = true },
 [tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present =
true },
 [tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1,
.present = true },
 [tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3,
.present = true },
@@ -2229,7 +2228,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
 { .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
 { .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
 { .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
-{ .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
 { .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
 { .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
 { .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
@@ -2404,9 +2402,6 @@ static void __init tegra210_pll_init(void
__iomem *clk_base,
 clk_register_clkdev(clk, "pll_mb", NULL);
 clks[TEGRA210_CLK_PLL_MB] = clk;

-clk_register_clkdev(clk, "pll_m_out1", NULL);
-clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
-
 /* PLLM_UD */
 clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
 CLK_SET_RATE_PARENT, 1, 1);


--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/7] clk: tegra: remove non-existing pll_m_out1 clock

2017-02-23 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:13, Peter De Schrijver wrote:

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 7bda8ba..b7ef8a7 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2115,7 +2115,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
[tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true },
[tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true },
[tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true },
-   [tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = 
true },
[tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true },
[tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = 
true },
[tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = 
true },
@@ -2229,7 +2228,6 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv)
{ .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
{ .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
{ .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
-   { .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
{ .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
{ .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
{ .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
@@ -2404,9 +2402,6 @@ static void __init tegra210_pll_init(void __iomem 
*clk_base,
clk_register_clkdev(clk, "pll_mb", NULL);
clks[TEGRA210_CLK_PLL_MB] = clk;

-   clk_register_clkdev(clk, "pll_m_out1", NULL);
-   clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
-
/* PLLM_UD */
clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
CLK_SET_RATE_PARENT, 1, 1);



Re: [PATCH 3/7] clk: tegra: correct afi parent

2017-02-23 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:13, Peter De Schrijver wrote:

The parent for afi is actually mselect, not clk_m.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra-periph.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra-periph.c 
b/drivers/clk/tegra/clk-tegra-periph.c
index 19b00b7..c9e795b 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -815,7 +815,7 @@
GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
-   GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
+   GATE("afi", "mselect", 72, 0, tegra_clk_afi, 0),
GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),



Re: [PATCH 5/7] clk: tegra: don't warn for PLL defaults unnecessarily

2017-02-23 Thread Mikko Perttunen

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>

On 22.02.2017 17:14, Peter De Schrijver wrote:

If the PLL is on, only warn if the defaults are not yet set. Otherwise be
silent.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index b7ef8a7..fe698d2 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -502,7 +502,7 @@ static void tegra210_pllcx_set_defaults(const char *name,
pllcx->params->defaults_set = true;

if (readl_relaxed(clk_base + pllcx->params->base_reg) &
-   PLL_ENABLE) {
+   PLL_ENABLE && !pllcx->params->defaults_set) {
/* PLL is ON: only check if defaults already set */
pllcx_check_defaults(pllcx->params);
pr_warn("%s already enabled. Postponing set full defaults\n",
@@ -608,7 +608,6 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll 
*plld)

if (readl_relaxed(clk_base + plld->params->base_reg) &
PLL_ENABLE) {
-   pr_warn("PLL_D already enabled. Postponing set full 
defaults\n");

/*
 * PLL is ON: check if defaults already set, then set those
@@ -625,6 +624,9 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll 
*plld)
_pll_misc_chk_default(clk_base, plld->params, 0, val,
~mask & PLLD_MISC0_WRITE_MASK);

+   if (!plld->params->defaults_set)
+   pr_warn("PLL_D already enabled. Postponing set full 
defaults\n");
+
/* Enable lock detect */
mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE;
val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
@@ -896,7 +898,6 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll 
*pllx)
val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT;

if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) {
-   pr_warn("PLL_X already enabled. Postponing set full 
defaults\n");

/*
 * PLL is ON: check if defaults already set, then set those
@@ -904,6 +905,8 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll 
*pllx)
 */
pllx_check_defaults(pllx);

+   if (!pllx->params->defaults_set)
+   pr_warn("PLL_X already enabled. Postponing set full 
defaults\n");
/* Configure dyn ramp, disable lock override */
writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);

@@ -948,7 +951,6 @@ static void tegra210_pllmb_set_defaults(struct 
tegra_clk_pll *pllmb)
pllmb->params->defaults_set = true;

if (val & PLL_ENABLE) {
-   pr_warn("PLL_MB already enabled. Postponing set full 
defaults\n");

/*
 * PLL is ON: check if defaults already set, then set those
@@ -959,6 +961,8 @@ static void tegra210_pllmb_set_defaults(struct 
tegra_clk_pll *pllmb)
_pll_misc_chk_default(clk_base, pllmb->params, 0, val,
~mask & PLLMB_MISC1_WRITE_MASK);

+   if (!pllmb->params->defaults_set)
+   pr_warn("PLL_MB already enabled. Postponing set full 
defaults\n");
/* Enable lock detect */
val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
val &= ~mask;
@@ -1008,13 +1012,14 @@ static void tegra210_pllp_set_defaults(struct 
tegra_clk_pll *pllp)
pllp->params->defaults_set = true;

if (val & PLL_ENABLE) {
-   pr_warn("PLL_P already enabled. Postponing set full 
defaults\n");

/*
 * PLL is ON: check if defaults already set, then set those
 * that can be updated in flight.
 */
pllp_check_defaults(pllp, true);
+   if (!pllp->params->defaults_set)
+   pr_warn("PLL_P already enabled. Postponing set full 
defaults\n");

/* Enable lock detect */
val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]);
@@ -1069,13 +1074,14 @@ static void tegra210_pllu_set_defaults(struct 
tegra_clk_pll *pllu)
pllu->params->defaults_set = true;

if (val & PLL_ENABLE) {
-   pr_warn("PLL_U already enabled. Postponing set full 
defaults\n");

/*
 * PLL is ON: check if defaults alrea

Re: [PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()

2017-02-27 Thread Mikko Perttunen
plat_dat);

return ret;
@@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct platform_device 
*pdev)

 static int dwc_eth_dwmac_remove(struct platform_device *pdev)
 {
-   return stmmac_pltfr_remove(pdev);
+   struct net_device *ndev = platform_get_drvdata(pdev);
+   struct stmmac_priv *priv = netdev_priv(ndev);
+   const struct dwc_eth_dwmac_data *data;
+   int err;
+
+   data = of_device_get_match_data(>dev);
+
+   err = stmmac_dvr_remove(>dev);
+   if (err < 0)
+   dev_err(>dev, "failed to remove platform: %d\n", err);
+
+   err = data->remove(pdev);
+   if (err < 0)
+   dev_err(>dev, "failed to remove subdriver: %d\n", err);
+
+   stmmac_remove_config_dt(pdev, priv->plat);
+
+   return err;
 }

 static const struct of_device_id dwc_eth_dwmac_match[] = {
-   { .compatible = "snps,dwc-qos-ethernet-4.10", },
+   { .compatible = "snps,dwc-qos-ethernet-4.10", .data = _qos_data },
{ }
 };
 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);



Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>


Re: [PATCH 2/7] net: stmmac: Balance PTP reference clock enable/disable

2017-02-27 Thread Mikko Perttunen

On 23.02.2017 19:24, Thierry Reding wrote:

From: Thierry Reding 

clk_prepare_enable() and clk_disable_unprepare() for this clock aren't
properly balanced, which can trigger a WARN_ON() in the common clock
framework.

Signed-off-by: Thierry Reding 
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 -
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3cbe09682afe..6b7a5ce19589 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1711,6 +1711,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool 
init_ptp)
stmmac_mmc_setup(priv);

if (init_ptp) {
+   ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
+   if (ret < 0)
+   netdev_warn(priv->dev, "failed to enable PTP reference 
clock: %d\n", ret);
+


Should we return an error code if the clock enable fails?


ret = stmmac_init_ptp(priv);
if (ret == -EOPNOTSUPP)
netdev_warn(priv->dev, "PTP not supported by HW\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 5b18355c0d2b..d285d6cfbd0d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -365,7 +365,6 @@ stmmac_probe_config_dt(struct platform_device *pdev, const 
char **mac)
plat->clk_ptp_ref = NULL;
dev_warn(>dev, "PTP uses main clock\n");
} else {
-   clk_prepare_enable(plat->clk_ptp_ref);
plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
dev_dbg(>dev, "PTP rate %d\n", plat->clk_ptp_rate);
}



It seems like there will still be a refcount mismatch for the clock if 
any of the request_irqs that are after stmmac_hw_setup in stmmac_open fail.


Cheers,
Mikko.


Re: [PATCH 5/7] net: stmmac: Program RX queue size and flow control

2017-02-27 Thread Mikko Perttunen

On 23.02.2017 19:24, Thierry Reding wrote:

From: Thierry Reding 

Program the receive queue size based on the RX FIFO size and enable
hardware flow control for large FIFOs.

Signed-off-by: Thierry Reding 
---
 drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 12 +++
 drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 43 ++--
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h 
b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index db45134fddf0..9acc1f1252b3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -180,6 +180,7 @@ enum power_event {
 #define MTL_OP_MODE_TSFBIT(1)

 #define MTL_OP_MODE_TQS_MASK   GENMASK(24, 16)
+#define MTL_OP_MODE_TQS_SHIFT  16

 #define MTL_OP_MODE_TTC_MASK   0x70
 #define MTL_OP_MODE_TTC_SHIFT  4
@@ -193,6 +194,17 @@ enum power_event {
 #define MTL_OP_MODE_TTC_384(6 << MTL_OP_MODE_TTC_SHIFT)
 #define MTL_OP_MODE_TTC_512(7 << MTL_OP_MODE_TTC_SHIFT)

+#define MTL_OP_MODE_RQS_MASK   GENMASK(29, 20)
+#define MTL_OP_MODE_RQS_SHIFT  20
+
+#define MTL_OP_MODE_RFD_MASK   GENMASK(19, 14)
+#define MTL_OP_MODE_RFD_SHIFT  14
+
+#define MTL_OP_MODE_RFA_MASK   GENMASK(13, 8)
+#define MTL_OP_MODE_RFA_SHIFT  8
+
+#define MTL_OP_MODE_EHFC   BIT(7)
+
 #define MTL_OP_MODE_RTC_MASK   0x18
 #define MTL_OP_MODE_RTC_SHIFT  3

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 8d249f3b34c8..03d230201960 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -185,8 +185,9 @@ static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 
riwt)
 }

 static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode,
-   int rxmode, u32 channel)
+   int rxmode, u32 channel, int rxfifosz)
 {
+   unsigned int rqs = rxfifosz / 256 - 1;
u32 mtl_tx_op, mtl_rx_op, mtl_rx_int;

/* Following code only done for channel 0, other channels not yet
@@ -252,6 +253,44 @@ static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, 
int txmode,
mtl_rx_op |= MTL_OP_MODE_RTC_128;
}

+   mtl_rx_op &= ~MTL_OP_MODE_RQS_MASK;
+   mtl_rx_op |= rqs << MTL_OP_MODE_RQS_SHIFT;
+
+   /* enable flow control only if each channel gets 4 KiB or more FIFO */
+   if (rxfifosz >= 4096) {
+   unsigned int rfd, rfa;
+
+   mtl_rx_op |= MTL_OP_MODE_EHFC;
+
+   switch (rxfifosz) {
+   case 4096:
+   rfd = 0x03;
+   rfa = 0x01;
+   break;
+
+   case 8192:
+   rfd = 0x06;
+   rfa = 0x0a;
+   break;
+
+   case 16384:
+   rfd = 0x06;
+   rfa = 0x12;
+   break;
+
+   default:
+   rfd = 0x06;
+   rfa = 0x1e;
+   break;
+   }


Are these values correct? In the 4096 case, rfd > rfa, in all other 
cases the other way around. In any case it would be useful to have a 
comment clarifying the thresholds in bytes.



+
+   mtl_rx_op &= ~MTL_OP_MODE_RFD_MASK;
+   mtl_rx_op |= rfd << MTL_OP_MODE_RFD_SHIFT;
+
+   mtl_rx_op &= ~MTL_OP_MODE_RFA_MASK;
+   mtl_rx_op |= rfa << MTL_OP_MODE_RFA_SHIFT;
+   }
+
writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel));

/* Enable MTL RX overflow */
@@ -264,7 +303,7 @@ static void dwmac4_dma_operation_mode(void __iomem *ioaddr, 
int txmode,
  int rxmode, int rxfifosz)
 {
/* Only Channel 0 is actually configured and used */
-   dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0);
+   dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0, rxfifosz);
 }

 static void dwmac4_get_hw_feature(void __iomem *ioaddr,



Re: [PATCH 7/7] net: stmmac: dwc-qos: Add Tegra186 support

2017-02-27 Thread Mikko Perttunen

On 23.02.2017 19:24, Thierry Reding wrote:

From: Thierry Reding 

The NVIDIA Tegra186 SoC contains an instance of the Synopsys DWC
ethernet QOS IP core. The binding that it uses is slightly different
from existing ones because of the integration (clocks, resets, ...).

Signed-off-by: Thierry Reding 
---
 .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 252 +
 1 file changed, 252 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 5071d3c15adc..54dfbdc48f6d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,10 +23,24 @@
 #include 
 #include 
 #include 
+#include 
 #include 

 #include "stmmac_platform.h"

+struct tegra_eqos {
+   struct device *dev;
+   void __iomem *regs;
+
+   struct reset_control *rst;
+   struct clk *clk_master;
+   struct clk *clk_slave;
+   struct clk *clk_tx;
+   struct clk *clk_rx;
+
+   struct gpio_desc *reset;
+};
+
 static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
   struct plat_stmmacenet_data *plat_dat)
 {
@@ -148,6 +163,237 @@ static int dwc_qos_remove(struct platform_device *pdev)
return 0;
 }

+#define SDMEMCOMPPADCTRL 0x8800
+#define  SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
+
+#define AUTO_CAL_CONFIG 0x8804
+#define  AUTO_CAL_CONFIG_START BIT(31)
+#define  AUTO_CAL_CONFIG_ENABLE BIT(29)
+
+#define AUTO_CAL_STATUS 0x880c
+#define  AUTO_CAL_STATUS_ACTIVE BIT(31)
+
+static void tegra_eqos_fix_speed(void *priv, unsigned int speed)
+{
+   struct tegra_eqos *eqos = priv;
+   unsigned long rate = 12500;
+   bool needs_calibration = false;
+   unsigned int i;
+   u32 value;
+
+   switch (speed) {
+   case SPEED_1000:
+   needs_calibration = true;
+   rate = 12500;
+   break;
+
+   case SPEED_100:
+   needs_calibration = true;
+   rate = 2500;
+   break;
+
+   case SPEED_10:
+   rate = 250;
+   break;
+
+   default:
+   dev_err(eqos->dev, "invalid speed %u\n", speed);
+   break;
+   }
+
+   if (needs_calibration) {
+   /* calibrate */
+   value = readl(eqos->regs + SDMEMCOMPPADCTRL);
+   value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
+   writel(value, eqos->regs + SDMEMCOMPPADCTRL);
+
+   udelay(1);
+
+   value = readl(eqos->regs + AUTO_CAL_CONFIG);
+   value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE;
+   writel(value, eqos->regs + AUTO_CAL_CONFIG);
+
+   for (i = 0; i <= 10; i++) {
+   value = readl(eqos->regs + AUTO_CAL_STATUS);
+   if (value & AUTO_CAL_STATUS_ACTIVE)
+   break;
+
+   udelay(1);
+   }
+
+   if ((value & AUTO_CAL_STATUS_ACTIVE) == 0) {
+   dev_err(eqos->dev, "calibration did not start\n");
+   goto failed;
+   }
+
+   for (i = 0; i <= 10; i++) {
+   value = readl(eqos->regs + AUTO_CAL_STATUS);
+   if ((value & AUTO_CAL_STATUS_ACTIVE) == 0)
+   break;
+
+   udelay(20);
+   }
+
+   if (value & AUTO_CAL_STATUS_ACTIVE) {
+   dev_err(eqos->dev, "calibration didn't finish\n");
+   goto failed;
+   }


Could use readl_poll_timeout/readl_poll_timeout_atomic for these loops 
instead.



+
+   failed:
+   value = readl(eqos->regs + SDMEMCOMPPADCTRL);
+   value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD;
+   writel(value, eqos->regs + SDMEMCOMPPADCTRL);
+   } else {
+   value = readl(eqos->regs + AUTO_CAL_CONFIG);
+   value &= ~AUTO_CAL_CONFIG_ENABLE;
+   writel(value, eqos->regs + AUTO_CAL_CONFIG);
+   }
+
+   clk_set_rate(eqos->clk_tx, rate);


Could check error code here, and for other clock ops too.


+}
+
+static int tegra_eqos_init(struct platform_device *pdev, void *priv)
+{
+   struct tegra_eqos *eqos = priv;
+   unsigned long rate;
+   u32 value;
+
+   rate = clk_get_rate(eqos->clk_slave);
+
+   value = readl(eqos->regs + 0xdc);


No point in reading the value when it is fully overwritten.


+   value = (rate / 100) - 1;
+   writel(value, eqos->regs + 0xdc);


Please add a define for 0xdc.


+
+   return 0;
+}
+
+static void *tegra_eqos_probe(struct platform_device *pdev,
+   

Re: [PATCH v2 0/7] Tegra210 clock bug fixes

2017-02-27 Thread Mikko Perttunen

Series,

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>
Tested-by: Mikko Perttunen <mperttu...@nvidia.com>

On 02/23/2017 12:44 PM, Peter De Schrijver wrote:

A number of bug fixes for the Tegra210 clock implementation.

Changelog:

v2: add better description for 'remove non-existing pll_m_out1 clock'

Peter De Schrijver (7):
  clk: tegra: fix pll_a1 iddq register, add pll_a1
  clk: tegra: fix isp clock modelling
  clk: tegra: correct afi parent
  clk: tegra: remove non-existing pll_m_out1 clock
  clk: tegra: don't warn for PLL defaults unnecessarily
  clk: tegra: correct tegra210_pll_fixed_mdiv_cfg rate calculation
  clk: tegra: fix type for m field

 drivers/clk/tegra/clk-id.h   |  1 +
 drivers/clk/tegra/clk-tegra-periph.c | 13 +---
 drivers/clk/tegra/clk-tegra210.c | 35 
 drivers/clk/tegra/clk.h  |  2 +-
 include/dt-bindings/clock/tegra210-car.h |  4 ++--
 5 files changed, 36 insertions(+), 19 deletions(-)



Re: [PATCH 2/5] clk: tegra: define Tegra210 DMIC sync clocks

2017-02-27 Thread Mikko Perttunen

On 02/23/2017 02:39 PM, Peter De Schrijver wrote:

Tegra210 has 3 DMIC inputs which can be clocked from the recovered clock
of several other audio inputs (eg. i2s0, i2s1, ...). To model this, we add
a 3 new clocks similar to the audio* clocks which handle the same function
for the i2s and spdif clocks.

Signed-off-by: Peter De Schrijver <pdeschrij...@nvidia.com>
---
 drivers/clk/tegra/clk-id.h   |  8 ++-
 drivers/clk/tegra/clk-tegra-audio.c  | 85 +++-
 drivers/clk/tegra/clk-tegra210.c |  6 +++
 include/dt-bindings/clock/tegra210-car.h |  9 +++-
 4 files changed, 82 insertions(+), 26 deletions(-)

diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index fc978b2..ab9b347 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -307,8 +307,14 @@ enum clk_id {
tegra_clk_xusb_ssp_src,
tegra_clk_sclk_mux,
tegra_clk_sor_safe,
-   tegra_clk_ispa,
tegra_clk_cec,
+   tegra_clk_ispa,
+   tegra_clk_dmic1_sync_clk,
+   tegra_clk_dmic2_sync_clk,
+   tegra_clk_dmic3_sync_clk,
+   tegra_clk_dmic1_sync_clk_mux,
+   tegra_clk_dmic2_sync_clk_mux,
+   tegra_clk_dmic3_sync_clk_mux,
tegra_clk_max,
 };

diff --git a/drivers/clk/tegra/clk-tegra-audio.c 
b/drivers/clk/tegra/clk-tegra-audio.c
index e2bfa9b..b4da6e0 100644
--- a/drivers/clk/tegra/clk-tegra-audio.c
+++ b/drivers/clk/tegra/clk-tegra-audio.c
@@ -31,6 +31,9 @@
 #define AUDIO_SYNC_CLK_I2S3 0x4ac
 #define AUDIO_SYNC_CLK_I2S4 0x4b0
 #define AUDIO_SYNC_CLK_SPDIF 0x4b4
+#define AUDIO_SYNC_CLK_DMIC1 0x560
+#define AUDIO_SYNC_CLK_DMIC2 0x564
+#define AUDIO_SYNC_CLK_DMIC3 0x6b8

 #define AUDIO_SYNC_DOUBLER 0x49c

@@ -91,8 +94,14 @@ struct tegra_audio2x_clk_initdata {

 static DEFINE_SPINLOCK(clk_doubler_lock);

-static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
-   "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+static const char * const mux_audio_sync_clk[] = { "spdif_in_sync",
+   "i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync",
+   "pll_a_out0", "vimclk_sync",
+};
+
+static const char * const mux_dmic_sync_clk[] = { "unused", "i2s0_sync",
+   "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "pll_a_out0",
+   "vimclk_sync",
 };


My GCC spews a bunch of warnings because these are "const char * const" 
and are passed to tegra_audio_sync_clk_init which takes "const char **". 
Similarly for mux_dmic[123] which end up in a struct 
tegra_periph_init_data which also has a "const char **" field; and 
finally aclk_parents has the same issue.


Apart from that, the series:

Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>
Tested-by: Mikko Perttunen <mperttu...@nvidia.com>
(booted and verified clocks show up)



 static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
@@ -114,6 +123,12 @@ struct tegra_audio2x_clk_initdata {
AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
 };

+static struct tegra_audio_clk_initdata dmic_clks[] = {
+   AUDIO(dmic1_sync_clk, AUDIO_SYNC_CLK_DMIC1),
+   AUDIO(dmic2_sync_clk, AUDIO_SYNC_CLK_DMIC2),
+   AUDIO(dmic3_sync_clk, AUDIO_SYNC_CLK_DMIC3),
+};
+
 static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
AUDIO2X(audio0, 113, 24),
AUDIO2X(audio1, 114, 25),
@@ -123,6 +138,41 @@ struct tegra_audio2x_clk_initdata {
AUDIO2X(spdif, 118, 29),
 };

+static void __init tegra_audio_sync_clk_init(void __iomem *clk_base,
+ struct tegra_clk *tegra_clks,
+ struct tegra_audio_clk_initdata *sync,
+ int num_sync_clks,
+ const char **mux_names,
+ int num_mux_inputs)
+{
+   struct clk *clk;
+   struct clk **dt_clk;
+   struct tegra_audio_clk_initdata *data;
+   int i;
+
+   for (i = 0, data = sync; i < num_sync_clks; i++, data++) {
+   dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
+   if (!dt_clk)
+   continue;
+
+   clk = clk_register_mux(NULL, data->mux_name, mux_names,
+   num_mux_inputs,
+   CLK_SET_RATE_NO_REPARENT,
+   clk_base + data->offset, 0, 3, 0,
+   NULL);
+   *dt_clk = clk;
+
+   dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
+   if (!dt_clk)
+   continue;
+
+   clk = clk_regis

Re: [PATCH 4/7] net: stmmac: Parse FIFO sizes from feature registers

2017-02-27 Thread Mikko Perttunen

On 23.02.2017 19:24, Thierry Reding wrote:

From: Thierry Reding <tred...@nvidia.com>

New version of this core encode the FIFO sizes in one of the feature
registers. Use these sizes as default, but still allow device tree to
override them for backwards compatibility.

Signed-off-by: Thierry Reding <tred...@nvidia.com>
---
 drivers/net/ethernet/stmicro/stmmac/common.h  | 3 +++
 drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c  | 2 ++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h 
b/drivers/net/ethernet/stmicro/stmmac/common.h
index 144fe84e8a53..6ac653845d82 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -324,6 +324,9 @@ struct dma_features {
unsigned int number_tx_queues;
/* Alternate (enhanced) DESC mode */
unsigned int enh_desc;
+   /* TX and RX FIFO sizes */
+   unsigned int tx_fifo_size;
+   unsigned int rx_fifo_size;
 };

 /* GMAC TX FIFO is 8K, Rx FIFO is 16K */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 377d1b44d4f2..8d249f3b34c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -296,6 +296,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
+   dma_cap->tx_fifo_size = 128 << ((hw_cap >> 6) & 0x1f);
+   dma_cap->rx_fifo_size = 128 << ((hw_cap >> 0) & 0x1f);
/* MAC HW feature2 */
hw_cap = readl(ioaddr + GMAC_HW_FEATURE2);
/* TX and RX number of channels */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d7387919bdb6..291e34f0ca94 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1281,6 +1281,9 @@ static void stmmac_dma_operation_mode(struct stmmac_priv 
*priv)
 {
int rxfifosz = priv->plat->rx_fifo_size;

+   if (rxfifosz == 0)
+   rxfifosz = priv->dma_cap.rx_fifo_size;
+
if (priv->plat->force_thresh_dma_mode)
priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz);
else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {



Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>


Re: [PATCH 3/7] net: stmmac: Check for DMA mapping errors

2017-02-27 Thread Mikko Perttunen

On 23.02.2017 19:24, Thierry Reding wrote:

From: Thierry Reding 

When DMA mapping an SKB fragment, the mapping must be checked for
errors, otherwise the DMA debug code will complain upon unmap.

Signed-off-by: Thierry Reding 
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6b7a5ce19589..d7387919bdb6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2072,6 +2072,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, 
struct net_device *dev)
des = skb_frag_dma_map(priv->device, frag, 0,
   skb_frag_size(frag),
   DMA_TO_DEVICE);
+   if (dma_mapping_error(priv->device, des))
+   goto dma_map_err;


If this map fails, we should also unmap the previously mapped fragments 
and the separate mapping made using dma_map_single.




stmmac_tso_allocator(priv, des, skb_frag_size(frag),
 (i == nfrags - 1));



Re: linux-next: build failure after merge of the tip tree

2017-04-05 Thread Mikko Perttunen

On 05.04.2017 06:36, Stephen Rothwell wrote:

Hi all,

After merging the tip tree, today's linux-next build (arm
multi_v7_defconfig) failed like this:

drivers/gpu/built-in.o:(__tracepoints+0x64): multiple definition of 
`__tracepoint_remove_device_from_group'
drivers/iommu/built-in.o:(__tracepoints+0x64): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x3c): multiple definition of 
`__tracepoint_detach_device_from_domain'
drivers/iommu/built-in.o:(__tracepoints+0x3c): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x0): multiple definition of 
`__tracepoint_io_page_fault'
drivers/iommu/built-in.o:(__tracepoints+0x0): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x78): multiple definition of 
`__tracepoint_add_device_to_group'
drivers/iommu/built-in.o:(__tracepoints+0x78): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x14): multiple definition of 
`__tracepoint_unmap'
drivers/iommu/built-in.o:(__tracepoints+0x14): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x28): multiple definition of 
`__tracepoint_map'
drivers/iommu/built-in.o:(__tracepoints+0x28): first defined here
drivers/gpu/built-in.o:(__tracepoints+0x50): multiple definition of 
`__tracepoint_attach_device_to_domain'
drivers/iommu/built-in.o:(__tracepoints+0x50): first defined here

The tip tree has not changed since yesterday.  However, reverting
the drm-tegra tree fixes the build problem.  So there is some interaction
between the tip tree and today's drm-tegra tree.

So for now, I have reverted the merge of the drm-tegra tree.



Looks like this is caused by my patch to add IOMMU support to Host1x. 
I'm confused by how it doesn't appear on ARMv8, though. The cause is 
that host1x/dev.c defines CREATE_TRACE_POINTS and includes 
trace/events/host1x.h, which is fine. However, it then also includes, 
among other local files, dev.h. This used to be fine, but my patch adds 
an include of linux/iommu.h to dev.h, so we get this failure. I'll post 
a fix shortly.


Thanks,
Mikko.


[PATCH] fixup! gpu: host1x: Add IOMMU support

2017-04-05 Thread Mikko Perttunen
Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/gpu/host1x/dev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index f8fda446a6a6..f05ebb14fa63 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -27,6 +27,7 @@
 
 #define CREATE_TRACE_POINTS
 #include 
+#undef CREATE_TRACE_POINTS
 
 #include "bus.h"
 #include "channel.h"
-- 
2.11.1



[PATCH 1/3] cpufreq: Add Tegra186 cpufreq driver

2017-04-03 Thread Mikko Perttunen
Add a new cpufreq driver for Tegra186 (and likely later).
The CPUs are organized into two clusters, Denver and A57,
with two and four cores respectively. CPU frequency can be
adjusted by writing the desired rate divisor and a voltage
hint to a special per-core register.

The frequency of each core can be set individually; however,
this is just a hint as all CPUs in a cluster will run at
the maximum rate of non-idle CPUs in the cluster.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/cpufreq/Kconfig.arm|   7 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra186-cpufreq.c | 277 +
 3 files changed, 285 insertions(+)
 create mode 100644 drivers/cpufreq/tegra186-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 74fa5c5904d3..168d36fa4a58 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -247,6 +247,13 @@ config ARM_TEGRA124_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra124 SOCs.
 
+config ARM_TEGRA186_CPUFREQ
+   tristate "Tegra186 CPUFreq support"
+   depends on ARCH_TEGRA && TEGRA_BPMP
+   default y
+   help
+ This adds the CPUFreq driver support for Tegra186 SOCs.
+
 config ARM_TI_CPUFREQ
bool "Texas Instruments CPUFreq support"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9f5a8045f36d..b7e78f063c4f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)   += 
spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)  += sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
 obj-$(CONFIG_ARM_TI_CPUFREQ)   += ti-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
diff --git a/drivers/cpufreq/tegra186-cpufreq.c 
b/drivers/cpufreq/tegra186-cpufreq.c
new file mode 100644
index ..794c1f2d8231
--- /dev/null
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define EDVD_CORE_VOLT_FREQ(core)  (0x20 + (core) * 0x4)
+#define EDVD_CORE_VOLT_FREQ_F_SHIFT0
+#define EDVD_CORE_VOLT_FREQ_F_MASK 0xff
+#define EDVD_CORE_VOLT_FREQ_V_SHIFT16
+#define EDVD_CORE_VOLT_FREQ_V_MASK 0xff
+
+#define CLUSTER_DENVER 0
+#define CLUSTER_A571
+#define NUM_CLUSTERS   2
+
+struct tegra186_cpufreq_cluster {
+   const char *name;
+   unsigned int num_cores;
+};
+
+static const struct tegra186_cpufreq_cluster CLUSTERS[] = {
+   {
+   .name = "denver",
+   .num_cores = 2,
+   },
+   {
+   .name = "a57",
+   .num_cores = 4,
+   }
+};
+
+struct tegra186_cpufreq_data {
+   void __iomem *regs[NUM_CLUSTERS];
+   struct cpufreq_frequency_table *tables[NUM_CLUSTERS];
+};
+
+static void get_cluster_core(int cpu, int *cluster, int *core)
+{
+   switch (cpu) {
+   case 0:
+   *cluster = CLUSTER_A57; *core = 0; break;
+   case 3:
+   *cluster = CLUSTER_A57; *core = 1; break;
+   case 4:
+   *cluster = CLUSTER_A57; *core = 2; break;
+   case 5:
+   *cluster = CLUSTER_A57; *core = 3; break;
+   case 1:
+   *cluster = CLUSTER_DENVER; *core = 0; break;
+   case 2:
+   *cluster = CLUSTER_DENVER; *core = 1; break;
+   }
+}
+
+static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
+{
+   struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
+   struct cpufreq_frequency_table *table;
+   int cluster, core;
+
+   get_cluster_core(policy->cpu, , );
+
+   table = data->tables[cluster];
+   cpufreq_table_validate_and_show(policy, table);
+
+   policy->cpuinfo.transition_latency = 300 * 1000;
+
+   return 0;
+}
+
+static void write_volt_freq(uint8_t vidx, uint8_t ndiv, void __iomem *regs,
+   unsigned int core)
+{
+   u3

[PATCH 2/3] dt-bindings: Add bindings for nvidia,tegra186-ccplex-cluster

2017-04-03 Thread Mikko Perttunen
The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 .../arm/tegra/nvidia,tegra186-ccplex-cluster.txt   | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
new file mode 100644
index ..50cd615219e9
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
@@ -0,0 +1,22 @@
+NVIDIA Tegra CCPLEX_CLUSTER area
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-ccplex-cluster": for Tegra186
+- reg: Must contain an (offset, length) pair of the register set for each
+  entry in reg-names.
+- reg-names: Must include the following entries:
+  - "a57": Public aperture for A57 CPU cluster
+  - "denver": Public aperture for Denver CPU cluster
+- nvidia,bpmp: Phandle to BPMP device that can be queried for OPP tables
+
+Example:
+
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e06 0x0 0x1000>,
+ <0x0 0x0e07 0x0 0x1000>;
+   reg-names = "a57", "denver";
+
+   nvidia,bpmp = <>;
+   };
-- 
2.1.4



[PATCH 3/3] arm64: tegra: Add CCPLEX_CLUSTER area in Tegra186

2017-04-03 Thread Mikko Perttunen
The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 9 +
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 3ea5e6369bc3..765b840933ac 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -347,6 +347,15 @@
reg-names = "pmc", "wake", "aotag", "scratch";
};
 
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e06 0x0 0x1000>,
+ <0x0 0x0e07 0x0 0x1000>;
+   reg-names = "a57", "denver";
+
+   nvidia,bpmp = <>;
+   };
+
sysram@3000 {
compatible = "nvidia,tegra186-sysram", "mmio-sram";
reg = <0x0 0x3000 0x0 0x5>;
-- 
2.1.4



Re: [PATCH 2/3] dt-bindings: Add bindings for nvidia,tegra186-ccplex-cluster

2017-04-03 Thread Mikko Perttunen



On 04/03/2017 05:24 PM, Jon Hunter wrote:


On 03/04/17 13:42, Mikko Perttunen wrote:

The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 .../arm/tegra/nvidia,tegra186-ccplex-cluster.txt   | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
new file mode 100644
index ..50cd615219e9
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
@@ -0,0 +1,22 @@
+NVIDIA Tegra CCPLEX_CLUSTER area
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-ccplex-cluster": for Tegra186


Nit pick ... any reason why we append 'cluster' here? The TRM just says
the "CPU Complex" consists of two CPU clusters. So
"nvidia,tegra186-cpu-complex" or "nvidia,tegra186-ccplex" seems fine.

BTW, I do see references in the TRM to CCPLEX_CLUSTER0/1, but never
CCPLEX_CLUSTER in reference to both. I think it is just CCPLEX AFAICT.


The reason was that the MMIO aperture is called "CCPLEX_CLUSTER" in the 
address map. But I agree it's not a very descriptive name.




Cheers
Jon



Re: [PATCH 2/3] dt-bindings: Add bindings for nvidia,tegra186-ccplex-cluster

2017-04-03 Thread Mikko Perttunen

On 04/03/2017 05:06 PM, Thierry Reding wrote:

On Mon, Apr 03, 2017 at 03:42:24PM +0300, Mikko Perttunen wrote:

The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 .../arm/tegra/nvidia,tegra186-ccplex-cluster.txt   | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
new file mode 100644
index ..50cd615219e9
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
@@ -0,0 +1,22 @@
+NVIDIA Tegra CCPLEX_CLUSTER area
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-ccplex-cluster": for Tegra186
+- reg: Must contain an (offset, length) pair of the register set for each
+  entry in reg-names.
+- reg-names: Must include the following entries:
+  - "a57": Public aperture for A57 CPU cluster
+  - "denver": Public aperture for Denver CPU cluster
+- nvidia,bpmp: Phandle to BPMP device that can be queried for OPP tables


"phandle"


Will fix.




+Example:
+
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e06 0x0 0x1000>,
+ <0x0 0x0e07 0x0 0x1000>;
+   reg-names = "a57", "denver";
+
+   nvidia,bpmp = <>;
+   };


Where's the information about the register offsets coming from? The TRM
says that CCPLEX_CLUSTER has a single aperture from 0x0e00 to
0x0e3f.


Some internal document with a name related to Denver power management, 
IIRC. I'll link it to you tomorrow.




Thierry



Re: [PATCH 1/3] cpufreq: Add Tegra186 cpufreq driver

2017-04-03 Thread Mikko Perttunen

On 04/03/2017 05:47 PM, Thierry Reding wrote:

On Mon, Apr 03, 2017 at 03:42:23PM +0300, Mikko Perttunen wrote:

Add a new cpufreq driver for Tegra186 (and likely later).
The CPUs are organized into two clusters, Denver and A57,
with two and four cores respectively. CPU frequency can be
adjusted by writing the desired rate divisor and a voltage
hint to a special per-core register.

The frequency of each core can be set individually; however,
this is just a hint as all CPUs in a cluster will run at
the maximum rate of non-idle CPUs in the cluster.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/cpufreq/Kconfig.arm|   7 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra186-cpufreq.c | 277 +
 3 files changed, 285 insertions(+)
 create mode 100644 drivers/cpufreq/tegra186-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 74fa5c5904d3..168d36fa4a58 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -247,6 +247,13 @@ config ARM_TEGRA124_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra124 SOCs.

+config ARM_TEGRA186_CPUFREQ
+   tristate "Tegra186 CPUFreq support"
+   depends on ARCH_TEGRA && TEGRA_BPMP
+   default y


I'd rather not default this to "y". We can use the defconfig to enable
this.


Sure.




+   help
+ This adds the CPUFreq driver support for Tegra186 SOCs.
+
 config ARM_TI_CPUFREQ
bool "Texas Instruments CPUFreq support"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9f5a8045f36d..b7e78f063c4f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)   += 
spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)  += sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
 obj-$(CONFIG_ARM_TI_CPUFREQ)   += ti-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
diff --git a/drivers/cpufreq/tegra186-cpufreq.c 
b/drivers/cpufreq/tegra186-cpufreq.c
new file mode 100644
index ..794c1f2d8231
--- /dev/null
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define EDVD_CORE_VOLT_FREQ(core)  (0x20 + (core) * 0x4)
+#define EDVD_CORE_VOLT_FREQ_F_SHIFT0
+#define EDVD_CORE_VOLT_FREQ_F_MASK 0xff
+#define EDVD_CORE_VOLT_FREQ_V_SHIFT16
+#define EDVD_CORE_VOLT_FREQ_V_MASK 0xff
+
+#define CLUSTER_DENVER 0
+#define CLUSTER_A571
+#define NUM_CLUSTERS   2
+
+struct tegra186_cpufreq_cluster {
+   const char *name;
+   unsigned int num_cores;
+};
+
+static const struct tegra186_cpufreq_cluster CLUSTERS[] = {


We don't usually use uppercase letters for variable names.


You're right. Looks like I've misapplied some style rules from other 
projects :e





+   {
+   .name = "denver",
+   .num_cores = 2,
+   },
+   {
+   .name = "a57",
+   .num_cores = 4,
+   }
+};
+
+struct tegra186_cpufreq_data {
+   void __iomem *regs[NUM_CLUSTERS];
+   struct cpufreq_frequency_table *tables[NUM_CLUSTERS];
+};


Given my comments regarding the aperture, perhaps it would be useful to
only have a single range of memory-mapped registers and add an offset to
struct tegra186_cpufreq_cluster that points into that region?


Yes, that might be cleaner. Would slightly simplify the probe code as well.



Also, you're somewhat mixing arrays of NUM_CLUSTERS elements and
dynamically sized ones (CLUSTERS[]). Probably best to just stick to one
of them.

Might be worth considering to dynamically allocate based on the cluster
table, but that could be done in a separate patch if we ever get a
configuration where NUM_CLUSTERS != 2.


I think we will have that eventually, so I'll do this for v2.




+static void get_cluster_core(int cpu, int *cluster, int *core)


These can all be u

[PATCH v2 2/3] dt-bindings: Add bindings for nvidia,tegra186-ccplex-cluster

2017-04-04 Thread Mikko Perttunen
The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2:
- Only one regs entry.
- s/Phandle/phandle/

 .../arm/tegra/nvidia,tegra186-ccplex-cluster.txt| 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
new file mode 100644
index ..e8fb416c892b
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
@@ -0,0 +1,17 @@
+NVIDIA Tegra CCPLEX_CLUSTER area
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-ccplex-cluster": for Tegra186
+- reg: Must contain an (offset, length) pair of the device's MMIO
+  register area
+- nvidia,bpmp: phandle to BPMP device that can be queried for OPP tables
+
+Example:
+
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e00 0x0 0x3f>,
+
+   nvidia,bpmp = <>;
+   };
-- 
2.1.4



[PATCH v2 3/3] arm64: tegra: Add CCPLEX_CLUSTER area in Tegra186

2017-04-04 Thread Mikko Perttunen
The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2:
- Only one regs entry

 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 3ea5e6369bc3..c023af0be43d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -347,6 +347,13 @@
reg-names = "pmc", "wake", "aotag", "scratch";
};
 
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e00 0x0 0x3f>;
+
+   nvidia,bpmp = <>;
+   };
+
sysram@3000 {
compatible = "nvidia,tegra186-sysram", "mmio-sram";
reg = <0x0 0x3000 0x0 0x5>;
-- 
2.1.4



[PATCH v2 1/3] cpufreq: Add Tegra186 cpufreq driver

2017-04-04 Thread Mikko Perttunen
Add a new cpufreq driver for Tegra186 (and likely later).
The CPUs are organized into two clusters, Denver and A57,
with two and four cores respectively. CPU frequency can be
adjusted by writing the desired rate divisor and a voltage
hint to a special per-core register.

The frequency of each core can be set individually; however,
this is just a hint as all CPUs in a cluster will run at
the maximum rate of non-idle CPUs in the cluster.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2:
- Many cosmetic / restructuring changes
- Only one aperture read from DT now, with a new
  structure containing the offset among other details
  per cluster.
- Don't enable the driver by default.

 drivers/cpufreq/Kconfig.arm|   6 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra186-cpufreq.c | 275 +
 3 files changed, 282 insertions(+)
 create mode 100644 drivers/cpufreq/tegra186-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 74fa5c5904d3..74ed7e9a7f27 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -247,6 +247,12 @@ config ARM_TEGRA124_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra124 SOCs.
 
+config ARM_TEGRA186_CPUFREQ
+   tristate "Tegra186 CPUFreq support"
+   depends on ARCH_TEGRA && TEGRA_BPMP
+   help
+ This adds the CPUFreq driver support for Tegra186 SOCs.
+
 config ARM_TI_CPUFREQ
bool "Texas Instruments CPUFreq support"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9f5a8045f36d..b7e78f063c4f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)   += 
spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)  += sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
 obj-$(CONFIG_ARM_TI_CPUFREQ)   += ti-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
diff --git a/drivers/cpufreq/tegra186-cpufreq.c 
b/drivers/cpufreq/tegra186-cpufreq.c
new file mode 100644
index ..3c49591fa0ff
--- /dev/null
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define EDVD_CORE_VOLT_FREQ(core)  (0x20 + (core) * 0x4)
+#define EDVD_CORE_VOLT_FREQ_F_SHIFT0
+#define EDVD_CORE_VOLT_FREQ_V_SHIFT16
+
+struct tegra186_cpufreq_cluster_info {
+   unsigned long offset;
+   int cpus[4];
+   unsigned int bpmp_cluster_id;
+};
+
+#define NO_CPU -1
+static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = {
+   /* Denver cluster */
+   {
+   .offset = SZ_64K * 7,
+   .cpus = { 1, 2, NO_CPU, NO_CPU },
+   .bpmp_cluster_id = 0,
+   },
+   /* A57 cluster */
+   {
+   .offset = SZ_64K * 6,
+   .cpus = { 0, 3, 4, 5 },
+   .bpmp_cluster_id = 1,
+   },
+};
+
+struct tegra186_cpufreq_cluster {
+   const struct tegra186_cpufreq_cluster_info *info;
+   struct cpufreq_frequency_table *table;
+};
+
+struct tegra186_cpufreq_data {
+   void __iomem *regs;
+
+   size_t num_clusters;
+   struct tegra186_cpufreq_cluster *clusters;
+};
+
+static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
+{
+   struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
+   unsigned int i;
+
+   for (i = 0; i < data->num_clusters; i++) {
+   struct tegra186_cpufreq_cluster *cluster = >clusters[i];
+   const struct tegra186_cpufreq_cluster_info *info =
+   cluster->info;
+   int core;
+
+   for (core = 0; core < ARRAY_SIZE(info->cpus); core++) {
+   if (info->cpus[core] == policy->cpu)
+   break;
+   }
+   if (core == ARRAY_SIZE(info->cpus))
+   continue;
+
+   policy->driver_data =
+   data->regs + info->offset + EDVD_CORE_VOLT_FREQ(

[PATCH] irqchip/gic: Don't write to GICD_ICFGR0

2017-04-06 Thread Mikko Perttunen
From: Matt Craighead <mcraigh...@nvidia.com>

According to the GICv2 specification, the GICD_ICFGR0,
or GIC_DIST_CONFIG[0] register is read-only. Therefore
avoid writing to it.

Signed-off-by: Matt Craighead <mcraigh...@nvidia.com>
[mperttu...@nvidia.com: commit message rewritten]
Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/irqchip/irq-gic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 1b1df4f770bd..d9c050e0 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -609,7 +609,7 @@ void gic_dist_restore(struct gic_chip_data *gic)
 
writel_relaxed(GICD_DISABLE, dist_base + GIC_DIST_CTRL);
 
-   for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+   for (i = 1; i < DIV_ROUND_UP(gic_irqs, 16); i++)
writel_relaxed(gic->saved_spi_conf[i],
dist_base + GIC_DIST_CONFIG + i * 4);
 
@@ -699,7 +699,7 @@ void gic_cpu_restore(struct gic_chip_data *gic)
}
 
ptr = raw_cpu_ptr(gic->saved_ppi_conf);
-   for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+   for (i = 1; i < DIV_ROUND_UP(32, 16); i++)
writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
 
for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
-- 
2.1.4



Re: [PATCH] irqchip/gic: Don't write to GICD_ICFGR0

2017-04-10 Thread Mikko Perttunen

On 07.04.2017 10:32, Marc Zyngier wrote:

On 07/04/17 07:49, Mikko Perttunen wrote:

On 06.04.2017 12:26, Marc Zyngier wrote:

On 06/04/17 09:17, Mikko Perttunen wrote:

From: Matt Craighead <mcraigh...@nvidia.com>

According to the GICv2 specification, the GICD_ICFGR0,
or GIC_DIST_CONFIG[0] register is read-only. Therefore
avoid writing to it.


Have you verified that this also applies to pre-v2 GICs?


I had not, but I just looked up the GICv1 specification and this also
applies to GICv1.





Signed-off-by: Matt Craighead <mcraigh...@nvidia.com>
[mperttu...@nvidia.com: commit message rewritten]
Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
 drivers/irqchip/irq-gic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 1b1df4f770bd..d9c050e0 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -609,7 +609,7 @@ void gic_dist_restore(struct gic_chip_data *gic)

writel_relaxed(GICD_DISABLE, dist_base + GIC_DIST_CTRL);

-   for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
+   for (i = 1; i < DIV_ROUND_UP(gic_irqs, 16); i++)
writel_relaxed(gic->saved_spi_conf[i],
dist_base + GIC_DIST_CONFIG + i * 4);

@@ -699,7 +699,7 @@ void gic_cpu_restore(struct gic_chip_data *gic)
}

ptr = raw_cpu_ptr(gic->saved_ppi_conf);
-   for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
+   for (i = 1; i < DIV_ROUND_UP(32, 16); i++)
writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);


Assuming that the above stands for all GICs, it feels like there is room
for simplification here. But you haven't dealt with the save side, so
what's the point?



Yes, with this we could also drop saving the value when saving, and
that's probably worth doing. We could also just shift the indexing to be
one higher always.


Also, you're missing out some other stuff which is (by definition) RO as
well, such as the target registers for SGIs and PPIs. Finally, there is
the question of the allocated memory for these registers.


At least for the target register, the driver already seems to have code
to skip the fields defined as read-only. I havent looked for other
read-only registers, but this is the only registers we are having issues
with (see below).



Overall, I'm not sure what this patch is trying to achieve. It doesn't
fix a bug, and is not complete enough to do something useful (even
though it would only be saving a handful of bytes).

Maybe you can explain what you're trying to do here?


Sure. Our simulation environment enforces the read-only-ness of these
registers, so the driver as is doesn't work in simulation. As far as I
understand, the register being read-only means that the model is allowed
to do this.


I'm not sure this is a valid model for a GICv2. Some other parts of the
documentation hint at registers being RO/WI, but more crucially, there
is the case of GICD_ICFGR1. It is implementation defined whether it is
RO or not, and SW has no way to find out other than writing to it. What
would you do in this case? My position is that GICD_GICR0 should have a
similar behaviour.

Thoughts?


We could add some device data that specifies this, but that that would 
be serious overkill just to support a simulation implementation. I do 
think we could still make the change for ICFGR0, as that is guaranteed 
to be read-only and the patch is very small and correct regardless of 
the interpretation of 'read-only'. However, I do see your point of 
keeping it uniform. Of course, it's your decision :)




M.



Thanks,
Mikko


[PATCH v3 1/3] cpufreq: Add Tegra186 cpufreq driver

2017-04-11 Thread Mikko Perttunen
Add a new cpufreq driver for Tegra186 (and likely later).
The CPUs are organized into two clusters, Denver and A57,
with two and four cores respectively. CPU frequency can be
adjusted by writing the desired rate divisor and a voltage
hint to a special per-core register.

The frequency of each core can be set individually; however,
this is just a hint as all CPUs in a cluster will run at
the maximum rate of non-idle CPUs in the cluster.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
Acked-by: Viresh Kumar <viresh.ku...@linaro.org>
---
v3:
- Fixed size parameter of dma_free_coherent

 drivers/cpufreq/Kconfig.arm|   6 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra186-cpufreq.c | 275 +
 3 files changed, 282 insertions(+)
 create mode 100644 drivers/cpufreq/tegra186-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 74fa5c5904d3..74ed7e9a7f27 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -247,6 +247,12 @@ config ARM_TEGRA124_CPUFREQ
help
  This adds the CPUFreq driver support for Tegra124 SOCs.
 
+config ARM_TEGRA186_CPUFREQ
+   tristate "Tegra186 CPUFreq support"
+   depends on ARCH_TEGRA && TEGRA_BPMP
+   help
+ This adds the CPUFreq driver support for Tegra186 SOCs.
+
 config ARM_TI_CPUFREQ
bool "Texas Instruments CPUFreq support"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9f5a8045f36d..b7e78f063c4f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)   += 
spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)  += sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)  += tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
 obj-$(CONFIG_ARM_TI_CPUFREQ)   += ti-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
diff --git a/drivers/cpufreq/tegra186-cpufreq.c 
b/drivers/cpufreq/tegra186-cpufreq.c
new file mode 100644
index ..fe7875311d62
--- /dev/null
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#define EDVD_CORE_VOLT_FREQ(core)  (0x20 + (core) * 0x4)
+#define EDVD_CORE_VOLT_FREQ_F_SHIFT0
+#define EDVD_CORE_VOLT_FREQ_V_SHIFT16
+
+struct tegra186_cpufreq_cluster_info {
+   unsigned long offset;
+   int cpus[4];
+   unsigned int bpmp_cluster_id;
+};
+
+#define NO_CPU -1
+static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = {
+   /* Denver cluster */
+   {
+   .offset = SZ_64K * 7,
+   .cpus = { 1, 2, NO_CPU, NO_CPU },
+   .bpmp_cluster_id = 0,
+   },
+   /* A57 cluster */
+   {
+   .offset = SZ_64K * 6,
+   .cpus = { 0, 3, 4, 5 },
+   .bpmp_cluster_id = 1,
+   },
+};
+
+struct tegra186_cpufreq_cluster {
+   const struct tegra186_cpufreq_cluster_info *info;
+   struct cpufreq_frequency_table *table;
+};
+
+struct tegra186_cpufreq_data {
+   void __iomem *regs;
+
+   size_t num_clusters;
+   struct tegra186_cpufreq_cluster *clusters;
+};
+
+static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
+{
+   struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
+   unsigned int i;
+
+   for (i = 0; i < data->num_clusters; i++) {
+   struct tegra186_cpufreq_cluster *cluster = >clusters[i];
+   const struct tegra186_cpufreq_cluster_info *info =
+   cluster->info;
+   int core;
+
+   for (core = 0; core < ARRAY_SIZE(info->cpus); core++) {
+   if (info->cpus[core] == policy->cpu)
+   break;
+   }
+   if (core == ARRAY_SIZE(info->cpus))
+   continue;
+
+   policy->driver_data =
+   data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core);
+   cpufreq_table_validate_and_show(policy, cluster->table);
+   

Re: [PATCH v2 1/3] cpufreq: Add Tegra186 cpufreq driver

2017-04-11 Thread Mikko Perttunen

On 04/11/2017 09:35 AM, Viresh Kumar wrote:

On 04-04-17, 16:43, Mikko Perttunen wrote:

Add a new cpufreq driver for Tegra186 (and likely later).
The CPUs are organized into two clusters, Denver and A57,
with two and four cores respectively. CPU frequency can be
adjusted by writing the desired rate divisor and a voltage
hint to a special per-core register.

The frequency of each core can be set individually; however,
this is just a hint as all CPUs in a cluster will run at
the maximum rate of non-idle CPUs in the cluster.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2:
- Many cosmetic / restructuring changes
- Only one aperture read from DT now, with a new
  structure containing the offset among other details
  per cluster.
- Don't enable the driver by default.

 drivers/cpufreq/Kconfig.arm|   6 +
 drivers/cpufreq/Makefile   |   1 +
 drivers/cpufreq/tegra186-cpufreq.c | 275 +
 3 files changed, 282 insertions(+)
 create mode 100644 drivers/cpufreq/tegra186-cpufreq.c


For all three patches.

Acked-by: Viresh Kumar <viresh.ku...@linaro.org>



Thanks!

Mikko


Re: [PATCH] gpu: host1x: Fix error handling

2017-04-11 Thread Mikko Perttunen

On 10.04.2017 23:29, Christophe JAILLET wrote:

If 'devm_reset_control_get' returns an error, then we erroneously return
success because error code is taken from 'host->clk' instead of
'host->rst'.

Fixes: b386c6b73ac6 ("gpu: host1x: Support module reset")

Signed-off-by: Christophe JAILLET <christophe.jail...@wanadoo.fr>
---
 drivers/gpu/host1x/dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index f05ebb14fa63..ac65f52850a6 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -172,7 +172,7 @@ static int host1x_probe(struct platform_device *pdev)

host->rst = devm_reset_control_get(>dev, "host1x");
if (IS_ERR(host->rst)) {
-   err = PTR_ERR(host->clk);
+   err = PTR_ERR(host->rst);
dev_err(>dev, "failed to get reset: %d\n", err);
    return err;
}



Reviewed-by: Mikko Perttunen <mperttu...@nvidia.com>


Re: [PATCH] [RFC] gpu: host1x: shut up warning about DMA API misuse

2017-04-20 Thread Mikko Perttunen

On 20.04.2017 11:25, Arnd Bergmann wrote:

On Thu, Apr 20, 2017 at 9:02 AM, Mikko Perttunen <cyn...@kapsi.fi> wrote:

On 19.04.2017 21:24, Arnd Bergmann wrote:


When dma_addr_t and phys_addr_t are not the same size, we get a warning
from the dma_alloc_wc function:

drivers/gpu/host1x/cdma.c: In function 'host1x_pushbuffer_init':
drivers/gpu/host1x/cdma.c:94:48: error: passing argument 3 of
'dma_alloc_wc' from incompatible pointer type
[-Werror=incompatible-pointer-types]
   pb->mapped = dma_alloc_wc(host1x->dev, size, >phys,
^
In file included from drivers/gpu/host1x/cdma.c:22:0:
include/linux/dma-mapping.h:761:37: note: expected 'dma_addr_t * {aka long
long unsigned int *}' but argument is of type 'phys_addr_t * {aka unsigned
int *}'
 static noinline_if_stackbloat void *dma_alloc_wc(struct device *dev,
size_t size,
 ^~~~
drivers/gpu/host1x/cdma.c:113:48: error: passing argument 3 of
'dma_alloc_wc' from incompatible pointer type
[-Werror=incompatible-pointer-types]
   pb->mapped = dma_alloc_wc(host1x->dev, size, >phys,
^
In file included from drivers/gpu/host1x/cdma.c:22:0:
include/linux/dma-mapping.h:761:37: note: expected 'dma_addr_t * {aka long
long unsigned int *}' but argument is of type 'phys_addr_t * {aka unsigned
int *}'
 static noinline_if_stackbloat void *dma_alloc_wc(struct device *dev,
size_t size,
 ^~~~

The problem here is that dma_alloc_wc() returns a pointer to a dma_addr_t
that may already be translated by an IOMMU, but the driver passes this
into iommu_map() as a physical address. This works by accident only when
the IOMMU does not get registered with the DMA API and there is a 1:1
mapping between physical addresses as seen by the CPU and the device.

The fundamental problem here is the lack of a generic API to do what the
driver wants: allocating CPU-visible memory for use by a device through
user-defined IOMMU settings. Neither the dma-mapping API nor the IOMMU
API can do this by itself, and combining the two is not well-defined.

This patch addresses the type mismatch by adding a third pointer into the
push_buffer structure: in addition to the address as seen from the CPU
and the address inside of the local IOMMU domain, the pb->alloc pointer
is the token returned by dma_alloc_wc(), and this is what we later need
to pass into dma_free_wc().

The address we pass into iommu_map() however is the physical address
computed from virt_to_phys(), assuming that the pointer we have here
is part of the linear mapping (which is also questionable, e.g. when we
have a non-coherent device on ARM32 this may be false). Also, when
the DMA API uses the IOMMU to allocate the pointer for the default
domain, we end up with two IOMMU mappings for the same physical address.



I think we have a "policy" on Tegra that the DMA API will never allocate
using the IOMMU (Thierry can elaborate on this), which is why I wrote the
code with that assumption. Essentially, we have made the DMA API into the
API that allocates CPU-visible memory.


I don't think this can be a per-platform policy.


Yeah, now that we are using the ARM SMMU on T186 onwards it's more 
difficult than when we were using the Tegra SMMU, so we'll probably have 
to change that.


The goal of the current code is to allocate memory from the CMA, so one 
option would be to change it to use dma_alloc_from_contiguous. That way 
we wouldn't get the double IOMMU mapping, which would be nice.





Considering that, I'm wondering if we can just have a temporary local
dma_addr_t and then cast that to phys_addr_t, combined with a good comment?


That was my first approach, and it does address the warning, but
I did not send it because it still felt too wrong.

 Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



Re: [PATCH] [RFC] gpu: host1x: shut up warning about DMA API misuse

2017-04-20 Thread Mikko Perttunen

On 20.04.2017 13:02, Arnd Bergmann wrote:

On Thu, Apr 20, 2017 at 11:44 AM, Mikko Perttunen <cyn...@kapsi.fi> wrote:

On 20.04.2017 11:25, Arnd Bergmann wrote:

On Thu, Apr 20, 2017 at 9:02 AM, Mikko Perttunen <cyn...@kapsi.fi> wrote:

On 19.04.2017 21:24, Arnd Bergmann wrote:


I don't think this can be a per-platform policy.



Yeah, now that we are using the ARM SMMU on T186 onwards it's more difficult
than when we were using the Tegra SMMU, so we'll probably have to change
that.

The goal of the current code is to allocate memory from the CMA, so one
option would be to change it to use dma_alloc_from_contiguous. That way we
wouldn't get the double IOMMU mapping, which would be nice.


Right, also we shouldn't define what a particular API does based on
which platform you run on.


Indeed.




The goal of the current code is to allocate memory from the CMA, so one
option would be to change it to use dma_alloc_from_contiguous. That way
we wouldn't get the double IOMMU mapping, which would be nice.


dma_alloc_from_contiguous() is intentionally not exported to drivers,
and it would result in a page that is not mapped into your kernel
address space.


Ah, sorry, didn't notice that while looking.



This is probably not the only driver that has this issue, so maybe a
better approach would be to fill the API gap and introduce an IOMMU
API function that takes a domain/iova/length tuple as its argument
and allocates coherent or WC memory that it maps into that address?


There is definitely space for some API improvement in the whole IOMMU 
domain memory allocation space. I would prefer keeping the IOMMU mapping 
and memory allocation separate, though, since otherwise we couldn't map 
the same physical memory into multiple domains (or have some memory that 
is temporarily not mapped into any.)


The issue seems to be non-trivial, so I'm fine with your RFC patch - it 
solves the issue and the double domain mapping thing is not a problem 
currently as we don't yet support IOMMU on T186. By the time we do 
support it I hope we'll have the new API or whatever replacement in place.




  Arnd



Thanks,
Mikko


Re: [PATCH v2 2/3] dt-bindings: Add bindings for nvidia,tegra186-ccplex-cluster

2017-04-20 Thread Mikko Perttunen

Rob, Mark,

could you review this and the 3/3 in the series (which I'm sending to 
you momentarily)?


Thanks,
Mikko.

On 04.04.2017 16:43, Mikko Perttunen wrote:

The Tegra186 CCPLEX_CLUSTER area contains memory-mapped
registers that initiate CPU frequency/voltage transitions.

Signed-off-by: Mikko Perttunen <mperttu...@nvidia.com>
---
v2:
- Only one regs entry.
- s/Phandle/phandle/

 .../arm/tegra/nvidia,tegra186-ccplex-cluster.txt| 17 +
 1 file changed, 17 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt

diff --git 
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
new file mode 100644
index ..e8fb416c892b
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-ccplex-cluster.txt
@@ -0,0 +1,17 @@
+NVIDIA Tegra CCPLEX_CLUSTER area
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-ccplex-cluster": for Tegra186
+- reg: Must contain an (offset, length) pair of the device's MMIO
+  register area
+- nvidia,bpmp: phandle to BPMP device that can be queried for OPP tables
+
+Example:
+
+   ccplex@e00 {
+   compatible = "nvidia,tegra186-ccplex-cluster";
+   reg = <0x0 0x0e00 0x0 0x3f>,
+
+   nvidia,bpmp = <>;
+   };



<    1   2   3   4   5   6   7   8   9   10   >