Re: [PATCH] clk: rockchip: Fix overflow rate during fractional approximation

2020-09-14 Thread Finley Xiao
ommit:

commit <88a5404a2277> ("clk: rockchip: fix up the
rockchip_fractional_approximation")

commit <4186a0e4239b> ("clk: rockchip: Add supprot to limit input rate
for fractional divider")

Signed-off-by: Jagan Teki 
Signed-off-by: Finley Xiao 
---
  drivers/clk/rockchip/clk-px30.c | 12 ++--
  drivers/clk/rockchip/clk.c  |  9 +
  2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
index 6fb9c98b7d24..06d3ff39d12f 100644
--- a/drivers/clk/rockchip/clk-px30.c
+++ b/drivers/clk/rockchip/clk-px30.c
@@ -660,7 +660,7 @@ static struct rockchip_clk_branch px30_clk_branches[] 
__initdata = {
COMPOSITE(SCLK_UART1_SRC, "clk_uart1_src", mux_uart_src_p, 
CLK_SET_RATE_NO_REPARENT,
PX30_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_CLKGATE_CON(10), 12, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart1_np5", "clk_uart1_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart1_np5", "clk_uart1_src", 
CLK_SET_RATE_PARENT,
PX30_CLKSEL_CON(35), 0, 5, DFLAGS,
PX30_CLKGATE_CON(10), 13, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_src", 
CLK_SET_RATE_PARENT,
@@ -673,7 +673,7 @@ static struct rockchip_clk_branch px30_clk_branches[] 
__initdata = {
COMPOSITE(SCLK_UART2_SRC, "clk_uart2_src", mux_uart_src_p, 0,
PX30_CLKSEL_CON(37), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 0, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart2_np5", "clk_uart2_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart2_np5", "clk_uart2_src", 
CLK_SET_RATE_PARENT,
PX30_CLKSEL_CON(38), 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 1, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_src", 
CLK_SET_RATE_PARENT,
@@ -686,7 +686,7 @@ static struct rockchip_clk_branch px30_clk_branches[] 
__initdata = {
COMPOSITE(0, "clk_uart3_src", mux_uart_src_p, 0,
PX30_CLKSEL_CON(40), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 4, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart3_np5", "clk_uart3_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart3_np5", "clk_uart3_src", 
CLK_SET_RATE_PARENT,
PX30_CLKSEL_CON(41), 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 5, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_src", 
CLK_SET_RATE_PARENT,
@@ -699,7 +699,7 @@ static struct rockchip_clk_branch px30_clk_branches[] 
__initdata = {
COMPOSITE(0, "clk_uart4_src", mux_uart_src_p, 0,
PX30_CLKSEL_CON(43), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 8, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart4_np5", "clk_uart4_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart4_np5", "clk_uart4_src", 
CLK_SET_RATE_PARENT,
PX30_CLKSEL_CON(44), 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 9, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_src", 
CLK_SET_RATE_PARENT,
@@ -712,7 +712,7 @@ static struct rockchip_clk_branch px30_clk_branches[] 
__initdata = {
COMPOSITE(0, "clk_uart5_src", mux_uart_src_p, 0,
PX30_CLKSEL_CON(46), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 12, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart5_np5", "clk_uart5_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart5_np5", "clk_uart5_src", 
CLK_SET_RATE_PARENT,
PX30_CLKSEL_CON(47), 0, 5, DFLAGS,
PX30_CLKGATE_CON(11), 13, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart5_frac", "clk_uart5_src", 
CLK_SET_RATE_PARENT,
@@ -934,7 +934,7 @@ static struct rockchip_clk_branch px30_clk_pmu_branches[] 
__initdata = {
COMPOSITE(0, "clk_uart0_pmu_src", mux_uart_src_p, 0,
PX30_PMU_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 5, DFLAGS,
PX30_PMU_CLKGATE_CON(1), 0, GFLAGS),
-   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart0_np5", "clk_uart0_pmu_src", 0,
+   COMPOSITE_NOMUX_HALFDIV(0, "clk_uart0_np5", "clk_uart0_pmu_src", 
CLK_SET_RATE_PARENT,
PX30_PMU_CLKSEL_CON(4), 0, 5, DFLAGS,
PX30_PMU_CLKGATE_CON(1), 1, GFLAGS),
COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_pmu_src",

[PATCH v1] thermal/of: Introduce k-po, k-pu and k-i for a thermal zone

2020-08-11 Thread Finley Xiao
The default value for k_pu is:
2 * sustainable_power / (desired_temperature - switch_on_temp)
The default value for k_po is:
sustainable_power / (desired_temperature - switch_on_temp)
The default value for k_i is 10.

Even though these parameters of the PID controller can be changed
by the following sysfs files:
/sys/class/thermal/thermal_zoneX/k_pu
/sys/class/thermal/thermal_zoneX/k_po
/sys/class/thermal/thermal_zoneX/k_i

But it's still more convenient to change the default values by devicetree,
so introduce these three optional properties. If provided these properties,
they will be parsed and associated with the thermal zone via the thermal
zone parameters.

Signed-off-by: Finley Xiao 
---
 Documentation/devicetree/bindings/thermal/thermal.txt | 14 ++
 drivers/thermal/thermal_of.c  |  7 +++
 2 files changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt 
b/Documentation/devicetree/bindings/thermal/thermal.txt
index f78bec19ca35..ebe936b57ded 100644
--- a/Documentation/devicetree/bindings/thermal/thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -165,6 +165,20 @@ Optional property:
2000mW, while on a 10'' tablet is around
4500mW.
 
+- k-po:Proportional parameter of the PID controller 
when
+   current temperature is above the target.
+  Type: signed
+  Size: one cell
+
+- k-pu:Proportional parameter of the PID controller 
when
+   current temperature is below the target.
+  Type: signed
+  Size: one cell
+
+- k-i: Integral parameter of the PID controller.
+  Type: signed
+  Size: one cell
+
 Note: The delay properties are bound to the maximum dT/dt (temperature
 derivative over time) in two situations for a thermal zone:
 (i)  - when passive cooling is activated (polling-delay-passive); and
diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
index ddf88dbe7ba2..b2a9f92cd8d2 100644
--- a/drivers/thermal/thermal_of.c
+++ b/drivers/thermal/thermal_of.c
@@ -1089,6 +1089,7 @@ int __init of_parse_thermal_zones(void)
struct thermal_zone_params *tzp;
int i, mask = 0;
u32 prop;
+   s32 sval;
 
tz = thermal_of_build_thermal_zone(child);
if (IS_ERR(tz)) {
@@ -1113,6 +1114,12 @@ int __init of_parse_thermal_zones(void)
 
if (!of_property_read_u32(child, "sustainable-power", ))
tzp->sustainable_power = prop;
+   if (!of_property_read_s32(child, "k-po", ))
+   tzp->k_po = sval;
+   if (!of_property_read_s32(child, "k-pu", ))
+   tzp->k_pu = sval;
+   if (!of_property_read_s32(child, "k-i", ))
+   tzp->k_i = sval;
 
for (i = 0; i < tz->ntrips; i++)
mask |= 1 << i;
-- 
2.11.0





[PATCH] thermal/drivers/cpufreq_cooling: Fix wrong frequency converted from power

2020-06-19 Thread Finley Xiao
The function cpu_power_to_freq is used to find a frequency and set the
cooling device to consume at most the power to be converted. For example,
if the power to be converted is 80mW, and the em table is as follow.
struct em_cap_state table[] = {
/* KHz mW */
{ 1008000, 36, 0 },
{ 120, 49, 0 },
{ 1296000, 59, 0 },
{ 1416000, 72, 0 },
{ 1512000, 86, 0 },
};
The target frequency should be 1416000KHz, not 1512000KHz.

Fixes: 349d39dc5739 ("thermal: cpu_cooling: merge frequency and power tables")
Cc:  # v4.13+
Signed-off-by: Finley Xiao 
Acked-by: Viresh Kumar 
---
 drivers/thermal/cpufreq_cooling.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/cpufreq_cooling.c 
b/drivers/thermal/cpufreq_cooling.c
index 9e124020519f..6c0e1b053126 100644
--- a/drivers/thermal/cpufreq_cooling.c
+++ b/drivers/thermal/cpufreq_cooling.c
@@ -123,12 +123,12 @@ static u32 cpu_power_to_freq(struct 
cpufreq_cooling_device *cpufreq_cdev,
 {
int i;
 
-   for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
-   if (power > cpufreq_cdev->em->table[i].power)
+   for (i = cpufreq_cdev->max_level; i >= 0; i--) {
+   if (power >= cpufreq_cdev->em->table[i].power)
break;
}
 
-   return cpufreq_cdev->em->table[i + 1].frequency;
+   return cpufreq_cdev->em->table[i].frequency;
 }
 
 /**
-- 
2.11.0





[PATCH] thermal/drivers/cpufreq_cooling: Fix wrong frequency converted from power

2020-06-18 Thread Finley Xiao
The function cpu_power_to_freq is used to find a frequency and set the
cooling device to consume at most the power to be converted. For example,
if the power to be converted is 80mW, and the em table is as follow.
struct em_cap_state table[] = {
/* KHz mW */
{ 1008000, 36, 0 },
{ 120, 49, 0 },
{ 1296000, 59, 0 },
{ 1416000, 72, 0 },
{ 1512000, 86, 0 },
};
The target frequency should be 1416000KHz, not 1512000KHz.

Fixes: 349d39dc5739 ("thermal: cpu_cooling: merge frequency and power tables")
Signed-off-by: Finley Xiao 
---
 drivers/thermal/cpufreq_cooling.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/cpufreq_cooling.c 
b/drivers/thermal/cpufreq_cooling.c
index 9e124020519f..6c0e1b053126 100644
--- a/drivers/thermal/cpufreq_cooling.c
+++ b/drivers/thermal/cpufreq_cooling.c
@@ -123,12 +123,12 @@ static u32 cpu_power_to_freq(struct 
cpufreq_cooling_device *cpufreq_cdev,
 {
int i;
 
-   for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
-   if (power > cpufreq_cdev->em->table[i].power)
+   for (i = cpufreq_cdev->max_level; i >= 0; i--) {
+   if (power >= cpufreq_cdev->em->table[i].power)
break;
}
 
-   return cpufreq_cdev->em->table[i + 1].frequency;
+   return cpufreq_cdev->em->table[i].frequency;
 }
 
 /**
-- 
2.11.0





[PATCH v1 3/3] clk: rockchip: Add clock controller for the RK3308

2019-09-03 Thread Finley Xiao
Add the clock tree definition for the new RK3308 SoC.

Signed-off-by: Finley Xiao 
---
 drivers/clk/rockchip/Makefile |   1 +
 drivers/clk/rockchip/clk-rk3308.c | 955 ++
 drivers/clk/rockchip/clk.h|  13 +
 3 files changed, 969 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-rk3308.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index ff35ab463a6f..7c5b5813a87c 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -20,6 +20,7 @@ obj-y += clk-rk3128.o
 obj-y  += clk-rk3188.o
 obj-y  += clk-rk3228.o
 obj-y  += clk-rk3288.o
+obj-y  += clk-rk3308.o
 obj-y  += clk-rk3328.o
 obj-y  += clk-rk3368.o
 obj-y  += clk-rk3399.o
diff --git a/drivers/clk/rockchip/clk-rk3308.c 
b/drivers/clk/rockchip/clk-rk3308.c
new file mode 100644
index ..b0baf87a283e
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3308.c
@@ -0,0 +1,955 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "clk.h"
+
+#define RK3308_GRF_SOC_STATUS0 0x380
+
+enum rk3308_plls {
+   apll, dpll, vpll0, vpll1,
+};
+
+static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
+   /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+   RK3036_PLL_RATE(160800, 1, 67, 1, 1, 1, 0),
+   RK3036_PLL_RATE(158400, 1, 66, 1, 1, 1, 0),
+   RK3036_PLL_RATE(156000, 1, 65, 1, 1, 1, 0),
+   RK3036_PLL_RATE(153600, 1, 64, 1, 1, 1, 0),
+   RK3036_PLL_RATE(151200, 1, 63, 1, 1, 1, 0),
+   RK3036_PLL_RATE(148800, 1, 62, 1, 1, 1, 0),
+   RK3036_PLL_RATE(146400, 1, 61, 1, 1, 1, 0),
+   RK3036_PLL_RATE(144000, 1, 60, 1, 1, 1, 0),
+   RK3036_PLL_RATE(141600, 1, 59, 1, 1, 1, 0),
+   RK3036_PLL_RATE(139200, 1, 58, 1, 1, 1, 0),
+   RK3036_PLL_RATE(136800, 1, 57, 1, 1, 1, 0),
+   RK3036_PLL_RATE(134400, 1, 56, 1, 1, 1, 0),
+   RK3036_PLL_RATE(132000, 1, 55, 1, 1, 1, 0),
+   RK3036_PLL_RATE(129600, 1, 54, 1, 1, 1, 0),
+   RK3036_PLL_RATE(127200, 1, 53, 1, 1, 1, 0),
+   RK3036_PLL_RATE(124800, 1, 52, 1, 1, 1, 0),
+   RK3036_PLL_RATE(12, 1, 50, 1, 1, 1, 0),
+   RK3036_PLL_RATE(118800, 2, 99, 1, 1, 1, 0),
+   RK3036_PLL_RATE(110400, 1, 46, 1, 1, 1, 0),
+   RK3036_PLL_RATE(11, 12, 550, 1, 1, 1, 0),
+   RK3036_PLL_RATE(100800, 1, 84, 2, 1, 1, 0),
+   RK3036_PLL_RATE(10, 6, 500, 2, 1, 1, 0),
+   RK3036_PLL_RATE(98400, 1, 82, 2, 1, 1, 0),
+   RK3036_PLL_RATE(96000, 1, 80, 2, 1, 1, 0),
+   RK3036_PLL_RATE(93600, 1, 78, 2, 1, 1, 0),
+   RK3036_PLL_RATE(91200, 1, 76, 2, 1, 1, 0),
+   RK3036_PLL_RATE(9, 4, 300, 2, 1, 1, 0),
+   RK3036_PLL_RATE(88800, 1, 74, 2, 1, 1, 0),
+   RK3036_PLL_RATE(86400, 1, 72, 2, 1, 1, 0),
+   RK3036_PLL_RATE(84000, 1, 70, 2, 1, 1, 0),
+   RK3036_PLL_RATE(81600, 1, 68, 2, 1, 1, 0),
+   RK3036_PLL_RATE(8, 6, 400, 2, 1, 1, 0),
+   RK3036_PLL_RATE(7, 6, 350, 2, 1, 1, 0),
+   RK3036_PLL_RATE(69600, 1, 58, 2, 1, 1, 0),
+   RK3036_PLL_RATE(62400, 1, 52, 2, 1, 1, 0),
+   RK3036_PLL_RATE(6, 1, 75, 3, 1, 1, 0),
+   RK3036_PLL_RATE(59400, 2, 99, 2, 1, 1, 0),
+   RK3036_PLL_RATE(50400, 1, 63, 3, 1, 1, 0),
+   RK3036_PLL_RATE(5, 6, 250, 2, 1, 1, 0),
+   RK3036_PLL_RATE(40800, 1, 68, 2, 2, 1, 0),
+   RK3036_PLL_RATE(31200, 1, 52, 2, 2, 1, 0),
+   RK3036_PLL_RATE(21600, 1, 72, 4, 2, 1, 0),
+   RK3036_PLL_RATE(9600, 1, 64, 4, 4, 1, 0),
+   { /* sentinel */ },
+};
+
+#define RK3308_DIV_ACLKM_MASK  0x7
+#define RK3308_DIV_ACLKM_SHIFT 12
+#define RK3308_DIV_PCLK_DBG_MASK   0xf
+#define RK3308_DIV_PCLK_DBG_SHIFT  8
+
+#define RK3308_CLKSEL0(_aclk_core, _pclk_dbg)  \
+{  \
+   .reg = RK3308_CLKSEL_CON(0),\
+   .val = HIWORD_UPDATE(_aclk_core, RK3308_DIV_ACLKM_MASK, \
+RK3308_DIV_ACLKM_SHIFT) |  \
+  HIWORD_UPDATE(_pclk_dbg, RK3308_DIV_PCLK_DBG_MASK,   \
+RK3308_DIV_PCLK_DBG_SHIFT),\
+}
+
+#define RK3308_CPUCLK_RATE(_prate, _aclk_core, _pclk_dbg)  \
+{  \
+   .prate = _prate,\
+   .divs = {   \
+   RK3308_CLKSEL0(_aclk_core, _pclk_dbg),  \
+   },  \
+}

[PATCH v1 1/3] dt-bindings: Add bindings for rk3308 clock controller

2019-09-03 Thread Finley Xiao
Add devicetree bindings for Rockchip cru which found on
Rockchip SoCs.

Signed-off-by: Finley Xiao 
---
 .../devicetree/bindings/clock/rockchip,rk3308.txt  | 58 ++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3308.txt

diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3308.txt 
b/Documentation/devicetree/bindings/clock/rockchip,rk3308.txt
new file mode 100644
index ..5d46c9b7f937
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3308.txt
@@ -0,0 +1,58 @@
+* Rockchip RK3308 Clock and Reset Unit
+
+The RK3308 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: CRU should be "rockchip,rk3308-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing, pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3308-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "mclk_i2sx_xch_in" - external I2S or SPDIF clock - optional,
+ - "mac_clkin" - external MAC clock - optional
+
+Example: Clock controller node:
+
+   cru: clock-controller@ff50 {
+   compatible = "rockchip,rk3308-cru";
+   reg = <0x0 0xff50 0x0 0x1000>;
+   rockchip,grf = <>;
+   #clock-cells = <1>;
+   #reset-cells = <1>;
+   };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+   uart0: serial@ff0a {
+   compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
+   reg = <0x0 0xff0a 0x0 0x100>;
+   interrupts = ;
+   clocks = < SCLK_UART0>, < PCLK_UART0>;
+   clock-names = "baudclk", "apb_pclk";
+   reg-shift = <2>;
+   reg-io-width = <4>;
+   status = "disabled";
+   };
-- 
2.11.0





[PATCH v1 0/3] clk: rockchip: support clock controller for rk3308 SoC

2019-09-03 Thread Finley Xiao
Finley Xiao (3):
  dt-bindings: Add bindings for rk3308 clock controller
  clk: rockchip: Add dt-binding header for rk3308
  clk: rockchip: Add clock controller for the RK3308

 .../devicetree/bindings/clock/rockchip,rk3308.txt  |  58 ++
 drivers/clk/rockchip/Makefile  |   1 +
 drivers/clk/rockchip/clk-rk3308.c  | 955 +
 drivers/clk/rockchip/clk.h |  13 +
 include/dt-bindings/clock/rk3308-cru.h | 387 +
 5 files changed, 1414 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3308.txt
 create mode 100644 drivers/clk/rockchip/clk-rk3308.c
 create mode 100644 include/dt-bindings/clock/rk3308-cru.h

-- 
2.11.0





[PATCH v1 2/3] clk: rockchip: Add dt-binding header for rk3308

2019-09-03 Thread Finley Xiao
Add the dt-bindings header for the rk3308, that gets shared between
the clock controller and the clock references in the dts.

Signed-off-by: Finley Xiao 
---
 include/dt-bindings/clock/rk3308-cru.h | 387 +
 1 file changed, 387 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk3308-cru.h

diff --git a/include/dt-bindings/clock/rk3308-cru.h 
b/include/dt-bindings/clock/rk3308-cru.h
new file mode 100644
index ..d97840f9ee2e
--- /dev/null
+++ b/include/dt-bindings/clock/rk3308-cru.h
@@ -0,0 +1,387 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao 
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H
+
+/* core clocks */
+#define PLL_APLL   1
+#define PLL_DPLL   2
+#define PLL_VPLL0  3
+#define PLL_VPLL1  4
+#define ARMCLK 5
+
+/* sclk (special clocks) */
+#define USB480M14
+#define SCLK_RTC32K15
+#define SCLK_PVTM_CORE 16
+#define SCLK_UART0 17
+#define SCLK_UART1 18
+#define SCLK_UART2 19
+#define SCLK_UART3 20
+#define SCLK_UART4 21
+#define SCLK_I2C0  22
+#define SCLK_I2C1  23
+#define SCLK_I2C2  24
+#define SCLK_I2C3  25
+#define SCLK_PWM0  26
+#define SCLK_SPI0  27
+#define SCLK_SPI1  28
+#define SCLK_SPI2  29
+#define SCLK_TIMER030
+#define SCLK_TIMER131
+#define SCLK_TIMER232
+#define SCLK_TIMER333
+#define SCLK_TIMER434
+#define SCLK_TIMER535
+#define SCLK_TSADC 36
+#define SCLK_SARADC37
+#define SCLK_OTP   38
+#define SCLK_OTP_USR   39
+#define SCLK_CPU_BOOST 40
+#define SCLK_CRYPTO41
+#define SCLK_CRYPTO_APK42
+#define SCLK_NANDC_DIV 43
+#define SCLK_NANDC_DIV50   44
+#define SCLK_NANDC 45
+#define SCLK_SDMMC_DIV 46
+#define SCLK_SDMMC_DIV50   47
+#define SCLK_SDMMC 48
+#define SCLK_SDMMC_DRV 49
+#define SCLK_SDMMC_SAMPLE  50
+#define SCLK_SDIO_DIV  51
+#define SCLK_SDIO_DIV5052
+#define SCLK_SDIO  53
+#define SCLK_SDIO_DRV  54
+#define SCLK_SDIO_SAMPLE   55
+#define SCLK_EMMC_DIV  56
+#define SCLK_EMMC_DIV5057
+#define SCLK_EMMC  58
+#define SCLK_EMMC_DRV  59
+#define SCLK_EMMC_SAMPLE   60
+#define SCLK_SFC   61
+#define SCLK_OTG_ADP   62
+#define SCLK_MAC_SRC   63
+#define SCLK_MAC   64
+#define SCLK_MAC_REF   65
+#define SCLK_MAC_RX_TX 66
+#define SCLK_MAC_RMII  67
+#define SCLK_DDR_MON_TIMER 68
+#define SCLK_DDR_MON   69
+#define SCLK_DDRCLK70
+#define SCLK_PMU   71
+#define SCLK_USBPHY_REF72
+#define SCLK_WIFI  73
+#define SCLK_PVTM_PMU  74
+#define SCLK_PDM   75
+#define SCLK_I2S0_8CH_TX   76
+#define SCLK_I2S0_8CH_TX_OUT   77
+#define SCLK_I2S0_8CH_RX   78
+#define SCLK_I2S0_8CH_RX_OUT   79
+#define SCLK_I2S1_8CH_TX   80
+#define SCLK_I2S1_8CH_TX_OUT   81
+#define SCLK_I2S1_8CH_RX   82
+#define SCLK_I2S1_8CH_RX_OUT   83
+#define SCLK_I2S2_8CH_TX   84
+#define SCLK_I2S2_8CH_TX_OUT   85
+#define SCLK_I2S2_8CH_RX   86
+#define SCLK_I2S2_8CH_RX_OUT   87
+#define SCLK_I2S3_8CH_TX   88
+#define SCLK_I2S3_8CH_TX_OUT   89
+#define SCLK_I2S3_8CH_RX   90
+#define SCLK_I2S3_8CH_RX_OUT   91
+#define SCLK_I2S0_2CH  92
+#define SCLK_I2S0_2CH_OUT  93
+#define SCLK_I2S1_2CH  94
+#define SCLK_I2S1_2CH_OUT  95
+#define SCLK_SPDIF_TX_DIV  96
+#define SCLK_SPDIF_TX_DIV5097
+#define SCLK_SPDIF_TX  98
+#define SCLK_SPDIF_RX_DIV  99
+#define SCLK_SPDIF_RX_DIV50100
+#define SCLK_SPDIF_RX  101
+#define SCLK_I2S0_8CH_TX_MUX   102
+#define SCLK_I2S0_8CH_RX_MUX   103
+#define SCLK_I2S1_8CH_TX_MUX   104
+#define SCLK_I2S1_8CH_RX_MUX   105
+#define SCLK_I2S2_8CH_TX_MUX   106
+#define SCLK_I2S2_8CH_RX_MUX   107
+#define SCLK_I2S3_8CH_TX_MUX   108
+#define SCLK_I2S3_8CH_RX_MUX   109
+#define SCLK_I2S0_8CH_TX_SRC   110
+#define SCLK_I2S0_8CH_RX_SRC   111
+#define SCLK_I2S1_8CH_TX_SRC   112
+#define SCLK_I2S1_8CH_RX_SRC   113
+#define SCLK_I2S2_8CH_TX_SRC   114
+#define SCLK_I2S2_8CH_RX_SRC   115
+#define SCLK_I2S3_8CH_TX_SRC   116
+#define SCLK_I2S3_8CH_RX_SRC   117
+#define SCLK_I2S0_2CH_SRC  118
+#define SCLK_I2S1_2CH_SRC  119
+#define SCLK_PWM1  120
+#define SCLK_PWM2  121
+#define SCLK_OWIRE 122
+
+/* dclk */
+#define DCLK_VOP   125
+
+/* aclk */
+#define ACLK_BUS_SRC   130
+#define ACLK_BUS

[PATCH 0/2] arm64: dts: rockchip: add cpu operating points and efuse node for RK3328 SoC

2017-08-03 Thread Finley Xiao
Add cpu operating points and an efuse node in the device tree for rk3228 SoC

Finley Xiao (2):
  arm64: dts: rockchip: Add cpu operating points for RK3328 SoC
  arm64: dts: rockchip: Add efuse device node for RK3328 SoC

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 66 
 1 file changed, 66 insertions(+)

-- 
2.7.4




[PATCH 0/2] arm64: dts: rockchip: add cpu operating points and efuse node for RK3328 SoC

2017-08-03 Thread Finley Xiao
Add cpu operating points and an efuse node in the device tree for rk3228 SoC

Finley Xiao (2):
  arm64: dts: rockchip: Add cpu operating points for RK3328 SoC
  arm64: dts: rockchip: Add efuse device node for RK3328 SoC

 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 66 
 1 file changed, 66 insertions(+)

-- 
2.7.4




[PATCH 2/2] arm64: dts: rockchip: Add efuse device node for RK3328 SoC

2017-08-03 Thread Finley Xiao
This patch adds an efuse node in the device tree for rk3228 SoC.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 25 +
 1 file changed, 25 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 81fd8cb..cc8dd80 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -367,6 +367,31 @@
interrupts = ;
};
 
+   efuse: efuse@ff26 {
+   compatible = "rockchip,rk3328-efuse";
+   reg = <0x0 0xff26 0x0 0x50>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   clocks = < SCLK_EFUSE>;
+   clock-names = "pclk_efuse";
+   rockchip,efuse-size = <0x20>;
+
+   /* Data cells */
+   efuse_id: id@7 {
+   reg = <0x07 0x10>;
+   };
+   cpu_leakage: cpu-leakage@17 {
+   reg = <0x17 0x1>;
+   };
+   logic_leakage: logic-leakage@19 {
+   reg = <0x19 0x1>;
+   };
+   efuse_cpu_version: cpu-version@1a {
+   reg = <0x1a 0x1>;
+   bits = <3 3>;
+   };
+   };
+
saradc: adc@ff28 {
compatible = "rockchip,rk3328-saradc", "rockchip,rk3399-saradc";
reg = <0x0 0xff28 0x0 0x100>;
-- 
2.7.4




[PATCH 1/2] arm64: dts: rockchip: Add cpu operating points for RK3328 SoC

2017-08-03 Thread Finley Xiao
This patch adds basic OPP entries for RK3328 SoC.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 41 
 1 file changed, 41 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 440e6bc..81fd8cb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -76,6 +76,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu1: cpu@1 {
@@ -85,6 +86,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu2: cpu@2 {
@@ -94,6 +96,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu3: cpu@3 {
@@ -103,6 +106,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
l2: l2-cache0 {
@@ -110,6 +114,43 @@
};
};
 
+   cpu0_opp_table: opp_table0 {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   opp-40800 {
+   opp-hz = /bits/ 64 <40800>;
+   opp-microvolt = <95>;
+   clock-latency-ns = <4>;
+   opp-suspend;
+   };
+   opp-6 {
+   opp-hz = /bits/ 64 <6>;
+   opp-microvolt = <95>;
+   clock-latency-ns = <4>;
+   };
+   opp-81600 {
+   opp-hz = /bits/ 64 <81600>;
+   opp-microvolt = <100>;
+   clock-latency-ns = <4>;
+   };
+   opp-100800 {
+   opp-hz = /bits/ 64 <100800>;
+   opp-microvolt = <110>;
+   clock-latency-ns = <4>;
+   };
+   opp-12 {
+   opp-hz = /bits/ 64 <12>;
+   opp-microvolt = <1225000>;
+   clock-latency-ns = <4>;
+   };
+   opp-129600 {
+   opp-hz = /bits/ 64 <129600>;
+   opp-microvolt = <130>;
+   clock-latency-ns = <4>;
+   };
+   };
+
amba {
compatible = "simple-bus";
#address-cells = <2>;
-- 
2.7.4




[PATCH 2/2] arm64: dts: rockchip: Add efuse device node for RK3328 SoC

2017-08-03 Thread Finley Xiao
This patch adds an efuse node in the device tree for rk3228 SoC.

Signed-off-by: Finley Xiao 
---
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 25 +
 1 file changed, 25 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 81fd8cb..cc8dd80 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -367,6 +367,31 @@
interrupts = ;
};
 
+   efuse: efuse@ff26 {
+   compatible = "rockchip,rk3328-efuse";
+   reg = <0x0 0xff26 0x0 0x50>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   clocks = < SCLK_EFUSE>;
+   clock-names = "pclk_efuse";
+   rockchip,efuse-size = <0x20>;
+
+   /* Data cells */
+   efuse_id: id@7 {
+   reg = <0x07 0x10>;
+   };
+   cpu_leakage: cpu-leakage@17 {
+   reg = <0x17 0x1>;
+   };
+   logic_leakage: logic-leakage@19 {
+   reg = <0x19 0x1>;
+   };
+   efuse_cpu_version: cpu-version@1a {
+   reg = <0x1a 0x1>;
+   bits = <3 3>;
+   };
+   };
+
saradc: adc@ff28 {
compatible = "rockchip,rk3328-saradc", "rockchip,rk3399-saradc";
reg = <0x0 0xff28 0x0 0x100>;
-- 
2.7.4




[PATCH 1/2] arm64: dts: rockchip: Add cpu operating points for RK3328 SoC

2017-08-03 Thread Finley Xiao
This patch adds basic OPP entries for RK3328 SoC.

Signed-off-by: Finley Xiao 
---
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 41 
 1 file changed, 41 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 440e6bc..81fd8cb 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -76,6 +76,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu1: cpu@1 {
@@ -85,6 +86,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu2: cpu@2 {
@@ -94,6 +96,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
cpu3: cpu@3 {
@@ -103,6 +106,7 @@
clocks = < ARMCLK>;
enable-method = "psci";
next-level-cache = <>;
+   operating-points-v2 = <_opp_table>;
};
 
l2: l2-cache0 {
@@ -110,6 +114,43 @@
};
};
 
+   cpu0_opp_table: opp_table0 {
+   compatible = "operating-points-v2";
+   opp-shared;
+
+   opp-40800 {
+   opp-hz = /bits/ 64 <40800>;
+   opp-microvolt = <95>;
+   clock-latency-ns = <4>;
+   opp-suspend;
+   };
+   opp-6 {
+   opp-hz = /bits/ 64 <6>;
+   opp-microvolt = <95>;
+   clock-latency-ns = <4>;
+   };
+   opp-81600 {
+   opp-hz = /bits/ 64 <81600>;
+   opp-microvolt = <100>;
+   clock-latency-ns = <4>;
+   };
+   opp-100800 {
+   opp-hz = /bits/ 64 <100800>;
+   opp-microvolt = <110>;
+   clock-latency-ns = <4>;
+   };
+   opp-12 {
+   opp-hz = /bits/ 64 <12>;
+   opp-microvolt = <1225000>;
+   clock-latency-ns = <4>;
+   };
+   opp-129600 {
+   opp-hz = /bits/ 64 <129600>;
+   opp-microvolt = <130>;
+   clock-latency-ns = <4>;
+   };
+   };
+
amba {
compatible = "simple-bus";
#address-cells = <2>;
-- 
2.7.4




[PATCH] cpufreq: dt: Add rk3328 compatible to use generic cpufreq driver

2017-08-03 Thread Finley Xiao
This patch adds the rk3328 compatible string for supporting
the generic cpufreq driver on RK3328.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 096aea7..13c0c47 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -76,6 +76,7 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "rockchip,rk3188", },
{ .compatible = "rockchip,rk3228", },
{ .compatible = "rockchip,rk3288", },
+   { .compatible = "rockchip,rk3328", },
{ .compatible = "rockchip,rk3366", },
{ .compatible = "rockchip,rk3368", },
{ .compatible = "rockchip,rk3399", },
-- 
2.7.4




[PATCH] cpufreq: dt: Add rk3328 compatible to use generic cpufreq driver

2017-08-03 Thread Finley Xiao
This patch adds the rk3328 compatible string for supporting
the generic cpufreq driver on RK3328.

Signed-off-by: Finley Xiao 
---
 drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
b/drivers/cpufreq/cpufreq-dt-platdev.c
index 096aea7..13c0c47 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -76,6 +76,7 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "rockchip,rk3188", },
{ .compatible = "rockchip,rk3228", },
{ .compatible = "rockchip,rk3288", },
+   { .compatible = "rockchip,rk3328", },
{ .compatible = "rockchip,rk3366", },
{ .compatible = "rockchip,rk3368", },
{ .compatible = "rockchip,rk3399", },
-- 
2.7.4




[PATCH 2/2] nvmem: rockchip-efuse: add support for rk3328-efuse

2017-07-06 Thread Finley Xiao
This adds the necessary data for handling eFuse on the rk3328.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  1 +
 drivers/nvmem/rockchip-efuse.c | 66 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index d206aa1..7a817c5 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -6,6 +6,7 @@ Required properties:
   - "rockchip,rk3188-efuse" - for RK3188 SoCs.
   - "rockchip,rk322x-efuse" - for RK322x SoCs.
   - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3328-efuse" - for RK3328 SoCs.
   - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 8e3e5d0..70c2d64 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -32,6 +32,14 @@
 #define RK3288_STROBE  BIT(1)
 #define RK3288_CSB BIT(0)
 
+#define RK3328_SECURE_SIZES96
+#define RK3328_INT_STATUS  0x0018
+#define RK3328_DOUT0x0020
+#define RK3328_AUTO_CTRL   0x0024
+#define RK3328_INT_FINISH  BIT(0)
+#define RK3328_AUTO_ENBBIT(0)
+#define RK3328_AUTO_RD BIT(1)
+
 #define RK3399_A_SHIFT 16
 #define RK3399_A_MASK  0x3ff
 #define RK3399_NBYTES  4
@@ -92,6 +100,60 @@ static int rockchip_rk3288_efuse_read(void *context, 
unsigned int offset,
return 0;
 }
 
+static int rockchip_rk3328_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value, status;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */
+   offset += RK3328_SECURE_SIZES;
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+   if (!buf) {
+   ret = -ENOMEM;
+   goto nomem;
+   }
+
+   while (addr_len--) {
+   writel(RK3328_AUTO_RD | RK3328_AUTO_ENB |
+  ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT),
+  efuse->base + RK3328_AUTO_CTRL);
+   udelay(2);
+   status = readl(efuse->base + RK3328_INT_STATUS);
+   if (!(status & RK3328_INT_FINISH)) {
+   ret = -EIO;
+   goto err;
+   }
+   out_value = readl(efuse->base + RK3328_DOUT);
+   writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS);
+
+   memcpy([i], _value, RK3399_NBYTES);
+   i += RK3399_NBYTES;
+   }
+
+   memcpy(val, buf + addr_offset, bytes);
+err:
+   kfree(buf);
+nomem:
+   clk_disable_unprepare(efuse->clk);
+
+   return ret;
+}
+
 static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
  void *val, size_t bytes)
 {
@@ -178,6 +240,10 @@ static const struct of_device_id rockchip_efuse_match[] = {
.data = (void *)_rk3288_efuse_read,
},
{
+   .compatible = "rockchip,rk3328-efuse",
+   .data = (void *)_rk3328_efuse_read,
+   },
+   {
.compatible = "rockchip,rk3399-efuse",
.data = (void *)_rk3399_efuse_read,
},
-- 
2.7.4




[PATCH 1/2] nvmem: rockchip-efuse: parse 'rockchip,efuse-size'

2017-07-06 Thread Finley Xiao
The eFuse size is defined in property  before, but the length
of registers is not equal to the size on some platforms, so we
add a new property to redefine it.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 4 
 drivers/nvmem/rockchip-efuse.c | 4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 194926f..d206aa1 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -11,6 +11,10 @@ Required properties:
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Optional properties:
+- rockchip,efuse-size: Should be exact eFuse size in byte, the eFuse
+  size in property  will be invalid if define this property.
+
 Deprecated properties:
 - compatible: "rockchip,rockchip-efuse"
   Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index a0d4ede..8e3e5d0 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -214,7 +214,9 @@ static int rockchip_efuse_probe(struct platform_device 
*pdev)
return PTR_ERR(efuse->clk);
 
efuse->dev = >dev;
-   econfig.size = resource_size(res);
+   if (of_property_read_u32(dev->of_node, "rockchip,efuse-size",
+))
+   econfig.size = resource_size(res);
econfig.reg_read = match->data;
econfig.priv = efuse;
econfig.dev = efuse->dev;
-- 
2.7.4




[PATCH 2/2] nvmem: rockchip-efuse: add support for rk3328-efuse

2017-07-06 Thread Finley Xiao
This adds the necessary data for handling eFuse on the rk3328.

Signed-off-by: Finley Xiao 
---
 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  1 +
 drivers/nvmem/rockchip-efuse.c | 66 ++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index d206aa1..7a817c5 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -6,6 +6,7 @@ Required properties:
   - "rockchip,rk3188-efuse" - for RK3188 SoCs.
   - "rockchip,rk322x-efuse" - for RK322x SoCs.
   - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3328-efuse" - for RK3328 SoCs.
   - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 8e3e5d0..70c2d64 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -32,6 +32,14 @@
 #define RK3288_STROBE  BIT(1)
 #define RK3288_CSB BIT(0)
 
+#define RK3328_SECURE_SIZES96
+#define RK3328_INT_STATUS  0x0018
+#define RK3328_DOUT0x0020
+#define RK3328_AUTO_CTRL   0x0024
+#define RK3328_INT_FINISH  BIT(0)
+#define RK3328_AUTO_ENBBIT(0)
+#define RK3328_AUTO_RD BIT(1)
+
 #define RK3399_A_SHIFT 16
 #define RK3399_A_MASK  0x3ff
 #define RK3399_NBYTES  4
@@ -92,6 +100,60 @@ static int rockchip_rk3288_efuse_read(void *context, 
unsigned int offset,
return 0;
 }
 
+static int rockchip_rk3328_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value, status;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */
+   offset += RK3328_SECURE_SIZES;
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+   if (!buf) {
+   ret = -ENOMEM;
+   goto nomem;
+   }
+
+   while (addr_len--) {
+   writel(RK3328_AUTO_RD | RK3328_AUTO_ENB |
+  ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT),
+  efuse->base + RK3328_AUTO_CTRL);
+   udelay(2);
+   status = readl(efuse->base + RK3328_INT_STATUS);
+   if (!(status & RK3328_INT_FINISH)) {
+   ret = -EIO;
+   goto err;
+   }
+   out_value = readl(efuse->base + RK3328_DOUT);
+   writel(RK3328_INT_FINISH, efuse->base + RK3328_INT_STATUS);
+
+   memcpy([i], _value, RK3399_NBYTES);
+   i += RK3399_NBYTES;
+   }
+
+   memcpy(val, buf + addr_offset, bytes);
+err:
+   kfree(buf);
+nomem:
+   clk_disable_unprepare(efuse->clk);
+
+   return ret;
+}
+
 static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
  void *val, size_t bytes)
 {
@@ -178,6 +240,10 @@ static const struct of_device_id rockchip_efuse_match[] = {
.data = (void *)_rk3288_efuse_read,
},
{
+   .compatible = "rockchip,rk3328-efuse",
+   .data = (void *)_rk3328_efuse_read,
+   },
+   {
.compatible = "rockchip,rk3399-efuse",
.data = (void *)_rk3399_efuse_read,
},
-- 
2.7.4




[PATCH 1/2] nvmem: rockchip-efuse: parse 'rockchip,efuse-size'

2017-07-06 Thread Finley Xiao
The eFuse size is defined in property  before, but the length
of registers is not equal to the size on some platforms, so we
add a new property to redefine it.

Signed-off-by: Finley Xiao 
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 4 
 drivers/nvmem/rockchip-efuse.c | 4 +++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 194926f..d206aa1 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -11,6 +11,10 @@ Required properties:
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Optional properties:
+- rockchip,efuse-size: Should be exact eFuse size in byte, the eFuse
+  size in property  will be invalid if define this property.
+
 Deprecated properties:
 - compatible: "rockchip,rockchip-efuse"
   Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index a0d4ede..8e3e5d0 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -214,7 +214,9 @@ static int rockchip_efuse_probe(struct platform_device 
*pdev)
return PTR_ERR(efuse->clk);
 
efuse->dev = >dev;
-   econfig.size = resource_size(res);
+   if (of_property_read_u32(dev->of_node, "rockchip,efuse-size",
+))
+   econfig.size = resource_size(res);
econfig.reg_read = match->data;
econfig.priv = efuse;
econfig.dev = efuse->dev;
-- 
2.7.4




[PATCH 0/2] nvmem: rockchip-efuse: add support for rk3328-efuse

2017-07-06 Thread Finley Xiao
Add a new property to define eFuse size and add the necessary data
for handling eFuse on the rk3328.

Finley Xiao (2):
  nvmem: rockchip-efuse: parse 'rockchip,efuse-size'
  nvmem: rockchip-efuse: add support for rk3328-efuse

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  5 ++
 drivers/nvmem/rockchip-efuse.c | 70 +-
 2 files changed, 74 insertions(+), 1 deletion(-)

-- 
2.7.4




[PATCH 0/2] nvmem: rockchip-efuse: add support for rk3328-efuse

2017-07-06 Thread Finley Xiao
Add a new property to define eFuse size and add the necessary data
for handling eFuse on the rk3328.

Finley Xiao (2):
  nvmem: rockchip-efuse: parse 'rockchip,efuse-size'
  nvmem: rockchip-efuse: add support for rk3328-efuse

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  5 ++
 drivers/nvmem/rockchip-efuse.c | 70 +-
 2 files changed, 74 insertions(+), 1 deletion(-)

-- 
2.7.4




[PATCH] nvmem: rockchip-efuse: add support for rk322x-efuse

2017-05-11 Thread Finley Xiao
This adds the necessary data for handling eFuse on the rk322x.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 1 +
 drivers/nvmem/rockchip-efuse.c | 4 
 2 files changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 94aeeea..194926f 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be one of the following.
   - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
   - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk322x-efuse" - for RK322x SoCs.
   - "rockchip,rk3288-efuse" - for RK3288 SoCs.
   - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 423907b..a0d4ede 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -170,6 +170,10 @@ static const struct of_device_id rockchip_efuse_match[] = {
.data = (void *)_rk3288_efuse_read,
},
{
+   .compatible = "rockchip,rk322x-efuse",
+   .data = (void *)_rk3288_efuse_read,
+   },
+   {
.compatible = "rockchip,rk3288-efuse",
.data = (void *)_rk3288_efuse_read,
},
-- 
2.7.4




[PATCH] nvmem: rockchip-efuse: add support for rk322x-efuse

2017-05-11 Thread Finley Xiao
This adds the necessary data for handling eFuse on the rk322x.

Signed-off-by: Finley Xiao 
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 1 +
 drivers/nvmem/rockchip-efuse.c | 4 
 2 files changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 94aeeea..194926f 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Should be one of the following.
   - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
   - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk322x-efuse" - for RK322x SoCs.
   - "rockchip,rk3288-efuse" - for RK3288 SoCs.
   - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 423907b..a0d4ede 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -170,6 +170,10 @@ static const struct of_device_id rockchip_efuse_match[] = {
.data = (void *)_rk3288_efuse_read,
},
{
+   .compatible = "rockchip,rk322x-efuse",
+   .data = (void *)_rk3288_efuse_read,
+   },
+   {
.compatible = "rockchip,rk3288-efuse",
.data = (void *)_rk3288_efuse_read,
},
-- 
2.7.4




Re: [PATCH v2 4/4] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-09-27 Thread Finley Xiao



在 2016/9/26 16:05, Heiko Stuebner 写道:

Am Montag, 26. September 2016, 09:25:11 CEST schrieb Viresh Kumar:

On 12-09-16, 14:55, Stephen Boyd wrote:

On 08/29, Viresh Kumar wrote:

On 18-08-16, 16:52, Finlye Xiao wrote:

+static int rockchip_adjust_opp_table(struct device *cpu_dev,
+struct cpufreq_frequency_table *table,
+int volt)
+{
+   struct opp_table *opp_table;
+   struct cpufreq_frequency_table *pos;
+   struct dev_pm_opp *opp;
+
+   if (!volt)
+   return 0;
+
+   rcu_read_lock();
+
+   opp_table = _find_opp_table(cpu_dev);
+   if (IS_ERR(opp_table)) {
+   rcu_read_unlock();
+   return PTR_ERR(opp_table);
+   }
+
+   cpufreq_for_each_valid_entry(pos, table) {
+   opp = dev_pm_opp_find_freq_exact(cpu_dev, pos->frequency * 1000,
+true);
+   if (IS_ERR(opp))
+   continue;
+
+   opp->u_volt += volt;
+   opp->u_volt_min += volt;
+   opp->u_volt_max += volt;
+   }
+
+   rcu_read_unlock();
+
+   return 0;
+}

I wouldn't prefer altering the opp tables from individual drivers at
all. At the least, it should be done via some helpers exposed by the
core.

But before that I would like to hear from Stephen a bit as I recall he
was also working on something similar.

I had a patch to modify the voltage at runtime for the "current"
OPP. Now that we have regulator and clk control inside OPP that
became a little easier to do without having to do some notifier
from the OPP layer to the consumers. I haven't had time to revive
those patches though. Should we do that?

Perhaps yes, we should have a common place for doing all that.


Does this need to modify
anything besides the OPP the device is currently running at?

Finlye, can you please answer this ?

If I understand it correctly, depending on the leakage value stored in an
efuse, all opp voltages are reduced by a certain value. Right now the driver
does it in one go for the full opp table, but of course could also do it for
each new opp individually before it gets set.


Yes, it is necessary to modify all opp voltages and  I agreed with Heiko.




--
Finley




Re: [PATCH v2 4/4] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-09-27 Thread Finley Xiao



在 2016/9/26 16:05, Heiko Stuebner 写道:

Am Montag, 26. September 2016, 09:25:11 CEST schrieb Viresh Kumar:

On 12-09-16, 14:55, Stephen Boyd wrote:

On 08/29, Viresh Kumar wrote:

On 18-08-16, 16:52, Finlye Xiao wrote:

+static int rockchip_adjust_opp_table(struct device *cpu_dev,
+struct cpufreq_frequency_table *table,
+int volt)
+{
+   struct opp_table *opp_table;
+   struct cpufreq_frequency_table *pos;
+   struct dev_pm_opp *opp;
+
+   if (!volt)
+   return 0;
+
+   rcu_read_lock();
+
+   opp_table = _find_opp_table(cpu_dev);
+   if (IS_ERR(opp_table)) {
+   rcu_read_unlock();
+   return PTR_ERR(opp_table);
+   }
+
+   cpufreq_for_each_valid_entry(pos, table) {
+   opp = dev_pm_opp_find_freq_exact(cpu_dev, pos->frequency * 1000,
+true);
+   if (IS_ERR(opp))
+   continue;
+
+   opp->u_volt += volt;
+   opp->u_volt_min += volt;
+   opp->u_volt_max += volt;
+   }
+
+   rcu_read_unlock();
+
+   return 0;
+}

I wouldn't prefer altering the opp tables from individual drivers at
all. At the least, it should be done via some helpers exposed by the
core.

But before that I would like to hear from Stephen a bit as I recall he
was also working on something similar.

I had a patch to modify the voltage at runtime for the "current"
OPP. Now that we have regulator and clk control inside OPP that
became a little easier to do without having to do some notifier
from the OPP layer to the consumers. I haven't had time to revive
those patches though. Should we do that?

Perhaps yes, we should have a common place for doing all that.


Does this need to modify
anything besides the OPP the device is currently running at?

Finlye, can you please answer this ?

If I understand it correctly, depending on the leakage value stored in an
efuse, all opp voltages are reduced by a certain value. Right now the driver
does it in one go for the full opp table, but of course could also do it for
each new opp individually before it gets set.


Yes, it is necessary to modify all opp voltages and  I agreed with Heiko.




--
Finley




[PATCH v5 4/4] nvmem: rockchip-efuse: add rk3399-efuse support

2016-09-01 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 drivers/nvmem/rockchip-efuse.c | 133 +++--
 1 file changed, 114 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..423907b 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,82 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+  (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
+   udelay(1);
+   }
+
+   /* Switch to standby mode */
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+   if (!buf) {
+   clk_disable_unprepare(efuse->clk);
+   return -ENOM

[PATCH v5 1/4] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-09-01 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
2.7.4




[PATCH v5 4/4] nvmem: rockchip-efuse: add rk3399-efuse support

2016-09-01 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 drivers/nvmem/rockchip-efuse.c | 133 +++--
 1 file changed, 114 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..423907b 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,82 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+  (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
+   udelay(1);
+   }
+
+   /* Switch to standby mode */
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+   if (!buf) {
+   clk_disable_unprepare(efuse->clk);
+   return -ENOMEM;
+   }
+
+   writel(RK3399_LOAD | RK3

[PATCH v5 1/4] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-09-01 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
2.7.4




[PATCH v5 2/4] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-09-01 Thread Finley Xiao
Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
2.7.4




[PATCH v5 3/4] arm64: dts: rockchip: add efuse0 device node for rk3399

2016-09-01 Thread Finley Xiao
Add a efuse0 node in the device tree for the ARM64 rk3399 SoC.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 29 +
 1 file changed, 29 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index a6dd623..05b48e2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -721,6 +721,35 @@
status = "disabled";
};
 
+   efuse0: efuse@ff69 {
+   compatible = "rockchip,rk3399-efuse";
+   reg = <0x0 0xff69 0x0 0x80>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   clocks = < PCLK_EFUSE1024NS>;
+   clock-names = "pclk_efuse";
+
+   /* Data cells */
+   cpul_leakage: cpul-leakage {
+   reg = <0x1a 0x1>;
+   };
+   cpub_leakage: cpub-leakage {
+   reg = <0x17 0x1>;
+   };
+   gpu_leakage: gpu-leakage {
+   reg = <0x18 0x1>;
+   };
+   center_leakage: center-leakage {
+   reg = <0x19 0x1>;
+   };
+   logic_leakage: logic-leakage {
+   reg = <0x1b 0x1>;
+   };
+   wafer_info: wafer-info {
+   reg = <0x1c 0x1>;
+   };
+   };
+
pmucru: pmu-clock-controller@ff75 {
compatible = "rockchip,rk3399-pmucru";
reg = <0x0 0xff75 0x0 0x1000>;
-- 
2.7.4




[PATCH v5 0/4] nvmem: rockchip-efuse: support more rockchip SoCs

2016-09-01 Thread Finley Xiao
As the timing and organization of efuse may be different  
between rockchip SoCs, so their read function may be different.   
We add different device tree compatible string for rockchip SoCs  
to match their own read function. 
  
V4->V5:   
- 3/4 alter the efuse node name
- 4/4 align the macro definition
  disable clk if fail to allocate memory

Finley Xiao (4):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  arm64: dts: rockchip: add efuse0 device node for rk3399
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  29 +
 drivers/nvmem/rockchip-efuse.c | 133 ++---
 6 files changed, 157 insertions(+), 24 deletions(-)

-- 
2.7.4




[PATCH v5 2/4] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-09-01 Thread Finley Xiao
Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
2.7.4




[PATCH v5 3/4] arm64: dts: rockchip: add efuse0 device node for rk3399

2016-09-01 Thread Finley Xiao
Add a efuse0 node in the device tree for the ARM64 rk3399 SoC.

Signed-off-by: Finley Xiao 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 29 +
 1 file changed, 29 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index a6dd623..05b48e2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -721,6 +721,35 @@
status = "disabled";
};
 
+   efuse0: efuse@ff69 {
+   compatible = "rockchip,rk3399-efuse";
+   reg = <0x0 0xff69 0x0 0x80>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+   clocks = < PCLK_EFUSE1024NS>;
+   clock-names = "pclk_efuse";
+
+   /* Data cells */
+   cpul_leakage: cpul-leakage {
+   reg = <0x1a 0x1>;
+   };
+   cpub_leakage: cpub-leakage {
+   reg = <0x17 0x1>;
+   };
+   gpu_leakage: gpu-leakage {
+   reg = <0x18 0x1>;
+   };
+   center_leakage: center-leakage {
+   reg = <0x19 0x1>;
+   };
+   logic_leakage: logic-leakage {
+   reg = <0x1b 0x1>;
+   };
+   wafer_info: wafer-info {
+   reg = <0x1c 0x1>;
+   };
+   };
+
pmucru: pmu-clock-controller@ff75 {
compatible = "rockchip,rk3399-pmucru";
reg = <0x0 0xff75 0x0 0x1000>;
-- 
2.7.4




[PATCH v5 0/4] nvmem: rockchip-efuse: support more rockchip SoCs

2016-09-01 Thread Finley Xiao
As the timing and organization of efuse may be different  
between rockchip SoCs, so their read function may be different.   
We add different device tree compatible string for rockchip SoCs  
to match their own read function. 
  
V4->V5:   
- 3/4 alter the efuse node name
- 4/4 align the macro definition
  disable clk if fail to allocate memory

Finley Xiao (4):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  arm64: dts: rockchip: add efuse0 device node for rk3399
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 arch/arm64/boot/dts/rockchip/rk3399.dtsi   |  29 +
 drivers/nvmem/rockchip-efuse.c | 133 ++---
 6 files changed, 157 insertions(+), 24 deletions(-)

-- 
2.7.4




[PATCH v4 0/3] nvmem: rockchip-efuse: support more rockchip SoCs

2016-08-29 Thread Finley Xiao
As the timing and organization of efuse may be different
between rockchip SoCs, so their read function may be different.
We add different device tree compatible string for rockchip SoCs
to match their own read function.

V3->V4:
- 3/3 change the type of out_value into u32 and buf into u8, their values
  come from register, use u32 and u8 may be more readable. 

Finley Xiao (3):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 drivers/nvmem/rockchip-efuse.c | 131 ++---
 5 files changed, 126 insertions(+), 24 deletions(-)

-- 
1.9.1




[PATCH v4 0/3] nvmem: rockchip-efuse: support more rockchip SoCs

2016-08-29 Thread Finley Xiao
As the timing and organization of efuse may be different
between rockchip SoCs, so their read function may be different.
We add different device tree compatible string for rockchip SoCs
to match their own read function.

V3->V4:
- 3/3 change the type of out_value into u32 and buf into u8, their values
  come from register, use u32 and u8 may be more readable. 

Finley Xiao (3):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 drivers/nvmem/rockchip-efuse.c | 131 ++---
 5 files changed, 126 insertions(+), 24 deletions(-)

-- 
1.9.1




[PATCH v4 3/3] nvmem: rockchip-efuse: add rk3399-efuse support

2016-08-29 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 drivers/nvmem/rockchip-efuse.c | 131 +++--
 1 file changed, 112 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..1825fd3 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,80 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+(~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
udelay(1);
}
 
/* Switch to standby mode */
-   writel(EFUSE_PGENB | EFUSE_CSB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK

[PATCH v4 2/3] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-08-29 Thread Finley Xiao
Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v4 1/3] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-08-29 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v4 3/3] nvmem: rockchip-efuse: add rk3399-efuse support

2016-08-29 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 drivers/nvmem/rockchip-efuse.c | 131 +++--
 1 file changed, 112 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..1825fd3 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,80 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+(~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
udelay(1);
}
 
/* Switch to standby mode */
-   writel(EFUSE_PGENB | EFUSE_CSB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   u32 out_value;
+   u8 *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+   if (!buf)
+ 

[PATCH v4 2/3] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-08-29 Thread Finley Xiao
Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v4 1/3] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-08-29 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v3 1/3] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-08-26 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v3 1/3] nvmem: rockchip-efuse: update compatible strings for Rockchip efuse

2016-08-26 Thread Finley Xiao
Rk3399-efuse is organized as 32bits by 32 one-time programmable electrical
fuses. The efuse of earlier SoCs are organized as 32bits by 8 one-time
programmable electrical fuses with random access interface.

Add different device tree compatible string for different SoCs to be able
to differentiate between the two. The old binding is of course preserved,
though deprecated.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
index 8f86ab3..94aeeea 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt
@@ -1,11 +1,20 @@
 = Rockchip eFuse device tree bindings =
 
 Required properties:
-- compatible: Should be "rockchip,rockchip-efuse"
+- compatible: Should be one of the following.
+  - "rockchip,rk3066a-efuse" - for RK3066a SoCs.
+  - "rockchip,rk3188-efuse" - for RK3188 SoCs.
+  - "rockchip,rk3288-efuse" - for RK3288 SoCs.
+  - "rockchip,rk3399-efuse" - for RK3399 SoCs.
 - reg: Should contain the registers location and exact eFuse size
 - clocks: Should be the clock id of eFuse
 - clock-names: Should be "pclk_efuse"
 
+Deprecated properties:
+- compatible: "rockchip,rockchip-efuse"
+  Old efuse compatible value compatible to rk3066a, rk3188 and rk3288
+  efuses
+
 = Data cells =
 Are child nodes of eFuse, bindings of which as described in
 bindings/nvmem/nvmem.txt
@@ -13,7 +22,7 @@ bindings/nvmem/nvmem.txt
 Example:
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v3 0/3] nvmem: rockchip-efuse: support more rockchip SoCs

2016-08-26 Thread Finley Xiao
As the timing and organization of efuse may be different
between rockchip SoCs, so their read function may be different.
We add different device tree compatible string for rockchip SoCs
to match their own read function.
 
V2->V3:
- delete patch 3/4 in v2, don't add efuse0 device node
- 3/3 fix read data error sometimes by disable efuse redundancy

Finley Xiao (3):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 drivers/nvmem/rockchip-efuse.c | 131 ++---
 5 files changed, 126 insertions(+), 24 deletions(-)

-- 
1.9.1




[PATCH v3 2/3] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-08-26 Thread Finley Xiao
Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v3 0/3] nvmem: rockchip-efuse: support more rockchip SoCs

2016-08-26 Thread Finley Xiao
As the timing and organization of efuse may be different
between rockchip SoCs, so their read function may be different.
We add different device tree compatible string for rockchip SoCs
to match their own read function.
 
V2->V3:
- delete patch 3/4 in v2, don't add efuse0 device node
- 3/3 fix read data error sometimes by disable efuse redundancy

Finley Xiao (3):
  nvmem: rockchip-efuse: update compatible strings for Rockchip efuse
  ARM: dts: rockchip: update compatible strings for Rockchip efuse
  nvmem: rockchip-efuse: add rk3399-efuse support

 .../devicetree/bindings/nvmem/rockchip-efuse.txt   |  13 +-
 arch/arm/boot/dts/rk3066a.dtsi |   2 +-
 arch/arm/boot/dts/rk3188.dtsi  |   2 +-
 arch/arm/boot/dts/rk3288.dtsi  |   2 +-
 drivers/nvmem/rockchip-efuse.c | 131 ++---
 5 files changed, 126 insertions(+), 24 deletions(-)

-- 
1.9.1




[PATCH v3 2/3] ARM: dts: rockchip: update compatible strings for Rockchip efuse

2016-08-26 Thread Finley Xiao
Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 arch/arm/boot/dts/rk3066a.dtsi | 2 +-
 arch/arm/boot/dts/rk3188.dtsi  | 2 +-
 arch/arm/boot/dts/rk3288.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index c0ba86c..5387cc8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -162,7 +162,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3066a-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 31f81b2..869e189 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -147,7 +147,7 @@
};
 
efuse: efuse@2001 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3188-efuse";
reg = <0x2001 0x4000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index cd33f01..0eadb96 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -1073,7 +1073,7 @@
};
 
efuse: efuse@ffb4 {
-   compatible = "rockchip,rockchip-efuse";
+   compatible = "rockchip,rk3288-efuse";
reg = <0xffb4 0x20>;
#address-cells = <1>;
#size-cells = <1>;
-- 
1.9.1




[PATCH v3 3/3] nvmem: rockchip-efuse: add rk3399-efuse support

2016-08-26 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
 drivers/nvmem/rockchip-efuse.c | 131 +++--
 1 file changed, 112 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..2fb6c34 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,80 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+(~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
udelay(1);
}
 
/* Switch to standby mode */
-   writel(EFUSE_PGENB | EFUSE_CSB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   unsigned int out_value;
+   unsigned char *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) 

[PATCH v3 3/3] nvmem: rockchip-efuse: add rk3399-efuse support

2016-08-26 Thread Finley Xiao
1) the efuse timing of rk3399 is different from earlier SoCs.
2) rk3399-efuse is organized as 32bits by 32 one-time programmable
electrical fuses, the efuse of earlier SoCs is organized as 32bits
by 8 one-time programmable electrical fuses with random access interface.

This patch adds a new read function for rk3399-efuse.

Signed-off-by: Finley Xiao 
Reviewed-by: Heiko Stuebner 
---
 drivers/nvmem/rockchip-efuse.c | 131 +++--
 1 file changed, 112 insertions(+), 19 deletions(-)

diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index 4d3f391..2fb6c34 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -22,17 +22,29 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
-#define EFUSE_A_SHIFT  6
-#define EFUSE_A_MASK   0x3ff
-#define EFUSE_PGENBBIT(3)
-#define EFUSE_LOAD BIT(2)
-#define EFUSE_STROBE   BIT(1)
-#define EFUSE_CSB  BIT(0)
-
-#define REG_EFUSE_CTRL 0x
-#define REG_EFUSE_DOUT 0x0004
+#define RK3288_A_SHIFT 6
+#define RK3288_A_MASK  0x3ff
+#define RK3288_PGENB   BIT(3)
+#define RK3288_LOADBIT(2)
+#define RK3288_STROBE  BIT(1)
+#define RK3288_CSB BIT(0)
+
+#define RK3399_A_SHIFT 16
+#define RK3399_A_MASK  0x3ff
+#define RK3399_NBYTES  4
+#define RK3399_STROBSFTSEL BIT(9)
+#define RK3399_RSB BIT(7)
+#define RK3399_PD  BIT(5)
+#define RK3399_PGENB   BIT(3)
+#define RK3399_LOADBIT(2)
+#define RK3399_STROBE  BIT(1)
+#define RK3399_CSB BIT(0)
+
+#define REG_EFUSE_CTRL 0x
+#define REG_EFUSE_DOUT 0x0004
 
 struct rockchip_efuse_chip {
struct device *dev;
@@ -40,8 +52,8 @@ struct rockchip_efuse_chip {
struct clk *clk;
 };
 
-static int rockchip_efuse_read(void *context, unsigned int offset,
-  void *val, size_t bytes)
+static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
 {
struct rockchip_efuse_chip *efuse = context;
u8 *buf = val;
@@ -53,27 +65,80 @@ static int rockchip_efuse_read(void *context, unsigned int 
offset,
return ret;
}
 
-   writel(EFUSE_LOAD | EFUSE_PGENB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
udelay(1);
while (bytes--) {
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+(~(RK3288_A_MASK << RK3288_A_SHIFT)),
 efuse->base + REG_EFUSE_CTRL);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-((offset++ & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
 efuse->base + REG_EFUSE_CTRL);
udelay(1);
writel(readl(efuse->base + REG_EFUSE_CTRL) |
-EFUSE_STROBE, efuse->base + REG_EFUSE_CTRL);
+RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
udelay(1);
*buf++ = readb(efuse->base + REG_EFUSE_DOUT);
writel(readl(efuse->base + REG_EFUSE_CTRL) &
-(~EFUSE_STROBE), efuse->base + REG_EFUSE_CTRL);
+(~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
udelay(1);
}
 
/* Switch to standby mode */
-   writel(EFUSE_PGENB | EFUSE_CSB, efuse->base + REG_EFUSE_CTRL);
+   writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
+
+   clk_disable_unprepare(efuse->clk);
+
+   return 0;
+}
+
+static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+   struct rockchip_efuse_chip *efuse = context;
+   unsigned int addr_start, addr_end, addr_offset, addr_len;
+   unsigned int out_value;
+   unsigned char *buf;
+   int ret, i = 0;
+
+   ret = clk_prepare_enable(efuse->clk);
+   if (ret < 0) {
+   dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
+   return ret;
+   }
+
+   addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
+   addr_offset = offset % RK3399_NBYTES;
+   addr_len = addr_end - addr_start;
+
+   buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+  

Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-23 Thread Finley Xiao



在 2016/8/23 17:03, Heiko Stübner 写道:

Hi Finley,

Am Dienstag, 23. August 2016, 12:10:27 schrieb Finley Xiao:

在 2016/8/19 21:36, Rob Herring 写道:

On Tue, Aug 16, 2016 at 10:38:59AM +0800, Finlye Xiao wrote:

From: Finley Xiao <finley.x...@rock-chips.com>

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---

   .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
   drivers/power/avs/Kconfig  |   8 +
   drivers/power/avs/Makefile |   1 +
   drivers/power/avs/rockchip-cpu-avs.c   | 314
   + 4 files changed, 360 insertions(+)
   create mode 100644
   Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt create
   mode 100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt new file
mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and
match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .
+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

How do you determine these values? When do they vary?

How do you determine these values?

run antutu-benchmark
leakage freqmin_volt
30mA1608MHz 1025mV
40mA1608MHz 1000mV
50mA1608MHz 975mV

  From the table, we see the min_volt decrease with increasing leakage.
So we can set the default opp-microvolt 1025mV for 1608MHz,
and add an leakage_volt_cluster0 property as follows.
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)


;

If the leakage is between 41mA and 50mA,the opp-microvolt will subtract
25mV。 If the leakage is between 41mA and 50mA,the opp-microvolt will
subtract 50mV。

When do they vary?

  From the code,
cpufreq_online
--cpufreq_driver->init(policy);  /* add new opp table */
--blocking_notifier_call_chain(_policy_notifier_list,
CPUFREQ_START, policy);
--cpufreq_init_policy
cpufreq_set_policy
__cpufreq_governor(policy, CPUFREQ_GOV_START);

The cpu's opp table is added in the init function(cpufreq_init),and I will
register a cpufreq notifier, once the first cpu of cluster is onlined,
my notifer will be called, and if the event is CPUFREQ_START,it will modify
the opp-microvolt according to leakage_volt_cluster0.

I think what Rob was asking with "when do they vary" is, are these leakage
values the same for each and every rk3399 soc or are they determined
separately for each board-type using the rk3399.


Oh, sorry, I misunderstood.
They are the same for every rk3399 soc.









--
Finley




Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-23 Thread Finley Xiao



在 2016/8/23 17:03, Heiko Stübner 写道:

Hi Finley,

Am Dienstag, 23. August 2016, 12:10:27 schrieb Finley Xiao:

在 2016/8/19 21:36, Rob Herring 写道:

On Tue, Aug 16, 2016 at 10:38:59AM +0800, Finlye Xiao wrote:

From: Finley Xiao 

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao 
---

   .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
   drivers/power/avs/Kconfig  |   8 +
   drivers/power/avs/Makefile |   1 +
   drivers/power/avs/rockchip-cpu-avs.c   | 314
   + 4 files changed, 360 insertions(+)
   create mode 100644
   Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt create
   mode 100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt new file
mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and
match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .
+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

How do you determine these values? When do they vary?

How do you determine these values?

run antutu-benchmark
leakage freqmin_volt
30mA1608MHz 1025mV
40mA1608MHz 1000mV
50mA1608MHz 975mV

  From the table, we see the min_volt decrease with increasing leakage.
So we can set the default opp-microvolt 1025mV for 1608MHz,
and add an leakage_volt_cluster0 property as follows.
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)


;

If the leakage is between 41mA and 50mA,the opp-microvolt will subtract
25mV。 If the leakage is between 41mA and 50mA,the opp-microvolt will
subtract 50mV。

When do they vary?

  From the code,
cpufreq_online
--cpufreq_driver->init(policy);  /* add new opp table */
--blocking_notifier_call_chain(_policy_notifier_list,
CPUFREQ_START, policy);
--cpufreq_init_policy
cpufreq_set_policy
__cpufreq_governor(policy, CPUFREQ_GOV_START);

The cpu's opp table is added in the init function(cpufreq_init),and I will
register a cpufreq notifier, once the first cpu of cluster is onlined,
my notifer will be called, and if the event is CPUFREQ_START,it will modify
the opp-microvolt according to leakage_volt_cluster0.

I think what Rob was asking with "when do they vary" is, are these leakage
values the same for each and every rk3399 soc or are they determined
separately for each board-type using the rk3399.


Oh, sorry, I misunderstood.
They are the same for every rk3399 soc.









--
Finley




Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-22 Thread Finley Xiao



在 2016/8/19 21:36, Rob Herring 写道:

On Tue, Aug 16, 2016 at 10:38:59AM +0800, Finlye Xiao wrote:

From: Finley Xiao <finley.x...@rock-chips.com>

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>
---
  .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
  drivers/power/avs/Kconfig  |   8 +
  drivers/power/avs/Makefile |   1 +
  drivers/power/avs/rockchip-cpu-avs.c   | 314 +
  4 files changed, 360 insertions(+)
  create mode 100644 
Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
  create mode 100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt 
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
new file mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .
+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

How do you determine these values? When do they vary?


How do you determine these values?

run antutu-benchmark
leakage freqmin_volt
30mA1608MHz 1025mV
40mA1608MHz 1000mV
50mA1608MHz 975mV

From the table, we see the min_volt decrease with increasing leakage.
So we can set the default opp-microvolt 1025mV for 1608MHz,
and add an leakage_volt_cluster0 property as follows.
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)

;

If the leakage is between 41mA and 50mA,the opp-microvolt will subtract 25mV。
If the leakage is between 41mA and 50mA,the opp-microvolt will subtract 50mV。
 
When do they vary?


From the code,
cpufreq_online
--cpufreq_driver->init(policy);  /* add new opp table */
--blocking_notifier_call_chain(_policy_notifier_list,
CPUFREQ_START, policy);
--cpufreq_init_policy
cpufreq_set_policy
__cpufreq_governor(policy, CPUFREQ_GOV_START);

The cpu's opp table is added in the init function(cpufreq_init),and I will
register a cpufreq notifier, once the first cpu of cluster is onlined,
my notifer will be called, and if the event is CPUFREQ_START,it will modify
the opp-microvolt according to leakage_volt_cluster0.


+
+Example:
+
+   cpu_avs: cpu-avs {
+   compatible = "rockchip,rk3399-cpu-avs";

This isn't really a hardware block. For the same reasons we don't have
cpufreq nodes. So I don't think this belongs in DT.


if I delete the compatible property like the thermal-zones node, is it allowed?
cpu_avs: cpu-avs {
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)
>;
leakage_volt_cluster1 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)
>;
}




Rob





--
Finley




Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-22 Thread Finley Xiao



在 2016/8/19 21:36, Rob Herring 写道:

On Tue, Aug 16, 2016 at 10:38:59AM +0800, Finlye Xiao wrote:

From: Finley Xiao 

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao 
---
  .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
  drivers/power/avs/Kconfig  |   8 +
  drivers/power/avs/Makefile |   1 +
  drivers/power/avs/rockchip-cpu-avs.c   | 314 +
  4 files changed, 360 insertions(+)
  create mode 100644 
Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
  create mode 100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt 
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
new file mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .
+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

How do you determine these values? When do they vary?


How do you determine these values?

run antutu-benchmark
leakage freqmin_volt
30mA1608MHz 1025mV
40mA1608MHz 1000mV
50mA1608MHz 975mV

From the table, we see the min_volt decrease with increasing leakage.
So we can set the default opp-microvolt 1025mV for 1608MHz,
and add an leakage_volt_cluster0 property as follows.
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)

;

If the leakage is between 41mA and 50mA,the opp-microvolt will subtract 25mV。
If the leakage is between 41mA and 50mA,the opp-microvolt will subtract 50mV。
 
When do they vary?


From the code,
cpufreq_online
--cpufreq_driver->init(policy);  /* add new opp table */
--blocking_notifier_call_chain(_policy_notifier_list,
CPUFREQ_START, policy);
--cpufreq_init_policy
cpufreq_set_policy
__cpufreq_governor(policy, CPUFREQ_GOV_START);

The cpu's opp table is added in the init function(cpufreq_init),and I will
register a cpufreq notifier, once the first cpu of cluster is onlined,
my notifer will be called, and if the event is CPUFREQ_START,it will modify
the opp-microvolt according to leakage_volt_cluster0.


+
+Example:
+
+   cpu_avs: cpu-avs {
+   compatible = "rockchip,rk3399-cpu-avs";

This isn't really a hardware block. For the same reasons we don't have
cpufreq nodes. So I don't think this belongs in DT.


if I delete the compatible property like the thermal-zones node, is it allowed?
cpu_avs: cpu-avs {
leakage_volt_cluster0 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)
>;
leakage_volt_cluster1 = <
/*  min(mA)   max(mA)volt(uV)*/
0 400
4150(-25000)
51254   (-5)
>;
}




Rob





--
Finley




Re: [PATCH v1 2/3] of: Add support for reading a s32 from a multi-value property.

2016-08-22 Thread Finley Xiao



在 2016/8/20 4:47, David Woodhouse 写道:

On Fri, 2016-08-19 at 22:41 +0200, Heiko Stuebner wrote:

So no, don't *add* any more of these functions. Only add the generic
version. And if your driver isn't using the generic property
functions... fix it.

As far as I can see, all the device_property_* functions are grounded on their
of_property_*, acpi_property_* etc counterparts and functions reading specific
elements (the _index variants) are currently not available at all.

drivers/base/property.c:
#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) 
\
 (val) ? of_property_read_##type##_array((node), (propname), (val), 
(nval))  \
   : of_property_count_elems_of_size((node), (propname), 
sizeof(type))

So even if you're using the device_property_* functions you'd still need
a match in the underlying functions or am I missing something?

Yes, but the underlying function should never be used directly by
drivers. And should probably be prefixed with __ or marked deprecated
(with an override in its one genuine call site).



So can I add a device_property_read_s32_array function in property.h?

--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -108,6 +108,13 @@ static inline int device_property_read_u32(struct 
device *dev,

return device_property_read_u32_array(dev, propname, val, 1);
 }

+static inline int device_property_read_s32_array(struct device *dev, 
const char *propname,

+  s32 *val, size_t nval)
+{
+   return device_property_read_u32_array(struct device *dev, const 
char *propname,

+  (u32 *)val, size_t nval);
+}

--
Finley




Re: [PATCH v1 2/3] of: Add support for reading a s32 from a multi-value property.

2016-08-22 Thread Finley Xiao



在 2016/8/20 4:47, David Woodhouse 写道:

On Fri, 2016-08-19 at 22:41 +0200, Heiko Stuebner wrote:

So no, don't *add* any more of these functions. Only add the generic
version. And if your driver isn't using the generic property
functions... fix it.

As far as I can see, all the device_property_* functions are grounded on their
of_property_*, acpi_property_* etc counterparts and functions reading specific
elements (the _index variants) are currently not available at all.

drivers/base/property.c:
#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) 
\
 (val) ? of_property_read_##type##_array((node), (propname), (val), 
(nval))  \
   : of_property_count_elems_of_size((node), (propname), 
sizeof(type))

So even if you're using the device_property_* functions you'd still need
a match in the underlying functions or am I missing something?

Yes, but the underlying function should never be used directly by
drivers. And should probably be prefixed with __ or marked deprecated
(with an override in its one genuine call site).



So can I add a device_property_read_s32_array function in property.h?

--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -108,6 +108,13 @@ static inline int device_property_read_u32(struct 
device *dev,

return device_property_read_u32_array(dev, propname, val, 1);
 }

+static inline int device_property_read_s32_array(struct device *dev, 
const char *propname,

+  s32 *val, size_t nval)
+{
+   return device_property_read_u32_array(struct device *dev, const 
char *propname,

+  (u32 *)val, size_t nval);
+}

--
Finley




Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-17 Thread Finley Xiao



在 2016/8/17 1:24, Heiko Stübner 写道:

Hi Finley,

Am Dienstag, 16. August 2016, 10:38:59 schrieb Finlye Xiao:

From: Finley Xiao <finley.x...@rock-chips.com>

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao <finley.x...@rock-chips.com>

we of course talked about this before and it generally looks good, I just
found a bunch of smaller issues below.



---
  .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
  drivers/power/avs/Kconfig  |   8 +
  drivers/power/avs/Makefile |   1 +
  drivers/power/avs/rockchip-cpu-avs.c   | 314
+ 4 files changed, 360 insertions(+)
  create mode 100644
Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt create mode
100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt new file
mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt

the binding should generally be a separate patch, so that Rob and other
devicetree-maintainers can spot them better, so name it something like
dt-bindings: add binding document for Rockchip cpu avs
or similar.



@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .

vol -> volt ?


+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

vol -> volt?

maybe also make that
volt: voltage offset in mV to apply to the opp table entries



+
+Example:
+
+   cpu_avs: cpu-avs {
+   compatible = "rockchip,rk3399-cpu-avs";
+   leakage-volt-cluster0 = <
+   /*  mAmA uV*/
+   0 1000
+   101   200(-25000)
+   201   300(-5)
+   >;
+   leakage-volt-cluster1 = <
+   /*  mAmA uV*/
+   0 1000
+   101   200(-25000)
+   201   300(-5)
+   >;
+   };
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
index a67eeac..c8f2d09 100644
--- a/drivers/power/avs/Kconfig
+++ b/drivers/power/avs/Kconfig
@@ -18,3 +18,11 @@ config ROCKCHIP_IODOMAIN
Say y here to enable support io domains on Rockchip SoCs. It is
necessary for the io domain setting of the SoC to match the
voltage supplied by the regulators.
+
+config ROCKCHIP_CPU_AVS
+bool "Rockchip CPU AVS support"
+depends on POWER_AVS && ARCH_ROCKCHIP && OF

as the kbuild-robot found out, you'll need as well a
depends on CPU_FREQ

also, I don't know if this also applies to the rk3288 and before (arm32), but
if so and with your generic depends on ARCH_ROCKCHIP, you'd also need a
depends on ARM_CPU_TOPOLOGY if ARM

as the topology-stuff is not always active on arm32.



+help
+  Say y here to enable support CPU AVS on Rockchip SoCs.
+  The cpu's operating voltage is adapted depending on leakage
+  or pvtm.
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
index ba4c7bc..11ce242 100644
--- a/drivers/power/avs/Makefile
+++ b/drivers/power/avs/Makefile
@@ -1,2 +1,3 @@
  obj-$(CONFIG_POWER_AVS_OMAP)  += smartreflex.o
  obj-$(CONFIG_ROCKCHIP_IODOMAIN)   += rockchip-io-domain.o
+obj-$(CONFIG_ROCKCHIP_CPU_AVS) += rockchip-cpu-avs.o
diff --git a/drivers/power/avs/rockchip-cpu-avs.c
b/drivers/power/avs/rockchip-cpu-avs.c new file mode 100644
index 000..8266c02
--- /dev/null
+++ b/drivers/power/avs/rockchip-cpu-avs.c
@@ -0,0 +1,314 @@
+/*
+ * Rockchip CPU AVS support.
+ *
+ * Copyright (c) 2016 ROCKCHIP, Co. Ltd.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

copy'n'pasted from somewhere? Should probably not be here



+#include 
+#include 
+#include 
+#include 
+#include 
+#include 

Re: [PATCH v1 3/3] PM / AVS: rockchip-cpu-avs: add driver handling Rockchip cpu avs

2016-08-17 Thread Finley Xiao



在 2016/8/17 1:24, Heiko Stübner 写道:

Hi Finley,

Am Dienstag, 16. August 2016, 10:38:59 schrieb Finlye Xiao:

From: Finley Xiao 

This patch supports adjusting opp's voltage according to leakage

Signed-off-by: Finley Xiao 

we of course talked about this before and it generally looks good, I just
found a bunch of smaller issues below.



---
  .../devicetree/bindings/power/rockchip-cpu-avs.txt |  37 +++
  drivers/power/avs/Kconfig  |   8 +
  drivers/power/avs/Makefile |   1 +
  drivers/power/avs/rockchip-cpu-avs.c   | 314
+ 4 files changed, 360 insertions(+)
  create mode 100644
Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt create mode
100644 drivers/power/avs/rockchip-cpu-avs.c

diff --git a/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt
b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt new file
mode 100644
index 000..90f6b08
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rockchip-cpu-avs.txt

the binding should generally be a separate patch, so that Rob and other
devicetree-maintainers can spot them better, so name it something like
dt-bindings: add binding document for Rockchip cpu avs
or similar.



@@ -0,0 +1,37 @@
+Rockchip cpu avs device tree bindings
+-
+
+Under the same frequency, the operating voltage tends to decrease with
+increasing leakage. so it is necessary to adjust opp's voltage according
+to leakage for power.
+
+
+Required properties:
+- compatible: Should be one of the following.
+  - "rockchip,rk3399-cpu-avs" - for RK3399 SoCs.
+- leakage-volt-: Named leakage-volt property. At runtime, the
+  platform can find a cpu's cluster_id according to it's cpu_id and match
+  leakage-volt- property. The property is an array of 3-tuples
+  items, and each item consists of leakage and voltage like
+  .

vol -> volt ?


+   min-leakage: minimum leakage in mA.
+   max-leakage: maximum leakage in mA.
+   vol: voltage in microvolt.

vol -> volt?

maybe also make that
volt: voltage offset in mV to apply to the opp table entries



+
+Example:
+
+   cpu_avs: cpu-avs {
+   compatible = "rockchip,rk3399-cpu-avs";
+   leakage-volt-cluster0 = <
+   /*  mAmA uV*/
+   0 1000
+   101   200(-25000)
+   201   300(-5)
+   >;
+   leakage-volt-cluster1 = <
+   /*  mAmA uV*/
+   0 1000
+   101   200(-25000)
+   201   300(-5)
+   >;
+   };
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
index a67eeac..c8f2d09 100644
--- a/drivers/power/avs/Kconfig
+++ b/drivers/power/avs/Kconfig
@@ -18,3 +18,11 @@ config ROCKCHIP_IODOMAIN
Say y here to enable support io domains on Rockchip SoCs. It is
necessary for the io domain setting of the SoC to match the
voltage supplied by the regulators.
+
+config ROCKCHIP_CPU_AVS
+bool "Rockchip CPU AVS support"
+depends on POWER_AVS && ARCH_ROCKCHIP && OF

as the kbuild-robot found out, you'll need as well a
depends on CPU_FREQ

also, I don't know if this also applies to the rk3288 and before (arm32), but
if so and with your generic depends on ARCH_ROCKCHIP, you'd also need a
depends on ARM_CPU_TOPOLOGY if ARM

as the topology-stuff is not always active on arm32.



+help
+  Say y here to enable support CPU AVS on Rockchip SoCs.
+  The cpu's operating voltage is adapted depending on leakage
+  or pvtm.
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
index ba4c7bc..11ce242 100644
--- a/drivers/power/avs/Makefile
+++ b/drivers/power/avs/Makefile
@@ -1,2 +1,3 @@
  obj-$(CONFIG_POWER_AVS_OMAP)  += smartreflex.o
  obj-$(CONFIG_ROCKCHIP_IODOMAIN)   += rockchip-io-domain.o
+obj-$(CONFIG_ROCKCHIP_CPU_AVS) += rockchip-cpu-avs.o
diff --git a/drivers/power/avs/rockchip-cpu-avs.c
b/drivers/power/avs/rockchip-cpu-avs.c new file mode 100644
index 000..8266c02
--- /dev/null
+++ b/drivers/power/avs/rockchip-cpu-avs.c
@@ -0,0 +1,314 @@
+/*
+ * Rockchip CPU AVS support.
+ *
+ * Copyright (c) 2016 ROCKCHIP, Co. Ltd.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

copy'n'pasted from somewhere? Should probably not be here



+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+

Re: [PATCH v2] cpufreq: rockchip: add driver

2016-03-24 Thread Finley Xiao

Hi Viresh,

can we add a of_match_table with a common compatible name as follows ?

--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -470,10 +470,16 @@ static int dt_cpufreq_remove(struct 
platform_device *pdev)

cpufreq_unregister_driver(_cpufreq_driver);
return 0;
 }
+static const struct of_device_id dt_cpufreq_of_match[] = {
+   { .compatible = "***,***", },
+   { }
+};
+MODULE_DEVICE_TABLE(of, dt_cpufreq_of_match);
 static struct platform_driver dt_cpufreq_platdrv = {
.driver = {
.name   = "cpufreq-dt",
+   .of_match_table = dt_cpufreq_of_match,
},

--- a/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+   cpufreq {
+   compatible = "***,***";
+   }

Does it create a DT node for a dummy device too ?


在 2016/3/24 14:43, Viresh Kumar 写道:

On 24-03-16, 11:01, Feng Xiao wrote:

hi all,
  I found that it could match the cpufreq-dt driver succesfully only with
the following changes.
--- a/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3366.dtsi
@@ -139,6 +139,10 @@
 };
 };

+   cpufreq-dt {   //the node name must be cpufreq-dt
+   compatible = "rockchip,cpufreq";  //  the compatible name is
insignificant
+   };
+

Its not allowed to create a DT node for a dummy device and so we never
followed this way.

I have just sent a patchset and cc'd you:
"[PATCH 0/3] cpufreq: dt: Create platform device from generic code"

and so this patch shall get replaced now.



--
Finley




Re: [PATCH v2] cpufreq: rockchip: add driver

2016-03-24 Thread Finley Xiao

Hi Viresh,

can we add a of_match_table with a common compatible name as follows ?

--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -470,10 +470,16 @@ static int dt_cpufreq_remove(struct 
platform_device *pdev)

cpufreq_unregister_driver(_cpufreq_driver);
return 0;
 }
+static const struct of_device_id dt_cpufreq_of_match[] = {
+   { .compatible = "***,***", },
+   { }
+};
+MODULE_DEVICE_TABLE(of, dt_cpufreq_of_match);
 static struct platform_driver dt_cpufreq_platdrv = {
.driver = {
.name   = "cpufreq-dt",
+   .of_match_table = dt_cpufreq_of_match,
},

--- a/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+   cpufreq {
+   compatible = "***,***";
+   }

Does it create a DT node for a dummy device too ?


在 2016/3/24 14:43, Viresh Kumar 写道:

On 24-03-16, 11:01, Feng Xiao wrote:

hi all,
  I found that it could match the cpufreq-dt driver succesfully only with
the following changes.
--- a/arch/arm64/boot/dts/rockchip/rk3366.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3366.dtsi
@@ -139,6 +139,10 @@
 };
 };

+   cpufreq-dt {   //the node name must be cpufreq-dt
+   compatible = "rockchip,cpufreq";  //  the compatible name is
insignificant
+   };
+

Its not allowed to create a DT node for a dummy device and so we never
followed this way.

I have just sent a patchset and cc'd you:
"[PATCH 0/3] cpufreq: dt: Create platform device from generic code"

and so this patch shall get replaced now.



--
Finley