All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] PWM changes for rk3288-evb
@ 2014-08-18 17:09 ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: Sonny Rao, olof, Eddie Cai, Doug Anderson, mark.rutland,
	linux-pwm, linux, pawel.moll, ijc+devicetree, linux-kernel,
	devicetree, robh+dt, galak, linux-arm-kernel

These patches enable the pwm backlight for the rk3288-evb board.
There were tested by watching the backlight grow from off to max with
the following instructions:

  cd /sys/class/backlight/backlight*/
  for i in $(seq 255); do echo $i > brightness; sleep .01; done

The first patch enables the proper IP.  I think it could land in
Heiko's tree.

The second patch switches PWM cells from 2 to 3 on rk3288.  I think it
could land in Thierry's tree.  With the PWM subsystem as currently
structured, I believe this will break backward compatibility.  However
the rk3288 PWM driver was added so recently (and the rk3288 is so new)
that this seems OK.  In the worst case if someone yells that they are
broken, I believe we could fix this in Linux by saying that if a PWM
driver specifies 3 cells and the DTS definition of the PWM says 2
cells that we'll just pretend that we have no flags.

The 3rd and 4th patches are DTS ones.  They could land in Heiko's tree
after the second patch has landed.  They are based atop his current
WIP 3.18 dts tree.  Note that instantiating the PWM backlight will
cause the system to hang unless Heiko's (clk: rockchip: protect
critical clocks from getting disabled)
<patchwork.kernel.org/patch/4725391> is landed.

There are no compile time or runtime dependencies between these
patches except that patch #3 needs to come before patch #4.  ...and of
course the PWM won't work without all 4 patches.


Doug Anderson (4):
  ARM: rockchip: rk3288: Switch to use the proper PWM IP
  pwm: rockchip: Allow polarity invert on rk3288
  ARM: dts: Add main PWM info to rk3288
  ARM: dts: Enable pwm backlight on rk3288-EVB

 .../devicetree/bindings/pwm/pwm-rockchip.txt       |  4 +-
 arch/arm/boot/dts/rk3288-evb.dtsi                  | 53 +++++++++++++++++
 arch/arm/boot/dts/rk3288.dtsi                      | 68 ++++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c                  | 19 ++++++
 drivers/pwm/pwm-rockchip.c                         | 32 +++++++++-
 5 files changed, 172 insertions(+), 4 deletions(-)

-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 0/4] PWM changes for rk3288-evb
@ 2014-08-18 17:09 ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

These patches enable the pwm backlight for the rk3288-evb board.
There were tested by watching the backlight grow from off to max with
the following instructions:

  cd /sys/class/backlight/backlight*/
  for i in $(seq 255); do echo $i > brightness; sleep .01; done

The first patch enables the proper IP.  I think it could land in
Heiko's tree.

The second patch switches PWM cells from 2 to 3 on rk3288.  I think it
could land in Thierry's tree.  With the PWM subsystem as currently
structured, I believe this will break backward compatibility.  However
the rk3288 PWM driver was added so recently (and the rk3288 is so new)
that this seems OK.  In the worst case if someone yells that they are
broken, I believe we could fix this in Linux by saying that if a PWM
driver specifies 3 cells and the DTS definition of the PWM says 2
cells that we'll just pretend that we have no flags.

The 3rd and 4th patches are DTS ones.  They could land in Heiko's tree
after the second patch has landed.  They are based atop his current
WIP 3.18 dts tree.  Note that instantiating the PWM backlight will
cause the system to hang unless Heiko's (clk: rockchip: protect
critical clocks from getting disabled)
<patchwork.kernel.org/patch/4725391> is landed.

There are no compile time or runtime dependencies between these
patches except that patch #3 needs to come before patch #4.  ...and of
course the PWM won't work without all 4 patches.


Doug Anderson (4):
  ARM: rockchip: rk3288: Switch to use the proper PWM IP
  pwm: rockchip: Allow polarity invert on rk3288
  ARM: dts: Add main PWM info to rk3288
  ARM: dts: Enable pwm backlight on rk3288-EVB

 .../devicetree/bindings/pwm/pwm-rockchip.txt       |  4 +-
 arch/arm/boot/dts/rk3288-evb.dtsi                  | 53 +++++++++++++++++
 arch/arm/boot/dts/rk3288.dtsi                      | 68 ++++++++++++++++++++++
 arch/arm/mach-rockchip/rockchip.c                  | 19 ++++++
 drivers/pwm/pwm-rockchip.c                         | 32 +++++++++-
 5 files changed, 172 insertions(+), 4 deletions(-)

-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-18 17:09 ` Doug Anderson
@ 2014-08-18 17:09   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: Sonny Rao, olof, Eddie Cai, Doug Anderson, linux,
	linux-arm-kernel, linux-kernel

The rk3288 SoC has an option to switch all of the PWMs in the system
between the old IP block and the new IP block.  The new IP block is
working and tested and the suggested PWM to use, so setup the SoC to
use it and then we can pretend that the other IP block doesn't exist.

This code could go lots of other places, but we've put it here.  Why?
- Pushing it to the bootloader just makes the code harder to update in
  the field.  If we later find a bug in the new IP block and want to
  change our mind about what to use we want it to be easy to update.
- Putting this code in the driver for IP block is a lot of extra work,
  device tree bindings, etc.  Now that the new IP block is validated
  it's likely no future SoCs will need this code.  Why pollute the PWM
  driver with this?  This is an rk3288 thing so it should be in rk3288
  code.
- There's a single bit that switches over PWMs, which makes it extra
  hard to put this under the PWM device tree nodes.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 8ab9e0e..99133b9 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -24,6 +24,24 @@
 #include <asm/hardware/cache-l2x0.h>
 #include "core.h"
 
+static void __init rk3288_init_machine(void)
+{
+	void *grf = ioremap(0xff770000, 0x10000);
+
+	/* Set pwm_sel to RK design PWM in GRF_SOC_CON2; affects all PWMs */
+	writel(0x00010001, grf + 0x24c);
+
+	iounmap(grf);
+}
+
+static void __init rockchip_init_machine(void)
+{
+	if (of_machine_is_compatible("rockchip,rk3288"))
+		rk3288_init_machine();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
 static const char * const rockchip_board_dt_compat[] = {
 	"rockchip,rk2928",
 	"rockchip,rk3066a",
@@ -34,6 +52,7 @@ static const char * const rockchip_board_dt_compat[] = {
 };
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+	.init_machine	= rockchip_init_machine,
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
 	.dt_compat	= rockchip_board_dt_compat,
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-18 17:09   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

The rk3288 SoC has an option to switch all of the PWMs in the system
between the old IP block and the new IP block.  The new IP block is
working and tested and the suggested PWM to use, so setup the SoC to
use it and then we can pretend that the other IP block doesn't exist.

This code could go lots of other places, but we've put it here.  Why?
- Pushing it to the bootloader just makes the code harder to update in
  the field.  If we later find a bug in the new IP block and want to
  change our mind about what to use we want it to be easy to update.
- Putting this code in the driver for IP block is a lot of extra work,
  device tree bindings, etc.  Now that the new IP block is validated
  it's likely no future SoCs will need this code.  Why pollute the PWM
  driver with this?  This is an rk3288 thing so it should be in rk3288
  code.
- There's a single bit that switches over PWMs, which makes it extra
  hard to put this under the PWM device tree nodes.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 8ab9e0e..99133b9 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -24,6 +24,24 @@
 #include <asm/hardware/cache-l2x0.h>
 #include "core.h"
 
+static void __init rk3288_init_machine(void)
+{
+	void *grf = ioremap(0xff770000, 0x10000);
+
+	/* Set pwm_sel to RK design PWM in GRF_SOC_CON2; affects all PWMs */
+	writel(0x00010001, grf + 0x24c);
+
+	iounmap(grf);
+}
+
+static void __init rockchip_init_machine(void)
+{
+	if (of_machine_is_compatible("rockchip,rk3288"))
+		rk3288_init_machine();
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
 static const char * const rockchip_board_dt_compat[] = {
 	"rockchip,rk2928",
 	"rockchip,rk3066a",
@@ -34,6 +52,7 @@ static const char * const rockchip_board_dt_compat[] = {
 };
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+	.init_machine	= rockchip_init_machine,
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
 	.dt_compat	= rockchip_board_dt_compat,
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
  2014-08-18 17:09 ` Doug Anderson
  (?)
@ 2014-08-18 17:09   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: Sonny Rao, olof, Eddie Cai, Doug Anderson, robh+dt, pawel.moll,
	mark.rutland, ijc+devicetree, galak, linux-pwm, devicetree,
	linux-kernel, linux-arm-kernel

The rk3288 has the ability to invert the polarity of the PWM.  Let's
enable that ability.

To do this we increase the number of pwm_cells to 3 to allow using the
PWM_POLARITY_INVERTED flag.  Since the PWM driver on rk3288 is very
new, I thought this was OK.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 .../devicetree/bindings/pwm/pwm-rockchip.txt       |  4 +--
 drivers/pwm/pwm-rockchip.c                         | 32 ++++++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
index d47d15a..b8be3d0 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -7,8 +7,8 @@ Required properties:
    "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
- - #pwm-cells: should be 2. See pwm.txt in this directory for a
-   description of the cell format.
+ - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
+   for a description of the cell format.
 
 Example:
 
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index bdd8644..27f20d6 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -24,7 +24,9 @@
 #define PWM_ENABLE		(1 << 0)
 #define PWM_CONTINUOUS		(1 << 1)
 #define PWM_DUTY_POSITIVE	(1 << 3)
+#define PWM_DUTY_NEGATIVE	(0 << 3)
 #define PWM_INACTIVE_NEGATIVE	(0 << 4)
+#define PWM_INACTIVE_POSITIVE	(1 << 4)
 #define PWM_OUTPUT_LEFT		(0 << 5)
 #define PWM_LP_DISABLE		(0 << 8)
 
@@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
 	struct pwm_chip chip;
 	struct clk *clk;
 	const struct rockchip_pwm_data *data;
+	enum pwm_polarity polarity;
 	void __iomem *base;
 };
 
@@ -45,6 +48,7 @@ struct rockchip_pwm_regs {
 struct rockchip_pwm_data {
 	struct rockchip_pwm_regs regs;
 	unsigned int prescaler;
+	bool has_invert;
 
 	void (*set_enable)(struct pwm_chip *chip, bool enable);
 };
@@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
 	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
-			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
-			  PWM_INACTIVE_NEGATIVE;
+			  PWM_CONTINUOUS;
 	u32 val;
 
+	if (pc->polarity == PWM_POLARITY_INVERSED)
+		enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
+	else
+		enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
+
 	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
 
 	if (enable)
@@ -124,6 +132,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	return 0;
 }
 
+int rockchip_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+			      enum pwm_polarity polarity)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+
+	if (!pc->data->has_invert)
+		return -ENOSYS;
+
+	pc->polarity = polarity;
+
+	return 0;
+}
+
 static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
@@ -149,6 +170,7 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static const struct pwm_ops rockchip_pwm_ops = {
 	.config = rockchip_pwm_config,
+	.set_polarity = rockchip_pwm_set_polarity,
 	.enable = rockchip_pwm_enable,
 	.disable = rockchip_pwm_disable,
 	.owner = THIS_MODULE,
@@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
 		.ctrl = 0x0c,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -184,6 +207,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
 		.ctrl = 0x00,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
 	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
+	if (pc->data->has_invert) {
+		pc->chip.of_xlate = of_pwm_xlate_with_flags;
+		pc->chip.of_pwm_n_cells = 3;
+	}
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
 
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-18 17:09   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: mark.rutland, linux-pwm, pawel.moll, ijc+devicetree,
	Doug Anderson, linux-kernel, devicetree, robh+dt, Eddie Cai,
	galak, olof, Sonny Rao, linux-arm-kernel

The rk3288 has the ability to invert the polarity of the PWM.  Let's
enable that ability.

To do this we increase the number of pwm_cells to 3 to allow using the
PWM_POLARITY_INVERTED flag.  Since the PWM driver on rk3288 is very
new, I thought this was OK.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 .../devicetree/bindings/pwm/pwm-rockchip.txt       |  4 +--
 drivers/pwm/pwm-rockchip.c                         | 32 ++++++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
index d47d15a..b8be3d0 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -7,8 +7,8 @@ Required properties:
    "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
- - #pwm-cells: should be 2. See pwm.txt in this directory for a
-   description of the cell format.
+ - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
+   for a description of the cell format.
 
 Example:
 
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index bdd8644..27f20d6 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -24,7 +24,9 @@
 #define PWM_ENABLE		(1 << 0)
 #define PWM_CONTINUOUS		(1 << 1)
 #define PWM_DUTY_POSITIVE	(1 << 3)
+#define PWM_DUTY_NEGATIVE	(0 << 3)
 #define PWM_INACTIVE_NEGATIVE	(0 << 4)
+#define PWM_INACTIVE_POSITIVE	(1 << 4)
 #define PWM_OUTPUT_LEFT		(0 << 5)
 #define PWM_LP_DISABLE		(0 << 8)
 
@@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
 	struct pwm_chip chip;
 	struct clk *clk;
 	const struct rockchip_pwm_data *data;
+	enum pwm_polarity polarity;
 	void __iomem *base;
 };
 
@@ -45,6 +48,7 @@ struct rockchip_pwm_regs {
 struct rockchip_pwm_data {
 	struct rockchip_pwm_regs regs;
 	unsigned int prescaler;
+	bool has_invert;
 
 	void (*set_enable)(struct pwm_chip *chip, bool enable);
 };
@@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
 	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
-			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
-			  PWM_INACTIVE_NEGATIVE;
+			  PWM_CONTINUOUS;
 	u32 val;
 
+	if (pc->polarity == PWM_POLARITY_INVERSED)
+		enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
+	else
+		enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
+
 	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
 
 	if (enable)
@@ -124,6 +132,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	return 0;
 }
 
+int rockchip_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+			      enum pwm_polarity polarity)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+
+	if (!pc->data->has_invert)
+		return -ENOSYS;
+
+	pc->polarity = polarity;
+
+	return 0;
+}
+
 static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
@@ -149,6 +170,7 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static const struct pwm_ops rockchip_pwm_ops = {
 	.config = rockchip_pwm_config,
+	.set_polarity = rockchip_pwm_set_polarity,
 	.enable = rockchip_pwm_enable,
 	.disable = rockchip_pwm_disable,
 	.owner = THIS_MODULE,
@@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
 		.ctrl = 0x0c,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -184,6 +207,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
 		.ctrl = 0x00,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
 	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
+	if (pc->data->has_invert) {
+		pc->chip.of_xlate = of_pwm_xlate_with_flags;
+		pc->chip.of_pwm_n_cells = 3;
+	}
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
 
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-18 17:09   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

The rk3288 has the ability to invert the polarity of the PWM.  Let's
enable that ability.

To do this we increase the number of pwm_cells to 3 to allow using the
PWM_POLARITY_INVERTED flag.  Since the PWM driver on rk3288 is very
new, I thought this was OK.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 .../devicetree/bindings/pwm/pwm-rockchip.txt       |  4 +--
 drivers/pwm/pwm-rockchip.c                         | 32 ++++++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
index d47d15a..b8be3d0 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -7,8 +7,8 @@ Required properties:
    "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
- - #pwm-cells: should be 2. See pwm.txt in this directory for a
-   description of the cell format.
+ - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
+   for a description of the cell format.
 
 Example:
 
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index bdd8644..27f20d6 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -24,7 +24,9 @@
 #define PWM_ENABLE		(1 << 0)
 #define PWM_CONTINUOUS		(1 << 1)
 #define PWM_DUTY_POSITIVE	(1 << 3)
+#define PWM_DUTY_NEGATIVE	(0 << 3)
 #define PWM_INACTIVE_NEGATIVE	(0 << 4)
+#define PWM_INACTIVE_POSITIVE	(1 << 4)
 #define PWM_OUTPUT_LEFT		(0 << 5)
 #define PWM_LP_DISABLE		(0 << 8)
 
@@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
 	struct pwm_chip chip;
 	struct clk *clk;
 	const struct rockchip_pwm_data *data;
+	enum pwm_polarity polarity;
 	void __iomem *base;
 };
 
@@ -45,6 +48,7 @@ struct rockchip_pwm_regs {
 struct rockchip_pwm_data {
 	struct rockchip_pwm_regs regs;
 	unsigned int prescaler;
+	bool has_invert;
 
 	void (*set_enable)(struct pwm_chip *chip, bool enable);
 };
@@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
 	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
-			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
-			  PWM_INACTIVE_NEGATIVE;
+			  PWM_CONTINUOUS;
 	u32 val;
 
+	if (pc->polarity == PWM_POLARITY_INVERSED)
+		enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
+	else
+		enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
+
 	val = readl_relaxed(pc->base + pc->data->regs.ctrl);
 
 	if (enable)
@@ -124,6 +132,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	return 0;
 }
 
+int rockchip_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+			      enum pwm_polarity polarity)
+{
+	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+
+	if (!pc->data->has_invert)
+		return -ENOSYS;
+
+	pc->polarity = polarity;
+
+	return 0;
+}
+
 static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
@@ -149,6 +170,7 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static const struct pwm_ops rockchip_pwm_ops = {
 	.config = rockchip_pwm_config,
+	.set_polarity = rockchip_pwm_set_polarity,
 	.enable = rockchip_pwm_enable,
 	.disable = rockchip_pwm_disable,
 	.owner = THIS_MODULE,
@@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
 		.ctrl = 0x0c,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -184,6 +207,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
 		.ctrl = 0x00,
 	},
 	.prescaler = 1,
+	.has_invert = 1,
 	.set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
 	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
+	if (pc->data->has_invert) {
+		pc->chip.of_xlate = of_pwm_xlate_with_flags;
+		pc->chip.of_pwm_n_cells = 3;
+	}
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
 
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 3/4] ARM: dts: Add main PWM info to rk3288
  2014-08-18 17:09 ` Doug Anderson
@ 2014-08-18 17:09   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: Sonny Rao, olof, Eddie Cai, Doug Anderson, robh+dt, pawel.moll,
	mark.rutland, ijc+devicetree, galak, linux, devicetree,
	linux-arm-kernel, linux-kernel

This adds the PWM info (other than the VOP PWM) to the main rk3288
dtsi file.

Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288.dtsi | 68 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 36be7bb..9c9d9c5 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -261,6 +261,50 @@
 		status = "disabled";
 	};
 
+	pwm0: pwm@ff680000 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680000 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm1: pwm@ff680010 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680010 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm2: pwm@ff680020 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680020 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm3: pwm@ff680030 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680030 0x10>;
+		#pwm-cells = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
 	pmu: power-management@ff730000 {
 		compatible = "rockchip,rk3288-pmu", "syscon";
 		reg = <0xff730000 0x100>;
@@ -611,5 +655,29 @@
 				rockchip,pins = <5 15 3 &pcfg_pull_none>;
 			};
 		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins = <7 0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins = <7 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins = <7 22 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_pin: pwm3-pin {
+				rockchip,pins = <7 23 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
 	};
 };
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 3/4] ARM: dts: Add main PWM info to rk3288
@ 2014-08-18 17:09   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

This adds the PWM info (other than the VOP PWM) to the main rk3288
dtsi file.

Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288.dtsi | 68 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 36be7bb..9c9d9c5 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -261,6 +261,50 @@
 		status = "disabled";
 	};
 
+	pwm0: pwm at ff680000 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680000 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm1: pwm at ff680010 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680010 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm2: pwm at ff680020 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680020 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm3: pwm at ff680030 {
+		compatible = "rockchip,rk3288-pwm";
+		reg = <0xff680030 0x10>;
+		#pwm-cells = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3_pin>;
+		clocks = <&cru PCLK_PWM>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
 	pmu: power-management at ff730000 {
 		compatible = "rockchip,rk3288-pmu", "syscon";
 		reg = <0xff730000 0x100>;
@@ -611,5 +655,29 @@
 				rockchip,pins = <5 15 3 &pcfg_pull_none>;
 			};
 		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins = <7 0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins = <7 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins = <7 22 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_pin: pwm3-pin {
+				rockchip,pins = <7 23 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
 	};
 };
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
  2014-08-18 17:09 ` Doug Anderson
@ 2014-08-18 17:09   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: Heiko Stuebner, Thierry Reding, Caesar Wang
  Cc: Sonny Rao, olof, Eddie Cai, Doug Anderson, robh+dt, pawel.moll,
	mark.rutland, ijc+devicetree, galak, linux, devicetree,
	linux-arm-kernel, linux-kernel

The pwm0 is the PWM associated with the LCD backlight.  Enable it.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
index 2964370..242e1a9 100644
--- a/arch/arm/boot/dts/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/pwm/pwm.h>
 #include "rk3288.dtsi"
 
 / {
@@ -17,6 +18,48 @@
 		reg = <0x0 0x80000000>;
 	};
 
+        backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <128>;
+		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en>;
+		pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
+        };
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		#address-cells = <1>;
@@ -81,6 +124,10 @@
 	status = "okay";
 };
 
+&pwm0 {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
@@ -102,6 +149,12 @@
 };
 
 &pinctrl {
+	backlight {
+		bl_en: bl-en {
+			rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	buttons {
 		pwrbtn: pwrbtn {
 			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
-- 
2.1.0.rc2.206.gedb03e5


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-18 17:09   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

The pwm0 is the PWM associated with the LCD backlight.  Enable it.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
index 2964370..242e1a9 100644
--- a/arch/arm/boot/dts/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/pwm/pwm.h>
 #include "rk3288.dtsi"
 
 / {
@@ -17,6 +18,48 @@
 		reg = <0x0 0x80000000>;
 	};
 
+        backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <128>;
+		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en>;
+		pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
+        };
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		#address-cells = <1>;
@@ -81,6 +124,10 @@
 	status = "okay";
 };
 
+&pwm0 {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
@@ -102,6 +149,12 @@
 };
 
 &pinctrl {
+	backlight {
+		bl_en: bl-en {
+			rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	buttons {
 		pwrbtn: pwrbtn {
 			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-18 17:09   ` Doug Anderson
@ 2014-08-18 17:11     ` Sonny Rao
  -1 siblings, 0 replies; 69+ messages in thread
From: Sonny Rao @ 2014-08-18 17:11 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Thierry Reding, Caesar Wang, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

On Mon, Aug 18, 2014 at 10:09 AM, Doug Anderson <dianders@chromium.org> wrote:
> The rk3288 SoC has an option to switch all of the PWMs in the system
> between the old IP block and the new IP block.  The new IP block is
> working and tested and the suggested PWM to use, so setup the SoC to
> use it and then we can pretend that the other IP block doesn't exist.
>
> This code could go lots of other places, but we've put it here.  Why?
> - Pushing it to the bootloader just makes the code harder to update in
>   the field.  If we later find a bug in the new IP block and want to
>   change our mind about what to use we want it to be easy to update.
> - Putting this code in the driver for IP block is a lot of extra work,
>   device tree bindings, etc.  Now that the new IP block is validated
>   it's likely no future SoCs will need this code.  Why pollute the PWM
>   driver with this?  This is an rk3288 thing so it should be in rk3288
>   code.
> - There's a single bit that switches over PWMs, which makes it extra
>   hard to put this under the PWM device tree nodes.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> index 8ab9e0e..99133b9 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -24,6 +24,24 @@
>  #include <asm/hardware/cache-l2x0.h>
>  #include "core.h"
>
> +static void __init rk3288_init_machine(void)
> +{
> +       void *grf = ioremap(0xff770000, 0x10000);

Is it worth checking for failure here?  Will the system boot without this?

> +
> +       /* Set pwm_sel to RK design PWM in GRF_SOC_CON2; affects all PWMs */
> +       writel(0x00010001, grf + 0x24c);
> +
> +       iounmap(grf);
> +}
> +
> +static void __init rockchip_init_machine(void)
> +{
> +       if (of_machine_is_compatible("rockchip,rk3288"))
> +               rk3288_init_machine();
> +
> +       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +}
> +
>  static const char * const rockchip_board_dt_compat[] = {
>         "rockchip,rk2928",
>         "rockchip,rk3066a",
> @@ -34,6 +52,7 @@ static const char * const rockchip_board_dt_compat[] = {
>  };
>
>  DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
> +       .init_machine   = rockchip_init_machine,
>         .l2c_aux_val    = 0,
>         .l2c_aux_mask   = ~0,
>         .dt_compat      = rockchip_board_dt_compat,
> --
> 2.1.0.rc2.206.gedb03e5
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-18 17:11     ` Sonny Rao
  0 siblings, 0 replies; 69+ messages in thread
From: Sonny Rao @ 2014-08-18 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:09 AM, Doug Anderson <dianders@chromium.org> wrote:
> The rk3288 SoC has an option to switch all of the PWMs in the system
> between the old IP block and the new IP block.  The new IP block is
> working and tested and the suggested PWM to use, so setup the SoC to
> use it and then we can pretend that the other IP block doesn't exist.
>
> This code could go lots of other places, but we've put it here.  Why?
> - Pushing it to the bootloader just makes the code harder to update in
>   the field.  If we later find a bug in the new IP block and want to
>   change our mind about what to use we want it to be easy to update.
> - Putting this code in the driver for IP block is a lot of extra work,
>   device tree bindings, etc.  Now that the new IP block is validated
>   it's likely no future SoCs will need this code.  Why pollute the PWM
>   driver with this?  This is an rk3288 thing so it should be in rk3288
>   code.
> - There's a single bit that switches over PWMs, which makes it extra
>   hard to put this under the PWM device tree nodes.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> index 8ab9e0e..99133b9 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -24,6 +24,24 @@
>  #include <asm/hardware/cache-l2x0.h>
>  #include "core.h"
>
> +static void __init rk3288_init_machine(void)
> +{
> +       void *grf = ioremap(0xff770000, 0x10000);

Is it worth checking for failure here?  Will the system boot without this?

> +
> +       /* Set pwm_sel to RK design PWM in GRF_SOC_CON2; affects all PWMs */
> +       writel(0x00010001, grf + 0x24c);
> +
> +       iounmap(grf);
> +}
> +
> +static void __init rockchip_init_machine(void)
> +{
> +       if (of_machine_is_compatible("rockchip,rk3288"))
> +               rk3288_init_machine();
> +
> +       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> +}
> +
>  static const char * const rockchip_board_dt_compat[] = {
>         "rockchip,rk2928",
>         "rockchip,rk3066a",
> @@ -34,6 +52,7 @@ static const char * const rockchip_board_dt_compat[] = {
>  };
>
>  DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
> +       .init_machine   = rockchip_init_machine,
>         .l2c_aux_val    = 0,
>         .l2c_aux_mask   = ~0,
>         .dt_compat      = rockchip_board_dt_compat,
> --
> 2.1.0.rc2.206.gedb03e5
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-18 17:11     ` Sonny Rao
@ 2014-08-18 17:19       ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:19 UTC (permalink / raw)
  To: Sonny Rao
  Cc: Heiko Stuebner, Thierry Reding, Caesar Wang, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Sonny,

On Mon, Aug 18, 2014 at 10:11 AM, Sonny Rao <sonnyrao@chromium.org> wrote:
> On Mon, Aug 18, 2014 at 10:09 AM, Doug Anderson <dianders@chromium.org> wrote:
>> The rk3288 SoC has an option to switch all of the PWMs in the system
>> between the old IP block and the new IP block.  The new IP block is
>> working and tested and the suggested PWM to use, so setup the SoC to
>> use it and then we can pretend that the other IP block doesn't exist.
>>
>> This code could go lots of other places, but we've put it here.  Why?
>> - Pushing it to the bootloader just makes the code harder to update in
>>   the field.  If we later find a bug in the new IP block and want to
>>   change our mind about what to use we want it to be easy to update.
>> - Putting this code in the driver for IP block is a lot of extra work,
>>   device tree bindings, etc.  Now that the new IP block is validated
>>   it's likely no future SoCs will need this code.  Why pollute the PWM
>>   driver with this?  This is an rk3288 thing so it should be in rk3288
>>   code.
>> - There's a single bit that switches over PWMs, which makes it extra
>>   hard to put this under the PWM device tree nodes.
>>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> index 8ab9e0e..99133b9 100644
>> --- a/arch/arm/mach-rockchip/rockchip.c
>> +++ b/arch/arm/mach-rockchip/rockchip.c
>> @@ -24,6 +24,24 @@
>>  #include <asm/hardware/cache-l2x0.h>
>>  #include "core.h"
>>
>> +static void __init rk3288_init_machine(void)
>> +{
>> +       void *grf = ioremap(0xff770000, 0x10000);
>
> Is it worth checking for failure here?  Will the system boot without this?

Yes, the system will boot without it.  I can't quite imagine the
ioremap failing, but I can add a test.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-18 17:19       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-18 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

Sonny,

On Mon, Aug 18, 2014 at 10:11 AM, Sonny Rao <sonnyrao@chromium.org> wrote:
> On Mon, Aug 18, 2014 at 10:09 AM, Doug Anderson <dianders@chromium.org> wrote:
>> The rk3288 SoC has an option to switch all of the PWMs in the system
>> between the old IP block and the new IP block.  The new IP block is
>> working and tested and the suggested PWM to use, so setup the SoC to
>> use it and then we can pretend that the other IP block doesn't exist.
>>
>> This code could go lots of other places, but we've put it here.  Why?
>> - Pushing it to the bootloader just makes the code harder to update in
>>   the field.  If we later find a bug in the new IP block and want to
>>   change our mind about what to use we want it to be easy to update.
>> - Putting this code in the driver for IP block is a lot of extra work,
>>   device tree bindings, etc.  Now that the new IP block is validated
>>   it's likely no future SoCs will need this code.  Why pollute the PWM
>>   driver with this?  This is an rk3288 thing so it should be in rk3288
>>   code.
>> - There's a single bit that switches over PWMs, which makes it extra
>>   hard to put this under the PWM device tree nodes.
>>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> index 8ab9e0e..99133b9 100644
>> --- a/arch/arm/mach-rockchip/rockchip.c
>> +++ b/arch/arm/mach-rockchip/rockchip.c
>> @@ -24,6 +24,24 @@
>>  #include <asm/hardware/cache-l2x0.h>
>>  #include "core.h"
>>
>> +static void __init rk3288_init_machine(void)
>> +{
>> +       void *grf = ioremap(0xff770000, 0x10000);
>
> Is it worth checking for failure here?  Will the system boot without this?

Yes, the system will boot without it.  I can't quite imagine the
ioremap failing, but I can add a test.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-18 17:09   ` Doug Anderson
@ 2014-08-19  7:10     ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:10 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, olof, Eddie Cai, linux,
	linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1974 bytes --]

On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> The rk3288 SoC has an option to switch all of the PWMs in the system
> between the old IP block and the new IP block.  The new IP block is
> working and tested and the suggested PWM to use, so setup the SoC to
> use it and then we can pretend that the other IP block doesn't exist.
> 
> This code could go lots of other places, but we've put it here.  Why?
> - Pushing it to the bootloader just makes the code harder to update in
>   the field.  If we later find a bug in the new IP block and want to
>   change our mind about what to use we want it to be easy to update.
> - Putting this code in the driver for IP block is a lot of extra work,
>   device tree bindings, etc.  Now that the new IP block is validated
>   it's likely no future SoCs will need this code.  Why pollute the PWM
>   driver with this?  This is an rk3288 thing so it should be in rk3288
>   code.
> - There's a single bit that switches over PWMs, which makes it extra
>   hard to put this under the PWM device tree nodes.
> 
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> index 8ab9e0e..99133b9 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -24,6 +24,24 @@
>  #include <asm/hardware/cache-l2x0.h>
>  #include "core.h"
>  
> +static void __init rk3288_init_machine(void)
> +{
> +	void *grf = ioremap(0xff770000, 0x10000);

This region of memory is part of the "grf" "syscon" device (according to
arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
that driver. It looks as if no such driver currently exists, but given
the existence of the device tree node it's fair to assume that one will
eventually be merged.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-19  7:10     ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> The rk3288 SoC has an option to switch all of the PWMs in the system
> between the old IP block and the new IP block.  The new IP block is
> working and tested and the suggested PWM to use, so setup the SoC to
> use it and then we can pretend that the other IP block doesn't exist.
> 
> This code could go lots of other places, but we've put it here.  Why?
> - Pushing it to the bootloader just makes the code harder to update in
>   the field.  If we later find a bug in the new IP block and want to
>   change our mind about what to use we want it to be easy to update.
> - Putting this code in the driver for IP block is a lot of extra work,
>   device tree bindings, etc.  Now that the new IP block is validated
>   it's likely no future SoCs will need this code.  Why pollute the PWM
>   driver with this?  This is an rk3288 thing so it should be in rk3288
>   code.
> - There's a single bit that switches over PWMs, which makes it extra
>   hard to put this under the PWM device tree nodes.
> 
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> index 8ab9e0e..99133b9 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -24,6 +24,24 @@
>  #include <asm/hardware/cache-l2x0.h>
>  #include "core.h"
>  
> +static void __init rk3288_init_machine(void)
> +{
> +	void *grf = ioremap(0xff770000, 0x10000);

This region of memory is part of the "grf" "syscon" device (according to
arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
that driver. It looks as if no such driver currently exists, but given
the existence of the device tree node it's fair to assume that one will
eventually be merged.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140819/d53ef38e/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
  2014-08-18 17:09   ` Doug Anderson
@ 2014-08-19  7:18     ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:18 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, olof, Eddie Cai, robh+dt,
	pawel.moll, mark.rutland, ijc+devicetree, galak, linux-pwm,
	devicetree, linux-kernel, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 2100 bytes --]

On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
[...]
> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>  #define PWM_LP_DISABLE		(0 << 8)
>  
> @@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
>  	struct pwm_chip chip;
>  	struct clk *clk;
>  	const struct rockchip_pwm_data *data;
> +	enum pwm_polarity polarity;

Why do you need this field? struct pwm_device already has a copy of it.

> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>  {
>  	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>  	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
> -			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
> -			  PWM_INACTIVE_NEGATIVE;
> +			  PWM_CONTINUOUS;
>  	u32 val;
>  
> +	if (pc->polarity == PWM_POLARITY_INVERSED)
> +		enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
> +	else
> +		enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;

I have a feeling you're going to answer the above question with: "Because
it's needed here". If so, my reply would be: "Then this function should
take a struct pwm_device instead of struct pwm_chip."

> @@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
>  		.ctrl = 0x0c,
>  	},
>  	.prescaler = 1,
> +	.has_invert = 1,

Since has_invert is a boolean, the proper value here would be "true".

> @@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
>  	pc->data = id->data;
>  	pc->chip.dev = &pdev->dev;
>  	pc->chip.ops = &rockchip_pwm_ops;
> +	if (pc->data->has_invert) {
> +		pc->chip.of_xlate = of_pwm_xlate_with_flags;
> +		pc->chip.of_pwm_n_cells = 3;
> +	}
>  	pc->chip.base = -1;
>  	pc->chip.npwm = 1;

I suggest to rewrite the above as follows for readability:

 	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
+
+	if (pc->data->has_invert) {
+		pc->chip.of_xlate = of_pwm_xlate_with_flags;
+		pc->chip.of_pwm_n_cells = 3;
+	}

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-19  7:18     ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
[...]
> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>  #define PWM_LP_DISABLE		(0 << 8)
>  
> @@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
>  	struct pwm_chip chip;
>  	struct clk *clk;
>  	const struct rockchip_pwm_data *data;
> +	enum pwm_polarity polarity;

Why do you need this field? struct pwm_device already has a copy of it.

> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>  {
>  	struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>  	u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
> -			  PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
> -			  PWM_INACTIVE_NEGATIVE;
> +			  PWM_CONTINUOUS;
>  	u32 val;
>  
> +	if (pc->polarity == PWM_POLARITY_INVERSED)
> +		enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
> +	else
> +		enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;

I have a feeling you're going to answer the above question with: "Because
it's needed here". If so, my reply would be: "Then this function should
take a struct pwm_device instead of struct pwm_chip."

> @@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
>  		.ctrl = 0x0c,
>  	},
>  	.prescaler = 1,
> +	.has_invert = 1,

Since has_invert is a boolean, the proper value here would be "true".

> @@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
>  	pc->data = id->data;
>  	pc->chip.dev = &pdev->dev;
>  	pc->chip.ops = &rockchip_pwm_ops;
> +	if (pc->data->has_invert) {
> +		pc->chip.of_xlate = of_pwm_xlate_with_flags;
> +		pc->chip.of_pwm_n_cells = 3;
> +	}
>  	pc->chip.base = -1;
>  	pc->chip.npwm = 1;

I suggest to rewrite the above as follows for readability:

 	pc->data = id->data;
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &rockchip_pwm_ops;
 	pc->chip.base = -1;
 	pc->chip.npwm = 1;
+
+	if (pc->data->has_invert) {
+		pc->chip.of_xlate = of_pwm_xlate_with_flags;
+		pc->chip.of_pwm_n_cells = 3;
+	}

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140819/51892853/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-19  7:22     ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:22 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, olof, Eddie Cai, robh+dt,
	pawel.moll, mark.rutland, ijc+devicetree, galak, linux,
	devicetree, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2412 bytes --]

On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
> The pwm0 is the PWM associated with the LCD backlight.  Enable it.

In the subject, s/pwm/PWM/.

> 
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
> index 2964370..242e1a9 100644
> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
> @@ -10,6 +10,7 @@
>   * GNU General Public License for more details.
>   */
>  
> +#include <dt-bindings/pwm/pwm.h>
>  #include "rk3288.dtsi"
>  
>  / {
> @@ -17,6 +18,48 @@
>  		reg = <0x0 0x80000000>;
>  	};
>  
> +        backlight {

Indentation seems to be off here.

> +		compatible = "pwm-backlight";
> +		brightness-levels = <
> +			  0   1   2   3   4   5   6   7
> +			  8   9  10  11  12  13  14  15
> +			 16  17  18  19  20  21  22  23
> +			 24  25  26  27  28  29  30  31
> +			 32  33  34  35  36  37  38  39
> +			 40  41  42  43  44  45  46  47
> +			 48  49  50  51  52  53  54  55
> +			 56  57  58  59  60  61  62  63
> +			 64  65  66  67  68  69  70  71
> +			 72  73  74  75  76  77  78  79
> +			 80  81  82  83  84  85  86  87
> +			 88  89  90  91  92  93  94  95
> +			 96  97  98  99 100 101 102 103
> +			104 105 106 107 108 109 110 111
> +			112 113 114 115 116 117 118 119
> +			120 121 122 123 124 125 126 127
> +			128 129 130 131 132 133 134 135
> +			136 137 138 139 140 141 142 143
> +			144 145 146 147 148 149 150 151
> +			152 153 154 155 156 157 158 159
> +			160 161 162 163 164 165 166 167
> +			168 169 170 171 172 173 174 175
> +			176 177 178 179 180 181 182 183
> +			184 185 186 187 188 189 190 191
> +			192 193 194 195 196 197 198 199
> +			200 201 202 203 204 205 206 207
> +			208 209 210 211 212 213 214 215
> +			216 217 218 219 220 221 222 223
> +			224 225 226 227 228 229 230 231
> +			232 233 234 235 236 237 238 239
> +			240 241 242 243 244 245 246 247
> +			248 249 250 251 252 253 254 255>;
> +		default-brightness-level = <128>;
> +		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&bl_en>;
> +		pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
> +        };

And here.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-19  7:22     ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:22 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao,
	olof-nZhT3qVonbNeoWH0uzbU5w, Eddie Cai,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 2439 bytes --]

On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
> The pwm0 is the PWM associated with the LCD backlight.  Enable it.

In the subject, s/pwm/PWM/.

> 
> Signed-off-by: Doug Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
> index 2964370..242e1a9 100644
> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
> @@ -10,6 +10,7 @@
>   * GNU General Public License for more details.
>   */
>  
> +#include <dt-bindings/pwm/pwm.h>
>  #include "rk3288.dtsi"
>  
>  / {
> @@ -17,6 +18,48 @@
>  		reg = <0x0 0x80000000>;
>  	};
>  
> +        backlight {

Indentation seems to be off here.

> +		compatible = "pwm-backlight";
> +		brightness-levels = <
> +			  0   1   2   3   4   5   6   7
> +			  8   9  10  11  12  13  14  15
> +			 16  17  18  19  20  21  22  23
> +			 24  25  26  27  28  29  30  31
> +			 32  33  34  35  36  37  38  39
> +			 40  41  42  43  44  45  46  47
> +			 48  49  50  51  52  53  54  55
> +			 56  57  58  59  60  61  62  63
> +			 64  65  66  67  68  69  70  71
> +			 72  73  74  75  76  77  78  79
> +			 80  81  82  83  84  85  86  87
> +			 88  89  90  91  92  93  94  95
> +			 96  97  98  99 100 101 102 103
> +			104 105 106 107 108 109 110 111
> +			112 113 114 115 116 117 118 119
> +			120 121 122 123 124 125 126 127
> +			128 129 130 131 132 133 134 135
> +			136 137 138 139 140 141 142 143
> +			144 145 146 147 148 149 150 151
> +			152 153 154 155 156 157 158 159
> +			160 161 162 163 164 165 166 167
> +			168 169 170 171 172 173 174 175
> +			176 177 178 179 180 181 182 183
> +			184 185 186 187 188 189 190 191
> +			192 193 194 195 196 197 198 199
> +			200 201 202 203 204 205 206 207
> +			208 209 210 211 212 213 214 215
> +			216 217 218 219 220 221 222 223
> +			224 225 226 227 228 229 230 231
> +			232 233 234 235 236 237 238 239
> +			240 241 242 243 244 245 246 247
> +			248 249 250 251 252 253 254 255>;
> +		default-brightness-level = <128>;
> +		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&bl_en>;
> +		pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
> +        };

And here.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-19  7:22     ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-19  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
> The pwm0 is the PWM associated with the LCD backlight.  Enable it.

In the subject, s/pwm/PWM/.

> 
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
> index 2964370..242e1a9 100644
> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
> @@ -10,6 +10,7 @@
>   * GNU General Public License for more details.
>   */
>  
> +#include <dt-bindings/pwm/pwm.h>
>  #include "rk3288.dtsi"
>  
>  / {
> @@ -17,6 +18,48 @@
>  		reg = <0x0 0x80000000>;
>  	};
>  
> +        backlight {

Indentation seems to be off here.

> +		compatible = "pwm-backlight";
> +		brightness-levels = <
> +			  0   1   2   3   4   5   6   7
> +			  8   9  10  11  12  13  14  15
> +			 16  17  18  19  20  21  22  23
> +			 24  25  26  27  28  29  30  31
> +			 32  33  34  35  36  37  38  39
> +			 40  41  42  43  44  45  46  47
> +			 48  49  50  51  52  53  54  55
> +			 56  57  58  59  60  61  62  63
> +			 64  65  66  67  68  69  70  71
> +			 72  73  74  75  76  77  78  79
> +			 80  81  82  83  84  85  86  87
> +			 88  89  90  91  92  93  94  95
> +			 96  97  98  99 100 101 102 103
> +			104 105 106 107 108 109 110 111
> +			112 113 114 115 116 117 118 119
> +			120 121 122 123 124 125 126 127
> +			128 129 130 131 132 133 134 135
> +			136 137 138 139 140 141 142 143
> +			144 145 146 147 148 149 150 151
> +			152 153 154 155 156 157 158 159
> +			160 161 162 163 164 165 166 167
> +			168 169 170 171 172 173 174 175
> +			176 177 178 179 180 181 182 183
> +			184 185 186 187 188 189 190 191
> +			192 193 194 195 196 197 198 199
> +			200 201 202 203 204 205 206 207
> +			208 209 210 211 212 213 214 215
> +			216 217 218 219 220 221 222 223
> +			224 225 226 227 228 229 230 231
> +			232 233 234 235 236 237 238 239
> +			240 241 242 243 244 245 246 247
> +			248 249 250 251 252 253 254 255>;
> +		default-brightness-level = <128>;
> +		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&bl_en>;
> +		pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
> +        };

And here.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140819/d4d4db57/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-19  7:10     ` Thierry Reding
@ 2014-08-19 15:18       ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 15:18 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Thierry,

On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> The rk3288 SoC has an option to switch all of the PWMs in the system
>> between the old IP block and the new IP block.  The new IP block is
>> working and tested and the suggested PWM to use, so setup the SoC to
>> use it and then we can pretend that the other IP block doesn't exist.
>>
>> This code could go lots of other places, but we've put it here.  Why?
>> - Pushing it to the bootloader just makes the code harder to update in
>>   the field.  If we later find a bug in the new IP block and want to
>>   change our mind about what to use we want it to be easy to update.
>> - Putting this code in the driver for IP block is a lot of extra work,
>>   device tree bindings, etc.  Now that the new IP block is validated
>>   it's likely no future SoCs will need this code.  Why pollute the PWM
>>   driver with this?  This is an rk3288 thing so it should be in rk3288
>>   code.
>> - There's a single bit that switches over PWMs, which makes it extra
>>   hard to put this under the PWM device tree nodes.
>>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> index 8ab9e0e..99133b9 100644
>> --- a/arch/arm/mach-rockchip/rockchip.c
>> +++ b/arch/arm/mach-rockchip/rockchip.c
>> @@ -24,6 +24,24 @@
>>  #include <asm/hardware/cache-l2x0.h>
>>  #include "core.h"
>>
>> +static void __init rk3288_init_machine(void)
>> +{
>> +     void *grf = ioremap(0xff770000, 0x10000);
>
> This region of memory is part of the "grf" "syscon" device (according to
> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> that driver. It looks as if no such driver currently exists, but given
> the existence of the device tree node it's fair to assume that one will
> eventually be merged.

The "grf" syscon device is the "general register file".  It's a
collection of totally random registers stuffed together in one address
space.  Sometimes a single 32-bit register has things you need to
tweak for completely different subsystems.

Most drivers referene the syscon using this in dts:
  rockchip,grf = <&grf>;

Then the drivers do:
  grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");


See the Rockchip i2c, pinctrl, or clock drivers for examples.

I could follow the lead of those subsystem and do the same thing, but
I haven't because of the reasons talked about in the patch
description.  To summarize: I thought it was cleaner and would have
less baggage to carry to put this code in an rk3288-specific function.


There was no clean place to put rk3288-specific code such that it used
the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
infrastructure for something like that seems like a bit too much to
me.  As it's written the code will never need to change (the physical
address of GRF and this bit will always be right on rk3288) and
hopefully nobody will need to think about it again.  ;)


-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-19 15:18       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> The rk3288 SoC has an option to switch all of the PWMs in the system
>> between the old IP block and the new IP block.  The new IP block is
>> working and tested and the suggested PWM to use, so setup the SoC to
>> use it and then we can pretend that the other IP block doesn't exist.
>>
>> This code could go lots of other places, but we've put it here.  Why?
>> - Pushing it to the bootloader just makes the code harder to update in
>>   the field.  If we later find a bug in the new IP block and want to
>>   change our mind about what to use we want it to be easy to update.
>> - Putting this code in the driver for IP block is a lot of extra work,
>>   device tree bindings, etc.  Now that the new IP block is validated
>>   it's likely no future SoCs will need this code.  Why pollute the PWM
>>   driver with this?  This is an rk3288 thing so it should be in rk3288
>>   code.
>> - There's a single bit that switches over PWMs, which makes it extra
>>   hard to put this under the PWM device tree nodes.
>>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>>  1 file changed, 19 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> index 8ab9e0e..99133b9 100644
>> --- a/arch/arm/mach-rockchip/rockchip.c
>> +++ b/arch/arm/mach-rockchip/rockchip.c
>> @@ -24,6 +24,24 @@
>>  #include <asm/hardware/cache-l2x0.h>
>>  #include "core.h"
>>
>> +static void __init rk3288_init_machine(void)
>> +{
>> +     void *grf = ioremap(0xff770000, 0x10000);
>
> This region of memory is part of the "grf" "syscon" device (according to
> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> that driver. It looks as if no such driver currently exists, but given
> the existence of the device tree node it's fair to assume that one will
> eventually be merged.

The "grf" syscon device is the "general register file".  It's a
collection of totally random registers stuffed together in one address
space.  Sometimes a single 32-bit register has things you need to
tweak for completely different subsystems.

Most drivers referene the syscon using this in dts:
  rockchip,grf = <&grf>;

Then the drivers do:
  grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");


See the Rockchip i2c, pinctrl, or clock drivers for examples.

I could follow the lead of those subsystem and do the same thing, but
I haven't because of the reasons talked about in the patch
description.  To summarize: I thought it was cleaner and would have
less baggage to carry to put this code in an rk3288-specific function.


There was no clean place to put rk3288-specific code such that it used
the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
infrastructure for something like that seems like a bit too much to
me.  As it's written the code will never need to change (the physical
address of GRF and this bit will always be right on rk3288) and
hopefully nobody will need to think about it again.  ;)


-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
  2014-08-19  7:18     ` Thierry Reding
  (?)
@ 2014-08-19 16:05       ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, linux-pwm, devicetree, linux-kernel,
	linux-arm-kernel

Thierry

On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
> [...]
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>>  #define PWM_LP_DISABLE               (0 << 8)
>>
>> @@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
>>       struct pwm_chip chip;
>>       struct clk *clk;
>>       const struct rockchip_pwm_data *data;
>> +     enum pwm_polarity polarity;
>
> Why do you need this field? struct pwm_device already has a copy of it.

OK, good point.


>> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>>  {
>>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
>> -                       PWM_INACTIVE_NEGATIVE;
>> +                       PWM_CONTINUOUS;
>>       u32 val;
>>
>> +     if (pc->polarity == PWM_POLARITY_INVERSED)
>> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
>> +     else
>> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>
> I have a feeling you're going to answer the above question with: "Because
> it's needed here". If so, my reply would be: "Then this function should
> take a struct pwm_device instead of struct pwm_chip."

OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
little redundant because a pwm_device has a pointer to its pwm_chip,
but it follows the lead of all of the callbacks in "struct pwm_ops".
If you'd like me to spin it to take only a pwm_device I'm happy to.


>
>> @@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
>>               .ctrl = 0x0c,
>>       },
>>       .prescaler = 1,
>> +     .has_invert = 1,
>
> Since has_invert is a boolean, the proper value here would be "true".

Done.


>> @@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
>>       pc->data = id->data;
>>       pc->chip.dev = &pdev->dev;
>>       pc->chip.ops = &rockchip_pwm_ops;
>> +     if (pc->data->has_invert) {
>> +             pc->chip.of_xlate = of_pwm_xlate_with_flags;
>> +             pc->chip.of_pwm_n_cells = 3;
>> +     }
>>       pc->chip.base = -1;
>>       pc->chip.npwm = 1;
>
> I suggest to rewrite the above as follows for readability:
>
>         pc->data = id->data;
>         pc->chip.dev = &pdev->dev;
>         pc->chip.ops = &rockchip_pwm_ops;
>         pc->chip.base = -1;
>         pc->chip.npwm = 1;

Done.


> +       if (pc->data->has_invert) {
> +               pc->chip.of_xlate = of_pwm_xlate_with_flags;
> +               pc->chip.of_pwm_n_cells = 3;
> +       }
>
> Thierry

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-19 16:05       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, linux-pwm, devicetree, linux-kernel,
	linux-arm-kernel

Thierry

On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
> [...]
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>>  #define PWM_LP_DISABLE               (0 << 8)
>>
>> @@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
>>       struct pwm_chip chip;
>>       struct clk *clk;
>>       const struct rockchip_pwm_data *data;
>> +     enum pwm_polarity polarity;
>
> Why do you need this field? struct pwm_device already has a copy of it.

OK, good point.


>> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>>  {
>>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
>> -                       PWM_INACTIVE_NEGATIVE;
>> +                       PWM_CONTINUOUS;
>>       u32 val;
>>
>> +     if (pc->polarity == PWM_POLARITY_INVERSED)
>> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
>> +     else
>> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>
> I have a feeling you're going to answer the above question with: "Because
> it's needed here". If so, my reply would be: "Then this function should
> take a struct pwm_device instead of struct pwm_chip."

OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
little redundant because a pwm_device has a pointer to its pwm_chip,
but it follows the lead of all of the callbacks in "struct pwm_ops".
If you'd like me to spin it to take only a pwm_device I'm happy to.


>
>> @@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
>>               .ctrl = 0x0c,
>>       },
>>       .prescaler = 1,
>> +     .has_invert = 1,
>
> Since has_invert is a boolean, the proper value here would be "true".

Done.


>> @@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
>>       pc->data = id->data;
>>       pc->chip.dev = &pdev->dev;
>>       pc->chip.ops = &rockchip_pwm_ops;
>> +     if (pc->data->has_invert) {
>> +             pc->chip.of_xlate = of_pwm_xlate_with_flags;
>> +             pc->chip.of_pwm_n_cells = 3;
>> +     }
>>       pc->chip.base = -1;
>>       pc->chip.npwm = 1;
>
> I suggest to rewrite the above as follows for readability:
>
>         pc->data = id->data;
>         pc->chip.dev = &pdev->dev;
>         pc->chip.ops = &rockchip_pwm_ops;
>         pc->chip.base = -1;
>         pc->chip.npwm = 1;

Done.


> +       if (pc->data->has_invert) {
> +               pc->chip.of_xlate = of_pwm_xlate_with_flags;
> +               pc->chip.of_pwm_n_cells = 3;
> +       }
>
> Thierry

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-19 16:05       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry

On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
> [...]
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>>  #define PWM_LP_DISABLE               (0 << 8)
>>
>> @@ -32,6 +34,7 @@ struct rockchip_pwm_chip {
>>       struct pwm_chip chip;
>>       struct clk *clk;
>>       const struct rockchip_pwm_data *data;
>> +     enum pwm_polarity polarity;
>
> Why do you need this field? struct pwm_device already has a copy of it.

OK, good point.


>> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>>  {
>>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
>> -                       PWM_INACTIVE_NEGATIVE;
>> +                       PWM_CONTINUOUS;
>>       u32 val;
>>
>> +     if (pc->polarity == PWM_POLARITY_INVERSED)
>> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
>> +     else
>> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>
> I have a feeling you're going to answer the above question with: "Because
> it's needed here". If so, my reply would be: "Then this function should
> take a struct pwm_device instead of struct pwm_chip."

OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
little redundant because a pwm_device has a pointer to its pwm_chip,
but it follows the lead of all of the callbacks in "struct pwm_ops".
If you'd like me to spin it to take only a pwm_device I'm happy to.


>
>> @@ -173,6 +195,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
>>               .ctrl = 0x0c,
>>       },
>>       .prescaler = 1,
>> +     .has_invert = 1,
>
> Since has_invert is a boolean, the proper value here would be "true".

Done.


>> @@ -228,6 +252,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
>>       pc->data = id->data;
>>       pc->chip.dev = &pdev->dev;
>>       pc->chip.ops = &rockchip_pwm_ops;
>> +     if (pc->data->has_invert) {
>> +             pc->chip.of_xlate = of_pwm_xlate_with_flags;
>> +             pc->chip.of_pwm_n_cells = 3;
>> +     }
>>       pc->chip.base = -1;
>>       pc->chip.npwm = 1;
>
> I suggest to rewrite the above as follows for readability:
>
>         pc->data = id->data;
>         pc->chip.dev = &pdev->dev;
>         pc->chip.ops = &rockchip_pwm_ops;
>         pc->chip.base = -1;
>         pc->chip.npwm = 1;

Done.


> +       if (pc->data->has_invert) {
> +               pc->chip.of_xlate = of_pwm_xlate_with_flags;
> +               pc->chip.of_pwm_n_cells = 3;
> +       }
>
> Thierry

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
  2014-08-19  7:22     ` Thierry Reding
  (?)
@ 2014-08-19 16:05       ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Russell King, devicetree, linux-arm-kernel,
	linux-kernel

Thierry,

On Tue, Aug 19, 2014 at 12:22 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
>> The pwm0 is the PWM associated with the LCD backlight.  Enable it.
>
> In the subject, s/pwm/PWM/.

Done.


>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 53 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
>> index 2964370..242e1a9 100644
>> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
>> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
>> @@ -10,6 +10,7 @@
>>   * GNU General Public License for more details.
>>   */
>>
>> +#include <dt-bindings/pwm/pwm.h>
>>  #include "rk3288.dtsi"
>>
>>  / {
>> @@ -17,6 +18,48 @@
>>               reg = <0x0 0x80000000>;
>>       };
>>
>> +        backlight {
>
> Indentation seems to be off here.

Good catch.  Done.


>> +             compatible = "pwm-backlight";
>> +             brightness-levels = <
>> +                       0   1   2   3   4   5   6   7
>> +                       8   9  10  11  12  13  14  15
>> +                      16  17  18  19  20  21  22  23
>> +                      24  25  26  27  28  29  30  31
>> +                      32  33  34  35  36  37  38  39
>> +                      40  41  42  43  44  45  46  47
>> +                      48  49  50  51  52  53  54  55
>> +                      56  57  58  59  60  61  62  63
>> +                      64  65  66  67  68  69  70  71
>> +                      72  73  74  75  76  77  78  79
>> +                      80  81  82  83  84  85  86  87
>> +                      88  89  90  91  92  93  94  95
>> +                      96  97  98  99 100 101 102 103
>> +                     104 105 106 107 108 109 110 111
>> +                     112 113 114 115 116 117 118 119
>> +                     120 121 122 123 124 125 126 127
>> +                     128 129 130 131 132 133 134 135
>> +                     136 137 138 139 140 141 142 143
>> +                     144 145 146 147 148 149 150 151
>> +                     152 153 154 155 156 157 158 159
>> +                     160 161 162 163 164 165 166 167
>> +                     168 169 170 171 172 173 174 175
>> +                     176 177 178 179 180 181 182 183
>> +                     184 185 186 187 188 189 190 191
>> +                     192 193 194 195 196 197 198 199
>> +                     200 201 202 203 204 205 206 207
>> +                     208 209 210 211 212 213 214 215
>> +                     216 217 218 219 220 221 222 223
>> +                     224 225 226 227 228 229 230 231
>> +                     232 233 234 235 236 237 238 239
>> +                     240 241 242 243 244 245 246 247
>> +                     248 249 250 251 252 253 254 255>;
>> +             default-brightness-level = <128>;
>> +             enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&bl_en>;
>> +             pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
>> +        };
>
> And here.

Done.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-19 16:05       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Russell King, devicetree, linux-arm-kernel,
	linux-kernel

Thierry,

On Tue, Aug 19, 2014 at 12:22 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
>> The pwm0 is the PWM associated with the LCD backlight.  Enable it.
>
> In the subject, s/pwm/PWM/.

Done.


>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 53 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
>> index 2964370..242e1a9 100644
>> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
>> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
>> @@ -10,6 +10,7 @@
>>   * GNU General Public License for more details.
>>   */
>>
>> +#include <dt-bindings/pwm/pwm.h>
>>  #include "rk3288.dtsi"
>>
>>  / {
>> @@ -17,6 +18,48 @@
>>               reg = <0x0 0x80000000>;
>>       };
>>
>> +        backlight {
>
> Indentation seems to be off here.

Good catch.  Done.


>> +             compatible = "pwm-backlight";
>> +             brightness-levels = <
>> +                       0   1   2   3   4   5   6   7
>> +                       8   9  10  11  12  13  14  15
>> +                      16  17  18  19  20  21  22  23
>> +                      24  25  26  27  28  29  30  31
>> +                      32  33  34  35  36  37  38  39
>> +                      40  41  42  43  44  45  46  47
>> +                      48  49  50  51  52  53  54  55
>> +                      56  57  58  59  60  61  62  63
>> +                      64  65  66  67  68  69  70  71
>> +                      72  73  74  75  76  77  78  79
>> +                      80  81  82  83  84  85  86  87
>> +                      88  89  90  91  92  93  94  95
>> +                      96  97  98  99 100 101 102 103
>> +                     104 105 106 107 108 109 110 111
>> +                     112 113 114 115 116 117 118 119
>> +                     120 121 122 123 124 125 126 127
>> +                     128 129 130 131 132 133 134 135
>> +                     136 137 138 139 140 141 142 143
>> +                     144 145 146 147 148 149 150 151
>> +                     152 153 154 155 156 157 158 159
>> +                     160 161 162 163 164 165 166 167
>> +                     168 169 170 171 172 173 174 175
>> +                     176 177 178 179 180 181 182 183
>> +                     184 185 186 187 188 189 190 191
>> +                     192 193 194 195 196 197 198 199
>> +                     200 201 202 203 204 205 206 207
>> +                     208 209 210 211 212 213 214 215
>> +                     216 217 218 219 220 221 222 223
>> +                     224 225 226 227 228 229 230 231
>> +                     232 233 234 235 236 237 238 239
>> +                     240 241 242 243 244 245 246 247
>> +                     248 249 250 251 252 253 254 255>;
>> +             default-brightness-level = <128>;
>> +             enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&bl_en>;
>> +             pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
>> +        };
>
> And here.

Done.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB
@ 2014-08-19 16:05       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-19 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Tue, Aug 19, 2014 at 12:22 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 10:09:09AM -0700, Doug Anderson wrote:
>> The pwm0 is the PWM associated with the LCD backlight.  Enable it.
>
> In the subject, s/pwm/PWM/.

Done.


>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> ---
>>  arch/arm/boot/dts/rk3288-evb.dtsi | 53 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 53 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
>> index 2964370..242e1a9 100644
>> --- a/arch/arm/boot/dts/rk3288-evb.dtsi
>> +++ b/arch/arm/boot/dts/rk3288-evb.dtsi
>> @@ -10,6 +10,7 @@
>>   * GNU General Public License for more details.
>>   */
>>
>> +#include <dt-bindings/pwm/pwm.h>
>>  #include "rk3288.dtsi"
>>
>>  / {
>> @@ -17,6 +18,48 @@
>>               reg = <0x0 0x80000000>;
>>       };
>>
>> +        backlight {
>
> Indentation seems to be off here.

Good catch.  Done.


>> +             compatible = "pwm-backlight";
>> +             brightness-levels = <
>> +                       0   1   2   3   4   5   6   7
>> +                       8   9  10  11  12  13  14  15
>> +                      16  17  18  19  20  21  22  23
>> +                      24  25  26  27  28  29  30  31
>> +                      32  33  34  35  36  37  38  39
>> +                      40  41  42  43  44  45  46  47
>> +                      48  49  50  51  52  53  54  55
>> +                      56  57  58  59  60  61  62  63
>> +                      64  65  66  67  68  69  70  71
>> +                      72  73  74  75  76  77  78  79
>> +                      80  81  82  83  84  85  86  87
>> +                      88  89  90  91  92  93  94  95
>> +                      96  97  98  99 100 101 102 103
>> +                     104 105 106 107 108 109 110 111
>> +                     112 113 114 115 116 117 118 119
>> +                     120 121 122 123 124 125 126 127
>> +                     128 129 130 131 132 133 134 135
>> +                     136 137 138 139 140 141 142 143
>> +                     144 145 146 147 148 149 150 151
>> +                     152 153 154 155 156 157 158 159
>> +                     160 161 162 163 164 165 166 167
>> +                     168 169 170 171 172 173 174 175
>> +                     176 177 178 179 180 181 182 183
>> +                     184 185 186 187 188 189 190 191
>> +                     192 193 194 195 196 197 198 199
>> +                     200 201 202 203 204 205 206 207
>> +                     208 209 210 211 212 213 214 215
>> +                     216 217 218 219 220 221 222 223
>> +                     224 225 226 227 228 229 230 231
>> +                     232 233 234 235 236 237 238 239
>> +                     240 241 242 243 244 245 246 247
>> +                     248 249 250 251 252 253 254 255>;
>> +             default-brightness-level = <128>;
>> +             enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&bl_en>;
>> +             pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
>> +        };
>
> And here.

Done.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-19 15:18       ` Doug Anderson
@ 2014-08-20  6:08         ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20  6:08 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4897 bytes --]

On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> The rk3288 SoC has an option to switch all of the PWMs in the system
> >> between the old IP block and the new IP block.  The new IP block is
> >> working and tested and the suggested PWM to use, so setup the SoC to
> >> use it and then we can pretend that the other IP block doesn't exist.

A few more questions as to how this actually works. Does it mean there
are two physically separate blocks (with different physical addresses)
to control the same PWM? And this register simply causes some of the
pins to be routed to one or another? As far as I recall there are a
number of instances of the PWM block, so the above would need to count
for all of them. Or are there separate bits for each of them?

> >> This code could go lots of other places, but we've put it here.  Why?
> >> - Pushing it to the bootloader just makes the code harder to update in
> >>   the field.  If we later find a bug in the new IP block and want to
> >>   change our mind about what to use we want it to be easy to update.

Depending on how this muxing works you won't be able to change your mind
anyway. If the IP blocks are different then the device tree will
effectively make the decision for you. So if you really want to be safe
you'd need to have code in the kernel that parses the device tree and
checks that all PWM instances are of the new type, then set this
register accordingly.

Or you don't set the bit from the driver and need to verify that device
tree and syscon match to avoid using the wrong controller.

> >> - Putting this code in the driver for IP block is a lot of extra work,
> >>   device tree bindings, etc.  Now that the new IP block is validated
> >>   it's likely no future SoCs will need this code.  Why pollute the PWM
> >>   driver with this?  This is an rk3288 thing so it should be in rk3288
> >>   code.
> >> - There's a single bit that switches over PWMs, which makes it extra
> >>   hard to put this under the PWM device tree nodes.
> >>
> >> Signed-off-by: Doug Anderson <dianders@chromium.org>
> >> ---
> >>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> >> index 8ab9e0e..99133b9 100644
> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> @@ -24,6 +24,24 @@
> >>  #include <asm/hardware/cache-l2x0.h>
> >>  #include "core.h"
> >>
> >> +static void __init rk3288_init_machine(void)
> >> +{
> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >
> > This region of memory is part of the "grf" "syscon" device (according to
> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> > that driver. It looks as if no such driver currently exists, but given
> > the existence of the device tree node it's fair to assume that one will
> > eventually be merged.
> 
> The "grf" syscon device is the "general register file".  It's a
> collection of totally random registers stuffed together in one address
> space.  Sometimes a single 32-bit register has things you need to
> tweak for completely different subsystems.
> 
> Most drivers referene the syscon using this in dts:
>   rockchip,grf = <&grf>;
> 
> Then the drivers do:
>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> 
> 
> See the Rockchip i2c, pinctrl, or clock drivers for examples.

That's one way to do it. But if it's really just a one-time thing, then
you could easily perform the register write from the syscon driver where
the memory is already parsed from device tree and mapped. That way you
don't have to hardcode the physical address in some other random piece
of code and map the memory again.

> I could follow the lead of those subsystem and do the same thing, but
> I haven't because of the reasons talked about in the patch
> description.  To summarize: I thought it was cleaner and would have
> less baggage to carry to put this code in an rk3288-specific function.
> 
> There was no clean place to put rk3288-specific code such that it used
> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
> infrastructure for something like that seems like a bit too much to
> me.  As it's written the code will never need to change (the physical
> address of GRF and this bit will always be right on rk3288) and
> hopefully nobody will need to think about it again.  ;)

I understand that it looks cleaner this way. But it's completely the
wrong way around. We're trying to move code out of arch/arm and into
proper drivers.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20  6:08         ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20  6:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> The rk3288 SoC has an option to switch all of the PWMs in the system
> >> between the old IP block and the new IP block.  The new IP block is
> >> working and tested and the suggested PWM to use, so setup the SoC to
> >> use it and then we can pretend that the other IP block doesn't exist.

A few more questions as to how this actually works. Does it mean there
are two physically separate blocks (with different physical addresses)
to control the same PWM? And this register simply causes some of the
pins to be routed to one or another? As far as I recall there are a
number of instances of the PWM block, so the above would need to count
for all of them. Or are there separate bits for each of them?

> >> This code could go lots of other places, but we've put it here.  Why?
> >> - Pushing it to the bootloader just makes the code harder to update in
> >>   the field.  If we later find a bug in the new IP block and want to
> >>   change our mind about what to use we want it to be easy to update.

Depending on how this muxing works you won't be able to change your mind
anyway. If the IP blocks are different then the device tree will
effectively make the decision for you. So if you really want to be safe
you'd need to have code in the kernel that parses the device tree and
checks that all PWM instances are of the new type, then set this
register accordingly.

Or you don't set the bit from the driver and need to verify that device
tree and syscon match to avoid using the wrong controller.

> >> - Putting this code in the driver for IP block is a lot of extra work,
> >>   device tree bindings, etc.  Now that the new IP block is validated
> >>   it's likely no future SoCs will need this code.  Why pollute the PWM
> >>   driver with this?  This is an rk3288 thing so it should be in rk3288
> >>   code.
> >> - There's a single bit that switches over PWMs, which makes it extra
> >>   hard to put this under the PWM device tree nodes.
> >>
> >> Signed-off-by: Doug Anderson <dianders@chromium.org>
> >> ---
> >>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
> >>  1 file changed, 19 insertions(+)
> >>
> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> >> index 8ab9e0e..99133b9 100644
> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> @@ -24,6 +24,24 @@
> >>  #include <asm/hardware/cache-l2x0.h>
> >>  #include "core.h"
> >>
> >> +static void __init rk3288_init_machine(void)
> >> +{
> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >
> > This region of memory is part of the "grf" "syscon" device (according to
> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> > that driver. It looks as if no such driver currently exists, but given
> > the existence of the device tree node it's fair to assume that one will
> > eventually be merged.
> 
> The "grf" syscon device is the "general register file".  It's a
> collection of totally random registers stuffed together in one address
> space.  Sometimes a single 32-bit register has things you need to
> tweak for completely different subsystems.
> 
> Most drivers referene the syscon using this in dts:
>   rockchip,grf = <&grf>;
> 
> Then the drivers do:
>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> 
> 
> See the Rockchip i2c, pinctrl, or clock drivers for examples.

That's one way to do it. But if it's really just a one-time thing, then
you could easily perform the register write from the syscon driver where
the memory is already parsed from device tree and mapped. That way you
don't have to hardcode the physical address in some other random piece
of code and map the memory again.

> I could follow the lead of those subsystem and do the same thing, but
> I haven't because of the reasons talked about in the patch
> description.  To summarize: I thought it was cleaner and would have
> less baggage to carry to put this code in an rk3288-specific function.
> 
> There was no clean place to put rk3288-specific code such that it used
> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
> infrastructure for something like that seems like a bit too much to
> me.  As it's written the code will never need to change (the physical
> address of GRF and this bit will always be right on rk3288) and
> hopefully nobody will need to think about it again.  ;)

I understand that it looks cleaner this way. But it's completely the
wrong way around. We're trying to move code out of arch/arm and into
proper drivers.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140820/da288634/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
  2014-08-19 16:05       ` Doug Anderson
  (?)
@ 2014-08-20  6:09         ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20  6:09 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, linux-pwm, devicetree, linux-kernel,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]

On Tue, Aug 19, 2014 at 09:05:20AM -0700, Doug Anderson wrote:
> On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
[...]
> >> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
> >>  {
> >>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
> >>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
> >> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
> >> -                       PWM_INACTIVE_NEGATIVE;
> >> +                       PWM_CONTINUOUS;
> >>       u32 val;
> >>
> >> +     if (pc->polarity == PWM_POLARITY_INVERSED)
> >> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
> >> +     else
> >> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
> >
> > I have a feeling you're going to answer the above question with: "Because
> > it's needed here". If so, my reply would be: "Then this function should
> > take a struct pwm_device instead of struct pwm_chip."
> 
> OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
> little redundant because a pwm_device has a pointer to its pwm_chip,
> but it follows the lead of all of the callbacks in "struct pwm_ops".
> If you'd like me to spin it to take only a pwm_device I'm happy to.

No, that's fine.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-20  6:09         ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20  6:09 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, linux-pwm, devicetree, linux-kernel,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]

On Tue, Aug 19, 2014 at 09:05:20AM -0700, Doug Anderson wrote:
> On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
[...]
> >> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
> >>  {
> >>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
> >>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
> >> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
> >> -                       PWM_INACTIVE_NEGATIVE;
> >> +                       PWM_CONTINUOUS;
> >>       u32 val;
> >>
> >> +     if (pc->polarity == PWM_POLARITY_INVERSED)
> >> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
> >> +     else
> >> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
> >
> > I have a feeling you're going to answer the above question with: "Because
> > it's needed here". If so, my reply would be: "Then this function should
> > take a struct pwm_device instead of struct pwm_chip."
> 
> OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
> little redundant because a pwm_device has a pointer to its pwm_chip,
> but it follows the lead of all of the callbacks in "struct pwm_ops".
> If you'd like me to spin it to take only a pwm_device I'm happy to.

No, that's fine.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288
@ 2014-08-20  6:09         ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20  6:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 19, 2014 at 09:05:20AM -0700, Doug Anderson wrote:
> On Tue, Aug 19, 2014 at 12:18 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 10:09:07AM -0700, Doug Anderson wrote:
[...]
> >> @@ -74,10 +78,14 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
> >>  {
> >>       struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
> >>       u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
> >> -                       PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
> >> -                       PWM_INACTIVE_NEGATIVE;
> >> +                       PWM_CONTINUOUS;
> >>       u32 val;
> >>
> >> +     if (pc->polarity == PWM_POLARITY_INVERSED)
> >> +             enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
> >> +     else
> >> +             enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
> >
> > I have a feeling you're going to answer the above question with: "Because
> > it's needed here". If so, my reply would be: "Then this function should
> > take a struct pwm_device instead of struct pwm_chip."
> 
> OK.  I've chosen to have it take a pwm_device AND a pwm_chip.  It is a
> little redundant because a pwm_device has a pointer to its pwm_chip,
> but it follows the lead of all of the callbacks in "struct pwm_ops".
> If you'd like me to spin it to take only a pwm_device I'm happy to.

No, that's fine.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140820/387c5e48/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20  6:08         ` Thierry Reding
@ 2014-08-20 15:20           ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 15:20 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Thierry,

On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> The rk3288 SoC has an option to switch all of the PWMs in the system
>> >> between the old IP block and the new IP block.  The new IP block is
>> >> working and tested and the suggested PWM to use, so setup the SoC to
>> >> use it and then we can pretend that the other IP block doesn't exist.
>
> A few more questions as to how this actually works. Does it mean there
> are two physically separate blocks (with different physical addresses)
> to control the same PWM? And this register simply causes some of the
> pins to be routed to one or another? As far as I recall there are a
> number of instances of the PWM block, so the above would need to count
> for all of them. Or are there separate bits for each of them?

All I have is the TRM (technical reference manual) which doesn't give
me much more info than I've provided you.  But I can answer some of
your questoins:

1. If there are two physically separate blocks then the "old" block is
not documented in my TRM.

1a) It's entirely possible it's located at some memory address that is
marked "Reserved" in the TRM, but I have no idea.

1b) It's entirely possible that the old IP block and the new IP block
are supposed to be "compatible" but that the old block is broken and
thus isn't behaving properly.

1c) It's entirely possible that the old IP block and the new IP block
are located at the same physical addresses but somehow work
differently.  If so, the old IP block isn't documented.


2. As per the patch description, there is a single bit that controls
all of the PWMs.  My guess is that there's actually a single IP block
that implements all 4 PWMs.


>> >> This code could go lots of other places, but we've put it here.  Why?
>> >> - Pushing it to the bootloader just makes the code harder to update in
>> >>   the field.  If we later find a bug in the new IP block and want to
>> >>   change our mind about what to use we want it to be easy to update.
>
> Depending on how this muxing works you won't be able to change your mind
> anyway. If the IP blocks are different then the device tree will
> effectively make the decision for you. So if you really want to be safe
> you'd need to have code in the kernel that parses the device tree and
> checks that all PWM instances are of the new type, then set this
> register accordingly.

Since there is no documentation about how you would instantiate the
"old" type in the TRM and no good reason I can think of why someone
would want to do this, it doesn't seem super fruitful.


> Or you don't set the bit from the driver and need to verify that device
> tree and syscon match to avoid using the wrong controller.

This becomes difficult because there's a single bit that switches all the PWMs.


>> >> - Putting this code in the driver for IP block is a lot of extra work,
>> >>   device tree bindings, etc.  Now that the new IP block is validated
>> >>   it's likely no future SoCs will need this code.  Why pollute the PWM
>> >>   driver with this?  This is an rk3288 thing so it should be in rk3288
>> >>   code.
>> >> - There's a single bit that switches over PWMs, which makes it extra
>> >>   hard to put this under the PWM device tree nodes.
>> >>
>> >> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> >> ---
>> >>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>> >>  1 file changed, 19 insertions(+)
>> >>
>> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> >> index 8ab9e0e..99133b9 100644
>> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> @@ -24,6 +24,24 @@
>> >>  #include <asm/hardware/cache-l2x0.h>
>> >>  #include "core.h"
>> >>
>> >> +static void __init rk3288_init_machine(void)
>> >> +{
>> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >
>> > This region of memory is part of the "grf" "syscon" device (according to
>> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
>> > that driver. It looks as if no such driver currently exists, but given
>> > the existence of the device tree node it's fair to assume that one will
>> > eventually be merged.
>>
>> The "grf" syscon device is the "general register file".  It's a
>> collection of totally random registers stuffed together in one address
>> space.  Sometimes a single 32-bit register has things you need to
>> tweak for completely different subsystems.
>>
>> Most drivers referene the syscon using this in dts:
>>   rockchip,grf = <&grf>;
>>
>> Then the drivers do:
>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>>
>>
>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>
> That's one way to do it. But if it's really just a one-time thing, then
> you could easily perform the register write from the syscon driver where
> the memory is already parsed from device tree and mapped. That way you
> don't have to hardcode the physical address in some other random piece
> of code and map the memory again.

Well, except that we're using the general "syscon" driver.  I could
create a whole new driver that "subclasses" this syscon driver I
suppose.


>> I could follow the lead of those subsystem and do the same thing, but
>> I haven't because of the reasons talked about in the patch
>> description.  To summarize: I thought it was cleaner and would have
>> less baggage to carry to put this code in an rk3288-specific function.
>>
>> There was no clean place to put rk3288-specific code such that it used
>> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
>> infrastructure for something like that seems like a bit too much to
>> me.  As it's written the code will never need to change (the physical
>> address of GRF and this bit will always be right on rk3288) and
>> hopefully nobody will need to think about it again.  ;)
>
> I understand that it looks cleaner this way. But it's completely the
> wrong way around. We're trying to move code out of arch/arm and into
> proper drivers.

Yup, I understand that.  I did ask for some advice before posting this
and I got the impression that folks thought that it would be fine to
put it here, though.  I will let those folks clarify their thoughts
and/or correct my understanding.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 15:20           ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 15:20 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> The rk3288 SoC has an option to switch all of the PWMs in the system
>> >> between the old IP block and the new IP block.  The new IP block is
>> >> working and tested and the suggested PWM to use, so setup the SoC to
>> >> use it and then we can pretend that the other IP block doesn't exist.
>
> A few more questions as to how this actually works. Does it mean there
> are two physically separate blocks (with different physical addresses)
> to control the same PWM? And this register simply causes some of the
> pins to be routed to one or another? As far as I recall there are a
> number of instances of the PWM block, so the above would need to count
> for all of them. Or are there separate bits for each of them?

All I have is the TRM (technical reference manual) which doesn't give
me much more info than I've provided you.  But I can answer some of
your questoins:

1. If there are two physically separate blocks then the "old" block is
not documented in my TRM.

1a) It's entirely possible it's located at some memory address that is
marked "Reserved" in the TRM, but I have no idea.

1b) It's entirely possible that the old IP block and the new IP block
are supposed to be "compatible" but that the old block is broken and
thus isn't behaving properly.

1c) It's entirely possible that the old IP block and the new IP block
are located at the same physical addresses but somehow work
differently.  If so, the old IP block isn't documented.


2. As per the patch description, there is a single bit that controls
all of the PWMs.  My guess is that there's actually a single IP block
that implements all 4 PWMs.


>> >> This code could go lots of other places, but we've put it here.  Why?
>> >> - Pushing it to the bootloader just makes the code harder to update in
>> >>   the field.  If we later find a bug in the new IP block and want to
>> >>   change our mind about what to use we want it to be easy to update.
>
> Depending on how this muxing works you won't be able to change your mind
> anyway. If the IP blocks are different then the device tree will
> effectively make the decision for you. So if you really want to be safe
> you'd need to have code in the kernel that parses the device tree and
> checks that all PWM instances are of the new type, then set this
> register accordingly.

Since there is no documentation about how you would instantiate the
"old" type in the TRM and no good reason I can think of why someone
would want to do this, it doesn't seem super fruitful.


> Or you don't set the bit from the driver and need to verify that device
> tree and syscon match to avoid using the wrong controller.

This becomes difficult because there's a single bit that switches all the PWMs.


>> >> - Putting this code in the driver for IP block is a lot of extra work,
>> >>   device tree bindings, etc.  Now that the new IP block is validated
>> >>   it's likely no future SoCs will need this code.  Why pollute the PWM
>> >>   driver with this?  This is an rk3288 thing so it should be in rk3288
>> >>   code.
>> >> - There's a single bit that switches over PWMs, which makes it extra
>> >>   hard to put this under the PWM device tree nodes.
>> >>
>> >> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> >> ---
>> >>  arch/arm/mach-rockchip/rockchip.c | 19 +++++++++++++++++++
>> >>  1 file changed, 19 insertions(+)
>> >>
>> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> >> index 8ab9e0e..99133b9 100644
>> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> @@ -24,6 +24,24 @@
>> >>  #include <asm/hardware/cache-l2x0.h>
>> >>  #include "core.h"
>> >>
>> >> +static void __init rk3288_init_machine(void)
>> >> +{
>> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >
>> > This region of memory is part of the "grf" "syscon" device (according to
>> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
>> > that driver. It looks as if no such driver currently exists, but given
>> > the existence of the device tree node it's fair to assume that one will
>> > eventually be merged.
>>
>> The "grf" syscon device is the "general register file".  It's a
>> collection of totally random registers stuffed together in one address
>> space.  Sometimes a single 32-bit register has things you need to
>> tweak for completely different subsystems.
>>
>> Most drivers referene the syscon using this in dts:
>>   rockchip,grf = <&grf>;
>>
>> Then the drivers do:
>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>>
>>
>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>
> That's one way to do it. But if it's really just a one-time thing, then
> you could easily perform the register write from the syscon driver where
> the memory is already parsed from device tree and mapped. That way you
> don't have to hardcode the physical address in some other random piece
> of code and map the memory again.

Well, except that we're using the general "syscon" driver.  I could
create a whole new driver that "subclasses" this syscon driver I
suppose.


>> I could follow the lead of those subsystem and do the same thing, but
>> I haven't because of the reasons talked about in the patch
>> description.  To summarize: I thought it was cleaner and would have
>> less baggage to carry to put this code in an rk3288-specific function.
>>
>> There was no clean place to put rk3288-specific code such that it used
>> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
>> infrastructure for something like that seems like a bit too much to
>> me.  As it's written the code will never need to change (the physical
>> address of GRF and this bit will always be right on rk3288) and
>> hopefully nobody will need to think about it again.  ;)
>
> I understand that it looks cleaner this way. But it's completely the
> wrong way around. We're trying to move code out of arch/arm and into
> proper drivers.

Yup, I understand that.  I did ask for some advice before posting this
and I got the impression that folks thought that it would be fine to
put it here, though.  I will let those folks clarify their thoughts
and/or correct my understanding.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 15:20           ` Doug Anderson
@ 2014-08-20 15:38             ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20 15:38 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 7301 bytes --]

On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> Thierry,
> >>
> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> <thierry.reding@gmail.com> wrote:
> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> The rk3288 SoC has an option to switch all of the PWMs in the system
> >> >> between the old IP block and the new IP block.  The new IP block is
> >> >> working and tested and the suggested PWM to use, so setup the SoC to
> >> >> use it and then we can pretend that the other IP block doesn't exist.
> >
> > A few more questions as to how this actually works. Does it mean there
> > are two physically separate blocks (with different physical addresses)
> > to control the same PWM? And this register simply causes some of the
> > pins to be routed to one or another? As far as I recall there are a
> > number of instances of the PWM block, so the above would need to count
> > for all of them. Or are there separate bits for each of them?
> 
> All I have is the TRM (technical reference manual) which doesn't give
> me much more info than I've provided you.  But I can answer some of
> your questoins:
> 
> 1. If there are two physically separate blocks then the "old" block is
> not documented in my TRM.
> 
> 1a) It's entirely possible it's located at some memory address that is
> marked "Reserved" in the TRM, but I have no idea.
> 
> 1b) It's entirely possible that the old IP block and the new IP block
> are supposed to be "compatible" but that the old block is broken and
> thus isn't behaving properly.
> 
> 1c) It's entirely possible that the old IP block and the new IP block
> are located at the same physical addresses but somehow work
> differently.  If so, the old IP block isn't documented.
> 
> 
> 2. As per the patch description, there is a single bit that controls
> all of the PWMs.  My guess is that there's actually a single IP block
> that implements all 4 PWMs.

Looking at the register offsets in the device tree that seems likely. At
least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
same IP block. Their placement in the register map is somewhat strange:

	pwm0: pwm@20030000 {
		...
		reg = <0x20030000 0x10>;
		...
		clocks = <&cru PCLK_PWM01>;
		...
	};

	pwm1: pwm@20030010 {
		...
		reg = <0x20030010 0x10>;
		...
		clocks = <&cru PCLK_PWM01>;
		...
	};

	...

	pwm2: pwm@20050020 {
		...
		reg = <0x20050020 0x10>;
		...
		clocks = <&cru PCLK_PWM23>;
		...
	};

	pwm3: pwm@20050030 {
		...
		reg = <0x20050030 0x10>;
		...
		clocks = <&cru PCLK_PWM23>;
		...
	};

The clocks would also indicate that there are actually two blocks. I
seem to remember a discussion about whether to handle them as a single
block or two/four, but I can't seem to find a reference to it. Maybe I'm
confusing it with another driver.

> >> >> This code could go lots of other places, but we've put it here.  Why?
> >> >> - Pushing it to the bootloader just makes the code harder to update in
> >> >>   the field.  If we later find a bug in the new IP block and want to
> >> >>   change our mind about what to use we want it to be easy to update.
> >
> > Depending on how this muxing works you won't be able to change your mind
> > anyway. If the IP blocks are different then the device tree will
> > effectively make the decision for you. So if you really want to be safe
> > you'd need to have code in the kernel that parses the device tree and
> > checks that all PWM instances are of the new type, then set this
> > register accordingly.
> 
> Since there is no documentation about how you would instantiate the
> "old" type in the TRM and no good reason I can think of why someone
> would want to do this, it doesn't seem super fruitful.

Okay, so if it's not at all documented and never used then yes, we'd
better just ignore it.

> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> >> >> index 8ab9e0e..99133b9 100644
> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> >> @@ -24,6 +24,24 @@
> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> >>  #include "core.h"
> >> >>
> >> >> +static void __init rk3288_init_machine(void)
> >> >> +{
> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> >
> >> > This region of memory is part of the "grf" "syscon" device (according to
> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> >> > that driver. It looks as if no such driver currently exists, but given
> >> > the existence of the device tree node it's fair to assume that one will
> >> > eventually be merged.
> >>
> >> The "grf" syscon device is the "general register file".  It's a
> >> collection of totally random registers stuffed together in one address
> >> space.  Sometimes a single 32-bit register has things you need to
> >> tweak for completely different subsystems.
> >>
> >> Most drivers referene the syscon using this in dts:
> >>   rockchip,grf = <&grf>;
> >>
> >> Then the drivers do:
> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >>
> >>
> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >
> > That's one way to do it. But if it's really just a one-time thing, then
> > you could easily perform the register write from the syscon driver where
> > the memory is already parsed from device tree and mapped. That way you
> > don't have to hardcode the physical address in some other random piece
> > of code and map the memory again.
> 
> Well, except that we're using the general "syscon" driver.  I could
> create a whole new driver that "subclasses" this syscon driver I
> suppose.

Ah, I wasn't aware that there was even something like a generic syscon
driver. But yes, subclassing it sounds like a reasonable thing to do.

> >> I could follow the lead of those subsystem and do the same thing, but
> >> I haven't because of the reasons talked about in the patch
> >> description.  To summarize: I thought it was cleaner and would have
> >> less baggage to carry to put this code in an rk3288-specific function.
> >>
> >> There was no clean place to put rk3288-specific code such that it used
> >> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
> >> infrastructure for something like that seems like a bit too much to
> >> me.  As it's written the code will never need to change (the physical
> >> address of GRF and this bit will always be right on rk3288) and
> >> hopefully nobody will need to think about it again.  ;)
> >
> > I understand that it looks cleaner this way. But it's completely the
> > wrong way around. We're trying to move code out of arch/arm and into
> > proper drivers.
> 
> Yup, I understand that.  I did ask for some advice before posting this
> and I got the impression that folks thought that it would be fine to
> put it here, though.  I will let those folks clarify their thoughts
> and/or correct my understanding.

Sure.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 15:38             ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-20 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> Thierry,
> >>
> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> <thierry.reding@gmail.com> wrote:
> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> The rk3288 SoC has an option to switch all of the PWMs in the system
> >> >> between the old IP block and the new IP block.  The new IP block is
> >> >> working and tested and the suggested PWM to use, so setup the SoC to
> >> >> use it and then we can pretend that the other IP block doesn't exist.
> >
> > A few more questions as to how this actually works. Does it mean there
> > are two physically separate blocks (with different physical addresses)
> > to control the same PWM? And this register simply causes some of the
> > pins to be routed to one or another? As far as I recall there are a
> > number of instances of the PWM block, so the above would need to count
> > for all of them. Or are there separate bits for each of them?
> 
> All I have is the TRM (technical reference manual) which doesn't give
> me much more info than I've provided you.  But I can answer some of
> your questoins:
> 
> 1. If there are two physically separate blocks then the "old" block is
> not documented in my TRM.
> 
> 1a) It's entirely possible it's located at some memory address that is
> marked "Reserved" in the TRM, but I have no idea.
> 
> 1b) It's entirely possible that the old IP block and the new IP block
> are supposed to be "compatible" but that the old block is broken and
> thus isn't behaving properly.
> 
> 1c) It's entirely possible that the old IP block and the new IP block
> are located at the same physical addresses but somehow work
> differently.  If so, the old IP block isn't documented.
> 
> 
> 2. As per the patch description, there is a single bit that controls
> all of the PWMs.  My guess is that there's actually a single IP block
> that implements all 4 PWMs.

Looking at the register offsets in the device tree that seems likely. At
least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
same IP block. Their placement in the register map is somewhat strange:

	pwm0: pwm at 20030000 {
		...
		reg = <0x20030000 0x10>;
		...
		clocks = <&cru PCLK_PWM01>;
		...
	};

	pwm1: pwm at 20030010 {
		...
		reg = <0x20030010 0x10>;
		...
		clocks = <&cru PCLK_PWM01>;
		...
	};

	...

	pwm2: pwm at 20050020 {
		...
		reg = <0x20050020 0x10>;
		...
		clocks = <&cru PCLK_PWM23>;
		...
	};

	pwm3: pwm at 20050030 {
		...
		reg = <0x20050030 0x10>;
		...
		clocks = <&cru PCLK_PWM23>;
		...
	};

The clocks would also indicate that there are actually two blocks. I
seem to remember a discussion about whether to handle them as a single
block or two/four, but I can't seem to find a reference to it. Maybe I'm
confusing it with another driver.

> >> >> This code could go lots of other places, but we've put it here.  Why?
> >> >> - Pushing it to the bootloader just makes the code harder to update in
> >> >>   the field.  If we later find a bug in the new IP block and want to
> >> >>   change our mind about what to use we want it to be easy to update.
> >
> > Depending on how this muxing works you won't be able to change your mind
> > anyway. If the IP blocks are different then the device tree will
> > effectively make the decision for you. So if you really want to be safe
> > you'd need to have code in the kernel that parses the device tree and
> > checks that all PWM instances are of the new type, then set this
> > register accordingly.
> 
> Since there is no documentation about how you would instantiate the
> "old" type in the TRM and no good reason I can think of why someone
> would want to do this, it doesn't seem super fruitful.

Okay, so if it's not at all documented and never used then yes, we'd
better just ignore it.

> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> >> >> index 8ab9e0e..99133b9 100644
> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> >> @@ -24,6 +24,24 @@
> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> >>  #include "core.h"
> >> >>
> >> >> +static void __init rk3288_init_machine(void)
> >> >> +{
> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> >
> >> > This region of memory is part of the "grf" "syscon" device (according to
> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
> >> > that driver. It looks as if no such driver currently exists, but given
> >> > the existence of the device tree node it's fair to assume that one will
> >> > eventually be merged.
> >>
> >> The "grf" syscon device is the "general register file".  It's a
> >> collection of totally random registers stuffed together in one address
> >> space.  Sometimes a single 32-bit register has things you need to
> >> tweak for completely different subsystems.
> >>
> >> Most drivers referene the syscon using this in dts:
> >>   rockchip,grf = <&grf>;
> >>
> >> Then the drivers do:
> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >>
> >>
> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >
> > That's one way to do it. But if it's really just a one-time thing, then
> > you could easily perform the register write from the syscon driver where
> > the memory is already parsed from device tree and mapped. That way you
> > don't have to hardcode the physical address in some other random piece
> > of code and map the memory again.
> 
> Well, except that we're using the general "syscon" driver.  I could
> create a whole new driver that "subclasses" this syscon driver I
> suppose.

Ah, I wasn't aware that there was even something like a generic syscon
driver. But yes, subclassing it sounds like a reasonable thing to do.

> >> I could follow the lead of those subsystem and do the same thing, but
> >> I haven't because of the reasons talked about in the patch
> >> description.  To summarize: I thought it was cleaner and would have
> >> less baggage to carry to put this code in an rk3288-specific function.
> >>
> >> There was no clean place to put rk3288-specific code such that it used
> >> the "syscon" interface like i2c/clk/pinctrl.  ...and adding a lot of
> >> infrastructure for something like that seems like a bit too much to
> >> me.  As it's written the code will never need to change (the physical
> >> address of GRF and this bit will always be right on rk3288) and
> >> hopefully nobody will need to think about it again.  ;)
> >
> > I understand that it looks cleaner this way. But it's completely the
> > wrong way around. We're trying to move code out of arch/arm and into
> > proper drivers.
> 
> Yup, I understand that.  I did ask for some advice before posting this
> and I got the impression that folks thought that it would be fine to
> put it here, though.  I will let those folks clarify their thoughts
> and/or correct my understanding.

Sure.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140820/d66d3a5a/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 15:38             ` Thierry Reding
@ 2014-08-20 15:55               ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 15:55 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Thierry,

On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> Thierry,
>> >>
>> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> The rk3288 SoC has an option to switch all of the PWMs in the system
>> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> >> working and tested and the suggested PWM to use, so setup the SoC to
>> >> >> use it and then we can pretend that the other IP block doesn't exist.
>> >
>> > A few more questions as to how this actually works. Does it mean there
>> > are two physically separate blocks (with different physical addresses)
>> > to control the same PWM? And this register simply causes some of the
>> > pins to be routed to one or another? As far as I recall there are a
>> > number of instances of the PWM block, so the above would need to count
>> > for all of them. Or are there separate bits for each of them?
>>
>> All I have is the TRM (technical reference manual) which doesn't give
>> me much more info than I've provided you.  But I can answer some of
>> your questoins:
>>
>> 1. If there are two physically separate blocks then the "old" block is
>> not documented in my TRM.
>>
>> 1a) It's entirely possible it's located at some memory address that is
>> marked "Reserved" in the TRM, but I have no idea.
>>
>> 1b) It's entirely possible that the old IP block and the new IP block
>> are supposed to be "compatible" but that the old block is broken and
>> thus isn't behaving properly.
>>
>> 1c) It's entirely possible that the old IP block and the new IP block
>> are located at the same physical addresses but somehow work
>> differently.  If so, the old IP block isn't documented.
>>
>>
>> 2. As per the patch description, there is a single bit that controls
>> all of the PWMs.  My guess is that there's actually a single IP block
>> that implements all 4 PWMs.
>
> Looking at the register offsets in the device tree that seems likely. At
> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> same IP block. Their placement in the register map is somewhat strange:
>
>         pwm0: pwm@20030000 {
>                 ...
>                 reg = <0x20030000 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM01>;
>                 ...
>         };
>
>         pwm1: pwm@20030010 {
>                 ...
>                 reg = <0x20030010 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM01>;
>                 ...
>         };
>
>         ...
>
>         pwm2: pwm@20050020 {
>                 ...
>                 reg = <0x20050020 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM23>;
>                 ...
>         };
>
>         pwm3: pwm@20050030 {
>                 ...
>                 reg = <0x20050030 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM23>;
>                 ...
>         };

Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
(the downsides of trying to guess ahead of time what SoC vendors will
name new models).

In rk3288 they have the same clocks.  See patch #3 in this series.


> The clocks would also indicate that there are actually two blocks. I
> seem to remember a discussion about whether to handle them as a single
> block or two/four, but I can't seem to find a reference to it. Maybe I'm
> confusing it with another driver.

At this point it seems like the choice has already been made to handle
them as separate PWMs.  I can change this choice if you want...


>> >> >> This code could go lots of other places, but we've put it here.  Why?
>> >> >> - Pushing it to the bootloader just makes the code harder to update in
>> >> >>   the field.  If we later find a bug in the new IP block and want to
>> >> >>   change our mind about what to use we want it to be easy to update.
>> >
>> > Depending on how this muxing works you won't be able to change your mind
>> > anyway. If the IP blocks are different then the device tree will
>> > effectively make the decision for you. So if you really want to be safe
>> > you'd need to have code in the kernel that parses the device tree and
>> > checks that all PWM instances are of the new type, then set this
>> > register accordingly.
>>
>> Since there is no documentation about how you would instantiate the
>> "old" type in the TRM and no good reason I can think of why someone
>> would want to do this, it doesn't seem super fruitful.
>
> Okay, so if it's not at all documented and never used then yes, we'd
> better just ignore it.

Heiko just pointed me at the base address for the other block.
There's nothing in the rk3288 TRM about it, but we can see the base
address.  We could probably guess that it behaves the same as the
older PWM if we need to.  I'm still not convinced there's a good
reason for someone to use it.


>> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> >> >> index 8ab9e0e..99133b9 100644
>> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> >> @@ -24,6 +24,24 @@
>> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> >>  #include "core.h"
>> >> >>
>> >> >> +static void __init rk3288_init_machine(void)
>> >> >> +{
>> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> >
>> >> > This region of memory is part of the "grf" "syscon" device (according to
>> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
>> >> > that driver. It looks as if no such driver currently exists, but given
>> >> > the existence of the device tree node it's fair to assume that one will
>> >> > eventually be merged.
>> >>
>> >> The "grf" syscon device is the "general register file".  It's a
>> >> collection of totally random registers stuffed together in one address
>> >> space.  Sometimes a single 32-bit register has things you need to
>> >> tweak for completely different subsystems.
>> >>
>> >> Most drivers referene the syscon using this in dts:
>> >>   rockchip,grf = <&grf>;
>> >>
>> >> Then the drivers do:
>> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >>
>> >>
>> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >
>> > That's one way to do it. But if it's really just a one-time thing, then
>> > you could easily perform the register write from the syscon driver where
>> > the memory is already parsed from device tree and mapped. That way you
>> > don't have to hardcode the physical address in some other random piece
>> > of code and map the memory again.
>>
>> Well, except that we're using the general "syscon" driver.  I could
>> create a whole new driver that "subclasses" this syscon driver I
>> suppose.
>
> Ah, I wasn't aware that there was even something like a generic syscon
> driver. But yes, subclassing it sounds like a reasonable thing to do.

I will do that if need be, but it's not my favorite.  I will let
others chime in.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 15:55               ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> Thierry,
>> >>
>> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> The rk3288 SoC has an option to switch all of the PWMs in the system
>> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> >> working and tested and the suggested PWM to use, so setup the SoC to
>> >> >> use it and then we can pretend that the other IP block doesn't exist.
>> >
>> > A few more questions as to how this actually works. Does it mean there
>> > are two physically separate blocks (with different physical addresses)
>> > to control the same PWM? And this register simply causes some of the
>> > pins to be routed to one or another? As far as I recall there are a
>> > number of instances of the PWM block, so the above would need to count
>> > for all of them. Or are there separate bits for each of them?
>>
>> All I have is the TRM (technical reference manual) which doesn't give
>> me much more info than I've provided you.  But I can answer some of
>> your questoins:
>>
>> 1. If there are two physically separate blocks then the "old" block is
>> not documented in my TRM.
>>
>> 1a) It's entirely possible it's located at some memory address that is
>> marked "Reserved" in the TRM, but I have no idea.
>>
>> 1b) It's entirely possible that the old IP block and the new IP block
>> are supposed to be "compatible" but that the old block is broken and
>> thus isn't behaving properly.
>>
>> 1c) It's entirely possible that the old IP block and the new IP block
>> are located at the same physical addresses but somehow work
>> differently.  If so, the old IP block isn't documented.
>>
>>
>> 2. As per the patch description, there is a single bit that controls
>> all of the PWMs.  My guess is that there's actually a single IP block
>> that implements all 4 PWMs.
>
> Looking at the register offsets in the device tree that seems likely. At
> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> same IP block. Their placement in the register map is somewhat strange:
>
>         pwm0: pwm at 20030000 {
>                 ...
>                 reg = <0x20030000 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM01>;
>                 ...
>         };
>
>         pwm1: pwm at 20030010 {
>                 ...
>                 reg = <0x20030010 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM01>;
>                 ...
>         };
>
>         ...
>
>         pwm2: pwm at 20050020 {
>                 ...
>                 reg = <0x20050020 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM23>;
>                 ...
>         };
>
>         pwm3: pwm at 20050030 {
>                 ...
>                 reg = <0x20050030 0x10>;
>                 ...
>                 clocks = <&cru PCLK_PWM23>;
>                 ...
>         };

Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
(the downsides of trying to guess ahead of time what SoC vendors will
name new models).

In rk3288 they have the same clocks.  See patch #3 in this series.


> The clocks would also indicate that there are actually two blocks. I
> seem to remember a discussion about whether to handle them as a single
> block or two/four, but I can't seem to find a reference to it. Maybe I'm
> confusing it with another driver.

At this point it seems like the choice has already been made to handle
them as separate PWMs.  I can change this choice if you want...


>> >> >> This code could go lots of other places, but we've put it here.  Why?
>> >> >> - Pushing it to the bootloader just makes the code harder to update in
>> >> >>   the field.  If we later find a bug in the new IP block and want to
>> >> >>   change our mind about what to use we want it to be easy to update.
>> >
>> > Depending on how this muxing works you won't be able to change your mind
>> > anyway. If the IP blocks are different then the device tree will
>> > effectively make the decision for you. So if you really want to be safe
>> > you'd need to have code in the kernel that parses the device tree and
>> > checks that all PWM instances are of the new type, then set this
>> > register accordingly.
>>
>> Since there is no documentation about how you would instantiate the
>> "old" type in the TRM and no good reason I can think of why someone
>> would want to do this, it doesn't seem super fruitful.
>
> Okay, so if it's not at all documented and never used then yes, we'd
> better just ignore it.

Heiko just pointed me at the base address for the other block.
There's nothing in the rk3288 TRM about it, but we can see the base
address.  We could probably guess that it behaves the same as the
older PWM if we need to.  I'm still not convinced there's a good
reason for someone to use it.


>> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
>> >> >> index 8ab9e0e..99133b9 100644
>> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> >> @@ -24,6 +24,24 @@
>> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> >>  #include "core.h"
>> >> >>
>> >> >> +static void __init rk3288_init_machine(void)
>> >> >> +{
>> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> >
>> >> > This region of memory is part of the "grf" "syscon" device (according to
>> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed from
>> >> > that driver. It looks as if no such driver currently exists, but given
>> >> > the existence of the device tree node it's fair to assume that one will
>> >> > eventually be merged.
>> >>
>> >> The "grf" syscon device is the "general register file".  It's a
>> >> collection of totally random registers stuffed together in one address
>> >> space.  Sometimes a single 32-bit register has things you need to
>> >> tweak for completely different subsystems.
>> >>
>> >> Most drivers referene the syscon using this in dts:
>> >>   rockchip,grf = <&grf>;
>> >>
>> >> Then the drivers do:
>> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >>
>> >>
>> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >
>> > That's one way to do it. But if it's really just a one-time thing, then
>> > you could easily perform the register write from the syscon driver where
>> > the memory is already parsed from device tree and mapped. That way you
>> > don't have to hardcode the physical address in some other random piece
>> > of code and map the memory again.
>>
>> Well, except that we're using the general "syscon" driver.  I could
>> create a whole new driver that "subclasses" this syscon driver I
>> suppose.
>
> Ah, I wasn't aware that there was even something like a generic syscon
> driver. But yes, subclassing it sounds like a reasonable thing to do.

I will do that if need be, but it's not my favorite.  I will let
others chime in.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 15:55               ` Doug Anderson
@ 2014-08-20 16:20                 ` Heiko Stübner
  -1 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-20 16:20 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Thierry Reding, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> 
> <thierry.reding@gmail.com> wrote:
> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> Thierry,
> >> 
> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> 
> >> <thierry.reding@gmail.com> wrote:
> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> >> Thierry,
> >> >> 
> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> >> 
> >> >> <thierry.reding@gmail.com> wrote:
> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> >> >> system
> >> >> >> between the old IP block and the new IP block.  The new IP block is
> >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> >> >> >> to
> >> >> >> use it and then we can pretend that the other IP block doesn't
> >> >> >> exist.
> >> > 
> >> > A few more questions as to how this actually works. Does it mean there
> >> > are two physically separate blocks (with different physical addresses)
> >> > to control the same PWM? And this register simply causes some of the
> >> > pins to be routed to one or another? As far as I recall there are a
> >> > number of instances of the PWM block, so the above would need to count
> >> > for all of them. Or are there separate bits for each of them?
> >> 
> >> All I have is the TRM (technical reference manual) which doesn't give
> >> me much more info than I've provided you.  But I can answer some of
> >> your questoins:
> >> 
> >> 1. If there are two physically separate blocks then the "old" block is
> >> not documented in my TRM.
> >> 
> >> 1a) It's entirely possible it's located at some memory address that is
> >> marked "Reserved" in the TRM, but I have no idea.
> >> 
> >> 1b) It's entirely possible that the old IP block and the new IP block
> >> are supposed to be "compatible" but that the old block is broken and
> >> thus isn't behaving properly.
> >> 
> >> 1c) It's entirely possible that the old IP block and the new IP block
> >> are located at the same physical addresses but somehow work
> >> differently.  If so, the old IP block isn't documented.
> >> 
> >> 
> >> 2. As per the patch description, there is a single bit that controls
> >> all of the PWMs.  My guess is that there's actually a single IP block
> >> that implements all 4 PWMs.
> > 
> > Looking at the register offsets in the device tree that seems likely. At
> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > 
> > same IP block. Their placement in the register map is somewhat strange:
> >         pwm0: pwm@20030000 {
> >         
> >                 ...
> >                 reg = <0x20030000 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         
> >         };
> >         
> >         pwm1: pwm@20030010 {
> >         
> >                 ...
> >                 reg = <0x20030010 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         
> >         };
> >         
> >         ...
> >         
> >         pwm2: pwm@20050020 {
> >         
> >                 ...
> >                 reg = <0x20050020 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         
> >         };
> >         
> >         pwm3: pwm@20050030 {
> >         
> >                 ...
> >                 reg = <0x20050030 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         
> >         };
> 
> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> (the downsides of trying to guess ahead of time what SoC vendors will
> name new models).

It did sound like a nice idea at the time to hold the common stuff of 
rk3066/rk3188 and all their derivatives and I assumed a SoC that changed 
dramatically (including the core) would be called 4xxx or so :-) .

> 
> In rk3288 they have the same clocks.  See patch #3 in this series.
> 
> > The clocks would also indicate that there are actually two blocks. I
> > seem to remember a discussion about whether to handle them as a single
> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > confusing it with another driver.
> 
> At this point it seems like the choice has already been made to handle
> them as separate PWMs.  I can change this choice if you want...
> 
> >> >> >> This code could go lots of other places, but we've put it here. 
> >> >> >> Why?
> >> >> >> - Pushing it to the bootloader just makes the code harder to update
> >> >> >> in
> >> >> >> 
> >> >> >>   the field.  If we later find a bug in the new IP block and want
> >> >> >>   to
> >> >> >>   change our mind about what to use we want it to be easy to
> >> >> >>   update.
> >> > 
> >> > Depending on how this muxing works you won't be able to change your
> >> > mind
> >> > anyway. If the IP blocks are different then the device tree will
> >> > effectively make the decision for you. So if you really want to be safe
> >> > you'd need to have code in the kernel that parses the device tree and
> >> > checks that all PWM instances are of the new type, then set this
> >> > register accordingly.
> >> 
> >> Since there is no documentation about how you would instantiate the
> >> "old" type in the TRM and no good reason I can think of why someone
> >> would want to do this, it doesn't seem super fruitful.
> > 
> > Okay, so if it's not at all documented and never used then yes, we'd
> > better just ignore it.
> 
> Heiko just pointed me at the base address for the other block.
> There's nothing in the rk3288 TRM about it, but we can see the base
> address.  We could probably guess that it behaves the same as the
> older PWM if we need to.  I'm still not convinced there's a good
> reason for someone to use it.

>From what I understood the old one was included as a fallback in case some 
drastic problem appeared with the newly developed IP. Similarly for the I2C 
the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both 
old and new i2c IP and now the rk3288 only contains the new one, as the new IP 
seems to have proven stable.

So there really is no incentive to use the old one if no drastic issue has 
appeared with the new one until now.


> >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> >> >> @@ -24,6 +24,24 @@
> >> >> >> 
> >> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> >> >>  #include "core.h"
> >> >> >> 
> >> >> >> +static void __init rk3288_init_machine(void)
> >> >> >> +{
> >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> >> > 
> >> >> > This region of memory is part of the "grf" "syscon" device
> >> >> > (according to
> >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >> >> > from
> >> >> > that driver. It looks as if no such driver currently exists, but
> >> >> > given
> >> >> > the existence of the device tree node it's fair to assume that one
> >> >> > will
> >> >> > eventually be merged.
> >> >> 
> >> >> The "grf" syscon device is the "general register file".  It's a
> >> >> collection of totally random registers stuffed together in one address
> >> >> space.  Sometimes a single 32-bit register has things you need to
> >> >> tweak for completely different subsystems.
> >> >> 
> >> >> Most drivers referene the syscon using this in dts:
> >> >>   rockchip,grf = <&grf>;
> >> >> 
> >> >> Then the drivers do:
> >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >> >> 
> >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >> > 
> >> > That's one way to do it. But if it's really just a one-time thing, then
> >> > you could easily perform the register write from the syscon driver
> >> > where
> >> > the memory is already parsed from device tree and mapped. That way you
> >> > don't have to hardcode the physical address in some other random piece
> >> > of code and map the memory again.
> >> 
> >> Well, except that we're using the general "syscon" driver.  I could
> >> create a whole new driver that "subclasses" this syscon driver I
> >> suppose.
> > 
> > Ah, I wasn't aware that there was even something like a generic syscon
> > driver. But yes, subclassing it sounds like a reasonable thing to do.
> 
> I will do that if need be, but it's not my favorite.  I will let
> others chime in.

I guess personally I like the idea best of just setting the relevant bit in 
_probe of the pwm driver, like the i2c driver does:

if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
	/* get regmap and set bit */
}

The downside would be that the bit would be written 4 times, but I guess this 
shouldn't matter to much. And I don't think anybody will get the idea of 
combining both ip variants in one dts anyway.
And of course in the next SoC the old IP will mostly have gone away and keep 
this somewhat close to the driver and not scatter pwm settings into other 
kernel parts.

Hacking up the syscon driver feels bad to me, especially as it is meant to be 
generic and export such shared registers to other drivers for just these stuff.


Heiko

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 16:20                 ` Heiko Stübner
  0 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-20 16:20 UTC (permalink / raw)
  To: linux-arm-kernel

Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> 
> <thierry.reding@gmail.com> wrote:
> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> Thierry,
> >> 
> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> 
> >> <thierry.reding@gmail.com> wrote:
> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> >> Thierry,
> >> >> 
> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> >> 
> >> >> <thierry.reding@gmail.com> wrote:
> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> >> >> system
> >> >> >> between the old IP block and the new IP block.  The new IP block is
> >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> >> >> >> to
> >> >> >> use it and then we can pretend that the other IP block doesn't
> >> >> >> exist.
> >> > 
> >> > A few more questions as to how this actually works. Does it mean there
> >> > are two physically separate blocks (with different physical addresses)
> >> > to control the same PWM? And this register simply causes some of the
> >> > pins to be routed to one or another? As far as I recall there are a
> >> > number of instances of the PWM block, so the above would need to count
> >> > for all of them. Or are there separate bits for each of them?
> >> 
> >> All I have is the TRM (technical reference manual) which doesn't give
> >> me much more info than I've provided you.  But I can answer some of
> >> your questoins:
> >> 
> >> 1. If there are two physically separate blocks then the "old" block is
> >> not documented in my TRM.
> >> 
> >> 1a) It's entirely possible it's located at some memory address that is
> >> marked "Reserved" in the TRM, but I have no idea.
> >> 
> >> 1b) It's entirely possible that the old IP block and the new IP block
> >> are supposed to be "compatible" but that the old block is broken and
> >> thus isn't behaving properly.
> >> 
> >> 1c) It's entirely possible that the old IP block and the new IP block
> >> are located at the same physical addresses but somehow work
> >> differently.  If so, the old IP block isn't documented.
> >> 
> >> 
> >> 2. As per the patch description, there is a single bit that controls
> >> all of the PWMs.  My guess is that there's actually a single IP block
> >> that implements all 4 PWMs.
> > 
> > Looking at the register offsets in the device tree that seems likely. At
> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > 
> > same IP block. Their placement in the register map is somewhat strange:
> >         pwm0: pwm at 20030000 {
> >         
> >                 ...
> >                 reg = <0x20030000 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         
> >         };
> >         
> >         pwm1: pwm at 20030010 {
> >         
> >                 ...
> >                 reg = <0x20030010 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         
> >         };
> >         
> >         ...
> >         
> >         pwm2: pwm at 20050020 {
> >         
> >                 ...
> >                 reg = <0x20050020 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         
> >         };
> >         
> >         pwm3: pwm at 20050030 {
> >         
> >                 ...
> >                 reg = <0x20050030 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         
> >         };
> 
> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> (the downsides of trying to guess ahead of time what SoC vendors will
> name new models).

It did sound like a nice idea at the time to hold the common stuff of 
rk3066/rk3188 and all their derivatives and I assumed a SoC that changed 
dramatically (including the core) would be called 4xxx or so :-) .

> 
> In rk3288 they have the same clocks.  See patch #3 in this series.
> 
> > The clocks would also indicate that there are actually two blocks. I
> > seem to remember a discussion about whether to handle them as a single
> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > confusing it with another driver.
> 
> At this point it seems like the choice has already been made to handle
> them as separate PWMs.  I can change this choice if you want...
> 
> >> >> >> This code could go lots of other places, but we've put it here. 
> >> >> >> Why?
> >> >> >> - Pushing it to the bootloader just makes the code harder to update
> >> >> >> in
> >> >> >> 
> >> >> >>   the field.  If we later find a bug in the new IP block and want
> >> >> >>   to
> >> >> >>   change our mind about what to use we want it to be easy to
> >> >> >>   update.
> >> > 
> >> > Depending on how this muxing works you won't be able to change your
> >> > mind
> >> > anyway. If the IP blocks are different then the device tree will
> >> > effectively make the decision for you. So if you really want to be safe
> >> > you'd need to have code in the kernel that parses the device tree and
> >> > checks that all PWM instances are of the new type, then set this
> >> > register accordingly.
> >> 
> >> Since there is no documentation about how you would instantiate the
> >> "old" type in the TRM and no good reason I can think of why someone
> >> would want to do this, it doesn't seem super fruitful.
> > 
> > Okay, so if it's not at all documented and never used then yes, we'd
> > better just ignore it.
> 
> Heiko just pointed me at the base address for the other block.
> There's nothing in the rk3288 TRM about it, but we can see the base
> address.  We could probably guess that it behaves the same as the
> older PWM if we need to.  I'm still not convinced there's a good
> reason for someone to use it.

>From what I understood the old one was included as a fallback in case some 
drastic problem appeared with the newly developed IP. Similarly for the I2C 
the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both 
old and new i2c IP and now the rk3288 only contains the new one, as the new IP 
seems to have proven stable.

So there really is no incentive to use the old one if no drastic issue has 
appeared with the new one until now.


> >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> >> >> @@ -24,6 +24,24 @@
> >> >> >> 
> >> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> >> >>  #include "core.h"
> >> >> >> 
> >> >> >> +static void __init rk3288_init_machine(void)
> >> >> >> +{
> >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> >> > 
> >> >> > This region of memory is part of the "grf" "syscon" device
> >> >> > (according to
> >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >> >> > from
> >> >> > that driver. It looks as if no such driver currently exists, but
> >> >> > given
> >> >> > the existence of the device tree node it's fair to assume that one
> >> >> > will
> >> >> > eventually be merged.
> >> >> 
> >> >> The "grf" syscon device is the "general register file".  It's a
> >> >> collection of totally random registers stuffed together in one address
> >> >> space.  Sometimes a single 32-bit register has things you need to
> >> >> tweak for completely different subsystems.
> >> >> 
> >> >> Most drivers referene the syscon using this in dts:
> >> >>   rockchip,grf = <&grf>;
> >> >> 
> >> >> Then the drivers do:
> >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >> >> 
> >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >> > 
> >> > That's one way to do it. But if it's really just a one-time thing, then
> >> > you could easily perform the register write from the syscon driver
> >> > where
> >> > the memory is already parsed from device tree and mapped. That way you
> >> > don't have to hardcode the physical address in some other random piece
> >> > of code and map the memory again.
> >> 
> >> Well, except that we're using the general "syscon" driver.  I could
> >> create a whole new driver that "subclasses" this syscon driver I
> >> suppose.
> > 
> > Ah, I wasn't aware that there was even something like a generic syscon
> > driver. But yes, subclassing it sounds like a reasonable thing to do.
> 
> I will do that if need be, but it's not my favorite.  I will let
> others chime in.

I guess personally I like the idea best of just setting the relevant bit in 
_probe of the pwm driver, like the i2c driver does:

if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
	/* get regmap and set bit */
}

The downside would be that the bit would be written 4 times, but I guess this 
shouldn't matter to much. And I don't think anybody will get the idea of 
combining both ip variants in one dts anyway.
And of course in the next SoC the old IP will mostly have gone away and keep 
this somewhat close to the driver and not scatter pwm settings into other 
kernel parts.

Hacking up the syscon driver feels bad to me, especially as it is meant to be 
generic and export such shared registers to other drivers for just these stuff.


Heiko

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 16:20                 ` Heiko Stübner
@ 2014-08-20 16:27                   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 16:27 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Thierry Reding, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Heiko,

On Wed, Aug 20, 2014 at 9:20 AM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> Thierry,
>>
>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>>
>> <thierry.reding@gmail.com> wrote:
>> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> Thierry,
>> >>
>> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >>
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> >> Thierry,
>> >> >>
>> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> >>
>> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> >> >> system
>> >> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> >> >> >> to
>> >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> >> >> exist.
>> >> >
>> >> > A few more questions as to how this actually works. Does it mean there
>> >> > are two physically separate blocks (with different physical addresses)
>> >> > to control the same PWM? And this register simply causes some of the
>> >> > pins to be routed to one or another? As far as I recall there are a
>> >> > number of instances of the PWM block, so the above would need to count
>> >> > for all of them. Or are there separate bits for each of them?
>> >>
>> >> All I have is the TRM (technical reference manual) which doesn't give
>> >> me much more info than I've provided you.  But I can answer some of
>> >> your questoins:
>> >>
>> >> 1. If there are two physically separate blocks then the "old" block is
>> >> not documented in my TRM.
>> >>
>> >> 1a) It's entirely possible it's located at some memory address that is
>> >> marked "Reserved" in the TRM, but I have no idea.
>> >>
>> >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> are supposed to be "compatible" but that the old block is broken and
>> >> thus isn't behaving properly.
>> >>
>> >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> are located at the same physical addresses but somehow work
>> >> differently.  If so, the old IP block isn't documented.
>> >>
>> >>
>> >> 2. As per the patch description, there is a single bit that controls
>> >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> that implements all 4 PWMs.
>> >
>> > Looking at the register offsets in the device tree that seems likely. At
>> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >
>> > same IP block. Their placement in the register map is somewhat strange:
>> >         pwm0: pwm@20030000 {
>> >
>> >                 ...
>> >                 reg = <0x20030000 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >
>> >         };
>> >
>> >         pwm1: pwm@20030010 {
>> >
>> >                 ...
>> >                 reg = <0x20030010 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >
>> >         };
>> >
>> >         ...
>> >
>> >         pwm2: pwm@20050020 {
>> >
>> >                 ...
>> >                 reg = <0x20050020 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >
>> >         };
>> >
>> >         pwm3: pwm@20050030 {
>> >
>> >                 ...
>> >                 reg = <0x20050030 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >
>> >         };
>>
>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> (the downsides of trying to guess ahead of time what SoC vendors will
>> name new models).
>
> It did sound like a nice idea at the time to hold the common stuff of
> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> dramatically (including the core) would be called 4xxx or so :-) .

Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
name things arbitrarily by the first machine that had them.  It's
confusing, but sorta less confusing too.


>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>
>> > The clocks would also indicate that there are actually two blocks. I
>> > seem to remember a discussion about whether to handle them as a single
>> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > confusing it with another driver.
>>
>> At this point it seems like the choice has already been made to handle
>> them as separate PWMs.  I can change this choice if you want...
>>
>> >> >> >> This code could go lots of other places, but we've put it here.
>> >> >> >> Why?
>> >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> >> >> >> in
>> >> >> >>
>> >> >> >>   the field.  If we later find a bug in the new IP block and want
>> >> >> >>   to
>> >> >> >>   change our mind about what to use we want it to be easy to
>> >> >> >>   update.
>> >> >
>> >> > Depending on how this muxing works you won't be able to change your
>> >> > mind
>> >> > anyway. If the IP blocks are different then the device tree will
>> >> > effectively make the decision for you. So if you really want to be safe
>> >> > you'd need to have code in the kernel that parses the device tree and
>> >> > checks that all PWM instances are of the new type, then set this
>> >> > register accordingly.
>> >>
>> >> Since there is no documentation about how you would instantiate the
>> >> "old" type in the TRM and no good reason I can think of why someone
>> >> would want to do this, it doesn't seem super fruitful.
>> >
>> > Okay, so if it's not at all documented and never used then yes, we'd
>> > better just ignore it.
>>
>> Heiko just pointed me at the base address for the other block.
>> There's nothing in the rk3288 TRM about it, but we can see the base
>> address.  We could probably guess that it behaves the same as the
>> older PWM if we need to.  I'm still not convinced there's a good
>> reason for someone to use it.
>
> From what I understood the old one was included as a fallback in case some
> drastic problem appeared with the newly developed IP. Similarly for the I2C
> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> seems to have proven stable.
>
> So there really is no incentive to use the old one if no drastic issue has
> appeared with the new one until now.
>
>
>> >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> @@ -24,6 +24,24 @@
>> >> >> >>
>> >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> >> >>  #include "core.h"
>> >> >> >>
>> >> >> >> +static void __init rk3288_init_machine(void)
>> >> >> >> +{
>> >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> >> >
>> >> >> > This region of memory is part of the "grf" "syscon" device
>> >> >> > (according to
>> >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> >> >> > from
>> >> >> > that driver. It looks as if no such driver currently exists, but
>> >> >> > given
>> >> >> > the existence of the device tree node it's fair to assume that one
>> >> >> > will
>> >> >> > eventually be merged.
>> >> >>
>> >> >> The "grf" syscon device is the "general register file".  It's a
>> >> >> collection of totally random registers stuffed together in one address
>> >> >> space.  Sometimes a single 32-bit register has things you need to
>> >> >> tweak for completely different subsystems.
>> >> >>
>> >> >> Most drivers referene the syscon using this in dts:
>> >> >>   rockchip,grf = <&grf>;
>> >> >>
>> >> >> Then the drivers do:
>> >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >> >>
>> >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >> >
>> >> > That's one way to do it. But if it's really just a one-time thing, then
>> >> > you could easily perform the register write from the syscon driver
>> >> > where
>> >> > the memory is already parsed from device tree and mapped. That way you
>> >> > don't have to hardcode the physical address in some other random piece
>> >> > of code and map the memory again.
>> >>
>> >> Well, except that we're using the general "syscon" driver.  I could
>> >> create a whole new driver that "subclasses" this syscon driver I
>> >> suppose.
>> >
>> > Ah, I wasn't aware that there was even something like a generic syscon
>> > driver. But yes, subclassing it sounds like a reasonable thing to do.
>>
>> I will do that if need be, but it's not my favorite.  I will let
>> others chime in.
>
> I guess personally I like the idea best of just setting the relevant bit in
> _probe of the pwm driver, like the i2c driver does:
>
> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>         /* get regmap and set bit */
> }
>
> The downside would be that the bit would be written 4 times, but I guess this
> shouldn't matter to much. And I don't think anybody will get the idea of
> combining both ip variants in one dts anyway.
> And of course in the next SoC the old IP will mostly have gone away and keep
> this somewhat close to the driver and not scatter pwm settings into other
> kernel parts.

I will try to spin this up today.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 16:27                   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

Heiko,

On Wed, Aug 20, 2014 at 9:20 AM, Heiko St?bner <heiko@sntech.de> wrote:
> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> Thierry,
>>
>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>>
>> <thierry.reding@gmail.com> wrote:
>> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> Thierry,
>> >>
>> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >>
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> >> Thierry,
>> >> >>
>> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> >>
>> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> >> >> system
>> >> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> >> >> >> to
>> >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> >> >> exist.
>> >> >
>> >> > A few more questions as to how this actually works. Does it mean there
>> >> > are two physically separate blocks (with different physical addresses)
>> >> > to control the same PWM? And this register simply causes some of the
>> >> > pins to be routed to one or another? As far as I recall there are a
>> >> > number of instances of the PWM block, so the above would need to count
>> >> > for all of them. Or are there separate bits for each of them?
>> >>
>> >> All I have is the TRM (technical reference manual) which doesn't give
>> >> me much more info than I've provided you.  But I can answer some of
>> >> your questoins:
>> >>
>> >> 1. If there are two physically separate blocks then the "old" block is
>> >> not documented in my TRM.
>> >>
>> >> 1a) It's entirely possible it's located at some memory address that is
>> >> marked "Reserved" in the TRM, but I have no idea.
>> >>
>> >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> are supposed to be "compatible" but that the old block is broken and
>> >> thus isn't behaving properly.
>> >>
>> >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> are located at the same physical addresses but somehow work
>> >> differently.  If so, the old IP block isn't documented.
>> >>
>> >>
>> >> 2. As per the patch description, there is a single bit that controls
>> >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> that implements all 4 PWMs.
>> >
>> > Looking at the register offsets in the device tree that seems likely. At
>> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >
>> > same IP block. Their placement in the register map is somewhat strange:
>> >         pwm0: pwm at 20030000 {
>> >
>> >                 ...
>> >                 reg = <0x20030000 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >
>> >         };
>> >
>> >         pwm1: pwm at 20030010 {
>> >
>> >                 ...
>> >                 reg = <0x20030010 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >
>> >         };
>> >
>> >         ...
>> >
>> >         pwm2: pwm at 20050020 {
>> >
>> >                 ...
>> >                 reg = <0x20050020 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >
>> >         };
>> >
>> >         pwm3: pwm at 20050030 {
>> >
>> >                 ...
>> >                 reg = <0x20050030 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >
>> >         };
>>
>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> (the downsides of trying to guess ahead of time what SoC vendors will
>> name new models).
>
> It did sound like a nice idea at the time to hold the common stuff of
> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> dramatically (including the core) would be called 4xxx or so :-) .

Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
name things arbitrarily by the first machine that had them.  It's
confusing, but sorta less confusing too.


>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>
>> > The clocks would also indicate that there are actually two blocks. I
>> > seem to remember a discussion about whether to handle them as a single
>> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > confusing it with another driver.
>>
>> At this point it seems like the choice has already been made to handle
>> them as separate PWMs.  I can change this choice if you want...
>>
>> >> >> >> This code could go lots of other places, but we've put it here.
>> >> >> >> Why?
>> >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> >> >> >> in
>> >> >> >>
>> >> >> >>   the field.  If we later find a bug in the new IP block and want
>> >> >> >>   to
>> >> >> >>   change our mind about what to use we want it to be easy to
>> >> >> >>   update.
>> >> >
>> >> > Depending on how this muxing works you won't be able to change your
>> >> > mind
>> >> > anyway. If the IP blocks are different then the device tree will
>> >> > effectively make the decision for you. So if you really want to be safe
>> >> > you'd need to have code in the kernel that parses the device tree and
>> >> > checks that all PWM instances are of the new type, then set this
>> >> > register accordingly.
>> >>
>> >> Since there is no documentation about how you would instantiate the
>> >> "old" type in the TRM and no good reason I can think of why someone
>> >> would want to do this, it doesn't seem super fruitful.
>> >
>> > Okay, so if it's not at all documented and never used then yes, we'd
>> > better just ignore it.
>>
>> Heiko just pointed me at the base address for the other block.
>> There's nothing in the rk3288 TRM about it, but we can see the base
>> address.  We could probably guess that it behaves the same as the
>> older PWM if we need to.  I'm still not convinced there's a good
>> reason for someone to use it.
>
> From what I understood the old one was included as a fallback in case some
> drastic problem appeared with the newly developed IP. Similarly for the I2C
> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> seems to have proven stable.
>
> So there really is no incentive to use the old one if no drastic issue has
> appeared with the new one until now.
>
>
>> >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> >> >> @@ -24,6 +24,24 @@
>> >> >> >>
>> >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> >> >>  #include "core.h"
>> >> >> >>
>> >> >> >> +static void __init rk3288_init_machine(void)
>> >> >> >> +{
>> >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> >> >
>> >> >> > This region of memory is part of the "grf" "syscon" device
>> >> >> > (according to
>> >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> >> >> > from
>> >> >> > that driver. It looks as if no such driver currently exists, but
>> >> >> > given
>> >> >> > the existence of the device tree node it's fair to assume that one
>> >> >> > will
>> >> >> > eventually be merged.
>> >> >>
>> >> >> The "grf" syscon device is the "general register file".  It's a
>> >> >> collection of totally random registers stuffed together in one address
>> >> >> space.  Sometimes a single 32-bit register has things you need to
>> >> >> tweak for completely different subsystems.
>> >> >>
>> >> >> Most drivers referene the syscon using this in dts:
>> >> >>   rockchip,grf = <&grf>;
>> >> >>
>> >> >> Then the drivers do:
>> >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >> >>
>> >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >> >
>> >> > That's one way to do it. But if it's really just a one-time thing, then
>> >> > you could easily perform the register write from the syscon driver
>> >> > where
>> >> > the memory is already parsed from device tree and mapped. That way you
>> >> > don't have to hardcode the physical address in some other random piece
>> >> > of code and map the memory again.
>> >>
>> >> Well, except that we're using the general "syscon" driver.  I could
>> >> create a whole new driver that "subclasses" this syscon driver I
>> >> suppose.
>> >
>> > Ah, I wasn't aware that there was even something like a generic syscon
>> > driver. But yes, subclassing it sounds like a reasonable thing to do.
>>
>> I will do that if need be, but it's not my favorite.  I will let
>> others chime in.
>
> I guess personally I like the idea best of just setting the relevant bit in
> _probe of the pwm driver, like the i2c driver does:
>
> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>         /* get regmap and set bit */
> }
>
> The downside would be that the bit would be written 4 times, but I guess this
> shouldn't matter to much. And I don't think anybody will get the idea of
> combining both ip variants in one dts anyway.
> And of course in the next SoC the old IP will mostly have gone away and keep
> this somewhat close to the driver and not scatter pwm settings into other
> kernel parts.

I will try to spin this up today.

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 16:27                   ` Doug Anderson
@ 2014-08-20 18:03                     ` Heiko Stübner
  -1 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-20 18:03 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Thierry Reding, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Am Mittwoch, 20. August 2014, 09:27:02 schrieb Doug Anderson:
> Heiko,
> 
> On Wed, Aug 20, 2014 at 9:20 AM, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >> Thierry,
> >> 
> >> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >> 
> >> <thierry.reding@gmail.com> wrote:
> >> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> >> Thierry,
> >> >> 
> >> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> >> 
> >> >> <thierry.reding@gmail.com> wrote:
> >> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> >> >> Thierry,
> >> >> >> 
> >> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> >> >> 
> >> >> >> <thierry.reding@gmail.com> wrote:
> >> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> >> >> >> system
> >> >> >> >> between the old IP block and the new IP block.  The new IP block
> >> >> >> >> is
> >> >> >> >> working and tested and the suggested PWM to use, so setup the
> >> >> >> >> SoC
> >> >> >> >> to
> >> >> >> >> use it and then we can pretend that the other IP block doesn't
> >> >> >> >> exist.
> >> >> > 
> >> >> > A few more questions as to how this actually works. Does it mean
> >> >> > there
> >> >> > are two physically separate blocks (with different physical
> >> >> > addresses)
> >> >> > to control the same PWM? And this register simply causes some of the
> >> >> > pins to be routed to one or another? As far as I recall there are a
> >> >> > number of instances of the PWM block, so the above would need to
> >> >> > count
> >> >> > for all of them. Or are there separate bits for each of them?
> >> >> 
> >> >> All I have is the TRM (technical reference manual) which doesn't give
> >> >> me much more info than I've provided you.  But I can answer some of
> >> >> your questoins:
> >> >> 
> >> >> 1. If there are two physically separate blocks then the "old" block is
> >> >> not documented in my TRM.
> >> >> 
> >> >> 1a) It's entirely possible it's located at some memory address that is
> >> >> marked "Reserved" in the TRM, but I have no idea.
> >> >> 
> >> >> 1b) It's entirely possible that the old IP block and the new IP block
> >> >> are supposed to be "compatible" but that the old block is broken and
> >> >> thus isn't behaving properly.
> >> >> 
> >> >> 1c) It's entirely possible that the old IP block and the new IP block
> >> >> are located at the same physical addresses but somehow work
> >> >> differently.  If so, the old IP block isn't documented.
> >> >> 
> >> >> 
> >> >> 2. As per the patch description, there is a single bit that controls
> >> >> all of the PWMs.  My guess is that there's actually a single IP block
> >> >> that implements all 4 PWMs.
> >> > 
> >> > Looking at the register offsets in the device tree that seems likely.
> >> > At
> >> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >> > 
> >> > same IP block. Their placement in the register map is somewhat strange:
> >> >         pwm0: pwm@20030000 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20030000 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM01>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         pwm1: pwm@20030010 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20030010 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM01>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         ...
> >> >         
> >> >         pwm2: pwm@20050020 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20050020 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM23>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         pwm3: pwm@20050030 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20050030 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM23>;
> >> >                 ...
> >> >         
> >> >         };
> >> 
> >> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >> (the downsides of trying to guess ahead of time what SoC vendors will
> >> name new models).
> > 
> > It did sound like a nice idea at the time to hold the common stuff of
> > rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> > dramatically (including the core) would be called 4xxx or so :-) .
> 
> Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
> name things arbitrarily by the first machine that had them.  It's
> confusing, but sorta less confusing too.

the problem was in this case, that there also is rk3066-specific material which 
made it all the more difficult.

I guess rk3066-common would have been a possibility but still sounds somewhat 
strange, or something else entirely.

I'm not sure but don't think dtsi file-naming counts as API, so we can rename 
the rk3xxx.dtsi file if this gets to confusing in the future.


Heiko

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 18:03                     ` Heiko Stübner
  0 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-20 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

Am Mittwoch, 20. August 2014, 09:27:02 schrieb Doug Anderson:
> Heiko,
> 
> On Wed, Aug 20, 2014 at 9:20 AM, Heiko St?bner <heiko@sntech.de> wrote:
> > Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >> Thierry,
> >> 
> >> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >> 
> >> <thierry.reding@gmail.com> wrote:
> >> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> >> Thierry,
> >> >> 
> >> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> >> 
> >> >> <thierry.reding@gmail.com> wrote:
> >> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> >> >> Thierry,
> >> >> >> 
> >> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> >> >> 
> >> >> >> <thierry.reding@gmail.com> wrote:
> >> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> >> >> >> system
> >> >> >> >> between the old IP block and the new IP block.  The new IP block
> >> >> >> >> is
> >> >> >> >> working and tested and the suggested PWM to use, so setup the
> >> >> >> >> SoC
> >> >> >> >> to
> >> >> >> >> use it and then we can pretend that the other IP block doesn't
> >> >> >> >> exist.
> >> >> > 
> >> >> > A few more questions as to how this actually works. Does it mean
> >> >> > there
> >> >> > are two physically separate blocks (with different physical
> >> >> > addresses)
> >> >> > to control the same PWM? And this register simply causes some of the
> >> >> > pins to be routed to one or another? As far as I recall there are a
> >> >> > number of instances of the PWM block, so the above would need to
> >> >> > count
> >> >> > for all of them. Or are there separate bits for each of them?
> >> >> 
> >> >> All I have is the TRM (technical reference manual) which doesn't give
> >> >> me much more info than I've provided you.  But I can answer some of
> >> >> your questoins:
> >> >> 
> >> >> 1. If there are two physically separate blocks then the "old" block is
> >> >> not documented in my TRM.
> >> >> 
> >> >> 1a) It's entirely possible it's located at some memory address that is
> >> >> marked "Reserved" in the TRM, but I have no idea.
> >> >> 
> >> >> 1b) It's entirely possible that the old IP block and the new IP block
> >> >> are supposed to be "compatible" but that the old block is broken and
> >> >> thus isn't behaving properly.
> >> >> 
> >> >> 1c) It's entirely possible that the old IP block and the new IP block
> >> >> are located at the same physical addresses but somehow work
> >> >> differently.  If so, the old IP block isn't documented.
> >> >> 
> >> >> 
> >> >> 2. As per the patch description, there is a single bit that controls
> >> >> all of the PWMs.  My guess is that there's actually a single IP block
> >> >> that implements all 4 PWMs.
> >> > 
> >> > Looking at the register offsets in the device tree that seems likely.
> >> > At
> >> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >> > 
> >> > same IP block. Their placement in the register map is somewhat strange:
> >> >         pwm0: pwm at 20030000 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20030000 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM01>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         pwm1: pwm at 20030010 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20030010 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM01>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         ...
> >> >         
> >> >         pwm2: pwm at 20050020 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20050020 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM23>;
> >> >                 ...
> >> >         
> >> >         };
> >> >         
> >> >         pwm3: pwm at 20050030 {
> >> >         
> >> >                 ...
> >> >                 reg = <0x20050030 0x10>;
> >> >                 ...
> >> >                 clocks = <&cru PCLK_PWM23>;
> >> >                 ...
> >> >         
> >> >         };
> >> 
> >> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >> (the downsides of trying to guess ahead of time what SoC vendors will
> >> name new models).
> > 
> > It did sound like a nice idea at the time to hold the common stuff of
> > rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> > dramatically (including the core) would be called 4xxx or so :-) .
> 
> Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
> name things arbitrarily by the first machine that had them.  It's
> confusing, but sorta less confusing too.

the problem was in this case, that there also is rk3066-specific material which 
made it all the more difficult.

I guess rk3066-common would have been a possibility but still sounds somewhat 
strange, or something else entirely.

I'm not sure but don't think dtsi file-naming counts as API, so we can rename 
the rk3xxx.dtsi file if this gets to confusing in the future.


Heiko

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 18:03                     ` Heiko Stübner
@ 2014-08-20 20:49                       ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 20:49 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Thierry Reding, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Heiko,

On Wed, Aug 20, 2014 at 11:03 AM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Mittwoch, 20. August 2014, 09:27:02 schrieb Doug Anderson:
>> Heiko,
>>
>> On Wed, Aug 20, 2014 at 9:20 AM, Heiko Stübner <heiko@sntech.de> wrote:
>> > Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> >> Thierry,
>> >>
>> >> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >>
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> >> Thierry,
>> >> >>
>> >> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >> >>
>> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> >> >> Thierry,
>> >> >> >>
>> >> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> >> >>
>> >> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> >> >> >> system
>> >> >> >> >> between the old IP block and the new IP block.  The new IP block
>> >> >> >> >> is
>> >> >> >> >> working and tested and the suggested PWM to use, so setup the
>> >> >> >> >> SoC
>> >> >> >> >> to
>> >> >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> >> >> >> exist.
>> >> >> >
>> >> >> > A few more questions as to how this actually works. Does it mean
>> >> >> > there
>> >> >> > are two physically separate blocks (with different physical
>> >> >> > addresses)
>> >> >> > to control the same PWM? And this register simply causes some of the
>> >> >> > pins to be routed to one or another? As far as I recall there are a
>> >> >> > number of instances of the PWM block, so the above would need to
>> >> >> > count
>> >> >> > for all of them. Or are there separate bits for each of them?
>> >> >>
>> >> >> All I have is the TRM (technical reference manual) which doesn't give
>> >> >> me much more info than I've provided you.  But I can answer some of
>> >> >> your questoins:
>> >> >>
>> >> >> 1. If there are two physically separate blocks then the "old" block is
>> >> >> not documented in my TRM.
>> >> >>
>> >> >> 1a) It's entirely possible it's located at some memory address that is
>> >> >> marked "Reserved" in the TRM, but I have no idea.
>> >> >>
>> >> >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> >> are supposed to be "compatible" but that the old block is broken and
>> >> >> thus isn't behaving properly.
>> >> >>
>> >> >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> >> are located at the same physical addresses but somehow work
>> >> >> differently.  If so, the old IP block isn't documented.
>> >> >>
>> >> >>
>> >> >> 2. As per the patch description, there is a single bit that controls
>> >> >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> >> that implements all 4 PWMs.
>> >> >
>> >> > Looking at the register offsets in the device tree that seems likely.
>> >> > At
>> >> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >> >
>> >> > same IP block. Their placement in the register map is somewhat strange:
>> >> >         pwm0: pwm@20030000 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20030000 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM01>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         pwm1: pwm@20030010 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20030010 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM01>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         ...
>> >> >
>> >> >         pwm2: pwm@20050020 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20050020 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM23>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         pwm3: pwm@20050030 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20050030 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM23>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >>
>> >> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> >> (the downsides of trying to guess ahead of time what SoC vendors will
>> >> name new models).
>> >
>> > It did sound like a nice idea at the time to hold the common stuff of
>> > rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> > dramatically (including the core) would be called 4xxx or so :-) .
>>
>> Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
>> name things arbitrarily by the first machine that had them.  It's
>> confusing, but sorta less confusing too.
>
> the problem was in this case, that there also is rk3066-specific material which
> made it all the more difficult.
>
> I guess rk3066-common would have been a possibility but still sounds somewhat
> strange, or something else entirely.
>
> I'm not sure but don't think dtsi file-naming counts as API, so we can rename
> the rk3xxx.dtsi file if this gets to confusing in the future.

Yup.  Sorry, didn't mean to bring it up.  It's not a huge deal IMHO,
but if you want to submit a patch to rename I'm happy to support it.
Since the dts issues are all around people shipping device tree files
in firmware, I don't think a rename will affect anything...

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-20 20:49                       ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-20 20:49 UTC (permalink / raw)
  To: linux-arm-kernel

Heiko,

On Wed, Aug 20, 2014 at 11:03 AM, Heiko St?bner <heiko@sntech.de> wrote:
> Am Mittwoch, 20. August 2014, 09:27:02 schrieb Doug Anderson:
>> Heiko,
>>
>> On Wed, Aug 20, 2014 at 9:20 AM, Heiko St?bner <heiko@sntech.de> wrote:
>> > Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> >> Thierry,
>> >>
>> >> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >>
>> >> <thierry.reding@gmail.com> wrote:
>> >> > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> >> Thierry,
>> >> >>
>> >> >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >> >>
>> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> >> >> Thierry,
>> >> >> >>
>> >> >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> >> >>
>> >> >> >> <thierry.reding@gmail.com> wrote:
>> >> >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> >> >> >> system
>> >> >> >> >> between the old IP block and the new IP block.  The new IP block
>> >> >> >> >> is
>> >> >> >> >> working and tested and the suggested PWM to use, so setup the
>> >> >> >> >> SoC
>> >> >> >> >> to
>> >> >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> >> >> >> exist.
>> >> >> >
>> >> >> > A few more questions as to how this actually works. Does it mean
>> >> >> > there
>> >> >> > are two physically separate blocks (with different physical
>> >> >> > addresses)
>> >> >> > to control the same PWM? And this register simply causes some of the
>> >> >> > pins to be routed to one or another? As far as I recall there are a
>> >> >> > number of instances of the PWM block, so the above would need to
>> >> >> > count
>> >> >> > for all of them. Or are there separate bits for each of them?
>> >> >>
>> >> >> All I have is the TRM (technical reference manual) which doesn't give
>> >> >> me much more info than I've provided you.  But I can answer some of
>> >> >> your questoins:
>> >> >>
>> >> >> 1. If there are two physically separate blocks then the "old" block is
>> >> >> not documented in my TRM.
>> >> >>
>> >> >> 1a) It's entirely possible it's located at some memory address that is
>> >> >> marked "Reserved" in the TRM, but I have no idea.
>> >> >>
>> >> >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> >> are supposed to be "compatible" but that the old block is broken and
>> >> >> thus isn't behaving properly.
>> >> >>
>> >> >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> >> are located at the same physical addresses but somehow work
>> >> >> differently.  If so, the old IP block isn't documented.
>> >> >>
>> >> >>
>> >> >> 2. As per the patch description, there is a single bit that controls
>> >> >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> >> that implements all 4 PWMs.
>> >> >
>> >> > Looking at the register offsets in the device tree that seems likely.
>> >> > At
>> >> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >> >
>> >> > same IP block. Their placement in the register map is somewhat strange:
>> >> >         pwm0: pwm at 20030000 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20030000 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM01>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         pwm1: pwm at 20030010 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20030010 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM01>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         ...
>> >> >
>> >> >         pwm2: pwm at 20050020 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20050020 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM23>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >> >
>> >> >         pwm3: pwm at 20050030 {
>> >> >
>> >> >                 ...
>> >> >                 reg = <0x20050030 0x10>;
>> >> >                 ...
>> >> >                 clocks = <&cru PCLK_PWM23>;
>> >> >                 ...
>> >> >
>> >> >         };
>> >>
>> >> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> >> (the downsides of trying to guess ahead of time what SoC vendors will
>> >> name new models).
>> >
>> > It did sound like a nice idea at the time to hold the common stuff of
>> > rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> > dramatically (including the core) would be called 4xxx or so :-) .
>>
>> Yes, I've fallen into the same trap.  Now I jump on the bandwagon and
>> name things arbitrarily by the first machine that had them.  It's
>> confusing, but sorta less confusing too.
>
> the problem was in this case, that there also is rk3066-specific material which
> made it all the more difficult.
>
> I guess rk3066-common would have been a possibility but still sounds somewhat
> strange, or something else entirely.
>
> I'm not sure but don't think dtsi file-naming counts as API, so we can rename
> the rk3xxx.dtsi file if this gets to confusing in the future.

Yup.  Sorry, didn't mean to bring it up.  It's not a huge deal IMHO,
but if you want to submit a patch to rename I'm happy to support it.
Since the dts issues are all around people shipping device tree files
in firmware, I don't think a rename will affect anything...

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 15:55               ` Doug Anderson
@ 2014-08-21  6:24                 ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21  6:24 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2793 bytes --]

On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > Looking at the register offsets in the device tree that seems likely. At
> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > same IP block. Their placement in the register map is somewhat strange:
> >
> >         pwm0: pwm@20030000 {
> >                 ...
> >                 reg = <0x20030000 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         };
> >
> >         pwm1: pwm@20030010 {
> >                 ...
> >                 reg = <0x20030010 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         };
> >
> >         ...
> >
> >         pwm2: pwm@20050020 {
> >                 ...
> >                 reg = <0x20050020 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         };
> >
> >         pwm3: pwm@20050030 {
> >                 ...
> >                 reg = <0x20050030 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         };
> 
> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> (the downsides of trying to guess ahead of time what SoC vendors will
> name new models).
> 
> In rk3288 they have the same clocks.  See patch #3 in this series.
> 
> 
> > The clocks would also indicate that there are actually two blocks. I
> > seem to remember a discussion about whether to handle them as a single
> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > confusing it with another driver.
> 
> At this point it seems like the choice has already been made to handle
> them as separate PWMs.  I can change this choice if you want...

Well, looking at patch 3/4 this really does seem to be one single block
providing four PWM channels, so the right thing to do would be to
represent it in one device tree node. But I'll leave it up to Heiko to
decide how he wants to handle this.

One downside of describing it as one device is that it would make the
pinmux handling slightly more difficult, since presumably you'd only
want to apply the pinmux settings when a channel is actually being used.
Currently the pinmux doesn't apply as long as the device remains
disabled in device tree (though enabling it doesn't necessarily mean
that it's being used).

Like I said, it's up to Heiko to decide whether it's worth making this
change (and it'd make sense to apply it to existing DTS files
retroactively) or better to keep what we have.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21  6:24                 ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21  6:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > Looking at the register offsets in the device tree that seems likely. At
> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > same IP block. Their placement in the register map is somewhat strange:
> >
> >         pwm0: pwm at 20030000 {
> >                 ...
> >                 reg = <0x20030000 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         };
> >
> >         pwm1: pwm at 20030010 {
> >                 ...
> >                 reg = <0x20030010 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM01>;
> >                 ...
> >         };
> >
> >         ...
> >
> >         pwm2: pwm at 20050020 {
> >                 ...
> >                 reg = <0x20050020 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         };
> >
> >         pwm3: pwm at 20050030 {
> >                 ...
> >                 reg = <0x20050030 0x10>;
> >                 ...
> >                 clocks = <&cru PCLK_PWM23>;
> >                 ...
> >         };
> 
> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> (the downsides of trying to guess ahead of time what SoC vendors will
> name new models).
> 
> In rk3288 they have the same clocks.  See patch #3 in this series.
> 
> 
> > The clocks would also indicate that there are actually two blocks. I
> > seem to remember a discussion about whether to handle them as a single
> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > confusing it with another driver.
> 
> At this point it seems like the choice has already been made to handle
> them as separate PWMs.  I can change this choice if you want...

Well, looking at patch 3/4 this really does seem to be one single block
providing four PWM channels, so the right thing to do would be to
represent it in one device tree node. But I'll leave it up to Heiko to
decide how he wants to handle this.

One downside of describing it as one device is that it would make the
pinmux handling slightly more difficult, since presumably you'd only
want to apply the pinmux settings when a channel is actually being used.
Currently the pinmux doesn't apply as long as the device remains
disabled in device tree (though enabling it doesn't necessarily mean
that it's being used).

Like I said, it's up to Heiko to decide whether it's worth making this
change (and it'd make sense to apply it to existing DTS files
retroactively) or better to keep what we have.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140821/aeaf8cfd/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-20 16:20                 ` Heiko Stübner
@ 2014-08-21  6:36                   ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21  6:36 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Doug Anderson, Caesar Wang, Sonny Rao, Olof Johansson, Eddie Cai,
	Russell King, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 10860 bytes --]

On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> > Thierry,
> > 
> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> > 
> > <thierry.reding@gmail.com> wrote:
> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> > >> Thierry,
> > >> 
> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> > >> 
> > >> <thierry.reding@gmail.com> wrote:
> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> > >> >> Thierry,
> > >> >> 
> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> > >> >> 
> > >> >> <thierry.reding@gmail.com> wrote:
> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> > >> >> >> system
> > >> >> >> between the old IP block and the new IP block.  The new IP block is
> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> > >> >> >> to
> > >> >> >> use it and then we can pretend that the other IP block doesn't
> > >> >> >> exist.
> > >> > 
> > >> > A few more questions as to how this actually works. Does it mean there
> > >> > are two physically separate blocks (with different physical addresses)
> > >> > to control the same PWM? And this register simply causes some of the
> > >> > pins to be routed to one or another? As far as I recall there are a
> > >> > number of instances of the PWM block, so the above would need to count
> > >> > for all of them. Or are there separate bits for each of them?
> > >> 
> > >> All I have is the TRM (technical reference manual) which doesn't give
> > >> me much more info than I've provided you.  But I can answer some of
> > >> your questoins:
> > >> 
> > >> 1. If there are two physically separate blocks then the "old" block is
> > >> not documented in my TRM.
> > >> 
> > >> 1a) It's entirely possible it's located at some memory address that is
> > >> marked "Reserved" in the TRM, but I have no idea.
> > >> 
> > >> 1b) It's entirely possible that the old IP block and the new IP block
> > >> are supposed to be "compatible" but that the old block is broken and
> > >> thus isn't behaving properly.
> > >> 
> > >> 1c) It's entirely possible that the old IP block and the new IP block
> > >> are located at the same physical addresses but somehow work
> > >> differently.  If so, the old IP block isn't documented.
> > >> 
> > >> 
> > >> 2. As per the patch description, there is a single bit that controls
> > >> all of the PWMs.  My guess is that there's actually a single IP block
> > >> that implements all 4 PWMs.
> > > 
> > > Looking at the register offsets in the device tree that seems likely. At
> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > > 
> > > same IP block. Their placement in the register map is somewhat strange:
> > >         pwm0: pwm@20030000 {
> > >         
> > >                 ...
> > >                 reg = <0x20030000 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm1: pwm@20030010 {
> > >         
> > >                 ...
> > >                 reg = <0x20030010 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         ...
> > >         
> > >         pwm2: pwm@20050020 {
> > >         
> > >                 ...
> > >                 reg = <0x20050020 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm3: pwm@20050030 {
> > >         
> > >                 ...
> > >                 reg = <0x20050030 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > 
> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> > (the downsides of trying to guess ahead of time what SoC vendors will
> > name new models).
> 
> It did sound like a nice idea at the time to hold the common stuff of 
> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed 
> dramatically (including the core) would be called 4xxx or so :-) .
> 
> > 
> > In rk3288 they have the same clocks.  See patch #3 in this series.
> > 
> > > The clocks would also indicate that there are actually two blocks. I
> > > seem to remember a discussion about whether to handle them as a single
> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > > confusing it with another driver.
> > 
> > At this point it seems like the choice has already been made to handle
> > them as separate PWMs.  I can change this choice if you want...
> > 
> > >> >> >> This code could go lots of other places, but we've put it here. 
> > >> >> >> Why?
> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
> > >> >> >> in
> > >> >> >> 
> > >> >> >>   the field.  If we later find a bug in the new IP block and want
> > >> >> >>   to
> > >> >> >>   change our mind about what to use we want it to be easy to
> > >> >> >>   update.
> > >> > 
> > >> > Depending on how this muxing works you won't be able to change your
> > >> > mind
> > >> > anyway. If the IP blocks are different then the device tree will
> > >> > effectively make the decision for you. So if you really want to be safe
> > >> > you'd need to have code in the kernel that parses the device tree and
> > >> > checks that all PWM instances are of the new type, then set this
> > >> > register accordingly.
> > >> 
> > >> Since there is no documentation about how you would instantiate the
> > >> "old" type in the TRM and no good reason I can think of why someone
> > >> would want to do this, it doesn't seem super fruitful.
> > > 
> > > Okay, so if it's not at all documented and never used then yes, we'd
> > > better just ignore it.
> > 
> > Heiko just pointed me at the base address for the other block.
> > There's nothing in the rk3288 TRM about it, but we can see the base
> > address.  We could probably guess that it behaves the same as the
> > older PWM if we need to.  I'm still not convinced there's a good
> > reason for someone to use it.
> 
> From what I understood the old one was included as a fallback in case some 
> drastic problem appeared with the newly developed IP. Similarly for the I2C 
> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both 
> old and new i2c IP and now the rk3288 only contains the new one, as the new IP 
> seems to have proven stable.
> 
> So there really is no incentive to use the old one if no drastic issue has 
> appeared with the new one until now.
> 
> 
> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> @@ -24,6 +24,24 @@
> > >> >> >> 
> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
> > >> >> >>  #include "core.h"
> > >> >> >> 
> > >> >> >> +static void __init rk3288_init_machine(void)
> > >> >> >> +{
> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> > >> >> > 
> > >> >> > This region of memory is part of the "grf" "syscon" device
> > >> >> > (according to
> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> > >> >> > from
> > >> >> > that driver. It looks as if no such driver currently exists, but
> > >> >> > given
> > >> >> > the existence of the device tree node it's fair to assume that one
> > >> >> > will
> > >> >> > eventually be merged.
> > >> >> 
> > >> >> The "grf" syscon device is the "general register file".  It's a
> > >> >> collection of totally random registers stuffed together in one address
> > >> >> space.  Sometimes a single 32-bit register has things you need to
> > >> >> tweak for completely different subsystems.
> > >> >> 
> > >> >> Most drivers referene the syscon using this in dts:
> > >> >>   rockchip,grf = <&grf>;
> > >> >> 
> > >> >> Then the drivers do:
> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> > >> >> 
> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> > >> > 
> > >> > That's one way to do it. But if it's really just a one-time thing, then
> > >> > you could easily perform the register write from the syscon driver
> > >> > where
> > >> > the memory is already parsed from device tree and mapped. That way you
> > >> > don't have to hardcode the physical address in some other random piece
> > >> > of code and map the memory again.
> > >> 
> > >> Well, except that we're using the general "syscon" driver.  I could
> > >> create a whole new driver that "subclasses" this syscon driver I
> > >> suppose.
> > > 
> > > Ah, I wasn't aware that there was even something like a generic syscon
> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
> > 
> > I will do that if need be, but it's not my favorite.  I will let
> > others chime in.
> 
> I guess personally I like the idea best of just setting the relevant bit in 
> _probe of the pwm driver, like the i2c driver does:
> 
> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> 	/* get regmap and set bit */
> }
> 
> The downside would be that the bit would be written 4 times, but I guess this 
> shouldn't matter to much. And I don't think anybody will get the idea of 
> combining both ip variants in one dts anyway.
> And of course in the next SoC the old IP will mostly have gone away and keep 
> this somewhat close to the driver and not scatter pwm settings into other 
> kernel parts.
> 
> Hacking up the syscon driver feels bad to me, especially as it is meant to be 
> generic and export such shared registers to other drivers for just these stuff.

I think using syscon in the first place is bad. In my opinion it would
be far better to export an explicit API from drivers that are currently
"implemented" as syscon. The thing is, nothing about syscon is truly
generic. All it provides is a memory-mapped I/O region and lets drivers
do to that memory region whatever they wants. But ioremap() can be used
for that purpose already. Yet we have infrastructure to prevent drivers
from doing that (request_resource() and friends) because it's usually a
bad idea. All syscon really gives us is a ratified way of doing things
that are otherwise frowned upon.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21  6:36                   ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21  6:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> > Thierry,
> > 
> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> > 
> > <thierry.reding@gmail.com> wrote:
> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> > >> Thierry,
> > >> 
> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> > >> 
> > >> <thierry.reding@gmail.com> wrote:
> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> > >> >> Thierry,
> > >> >> 
> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> > >> >> 
> > >> >> <thierry.reding@gmail.com> wrote:
> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> > >> >> >> system
> > >> >> >> between the old IP block and the new IP block.  The new IP block is
> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> > >> >> >> to
> > >> >> >> use it and then we can pretend that the other IP block doesn't
> > >> >> >> exist.
> > >> > 
> > >> > A few more questions as to how this actually works. Does it mean there
> > >> > are two physically separate blocks (with different physical addresses)
> > >> > to control the same PWM? And this register simply causes some of the
> > >> > pins to be routed to one or another? As far as I recall there are a
> > >> > number of instances of the PWM block, so the above would need to count
> > >> > for all of them. Or are there separate bits for each of them?
> > >> 
> > >> All I have is the TRM (technical reference manual) which doesn't give
> > >> me much more info than I've provided you.  But I can answer some of
> > >> your questoins:
> > >> 
> > >> 1. If there are two physically separate blocks then the "old" block is
> > >> not documented in my TRM.
> > >> 
> > >> 1a) It's entirely possible it's located at some memory address that is
> > >> marked "Reserved" in the TRM, but I have no idea.
> > >> 
> > >> 1b) It's entirely possible that the old IP block and the new IP block
> > >> are supposed to be "compatible" but that the old block is broken and
> > >> thus isn't behaving properly.
> > >> 
> > >> 1c) It's entirely possible that the old IP block and the new IP block
> > >> are located at the same physical addresses but somehow work
> > >> differently.  If so, the old IP block isn't documented.
> > >> 
> > >> 
> > >> 2. As per the patch description, there is a single bit that controls
> > >> all of the PWMs.  My guess is that there's actually a single IP block
> > >> that implements all 4 PWMs.
> > > 
> > > Looking at the register offsets in the device tree that seems likely. At
> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > > 
> > > same IP block. Their placement in the register map is somewhat strange:
> > >         pwm0: pwm at 20030000 {
> > >         
> > >                 ...
> > >                 reg = <0x20030000 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm1: pwm at 20030010 {
> > >         
> > >                 ...
> > >                 reg = <0x20030010 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         ...
> > >         
> > >         pwm2: pwm at 20050020 {
> > >         
> > >                 ...
> > >                 reg = <0x20050020 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm3: pwm at 20050030 {
> > >         
> > >                 ...
> > >                 reg = <0x20050030 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > 
> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> > (the downsides of trying to guess ahead of time what SoC vendors will
> > name new models).
> 
> It did sound like a nice idea at the time to hold the common stuff of 
> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed 
> dramatically (including the core) would be called 4xxx or so :-) .
> 
> > 
> > In rk3288 they have the same clocks.  See patch #3 in this series.
> > 
> > > The clocks would also indicate that there are actually two blocks. I
> > > seem to remember a discussion about whether to handle them as a single
> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > > confusing it with another driver.
> > 
> > At this point it seems like the choice has already been made to handle
> > them as separate PWMs.  I can change this choice if you want...
> > 
> > >> >> >> This code could go lots of other places, but we've put it here. 
> > >> >> >> Why?
> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
> > >> >> >> in
> > >> >> >> 
> > >> >> >>   the field.  If we later find a bug in the new IP block and want
> > >> >> >>   to
> > >> >> >>   change our mind about what to use we want it to be easy to
> > >> >> >>   update.
> > >> > 
> > >> > Depending on how this muxing works you won't be able to change your
> > >> > mind
> > >> > anyway. If the IP blocks are different then the device tree will
> > >> > effectively make the decision for you. So if you really want to be safe
> > >> > you'd need to have code in the kernel that parses the device tree and
> > >> > checks that all PWM instances are of the new type, then set this
> > >> > register accordingly.
> > >> 
> > >> Since there is no documentation about how you would instantiate the
> > >> "old" type in the TRM and no good reason I can think of why someone
> > >> would want to do this, it doesn't seem super fruitful.
> > > 
> > > Okay, so if it's not at all documented and never used then yes, we'd
> > > better just ignore it.
> > 
> > Heiko just pointed me at the base address for the other block.
> > There's nothing in the rk3288 TRM about it, but we can see the base
> > address.  We could probably guess that it behaves the same as the
> > older PWM if we need to.  I'm still not convinced there's a good
> > reason for someone to use it.
> 
> From what I understood the old one was included as a fallback in case some 
> drastic problem appeared with the newly developed IP. Similarly for the I2C 
> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both 
> old and new i2c IP and now the rk3288 only contains the new one, as the new IP 
> seems to have proven stable.
> 
> So there really is no incentive to use the old one if no drastic issue has 
> appeared with the new one until now.
> 
> 
> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> > >> >> >> @@ -24,6 +24,24 @@
> > >> >> >> 
> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
> > >> >> >>  #include "core.h"
> > >> >> >> 
> > >> >> >> +static void __init rk3288_init_machine(void)
> > >> >> >> +{
> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> > >> >> > 
> > >> >> > This region of memory is part of the "grf" "syscon" device
> > >> >> > (according to
> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> > >> >> > from
> > >> >> > that driver. It looks as if no such driver currently exists, but
> > >> >> > given
> > >> >> > the existence of the device tree node it's fair to assume that one
> > >> >> > will
> > >> >> > eventually be merged.
> > >> >> 
> > >> >> The "grf" syscon device is the "general register file".  It's a
> > >> >> collection of totally random registers stuffed together in one address
> > >> >> space.  Sometimes a single 32-bit register has things you need to
> > >> >> tweak for completely different subsystems.
> > >> >> 
> > >> >> Most drivers referene the syscon using this in dts:
> > >> >>   rockchip,grf = <&grf>;
> > >> >> 
> > >> >> Then the drivers do:
> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> > >> >> 
> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> > >> > 
> > >> > That's one way to do it. But if it's really just a one-time thing, then
> > >> > you could easily perform the register write from the syscon driver
> > >> > where
> > >> > the memory is already parsed from device tree and mapped. That way you
> > >> > don't have to hardcode the physical address in some other random piece
> > >> > of code and map the memory again.
> > >> 
> > >> Well, except that we're using the general "syscon" driver.  I could
> > >> create a whole new driver that "subclasses" this syscon driver I
> > >> suppose.
> > > 
> > > Ah, I wasn't aware that there was even something like a generic syscon
> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
> > 
> > I will do that if need be, but it's not my favorite.  I will let
> > others chime in.
> 
> I guess personally I like the idea best of just setting the relevant bit in 
> _probe of the pwm driver, like the i2c driver does:
> 
> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> 	/* get regmap and set bit */
> }
> 
> The downside would be that the bit would be written 4 times, but I guess this 
> shouldn't matter to much. And I don't think anybody will get the idea of 
> combining both ip variants in one dts anyway.
> And of course in the next SoC the old IP will mostly have gone away and keep 
> this somewhat close to the driver and not scatter pwm settings into other 
> kernel parts.
> 
> Hacking up the syscon driver feels bad to me, especially as it is meant to be 
> generic and export such shared registers to other drivers for just these stuff.

I think using syscon in the first place is bad. In my opinion it would
be far better to export an explicit API from drivers that are currently
"implemented" as syscon. The thing is, nothing about syscon is truly
generic. All it provides is a memory-mapped I/O region and lets drivers
do to that memory region whatever they wants. But ioremap() can be used
for that purpose already. Yet we have infrastructure to prevent drivers
from doing that (request_resource() and friends) because it's usually a
bad idea. All syscon really gives us is a ratified way of doing things
that are otherwise frowned upon.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140821/431976fe/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21  6:36                   ` Thierry Reding
@ 2014-08-21 15:38                     ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-21 15:38 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stübner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel,
	Tomasz Figa

Thierry,

On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> > Thierry,
>> >
>> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >
>> > <thierry.reding@gmail.com> wrote:
>> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> > >> Thierry,
>> > >>
>> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> > >>
>> > >> <thierry.reding@gmail.com> wrote:
>> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> > >> >> Thierry,
>> > >> >>
>> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> > >> >>
>> > >> >> <thierry.reding@gmail.com> wrote:
>> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> > >> >> >> system
>> > >> >> >> between the old IP block and the new IP block.  The new IP block is
>> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> > >> >> >> to
>> > >> >> >> use it and then we can pretend that the other IP block doesn't
>> > >> >> >> exist.
>> > >> >
>> > >> > A few more questions as to how this actually works. Does it mean there
>> > >> > are two physically separate blocks (with different physical addresses)
>> > >> > to control the same PWM? And this register simply causes some of the
>> > >> > pins to be routed to one or another? As far as I recall there are a
>> > >> > number of instances of the PWM block, so the above would need to count
>> > >> > for all of them. Or are there separate bits for each of them?
>> > >>
>> > >> All I have is the TRM (technical reference manual) which doesn't give
>> > >> me much more info than I've provided you.  But I can answer some of
>> > >> your questoins:
>> > >>
>> > >> 1. If there are two physically separate blocks then the "old" block is
>> > >> not documented in my TRM.
>> > >>
>> > >> 1a) It's entirely possible it's located at some memory address that is
>> > >> marked "Reserved" in the TRM, but I have no idea.
>> > >>
>> > >> 1b) It's entirely possible that the old IP block and the new IP block
>> > >> are supposed to be "compatible" but that the old block is broken and
>> > >> thus isn't behaving properly.
>> > >>
>> > >> 1c) It's entirely possible that the old IP block and the new IP block
>> > >> are located at the same physical addresses but somehow work
>> > >> differently.  If so, the old IP block isn't documented.
>> > >>
>> > >>
>> > >> 2. As per the patch description, there is a single bit that controls
>> > >> all of the PWMs.  My guess is that there's actually a single IP block
>> > >> that implements all 4 PWMs.
>> > >
>> > > Looking at the register offsets in the device tree that seems likely. At
>> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> > >
>> > > same IP block. Their placement in the register map is somewhat strange:
>> > >         pwm0: pwm@20030000 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20030000 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM01>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         pwm1: pwm@20030010 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20030010 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM01>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         ...
>> > >
>> > >         pwm2: pwm@20050020 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20050020 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM23>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         pwm3: pwm@20050030 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20050030 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM23>;
>> > >                 ...
>> > >
>> > >         };
>> >
>> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> > (the downsides of trying to guess ahead of time what SoC vendors will
>> > name new models).
>>
>> It did sound like a nice idea at the time to hold the common stuff of
>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> dramatically (including the core) would be called 4xxx or so :-) .
>>
>> >
>> > In rk3288 they have the same clocks.  See patch #3 in this series.
>> >
>> > > The clocks would also indicate that there are actually two blocks. I
>> > > seem to remember a discussion about whether to handle them as a single
>> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > > confusing it with another driver.
>> >
>> > At this point it seems like the choice has already been made to handle
>> > them as separate PWMs.  I can change this choice if you want...
>> >
>> > >> >> >> This code could go lots of other places, but we've put it here.
>> > >> >> >> Why?
>> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> > >> >> >> in
>> > >> >> >>
>> > >> >> >>   the field.  If we later find a bug in the new IP block and want
>> > >> >> >>   to
>> > >> >> >>   change our mind about what to use we want it to be easy to
>> > >> >> >>   update.
>> > >> >
>> > >> > Depending on how this muxing works you won't be able to change your
>> > >> > mind
>> > >> > anyway. If the IP blocks are different then the device tree will
>> > >> > effectively make the decision for you. So if you really want to be safe
>> > >> > you'd need to have code in the kernel that parses the device tree and
>> > >> > checks that all PWM instances are of the new type, then set this
>> > >> > register accordingly.
>> > >>
>> > >> Since there is no documentation about how you would instantiate the
>> > >> "old" type in the TRM and no good reason I can think of why someone
>> > >> would want to do this, it doesn't seem super fruitful.
>> > >
>> > > Okay, so if it's not at all documented and never used then yes, we'd
>> > > better just ignore it.
>> >
>> > Heiko just pointed me at the base address for the other block.
>> > There's nothing in the rk3288 TRM about it, but we can see the base
>> > address.  We could probably guess that it behaves the same as the
>> > older PWM if we need to.  I'm still not convinced there's a good
>> > reason for someone to use it.
>>
>> From what I understood the old one was included as a fallback in case some
>> drastic problem appeared with the newly developed IP. Similarly for the I2C
>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>> seems to have proven stable.
>>
>> So there really is no incentive to use the old one if no drastic issue has
>> appeared with the new one until now.
>>
>>
>> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> @@ -24,6 +24,24 @@
>> > >> >> >>
>> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> > >> >> >>  #include "core.h"
>> > >> >> >>
>> > >> >> >> +static void __init rk3288_init_machine(void)
>> > >> >> >> +{
>> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> > >> >> >
>> > >> >> > This region of memory is part of the "grf" "syscon" device
>> > >> >> > (according to
>> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> > >> >> > from
>> > >> >> > that driver. It looks as if no such driver currently exists, but
>> > >> >> > given
>> > >> >> > the existence of the device tree node it's fair to assume that one
>> > >> >> > will
>> > >> >> > eventually be merged.
>> > >> >>
>> > >> >> The "grf" syscon device is the "general register file".  It's a
>> > >> >> collection of totally random registers stuffed together in one address
>> > >> >> space.  Sometimes a single 32-bit register has things you need to
>> > >> >> tweak for completely different subsystems.
>> > >> >>
>> > >> >> Most drivers referene the syscon using this in dts:
>> > >> >>   rockchip,grf = <&grf>;
>> > >> >>
>> > >> >> Then the drivers do:
>> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> > >> >>
>> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> > >> >
>> > >> > That's one way to do it. But if it's really just a one-time thing, then
>> > >> > you could easily perform the register write from the syscon driver
>> > >> > where
>> > >> > the memory is already parsed from device tree and mapped. That way you
>> > >> > don't have to hardcode the physical address in some other random piece
>> > >> > of code and map the memory again.
>> > >>
>> > >> Well, except that we're using the general "syscon" driver.  I could
>> > >> create a whole new driver that "subclasses" this syscon driver I
>> > >> suppose.
>> > >
>> > > Ah, I wasn't aware that there was even something like a generic syscon
>> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
>> >
>> > I will do that if need be, but it's not my favorite.  I will let
>> > others chime in.
>>
>> I guess personally I like the idea best of just setting the relevant bit in
>> _probe of the pwm driver, like the i2c driver does:
>>
>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>>       /* get regmap and set bit */
>> }
>>
>> The downside would be that the bit would be written 4 times, but I guess this
>> shouldn't matter to much. And I don't think anybody will get the idea of
>> combining both ip variants in one dts anyway.
>> And of course in the next SoC the old IP will mostly have gone away and keep
>> this somewhat close to the driver and not scatter pwm settings into other
>> kernel parts.
>>
>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>> generic and export such shared registers to other drivers for just these stuff.
>
> I think using syscon in the first place is bad. In my opinion it would
> be far better to export an explicit API from drivers that are currently
> "implemented" as syscon. The thing is, nothing about syscon is truly
> generic. All it provides is a memory-mapped I/O region and lets drivers
> do to that memory region whatever they wants. But ioremap() can be used
> for that purpose already. Yet we have infrastructure to prevent drivers
> from doing that (request_resource() and friends) because it's usually a
> bad idea. All syscon really gives us is a ratified way of doing things
> that are otherwise frowned upon.

Agreed that it's a bit awkward, but it's the generally accepted way of
doing things across multiple drivers as far as I can tell...

In exynos we were also doing this.  Another alternative (which I saw
used before syscon) was just to list a second address in the "reg =
<>".  The second address might only be 4 bytes big if only a single
32-bit register was needed.  That started failing because sometimes
two drivers needed to access the same 32-bit register.  Added Tomasz
to this thread since I remember him being a fan of solving this with
syscon.


At the moment I'm not planning to spin this patch.  If folks come up
with a solution that they definitely like better I'm happy to spin it,
but for now this seems to work and doesn't seem (to me) to be terribly
worse than the alternatives proposed so far.


-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 15:38                     ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-21 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> > Thierry,
>> >
>> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >
>> > <thierry.reding@gmail.com> wrote:
>> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> > >> Thierry,
>> > >>
>> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> > >>
>> > >> <thierry.reding@gmail.com> wrote:
>> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> > >> >> Thierry,
>> > >> >>
>> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> > >> >>
>> > >> >> <thierry.reding@gmail.com> wrote:
>> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> > >> >> >> system
>> > >> >> >> between the old IP block and the new IP block.  The new IP block is
>> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> > >> >> >> to
>> > >> >> >> use it and then we can pretend that the other IP block doesn't
>> > >> >> >> exist.
>> > >> >
>> > >> > A few more questions as to how this actually works. Does it mean there
>> > >> > are two physically separate blocks (with different physical addresses)
>> > >> > to control the same PWM? And this register simply causes some of the
>> > >> > pins to be routed to one or another? As far as I recall there are a
>> > >> > number of instances of the PWM block, so the above would need to count
>> > >> > for all of them. Or are there separate bits for each of them?
>> > >>
>> > >> All I have is the TRM (technical reference manual) which doesn't give
>> > >> me much more info than I've provided you.  But I can answer some of
>> > >> your questoins:
>> > >>
>> > >> 1. If there are two physically separate blocks then the "old" block is
>> > >> not documented in my TRM.
>> > >>
>> > >> 1a) It's entirely possible it's located at some memory address that is
>> > >> marked "Reserved" in the TRM, but I have no idea.
>> > >>
>> > >> 1b) It's entirely possible that the old IP block and the new IP block
>> > >> are supposed to be "compatible" but that the old block is broken and
>> > >> thus isn't behaving properly.
>> > >>
>> > >> 1c) It's entirely possible that the old IP block and the new IP block
>> > >> are located at the same physical addresses but somehow work
>> > >> differently.  If so, the old IP block isn't documented.
>> > >>
>> > >>
>> > >> 2. As per the patch description, there is a single bit that controls
>> > >> all of the PWMs.  My guess is that there's actually a single IP block
>> > >> that implements all 4 PWMs.
>> > >
>> > > Looking at the register offsets in the device tree that seems likely. At
>> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> > >
>> > > same IP block. Their placement in the register map is somewhat strange:
>> > >         pwm0: pwm at 20030000 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20030000 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM01>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         pwm1: pwm at 20030010 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20030010 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM01>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         ...
>> > >
>> > >         pwm2: pwm at 20050020 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20050020 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM23>;
>> > >                 ...
>> > >
>> > >         };
>> > >
>> > >         pwm3: pwm at 20050030 {
>> > >
>> > >                 ...
>> > >                 reg = <0x20050030 0x10>;
>> > >                 ...
>> > >                 clocks = <&cru PCLK_PWM23>;
>> > >                 ...
>> > >
>> > >         };
>> >
>> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> > (the downsides of trying to guess ahead of time what SoC vendors will
>> > name new models).
>>
>> It did sound like a nice idea at the time to hold the common stuff of
>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> dramatically (including the core) would be called 4xxx or so :-) .
>>
>> >
>> > In rk3288 they have the same clocks.  See patch #3 in this series.
>> >
>> > > The clocks would also indicate that there are actually two blocks. I
>> > > seem to remember a discussion about whether to handle them as a single
>> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > > confusing it with another driver.
>> >
>> > At this point it seems like the choice has already been made to handle
>> > them as separate PWMs.  I can change this choice if you want...
>> >
>> > >> >> >> This code could go lots of other places, but we've put it here.
>> > >> >> >> Why?
>> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> > >> >> >> in
>> > >> >> >>
>> > >> >> >>   the field.  If we later find a bug in the new IP block and want
>> > >> >> >>   to
>> > >> >> >>   change our mind about what to use we want it to be easy to
>> > >> >> >>   update.
>> > >> >
>> > >> > Depending on how this muxing works you won't be able to change your
>> > >> > mind
>> > >> > anyway. If the IP blocks are different then the device tree will
>> > >> > effectively make the decision for you. So if you really want to be safe
>> > >> > you'd need to have code in the kernel that parses the device tree and
>> > >> > checks that all PWM instances are of the new type, then set this
>> > >> > register accordingly.
>> > >>
>> > >> Since there is no documentation about how you would instantiate the
>> > >> "old" type in the TRM and no good reason I can think of why someone
>> > >> would want to do this, it doesn't seem super fruitful.
>> > >
>> > > Okay, so if it's not at all documented and never used then yes, we'd
>> > > better just ignore it.
>> >
>> > Heiko just pointed me at the base address for the other block.
>> > There's nothing in the rk3288 TRM about it, but we can see the base
>> > address.  We could probably guess that it behaves the same as the
>> > older PWM if we need to.  I'm still not convinced there's a good
>> > reason for someone to use it.
>>
>> From what I understood the old one was included as a fallback in case some
>> drastic problem appeared with the newly developed IP. Similarly for the I2C
>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>> seems to have proven stable.
>>
>> So there really is no incentive to use the old one if no drastic issue has
>> appeared with the new one until now.
>>
>>
>> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> > >> >> >> @@ -24,6 +24,24 @@
>> > >> >> >>
>> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> > >> >> >>  #include "core.h"
>> > >> >> >>
>> > >> >> >> +static void __init rk3288_init_machine(void)
>> > >> >> >> +{
>> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> > >> >> >
>> > >> >> > This region of memory is part of the "grf" "syscon" device
>> > >> >> > (according to
>> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> > >> >> > from
>> > >> >> > that driver. It looks as if no such driver currently exists, but
>> > >> >> > given
>> > >> >> > the existence of the device tree node it's fair to assume that one
>> > >> >> > will
>> > >> >> > eventually be merged.
>> > >> >>
>> > >> >> The "grf" syscon device is the "general register file".  It's a
>> > >> >> collection of totally random registers stuffed together in one address
>> > >> >> space.  Sometimes a single 32-bit register has things you need to
>> > >> >> tweak for completely different subsystems.
>> > >> >>
>> > >> >> Most drivers referene the syscon using this in dts:
>> > >> >>   rockchip,grf = <&grf>;
>> > >> >>
>> > >> >> Then the drivers do:
>> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> > >> >>
>> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> > >> >
>> > >> > That's one way to do it. But if it's really just a one-time thing, then
>> > >> > you could easily perform the register write from the syscon driver
>> > >> > where
>> > >> > the memory is already parsed from device tree and mapped. That way you
>> > >> > don't have to hardcode the physical address in some other random piece
>> > >> > of code and map the memory again.
>> > >>
>> > >> Well, except that we're using the general "syscon" driver.  I could
>> > >> create a whole new driver that "subclasses" this syscon driver I
>> > >> suppose.
>> > >
>> > > Ah, I wasn't aware that there was even something like a generic syscon
>> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
>> >
>> > I will do that if need be, but it's not my favorite.  I will let
>> > others chime in.
>>
>> I guess personally I like the idea best of just setting the relevant bit in
>> _probe of the pwm driver, like the i2c driver does:
>>
>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>>       /* get regmap and set bit */
>> }
>>
>> The downside would be that the bit would be written 4 times, but I guess this
>> shouldn't matter to much. And I don't think anybody will get the idea of
>> combining both ip variants in one dts anyway.
>> And of course in the next SoC the old IP will mostly have gone away and keep
>> this somewhat close to the driver and not scatter pwm settings into other
>> kernel parts.
>>
>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>> generic and export such shared registers to other drivers for just these stuff.
>
> I think using syscon in the first place is bad. In my opinion it would
> be far better to export an explicit API from drivers that are currently
> "implemented" as syscon. The thing is, nothing about syscon is truly
> generic. All it provides is a memory-mapped I/O region and lets drivers
> do to that memory region whatever they wants. But ioremap() can be used
> for that purpose already. Yet we have infrastructure to prevent drivers
> from doing that (request_resource() and friends) because it's usually a
> bad idea. All syscon really gives us is a ratified way of doing things
> that are otherwise frowned upon.

Agreed that it's a bit awkward, but it's the generally accepted way of
doing things across multiple drivers as far as I can tell...

In exynos we were also doing this.  Another alternative (which I saw
used before syscon) was just to list a second address in the "reg =
<>".  The second address might only be 4 bytes big if only a single
32-bit register was needed.  That started failing because sometimes
two drivers needed to access the same 32-bit register.  Added Tomasz
to this thread since I remember him being a fan of solving this with
syscon.


At the moment I'm not planning to spin this patch.  If folks come up
with a solution that they definitely like better I'm happy to spin it,
but for now this seems to work and doesn't seem (to me) to be terribly
worse than the alternatives proposed so far.


-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21  6:24                 ` Thierry Reding
@ 2014-08-21 15:39                   ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-21 15:39 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stuebner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

Thierry and Heiko

On Wed, Aug 20, 2014 at 11:24 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
> [...]
>> > Looking at the register offsets in the device tree that seems likely. At
>> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> > same IP block. Their placement in the register map is somewhat strange:
>> >
>> >         pwm0: pwm@20030000 {
>> >                 ...
>> >                 reg = <0x20030000 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >         };
>> >
>> >         pwm1: pwm@20030010 {
>> >                 ...
>> >                 reg = <0x20030010 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >         };
>> >
>> >         ...
>> >
>> >         pwm2: pwm@20050020 {
>> >                 ...
>> >                 reg = <0x20050020 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >         };
>> >
>> >         pwm3: pwm@20050030 {
>> >                 ...
>> >                 reg = <0x20050030 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >         };
>>
>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> (the downsides of trying to guess ahead of time what SoC vendors will
>> name new models).
>>
>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>
>>
>> > The clocks would also indicate that there are actually two blocks. I
>> > seem to remember a discussion about whether to handle them as a single
>> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > confusing it with another driver.
>>
>> At this point it seems like the choice has already been made to handle
>> them as separate PWMs.  I can change this choice if you want...
>
> Well, looking at patch 3/4 this really does seem to be one single block
> providing four PWM channels, so the right thing to do would be to
> represent it in one device tree node. But I'll leave it up to Heiko to
> decide how he wants to handle this.
>
> One downside of describing it as one device is that it would make the
> pinmux handling slightly more difficult, since presumably you'd only
> want to apply the pinmux settings when a channel is actually being used.
> Currently the pinmux doesn't apply as long as the device remains
> disabled in device tree (though enabling it doesn't necessarily mean
> that it's being used).
>
> Like I said, it's up to Heiko to decide whether it's worth making this
> change (and it'd make sense to apply it to existing DTS files
> retroactively) or better to keep what we have.

Please let me know if you'd like me to spin.  Otherwise I'll assume
this is OK as is.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 15:39                   ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-21 15:39 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry and Heiko

On Wed, Aug 20, 2014 at 11:24 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> wrote:
> [...]
>> > Looking at the register offsets in the device tree that seems likely. At
>> > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> > same IP block. Their placement in the register map is somewhat strange:
>> >
>> >         pwm0: pwm at 20030000 {
>> >                 ...
>> >                 reg = <0x20030000 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >         };
>> >
>> >         pwm1: pwm at 20030010 {
>> >                 ...
>> >                 reg = <0x20030010 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM01>;
>> >                 ...
>> >         };
>> >
>> >         ...
>> >
>> >         pwm2: pwm at 20050020 {
>> >                 ...
>> >                 reg = <0x20050020 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >         };
>> >
>> >         pwm3: pwm at 20050030 {
>> >                 ...
>> >                 reg = <0x20050030 0x10>;
>> >                 ...
>> >                 clocks = <&cru PCLK_PWM23>;
>> >                 ...
>> >         };
>>
>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> (the downsides of trying to guess ahead of time what SoC vendors will
>> name new models).
>>
>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>
>>
>> > The clocks would also indicate that there are actually two blocks. I
>> > seem to remember a discussion about whether to handle them as a single
>> > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> > confusing it with another driver.
>>
>> At this point it seems like the choice has already been made to handle
>> them as separate PWMs.  I can change this choice if you want...
>
> Well, looking at patch 3/4 this really does seem to be one single block
> providing four PWM channels, so the right thing to do would be to
> represent it in one device tree node. But I'll leave it up to Heiko to
> decide how he wants to handle this.
>
> One downside of describing it as one device is that it would make the
> pinmux handling slightly more difficult, since presumably you'd only
> want to apply the pinmux settings when a channel is actually being used.
> Currently the pinmux doesn't apply as long as the device remains
> disabled in device tree (though enabling it doesn't necessarily mean
> that it's being used).
>
> Like I said, it's up to Heiko to decide whether it's worth making this
> change (and it'd make sense to apply it to existing DTS files
> retroactively) or better to keep what we have.

Please let me know if you'd like me to spin.  Otherwise I'll assume
this is OK as is.

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21 15:38                     ` Doug Anderson
@ 2014-08-21 15:49                       ` Tomasz Figa
  -1 siblings, 0 replies; 69+ messages in thread
From: Tomasz Figa @ 2014-08-21 15:49 UTC (permalink / raw)
  To: Doug Anderson, Thierry Reding
  Cc: Heiko Stübner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel

On 21.08.2014 17:38, Doug Anderson wrote:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
>> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
>>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>>>> Thierry,
>>>>
>>>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>>>>
>>>> <thierry.reding@gmail.com> wrote:
>>>>> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>>>>>> Thierry,
>>>>>>
>>>>>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>>>>>>
>>>>>> <thierry.reding@gmail.com> wrote:
>>>>>>> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>>>>>>>> Thierry,
>>>>>>>>
>>>>>>>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>>>>>>>>
>>>>>>>> <thierry.reding@gmail.com> wrote:
>>>>>>>>> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>>>>>>>>>> The rk3288 SoC has an option to switch all of the PWMs in the
>>>>>>>>>> system
>>>>>>>>>> between the old IP block and the new IP block.  The new IP block is
>>>>>>>>>> working and tested and the suggested PWM to use, so setup the SoC
>>>>>>>>>> to
>>>>>>>>>> use it and then we can pretend that the other IP block doesn't
>>>>>>>>>> exist.
>>>>>>>
>>>>>>> A few more questions as to how this actually works. Does it mean there
>>>>>>> are two physically separate blocks (with different physical addresses)
>>>>>>> to control the same PWM? And this register simply causes some of the
>>>>>>> pins to be routed to one or another? As far as I recall there are a
>>>>>>> number of instances of the PWM block, so the above would need to count
>>>>>>> for all of them. Or are there separate bits for each of them?
>>>>>>
>>>>>> All I have is the TRM (technical reference manual) which doesn't give
>>>>>> me much more info than I've provided you.  But I can answer some of
>>>>>> your questoins:
>>>>>>
>>>>>> 1. If there are two physically separate blocks then the "old" block is
>>>>>> not documented in my TRM.
>>>>>>
>>>>>> 1a) It's entirely possible it's located at some memory address that is
>>>>>> marked "Reserved" in the TRM, but I have no idea.
>>>>>>
>>>>>> 1b) It's entirely possible that the old IP block and the new IP block
>>>>>> are supposed to be "compatible" but that the old block is broken and
>>>>>> thus isn't behaving properly.
>>>>>>
>>>>>> 1c) It's entirely possible that the old IP block and the new IP block
>>>>>> are located at the same physical addresses but somehow work
>>>>>> differently.  If so, the old IP block isn't documented.
>>>>>>
>>>>>>
>>>>>> 2. As per the patch description, there is a single bit that controls
>>>>>> all of the PWMs.  My guess is that there's actually a single IP block
>>>>>> that implements all 4 PWMs.
>>>>>
>>>>> Looking at the register offsets in the device tree that seems likely. At
>>>>> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>>>>>
>>>>> same IP block. Their placement in the register map is somewhat strange:
>>>>>         pwm0: pwm@20030000 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20030000 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM01>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         pwm1: pwm@20030010 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20030010 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM01>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         ...
>>>>>
>>>>>         pwm2: pwm@20050020 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20050020 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM23>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         pwm3: pwm@20050030 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20050030 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM23>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>
>>>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>>>> (the downsides of trying to guess ahead of time what SoC vendors will
>>>> name new models).
>>>
>>> It did sound like a nice idea at the time to hold the common stuff of
>>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>>> dramatically (including the core) would be called 4xxx or so :-) .
>>>
>>>>
>>>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>>>
>>>>> The clocks would also indicate that there are actually two blocks. I
>>>>> seem to remember a discussion about whether to handle them as a single
>>>>> block or two/four, but I can't seem to find a reference to it. Maybe I'm
>>>>> confusing it with another driver.
>>>>
>>>> At this point it seems like the choice has already been made to handle
>>>> them as separate PWMs.  I can change this choice if you want...
>>>>
>>>>>>>>>> This code could go lots of other places, but we've put it here.
>>>>>>>>>> Why?
>>>>>>>>>> - Pushing it to the bootloader just makes the code harder to update
>>>>>>>>>> in
>>>>>>>>>>
>>>>>>>>>>   the field.  If we later find a bug in the new IP block and want
>>>>>>>>>>   to
>>>>>>>>>>   change our mind about what to use we want it to be easy to
>>>>>>>>>>   update.
>>>>>>>
>>>>>>> Depending on how this muxing works you won't be able to change your
>>>>>>> mind
>>>>>>> anyway. If the IP blocks are different then the device tree will
>>>>>>> effectively make the decision for you. So if you really want to be safe
>>>>>>> you'd need to have code in the kernel that parses the device tree and
>>>>>>> checks that all PWM instances are of the new type, then set this
>>>>>>> register accordingly.
>>>>>>
>>>>>> Since there is no documentation about how you would instantiate the
>>>>>> "old" type in the TRM and no good reason I can think of why someone
>>>>>> would want to do this, it doesn't seem super fruitful.
>>>>>
>>>>> Okay, so if it's not at all documented and never used then yes, we'd
>>>>> better just ignore it.
>>>>
>>>> Heiko just pointed me at the base address for the other block.
>>>> There's nothing in the rk3288 TRM about it, but we can see the base
>>>> address.  We could probably guess that it behaves the same as the
>>>> older PWM if we need to.  I'm still not convinced there's a good
>>>> reason for someone to use it.
>>>
>>> From what I understood the old one was included as a fallback in case some
>>> drastic problem appeared with the newly developed IP. Similarly for the I2C
>>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>>> seems to have proven stable.
>>>
>>> So there really is no incentive to use the old one if no drastic issue has
>>> appeared with the new one until now.
>>>
>>>
>>>>>>>>>> diff --git a/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>>>>>>>>>> --- a/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> +++ b/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> @@ -24,6 +24,24 @@
>>>>>>>>>>
>>>>>>>>>>  #include <asm/hardware/cache-l2x0.h>
>>>>>>>>>>  #include "core.h"
>>>>>>>>>>
>>>>>>>>>> +static void __init rk3288_init_machine(void)
>>>>>>>>>> +{
>>>>>>>>>> +     void *grf = ioremap(0xff770000, 0x10000);
>>>>>>>>>
>>>>>>>>> This region of memory is part of the "grf" "syscon" device
>>>>>>>>> (according to
>>>>>>>>> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>>>>>>>>> from
>>>>>>>>> that driver. It looks as if no such driver currently exists, but
>>>>>>>>> given
>>>>>>>>> the existence of the device tree node it's fair to assume that one
>>>>>>>>> will
>>>>>>>>> eventually be merged.
>>>>>>>>
>>>>>>>> The "grf" syscon device is the "general register file".  It's a
>>>>>>>> collection of totally random registers stuffed together in one address
>>>>>>>> space.  Sometimes a single 32-bit register has things you need to
>>>>>>>> tweak for completely different subsystems.
>>>>>>>>
>>>>>>>> Most drivers referene the syscon using this in dts:
>>>>>>>>   rockchip,grf = <&grf>;
>>>>>>>>
>>>>>>>> Then the drivers do:
>>>>>>>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>>>>>>>>
>>>>>>>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>>>>>>>
>>>>>>> That's one way to do it. But if it's really just a one-time thing, then
>>>>>>> you could easily perform the register write from the syscon driver
>>>>>>> where
>>>>>>> the memory is already parsed from device tree and mapped. That way you
>>>>>>> don't have to hardcode the physical address in some other random piece
>>>>>>> of code and map the memory again.
>>>>>>
>>>>>> Well, except that we're using the general "syscon" driver.  I could
>>>>>> create a whole new driver that "subclasses" this syscon driver I
>>>>>> suppose.
>>>>>
>>>>> Ah, I wasn't aware that there was even something like a generic syscon
>>>>> driver. But yes, subclassing it sounds like a reasonable thing to do.
>>>>
>>>> I will do that if need be, but it's not my favorite.  I will let
>>>> others chime in.
>>>
>>> I guess personally I like the idea best of just setting the relevant bit in
>>> _probe of the pwm driver, like the i2c driver does:
>>>
>>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>>>       /* get regmap and set bit */
>>> }
>>>
>>> The downside would be that the bit would be written 4 times, but I guess this
>>> shouldn't matter to much. And I don't think anybody will get the idea of
>>> combining both ip variants in one dts anyway.
>>> And of course in the next SoC the old IP will mostly have gone away and keep
>>> this somewhat close to the driver and not scatter pwm settings into other
>>> kernel parts.
>>>
>>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>>> generic and export such shared registers to other drivers for just these stuff.
>>
>> I think using syscon in the first place is bad. In my opinion it would
>> be far better to export an explicit API from drivers that are currently
>> "implemented" as syscon. The thing is, nothing about syscon is truly
>> generic. All it provides is a memory-mapped I/O region and lets drivers
>> do to that memory region whatever they wants. But ioremap() can be used
>> for that purpose already. Yet we have infrastructure to prevent drivers
>> from doing that (request_resource() and friends) because it's usually a
>> bad idea. All syscon really gives us is a ratified way of doing things
>> that are otherwise frowned upon.
> 
> Agreed that it's a bit awkward, but it's the generally accepted way of
> doing things across multiple drivers as far as I can tell...
> 
> In exynos we were also doing this.  Another alternative (which I saw
> used before syscon) was just to list a second address in the "reg =
> <>".  The second address might only be 4 bytes big if only a single
> 32-bit register was needed.  That started failing because sometimes
> two drivers needed to access the same 32-bit register.  Added Tomasz
> to this thread since I remember him being a fan of solving this with
> syscon.
> 
> 
> At the moment I'm not planning to spin this patch.  If folks come up
> with a solution that they definitely like better I'm happy to spin it,
> but for now this seems to work and doesn't seem (to me) to be terribly
> worse than the alternatives proposed so far.

So, in fact, I'm really a fan of the kind of solutions proposed by
Thierry. My idea of handling this kind of integration details is that we
should rather have a PMU driver on Exynos and it should be exporting all
the various functions to configure certain subtle bits without the IP
driver really knowing about SoC specifics. The PMU driver would know
which bits in which registers to set up depending on SoC compatible
string or data in PMU's device tree node.

I've been recommending the use of syscon for this purpose mostly because
few times before I received negative opinions about the idea of private
APIs like this and I simply didn't have time to push for them.

Best regards,
Tomasz

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 15:49                       ` Tomasz Figa
  0 siblings, 0 replies; 69+ messages in thread
From: Tomasz Figa @ 2014-08-21 15:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 21.08.2014 17:38, Doug Anderson wrote:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
>> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
>>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>>>> Thierry,
>>>>
>>>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>>>>
>>>> <thierry.reding@gmail.com> wrote:
>>>>> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>>>>>> Thierry,
>>>>>>
>>>>>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>>>>>>
>>>>>> <thierry.reding@gmail.com> wrote:
>>>>>>> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>>>>>>>> Thierry,
>>>>>>>>
>>>>>>>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>>>>>>>>
>>>>>>>> <thierry.reding@gmail.com> wrote:
>>>>>>>>> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>>>>>>>>>> The rk3288 SoC has an option to switch all of the PWMs in the
>>>>>>>>>> system
>>>>>>>>>> between the old IP block and the new IP block.  The new IP block is
>>>>>>>>>> working and tested and the suggested PWM to use, so setup the SoC
>>>>>>>>>> to
>>>>>>>>>> use it and then we can pretend that the other IP block doesn't
>>>>>>>>>> exist.
>>>>>>>
>>>>>>> A few more questions as to how this actually works. Does it mean there
>>>>>>> are two physically separate blocks (with different physical addresses)
>>>>>>> to control the same PWM? And this register simply causes some of the
>>>>>>> pins to be routed to one or another? As far as I recall there are a
>>>>>>> number of instances of the PWM block, so the above would need to count
>>>>>>> for all of them. Or are there separate bits for each of them?
>>>>>>
>>>>>> All I have is the TRM (technical reference manual) which doesn't give
>>>>>> me much more info than I've provided you.  But I can answer some of
>>>>>> your questoins:
>>>>>>
>>>>>> 1. If there are two physically separate blocks then the "old" block is
>>>>>> not documented in my TRM.
>>>>>>
>>>>>> 1a) It's entirely possible it's located at some memory address that is
>>>>>> marked "Reserved" in the TRM, but I have no idea.
>>>>>>
>>>>>> 1b) It's entirely possible that the old IP block and the new IP block
>>>>>> are supposed to be "compatible" but that the old block is broken and
>>>>>> thus isn't behaving properly.
>>>>>>
>>>>>> 1c) It's entirely possible that the old IP block and the new IP block
>>>>>> are located at the same physical addresses but somehow work
>>>>>> differently.  If so, the old IP block isn't documented.
>>>>>>
>>>>>>
>>>>>> 2. As per the patch description, there is a single bit that controls
>>>>>> all of the PWMs.  My guess is that there's actually a single IP block
>>>>>> that implements all 4 PWMs.
>>>>>
>>>>> Looking at the register offsets in the device tree that seems likely. At
>>>>> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>>>>>
>>>>> same IP block. Their placement in the register map is somewhat strange:
>>>>>         pwm0: pwm at 20030000 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20030000 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM01>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         pwm1: pwm at 20030010 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20030010 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM01>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         ...
>>>>>
>>>>>         pwm2: pwm at 20050020 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20050020 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM23>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>>
>>>>>         pwm3: pwm at 20050030 {
>>>>>
>>>>>                 ...
>>>>>                 reg = <0x20050030 0x10>;
>>>>>                 ...
>>>>>                 clocks = <&cru PCLK_PWM23>;
>>>>>                 ...
>>>>>
>>>>>         };
>>>>
>>>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>>>> (the downsides of trying to guess ahead of time what SoC vendors will
>>>> name new models).
>>>
>>> It did sound like a nice idea at the time to hold the common stuff of
>>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>>> dramatically (including the core) would be called 4xxx or so :-) .
>>>
>>>>
>>>> In rk3288 they have the same clocks.  See patch #3 in this series.
>>>>
>>>>> The clocks would also indicate that there are actually two blocks. I
>>>>> seem to remember a discussion about whether to handle them as a single
>>>>> block or two/four, but I can't seem to find a reference to it. Maybe I'm
>>>>> confusing it with another driver.
>>>>
>>>> At this point it seems like the choice has already been made to handle
>>>> them as separate PWMs.  I can change this choice if you want...
>>>>
>>>>>>>>>> This code could go lots of other places, but we've put it here.
>>>>>>>>>> Why?
>>>>>>>>>> - Pushing it to the bootloader just makes the code harder to update
>>>>>>>>>> in
>>>>>>>>>>
>>>>>>>>>>   the field.  If we later find a bug in the new IP block and want
>>>>>>>>>>   to
>>>>>>>>>>   change our mind about what to use we want it to be easy to
>>>>>>>>>>   update.
>>>>>>>
>>>>>>> Depending on how this muxing works you won't be able to change your
>>>>>>> mind
>>>>>>> anyway. If the IP blocks are different then the device tree will
>>>>>>> effectively make the decision for you. So if you really want to be safe
>>>>>>> you'd need to have code in the kernel that parses the device tree and
>>>>>>> checks that all PWM instances are of the new type, then set this
>>>>>>> register accordingly.
>>>>>>
>>>>>> Since there is no documentation about how you would instantiate the
>>>>>> "old" type in the TRM and no good reason I can think of why someone
>>>>>> would want to do this, it doesn't seem super fruitful.
>>>>>
>>>>> Okay, so if it's not at all documented and never used then yes, we'd
>>>>> better just ignore it.
>>>>
>>>> Heiko just pointed me at the base address for the other block.
>>>> There's nothing in the rk3288 TRM about it, but we can see the base
>>>> address.  We could probably guess that it behaves the same as the
>>>> older PWM if we need to.  I'm still not convinced there's a good
>>>> reason for someone to use it.
>>>
>>> From what I understood the old one was included as a fallback in case some
>>> drastic problem appeared with the newly developed IP. Similarly for the I2C
>>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>>> seems to have proven stable.
>>>
>>> So there really is no incentive to use the old one if no drastic issue has
>>> appeared with the new one until now.
>>>
>>>
>>>>>>>>>> diff --git a/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>>>>>>>>>> --- a/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> +++ b/arch/arm/mach-rockchip/rockchip.c
>>>>>>>>>> @@ -24,6 +24,24 @@
>>>>>>>>>>
>>>>>>>>>>  #include <asm/hardware/cache-l2x0.h>
>>>>>>>>>>  #include "core.h"
>>>>>>>>>>
>>>>>>>>>> +static void __init rk3288_init_machine(void)
>>>>>>>>>> +{
>>>>>>>>>> +     void *grf = ioremap(0xff770000, 0x10000);
>>>>>>>>>
>>>>>>>>> This region of memory is part of the "grf" "syscon" device
>>>>>>>>> (according to
>>>>>>>>> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>>>>>>>>> from
>>>>>>>>> that driver. It looks as if no such driver currently exists, but
>>>>>>>>> given
>>>>>>>>> the existence of the device tree node it's fair to assume that one
>>>>>>>>> will
>>>>>>>>> eventually be merged.
>>>>>>>>
>>>>>>>> The "grf" syscon device is the "general register file".  It's a
>>>>>>>> collection of totally random registers stuffed together in one address
>>>>>>>> space.  Sometimes a single 32-bit register has things you need to
>>>>>>>> tweak for completely different subsystems.
>>>>>>>>
>>>>>>>> Most drivers referene the syscon using this in dts:
>>>>>>>>   rockchip,grf = <&grf>;
>>>>>>>>
>>>>>>>> Then the drivers do:
>>>>>>>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>>>>>>>>
>>>>>>>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>>>>>>>
>>>>>>> That's one way to do it. But if it's really just a one-time thing, then
>>>>>>> you could easily perform the register write from the syscon driver
>>>>>>> where
>>>>>>> the memory is already parsed from device tree and mapped. That way you
>>>>>>> don't have to hardcode the physical address in some other random piece
>>>>>>> of code and map the memory again.
>>>>>>
>>>>>> Well, except that we're using the general "syscon" driver.  I could
>>>>>> create a whole new driver that "subclasses" this syscon driver I
>>>>>> suppose.
>>>>>
>>>>> Ah, I wasn't aware that there was even something like a generic syscon
>>>>> driver. But yes, subclassing it sounds like a reasonable thing to do.
>>>>
>>>> I will do that if need be, but it's not my favorite.  I will let
>>>> others chime in.
>>>
>>> I guess personally I like the idea best of just setting the relevant bit in
>>> _probe of the pwm driver, like the i2c driver does:
>>>
>>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>>>       /* get regmap and set bit */
>>> }
>>>
>>> The downside would be that the bit would be written 4 times, but I guess this
>>> shouldn't matter to much. And I don't think anybody will get the idea of
>>> combining both ip variants in one dts anyway.
>>> And of course in the next SoC the old IP will mostly have gone away and keep
>>> this somewhat close to the driver and not scatter pwm settings into other
>>> kernel parts.
>>>
>>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>>> generic and export such shared registers to other drivers for just these stuff.
>>
>> I think using syscon in the first place is bad. In my opinion it would
>> be far better to export an explicit API from drivers that are currently
>> "implemented" as syscon. The thing is, nothing about syscon is truly
>> generic. All it provides is a memory-mapped I/O region and lets drivers
>> do to that memory region whatever they wants. But ioremap() can be used
>> for that purpose already. Yet we have infrastructure to prevent drivers
>> from doing that (request_resource() and friends) because it's usually a
>> bad idea. All syscon really gives us is a ratified way of doing things
>> that are otherwise frowned upon.
> 
> Agreed that it's a bit awkward, but it's the generally accepted way of
> doing things across multiple drivers as far as I can tell...
> 
> In exynos we were also doing this.  Another alternative (which I saw
> used before syscon) was just to list a second address in the "reg =
> <>".  The second address might only be 4 bytes big if only a single
> 32-bit register was needed.  That started failing because sometimes
> two drivers needed to access the same 32-bit register.  Added Tomasz
> to this thread since I remember him being a fan of solving this with
> syscon.
> 
> 
> At the moment I'm not planning to spin this patch.  If folks come up
> with a solution that they definitely like better I'm happy to spin it,
> but for now this seems to work and doesn't seem (to me) to be terribly
> worse than the alternatives proposed so far.

So, in fact, I'm really a fan of the kind of solutions proposed by
Thierry. My idea of handling this kind of integration details is that we
should rather have a PMU driver on Exynos and it should be exporting all
the various functions to configure certain subtle bits without the IP
driver really knowing about SoC specifics. The PMU driver would know
which bits in which registers to set up depending on SoC compatible
string or data in PMU's device tree node.

I've been recommending the use of syscon for this purpose mostly because
few times before I received negative opinions about the idea of private
APIs like this and I simply didn't have time to push for them.

Best regards,
Tomasz

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21  6:24                 ` Thierry Reding
@ 2014-08-21 15:53                   ` Heiko Stübner
  -1 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-21 15:53 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Doug Anderson, Caesar Wang, Sonny Rao, Olof Johansson, Eddie Cai,
	Russell King, linux-arm-kernel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3435 bytes --]

Am Donnerstag, 21. August 2014, 08:24:22 schrieb Thierry Reding:
> On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> 
wrote:
> [...]
> 
> > > Looking at the register offsets in the device tree that seems likely. At
> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > > 
> > > same IP block. Their placement in the register map is somewhat strange:
> > >         pwm0: pwm@20030000 {
> > >         
> > >                 ...
> > >                 reg = <0x20030000 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm1: pwm@20030010 {
> > >         
> > >                 ...
> > >                 reg = <0x20030010 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         ...
> > >         
> > >         pwm2: pwm@20050020 {
> > >         
> > >                 ...
> > >                 reg = <0x20050020 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm3: pwm@20050030 {
> > >         
> > >                 ...
> > >                 reg = <0x20050030 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > 
> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> > (the downsides of trying to guess ahead of time what SoC vendors will
> > name new models).
> > 
> > In rk3288 they have the same clocks.  See patch #3 in this series.
> > 
> > > The clocks would also indicate that there are actually two blocks. I
> > > seem to remember a discussion about whether to handle them as a single
> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > > confusing it with another driver.
> > 
> > At this point it seems like the choice has already been made to handle
> > them as separate PWMs.  I can change this choice if you want...
> 
> Well, looking at patch 3/4 this really does seem to be one single block
> providing four PWM channels, so the right thing to do would be to
> represent it in one device tree node. But I'll leave it up to Heiko to
> decide how he wants to handle this.
> 
> One downside of describing it as one device is that it would make the
> pinmux handling slightly more difficult, since presumably you'd only
> want to apply the pinmux settings when a channel is actually being used.
> Currently the pinmux doesn't apply as long as the device remains
> disabled in device tree (though enabling it doesn't necessarily mean
> that it's being used).

yeah, the pinctrl settings would need to move to the board files, to only set 
the pins necessary on the relevant board. But I don't see that as a problem.


> Like I said, it's up to Heiko to decide whether it's worth making this
> change (and it'd make sense to apply it to existing DTS files
> retroactively) or better to keep what we have.

hmm, I guess I don't really have a hard opinion on this. Generally I like the 
"right thing" approach, but the current option also looks ok to me.
So I guess I'm not much help in deciding this :-)


Heiko

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 15:53                   ` Heiko Stübner
  0 siblings, 0 replies; 69+ messages in thread
From: Heiko Stübner @ 2014-08-21 15:53 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 21. August 2014, 08:24:22 schrieb Thierry Reding:
> On Wed, Aug 20, 2014 at 08:55:09AM -0700, Doug Anderson wrote:
> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding <thierry.reding@gmail.com> 
wrote:
> [...]
> 
> > > Looking at the register offsets in the device tree that seems likely. At
> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> > > 
> > > same IP block. Their placement in the register map is somewhat strange:
> > >         pwm0: pwm at 20030000 {
> > >         
> > >                 ...
> > >                 reg = <0x20030000 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm1: pwm at 20030010 {
> > >         
> > >                 ...
> > >                 reg = <0x20030010 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM01>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         ...
> > >         
> > >         pwm2: pwm at 20050020 {
> > >         
> > >                 ...
> > >                 reg = <0x20050020 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > >         
> > >         pwm3: pwm at 20050030 {
> > >         
> > >                 ...
> > >                 reg = <0x20050030 0x10>;
> > >                 ...
> > >                 clocks = <&cru PCLK_PWM23>;
> > >                 ...
> > >         
> > >         };
> > 
> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> > (the downsides of trying to guess ahead of time what SoC vendors will
> > name new models).
> > 
> > In rk3288 they have the same clocks.  See patch #3 in this series.
> > 
> > > The clocks would also indicate that there are actually two blocks. I
> > > seem to remember a discussion about whether to handle them as a single
> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> > > confusing it with another driver.
> > 
> > At this point it seems like the choice has already been made to handle
> > them as separate PWMs.  I can change this choice if you want...
> 
> Well, looking at patch 3/4 this really does seem to be one single block
> providing four PWM channels, so the right thing to do would be to
> represent it in one device tree node. But I'll leave it up to Heiko to
> decide how he wants to handle this.
> 
> One downside of describing it as one device is that it would make the
> pinmux handling slightly more difficult, since presumably you'd only
> want to apply the pinmux settings when a channel is actually being used.
> Currently the pinmux doesn't apply as long as the device remains
> disabled in device tree (though enabling it doesn't necessarily mean
> that it's being used).

yeah, the pinctrl settings would need to move to the board files, to only set 
the pins necessary on the relevant board. But I don't see that as a problem.


> Like I said, it's up to Heiko to decide whether it's worth making this
> change (and it'd make sense to apply it to existing DTS files
> retroactively) or better to keep what we have.

hmm, I guess I don't really have a hard opinion on this. Generally I like the 
"right thing" approach, but the current option also looks ok to me.
So I guess I'm not much help in deciding this :-)


Heiko
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140821/23ad51c0/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21 15:38                     ` Doug Anderson
@ 2014-08-21 16:47                       ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21 16:47 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stübner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel,
	Tomasz Figa

[-- Attachment #1: Type: text/plain, Size: 13810 bytes --]

On Thu, Aug 21, 2014 at 08:38:57AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
> >> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >> > Thierry,
> >> >
> >> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >> >
> >> > <thierry.reding@gmail.com> wrote:
> >> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> > >> Thierry,
> >> > >>
> >> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> > >>
> >> > >> <thierry.reding@gmail.com> wrote:
> >> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> > >> >> Thierry,
> >> > >> >>
> >> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> > >> >>
> >> > >> >> <thierry.reding@gmail.com> wrote:
> >> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> > >> >> >> system
> >> > >> >> >> between the old IP block and the new IP block.  The new IP block is
> >> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> >> > >> >> >> to
> >> > >> >> >> use it and then we can pretend that the other IP block doesn't
> >> > >> >> >> exist.
> >> > >> >
> >> > >> > A few more questions as to how this actually works. Does it mean there
> >> > >> > are two physically separate blocks (with different physical addresses)
> >> > >> > to control the same PWM? And this register simply causes some of the
> >> > >> > pins to be routed to one or another? As far as I recall there are a
> >> > >> > number of instances of the PWM block, so the above would need to count
> >> > >> > for all of them. Or are there separate bits for each of them?
> >> > >>
> >> > >> All I have is the TRM (technical reference manual) which doesn't give
> >> > >> me much more info than I've provided you.  But I can answer some of
> >> > >> your questoins:
> >> > >>
> >> > >> 1. If there are two physically separate blocks then the "old" block is
> >> > >> not documented in my TRM.
> >> > >>
> >> > >> 1a) It's entirely possible it's located at some memory address that is
> >> > >> marked "Reserved" in the TRM, but I have no idea.
> >> > >>
> >> > >> 1b) It's entirely possible that the old IP block and the new IP block
> >> > >> are supposed to be "compatible" but that the old block is broken and
> >> > >> thus isn't behaving properly.
> >> > >>
> >> > >> 1c) It's entirely possible that the old IP block and the new IP block
> >> > >> are located at the same physical addresses but somehow work
> >> > >> differently.  If so, the old IP block isn't documented.
> >> > >>
> >> > >>
> >> > >> 2. As per the patch description, there is a single bit that controls
> >> > >> all of the PWMs.  My guess is that there's actually a single IP block
> >> > >> that implements all 4 PWMs.
> >> > >
> >> > > Looking at the register offsets in the device tree that seems likely. At
> >> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >> > >
> >> > > same IP block. Their placement in the register map is somewhat strange:
> >> > >         pwm0: pwm@20030000 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20030000 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM01>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         pwm1: pwm@20030010 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20030010 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM01>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         ...
> >> > >
> >> > >         pwm2: pwm@20050020 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20050020 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM23>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         pwm3: pwm@20050030 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20050030 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM23>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> >
> >> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >> > (the downsides of trying to guess ahead of time what SoC vendors will
> >> > name new models).
> >>
> >> It did sound like a nice idea at the time to hold the common stuff of
> >> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> >> dramatically (including the core) would be called 4xxx or so :-) .
> >>
> >> >
> >> > In rk3288 they have the same clocks.  See patch #3 in this series.
> >> >
> >> > > The clocks would also indicate that there are actually two blocks. I
> >> > > seem to remember a discussion about whether to handle them as a single
> >> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> >> > > confusing it with another driver.
> >> >
> >> > At this point it seems like the choice has already been made to handle
> >> > them as separate PWMs.  I can change this choice if you want...
> >> >
> >> > >> >> >> This code could go lots of other places, but we've put it here.
> >> > >> >> >> Why?
> >> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
> >> > >> >> >> in
> >> > >> >> >>
> >> > >> >> >>   the field.  If we later find a bug in the new IP block and want
> >> > >> >> >>   to
> >> > >> >> >>   change our mind about what to use we want it to be easy to
> >> > >> >> >>   update.
> >> > >> >
> >> > >> > Depending on how this muxing works you won't be able to change your
> >> > >> > mind
> >> > >> > anyway. If the IP blocks are different then the device tree will
> >> > >> > effectively make the decision for you. So if you really want to be safe
> >> > >> > you'd need to have code in the kernel that parses the device tree and
> >> > >> > checks that all PWM instances are of the new type, then set this
> >> > >> > register accordingly.
> >> > >>
> >> > >> Since there is no documentation about how you would instantiate the
> >> > >> "old" type in the TRM and no good reason I can think of why someone
> >> > >> would want to do this, it doesn't seem super fruitful.
> >> > >
> >> > > Okay, so if it's not at all documented and never used then yes, we'd
> >> > > better just ignore it.
> >> >
> >> > Heiko just pointed me at the base address for the other block.
> >> > There's nothing in the rk3288 TRM about it, but we can see the base
> >> > address.  We could probably guess that it behaves the same as the
> >> > older PWM if we need to.  I'm still not convinced there's a good
> >> > reason for someone to use it.
> >>
> >> From what I understood the old one was included as a fallback in case some
> >> drastic problem appeared with the newly developed IP. Similarly for the I2C
> >> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> >> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> >> seems to have proven stable.
> >>
> >> So there really is no incentive to use the old one if no drastic issue has
> >> appeared with the new one until now.
> >>
> >>
> >> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> @@ -24,6 +24,24 @@
> >> > >> >> >>
> >> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> > >> >> >>  #include "core.h"
> >> > >> >> >>
> >> > >> >> >> +static void __init rk3288_init_machine(void)
> >> > >> >> >> +{
> >> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> > >> >> >
> >> > >> >> > This region of memory is part of the "grf" "syscon" device
> >> > >> >> > (according to
> >> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >> > >> >> > from
> >> > >> >> > that driver. It looks as if no such driver currently exists, but
> >> > >> >> > given
> >> > >> >> > the existence of the device tree node it's fair to assume that one
> >> > >> >> > will
> >> > >> >> > eventually be merged.
> >> > >> >>
> >> > >> >> The "grf" syscon device is the "general register file".  It's a
> >> > >> >> collection of totally random registers stuffed together in one address
> >> > >> >> space.  Sometimes a single 32-bit register has things you need to
> >> > >> >> tweak for completely different subsystems.
> >> > >> >>
> >> > >> >> Most drivers referene the syscon using this in dts:
> >> > >> >>   rockchip,grf = <&grf>;
> >> > >> >>
> >> > >> >> Then the drivers do:
> >> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >> > >> >>
> >> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >> > >> >
> >> > >> > That's one way to do it. But if it's really just a one-time thing, then
> >> > >> > you could easily perform the register write from the syscon driver
> >> > >> > where
> >> > >> > the memory is already parsed from device tree and mapped. That way you
> >> > >> > don't have to hardcode the physical address in some other random piece
> >> > >> > of code and map the memory again.
> >> > >>
> >> > >> Well, except that we're using the general "syscon" driver.  I could
> >> > >> create a whole new driver that "subclasses" this syscon driver I
> >> > >> suppose.
> >> > >
> >> > > Ah, I wasn't aware that there was even something like a generic syscon
> >> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
> >> >
> >> > I will do that if need be, but it's not my favorite.  I will let
> >> > others chime in.
> >>
> >> I guess personally I like the idea best of just setting the relevant bit in
> >> _probe of the pwm driver, like the i2c driver does:
> >>
> >> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> >>       /* get regmap and set bit */
> >> }
> >>
> >> The downside would be that the bit would be written 4 times, but I guess this
> >> shouldn't matter to much. And I don't think anybody will get the idea of
> >> combining both ip variants in one dts anyway.
> >> And of course in the next SoC the old IP will mostly have gone away and keep
> >> this somewhat close to the driver and not scatter pwm settings into other
> >> kernel parts.
> >>
> >> Hacking up the syscon driver feels bad to me, especially as it is meant to be
> >> generic and export such shared registers to other drivers for just these stuff.
> >
> > I think using syscon in the first place is bad. In my opinion it would
> > be far better to export an explicit API from drivers that are currently
> > "implemented" as syscon. The thing is, nothing about syscon is truly
> > generic. All it provides is a memory-mapped I/O region and lets drivers
> > do to that memory region whatever they wants. But ioremap() can be used
> > for that purpose already. Yet we have infrastructure to prevent drivers
> > from doing that (request_resource() and friends) because it's usually a
> > bad idea. All syscon really gives us is a ratified way of doing things
> > that are otherwise frowned upon.
> 
> Agreed that it's a bit awkward, but it's the generally accepted way of
> doing things across multiple drivers as far as I can tell...

But that's exactly what I've been saying. I consider it a very bad thing
that this is a generally accepted way. Sure, it's a very easy solution,
but it also means that all the details about how the syscon registers
need to be programmed are moved into drivers. That makes them inherently
non-portable. Consider for example if you have a driver for an IP block
that's used in one device and needs some registers set in a "syscon"
device to work on that device. Now somebody licenses the same IP block
and instantiates it in a completely different design. Now with some luck
it won't need a syscon's help in the second design, so you can make the
syscon optional and ignore it. But what if you need to program some
syscon in the second design as well but it has a different register
layout?

Admittedly this will also be a problem if you have an explicit API, but
then it's still better to create the proper abstraction that can be made
to work on both SoCs, or as in the case of this PWM block you move the
code that needs to be executed only once into the syscon driver where it
belongs. That way the driver becomes completely generic, no need to play
tricks because you (or somebody else for that matter) chose the easy way
out.

> In exynos we were also doing this.  Another alternative (which I saw
> used before syscon) was just to list a second address in the "reg =
> <>".  The second address might only be 4 bytes big if only a single
> 32-bit register was needed.  That started failing because sometimes
> two drivers needed to access the same 32-bit register.

That's /exactly/ what syscon does as well (albeit with a bunch of
overhead).

> At the moment I'm not planning to spin this patch.  If folks come up
> with a solution that they definitely like better I'm happy to spin it,
> but for now this seems to work and doesn't seem (to me) to be terribly
> worse than the alternatives proposed so far.

I still think having a separate syscon driver that does this one-time
initialization is the proper thing to do.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 16:47                       ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21 16:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 21, 2014 at 08:38:57AM -0700, Doug Anderson wrote:
> Thierry,
> 
> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
> >> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >> > Thierry,
> >> >
> >> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >> >
> >> > <thierry.reding@gmail.com> wrote:
> >> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >> > >> Thierry,
> >> > >>
> >> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >> > >>
> >> > >> <thierry.reding@gmail.com> wrote:
> >> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >> > >> >> Thierry,
> >> > >> >>
> >> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >> > >> >>
> >> > >> >> <thierry.reding@gmail.com> wrote:
> >> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
> >> > >> >> >> system
> >> > >> >> >> between the old IP block and the new IP block.  The new IP block is
> >> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
> >> > >> >> >> to
> >> > >> >> >> use it and then we can pretend that the other IP block doesn't
> >> > >> >> >> exist.
> >> > >> >
> >> > >> > A few more questions as to how this actually works. Does it mean there
> >> > >> > are two physically separate blocks (with different physical addresses)
> >> > >> > to control the same PWM? And this register simply causes some of the
> >> > >> > pins to be routed to one or another? As far as I recall there are a
> >> > >> > number of instances of the PWM block, so the above would need to count
> >> > >> > for all of them. Or are there separate bits for each of them?
> >> > >>
> >> > >> All I have is the TRM (technical reference manual) which doesn't give
> >> > >> me much more info than I've provided you.  But I can answer some of
> >> > >> your questoins:
> >> > >>
> >> > >> 1. If there are two physically separate blocks then the "old" block is
> >> > >> not documented in my TRM.
> >> > >>
> >> > >> 1a) It's entirely possible it's located at some memory address that is
> >> > >> marked "Reserved" in the TRM, but I have no idea.
> >> > >>
> >> > >> 1b) It's entirely possible that the old IP block and the new IP block
> >> > >> are supposed to be "compatible" but that the old block is broken and
> >> > >> thus isn't behaving properly.
> >> > >>
> >> > >> 1c) It's entirely possible that the old IP block and the new IP block
> >> > >> are located at the same physical addresses but somehow work
> >> > >> differently.  If so, the old IP block isn't documented.
> >> > >>
> >> > >>
> >> > >> 2. As per the patch description, there is a single bit that controls
> >> > >> all of the PWMs.  My guess is that there's actually a single IP block
> >> > >> that implements all 4 PWMs.
> >> > >
> >> > > Looking at the register offsets in the device tree that seems likely. At
> >> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >> > >
> >> > > same IP block. Their placement in the register map is somewhat strange:
> >> > >         pwm0: pwm at 20030000 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20030000 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM01>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         pwm1: pwm at 20030010 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20030010 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM01>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         ...
> >> > >
> >> > >         pwm2: pwm at 20050020 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20050020 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM23>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> > >
> >> > >         pwm3: pwm at 20050030 {
> >> > >
> >> > >                 ...
> >> > >                 reg = <0x20050030 0x10>;
> >> > >                 ...
> >> > >                 clocks = <&cru PCLK_PWM23>;
> >> > >                 ...
> >> > >
> >> > >         };
> >> >
> >> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >> > (the downsides of trying to guess ahead of time what SoC vendors will
> >> > name new models).
> >>
> >> It did sound like a nice idea at the time to hold the common stuff of
> >> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> >> dramatically (including the core) would be called 4xxx or so :-) .
> >>
> >> >
> >> > In rk3288 they have the same clocks.  See patch #3 in this series.
> >> >
> >> > > The clocks would also indicate that there are actually two blocks. I
> >> > > seem to remember a discussion about whether to handle them as a single
> >> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
> >> > > confusing it with another driver.
> >> >
> >> > At this point it seems like the choice has already been made to handle
> >> > them as separate PWMs.  I can change this choice if you want...
> >> >
> >> > >> >> >> This code could go lots of other places, but we've put it here.
> >> > >> >> >> Why?
> >> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
> >> > >> >> >> in
> >> > >> >> >>
> >> > >> >> >>   the field.  If we later find a bug in the new IP block and want
> >> > >> >> >>   to
> >> > >> >> >>   change our mind about what to use we want it to be easy to
> >> > >> >> >>   update.
> >> > >> >
> >> > >> > Depending on how this muxing works you won't be able to change your
> >> > >> > mind
> >> > >> > anyway. If the IP blocks are different then the device tree will
> >> > >> > effectively make the decision for you. So if you really want to be safe
> >> > >> > you'd need to have code in the kernel that parses the device tree and
> >> > >> > checks that all PWM instances are of the new type, then set this
> >> > >> > register accordingly.
> >> > >>
> >> > >> Since there is no documentation about how you would instantiate the
> >> > >> "old" type in the TRM and no good reason I can think of why someone
> >> > >> would want to do this, it doesn't seem super fruitful.
> >> > >
> >> > > Okay, so if it's not at all documented and never used then yes, we'd
> >> > > better just ignore it.
> >> >
> >> > Heiko just pointed me at the base address for the other block.
> >> > There's nothing in the rk3288 TRM about it, but we can see the base
> >> > address.  We could probably guess that it behaves the same as the
> >> > older PWM if we need to.  I'm still not convinced there's a good
> >> > reason for someone to use it.
> >>
> >> From what I understood the old one was included as a fallback in case some
> >> drastic problem appeared with the newly developed IP. Similarly for the I2C
> >> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> >> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> >> seems to have proven stable.
> >>
> >> So there really is no incentive to use the old one if no drastic issue has
> >> appeared with the new one until now.
> >>
> >>
> >> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
> >> > >> >> >> @@ -24,6 +24,24 @@
> >> > >> >> >>
> >> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
> >> > >> >> >>  #include "core.h"
> >> > >> >> >>
> >> > >> >> >> +static void __init rk3288_init_machine(void)
> >> > >> >> >> +{
> >> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
> >> > >> >> >
> >> > >> >> > This region of memory is part of the "grf" "syscon" device
> >> > >> >> > (according to
> >> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >> > >> >> > from
> >> > >> >> > that driver. It looks as if no such driver currently exists, but
> >> > >> >> > given
> >> > >> >> > the existence of the device tree node it's fair to assume that one
> >> > >> >> > will
> >> > >> >> > eventually be merged.
> >> > >> >>
> >> > >> >> The "grf" syscon device is the "general register file".  It's a
> >> > >> >> collection of totally random registers stuffed together in one address
> >> > >> >> space.  Sometimes a single 32-bit register has things you need to
> >> > >> >> tweak for completely different subsystems.
> >> > >> >>
> >> > >> >> Most drivers referene the syscon using this in dts:
> >> > >> >>   rockchip,grf = <&grf>;
> >> > >> >>
> >> > >> >> Then the drivers do:
> >> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >> > >> >>
> >> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >> > >> >
> >> > >> > That's one way to do it. But if it's really just a one-time thing, then
> >> > >> > you could easily perform the register write from the syscon driver
> >> > >> > where
> >> > >> > the memory is already parsed from device tree and mapped. That way you
> >> > >> > don't have to hardcode the physical address in some other random piece
> >> > >> > of code and map the memory again.
> >> > >>
> >> > >> Well, except that we're using the general "syscon" driver.  I could
> >> > >> create a whole new driver that "subclasses" this syscon driver I
> >> > >> suppose.
> >> > >
> >> > > Ah, I wasn't aware that there was even something like a generic syscon
> >> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
> >> >
> >> > I will do that if need be, but it's not my favorite.  I will let
> >> > others chime in.
> >>
> >> I guess personally I like the idea best of just setting the relevant bit in
> >> _probe of the pwm driver, like the i2c driver does:
> >>
> >> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> >>       /* get regmap and set bit */
> >> }
> >>
> >> The downside would be that the bit would be written 4 times, but I guess this
> >> shouldn't matter to much. And I don't think anybody will get the idea of
> >> combining both ip variants in one dts anyway.
> >> And of course in the next SoC the old IP will mostly have gone away and keep
> >> this somewhat close to the driver and not scatter pwm settings into other
> >> kernel parts.
> >>
> >> Hacking up the syscon driver feels bad to me, especially as it is meant to be
> >> generic and export such shared registers to other drivers for just these stuff.
> >
> > I think using syscon in the first place is bad. In my opinion it would
> > be far better to export an explicit API from drivers that are currently
> > "implemented" as syscon. The thing is, nothing about syscon is truly
> > generic. All it provides is a memory-mapped I/O region and lets drivers
> > do to that memory region whatever they wants. But ioremap() can be used
> > for that purpose already. Yet we have infrastructure to prevent drivers
> > from doing that (request_resource() and friends) because it's usually a
> > bad idea. All syscon really gives us is a ratified way of doing things
> > that are otherwise frowned upon.
> 
> Agreed that it's a bit awkward, but it's the generally accepted way of
> doing things across multiple drivers as far as I can tell...

But that's exactly what I've been saying. I consider it a very bad thing
that this is a generally accepted way. Sure, it's a very easy solution,
but it also means that all the details about how the syscon registers
need to be programmed are moved into drivers. That makes them inherently
non-portable. Consider for example if you have a driver for an IP block
that's used in one device and needs some registers set in a "syscon"
device to work on that device. Now somebody licenses the same IP block
and instantiates it in a completely different design. Now with some luck
it won't need a syscon's help in the second design, so you can make the
syscon optional and ignore it. But what if you need to program some
syscon in the second design as well but it has a different register
layout?

Admittedly this will also be a problem if you have an explicit API, but
then it's still better to create the proper abstraction that can be made
to work on both SoCs, or as in the case of this PWM block you move the
code that needs to be executed only once into the syscon driver where it
belongs. That way the driver becomes completely generic, no need to play
tricks because you (or somebody else for that matter) chose the easy way
out.

> In exynos we were also doing this.  Another alternative (which I saw
> used before syscon) was just to list a second address in the "reg =
> <>".  The second address might only be 4 bytes big if only a single
> 32-bit register was needed.  That started failing because sometimes
> two drivers needed to access the same 32-bit register.

That's /exactly/ what syscon does as well (albeit with a bunch of
overhead).

> At the moment I'm not planning to spin this patch.  If folks come up
> with a solution that they definitely like better I'm happy to spin it,
> but for now this seems to work and doesn't seem (to me) to be terribly
> worse than the alternatives proposed so far.

I still think having a separate syscon driver that does this one-time
initialization is the proper thing to do.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140821/b4697de3/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21 15:49                       ` Tomasz Figa
@ 2014-08-21 16:49                         ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21 16:49 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: Doug Anderson, Heiko Stübner, Caesar Wang, Sonny Rao,
	Olof Johansson, Eddie Cai, Russell King, linux-arm-kernel,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 13135 bytes --]

On Thu, Aug 21, 2014 at 05:49:22PM +0200, Tomasz Figa wrote:
> On 21.08.2014 17:38, Doug Anderson wrote:
> > Thierry,
> > 
> > On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> > <thierry.reding@gmail.com> wrote:
> >> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
> >>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >>>> Thierry,
> >>>>
> >>>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >>>>
> >>>> <thierry.reding@gmail.com> wrote:
> >>>>> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >>>>>> Thierry,
> >>>>>>
> >>>>>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >>>>>>
> >>>>>> <thierry.reding@gmail.com> wrote:
> >>>>>>> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >>>>>>>> Thierry,
> >>>>>>>>
> >>>>>>>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >>>>>>>>
> >>>>>>>> <thierry.reding@gmail.com> wrote:
> >>>>>>>>> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >>>>>>>>>> The rk3288 SoC has an option to switch all of the PWMs in the
> >>>>>>>>>> system
> >>>>>>>>>> between the old IP block and the new IP block.  The new IP block is
> >>>>>>>>>> working and tested and the suggested PWM to use, so setup the SoC
> >>>>>>>>>> to
> >>>>>>>>>> use it and then we can pretend that the other IP block doesn't
> >>>>>>>>>> exist.
> >>>>>>>
> >>>>>>> A few more questions as to how this actually works. Does it mean there
> >>>>>>> are two physically separate blocks (with different physical addresses)
> >>>>>>> to control the same PWM? And this register simply causes some of the
> >>>>>>> pins to be routed to one or another? As far as I recall there are a
> >>>>>>> number of instances of the PWM block, so the above would need to count
> >>>>>>> for all of them. Or are there separate bits for each of them?
> >>>>>>
> >>>>>> All I have is the TRM (technical reference manual) which doesn't give
> >>>>>> me much more info than I've provided you.  But I can answer some of
> >>>>>> your questoins:
> >>>>>>
> >>>>>> 1. If there are two physically separate blocks then the "old" block is
> >>>>>> not documented in my TRM.
> >>>>>>
> >>>>>> 1a) It's entirely possible it's located at some memory address that is
> >>>>>> marked "Reserved" in the TRM, but I have no idea.
> >>>>>>
> >>>>>> 1b) It's entirely possible that the old IP block and the new IP block
> >>>>>> are supposed to be "compatible" but that the old block is broken and
> >>>>>> thus isn't behaving properly.
> >>>>>>
> >>>>>> 1c) It's entirely possible that the old IP block and the new IP block
> >>>>>> are located at the same physical addresses but somehow work
> >>>>>> differently.  If so, the old IP block isn't documented.
> >>>>>>
> >>>>>>
> >>>>>> 2. As per the patch description, there is a single bit that controls
> >>>>>> all of the PWMs.  My guess is that there's actually a single IP block
> >>>>>> that implements all 4 PWMs.
> >>>>>
> >>>>> Looking at the register offsets in the device tree that seems likely. At
> >>>>> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >>>>>
> >>>>> same IP block. Their placement in the register map is somewhat strange:
> >>>>>         pwm0: pwm@20030000 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20030000 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM01>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         pwm1: pwm@20030010 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20030010 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM01>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         ...
> >>>>>
> >>>>>         pwm2: pwm@20050020 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20050020 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM23>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         pwm3: pwm@20050030 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20050030 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM23>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>
> >>>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >>>> (the downsides of trying to guess ahead of time what SoC vendors will
> >>>> name new models).
> >>>
> >>> It did sound like a nice idea at the time to hold the common stuff of
> >>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> >>> dramatically (including the core) would be called 4xxx or so :-) .
> >>>
> >>>>
> >>>> In rk3288 they have the same clocks.  See patch #3 in this series.
> >>>>
> >>>>> The clocks would also indicate that there are actually two blocks. I
> >>>>> seem to remember a discussion about whether to handle them as a single
> >>>>> block or two/four, but I can't seem to find a reference to it. Maybe I'm
> >>>>> confusing it with another driver.
> >>>>
> >>>> At this point it seems like the choice has already been made to handle
> >>>> them as separate PWMs.  I can change this choice if you want...
> >>>>
> >>>>>>>>>> This code could go lots of other places, but we've put it here.
> >>>>>>>>>> Why?
> >>>>>>>>>> - Pushing it to the bootloader just makes the code harder to update
> >>>>>>>>>> in
> >>>>>>>>>>
> >>>>>>>>>>   the field.  If we later find a bug in the new IP block and want
> >>>>>>>>>>   to
> >>>>>>>>>>   change our mind about what to use we want it to be easy to
> >>>>>>>>>>   update.
> >>>>>>>
> >>>>>>> Depending on how this muxing works you won't be able to change your
> >>>>>>> mind
> >>>>>>> anyway. If the IP blocks are different then the device tree will
> >>>>>>> effectively make the decision for you. So if you really want to be safe
> >>>>>>> you'd need to have code in the kernel that parses the device tree and
> >>>>>>> checks that all PWM instances are of the new type, then set this
> >>>>>>> register accordingly.
> >>>>>>
> >>>>>> Since there is no documentation about how you would instantiate the
> >>>>>> "old" type in the TRM and no good reason I can think of why someone
> >>>>>> would want to do this, it doesn't seem super fruitful.
> >>>>>
> >>>>> Okay, so if it's not at all documented and never used then yes, we'd
> >>>>> better just ignore it.
> >>>>
> >>>> Heiko just pointed me at the base address for the other block.
> >>>> There's nothing in the rk3288 TRM about it, but we can see the base
> >>>> address.  We could probably guess that it behaves the same as the
> >>>> older PWM if we need to.  I'm still not convinced there's a good
> >>>> reason for someone to use it.
> >>>
> >>> From what I understood the old one was included as a fallback in case some
> >>> drastic problem appeared with the newly developed IP. Similarly for the I2C
> >>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> >>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> >>> seems to have proven stable.
> >>>
> >>> So there really is no incentive to use the old one if no drastic issue has
> >>> appeared with the new one until now.
> >>>
> >>>
> >>>>>>>>>> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >>>>>>>>>> --- a/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> +++ b/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> @@ -24,6 +24,24 @@
> >>>>>>>>>>
> >>>>>>>>>>  #include <asm/hardware/cache-l2x0.h>
> >>>>>>>>>>  #include "core.h"
> >>>>>>>>>>
> >>>>>>>>>> +static void __init rk3288_init_machine(void)
> >>>>>>>>>> +{
> >>>>>>>>>> +     void *grf = ioremap(0xff770000, 0x10000);
> >>>>>>>>>
> >>>>>>>>> This region of memory is part of the "grf" "syscon" device
> >>>>>>>>> (according to
> >>>>>>>>> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >>>>>>>>> from
> >>>>>>>>> that driver. It looks as if no such driver currently exists, but
> >>>>>>>>> given
> >>>>>>>>> the existence of the device tree node it's fair to assume that one
> >>>>>>>>> will
> >>>>>>>>> eventually be merged.
> >>>>>>>>
> >>>>>>>> The "grf" syscon device is the "general register file".  It's a
> >>>>>>>> collection of totally random registers stuffed together in one address
> >>>>>>>> space.  Sometimes a single 32-bit register has things you need to
> >>>>>>>> tweak for completely different subsystems.
> >>>>>>>>
> >>>>>>>> Most drivers referene the syscon using this in dts:
> >>>>>>>>   rockchip,grf = <&grf>;
> >>>>>>>>
> >>>>>>>> Then the drivers do:
> >>>>>>>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >>>>>>>>
> >>>>>>>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >>>>>>>
> >>>>>>> That's one way to do it. But if it's really just a one-time thing, then
> >>>>>>> you could easily perform the register write from the syscon driver
> >>>>>>> where
> >>>>>>> the memory is already parsed from device tree and mapped. That way you
> >>>>>>> don't have to hardcode the physical address in some other random piece
> >>>>>>> of code and map the memory again.
> >>>>>>
> >>>>>> Well, except that we're using the general "syscon" driver.  I could
> >>>>>> create a whole new driver that "subclasses" this syscon driver I
> >>>>>> suppose.
> >>>>>
> >>>>> Ah, I wasn't aware that there was even something like a generic syscon
> >>>>> driver. But yes, subclassing it sounds like a reasonable thing to do.
> >>>>
> >>>> I will do that if need be, but it's not my favorite.  I will let
> >>>> others chime in.
> >>>
> >>> I guess personally I like the idea best of just setting the relevant bit in
> >>> _probe of the pwm driver, like the i2c driver does:
> >>>
> >>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> >>>       /* get regmap and set bit */
> >>> }
> >>>
> >>> The downside would be that the bit would be written 4 times, but I guess this
> >>> shouldn't matter to much. And I don't think anybody will get the idea of
> >>> combining both ip variants in one dts anyway.
> >>> And of course in the next SoC the old IP will mostly have gone away and keep
> >>> this somewhat close to the driver and not scatter pwm settings into other
> >>> kernel parts.
> >>>
> >>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
> >>> generic and export such shared registers to other drivers for just these stuff.
> >>
> >> I think using syscon in the first place is bad. In my opinion it would
> >> be far better to export an explicit API from drivers that are currently
> >> "implemented" as syscon. The thing is, nothing about syscon is truly
> >> generic. All it provides is a memory-mapped I/O region and lets drivers
> >> do to that memory region whatever they wants. But ioremap() can be used
> >> for that purpose already. Yet we have infrastructure to prevent drivers
> >> from doing that (request_resource() and friends) because it's usually a
> >> bad idea. All syscon really gives us is a ratified way of doing things
> >> that are otherwise frowned upon.
> > 
> > Agreed that it's a bit awkward, but it's the generally accepted way of
> > doing things across multiple drivers as far as I can tell...
> > 
> > In exynos we were also doing this.  Another alternative (which I saw
> > used before syscon) was just to list a second address in the "reg =
> > <>".  The second address might only be 4 bytes big if only a single
> > 32-bit register was needed.  That started failing because sometimes
> > two drivers needed to access the same 32-bit register.  Added Tomasz
> > to this thread since I remember him being a fan of solving this with
> > syscon.
> > 
> > 
> > At the moment I'm not planning to spin this patch.  If folks come up
> > with a solution that they definitely like better I'm happy to spin it,
> > but for now this seems to work and doesn't seem (to me) to be terribly
> > worse than the alternatives proposed so far.
> 
> So, in fact, I'm really a fan of the kind of solutions proposed by
> Thierry. My idea of handling this kind of integration details is that we
> should rather have a PMU driver on Exynos and it should be exporting all
> the various functions to configure certain subtle bits without the IP
> driver really knowing about SoC specifics. The PMU driver would know
> which bits in which registers to set up depending on SoC compatible
> string or data in PMU's device tree node.
> 
> I've been recommending the use of syscon for this purpose mostly because
> few times before I received negative opinions about the idea of private
> APIs like this and I simply didn't have time to push for them.

syscon is in fact not different from a private API. Except that the API
takes the form of arbitrary register accesses.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-21 16:49                         ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-21 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 21, 2014 at 05:49:22PM +0200, Tomasz Figa wrote:
> On 21.08.2014 17:38, Doug Anderson wrote:
> > Thierry,
> > 
> > On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
> > <thierry.reding@gmail.com> wrote:
> >> On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
> >>> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
> >>>> Thierry,
> >>>>
> >>>> On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
> >>>>
> >>>> <thierry.reding@gmail.com> wrote:
> >>>>> On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
> >>>>>> Thierry,
> >>>>>>
> >>>>>> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
> >>>>>>
> >>>>>> <thierry.reding@gmail.com> wrote:
> >>>>>>> On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
> >>>>>>>> Thierry,
> >>>>>>>>
> >>>>>>>> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
> >>>>>>>>
> >>>>>>>> <thierry.reding@gmail.com> wrote:
> >>>>>>>>> On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
> >>>>>>>>>> The rk3288 SoC has an option to switch all of the PWMs in the
> >>>>>>>>>> system
> >>>>>>>>>> between the old IP block and the new IP block.  The new IP block is
> >>>>>>>>>> working and tested and the suggested PWM to use, so setup the SoC
> >>>>>>>>>> to
> >>>>>>>>>> use it and then we can pretend that the other IP block doesn't
> >>>>>>>>>> exist.
> >>>>>>>
> >>>>>>> A few more questions as to how this actually works. Does it mean there
> >>>>>>> are two physically separate blocks (with different physical addresses)
> >>>>>>> to control the same PWM? And this register simply causes some of the
> >>>>>>> pins to be routed to one or another? As far as I recall there are a
> >>>>>>> number of instances of the PWM block, so the above would need to count
> >>>>>>> for all of them. Or are there separate bits for each of them?
> >>>>>>
> >>>>>> All I have is the TRM (technical reference manual) which doesn't give
> >>>>>> me much more info than I've provided you.  But I can answer some of
> >>>>>> your questoins:
> >>>>>>
> >>>>>> 1. If there are two physically separate blocks then the "old" block is
> >>>>>> not documented in my TRM.
> >>>>>>
> >>>>>> 1a) It's entirely possible it's located at some memory address that is
> >>>>>> marked "Reserved" in the TRM, but I have no idea.
> >>>>>>
> >>>>>> 1b) It's entirely possible that the old IP block and the new IP block
> >>>>>> are supposed to be "compatible" but that the old block is broken and
> >>>>>> thus isn't behaving properly.
> >>>>>>
> >>>>>> 1c) It's entirely possible that the old IP block and the new IP block
> >>>>>> are located at the same physical addresses but somehow work
> >>>>>> differently.  If so, the old IP block isn't documented.
> >>>>>>
> >>>>>>
> >>>>>> 2. As per the patch description, there is a single bit that controls
> >>>>>> all of the PWMs.  My guess is that there's actually a single IP block
> >>>>>> that implements all 4 PWMs.
> >>>>>
> >>>>> Looking at the register offsets in the device tree that seems likely. At
> >>>>> least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
> >>>>>
> >>>>> same IP block. Their placement in the register map is somewhat strange:
> >>>>>         pwm0: pwm at 20030000 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20030000 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM01>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         pwm1: pwm at 20030010 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20030010 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM01>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         ...
> >>>>>
> >>>>>         pwm2: pwm at 20050020 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20050020 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM23>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>>
> >>>>>         pwm3: pwm at 20050030 {
> >>>>>
> >>>>>                 ...
> >>>>>                 reg = <0x20050030 0x10>;
> >>>>>                 ...
> >>>>>                 clocks = <&cru PCLK_PWM23>;
> >>>>>                 ...
> >>>>>
> >>>>>         };
> >>>>
> >>>> Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
> >>>> (the downsides of trying to guess ahead of time what SoC vendors will
> >>>> name new models).
> >>>
> >>> It did sound like a nice idea at the time to hold the common stuff of
> >>> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
> >>> dramatically (including the core) would be called 4xxx or so :-) .
> >>>
> >>>>
> >>>> In rk3288 they have the same clocks.  See patch #3 in this series.
> >>>>
> >>>>> The clocks would also indicate that there are actually two blocks. I
> >>>>> seem to remember a discussion about whether to handle them as a single
> >>>>> block or two/four, but I can't seem to find a reference to it. Maybe I'm
> >>>>> confusing it with another driver.
> >>>>
> >>>> At this point it seems like the choice has already been made to handle
> >>>> them as separate PWMs.  I can change this choice if you want...
> >>>>
> >>>>>>>>>> This code could go lots of other places, but we've put it here.
> >>>>>>>>>> Why?
> >>>>>>>>>> - Pushing it to the bootloader just makes the code harder to update
> >>>>>>>>>> in
> >>>>>>>>>>
> >>>>>>>>>>   the field.  If we later find a bug in the new IP block and want
> >>>>>>>>>>   to
> >>>>>>>>>>   change our mind about what to use we want it to be easy to
> >>>>>>>>>>   update.
> >>>>>>>
> >>>>>>> Depending on how this muxing works you won't be able to change your
> >>>>>>> mind
> >>>>>>> anyway. If the IP blocks are different then the device tree will
> >>>>>>> effectively make the decision for you. So if you really want to be safe
> >>>>>>> you'd need to have code in the kernel that parses the device tree and
> >>>>>>> checks that all PWM instances are of the new type, then set this
> >>>>>>> register accordingly.
> >>>>>>
> >>>>>> Since there is no documentation about how you would instantiate the
> >>>>>> "old" type in the TRM and no good reason I can think of why someone
> >>>>>> would want to do this, it doesn't seem super fruitful.
> >>>>>
> >>>>> Okay, so if it's not at all documented and never used then yes, we'd
> >>>>> better just ignore it.
> >>>>
> >>>> Heiko just pointed me at the base address for the other block.
> >>>> There's nothing in the rk3288 TRM about it, but we can see the base
> >>>> address.  We could probably guess that it behaves the same as the
> >>>> older PWM if we need to.  I'm still not convinced there's a good
> >>>> reason for someone to use it.
> >>>
> >>> From what I understood the old one was included as a fallback in case some
> >>> drastic problem appeared with the newly developed IP. Similarly for the I2C
> >>> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
> >>> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
> >>> seems to have proven stable.
> >>>
> >>> So there really is no incentive to use the old one if no drastic issue has
> >>> appeared with the new one until now.
> >>>
> >>>
> >>>>>>>>>> diff --git a/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
> >>>>>>>>>> --- a/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> +++ b/arch/arm/mach-rockchip/rockchip.c
> >>>>>>>>>> @@ -24,6 +24,24 @@
> >>>>>>>>>>
> >>>>>>>>>>  #include <asm/hardware/cache-l2x0.h>
> >>>>>>>>>>  #include "core.h"
> >>>>>>>>>>
> >>>>>>>>>> +static void __init rk3288_init_machine(void)
> >>>>>>>>>> +{
> >>>>>>>>>> +     void *grf = ioremap(0xff770000, 0x10000);
> >>>>>>>>>
> >>>>>>>>> This region of memory is part of the "grf" "syscon" device
> >>>>>>>>> (according to
> >>>>>>>>> arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
> >>>>>>>>> from
> >>>>>>>>> that driver. It looks as if no such driver currently exists, but
> >>>>>>>>> given
> >>>>>>>>> the existence of the device tree node it's fair to assume that one
> >>>>>>>>> will
> >>>>>>>>> eventually be merged.
> >>>>>>>>
> >>>>>>>> The "grf" syscon device is the "general register file".  It's a
> >>>>>>>> collection of totally random registers stuffed together in one address
> >>>>>>>> space.  Sometimes a single 32-bit register has things you need to
> >>>>>>>> tweak for completely different subsystems.
> >>>>>>>>
> >>>>>>>> Most drivers referene the syscon using this in dts:
> >>>>>>>>   rockchip,grf = <&grf>;
> >>>>>>>>
> >>>>>>>> Then the drivers do:
> >>>>>>>>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
> >>>>>>>>
> >>>>>>>> See the Rockchip i2c, pinctrl, or clock drivers for examples.
> >>>>>>>
> >>>>>>> That's one way to do it. But if it's really just a one-time thing, then
> >>>>>>> you could easily perform the register write from the syscon driver
> >>>>>>> where
> >>>>>>> the memory is already parsed from device tree and mapped. That way you
> >>>>>>> don't have to hardcode the physical address in some other random piece
> >>>>>>> of code and map the memory again.
> >>>>>>
> >>>>>> Well, except that we're using the general "syscon" driver.  I could
> >>>>>> create a whole new driver that "subclasses" this syscon driver I
> >>>>>> suppose.
> >>>>>
> >>>>> Ah, I wasn't aware that there was even something like a generic syscon
> >>>>> driver. But yes, subclassing it sounds like a reasonable thing to do.
> >>>>
> >>>> I will do that if need be, but it's not my favorite.  I will let
> >>>> others chime in.
> >>>
> >>> I guess personally I like the idea best of just setting the relevant bit in
> >>> _probe of the pwm driver, like the i2c driver does:
> >>>
> >>> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
> >>>       /* get regmap and set bit */
> >>> }
> >>>
> >>> The downside would be that the bit would be written 4 times, but I guess this
> >>> shouldn't matter to much. And I don't think anybody will get the idea of
> >>> combining both ip variants in one dts anyway.
> >>> And of course in the next SoC the old IP will mostly have gone away and keep
> >>> this somewhat close to the driver and not scatter pwm settings into other
> >>> kernel parts.
> >>>
> >>> Hacking up the syscon driver feels bad to me, especially as it is meant to be
> >>> generic and export such shared registers to other drivers for just these stuff.
> >>
> >> I think using syscon in the first place is bad. In my opinion it would
> >> be far better to export an explicit API from drivers that are currently
> >> "implemented" as syscon. The thing is, nothing about syscon is truly
> >> generic. All it provides is a memory-mapped I/O region and lets drivers
> >> do to that memory region whatever they wants. But ioremap() can be used
> >> for that purpose already. Yet we have infrastructure to prevent drivers
> >> from doing that (request_resource() and friends) because it's usually a
> >> bad idea. All syscon really gives us is a ratified way of doing things
> >> that are otherwise frowned upon.
> > 
> > Agreed that it's a bit awkward, but it's the generally accepted way of
> > doing things across multiple drivers as far as I can tell...
> > 
> > In exynos we were also doing this.  Another alternative (which I saw
> > used before syscon) was just to list a second address in the "reg =
> > <>".  The second address might only be 4 bytes big if only a single
> > 32-bit register was needed.  That started failing because sometimes
> > two drivers needed to access the same 32-bit register.  Added Tomasz
> > to this thread since I remember him being a fan of solving this with
> > syscon.
> > 
> > 
> > At the moment I'm not planning to spin this patch.  If folks come up
> > with a solution that they definitely like better I'm happy to spin it,
> > but for now this seems to work and doesn't seem (to me) to be terribly
> > worse than the alternatives proposed so far.
> 
> So, in fact, I'm really a fan of the kind of solutions proposed by
> Thierry. My idea of handling this kind of integration details is that we
> should rather have a PMU driver on Exynos and it should be exporting all
> the various functions to configure certain subtle bits without the IP
> driver really knowing about SoC specifics. The PMU driver would know
> which bits in which registers to set up depending on SoC compatible
> string or data in PMU's device tree node.
> 
> I've been recommending the use of syscon for this purpose mostly because
> few times before I received negative opinions about the idea of private
> APIs like this and I simply didn't have time to push for them.

syscon is in fact not different from a private API. Except that the API
takes the form of arbitrary register accesses.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140821/d31ad540/attachment.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-21 16:47                       ` Thierry Reding
@ 2014-08-25 23:40                         ` Doug Anderson
  -1 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-25 23:40 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Heiko Stübner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel,
	Tomasz Figa

Thierry,

On Thu, Aug 21, 2014 at 9:47 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Thu, Aug 21, 2014 at 08:38:57AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko Stübner wrote:
>> >> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> >> > Thierry,
>> >> >
>> >> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >> >
>> >> > <thierry.reding@gmail.com> wrote:
>> >> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> > >> Thierry,
>> >> > >>
>> >> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >> > >>
>> >> > >> <thierry.reding@gmail.com> wrote:
>> >> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> > >> >> Thierry,
>> >> > >> >>
>> >> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> > >> >>
>> >> > >> >> <thierry.reding@gmail.com> wrote:
>> >> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> > >> >> >> system
>> >> > >> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> >> > >> >> >> to
>> >> > >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> > >> >> >> exist.
>> >> > >> >
>> >> > >> > A few more questions as to how this actually works. Does it mean there
>> >> > >> > are two physically separate blocks (with different physical addresses)
>> >> > >> > to control the same PWM? And this register simply causes some of the
>> >> > >> > pins to be routed to one or another? As far as I recall there are a
>> >> > >> > number of instances of the PWM block, so the above would need to count
>> >> > >> > for all of them. Or are there separate bits for each of them?
>> >> > >>
>> >> > >> All I have is the TRM (technical reference manual) which doesn't give
>> >> > >> me much more info than I've provided you.  But I can answer some of
>> >> > >> your questoins:
>> >> > >>
>> >> > >> 1. If there are two physically separate blocks then the "old" block is
>> >> > >> not documented in my TRM.
>> >> > >>
>> >> > >> 1a) It's entirely possible it's located at some memory address that is
>> >> > >> marked "Reserved" in the TRM, but I have no idea.
>> >> > >>
>> >> > >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> > >> are supposed to be "compatible" but that the old block is broken and
>> >> > >> thus isn't behaving properly.
>> >> > >>
>> >> > >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> > >> are located at the same physical addresses but somehow work
>> >> > >> differently.  If so, the old IP block isn't documented.
>> >> > >>
>> >> > >>
>> >> > >> 2. As per the patch description, there is a single bit that controls
>> >> > >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> > >> that implements all 4 PWMs.
>> >> > >
>> >> > > Looking at the register offsets in the device tree that seems likely. At
>> >> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >> > >
>> >> > > same IP block. Their placement in the register map is somewhat strange:
>> >> > >         pwm0: pwm@20030000 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20030000 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM01>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         pwm1: pwm@20030010 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20030010 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM01>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         ...
>> >> > >
>> >> > >         pwm2: pwm@20050020 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20050020 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM23>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         pwm3: pwm@20050030 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20050030 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM23>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> >
>> >> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> >> > (the downsides of trying to guess ahead of time what SoC vendors will
>> >> > name new models).
>> >>
>> >> It did sound like a nice idea at the time to hold the common stuff of
>> >> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> >> dramatically (including the core) would be called 4xxx or so :-) .
>> >>
>> >> >
>> >> > In rk3288 they have the same clocks.  See patch #3 in this series.
>> >> >
>> >> > > The clocks would also indicate that there are actually two blocks. I
>> >> > > seem to remember a discussion about whether to handle them as a single
>> >> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> >> > > confusing it with another driver.
>> >> >
>> >> > At this point it seems like the choice has already been made to handle
>> >> > them as separate PWMs.  I can change this choice if you want...
>> >> >
>> >> > >> >> >> This code could go lots of other places, but we've put it here.
>> >> > >> >> >> Why?
>> >> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> >> > >> >> >> in
>> >> > >> >> >>
>> >> > >> >> >>   the field.  If we later find a bug in the new IP block and want
>> >> > >> >> >>   to
>> >> > >> >> >>   change our mind about what to use we want it to be easy to
>> >> > >> >> >>   update.
>> >> > >> >
>> >> > >> > Depending on how this muxing works you won't be able to change your
>> >> > >> > mind
>> >> > >> > anyway. If the IP blocks are different then the device tree will
>> >> > >> > effectively make the decision for you. So if you really want to be safe
>> >> > >> > you'd need to have code in the kernel that parses the device tree and
>> >> > >> > checks that all PWM instances are of the new type, then set this
>> >> > >> > register accordingly.
>> >> > >>
>> >> > >> Since there is no documentation about how you would instantiate the
>> >> > >> "old" type in the TRM and no good reason I can think of why someone
>> >> > >> would want to do this, it doesn't seem super fruitful.
>> >> > >
>> >> > > Okay, so if it's not at all documented and never used then yes, we'd
>> >> > > better just ignore it.
>> >> >
>> >> > Heiko just pointed me at the base address for the other block.
>> >> > There's nothing in the rk3288 TRM about it, but we can see the base
>> >> > address.  We could probably guess that it behaves the same as the
>> >> > older PWM if we need to.  I'm still not convinced there's a good
>> >> > reason for someone to use it.
>> >>
>> >> From what I understood the old one was included as a fallback in case some
>> >> drastic problem appeared with the newly developed IP. Similarly for the I2C
>> >> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>> >> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>> >> seems to have proven stable.
>> >>
>> >> So there really is no incentive to use the old one if no drastic issue has
>> >> appeared with the new one until now.
>> >>
>> >>
>> >> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> >> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> @@ -24,6 +24,24 @@
>> >> > >> >> >>
>> >> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> > >> >> >>  #include "core.h"
>> >> > >> >> >>
>> >> > >> >> >> +static void __init rk3288_init_machine(void)
>> >> > >> >> >> +{
>> >> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> > >> >> >
>> >> > >> >> > This region of memory is part of the "grf" "syscon" device
>> >> > >> >> > (according to
>> >> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> >> > >> >> > from
>> >> > >> >> > that driver. It looks as if no such driver currently exists, but
>> >> > >> >> > given
>> >> > >> >> > the existence of the device tree node it's fair to assume that one
>> >> > >> >> > will
>> >> > >> >> > eventually be merged.
>> >> > >> >>
>> >> > >> >> The "grf" syscon device is the "general register file".  It's a
>> >> > >> >> collection of totally random registers stuffed together in one address
>> >> > >> >> space.  Sometimes a single 32-bit register has things you need to
>> >> > >> >> tweak for completely different subsystems.
>> >> > >> >>
>> >> > >> >> Most drivers referene the syscon using this in dts:
>> >> > >> >>   rockchip,grf = <&grf>;
>> >> > >> >>
>> >> > >> >> Then the drivers do:
>> >> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >> > >> >>
>> >> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >> > >> >
>> >> > >> > That's one way to do it. But if it's really just a one-time thing, then
>> >> > >> > you could easily perform the register write from the syscon driver
>> >> > >> > where
>> >> > >> > the memory is already parsed from device tree and mapped. That way you
>> >> > >> > don't have to hardcode the physical address in some other random piece
>> >> > >> > of code and map the memory again.
>> >> > >>
>> >> > >> Well, except that we're using the general "syscon" driver.  I could
>> >> > >> create a whole new driver that "subclasses" this syscon driver I
>> >> > >> suppose.
>> >> > >
>> >> > > Ah, I wasn't aware that there was even something like a generic syscon
>> >> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
>> >> >
>> >> > I will do that if need be, but it's not my favorite.  I will let
>> >> > others chime in.
>> >>
>> >> I guess personally I like the idea best of just setting the relevant bit in
>> >> _probe of the pwm driver, like the i2c driver does:
>> >>
>> >> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>> >>       /* get regmap and set bit */
>> >> }
>> >>
>> >> The downside would be that the bit would be written 4 times, but I guess this
>> >> shouldn't matter to much. And I don't think anybody will get the idea of
>> >> combining both ip variants in one dts anyway.
>> >> And of course in the next SoC the old IP will mostly have gone away and keep
>> >> this somewhat close to the driver and not scatter pwm settings into other
>> >> kernel parts.
>> >>
>> >> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>> >> generic and export such shared registers to other drivers for just these stuff.
>> >
>> > I think using syscon in the first place is bad. In my opinion it would
>> > be far better to export an explicit API from drivers that are currently
>> > "implemented" as syscon. The thing is, nothing about syscon is truly
>> > generic. All it provides is a memory-mapped I/O region and lets drivers
>> > do to that memory region whatever they wants. But ioremap() can be used
>> > for that purpose already. Yet we have infrastructure to prevent drivers
>> > from doing that (request_resource() and friends) because it's usually a
>> > bad idea. All syscon really gives us is a ratified way of doing things
>> > that are otherwise frowned upon.
>>
>> Agreed that it's a bit awkward, but it's the generally accepted way of
>> doing things across multiple drivers as far as I can tell...
>
> But that's exactly what I've been saying. I consider it a very bad thing
> that this is a generally accepted way. Sure, it's a very easy solution,
> but it also means that all the details about how the syscon registers
> need to be programmed are moved into drivers. That makes them inherently
> non-portable. Consider for example if you have a driver for an IP block
> that's used in one device and needs some registers set in a "syscon"
> device to work on that device. Now somebody licenses the same IP block
> and instantiates it in a completely different design. Now with some luck
> it won't need a syscon's help in the second design, so you can make the
> syscon optional and ignore it. But what if you need to program some
> syscon in the second design as well but it has a different register
> layout?
>
> Admittedly this will also be a problem if you have an explicit API, but
> then it's still better to create the proper abstraction that can be made
> to work on both SoCs, or as in the case of this PWM block you move the
> code that needs to be executed only once into the syscon driver where it
> belongs. That way the driver becomes completely generic, no need to play
> tricks because you (or somebody else for that matter) chose the easy way
> out.
>
>> In exynos we were also doing this.  Another alternative (which I saw
>> used before syscon) was just to list a second address in the "reg =
>> <>".  The second address might only be 4 bytes big if only a single
>> 32-bit register was needed.  That started failing because sometimes
>> two drivers needed to access the same 32-bit register.
>
> That's /exactly/ what syscon does as well (albeit with a bunch of
> overhead).
>
>> At the moment I'm not planning to spin this patch.  If folks come up
>> with a solution that they definitely like better I'm happy to spin it,
>> but for now this seems to work and doesn't seem (to me) to be terribly
>> worse than the alternatives proposed so far.
>
> I still think having a separate syscon driver that does this one-time
> initialization is the proper thing to do.

You probably noticed that I reposted my patches without the offending
parts.  Maybe we could at least land those while we figure things out?

It turns out that right now "syscon" can't be subclassed.  Heiko
pointed me at some WIP patches from Tomasz that allow subclassing of
syscon, but they're not all done yet.

I was doing some thinking about what to do, then.  I wondered whether
the right thing to do is not to make a "rk3288 syscon" driver that
configures these bits, but rather to make a "rk3288" driver has access
to the syscon.  It could live in drivers/soc/rockchip/rk3288.c and we
could give it a handle to the syscon.  It could do the one-time
initialization.  It would also be a place to put special rk3288 APIs
in cases where other drivers need similar things.

What do you think?

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-25 23:40                         ` Doug Anderson
  0 siblings, 0 replies; 69+ messages in thread
From: Doug Anderson @ 2014-08-25 23:40 UTC (permalink / raw)
  To: linux-arm-kernel

Thierry,

On Thu, Aug 21, 2014 at 9:47 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Thu, Aug 21, 2014 at 08:38:57AM -0700, Doug Anderson wrote:
>> Thierry,
>>
>> On Wed, Aug 20, 2014 at 11:36 PM, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>> > On Wed, Aug 20, 2014 at 06:20:31PM +0200, Heiko St?bner wrote:
>> >> Am Mittwoch, 20. August 2014, 08:55:09 schrieb Doug Anderson:
>> >> > Thierry,
>> >> >
>> >> > On Wed, Aug 20, 2014 at 8:38 AM, Thierry Reding
>> >> >
>> >> > <thierry.reding@gmail.com> wrote:
>> >> > > On Wed, Aug 20, 2014 at 08:20:53AM -0700, Doug Anderson wrote:
>> >> > >> Thierry,
>> >> > >>
>> >> > >> On Tue, Aug 19, 2014 at 11:08 PM, Thierry Reding
>> >> > >>
>> >> > >> <thierry.reding@gmail.com> wrote:
>> >> > >> > On Tue, Aug 19, 2014 at 08:18:54AM -0700, Doug Anderson wrote:
>> >> > >> >> Thierry,
>> >> > >> >>
>> >> > >> >> On Tue, Aug 19, 2014 at 12:10 AM, Thierry Reding
>> >> > >> >>
>> >> > >> >> <thierry.reding@gmail.com> wrote:
>> >> > >> >> > On Mon, Aug 18, 2014 at 10:09:06AM -0700, Doug Anderson wrote:
>> >> > >> >> >> The rk3288 SoC has an option to switch all of the PWMs in the
>> >> > >> >> >> system
>> >> > >> >> >> between the old IP block and the new IP block.  The new IP block is
>> >> > >> >> >> working and tested and the suggested PWM to use, so setup the SoC
>> >> > >> >> >> to
>> >> > >> >> >> use it and then we can pretend that the other IP block doesn't
>> >> > >> >> >> exist.
>> >> > >> >
>> >> > >> > A few more questions as to how this actually works. Does it mean there
>> >> > >> > are two physically separate blocks (with different physical addresses)
>> >> > >> > to control the same PWM? And this register simply causes some of the
>> >> > >> > pins to be routed to one or another? As far as I recall there are a
>> >> > >> > number of instances of the PWM block, so the above would need to count
>> >> > >> > for all of them. Or are there separate bits for each of them?
>> >> > >>
>> >> > >> All I have is the TRM (technical reference manual) which doesn't give
>> >> > >> me much more info than I've provided you.  But I can answer some of
>> >> > >> your questoins:
>> >> > >>
>> >> > >> 1. If there are two physically separate blocks then the "old" block is
>> >> > >> not documented in my TRM.
>> >> > >>
>> >> > >> 1a) It's entirely possible it's located at some memory address that is
>> >> > >> marked "Reserved" in the TRM, but I have no idea.
>> >> > >>
>> >> > >> 1b) It's entirely possible that the old IP block and the new IP block
>> >> > >> are supposed to be "compatible" but that the old block is broken and
>> >> > >> thus isn't behaving properly.
>> >> > >>
>> >> > >> 1c) It's entirely possible that the old IP block and the new IP block
>> >> > >> are located at the same physical addresses but somehow work
>> >> > >> differently.  If so, the old IP block isn't documented.
>> >> > >>
>> >> > >>
>> >> > >> 2. As per the patch description, there is a single bit that controls
>> >> > >> all of the PWMs.  My guess is that there's actually a single IP block
>> >> > >> that implements all 4 PWMs.
>> >> > >
>> >> > > Looking at the register offsets in the device tree that seems likely. At
>> >> > > least PWMs 0 and 1 as well as 2 and 3 seem like they could be in the
>> >> > >
>> >> > > same IP block. Their placement in the register map is somewhat strange:
>> >> > >         pwm0: pwm at 20030000 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20030000 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM01>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         pwm1: pwm at 20030010 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20030010 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM01>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         ...
>> >> > >
>> >> > >         pwm2: pwm at 20050020 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20050020 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM23>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> > >
>> >> > >         pwm3: pwm at 20050030 {
>> >> > >
>> >> > >                 ...
>> >> > >                 reg = <0x20050030 0x10>;
>> >> > >                 ...
>> >> > >                 clocks = <&cru PCLK_PWM23>;
>> >> > >                 ...
>> >> > >
>> >> > >         };
>> >> >
>> >> > Ah, you're looking at "rk3xxx.dtsi".  That doesn't apply to rk3288
>> >> > (the downsides of trying to guess ahead of time what SoC vendors will
>> >> > name new models).
>> >>
>> >> It did sound like a nice idea at the time to hold the common stuff of
>> >> rk3066/rk3188 and all their derivatives and I assumed a SoC that changed
>> >> dramatically (including the core) would be called 4xxx or so :-) .
>> >>
>> >> >
>> >> > In rk3288 they have the same clocks.  See patch #3 in this series.
>> >> >
>> >> > > The clocks would also indicate that there are actually two blocks. I
>> >> > > seem to remember a discussion about whether to handle them as a single
>> >> > > block or two/four, but I can't seem to find a reference to it. Maybe I'm
>> >> > > confusing it with another driver.
>> >> >
>> >> > At this point it seems like the choice has already been made to handle
>> >> > them as separate PWMs.  I can change this choice if you want...
>> >> >
>> >> > >> >> >> This code could go lots of other places, but we've put it here.
>> >> > >> >> >> Why?
>> >> > >> >> >> - Pushing it to the bootloader just makes the code harder to update
>> >> > >> >> >> in
>> >> > >> >> >>
>> >> > >> >> >>   the field.  If we later find a bug in the new IP block and want
>> >> > >> >> >>   to
>> >> > >> >> >>   change our mind about what to use we want it to be easy to
>> >> > >> >> >>   update.
>> >> > >> >
>> >> > >> > Depending on how this muxing works you won't be able to change your
>> >> > >> > mind
>> >> > >> > anyway. If the IP blocks are different then the device tree will
>> >> > >> > effectively make the decision for you. So if you really want to be safe
>> >> > >> > you'd need to have code in the kernel that parses the device tree and
>> >> > >> > checks that all PWM instances are of the new type, then set this
>> >> > >> > register accordingly.
>> >> > >>
>> >> > >> Since there is no documentation about how you would instantiate the
>> >> > >> "old" type in the TRM and no good reason I can think of why someone
>> >> > >> would want to do this, it doesn't seem super fruitful.
>> >> > >
>> >> > > Okay, so if it's not at all documented and never used then yes, we'd
>> >> > > better just ignore it.
>> >> >
>> >> > Heiko just pointed me at the base address for the other block.
>> >> > There's nothing in the rk3288 TRM about it, but we can see the base
>> >> > address.  We could probably guess that it behaves the same as the
>> >> > older PWM if we need to.  I'm still not convinced there's a good
>> >> > reason for someone to use it.
>> >>
>> >> From what I understood the old one was included as a fallback in case some
>> >> drastic problem appeared with the newly developed IP. Similarly for the I2C
>> >> the rk2928 and before contained the old IP, the rk3xxx SoCs did contain both
>> >> old and new i2c IP and now the rk3288 only contains the new one, as the new IP
>> >> seems to have proven stable.
>> >>
>> >> So there really is no incentive to use the old one if no drastic issue has
>> >> appeared with the new one until now.
>> >>
>> >>
>> >> > >> >> >> diff --git a/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> b/arch/arm/mach-rockchip/rockchip.c index 8ab9e0e..99133b9 100644
>> >> > >> >> >> --- a/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> +++ b/arch/arm/mach-rockchip/rockchip.c
>> >> > >> >> >> @@ -24,6 +24,24 @@
>> >> > >> >> >>
>> >> > >> >> >>  #include <asm/hardware/cache-l2x0.h>
>> >> > >> >> >>  #include "core.h"
>> >> > >> >> >>
>> >> > >> >> >> +static void __init rk3288_init_machine(void)
>> >> > >> >> >> +{
>> >> > >> >> >> +     void *grf = ioremap(0xff770000, 0x10000);
>> >> > >> >> >
>> >> > >> >> > This region of memory is part of the "grf" "syscon" device
>> >> > >> >> > (according to
>> >> > >> >> > arch/arm/boot/dts/rk3288.dtsi) so the register should be accessed
>> >> > >> >> > from
>> >> > >> >> > that driver. It looks as if no such driver currently exists, but
>> >> > >> >> > given
>> >> > >> >> > the existence of the device tree node it's fair to assume that one
>> >> > >> >> > will
>> >> > >> >> > eventually be merged.
>> >> > >> >>
>> >> > >> >> The "grf" syscon device is the "general register file".  It's a
>> >> > >> >> collection of totally random registers stuffed together in one address
>> >> > >> >> space.  Sometimes a single 32-bit register has things you need to
>> >> > >> >> tweak for completely different subsystems.
>> >> > >> >>
>> >> > >> >> Most drivers referene the syscon using this in dts:
>> >> > >> >>   rockchip,grf = <&grf>;
>> >> > >> >>
>> >> > >> >> Then the drivers do:
>> >> > >> >>   grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
>> >> > >> >>
>> >> > >> >> See the Rockchip i2c, pinctrl, or clock drivers for examples.
>> >> > >> >
>> >> > >> > That's one way to do it. But if it's really just a one-time thing, then
>> >> > >> > you could easily perform the register write from the syscon driver
>> >> > >> > where
>> >> > >> > the memory is already parsed from device tree and mapped. That way you
>> >> > >> > don't have to hardcode the physical address in some other random piece
>> >> > >> > of code and map the memory again.
>> >> > >>
>> >> > >> Well, except that we're using the general "syscon" driver.  I could
>> >> > >> create a whole new driver that "subclasses" this syscon driver I
>> >> > >> suppose.
>> >> > >
>> >> > > Ah, I wasn't aware that there was even something like a generic syscon
>> >> > > driver. But yes, subclassing it sounds like a reasonable thing to do.
>> >> >
>> >> > I will do that if need be, but it's not my favorite.  I will let
>> >> > others chime in.
>> >>
>> >> I guess personally I like the idea best of just setting the relevant bit in
>> >> _probe of the pwm driver, like the i2c driver does:
>> >>
>> >> if (of_device_is_compatible(np, "rockchip,rk3288-pwm") {
>> >>       /* get regmap and set bit */
>> >> }
>> >>
>> >> The downside would be that the bit would be written 4 times, but I guess this
>> >> shouldn't matter to much. And I don't think anybody will get the idea of
>> >> combining both ip variants in one dts anyway.
>> >> And of course in the next SoC the old IP will mostly have gone away and keep
>> >> this somewhat close to the driver and not scatter pwm settings into other
>> >> kernel parts.
>> >>
>> >> Hacking up the syscon driver feels bad to me, especially as it is meant to be
>> >> generic and export such shared registers to other drivers for just these stuff.
>> >
>> > I think using syscon in the first place is bad. In my opinion it would
>> > be far better to export an explicit API from drivers that are currently
>> > "implemented" as syscon. The thing is, nothing about syscon is truly
>> > generic. All it provides is a memory-mapped I/O region and lets drivers
>> > do to that memory region whatever they wants. But ioremap() can be used
>> > for that purpose already. Yet we have infrastructure to prevent drivers
>> > from doing that (request_resource() and friends) because it's usually a
>> > bad idea. All syscon really gives us is a ratified way of doing things
>> > that are otherwise frowned upon.
>>
>> Agreed that it's a bit awkward, but it's the generally accepted way of
>> doing things across multiple drivers as far as I can tell...
>
> But that's exactly what I've been saying. I consider it a very bad thing
> that this is a generally accepted way. Sure, it's a very easy solution,
> but it also means that all the details about how the syscon registers
> need to be programmed are moved into drivers. That makes them inherently
> non-portable. Consider for example if you have a driver for an IP block
> that's used in one device and needs some registers set in a "syscon"
> device to work on that device. Now somebody licenses the same IP block
> and instantiates it in a completely different design. Now with some luck
> it won't need a syscon's help in the second design, so you can make the
> syscon optional and ignore it. But what if you need to program some
> syscon in the second design as well but it has a different register
> layout?
>
> Admittedly this will also be a problem if you have an explicit API, but
> then it's still better to create the proper abstraction that can be made
> to work on both SoCs, or as in the case of this PWM block you move the
> code that needs to be executed only once into the syscon driver where it
> belongs. That way the driver becomes completely generic, no need to play
> tricks because you (or somebody else for that matter) chose the easy way
> out.
>
>> In exynos we were also doing this.  Another alternative (which I saw
>> used before syscon) was just to list a second address in the "reg =
>> <>".  The second address might only be 4 bytes big if only a single
>> 32-bit register was needed.  That started failing because sometimes
>> two drivers needed to access the same 32-bit register.
>
> That's /exactly/ what syscon does as well (albeit with a bunch of
> overhead).
>
>> At the moment I'm not planning to spin this patch.  If folks come up
>> with a solution that they definitely like better I'm happy to spin it,
>> but for now this seems to work and doesn't seem (to me) to be terribly
>> worse than the alternatives proposed so far.
>
> I still think having a separate syscon driver that does this one-time
> initialization is the proper thing to do.

You probably noticed that I reposted my patches without the offending
parts.  Maybe we could at least land those while we figure things out?

It turns out that right now "syscon" can't be subclassed.  Heiko
pointed me at some WIP patches from Tomasz that allow subclassing of
syscon, but they're not all done yet.

I was doing some thinking about what to do, then.  I wondered whether
the right thing to do is not to make a "rk3288 syscon" driver that
configures these bits, but rather to make a "rk3288" driver has access
to the syscon.  It could live in drivers/soc/rockchip/rk3288.c and we
could give it a handle to the syscon.  It could do the one-time
initialization.  It would also be a place to put special rk3288 APIs
in cases where other drivers need similar things.

What do you think?

-Doug

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
  2014-08-25 23:40                         ` Doug Anderson
@ 2014-08-26  7:31                           ` Thierry Reding
  -1 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-26  7:31 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Heiko Stübner, Caesar Wang, Sonny Rao, Olof Johansson,
	Eddie Cai, Russell King, linux-arm-kernel, linux-kernel,
	Tomasz Figa

[-- Attachment #1: Type: text/plain, Size: 825 bytes --]

On Mon, Aug 25, 2014 at 04:40:57PM -0700, Doug Anderson wrote:
[...]
> I was doing some thinking about what to do, then.  I wondered whether
> the right thing to do is not to make a "rk3288 syscon" driver that
> configures these bits, but rather to make a "rk3288" driver has access
> to the syscon.  It could live in drivers/soc/rockchip/rk3288.c and we
> could give it a handle to the syscon.  It could do the one-time
> initialization.  It would also be a place to put special rk3288 APIs
> in cases where other drivers need similar things.
> 
> What do you think?

Yes, that could work. There have been recent discussions about adding
such machine drivers that match on the top-level compatible string in
the DT.

I still think that subclassing syscon would be the cleanest solution,
though.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP
@ 2014-08-26  7:31                           ` Thierry Reding
  0 siblings, 0 replies; 69+ messages in thread
From: Thierry Reding @ 2014-08-26  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 04:40:57PM -0700, Doug Anderson wrote:
[...]
> I was doing some thinking about what to do, then.  I wondered whether
> the right thing to do is not to make a "rk3288 syscon" driver that
> configures these bits, but rather to make a "rk3288" driver has access
> to the syscon.  It could live in drivers/soc/rockchip/rk3288.c and we
> could give it a handle to the syscon.  It could do the one-time
> initialization.  It would also be a place to put special rk3288 APIs
> in cases where other drivers need similar things.
> 
> What do you think?

Yes, that could work. There have been recent discussions about adding
such machine drivers that match on the top-level compatible string in
the DT.

I still think that subclassing syscon would be the cleanest solution,
though.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/d26f983c/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 69+ messages in thread

end of thread, other threads:[~2014-08-26  7:31 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18 17:09 [PATCH 0/4] PWM changes for rk3288-evb Doug Anderson
2014-08-18 17:09 ` Doug Anderson
2014-08-18 17:09 ` [PATCH 1/4] ARM: rockchip: rk3288: Switch to use the proper PWM IP Doug Anderson
2014-08-18 17:09   ` Doug Anderson
2014-08-18 17:11   ` Sonny Rao
2014-08-18 17:11     ` Sonny Rao
2014-08-18 17:19     ` Doug Anderson
2014-08-18 17:19       ` Doug Anderson
2014-08-19  7:10   ` Thierry Reding
2014-08-19  7:10     ` Thierry Reding
2014-08-19 15:18     ` Doug Anderson
2014-08-19 15:18       ` Doug Anderson
2014-08-20  6:08       ` Thierry Reding
2014-08-20  6:08         ` Thierry Reding
2014-08-20 15:20         ` Doug Anderson
2014-08-20 15:20           ` Doug Anderson
2014-08-20 15:38           ` Thierry Reding
2014-08-20 15:38             ` Thierry Reding
2014-08-20 15:55             ` Doug Anderson
2014-08-20 15:55               ` Doug Anderson
2014-08-20 16:20               ` Heiko Stübner
2014-08-20 16:20                 ` Heiko Stübner
2014-08-20 16:27                 ` Doug Anderson
2014-08-20 16:27                   ` Doug Anderson
2014-08-20 18:03                   ` Heiko Stübner
2014-08-20 18:03                     ` Heiko Stübner
2014-08-20 20:49                     ` Doug Anderson
2014-08-20 20:49                       ` Doug Anderson
2014-08-21  6:36                 ` Thierry Reding
2014-08-21  6:36                   ` Thierry Reding
2014-08-21 15:38                   ` Doug Anderson
2014-08-21 15:38                     ` Doug Anderson
2014-08-21 15:49                     ` Tomasz Figa
2014-08-21 15:49                       ` Tomasz Figa
2014-08-21 16:49                       ` Thierry Reding
2014-08-21 16:49                         ` Thierry Reding
2014-08-21 16:47                     ` Thierry Reding
2014-08-21 16:47                       ` Thierry Reding
2014-08-25 23:40                       ` Doug Anderson
2014-08-25 23:40                         ` Doug Anderson
2014-08-26  7:31                         ` Thierry Reding
2014-08-26  7:31                           ` Thierry Reding
2014-08-21  6:24               ` Thierry Reding
2014-08-21  6:24                 ` Thierry Reding
2014-08-21 15:39                 ` Doug Anderson
2014-08-21 15:39                   ` Doug Anderson
2014-08-21 15:53                 ` Heiko Stübner
2014-08-21 15:53                   ` Heiko Stübner
2014-08-18 17:09 ` [PATCH 2/4] pwm: rockchip: Allow polarity invert on rk3288 Doug Anderson
2014-08-18 17:09   ` Doug Anderson
2014-08-18 17:09   ` Doug Anderson
2014-08-19  7:18   ` Thierry Reding
2014-08-19  7:18     ` Thierry Reding
2014-08-19 16:05     ` Doug Anderson
2014-08-19 16:05       ` Doug Anderson
2014-08-19 16:05       ` Doug Anderson
2014-08-20  6:09       ` Thierry Reding
2014-08-20  6:09         ` Thierry Reding
2014-08-20  6:09         ` Thierry Reding
2014-08-18 17:09 ` [PATCH 3/4] ARM: dts: Add main PWM info to rk3288 Doug Anderson
2014-08-18 17:09   ` Doug Anderson
2014-08-18 17:09 ` [PATCH 4/4] ARM: dts: Enable pwm backlight on rk3288-EVB Doug Anderson
2014-08-18 17:09   ` Doug Anderson
2014-08-19  7:22   ` Thierry Reding
2014-08-19  7:22     ` Thierry Reding
2014-08-19  7:22     ` Thierry Reding
2014-08-19 16:05     ` Doug Anderson
2014-08-19 16:05       ` Doug Anderson
2014-08-19 16:05       ` Doug Anderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.