Skip to contentSkip to conversation

arm: add basic support for Rockchip Cortex-A9 SoCs

PATCH In review Heiko Stübner 12 participants 43 messages Jun 2, 2013 – Jun 6, 2013

Subsystems (11)
lore
Share & tools
lore

Heiko Stübner

author maintainer
#0 lore raw

Prepare your eggs and tomatoes please, I got myself a second playground ;-) .

As the title implies this series adds basic support for Rockchip's Cortex-A9 SoCs, like the RK3066 used in many cheaper tablets.

On the periphal side it's very lightweight, as it seems someone from Rockchip was shopping in the DesignWare store.

This makes the pinctrl driver the biggest hunk in the series, but to get some bonus points I used the generic_irq implementation for the interrupt handling, based on Thomas' irqdomain support series.

Supported periphals are, the timers, uarts and mmc controllers, so interested parties will need a serial console for now.

Hopefully I didn't mess up to much :-)

Dependencies:
- the irqdomain support for the generic_irq from Thomas Gleixner is required by the pinctrl driver
- "mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA" moves the SDMMC_CMD_USE_HOLD_REG constant into the common header, which is required on these Rockchip SoCs

Heiko Stuebner (10):
clocksource: dw_apb_timer_of: use the clocksource as sched clock if
necessary
clocksource: dw_apb_timer_of: add clock-handling
clk: flag to use upper half of the register as change indicator
clk: divider: add flag to limit possible dividers to even numbers
mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove
mmc: dw_mmc-pltfm: add Rockchip variant
pinctrl: add pinctrl driver for Rockchip SoCs
clk: add basic Rockchip rk3066a clock support
arm: add debug uarts for rockchip rk29xx and rk3xxx series
arm: add basic support for Rockchip RK3066a boards

 .../bindings/pinctrl/rockchip-pinctrl.txt          |  100 ++
 Documentation/devicetree/bindings/rtc/dw-apb.txt   |   19 +
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Kconfig.debug                             |   34 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/rk3066a-clocks.dtsi              |  459 +++++++
 arch/arm/boot/dts/rk3066a.dtsi                     |  359 ++++++
 arch/arm/include/debug/rockchip.S                  |   42 +
 arch/arm/mach-rockchip/Kconfig                     |   17 +
 arch/arm/mach-rockchip/Makefile                    |    1 +
 arch/arm/mach-rockchip/Makefile.boot               |    3 +
 arch/arm/mach-rockchip/rockchip.c                  |   54 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk-divider.c                          |   29 +-
 drivers/clk/clk-gate.c                             |   24 +-
 drivers/clk/clk-mux.c                              |   15 +-
 drivers/clk/rockchip/Makefile                      |    6 +
 drivers/clk/rockchip/clk-rockchip-pll.c            |  131 ++
 drivers/clk/rockchip/clk-rockchip-pll.h            |   19 +
 drivers/clk/rockchip/clk-rockchip.c                |  315 +++++
 drivers/clocksource/dw_apb_timer_of.c              |   52 +-
 drivers/mmc/host/dw_mmc-pltfm.c                    |   48 +-
 drivers/pinctrl/Kconfig                            |    6 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-rockchip.c                 | 1319 ++++++++++++++++++++
 include/dt-bindings/pinctrl/rockchip.h             |   37 +
 include/linux/clk-provider.h                       |   18 +
 include/linux/clk/rockchip.h                       |   21 +
 28 files changed, 3097 insertions(+), 36 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt
 create mode 100644 arch/arm/boot/dts/rk3066a-clocks.dtsi
 create mode 100644 arch/arm/boot/dts/rk3066a.dtsi
 create mode 100644 arch/arm/include/debug/rockchip.S
 create mode 100644 arch/arm/mach-rockchip/Kconfig
 create mode 100644 arch/arm/mach-rockchip/Makefile
 create mode 100644 arch/arm/mach-rockchip/Makefile.boot
 create mode 100644 arch/arm/mach-rockchip/rockchip.c
 create mode 100644 drivers/clk/rockchip/Makefile
 create mode 100644 drivers/clk/rockchip/clk-rockchip-pll.c
 create mode 100644 drivers/clk/rockchip/clk-rockchip-pll.h
 create mode 100644 drivers/clk/rockchip/clk-rockchip.c
 create mode 100644 drivers/pinctrl/pinctrl-rockchip.c
 create mode 100644 include/dt-bindings/pinctrl/rockchip.h
 create mode 100644 include/linux/clk/rockchip.h
Signature · 1 line
1.7.2.3
author maintainer
#1 lore raw

PATCH 1/10 clocksource: dw_apb_timer_of: use the clocksource as sched clock if necessary

Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have the sptimer but can use the clocksource as sched_clock. Therefore this patch adds using the clocksource timer as
a fallback if no usable sched timer is found.

---
 drivers/clocksource/dw_apb_timer_of.c |   26 +++++++++++++++++---------
 1 files changed, 17 insertions(+), 9 deletions(-)
drivers/clocksource/dw_apb_timer_of.c +17 -9
index ab09ed3..d6c0fda 100644
@@ -57,6 +57,9 @@ static void add_clockevent(struct device_node *event_timer)
 	dw_apb_clockevent_register(ced);
 }
 
+static void __iomem *sched_io_base;
+static u32 sched_rate;
+
 static void add_clocksource(struct device_node *source_timer)
 {
 	void __iomem *iobase;
@@ -71,9 +74,15 @@ static void add_clocksource(struct device_node *source_timer)
 
 	dw_apb_clocksource_start(cs);
 	dw_apb_clocksource_register(cs);
-}
 
-static void __iomem *sched_io_base;
+	/*
+	 * Fallback to use the clocksource as sched_clock if no separate
+	 * timer is found. sched_io_base then points to the current_value
+	 * register of the clocksource timer.
+	 */
+	sched_io_base = iobase + 0x04;
+	sched_rate = rate;
+}
 
 static u32 read_sched_clock(void)
 {
@@ -89,16 +98,15 @@ static const struct of_device_id sptimer_ids[] __initconst = {
 static void init_sched_clock(void)
 {
 	struct device_node *sched_timer;
-	u32 rate;
 
 	sched_timer = of_find_matching_node(NULL, sptimer_ids);
-	if (!sched_timer)
-		panic("No RTC for sched clock to use");
-
-	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
-	of_node_put(sched_timer);
+	if (sched_timer) {
+		timer_get_base_and_rate(sched_timer, &sched_io_base,
+					&sched_rate);
+		of_node_put(sched_timer);
+	}
 
-	setup_sched_clock(read_sched_clock, 32, rate);
+	setup_sched_clock(read_sched_clock, 32, sched_rate);
 }
 
 static const struct of_device_id osctimer_ids[] __initconst = {
Signature · 1 line
1.7.2.3
#2 lore raw

Re: [PATCH 01/10] clocksource: dw_apb_timer_of: use the clocksource as sched clock if necessary

Quoted 7 lines · Heiko St?bner

Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have the sptimer but can use the clocksource as sched_clock. Therefore this patch adds using the clocksource timer as
a fallback if no usable sched timer is found.

Is this really what the patch does? I mean "ass the clocksourse as fallback", it seems more like that is controlled from the device tree, this looks more like some more careful handling of the device tree input making the sched_timer optional, it doesn't really "add" anything, does it?

Yours,
Linus Walleij

author maintainer
#3 lore raw

Re: [PATCH 01/10] clocksource: dw_apb_timer_of: use the clocksource as sched clock if necessary

Am Dienstag, 4. Juni 2013, 08:34:44 schrieb Linus Walleij:

Quoted 7 lines · Heiko St?bner
Quoted 6 lines

Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have the sptimer but can use the clocksource as sched_clock. Therefore this patch adds using the clocksource timer as
a fallback if no usable sched timer is found.

Quoted 7 lines
Quoted 1 line

Is this really what the patch does? I mean "ass the clocksourse as fallback", it seems more like that is controlled from the device tree, this looks more like some more careful handling of the device tree input making the sched_timer optional, it doesn't really "add" anything, does it?

Right, the commit message is probably based a bit to much on the before-state of the driver, always expecting the "sptimer" and panicing if not found.

How about:

Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have this sptimer but can use the clocksource as sched_clock instead.

Therefore enable the driver to distiguish between devices with and without sptimer based on the devicetree data and select the correct timer as sched_clock.

#4 lore raw

Re: [PATCH 01/10] clocksource: dw_apb_timer_of: use the clocksource as sched clock if necessary

Quoted 9 lines · Heiko St?bner

How about:

Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have this sptimer but can use the clocksource as sched_clock instead.

Therefore enable the driver to distiguish between devices with and without sptimer based on the devicetree data and select the correct timer as sched_clock.

Allright, Acked-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

author maintainer
#5 lore raw

PATCH 2/10 clocksource: dw_apb_timer_of: add clock-handling

In reply to Heiko Stübner

Add the possibility to get the clock-frequency from a timer clock instead of specifying it as dt property. Additionally also add the possibility to also define a controlling periphal clock for the timer block.

The clock-frequency property is kept to act as fallback if no clocks are specified.

---
 Documentation/devicetree/bindings/rtc/dw-apb.txt |   19 ++++++++++++++++
 drivers/clocksource/dw_apb_timer_of.c            |   26 +++++++++++++++++++++-
 2 files changed, 44 insertions(+), 1 deletions(-)
Documentation/devicetree/bindings/rtc/dw-apb.txt +19 -0
index 93e2b0f..80ab1c1 100644
@@ -5,9 +5,20 @@ Required properties:
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: IRQ line for the timer.
+- either clocks+clock-names or clock-frequency properties
+
+Optional properties:
+- clocks	: list of clock specifiers, corresponding to entries in
+		  the clock-names property;
+- clock-names	: should contain "timer and "pclk" entries, matching entries
+		  in the clocks property.
 - clock-frequency: The frequency in HZ of the timer.
 - clock-freq: For backwards compatibility with picoxcell
 
+If using the clock specifiers, the pclk clock is optional, as not all
+systems may use one.
+
+
 Example:
 
 		timer1: timer at ffc09000 {
@@ -23,3 +34,11 @@ Example:
 				clock-frequency = <200000000>;
 				reg = <0xffd00000 0x1000>;
 			};
+
+		timer3: timer at ffe00000 {
+				compatible = "snps,dw-apb-timer-osc";
+				interrupts = <0 170 4>;
+				reg = <0xffe00000 0x1000>;
+				clocks = <&timer_clk>, <&timer_pclk>;
+				clock-names = "timer", "pclk";
+			};
drivers/clocksource/dw_apb_timer_of.c +25 -1
index d6c0fda..1964f87 100644
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/clk.h>
 
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
@@ -27,14 +28,37 @@
 static void timer_get_base_and_rate(struct device_node *np,
 				    void __iomem **base, u32 *rate)
 {
+	struct clk *timer_clk;
+	struct clk *pclk;
+
 	*base = of_iomap(np, 0);
 
 	if (!*base)
 		panic("Unable to map regs for %s", np->name);
 
+	/*
+	 * Not all implementations use a periphal clock, so don't panic
+	 * if it's not present
+	 */
+	pclk = of_clk_get_by_name(np, "pclk");
+	if (!IS_ERR(pclk))
+		if (clk_prepare_enable(pclk))
+			pr_warn("pclk for %s is present, but could not be activated\n",
+				np->name);
+
+	timer_clk = of_clk_get_by_name(np, "timer");
+	if (IS_ERR(timer_clk))
+		goto try_clock_freq;
+
+	if (!clk_prepare_enable(timer_clk)) {
+		*rate = clk_get_rate(timer_clk);
+		return;
+	}
+
+try_clock_freq:
 	if (of_property_read_u32(np, "clock-freq", rate) &&
 		of_property_read_u32(np, "clock-frequency", rate))
-		panic("No clock-frequency property for %s", np->name);
+		panic("No clock nor clock-frequency property for %s", np->name);
 }
 
 static void add_clockevent(struct device_node *event_timer)
Signature · 1 line
1.7.2.3
#6 lore raw

Re: [PATCH 02/10] clocksource: dw_apb_timer_of: add clock-handling

Hi Heiko,

Quoted 18 lines · Heiko St?bner

Add the possibility to get the clock-frequency from a timer clock instead of specifying it as dt property. Additionally also add the possibility to also define a controlling periphal clock for the timer block.

The clock-frequency property is kept to act as fallback if no clocks are specified.

---
 Documentation/devicetree/bindings/rtc/dw-apb.txt |   19 ++++++++++++++++
 drivers/clocksource/dw_apb_timer_of.c            |   26 +++++++++++++++++++++-
 2 files changed, 44 insertions(+), 1 deletions(-)
Documentation/devicetree/bindings/rtc/dw-apb.txt +0 -0
index 93e2b0f..80ab1c1 100644

Documentation/devicetree/bindings/rtc/dw-apb.txt Required properties: · line 13

Quoted 9 lines
Documentation/devicetree/bindings/rtc/dw-apb.txt +6 -0
@@ -5,9 +5,20 @@ Required properties:
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: IRQ line for the timer.
+- either clocks+clock-names or clock-frequency properties
+
+Optional properties:
+- clocks	: list of clock specifiers, corresponding to entries in
+		  the clock-names property;
+- clock-names	: should contain "timer and "pclk" entries, matching entries

Missing closing quotes around "timer".

baruch

Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
author maintainer
#7 lore raw

Re: [PATCH 02/10] clocksource: dw_apb_timer_of: add clock-handling

Am Montag, 3. Juni 2013, 05:22:19 schrieb Baruch Siach:

Quoted 32 lines

Hi Heiko,

Quoted 29 lines · Heiko St?bner

Add the possibility to get the clock-frequency from a timer clock instead of specifying it as dt property. Additionally also add the possibility to also define a controlling periphal clock for the timer block.

The clock-frequency property is kept to act as fallback if no clocks are specified.

---

 Documentation/devicetree/bindings/rtc/dw-apb.txt |   19 ++++++++++++++++
 drivers/clocksource/dw_apb_timer_of.c            |   26

+++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletions(-)

(quoted diff) +0 -0

b/Documentation/devicetree/bindings/rtc/dw-apb.txt index 93e2b0f..80ab1c1 100644

Documentation/devicetree/bindings/rtc/dw-apb.txt +0 -0
@@ -5,9 +5,20 @@ Required properties:
 - reg: physical base address of the controller and length of memory
 mapped
 
   region.
 
 - interrupts: IRQ line for the timer.
 
Quoted 9 lines
Quoted 7 lines
Documentation/devicetree/bindings/rtc/dw-apb.txt +6 -0
+- either clocks+clock-names or clock-frequency properties
+
+Optional properties:
+- clocks	: list of clock specifiers, corresponding to entries in
+		  the clock-names property;
+- clock-names	: should contain "timer and "pclk" entries, matching

entries

Missing closing quotes around "timer".

thanks for finding ... will fix in the next run

author maintainer
#8 lore raw

PATCH 3/10 clk: flag to use upper half of the register as change indicator

In reply to Heiko Stübner

There exist platforms, namely at least all Rockchip Cortex-A9 based ones, that don't use the paradigm of reading-changing-writing the register contents, but instead only write the changes to the register with a mask that indicates the changed bits.

This patch adds flags and code to support the case where the lower 16 bit of hold the information and the upper 16 bit are used as mask to indicate the written changes.

As hardware-specific flags should not be added to the common clk flags, the flags are added to gate, mux and divider clocks individually.

---
 drivers/clk/clk-divider.c    |   15 +++++++++++++--
 drivers/clk/clk-gate.c       |   24 ++++++++++++++++++------
 drivers/clk/clk-mux.c        |   15 +++++++++++++--
 include/linux/clk-provider.h |   16 ++++++++++++++++
 4 files changed, 60 insertions(+), 10 deletions(-)
drivers/clk/clk-divider.c +13 -2
index 6d96741..e37c48a 100644
@@ -217,8 +217,12 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (divider->lock)
 		spin_lock_irqsave(divider->lock, flags);
 
-	val = readl(divider->reg);
-	val &= ~(div_mask(divider) << divider->shift);
+	if (divider->flags & CLK_DIVIDER_MASK_UPPER_HALF) {
+		val = div_mask(divider) << (divider->shift + 16);
+	} else {
+		val = readl(divider->reg);
+		val &= ~(div_mask(divider) << divider->shift);
+	}
 	val |= value << divider->shift;
 	writel(val, divider->reg);
 
@@ -245,6 +249,13 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	struct clk *clk;
 	struct clk_init_data init;
 
+	if ((clk_divider_flags & CLK_DIVIDER_MASK_UPPER_HALF) &&
+	    (shift + width > 15)) {
+		pr_err("%s: shift %d + width %d invalid\n", __func__,
+		       shift, width);
+		return ERR_PTR(-EINVAL);
+	}
+
 	/* allocate the divider */
 	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
 	if (!div) {
drivers/clk/clk-gate.c +18 -6
index 15114fe..e553fa7 100644
@@ -53,12 +53,19 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 	if (gate->lock)
 		spin_lock_irqsave(gate->lock, flags);
 
-	reg = readl(gate->reg);
-
-	if (set)
-		reg |= BIT(gate->bit_idx);
-	else
-		reg &= ~BIT(gate->bit_idx);
+	if (gate->flags & CLK_GATE_MASK_UPPER_HALF) {
+		reg = BIT(gate->bit_idx + 16);
+
+		if (set)
+			reg |= BIT(gate->bit_idx);
+	} else {
+		reg = readl(gate->reg);
+
+		if (set)
+			reg |= BIT(gate->bit_idx);
+		else
+			reg &= ~BIT(gate->bit_idx);
+	}
 
 	writel(reg, gate->reg);
 
@@ -121,6 +128,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	struct clk *clk;
 	struct clk_init_data init;
 
+	if ((clk_gate_flags & CLK_GATE_MASK_UPPER_HALF) && bit_idx > 15) {
+		pr_err("%s: bit_idx %d invalid\n", __func__, bit_idx);
+		return ERR_PTR(-EINVAL);
+	}
+
 	/* allocate the gate */
 	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
 	if (!gate) {
drivers/clk/clk-mux.c +13 -2
index 25b1734..fce26f5 100644
@@ -86,8 +86,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 	if (mux->lock)
 		spin_lock_irqsave(mux->lock, flags);
 
-	val = readl(mux->reg);
-	val &= ~(mux->mask << mux->shift);
+	if (mux->flags & CLK_MUX_MASK_UPPER_HALF) {
+		val = mux->mask << (mux->shift + 16);
+	} else {
+		val = readl(mux->reg);
+		val &= ~(mux->mask << mux->shift);
+	}
 	val |= index << mux->shift;
 	writel(val, mux->reg);
 
@@ -112,6 +116,13 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 	struct clk *clk;
 	struct clk_init_data init;
 
+	if (!mask || ((clk_mux_flags & CLK_MUX_MASK_UPPER_HALF) &&
+		      (__fls(mask << shift) > 15))) {
+		pr_err("%s: shift %d + mask %d invalid\n", __func__,
+		       shift, mask);
+		return ERR_PTR(-EINVAL);
+	}
+
 	/* allocate the mux */
 	mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
 	if (!mux) {
include/linux/clk-provider.h +16 -0
index 265f384..420a187 100644
@@ -210,6 +210,11 @@ void of_fixed_clk_setup(struct device_node *np);
  * CLK_GATE_SET_TO_DISABLE - by default this clock sets the bit at bit_idx to
  * 	enable the clock.  Setting this flag does the opposite: setting the bit
  * 	disable the clock and clearing it enables the clock
+ * CLK_GATE_MASK_UPPER_HALF - this clock only uses the lower 16 bit of the
+ *	register to hold the gate bits, while using the upper 16 bit to
+ *	indicate the bits that get changed during a write. So gating the
+ *	clock in bit 2 would write BIT(18) | BIT(2) to the register, while
+ *	ungating this clock would write only BIT(18) to the register.
  */
 struct clk_gate {
 	struct clk_hw hw;
@@ -220,6 +225,7 @@ struct clk_gate {
 };
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
+#define CLK_GATE_MASK_UPPER_HALF	BIT(1)
 
 extern const struct clk_ops clk_gate_ops;
 struct clk *clk_register_gate(struct device *dev, const char *name,
@@ -257,6 +263,11 @@ struct clk_div_table {
  *	Some hardware implementations gracefully handle this case and allow a
  *	zero divisor by not modifying their input clock
  *	(divide by one / bypass).
+ * CLK_DIVIDER_MASK_UPPER_HALF - this clock only uses the lower 16 bit of the
+ *	register to hold the divider bits, while using the upper 16 bit to
+ *	indicate the bits that get changed during a write. So for a clock with
+ *	shift 0 and width 2, setting the divider to 2 would result in a write
+ *	of (3 << 16) | (2 << 0).
  */
 struct clk_divider {
 	struct clk_hw	hw;
@@ -271,6 +282,7 @@ struct clk_divider {
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
 #define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
+#define CLK_DIVIDER_MASK_UPPER_HALF	BIT(3)
 
 extern const struct clk_ops clk_divider_ops;
 struct clk *clk_register_divider(struct device *dev, const char *name,
@@ -299,6 +311,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
  * Flags:
  * CLK_MUX_INDEX_ONE - register index starts@1, not 0
  * CLK_MUX_INDEX_BIT - register index is a single bit (power of two)
+ * CLK_MUX_MASK_UPPER_HALF - this clock only uses the lower 16 bit of the
+ *	register to hold the mux bits, while using the upper 16 bit to
+ *	indicate the bits that get changed during a write.
  */
 struct clk_mux {
 	struct clk_hw	hw;
@@ -312,6 +327,7 @@ struct clk_mux {
 
 #define CLK_MUX_INDEX_ONE		BIT(0)
 #define CLK_MUX_INDEX_BIT		BIT(1)
+#define CLK_MUX_MASK_UPPER_HALF		BIT(3)
 
 extern const struct clk_ops clk_mux_ops;
 
Signature · 1 line
1.7.2.3
author maintainer
#9 lore raw

PATCH 4/10 clk: divider: add flag to limit possible dividers to even numbers

In reply to Heiko Stübner

SoCs like the Rockchip Cortex-A9 ones contain divider some clocks that use the regular mechanisms for storage but allow only even dividers and 1 to be used.

Therefore add a flag that lets _is_valid_div limit the valid dividers to these values. _get_maxdiv is also adapted to return even values for the CLK_DIVIDER_ONE_BASED case.

---
 drivers/clk/clk-divider.c    |   14 ++++++++++++--
 include/linux/clk-provider.h |    2 ++
 2 files changed, 14 insertions(+), 2 deletions(-)
drivers/clk/clk-divider.c +12 -2
index e37c48a..adfbd0d 100644
@@ -45,8 +45,16 @@ static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
 
 static unsigned int _get_maxdiv(struct clk_divider *divider)
 {
-	if (divider->flags & CLK_DIVIDER_ONE_BASED)
-		return div_mask(divider);
+	if (divider->flags & CLK_DIVIDER_ONE_BASED) {
+		unsigned int div = div_mask(divider);
+
+		/* decrease to even number */
+		if (divider->flags & CLK_DIVIDER_EVEN)
+			div--;
+
+		return div;
+	}
+
 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
 		return 1 << div_mask(divider);
 	if (divider->table)
@@ -141,6 +149,8 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
 		return is_power_of_2(div);
 	if (divider->table)
 		return _is_valid_table_div(divider->table, div);
+	if (divider->flags & CLK_DIVIDER_EVEN && div != 1 && (div % 2) != 0)
+		return false;
 	return true;
 }
 
include/linux/clk-provider.h +2 -0
index 420a187..9fdd60d 100644
@@ -268,6 +268,7 @@ struct clk_div_table {
  *	indicate the bits that get changed during a write. So for a clock with
  *	shift 0 and width 2, setting the divider to 2 would result in a write
  *	of (3 << 16) | (2 << 0).
+ * CLK_DIVIDER_EVEN - only allow even divider values
  */
 struct clk_divider {
 	struct clk_hw	hw;
@@ -283,6 +284,7 @@ struct clk_divider {
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
 #define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
 #define CLK_DIVIDER_MASK_UPPER_HALF	BIT(3)
+#define CLK_DIVIDER_EVEN		BIT(4)
 
 extern const struct clk_ops clk_divider_ops;
 struct clk *clk_register_divider(struct device *dev, const char *name,
Signature · 1 line
1.7.2.3
author maintainer
#10 lore raw

PATCH 5/10 mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove

In reply to Heiko Stübner

dw_mci_pltfm_remove gets exported and used by dw_mmc-exynos, so should not be static.

---
 drivers/mmc/host/dw_mmc-pltfm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/mmc/host/dw_mmc-pltfm.c +1 -1
index 37873f1..0048da8 100644
@@ -68,7 +68,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
 	return dw_mci_pltfm_register(pdev, NULL);
 }
 
-static int dw_mci_pltfm_remove(struct platform_device *pdev)
+int dw_mci_pltfm_remove(struct platform_device *pdev)
 {
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
Signature · 1 line
1.7.2.3
maintainer Acked-by on v1 5/10
#11 lore raw

Re: [PATCH 05/10] mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove

Quoted 22 lines · Heiko Stübner

dw_mci_pltfm_remove gets exported and used by dw_mmc-exynos, so should not be static.

---
 drivers/mmc/host/dw_mmc-pltfm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/mmc/host/dw_mmc-pltfm.c +1 -1
index 37873f1..0048da8 100644
@@ -68,7 +68,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
 	return dw_mci_pltfm_register(pdev, NULL);
 }
 
-static int dw_mci_pltfm_remove(struct platform_device *pdev)
+int dw_mci_pltfm_remove(struct platform_device *pdev)
 {
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
author maintainer
#13 lore raw

PATCH 6/10 mmc: dw_mmc-pltfm: add Rockchip variant

In reply to Heiko Stübner

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

---
 drivers/mmc/host/dw_mmc-pltfm.c |   48 +++++++++++++++++++++++++++-----------
 1 files changed, 34 insertions(+), 14 deletions(-)
drivers/mmc/host/dw_mmc-pltfm.c +34 -14
index 0048da8..7d041b5 100644
@@ -24,6 +24,16 @@
 
 #include "dw_mmc.h"
 
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
+{
+	*cmdr |= SDMMC_CMD_USE_HOLD_REG;
+}
+
+static const struct dw_mci_drv_data rockchip_drv_data = {
+	.prepare_command	= dw_mci_rockchip_prepare_command,
+};
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
 				const struct dw_mci_drv_data *drv_data)
 {
@@ -63,20 +73,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
-{
-	return dw_mci_pltfm_register(pdev, NULL);
-}
-
-int dw_mci_pltfm_remove(struct platform_device *pdev)
-{
-	struct dw_mci *host = platform_get_drvdata(pdev);
-
-	dw_mci_remove(host);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
-
 #ifdef CONFIG_PM_SLEEP
 /*
  * TODO: we should probably disable the clock to the card in the suspend path.
@@ -114,10 +110,34 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
+	{ .compatible = "rockchip,cortex-a9-dw-mshc",
+		.data = &rockchip_drv_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data = NULL;
+	const struct of_device_id *match;
+
+	if (pdev->dev.of_node) {
+		match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node);
+		drv_data = match->data;
+	}
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+int dw_mci_pltfm_remove(struct platform_device *pdev)
+{
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+	dw_mci_remove(host);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
+
 static struct platform_driver dw_mci_pltfm_driver = {
 	.probe		= dw_mci_pltfm_probe,
 	.remove		= dw_mci_pltfm_remove,
Signature · 1 line
1.7.2.3
maintainer
#14 lore raw

Re: [PATCH 06/10] mmc: dw_mmc-pltfm: add Rockchip variant

Quoted 18 lines · Heiko Stübner

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

---
 drivers/mmc/host/dw_mmc-pltfm.c |   48 +++++++++++++++++++++++++++-----------
 1 files changed, 34 insertions(+), 14 deletions(-)
drivers/mmc/host/dw_mmc-pltfm.c +0 -0
index 0048da8..7d041b5 100644

drivers/mmc/host/dw_mmc-pltfm.c line 28

Quoted 5 lines
drivers/mmc/host/dw_mmc-pltfm.c +2 -0
@@ -24,6 +24,16 @@
 
 #include "dw_mmc.h"
 
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)

How about using "dw_mci_pltfm_prepare_command()"?
Maybe HOLD_REG could be used at other SoC.

Quoted 68 lines
drivers/mmc/host/dw_mmc-pltfm.c +32 -14
+{
+	*cmdr |= SDMMC_CMD_USE_HOLD_REG;
+}
+
+static const struct dw_mci_drv_data rockchip_drv_data = {
+	.prepare_command	= dw_mci_rockchip_prepare_command,
+};
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
 				const struct dw_mci_drv_data *drv_data)
 {
@@ -63,20 +73,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
-{
-	return dw_mci_pltfm_register(pdev, NULL);
-}
-
-int dw_mci_pltfm_remove(struct platform_device *pdev)
-{
-	struct dw_mci *host = platform_get_drvdata(pdev);
-
-	dw_mci_remove(host);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
-
 #ifdef CONFIG_PM_SLEEP
 /*
  * TODO: we should probably disable the clock to the card in the suspend path.
@@ -114,10 +110,34 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
+	{ .compatible = "rockchip,cortex-a9-dw-mshc",
+		.data = &rockchip_drv_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data = NULL;
+	const struct of_device_id *match;
+
+	if (pdev->dev.of_node) {
+		match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node);
+		drv_data = match->data;
+	}
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+int dw_mci_pltfm_remove(struct platform_device *pdev)
+{
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+	dw_mci_remove(host);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
+
 static struct platform_driver dw_mci_pltfm_driver = {
 	.probe		= dw_mci_pltfm_probe,
 	.remove		= dw_mci_pltfm_remove,
author maintainer
#15 lore raw

Re: [PATCH 06/10] mmc: dw_mmc-pltfm: add Rockchip variant

Am Dienstag, 4. Juni 2013, 06:06:39 schrieb Jaehoon Chung:

Quoted 22 lines · Heiko St?bner
Quoted 21 lines

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

---

 drivers/mmc/host/dw_mmc-pltfm.c |   48

+++++++++++++++++++++++++++----------- 1 files changed, 34 insertions(+), 14 deletions(-)

(quoted diff) +0 -0

b/drivers/mmc/host/dw_mmc-pltfm.c index 0048da8..7d041b5 100644

drivers/mmc/host/dw_mmc-pltfm.c +0 -0
@@ -24,6 +24,16 @@
 
Quoted 8 lines

drivers/mmc/host/dw_mmc-pltfm.c

Quoted 5 lines
drivers/mmc/host/dw_mmc-pltfm.c +2 -0
 #include "dw_mmc.h"
 
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32
 *cmdr)

How about using "dw_mci_pltfm_prepare_command()"?
Maybe HOLD_REG could be used at other SoC.

The problem I had when thinking about it is that every implementation using the HOLD_REG stuff does it differently ... on the Exynos variant it depends on the CLKSEL register value and on the SOCFPGA variant on other clock values.

It's only on the Rockchip variant that it seems to needed all the time.

So, doing it with a "dw_mci_pltfm_prepare_command()" would need a flag to signal that the implementation needs the HOLD_REG all the time, but we won't know yet if other implementations will have other constraints on its use - like only i special cases or such.

So personally I would keep it as it is for now, until more platforms using the HOLD_REG come along to see some sort of pattern of its use?

#16 lore raw

RE: [PATCH 06/10] mmc: dw_mmc-pltfm: add Rockchip variant

In reply to Heiko Stübner
Quoted 18 lines · Heiko St?bner

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

---
 drivers/mmc/host/dw_mmc-pltfm.c |   48 +++++++++++++++++++++++++++-----------
 1 files changed, 34 insertions(+), 14 deletions(-)
drivers/mmc/host/dw_mmc-pltfm.c +0 -0
index 0048da8..7d041b5 100644

drivers/mmc/host/dw_mmc-pltfm.c line 30

Quoted 7 lines
drivers/mmc/host/dw_mmc-pltfm.c +4 -0
@@ -24,6 +24,16 @@
 
 #include "dw_mmc.h"
 
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
+{
+	*cmdr |= SDMMC_CMD_USE_HOLD_REG;

Currently, SDMMC_CMD_USE_HOLD_REG is defined in dw_mmc-exynos.c It should be moved to dw_mmc.h

Thanks,
Seungwon Jeon

Quoted 72 lines
drivers/mmc/host/dw_mmc-pltfm.c +30 -15
+}
+
+static const struct dw_mci_drv_data rockchip_drv_data = {
+	.prepare_command	= dw_mci_rockchip_prepare_command,
+};
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
 				const struct dw_mci_drv_data *drv_data)
 {
@@ -63,20 +73,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
-{
-	return dw_mci_pltfm_register(pdev, NULL);
-}
-
-int dw_mci_pltfm_remove(struct platform_device *pdev)
-{
-	struct dw_mci *host = platform_get_drvdata(pdev);
-
-	dw_mci_remove(host);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
-
 #ifdef CONFIG_PM_SLEEP
 /*
  * TODO: we should probably disable the clock to the card in the suspend path.
@@ -114,10 +110,34 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
+	{ .compatible = "rockchip,cortex-a9-dw-mshc",
+		.data = &rockchip_drv_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
 
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data = NULL;
+	const struct of_device_id *match;
+
+	if (pdev->dev.of_node) {
+		match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node);
+		drv_data = match->data;
+	}
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+int dw_mci_pltfm_remove(struct platform_device *pdev)
+{
+	struct dw_mci *host = platform_get_drvdata(pdev);
+
+	dw_mci_remove(host);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
+
 static struct platform_driver dw_mci_pltfm_driver = {
 	.probe		= dw_mci_pltfm_probe,
 	.remove		= dw_mci_pltfm_remove,
--

1.7.2.3

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

author maintainer
#17 lore raw

Re: [PATCH 06/10] mmc: dw_mmc-pltfm: add Rockchip variant

Am Mittwoch, 5. Juni 2013, 16:00:43 schrieb Seungwon Jeon:

Quoted 24 lines · Heiko St?bner
Quoted 23 lines

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

---

 drivers/mmc/host/dw_mmc-pltfm.c |   48

+++++++++++++++++++++++++++----------- 1 files changed, 34 insertions(+), 14 deletions(-)

(quoted diff) +0 -0

b/drivers/mmc/host/dw_mmc-pltfm.c index 0048da8..7d041b5 100644

drivers/mmc/host/dw_mmc-pltfm.c +0 -0
@@ -24,6 +24,16 @@
 
 #include "dw_mmc.h"
 
Quoted 7 lines

drivers/mmc/host/dw_mmc-pltfm.c line 30

Quoted 4 lines
drivers/mmc/host/dw_mmc-pltfm.c +3 -0
+
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32
 *cmdr) +{
+	*cmdr |= SDMMC_CMD_USE_HOLD_REG;

Currently, SDMMC_CMD_USE_HOLD_REG is defined in dw_mmc-exynos.c It should be moved to dw_mmc.h

It's already done in another patch "mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA" from Dinh Nguyen <[email protected]>, which I therefore named as dependency in the cover letter.

Don't know if it's better to also include the move here again and let the merging person sort out the conflict?

#18 lore raw

Re: [PATCH 06/10] mmc: dw_mmc-pltfm: add Rockchip variant

In reply to Heiko Stübner
Quoted 7 lines · Heiko St?bner

Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set.

There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver.

Few comments below.

drivers/mmc/host/dw_mmc-pltfm.c line 27

Quoted 7 lines
drivers/mmc/host/dw_mmc-pltfm.c +1 -0
@@ -24,6 +24,16 @@
 
 #include "dw_mmc.h"
 
+

No need to add extra empty line here.

Quoted 10 lines
drivers/mmc/host/dw_mmc-pltfm.c +1 -4
+static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
 
@@ -63,20 +73,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-static int dw_mci_pltfm_probe(struct platform_device *pdev)
-{
-       return dw_mci_pltfm_register(pdev, NULL);
-}

drivers/mmc/host/dw_mmc-pltfm.c int dw_mci_pltfm_register(struct platform_device *pdev, · line 79

Quoted 10 lines
drivers/mmc/host/dw_mmc-pltfm.c +0 -10
-
-int dw_mci_pltfm_remove(struct platform_device *pdev)
-{
-       struct dw_mci *host = platform_get_drvdata(pdev);
-
-       dw_mci_remove(host);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove);
-

If you want to move those through code, please do separate patch.

--
With Best Regards,
Andy Shevchenko

author maintainer
#19 lore raw

PATCH 7/10 pinctrl: add pinctrl driver for Rockchip SoCs

In reply to Heiko Stübner

This driver adds support the Cortex-A9 based SoCs from Rockchip, so at least the RK2928, RK3066 (a and b) and RK3188. Earlier Rockchip SoCs seem to use similar mechanics for gpio handling so should be supportable with relative small changes. Pull handling on the rk3188 is currently a stub, due to it being a bit different to the earlier SoCs.

Pinmuxing as well as gpio (and interrupt-) handling tested on a rk3066a based machine.

---
 .../bindings/pinctrl/rockchip-pinctrl.txt          |  100 ++
 drivers/pinctrl/Kconfig                            |    6 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-rockchip.c                 | 1319 ++++++++++++++++++++
 include/dt-bindings/pinctrl/rockchip.h             |   37 +
 5 files changed, 1463 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt
 create mode 100644 drivers/pinctrl/pinctrl-rockchip.c
 create mode 100644 include/dt-bindings/pinctrl/rockchip.h
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +100 -0
new file mode 100644
index 0000000..b939192
@@ -0,0 +1,100 @@
+* Rockchip Pinmux Controller
+
+The Rockchip Pinmux Controller, enables the IC
+to share one PAD to several functional blocks. The sharing is done by
+multiplexing the PAD input/output signals. For each PAD there are up to
+4 muxing options with option 0 being the use as a GPIO.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The Rockchip pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and
+config of the pins in that group. The 'pins' selects the function mode(also
+named pin mode) this pin can work on and the 'config' configures various pad
+settings such as pull-up, etc.
+
+The pins are grouped into up to 5 individual pin banks which need to be
+defined as gpio sub-nodes of the pinmux controller.
+
+Required properties for iomux controller:
+  - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
+		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
+
+Required properties for gpio sub nodes:
+  - compatible: "rockchip,gpio-bank"
+  - reg: register of the gpio bank (different than the iomux registerset)
+  - interrupts: base interrupt of the gpio bank in the interrupt controller
+  - clocks: clock that drives this bank
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.
+  - interrupt-controller: identifies the controller node as interrupt-parent.
+  - #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       external gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
+
+
+Required properties for pin configuration node:
+  - rockchip,pins: 4 integers array, represents a group of pins mux and config
+    setting. The format is rockchip,pins = <PIN_BANK PIN_BANK_NUM MUX CONFIG>.
+    The MUX 0 means gpio and MUX 1 to 3 mean the specific device function
+
+Bits used for CONFIG:
+PULL_AUTO	(1 << 0): indicate this pin needs a pull setting for SoCs
+			  that determine the pull up or down themselfs
+PULL_UP		(1 << 1): indicate this pin needs a pull up
+PULL_DOWN	(1 << 2): indicate this pin needs a pull down
+
+Examples:
+
+pinctrl@20008000 {
+	compatible = "rockchip,rk3066a-pinctrl";
+	reg = <0x20008000 0x150>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	gpio0: gpio0 at 20034000 {
+		compatible = "rockchip,gpio-bank";
+		reg = <0x20034000 0x100>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clk_gates8 9>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	...
+
+	uart2 {
+		uart2_xfer: uart2-xfer {
+			rockchip,pins = <RK_GPIO1 8 1 RK_PINCTRL_PULL_AUTO>,
+					<RK_GPIO1 9 1 RK_PINCTRL_PULL_AUTO>;
+		};
+	};
+};
+
+uart2: serial at 20064000 {
+	compatible = "snps,dw-apb-uart";
+	reg = <0x20064000 0x400>;
+	interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+	reg-shift = <2>;
+	reg-io-width = <1>;
+	clocks = <&mux_uart2>;
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_xfer>;
+};
drivers/pinctrl/Kconfig +6 -0
index 5259d40..3e8cf8d 100644
@@ -158,6 +158,12 @@ config PINCTRL_DB8540
 	bool "DB8540 pin controller driver"
 	depends on PINCTRL_NOMADIK && ARCH_U8500
 
+config PINCTRL_ROCKCHIP
+	bool
+	select PINMUX
+	select PINCONF
+	select GENERIC_IRQ_CHIP
+
 config PINCTRL_SINGLE
 	tristate "One-register-per-pin type device tree based pinctrl driver"
 	depends on OF
drivers/pinctrl/Makefile +1 -0
index 3b26e3c..16c3f8bc 100644
@@ -31,6 +31,7 @@ obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
 obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
 obj-$(CONFIG_PINCTRL_DB8500)	+= pinctrl-nomadik-db8500.o
 obj-$(CONFIG_PINCTRL_DB8540)	+= pinctrl-nomadik-db8540.o
+obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_SIRF)	+= sirf/
 obj-$(CONFIG_PINCTRL_SUNXI)	+= pinctrl-sunxi.o
drivers/pinctrl/pinctrl-rockchip.c new file +1319 -0

1,319 lines not on this page · raw message

include/dt-bindings/pinctrl/rockchip.h new file +37 -0
new file mode 100644
index 0000000..8721db2
@@ -0,0 +1,37 @@
+/*
+ * Header providing constants for Rockchip pinctrl bindings.
+ *
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
+#define __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
+
+#define RK_GPIO0	0
+#define RK_GPIO1	1
+#define RK_GPIO2	2
+#define RK_GPIO3	3
+#define RK_GPIO4	4
+#define RK_GPIO6	6
+
+#define RK_FUNC_GPIO	0
+#define RK_FUNC_1	1
+#define RK_FUNC_2	2
+
+#define RK_PINCTRL_NONE		0
+#define RK_PINCTRL_PULL_AUTO	(1 << 0)
+#define RK_PINCTRL_PULL_UP	(1 << 1)
+#define RK_PINCTRL_PULL_DOWN	(1 << 2)
+
+#endif
Signature · 1 line
1.7.2.3
#20 lore raw

Re: [PATCH 07/10] pinctrl: add pinctrl driver for Rockchip SoCs

Quoted 11 lines · Heiko St?bner

This driver adds support the Cortex-A9 based SoCs from Rockchip, so at least the RK2928, RK3066 (a and b) and RK3188. Earlier Rockchip SoCs seem to use similar mechanics for gpio handling so should be supportable with relative small changes. Pull handling on the rk3188 is currently a stub, due to it being a bit different to the earlier SoCs.

Pinmuxing as well as gpio (and interrupt-) handling tested on a rk3066a based machine.

Overall this is looking very good, mainly minor comments.

Quoted 1 line

+++ b/Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt

Please name this beginning with the vendor and similar to the compatible string: rockchip,pinctrl or something. (Check the neighbors.)

(...)

Quoted 9 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +9 -0
+Required properties for gpio sub nodes:
+  - compatible: "rockchip,gpio-bank"
+  - reg: register of the gpio bank (different than the iomux registerset)
+  - interrupts: base interrupt of the gpio bank in the interrupt controller
+  - clocks: clock that drives this bank
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 43

Quoted 10 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +10 -0
+  - interrupt-controller: identifies the controller node as interrupt-parent.
+  - #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       external gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered

Can't you just reference Documentation/devicetree/bindings/interrupt-controller/interrupts.txt?

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 53

Quoted 8 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +8 -0
+Required properties for pin configuration node:
+  - rockchip,pins: 4 integers array, represents a group of pins mux and config
+    setting. The format is rockchip,pins = <PIN_BANK PIN_BANK_NUM MUX CONFIG>.
+    The MUX 0 means gpio and MUX 1 to 3 mean the specific device function
+
+Bits used for CONFIG:
+PULL_AUTO      (1 << 0): indicate this pin needs a pull setting for SoCs
+                         that determine the pull up or down themselfs

Hm, never saw that before...

(...)

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 85

Quoted 5 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +5 -0
+       uart2 {
+               uart2_xfer: uart2-xfer {
+                       rockchip,pins = <RK_GPIO1 8 1 RK_PINCTRL_PULL_AUTO>,
+                                       <RK_GPIO1 9 1 RK_PINCTRL_PULL_AUTO>;
+               };

This looks like you're using #include to define these constants, probably you should include that in the example or mention it?

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 92

Quoted 4 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +4 -0
+uart2: serial at 20064000 {
+       compatible = "snps,dw-apb-uart";
+       reg = <0x20064000 0x400>;
+       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;

Using #defines, nice!

(...)
+++ b/drivers/pinctrl/Kconfig
@@ -158,6 +158,12 @@ config PINCTRL_DB8540
bool "DB8540 pin controller driver"
depends on PINCTRL_NOMADIK && ARCH_U8500

+config PINCTRL_ROCKCHIP

+       bool
+       select PINMUX
+       select PINCONF
+       select GENERIC_IRQ_CHIP

Why is this super-simple pin config thing not using GENERIC_PINCONF?

I *know* it is simpler to implement your own thing, but think of the poor maintainers that have to wade through 50 identical implementations. Do this, it pays off.

BTW: it leads to wanting to use generic pinconf DT bindings as experienced by Laurent and others. We need to fix that too...

(...)

drivers/pinctrl/pinctrl-rockchip.c line 247

Quoted 6 lines

+++ b/drivers/pinctrl/pinctrl-rockchip.c

drivers/pinctrl/pinctrl-rockchip.c new file +5 -0
+static void rockchip_pin_dbg_show(struct pinctrl_dev *pctldev,
+                                       struct seq_file *s, unsigned offset)
+{
+       seq_printf(s, "%s", dev_name(pctldev->dev));
+}

Nothing else you want to say about the pins here?
(No big deal for sure, but....)

drivers/pinctrl/pinctrl-rockchip.c line 367

Quoted 5 lines
drivers/pinctrl/pinctrl-rockchip.c new file +5 -0
+static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       void __iomem *reg;
+       int bit;

Is that really an int? I'd guess more like u8...

drivers/pinctrl/pinctrl-rockchip.c line 377

Quoted 10 lines
drivers/pinctrl/pinctrl-rockchip.c new file +10 -0
+       u32 data;
+
+       /* rk3066b does support any pulls */
+       if (!info->ctrl->pull_offset)
+               return 0;
+
+       reg = info->reg_base + info->ctrl->pull_offset;
+
+       if (info->ctrl->pull_auto) {
+               reg += bank->bank_num * 8;

I'd define some constant like

#define RK_BANK_STRIDE 8
reg += bank->bank_num * RK_BANK_STRIDE;
(Since 8 bytes of stride is no natural law.)

And then use that here and elsewhere.

Review

Quoted 2 lines
(quoted diff) +2 -0
+               reg += (pin_num / 16) * 4;
+               bit = pin_num % 16;

This is clear however.

drivers/pinctrl/pinctrl-rockchip.c line 385

Quoted 6 lines
drivers/pinctrl/pinctrl-rockchip.c new file +6 -0
+
+               data = readl_relaxed(reg);
+               data >>= bit;
+               data &= 1;
+
+               return !data;

That's a bit hard to read, I'd just:

#include <linux/bitops.h>
return !(readl_relaxed(reg) & BIT(bit));

And skip the "data" variable. The ! operator will
clamp this to a bool (0/1).

But we all have our habits.

drivers/pinctrl/pinctrl-rockchip.c line 393

Quoted 2 lines
drivers/pinctrl/pinctrl-rockchip.c new file +2 -0
+static int rockchip_set_pull(struct rockchip_pin_bank *bank,
+                                       int pin_num, int pull)

Similar comments for this function.

Quoted 3 lines
drivers/pinctrl/pinctrl-rockchip.c new file +3 -0
+static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                             struct pinctrl_gpio_range *range,
+                                             unsigned offset, bool input)

(...)

drivers/pinctrl/pinctrl-rockchip.c line 542

Quoted 5 lines
drivers/pinctrl/pinctrl-rockchip.c new file +5 -0
+       /* set bit to 1 for output, 0 for input */
+       if (!input)
+               data |= (1 << pin);
+       else
+               data &= ~(1 << pin);

Here again I would use <linux/bitops.h> and:

data |= BIT(pin);

etc, but it's a matter of taste so if you prefer this, do keep it.

(...)

drivers/pinctrl/pinctrl-rockchip.c line 934

Quoted 5 lines
drivers/pinctrl/pinctrl-rockchip.c new file +5 -0
+static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct rockchip_pin_bank *bank = gc->private;
+       u32 bit = (1 << d->hwirq);

Name that something like "mask" to match other naming in the kernel. "bit" sort of implies a number between 0 and 31 and that is not the case.

All I could think of right now...

Yours,
Linus Walleij

author maintainer
#21 lore raw

Re: [PATCH 07/10] pinctrl: add pinctrl driver for Rockchip SoCs

Hi,

I'll just skip over the "right, will fix that" issues and just address the unclear ones.

Am Dienstag, 4. Juni 2013, 09:08:09 schrieb Linus Walleij:

Quoted 15 lines · Heiko St?bner
Quoted 11 lines

This driver adds support the Cortex-A9 based SoCs from Rockchip, so at least the RK2928, RK3066 (a and b) and RK3188. Earlier Rockchip SoCs seem to use similar mechanics for gpio handling so should be supportable with relative small changes. Pull handling on the rk3188 is currently a stub, due to it being a bit different to the earlier SoCs.

Pinmuxing as well as gpio (and interrupt-) handling tested on a rk3066a based machine.

Overall this is looking very good, mainly minor comments.

Quoted 10 lines

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 53

Quoted 8 lines
(quoted diff) +2 -0
+Required properties for pin configuration node:
+  - rockchip,pins: 4 integers array, represents a group of pins mux and

config + setting. The format is rockchip,pins = <PIN_BANK
PIN_BANK_NUM MUX CONFIG>. + The MUX 0 means gpio and MUX 1 to 3 mean
the specific device function +

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +3 -0
+Bits used for CONFIG:
+PULL_AUTO      (1 << 0): indicate this pin needs a pull setting for SoCs
+                         that determine the pull up or down themselfs

Hm, never saw that before...

Citing the original gpio driver:

/*
* Values written to this register independently
* control Pullup/Pulldown or not for the
* corresponding data bit in GPIO.
* 0: pull up/down enable, PAD type will decide
* to be up or down, not related with this value
* 1: pull up/down disable
*/

So if it's a pull up or down is decided based on the mux of the pin. Calling everything a "pull down" (or up) when it isn't seemed somehow wrong to me.

The rk3188 on the other hand supports both pull up and down separately.

Or should this be selected as PULL_UP | PULL_DOWN in the config?

Quoted 6 lines

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 92

Quoted 4 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +4 -0
+uart2: serial at 20064000 {
+       compatible = "snps,dw-apb-uart";
+       reg = <0x20064000 0x400>;
+       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;

Using #defines, nice!

everything for bonus-points ;-)

And actually it's definitly easier on me as well, as I don't have to remember what each integer value means.

Quoted 14 lines

+++ b/drivers/pinctrl/Kconfig

drivers/pinctrl/Kconfig +5 -0
@@ -158,6 +158,12 @@ config PINCTRL_DB8540
        bool "DB8540 pin controller driver"
        depends on PINCTRL_NOMADIK && ARCH_U8500
 
+config PINCTRL_ROCKCHIP
+       bool
+       select PINMUX
+       select PINCONF
+       select GENERIC_IRQ_CHIP
 

Why is this super-simple pin config thing not using GENERIC_PINCONF?

Quoted 3 lines

I *know* it is simpler to implement your own thing, but think of the poor maintainers that have to wade through 50 identical implementations. Do this, it pays off.

generic pinconf sounds interesting ... will give it a try.

The only problem is the pull stuff mentioned above that is either pull up or down without the driver having knowledge about it. And generic_pinconf only knows about them separately right now.

Quoted 5 lines

BTW: it leads to wanting to use generic pinconf DT bindings as experienced by Laurent and others. We need to fix that too...

(...)

Quoted 9 lines

Review

Quoted 6 lines

+++ b/drivers/pinctrl/pinctrl-rockchip.c

(quoted diff) +2 -0
+static void rockchip_pin_dbg_show(struct pinctrl_dev *pctldev,
+                                       struct seq_file *s, unsigned

offset) +{

(quoted diff) +2 -0
+       seq_printf(s, "%s", dev_name(pctldev->dev));
+}

Nothing else you want to say about the pins here?
(No big deal for sure, but....)

when using pinconfig_generic, its dump_pin function should be more talkative right?

Quoted 9 lines

drivers/pinctrl/pinctrl-rockchip.c line 385

Quoted 6 lines
drivers/pinctrl/pinctrl-rockchip.c new file +6 -0
+
+               data = readl_relaxed(reg);
+               data >>= bit;
+               data &= 1;
+
+               return !data;

That's a bit hard to read, I'd just:

Quoted 7 lines

#include <linux/bitops.h>
return !(readl_relaxed(reg) & BIT(bit));

And skip the "data" variable. The ! operator will
clamp this to a bool (0/1).

But we all have our habits.

yeah, but sometimes it's also good to try to break them ... your solution is much nicer to read (and shorter).

Quoted 1 line

All I could think of right now...

Thanks for the review
Heiko

#22 lore raw

Re: [PATCH 07/10] pinctrl: add pinctrl driver for Rockchip SoCs

Quoted 16 lines · Heiko St?bner
Quoted 4 lines

Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt line 53

Quoted 2 lines
Documentation/devicetree/bindings/pinctrl/rockchip-pinctrl.txt new file +2 -0
+PULL_AUTO      (1 << 0): indicate this pin needs a pull setting for SoCs
+                         that determine the pull up or down themselfs

Hm, never saw that before...

Citing the original gpio driver:

/*
* Values written to this register independently
* control Pullup/Pulldown or not for the
* corresponding data bit in GPIO.
* 0: pull up/down enable, PAD type will decide
* to be up or down, not related with this value
* 1: pull up/down disable
*/

Quoted 6 lines

So if it's a pull up or down is decided based on the mux of the pin. Calling everything a "pull down" (or up) when it isn't seemed somehow wrong to me.

The rk3188 on the other hand supports both pull up and down separately.

Or should this be selected as PULL_UP | PULL_DOWN in the config?

The generic config is pretty much either/or so it'd be a new config for that approach.

Basically it seems they have embedded knowledge into the
silicon: there is no specific rule as to whether a pad should be pulled up or down depending on "pad type" as is stated, rather it's so that if you know a pad will be used for I2C SCL then you know it needs pull-up. Probably something like a "1" on some constant switch in VHDL/Verilog is hard-coded into the silicon turning on pull-up if I2C is selected and the autopull is set for example.

Quoted 13 lines
Quoted 6 lines
drivers/pinctrl/Kconfig +5 -0
+config PINCTRL_ROCKCHIP
+       bool
+       select PINMUX
+       select PINCONF
+       select GENERIC_IRQ_CHIP
Quoted 6 lines

Why is this super-simple pin config thing not using GENERIC_PINCONF?

I *know* it is simpler to implement your own thing, but think of the poor maintainers that have to wade through 50 identical implementations. Do this, it pays off.

Quoted 5 lines

generic pinconf sounds interesting ... will give it a try.

The only problem is the pull stuff mentioned above that is either pull up or down without the driver having knowledge about it. And generic_pinconf only knows about them separately right now.

Create a separate patch adding PIN_CONFIG_BIAS_PULL_AUTO to include/linux/pinctrl/pinconf-generic.h, don't forget the kerneldoc, and patching drivers/pinctrl/pinconf-generic.c.

I'll apply it right away.

Quoted 5 lines
Quoted 2 lines

Nothing else you want to say about the pins here?
(No big deal for sure, but....)

when using pinconfig_generic, its dump_pin function should be more talkative right?

Yes, one of the things you get for free... soon also the pin config DT parser will be for free I hope.

Yours,
Linus Walleij

#23 lore raw

Re: [PATCH 07/10] pinctrl: add pinctrl driver for Rockchip SoCs

Quoted 1 line · Linus Walleij

On Tue, Jun 4, 2013 at 2:05 PM, Heiko St?bner <[email protected]> wrote:

...

Quoted 7 lines
Quoted 3 lines

The only problem is the pull stuff mentioned above that is either pull up or down without the driver having knowledge about it. And generic_pinconf only knows about them separately right now.

Create a separate patch adding PIN_CONFIG_BIAS_PULL_AUTO to include/linux/pinctrl/pinconf-generic.h, don't forget the kerneldoc, and patching drivers/pinctrl/pinconf-generic.c.

"AUTO" sounds really rather generic. Based on just the word "AUTO", I have no idea if it's a HW- or SW-supplied default, or what the algorithm is for determining the automatically selected value. Perhaps s/AUTO/PIN_DEFAULT/ or something like that?

While the concept is simple enough, it's unusual enough that such a patch would hopefully have a comment containing a full explanation of exactly what this option means.

author maintainer
#24 lore raw

Re: [PATCH 07/10] pinctrl: add pinctrl driver for Rockchip SoCs

Am Mittwoch, 5. Juni 2013, 19:18:49 schrieb Stephen Warren:

Quoted 8 lines · Linus Walleij
Quoted 1 line · Heiko St?bner

...

Quoted 4 lines
Quoted 3 lines

The only problem is the pull stuff mentioned above that is either pull up or down without the driver having knowledge about it. And generic_pinconf only knows about them separately right now.

Quoted 8 lines
Quoted 3 lines

Create a separate patch adding PIN_CONFIG_BIAS_PULL_AUTO to include/linux/pinctrl/pinconf-generic.h, don't forget the kerneldoc, and patching drivers/pinctrl/pinconf-generic.c.

"AUTO" sounds really rather generic. Based on just the word "AUTO", I have no idea if it's a HW- or SW-supplied default, or what the algorithm is for determining the automatically selected value. Perhaps s/AUTO/PIN_DEFAULT/ or something like that?

I would also go with PIN_DEFAULT, which somehow captures what the function does better than "AUTO". So, if no-one objects I'll go with Stephen's suggestion.

Quoted 3 lines

While the concept is simple enough, it's unusual enough that such a patch would hopefully have a comment containing a full explanation of exactly what this option means.

of course :-)

author maintainer
#25 lore raw

PATCH 8/10 clk: add basic Rockchip rk3066a clock support

In reply to Heiko Stübner

This adds basic support for clocks on Rockchip rk3066 SoCs. The clock handling thru small dt nodes is heavily inspired by the sunxi clk code.

The clock specifiers are named as "x-cortex-a9-x", because the clock semantics are the same thru the whole cortex-a9 series (rk30xx, rk3188, rk2928; but not the other rk29 SoCs, which are Cortex-A8 based).

The plls are currently read-only, as their setting needs more investigation. This also results in slow cpu speeds.

---
 arch/arm/boot/dts/rk3066a-clocks.dtsi   |  459 +++++++++++++++++++++++++++++++
 drivers/clk/Makefile                    |    1 +
 drivers/clk/rockchip/Makefile           |    6 +
 drivers/clk/rockchip/clk-rockchip-pll.c |  131 +++++++++
 drivers/clk/rockchip/clk-rockchip-pll.h |   19 ++
 drivers/clk/rockchip/clk-rockchip.c     |  315 +++++++++++++++++++++
 include/linux/clk/rockchip.h            |   21 ++
 7 files changed, 952 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/rk3066a-clocks.dtsi
 create mode 100644 drivers/clk/rockchip/Makefile
 create mode 100644 drivers/clk/rockchip/clk-rockchip-pll.c
 create mode 100644 drivers/clk/rockchip/clk-rockchip-pll.h
 create mode 100644 drivers/clk/rockchip/clk-rockchip.c
 create mode 100644 include/linux/clk/rockchip.h
arch/arm/boot/dts/rk3066a-clocks.dtsi new file +459 -0
new file mode 100644
index 0000000..5e0614a
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/*
+		 * This is a dummy clock, to be used as placeholder on
+		 * other mux clocks when a specific parent clock is not
+		 * yet implemented. It should be dropped when the driver
+		 * is complete.
+		 */
+		dummy: dummy {
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+			#clock-cells = <0>;
+		};
+
+		xin24m: xin24m {
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+			#clock-cells = <0>;
+		};
+
+		apll: apll at 20000000 {
+			compatible = "rockchip,rk3066a-apll";
+			reg = <0x20000000 0x10>,
+			      <0x20000040 0x04>;
+			clocks = <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		dpll: dpll at 20000000 {
+			compatible = "rockchip,rk3066a-dpll";
+			reg = <0x20000010 0x10>,
+			      <0x20000040 0x04>;
+			clocks = <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		cpll: cpll at 20000000 {
+			compatible = "rockchip,rk3066a-cpll";
+			reg = <0x20000020 0x10>,
+			      <0x20000040 0x04>;
+			clocks = <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		gpll: gpll at 20000000 {
+			compatible = "rockchip,rk3066a-gpll";
+			reg = <0x20000030 0x10>,
+			      <0x20000040 0x04>;
+			clocks = <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		mux_aclk_periph: mux-aclk-periph at 2000006c {
+			compatible = "rockchip,cortex-a9-gpll-cpll-bit15-mux";
+			reg = <0x2000006c 0x04>;
+			clocks = <&gpll>, <&cpll>;
+			#clock-cells = <0>;
+		};
+
+		mux_uart_pll: mux-uart_pll at 20000074 {
+			compatible = "rockchip,cortex-a9-gpll-cpll-bit15-mux";
+			reg = <0x20000074 0x04>;
+			clocks = <&gpll>, <&cpll>;
+			#clock-cells = <0>;
+		};
+
+		div_uart0: div-uart0 at 20000078 {
+			compatible = "rockchip,cortex-a9-uart-divider";
+			reg = <0x20000078 0x04>;
+			clocks = <&mux_uart_pll>;
+			#clock-cells = <0>;
+		};
+
+		mux_uart0: mux-uart0 at 20000078 {
+			compatible = "rockchip,cortex-a9-uart-mux";
+			reg = <0x20000078 0x04>;
+			clocks = <&clk_gates1 8>, <&dummy>, <&xin24m>; /* dummy is uart0_frac_div */
+			#clock-cells = <0>;
+		};
+
+		div_uart1: div-uart1 at 2000007c {
+			compatible = "rockchip,cortex-a9-uart-divider";
+			reg = <0x2000007c 0x04>;
+			clocks = <&mux_uart_pll>;
+			#clock-cells = <0>;
+		};
+
+		mux_uart1: mux-uart1 at 2000007c {
+			compatible = "rockchip,cortex-a9-uart-mux";
+			reg = <0x2000007c 0x04>;
+			clocks = <&clk_gates1 10>, <&dummy>, <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		div_uart2: div-uart2 at 20000080 {
+			compatible = "rockchip,cortex-a9-uart-divider";
+			reg = <0x20000080 0x04>;
+			clocks = <&mux_uart_pll>;
+			#clock-cells = <0>;
+		};
+
+		mux_uart2: mux-uart2 at 20000080 {
+			compatible = "rockchip,cortex-a9-uart-mux";
+			reg = <0x20000080 0x04>;
+			clocks = <&clk_gates1 12>, <&dummy>, <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		div_uart3: div-uart3 at 20000084 {
+			compatible = "rockchip,cortex-a9-uart-divider";
+			reg = <0x20000084 0x04>;
+			clocks = <&mux_uart_pll>;
+			#clock-cells = <0>;
+		};
+
+		mux_uart3: mux-uart3 at 20000084 {
+			compatible = "rockchip,cortex-a9-uart-mux";
+			reg = <0x20000084 0x04>;
+			clocks = <&clk_gates1 14>, <&dummy>, <&xin24m>;
+			#clock-cells = <0>;
+		};
+
+		mux_cpu: mux-cpu at 20000044 {
+			compatible = "rockchip,cortex-a9-cpu-mux";
+			reg = <0x20000044 0x4>;
+			clocks = <&apll>, <&dummy> /* cpu_gpll_path */;
+			#clock-cells = <0>;
+		};
+
+		div_cpu: div-cpu at 20000044 {
+			compatible = "rockchip,cortex-a9-cpu-divider";
+			reg = <0x20000044 0x4>;
+			clocks = <&mux_cpu>;
+			#clock-cells = <0>;
+		};
+
+		div_aclk_cpu: div-aclk-cpu at 20000048 {
+			compatible = "rockchip,cortex-a9-aclk-cpu-divider";
+			reg = <0x20000048 0x4>;
+			clocks = <&div_cpu>;
+			#clock-cells = <0>;
+		};
+
+		div_aclk_periph: div-aclk-periph at 2000006c {
+			compatible = "rockchip,cortex-a9-hclk-divider";
+			reg = <0x2000006c 0x4>;
+			clocks = <&mux_aclk_periph>;
+			#clock-cells = <0>;
+		};
+
+		div_hclk_periph: div-hclk-periph at 2000006c {
+			compatible = "rockchip,cortex-a9-hclk-divider";
+			reg = <0x2000006c 0x4>;
+			clocks = <&clk_gates2 1>;
+			#clock-cells = <0>;
+		};
+
+		div_pclk_periph: div-pclk-periph at 2000006c {
+			compatible = "rockchip,cortex-a9-pclk-divider";
+			reg = <0x2000006c 0x4>;
+			clocks = <&clk_gates2 1>;
+			#clock-cells = <0>;
+		};
+
+		div_hclk_cpu: div-hclk-cpu at 20000048 {
+			compatible = "rockchip,cortex-a9-hclk-divider";
+			reg = <0x20000048 0x4>;
+			clocks = <&clk_gates0 3>;
+			#clock-cells = <0>;
+		};
+
+		div_pclk_cpu: div-pclk-cpu at 20000048 {
+			compatible = "rockchip,cortex-a9-pclk-divider";
+			reg = <0x20000048 0x4>;
+			clocks = <&clk_gates0 3>;
+			#clock-cells = <0>;
+		};
+
+		div_mmc0: div-mmc0 at 20000070 {
+			compatible = "rockchip,cortex-a9-mmc-divider";
+			reg = <0x20000070 0x4>;
+			clocks = <&clk_gates2 2>;
+			#clock-cells = <0>;
+		};
+
+		div_mmc1: div-mmc1 at 20000074 {
+			compatible = "rockchip,cortex-a9-mmc-divider";
+			reg = <0x20000074 0x4>;
+			clocks = <&clk_gates2 2>;
+			#clock-cells = <0>;
+		};
+
+		clk_gates0: gate-clk at 200000d0 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000d0 0x4>;
+			clocks = <&dummy>, <&dummy>,
+				 <&dummy>, <&div_aclk_cpu>,
+				 <&div_hclk_cpu>, <&div_pclk_cpu>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_core_periph", "gate_cpu_gpll",
+				"gate_ddrphy", "gate_aclk_cpu",
+				"gate_hclk_cpu", "gate_pclk_cpu",
+				"gate_atclk_cpu", "gate_i2s0",
+				"gate_i2s0_frac", "gate_i2s1",
+				"gate_i2s1_frac", "gate_i2s2",
+				"gate_i2s2_frac", "gate_spdif",
+				"gate_spdif_frac", "gate_testclk";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates1: gate-clk at 200000d4 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000d4 0x4>;
+			clocks = <&xin24m>, <&xin24m>,
+				 <&xin24m>, <&dummy>,
+				 <&dummy>, <&xin24m>,
+				 <&xin24m>, <&dummy>,
+				 <&div_uart0>, <&dummy>,
+				 <&div_uart1>, <&dummy>,
+				 <&div_uart2>, <&dummy>,
+				 <&div_uart3>, <&dummy>;
+
+			clock-output-names =
+				"gate_timer0", "gate_timer1",
+				"gate_timer2", "gate_jtag",
+				"gate_aclk_lcdc1_src", "gate_otgphy0",
+				"gate_otgphy1", "gate_ddr_gpll",
+				"gate_uart0", "gate_frac_uart0",
+				"gate_uart1", "gate_frac_uart1",
+				"gate_uart2", "gate_frac_uart2",
+				"gate_uart3", "gate_frac_uart3";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates2: gate-clk at 200000d8 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000d8 0x4>;
+			clocks = <&clk_gates2 1>, <&div_aclk_periph>,
+				 <&div_hclk_periph>, <&div_pclk_periph>,
+				 <&dummy>, <&dummy>,
+				 <&clk_gates2 3>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&div_mmc0>,
+				 <&dummy>, <&div_mmc1>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_periph_src", "gate_aclk_periph",
+				"gate_hclk_periph", "gate_pclk_periph",
+				"gate_smc", "gate_mac",
+				"gate_hsadc", "gate_hsadc_frac",
+				"gate_saradc", "gate_spi0",
+				"gate_spi1", "gate_mmc0",
+				"gate_mac_lbtest", "gate_mmc1",
+				"gate_emmc", "gate_tsadc";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates3: gate-clk at 200000dc {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000dc 0x4>;
+			clocks = <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
+				"gate_dclk_lcdc1", "gate_pclkin_cif0",
+				"gate_pclkin_cif1", "reserved",
+				"reserved", "gate_cif0_out",
+				"gate_cif1_out", "gate_aclk_vepu",
+				"gate_hclk_vepu", "gate_aclk_vdpu",
+				"gate_hclk_vdpu", "gate_gpu_src",
+				"reserved", "gate_xin27m";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates4: gate-clk at 200000e0 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000e0 0x4>;
+			clocks = <&clk_gates2 2>, <&clk_gates2 3>,
+				 <&clk_gates2 1>, <&clk_gates2 1>,
+				 <&clk_gates2 1>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates2 2>,
+				 <&clk_gates0 4>, <&clk_gates0 4>,
+				 <&clk_gates0 3>, <&clk_gates0 3>,
+				 <&clk_gates0 3>, <&clk_gates2 3>,
+				 <&clk_gates0 4>;
+
+			clock-output-names =
+				"gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
+				"gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
+				"gate_aclk_pei_niu", "gate_hclk_usb_peri",
+				"gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
+				"gate_hclk_cpubus", "gate_hclk_ahb2apb",
+				"gate_aclk_strc_sys", "gate_aclk_l2mem_con",
+				"gate_aclk_intmem", "gate_pclk_tsadc",
+				"gate_hclk_hdmi";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates5: gate-clk at 200000e4 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000e4 0x4>;
+			clocks = <&clk_gates0 3>, <&clk_gates2 1>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates0 4>, <&clk_gates0 5>,
+				 <&clk_gates2 1>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates4 5>,
+				 <&clk_gates4 5>, <&dummy>;
+
+			clock-output-names =
+				"gate_aclk_dmac1", "gate_aclk_dmac2",
+				"gate_pclk_efuse", "gate_pclk_tzpc",
+				"gate_pclk_grf", "gate_pclk_pmu",
+				"gate_hclk_rom", "gate_pclk_ddrupctl",
+				"gate_aclk_smc", "gate_hclk_nandc",
+				"gate_hclk_mmc0", "gate_hclk_mmc1",
+				"gate_hclk_emmc", "gate_hclk_otg0",
+				"gate_hclk_otg1", "gate_aclk_gpu";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates6: gate-clk at 200000e8 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000e8 0x4>;
+			clocks = <&clk_gates3 0>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates1 4>,
+				 <&clk_gates0 4>, <&clk_gates3 0>,
+				 <&clk_gates0 4>, <&clk_gates1 4>,
+				 <&clk_gates3 0>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates1 4>,
+				 <&clk_gates0 4>, <&clk_gates3 0>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_aclk_lcdc0", "gate_hclk_lcdc0",
+				"gate_hclk_lcdc1", "gate_aclk_lcdc1",
+				"gate_hclk_cif0", "gate_aclk_cif0",
+				"gate_hclk_cif1", "gate_aclk_cif1",
+				"gate_aclk_ipp", "gate_hclk_ipp",
+				"gate_hclk_rga", "gate_aclk_rga",
+				"gate_hclk_vio_bus", "gate_aclk_vio0",
+				"gate_aclk_vcodec", "gate_shclk_vio_h2h";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates7: gate-clk at 200000ec {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000ec 0x4>;
+			clocks = <&clk_gates2 2>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates2 3>;
+
+			clock-output-names =
+				"gate_hclk_emac", "gate_hclk_spdif",
+				"gate_hclk_i2s0_2ch", "gate_hclk_i2s1_2ch",
+				"gate_hclk_i2s_8ch", "gate_hclk_hsadc",
+				"gate_hclk_pidf", "gate_pclk_timer0",
+				"gate_pclk_timer1", "gate_pclk_timer2",
+				"gate_pclk_pwm01", "gate_pclk_pwm23",
+				"gate_pclk_spi0", "gate_pclk_spi1",
+				"gate_pclk_saradc", "gate_pclk_wdt";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates8: gate-clk at 200000f0 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000f0 0x4>;
+			clocks = <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&dummy>, <&clk_gates0 5>;
+
+			clock-output-names =
+				"gate_pclk_uart0", "gate_pclk_uart1",
+				"gate_pclk_uart2", "gate_pclk_uart3",
+				"gate_pclk_i2c0", "gate_pclk_i2c1",
+				"gate_pclk_i2c2", "gate_pclk_i2c3",
+				"gate_pclk_i2c4", "gate_pclk_gpio0",
+				"gate_pclk_gpio1", "gate_pclk_gpio2",
+				"gate_pclk_gpio3", "gate_pclk_gpio4",
+				"reserved", "gate_pclk_gpio6";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates9: gate-clk at 200000f4 {
+			compatible = "rockchip,cortex-a9-gates-clk";
+			reg = <0x200000f4 0x4>;
+			clocks = <&dummy>, <&clk_gates0 5>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&clk_gates1 4>,
+				 <&clk_gates0 5>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>;
+
+			clock-output-names =
+				"gate_clk_core_dbg", "gate_pclk_dbg",
+				"gate_clk_trace", "gate_atclk",
+				"gate_clk_l2c", "gate_aclk_vio1",
+				"gate_pclk_publ", "gate_aclk_intmem0",
+				"gate_aclk_intmem1", "gate_aclk_intmem2",
+				"gate_aclk_intmem3";
+
+			#clock-cells = <1>;
+		};
+	};
+
+};
drivers/clk/Makefile +1 -0
index 3a26115..4063afc 100644
@@ -24,6 +24,7 @@ ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)		+= mmp/
 endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
+obj-$(CONFIG_ARCH_ROCKCHIP)	+= rockchip/
 obj-$(CONFIG_ARCH_SUNXI)	+= sunxi/
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
drivers/clk/rockchip/Makefile new file +6 -0
new file mode 100644
index 0000000..e0fbafb
@@ -0,0 +1,6 @@
+#
+# Rockchip Clock specific Makefile
+#
+
+obj-y	+= clk-rockchip.o
+obj-y	+= clk-rockchip-pll.o
drivers/clk/rockchip/clk-rockchip-pll.c new file +131 -0

131 lines not on this page · raw message

drivers/clk/rockchip/clk-rockchip-pll.h new file +19 -0
new file mode 100644
index 0000000..a63288a
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+extern struct clk * __init rockchip_clk_register_rk3x_pll(const char *name,
+			const char *pname, const void __iomem *reg_base,
+			const void __iomem *reg_mode, unsigned int shift_mode,
+			spinlock_t *lock);
drivers/clk/rockchip/clk-rockchip.c new file +315 -0

315 lines not on this page · raw message

include/linux/clk/rockchip.h new file +21 -0
new file mode 100644
index 0000000..571721f
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_CLK_ROCKCHIP_H_
+#define __LINUX_CLK_ROCKCHIP_H_
+
+void __init rockchip_init_clocks(void);
+
+#endif
Signature · 1 line
1.7.2.3
#26 lore raw

Re: [PATCH 08/10] clk: add basic Rockchip rk3066a clock support

Quoted 7 lines · Heiko St?bner

This adds basic support for clocks on Rockchip rk3066 SoCs. The clock handling thru small dt nodes is heavily inspired by the sunxi clk code.

The clock specifiers are named as "x-cortex-a9-x", because the clock semantics are the same thru the whole cortex-a9 series (rk30xx, rk3188, rk2928; but not the other rk29 SoCs, which are Cortex-A8 based).

Hi,

I think you're better off naming them after the first SoC of that series. Otherwise, if there's an A9-based platform in the future that is not compatible, things will get complicated.

It's pretty common that we do this for other kinds of devices, so it seems appropriate for clock drivers too.

-Olof

author maintainer
#27 lore raw

Re: [PATCH 08/10] clk: add basic Rockchip rk3066a clock support

Am Montag, 3. Juni 2013, 05:27:11 schrieb Olof Johansson:

Quoted 9 lines · Heiko St?bner
Quoted 7 lines

This adds basic support for clocks on Rockchip rk3066 SoCs. The clock handling thru small dt nodes is heavily inspired by the sunxi clk code.

The clock specifiers are named as "x-cortex-a9-x", because the clock semantics are the same thru the whole cortex-a9 series (rk30xx, rk3188, rk2928; but not the other rk29 SoCs, which are Cortex-A8 based).

Quoted 8 lines

Hi,

I think you're better off naming them after the first SoC of that series. Otherwise, if there's an A9-based platform in the future that is not compatible, things will get complicated.

It's pretty common that we do this for other kinds of devices, so it seems appropriate for clock drivers too.

ok, I'll rename them

author maintainer
#28 lore raw

PATCH 9/10 arm: add debug uarts for rockchip rk29xx and rk3xxx series

In reply to Heiko Stübner

Uarts on all recent Rockchip SoCs are Synopsis DesignWare 8250 types. Only their addresses vary very much.

This patch adds the necessary definitions to use any of the uart ports for early debug purposes.

---
 arch/arm/Kconfig.debug            |   34 +++++++++++++++++++++++++++++
 arch/arm/include/debug/rockchip.S |   42 +++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/debug/rockchip.S
arch/arm/Kconfig.debug +34 -0
index 29f7623..2060cd5 100644
@@ -360,6 +360,13 @@ choice
 		  their output to the standard serial port on the RealView
 		  PB1176 platform.
 
+	config DEBUG_ROCKCHIP_UART
+		bool "Kernel low-level debugging messages via Rockchip UART"
+		depends on ARCH_ROCKCHIP
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Rockchip based platforms.
+
 	config DEBUG_S3C_UART0
 		depends on PLAT_SAMSUNG
 		select DEBUG_EXYNOS_UART if ARCH_EXYNOS
@@ -597,6 +604,32 @@ endchoice
 
 choice
 	prompt "Low-level debug console UART"
+	depends on DEBUG_ROCKCHIP_UART
+
+	config DEBUG_RK29_UART0
+		bool "RK29 UART0"
+
+	config DEBUG_RK29_UART1
+		bool "RK29 UART1"
+
+	config DEBUG_RK29_UART2
+		bool "RK29 UART2"
+
+	config DEBUG_RK3X_UART0
+		bool "RK3X UART0"
+
+	config DEBUG_RK3X_UART1
+		bool "RK3X UART1"
+
+	config DEBUG_RK3X_UART2
+		bool "RK3X UART2"
+
+	config DEBUG_RK3X_UART3
+		bool "RK3X UART3"
+endchoice
+
+choice
+	prompt "Low-level debug console UART"
 	depends on DEBUG_LL && DEBUG_TEGRA_UART
 
 	config TEGRA_DEBUG_UART_AUTO_ODMDATA
@@ -648,6 +681,7 @@ config DEBUG_LL_INCLUDE
 	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
 	default "debug/pxa.S" if DEBUG_PXA_UART1 || DEBUG_MMP_UART2 || \
 				 DEBUG_MMP_UART3
+	default "debug/rockchip.S" if DEBUG_ROCKCHIP_UART
 	default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
 	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
 	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
arch/arm/include/debug/rockchip.S new file +42 -0

42 lines not on this page · raw message

Signature · 1 line
1.7.2.3
#29 lore raw

Re: [PATCH 09/10] arm: add debug uarts for rockchip rk29xx and rk3xxx series

arch/arm/include/debug/rockchip.S line 15

Quoted 3 lines · On Monday 03 June 2013 01:01:03 Heiko St?bner wrote:
arch/arm/include/debug/rockchip.S new file +3 -0
+#if defined(CONFIG_DEBUG_RK29_UART0)
+#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20060000
+#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfe060000

0xfed60000 maybe? looks like a typo.

Arnd

author maintainer
#30 lore raw

Re: [PATCH 09/10] arm: add debug uarts for rockchip rk29xx and rk3xxx series

Am Montag, 3. Juni 2013, 04:08:37 schrieb Arnd Bergmann:

Quoted 6 lines · On Monday 03 June 2013 01:01:03 Heiko St?bner wrote:

arch/arm/include/debug/rockchip.S line 15

Quoted 3 lines
arch/arm/include/debug/rockchip.S new file +3 -0
+#if defined(CONFIG_DEBUG_RK29_UART0)
+#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20060000
+#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfe060000

0xfed60000 maybe? looks like a typo.

ha, correct ... thanks

author maintainer
#31 lore raw

PATCH 10/10 arm: add basic support for Rockchip RK3066a boards

In reply to Heiko Stübner

This adds a generic devicetree board file and a dtsi for boards based on the RK3066a SoCs from Rockchip.

Apart from the generic parts (gic, clocks, pinctrl) the only components currently supported are the timers, uarts and mmc ports (all DesignWare- based).

---
 arch/arm/Kconfig                     |    2 +
 arch/arm/Makefile                    |    1 +
 arch/arm/boot/dts/rk3066a.dtsi       |  359 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/Kconfig       |   17 ++
 arch/arm/mach-rockchip/Makefile      |    1 +
 arch/arm/mach-rockchip/Makefile.boot |    3 +
 arch/arm/mach-rockchip/rockchip.c    |   54 +++++
 7 files changed, 437 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/rk3066a.dtsi
 create mode 100644 arch/arm/mach-rockchip/Kconfig
 create mode 100644 arch/arm/mach-rockchip/Makefile
 create mode 100644 arch/arm/mach-rockchip/Makefile.boot
 create mode 100644 arch/arm/mach-rockchip/rockchip.c
arch/arm/Kconfig +2 -0
index ff580d3..ff892b1 100644
@@ -983,6 +983,8 @@ source "arch/arm/mach-mmp/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
 
+source "arch/arm/mach-rockchip/Kconfig"
+
 source "arch/arm/mach-sa1100/Kconfig"
 
 source "arch/arm/plat-samsung/Kconfig"
arch/arm/Makefile +1 -0
index 3380c4f..0153f60 100644
@@ -172,6 +172,7 @@ machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
 machine-$(CONFIG_ARCH_PRIMA2)		+= prima2
 machine-$(CONFIG_ARCH_PXA)		+= pxa
 machine-$(CONFIG_ARCH_REALVIEW)		+= realview
+machine-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip
 machine-$(CONFIG_ARCH_RPC)		+= rpc
 machine-$(CONFIG_ARCH_S3C24XX)		+= s3c24xx
 machine-$(CONFIG_ARCH_S3C64XX)		+= s3c64xx
arch/arm/boot/dts/rk3066a.dtsi new file +359 -0

359 lines not on this page · raw message

arch/arm/mach-rockchip/Kconfig new file +17 -0
new file mode 100644
index 0000000..7e332ea
@@ -0,0 +1,17 @@
+config ARCH_ROCKCHIP
+	bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7
+	select PINCTRL
+	select PINCTRL_ROCKCHIP
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_GIC
+	select CACHE_L2X0
+	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_SMP
+	select LOCAL_TIMERS if SMP
+	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
+	select DW_APB_TIMER
+	select DW_APB_TIMER_OF
+	help
+	  Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
+	  containing the RK2928, RK30xx and RK31xx series.
arch/arm/mach-rockchip/Makefile new file +1 -0
new file mode 100644
index 0000000..880b287
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
\ No newline at end of file
arch/arm/mach-rockchip/Makefile.boot new file +3 -0
new file mode 100644
index 0000000..a2d8c70
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60408000
+params_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60088000
+initrd_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60800000
arch/arm/mach-rockchip/rockchip.c new file +54 -0

54 lines not on this page · raw message

Signature · 1 line
1.7.2.3
#32 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

arch/arm/mach-rockchip/rockchip.c

Quoted 3 lines · On Monday 03 June 2013 01:02:20 Heiko Stübner wrote:

index 0000000..094b37d

arch/arm/mach-rockchip/rockchip.c new file +0 -0

If all goes well, this file can be removed again in 3.11 since it's all generic, but let's add it for now.

arch/arm/mach-rockchip/rockchip.c line 32

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+
+static void __init rockchip_timer_init(void)
+{
+       rockchip_init_clocks();
+       dw_apb_timer_init();
+}

Can't you use

	of_clk_init(NULL);
	clocksource_of_init();

here and change the two drivers to provide the respective macros?

arch/arm/mach-rockchip/rockchip.c line 40

Quoted 8 lines
arch/arm/mach-rockchip/rockchip.c new file +8 -0
+
+static void __init rockchip_dt_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+       l2x0_of_init(0, ~0UL);
+#endif
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}

We still need to find a common location to call l2x0_of_init.

arch/arm/mach-rockchip/rockchip.c line 47

Quoted 7 lines
arch/arm/mach-rockchip/rockchip.c new file +7 -0
+
+static const char * const rockchip_board_dt_compat[] = {
+       "rockchip,rk2928", /* single core */
+       "rockchip,rk30xx", /* dual cores */
+       "rockchip,rk31xx", /* dual and quad cores */
+       NULL,
+};

Please use real numbers instead of wildcards: rockchip,rk3066 not rockchip,rk30xx.

arch/arm/mach-rockchip/rockchip.c line 54

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+       .map_io         = debug_ll_io_init,
+       .init_machine   = rockchip_dt_init,
+       .init_time      = rockchip_timer_init,
+       .dt_compat      = rockchip_board_dt_compat,
+MACHINE_END

The map_io line can already get removed.

What about SMP support? Still working on it?

Arnd

author maintainer
#33 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

Am Montag, 3. Juni 2013, 04:15:46 schrieb Arnd Bergmann:

Quoted 17 lines · On Monday 03 June 2013 01:02:20 Heiko St?bner wrote:

arch/arm/mach-rockchip/rockchip.c

Quoted 3 lines

index 0000000..094b37d

arch/arm/mach-rockchip/rockchip.c new file +0 -0

If all goes well, this file can be removed again in 3.11 since it's all generic, but let's add it for now.

arch/arm/mach-rockchip/rockchip.c line 32

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+
+static void __init rockchip_timer_init(void)
+{
+       rockchip_init_clocks();
+       dw_apb_timer_init();
+}

Can't you use

Quoted 4 lines
	of_clk_init(NULL);
	clocksource_of_init();

here and change the two drivers to provide the respective macros?

hmm, while this would make a lot of things easier I don't see right now how this would work.

The dw_apb_timer clocksource does not have its own device node, but instead uses two timer devices as clocksource and clockevent.

Hmm ... one idea would be to wrap them in the dt, like

	clocksource {
		compatible = "snps,dw-apb-clocksource"

		timer at 2003a000 {
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2003a000 0x100>;
			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 1>, <&clk_gates7 8>;
			clock-names = "timer", "pclk";
		};

		timer at 2000e000 {
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2000e000 0x100>;
			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 2>, <&clk_gates7 9>;
			clock-names = "timer", "pclk";
		};
	};
Quoted 11 lines
Quoted 8 lines
arch/arm/mach-rockchip/rockchip.c new file +7 -0
+
+static void __init rockchip_dt_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+       l2x0_of_init(0, ~0UL);
+#endif
+       of_platform_populate(NULL, of_default_bus_match_table, NULL,

NULL); +}

We still need to find a common location to call l2x0_of_init.

Quoted 10 lines

arch/arm/mach-rockchip/rockchip.c line 47

Quoted 7 lines
arch/arm/mach-rockchip/rockchip.c new file +7 -0
+
+static const char * const rockchip_board_dt_compat[] = {
+       "rockchip,rk2928", /* single core */
+       "rockchip,rk30xx", /* dual cores */
+       "rockchip,rk31xx", /* dual and quad cores */
+       NULL,
+};

Please use real numbers instead of wildcards: rockchip,rk3066 not rockchip,rk30xx.

ok

Quoted 8 lines

arch/arm/mach-rockchip/rockchip.c line 54

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+       .map_io         = debug_ll_io_init,
+       .init_machine   = rockchip_dt_init,
+       .init_time      = rockchip_timer_init,
+       .dt_compat      = rockchip_board_dt_compat,
+MACHINE_END

The map_io line can already get removed.

Yesterday I did grep thru the linux-next I was using as base looking for the debug_ll_io_init default I read about but was not able to find it ... most likely my linux-next is a tad to old.

Quoted 1 line

What about SMP support? Still working on it?

I haven't even looked into it yet ;-) . But this is one of the next items on my wishlist ... which also contains making the SoC run at more than 600MHz (due to the currently read-only pll which starts at this value and needs to be set)

Reading the "upstream" kernel code to get the necessary informations does not make this easier ;-)

Heiko

#34 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

Quoted 28 lines · On Monday 03 June 2013 10:23:49 Heiko St?bner wrote:

Am Montag, 3. Juni 2013, 04:15:46 schrieb Arnd Bergmann:

Quoted 7 lines

Can't you use

	of_clk_init(NULL);
	clocksource_of_init();

here and change the two drivers to provide the respective macros?

hmm, while this would make a lot of things easier I don't see right now how this would work.

The dw_apb_timer clocksource does not have its own device node, but instead uses two timer devices as clocksource and clockevent.

Hmm ... one idea would be to wrap them in the dt, like

	clocksource {
		compatible = "snps,dw-apb-clocksource"

		timer at 2003a000 {
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2003a000 0x100>;
			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 1>, <&clk_gates7 8>;
			clock-names = "timer", "pclk";
		};
Quoted 8 lines
		timer at 2000e000 {
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2000e000 0x100>;
			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 2>, <&clk_gates7 9>;
			clock-names = "timer", "pclk";
		};
	};

Can't you just have multiple CLOCKSOURCE_OF_DECLARE() lines, one for each of the nodes?

Quoted 9 lines
Quoted 8 lines

arch/arm/mach-rockchip/rockchip.c line 54

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+       .map_io         = debug_ll_io_init,
+       .init_machine   = rockchip_dt_init,
+       .init_time      = rockchip_timer_init,
+       .dt_compat      = rockchip_board_dt_compat,
+MACHINE_END

The map_io line can already get removed.

Quoted 3 lines

Yesterday I did grep thru the linux-next I was using as base looking for the debug_ll_io_init default I read about but was not able to find it ... most likely my linux-next is a tad to old.

Yes, it only showed up in today's linux-next. I thought it was older.

Arnd

author maintainer
#35 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

Am Montag, 3. Juni 2013, 11:22:35 schrieb Arnd Bergmann:

Quoted 39 lines · On Monday 03 June 2013 10:23:49 Heiko St?bner wrote:
Quoted 38 lines

Am Montag, 3. Juni 2013, 04:15:46 schrieb Arnd Bergmann:

Quoted 6 lines

Can't you use

	of_clk_init(NULL);
	clocksource_of_init();

here and change the two drivers to provide the respective macros?

hmm, while this would make a lot of things easier I don't see right now how this would work.

The dw_apb_timer clocksource does not have its own device node, but instead uses two timer devices as clocksource and clockevent.

Hmm ... one idea would be to wrap them in the dt, like

	clocksource {
	
		compatible = "snps,dw-apb-clocksource"
		
		timer at 2003a000 {
		
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2003a000 0x100>;
			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 1>, <&clk_gates7 8>;
			clock-names = "timer", "pclk";
		
		};
		
		timer at 2000e000 {
		
			compatible = "snps,dw-apb-timer-osc";
			reg = <0x2000e000 0x100>;
			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_gates1 2>, <&clk_gates7 9>;
			clock-names = "timer", "pclk";
Quoted 6 lines
Quoted 3 lines
		};
	
	};

Can't you just have multiple CLOCKSOURCE_OF_DECLARE() lines, one for each of the nodes?

The timers are of the same type and the clocksource driver just grabs the first of them as clockevent and the second as clocksource, so I think two CLOCKSOURCE_OF_DECLARE lines won't do.

But I just looked at clocksource_of_init a bit more closely, which does a for_each_matching_node_and_match over the nodes. So the init_func could grab the device for the clockevent on the first call and the clocksource when it gets called for the second matching node.

Quoted 14 lines
Quoted 9 lines
Quoted 8 lines

arch/arm/mach-rockchip/rockchip.c line 54

Quoted 6 lines
arch/arm/mach-rockchip/rockchip.c new file +6 -0
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+       .map_io         = debug_ll_io_init,
+       .init_machine   = rockchip_dt_init,
+       .init_time      = rockchip_timer_init,
+       .dt_compat      = rockchip_board_dt_compat,
+MACHINE_END

The map_io line can already get removed.

Quoted 3 lines

Yesterday I did grep thru the linux-next I was using as base looking for the debug_ll_io_init default I read about but was not able to find it ... most likely my linux-next is a tad to old.

Yes, it only showed up in today's linux-next. I thought it was older.

#36 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

Quoted 4 lines · On Monday 03 June 2013 11:46:57 Heiko Stübner wrote:

The timers are of the same type and the clocksource driver just grabs the first of them as clockevent and the second as clocksource, so I think two CLOCKSOURCE_OF_DECLARE lines won't do.

Ok, got it. I was confused by the fact that the existing two sets of "compatible" strings have separate sets of strings:

static const struct of_device_id sptimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-rtc" },
        { .compatible = "snps,dw-apb-timer-sp" },
        { /* Sentinel */ },
};
static const struct of_device_id osctimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-timer" },
        { .compatible = "snps,dw-apb-timer-osc" },
        {},
};

and thought they were for clocksource and clockevent respectively, which is wrong.

Quoted 4 lines

But I just looked at clocksource_of_init a bit more closely, which does a for_each_matching_node_and_match over the nodes. So the init_func could grab the device for the clockevent on the first call and the clocksource when it gets called for the second matching node.

Yes, I think that should work. You just have to be careful about calling init_sched_clock() only once.

Arnd

author maintainer
#37 lore raw

RFC 1/1 dw_apb_timer_of: use clocksource_of_init

dw_apb_timer_init used to search the devicetree for matching timer devices, making calls to it from board files necessary.

Change the dw_apb_timer_init to work with CLOCKSOURCE_OF_DECLARE. With this change the function gets called once for each timer node and tracks these number of calls to attach clockevent and clocksource devices to the nodes.

Also convert all previous users of dw_apb_timer_init to use clocksource_of_init.

Tested on the upcoming rk3066 code.

---
so something like this?

 arch/arm/mach-picoxcell/Kconfig       |    1 +
 arch/arm/mach-picoxcell/common.c      |    4 +-
 arch/arm/mach-socfpga/Kconfig         |    1 +
 arch/arm/mach-socfpga/socfpga.c       |    4 +-
 drivers/clocksource/dw_apb_timer_of.c |   41 ++++++++++++++++-----------------
 include/linux/dw_apb_timer.h          |    1 -
 6 files changed, 26 insertions(+), 26 deletions(-)
arch/arm/mach-picoxcell/Kconfig +1 -0
index 13bae78..3ef6bbe 100644
@@ -6,6 +6,7 @@ config ARCH_PICOXCELL
 	select CPU_V6K
 	select DW_APB_TIMER
 	select DW_APB_TIMER_OF
+	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
 	select HAVE_TCM
 	select NO_IOPORT
arch/arm/mach-picoxcell/common.c +2 -2
index 70b441a..170f085 100644
@@ -15,7 +15,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/dw_apb_timer.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -88,7 +88,7 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
 	.map_io		= picoxcell_map_io,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= irqchip_init,
-	.init_time	= dw_apb_timer_init,
+	.init_time	= clocksource_of_init,
 	.init_machine	= picoxcell_init_machine,
 	.dt_compat	= picoxcell_dt_match,
 	.restart	= picoxcell_wdt_restart,
arch/arm/mach-socfpga/Kconfig +1 -0
index 566e804..1c95288 100644
@@ -9,6 +9,7 @@ config ARCH_SOCFPGA
 	select CPU_V7
 	select DW_APB_TIMER
 	select DW_APB_TIMER_OF
+	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
 	select GPIO_PL061 if GPIOLIB
 	select HAVE_ARM_SCU
arch/arm/mach-socfpga/socfpga.c +2 -2
index 46a0513..921ff67 100644
@@ -14,7 +14,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/dw_apb_timer.h>
+#include <linux/clocksource.h>
 #include <linux/clk-provider.h>
 #include <linux/irqchip.h>
 #include <linux/of_address.h>
@@ -120,7 +120,7 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
 	.smp		= smp_ops(socfpga_smp_ops),
 	.map_io		= socfpga_map_io,
 	.init_irq	= socfpga_init_irq,
-	.init_time	= dw_apb_timer_init,
+	.init_time	= clocksource_of_init,
 	.init_machine	= socfpga_cyclone5_init,
 	.restart	= socfpga_cyclone5_restart,
 	.dt_compat	= altera_dt_match,
drivers/clocksource/dw_apb_timer_of.c +20 -21

47 lines not on this page · raw message

include/linux/dw_apb_timer.h +0 -1
index dd755ce..07261d5 100644
@@ -53,5 +53,4 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
 cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
 void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
 
-extern void dw_apb_timer_init(void);
 #endif /* __DW_APB_TIMER_H__ */
Signature · 1 line
1.7.2.3
Acked-by on v1 1/1
#38 lore raw

Re: [RFC] dw_apb_timer_of: use clocksource_of_init

Quoted 8 lines · Heiko St?bner

dw_apb_timer_init used to search the devicetree for matching timer devices, making calls to it from board files necessary.

Change the dw_apb_timer_init to work with CLOCKSOURCE_OF_DECLARE. With this change the function gets called once for each timer node and tracks these number of calls to attach clockevent and clocksource devices to the nodes.

Quoted 6 lines

Also convert all previous users of dw_apb_timer_init to use clocksource_of_init.

Tested on the upcoming rk3066 code.

But 1 comment:

arch/arm/mach-picoxcell/common.c DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") · line 91

Quoted 6 lines
arch/arm/mach-picoxcell/common.c +1 -1
@@ -88,7 +88,7 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
 	.map_io		= picoxcell_map_io,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= irqchip_init,
-	.init_time	= dw_apb_timer_init,
+	.init_time	= clocksource_of_init,

clocksource_of_init is the default now, so you can just remove this and the one in socfpga.

Same for irqchip_init BTW, but that's another patch.

Rob

Acked-by on v1 1/1
#39 lore raw

Re: [RFC] dw_apb_timer_of: use clocksource_of_init

In reply to Heiko Stübner
Quoted 8 lines · On Monday 03 June 2013 14:15:28 Heiko Stübner wrote:

dw_apb_timer_init used to search the devicetree for matching timer devices, making calls to it from board files necessary.

Change the dw_apb_timer_init to work with CLOCKSOURCE_OF_DECLARE. With this change the function gets called once for each timer node and tracks these number of calls to attach clockevent and clocksource devices to the nodes.

Quoted 6 lines

Also convert all previous users of dw_apb_timer_init to use clocksource_of_init.

Tested on the upcoming rk3066 code.

#40 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

In reply to Heiko Stübner

Dear Heiko St?bner,

arch/arm/mach-rockchip/Makefile.boot line 3

Quoted 7 lines · Heiko St?bner

index 0000000..a2d8c70

arch/arm/mach-rockchip/Makefile.boot new file +3 -0
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60408000
+params_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60088000
+initrd_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60800000

Thanks to the AUTO_ZRELADDR thing that you're using as part of the MULTIPLATFORM support, this Makefile.boot file is no longer useful. See mach-socfpga, mach-mvebu, mach-bcm2835, mach-bcm, mach-highbank, etc.

Cc'ing Maxime Ripard, since I see that mach-sunxi does have a Makefile.boot, even though I believe it is not needed.

Best regards,

Thomas

Signature · 4 lines
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#41 lore raw

Re: [PATCH 10/10] arm: add basic support for Rockchip RK3066a boards

Hi Thomas,

Quoted 15 lines · Thomas Petazzoni

Dear Heiko St?bner,

arch/arm/mach-rockchip/Makefile.boot line 3

Quoted 7 lines · Heiko St?bner

index 0000000..a2d8c70

arch/arm/mach-rockchip/Makefile.boot new file +3 -0
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60408000
+params_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60088000
+initrd_phys-$(CONFIG_ARCH_ROCKCHIP)	:= 0x60800000

Thanks to the AUTO_ZRELADDR thing that you're using as part of the MULTIPLATFORM support, this Makefile.boot file is no longer useful. See mach-socfpga, mach-mvebu, mach-bcm2835, mach-bcm, mach-highbank, etc.

Quoted 2 lines

Cc'ing Maxime Ripard, since I see that mach-sunxi does have a Makefile.boot, even though I believe it is not needed.

Yes, it is a left-over and should be removed obviously.

Thanks for reminding it to me :)

Maxime

#42 lore raw
In reply to Heiko Stübner
Quoted 8 lines · On Monday 03 June 2013 00:55:15 Heiko St?bner wrote:

Prepare your eggs and tomatoes please, I got myself a second playground .

As the title implies this series adds basic support for Rockchip's Cortex-A9 SoCs, like the RK3066 used in many cheaper tablets.

On the periphal side it's very lightweight, as it seems someone from Rockchip was shopping in the DesignWare store.

Quoted 8 lines

This makes the pinctrl driver the biggest hunk in the series, but to get some bonus points I used the generic_irq implementation for the interrupt handling, based on Thomas' irqdomain support series.

Supported periphals are, the timers, uarts and mmc controllers, so interested parties will need a serial console for now.

Hopefully I didn't mess up to much

Great stuff! I have a few small comments for later, but I'm basically fine with it going in as-is.

Needs review from the clk and pinctrl maintainers of course.

Arnd