All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/12] riscv: Add Sipeed Maix support
@ 2020-02-02 19:56 Sean Anderson
  2020-02-02 19:58 ` [PATCH v3 01/12] clk: Always use the supplied struct clk Sean Anderson
                   ` (11 more replies)
  0 siblings, 12 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 19:56 UTC (permalink / raw)
  To: u-boot

This patch series adds support for Sipeed Maix boards and the
Kendryte K210 CPU. Currently, only the Maix Bit V2.0 is supported,
however other models are similar. This series depends on
<https://patchwork.ozlabs.org/patch/1215327/>
(clk: Include missing headers for linux/clk-provider.h).
In addition, there are optional dependencies on
<https://patchwork.ozlabs.org/project/uboot/list/?series=156377>
<https://patchwork.ozlabs.org/project/uboot/list/?series=156381> and
<https://patchwork.ozlabs.org/patch/1232422/>
(wdt: Add DM support for Designware WDT)
(riscv: Try to get cpu frequency from device tree)
(serial: Set baudrate on boot)

To flash u-boot to a maix bit, run
kflash -tp /dev/<your tty here> -B bit_mic u-boot-dtb.bin

Boot output should look like the following:

U-Boot 2020.01-00455-gad03fd83e1 (Jan 15 2020 - 17:10:24 -0500)

DRAM:  8 MiB
MMC:   spi at 52000000:slot at 0: 0
In:    serial at 38000000
Out:   serial at 38000000
Err:   serial at 38000000
=> 

Note that spi does not work! I am trying to figure out what the problem is, but
for the moment the only way to boot something is to transfer it over serial.

Changes for v3:
  Remove patch to set RV64I as default.
  Remove patch for a separate sysctl driver.
  Split off cpu frequency patch into its own series.
  Reorder support/devicetree patches to come last.
  Add patch for reset driver.
  Add simple-pm-bus for busses with their own clocks.
  Add additional documentation.
  Reword mcounteren patch to refer to the RISC-V priv spec 1.9.1.
  Many devicetree changes
  Switch to "make savedefconfig" to generate the config

Changes for v2:
  Many bugfixes for the device tree.
  Modify the config to build without errors.
  Add support for keeping internal PLL frequencies in-range.
  Fix several rebase-induced artifacts.

Sean Anderson (12):
  clk: Always use the supplied struct clk
  clk: Check that ops of composite clock components exist before calling
  clk: Unconditionally recursively en-/dis-able clocks
  reset: Add generic reset driver
  dm: Add support for simple-pm-bus
  riscv: Add headers for asm/global_data.h
  riscv: Add option to support RISC-V privileged spec 1.9.1
  riscv: Allow use of reset drivers
  riscv: Add K210 pll support
  riscv: Add K210 clock support
  riscv: Add device tree for K210
  riscv: Add initial Sipeed Maix support

 arch/riscv/Kconfig                            |  14 +
 arch/riscv/cpu/cpu.c                          |   6 +
 arch/riscv/dts/Makefile                       |   1 +
 arch/riscv/dts/k210-maix-bit.dts              |  42 ++
 arch/riscv/dts/k210.dtsi                      | 496 ++++++++++++++
 arch/riscv/include/asm/csr.h                  |   6 +
 arch/riscv/include/asm/global_data.h          |   2 +
 arch/riscv/lib/reset.c                        |   2 +
 board/sipeed/maix/Kconfig                     |  51 ++
 board/sipeed/maix/MAINTAINERS                 |  10 +
 board/sipeed/maix/Makefile                    |   5 +
 board/sipeed/maix/maix.c                      |   9 +
 configs/sipeed_maix_bitm_defconfig            |  10 +
 doc/board/index.rst                           |   1 +
 doc/board/kendryte/index.rst                  |   9 +
 doc/board/kendryte/k210.rst                   |  46 ++
 .../bus/simple-pm-bus.txt                     |  44 ++
 .../reset/syscon-reset.txt                    |  36 ++
 doc/imx/clk/ccf.txt                           |  63 +-
 drivers/clk/Kconfig                           |   1 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-composite.c                   |  65 +-
 drivers/clk/clk-divider.c                     |   6 +-
 drivers/clk/clk-fixed-factor.c                |   3 +-
 drivers/clk/clk-gate.c                        |   6 +-
 drivers/clk/clk-mux.c                         |  12 +-
 drivers/clk/clk-uclass.c                      |  58 +-
 drivers/clk/imx/clk-gate2.c                   |   4 +-
 drivers/clk/kendryte/Kconfig                  |  12 +
 drivers/clk/kendryte/Makefile                 |   1 +
 drivers/clk/kendryte/clk.c                    | 390 +++++++++++
 drivers/clk/kendryte/clk.h                    |  27 +
 drivers/clk/kendryte/pll.c                    | 607 ++++++++++++++++++
 drivers/clk/kendryte/pll.h                    |  38 ++
 drivers/core/simple-bus.c                     |  57 +-
 drivers/reset/Kconfig                         |   6 +-
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-syscon.c                  |  79 +++
 include/configs/sipeed-maix.h                 |  19 +
 include/dt-bindings/clock/k210-sysctl.h       |  53 ++
 include/dt-bindings/mfd/k210-sysctl.h         |  38 ++
 include/dt-bindings/reset/k210-sysctl.h       |  38 ++
 42 files changed, 2266 insertions(+), 109 deletions(-)
 create mode 100644 arch/riscv/dts/k210-maix-bit.dts
 create mode 100644 arch/riscv/dts/k210.dtsi
 create mode 100644 board/sipeed/maix/Kconfig
 create mode 100644 board/sipeed/maix/MAINTAINERS
 create mode 100644 board/sipeed/maix/Makefile
 create mode 100644 board/sipeed/maix/maix.c
 create mode 100644 configs/sipeed_maix_bitm_defconfig
 create mode 100644 doc/board/kendryte/index.rst
 create mode 100644 doc/board/kendryte/k210.rst
 create mode 100644 doc/device-tree-bindings/bus/simple-pm-bus.txt
 create mode 100644 doc/device-tree-bindings/reset/syscon-reset.txt
 create mode 100644 drivers/clk/kendryte/Kconfig
 create mode 100644 drivers/clk/kendryte/Makefile
 create mode 100644 drivers/clk/kendryte/clk.c
 create mode 100644 drivers/clk/kendryte/clk.h
 create mode 100644 drivers/clk/kendryte/pll.c
 create mode 100644 drivers/clk/kendryte/pll.h
 create mode 100644 drivers/reset/reset-syscon.c
 create mode 100644 include/configs/sipeed-maix.h
 create mode 100644 include/dt-bindings/clock/k210-sysctl.h
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
 create mode 100644 include/dt-bindings/reset/k210-sysctl.h

-- 
2.25.0

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

* [PATCH v3 01/12] clk: Always use the supplied struct clk
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
@ 2020-02-02 19:58 ` Sean Anderson
  2020-02-06 21:21   ` Lukasz Majewski
  2020-02-02 19:58 ` [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling Sean Anderson
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 19:58 UTC (permalink / raw)
  To: u-boot

CCF clocks should always use the struct clock passed to their methods for
extracting the driver-specific clock information struct. Previously, many
functions would use the clk->dev->priv if the device was bound. This could cause
problems with composite clocks. The individual clocks in a composite clock did
not have the ->dev field filled in. This was fine, because the device-specific
clock information would be used. However, since there was no ->dev, there was no
way to get the parent clock. This caused the recalc_rate method of the CCF
divider clock to fail. One option would be to use the clk->priv field to get the
composite clock and from there get the appropriate parent device. However, this
would tie the implementation to the composite clock. In general, different
devices should not rely on the contents of ->priv from another device.

The simple solution to this problem is to just always use the supplied struct
clock. The composite clock now fills in the ->dev pointer of its child clocks.
This allows child clocks to make calls like clk_get_parent() without issue.

imx avoided the above problem by using a custom get_rate function with composite
clocks.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Documented new assumptions in the CCF
  - Wrapped docs to 80 columns

 doc/imx/clk/ccf.txt            | 63 +++++++++++++++++-----------------
 drivers/clk/clk-composite.c    |  8 +++++
 drivers/clk/clk-divider.c      |  6 ++--
 drivers/clk/clk-fixed-factor.c |  3 +-
 drivers/clk/clk-gate.c         |  6 ++--
 drivers/clk/clk-mux.c          | 12 +++----
 drivers/clk/imx/clk-gate2.c    |  4 +--
 7 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/doc/imx/clk/ccf.txt b/doc/imx/clk/ccf.txt
index 36b60dc438..e40ac360e8 100644
--- a/doc/imx/clk/ccf.txt
+++ b/doc/imx/clk/ccf.txt
@@ -1,42 +1,37 @@
 Introduction:
 =============
 
-This documentation entry describes the Common Clock Framework [CCF]
-port from Linux kernel (v5.1.12) to U-Boot.
+This documentation entry describes the Common Clock Framework [CCF] port from
+Linux kernel (v5.1.12) to U-Boot.
 
-This code is supposed to bring CCF to IMX based devices (imx6q, imx7
-imx8). Moreover, it also provides some common clock code, which would
-allow easy porting of CCF Linux code to other platforms.
+This code is supposed to bring CCF to IMX based devices (imx6q, imx7 imx8).
+Moreover, it also provides some common clock code, which would allow easy
+porting of CCF Linux code to other platforms.
 
 Design decisions:
 =================
 
-* U-Boot's driver model [DM] for clk differs from Linux CCF. The most
-  notably difference is the lack of support for hierarchical clocks and
-  "clock as a manager driver" (single clock DTS node acts as a starting
-  point for all other clocks).
+* U-Boot's driver model [DM] for clk differs from Linux CCF. The most notably
+  difference is the lack of support for hierarchical clocks and "clock as a
+  manager driver" (single clock DTS node acts as a starting point for all other
+  clocks).
 
-* The clk_get_rate() caches the previously read data if CLK_GET_RATE_NOCACHE
-  is not set (no need for recursive access).
+* The clk_get_rate() caches the previously read data if CLK_GET_RATE_NOCACHE is
+  not set (no need for recursive access).
 
-* On purpose the "manager" clk driver (clk-imx6q.c) is not using large
-  table to store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = ....
-  Instead we use udevice's linked list for the same class (UCLASS_CLK).
+* On purpose the "manager" clk driver (clk-imx6q.c) is not using large table to
+  store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = .... Instead we
+  use udevice's linked list for the same class (UCLASS_CLK).
 
   Rationale:
   ----------
-    When porting the code as is from Linux, one would need ~1KiB of RAM to
-    store it. This is way too much if we do plan to use this driver in SPL.
+    When porting the code as is from Linux, one would need ~1KiB of RAM to store
+    it. This is way too much if we do plan to use this driver in SPL.
 
 * The "central" structure of this patch series is struct udevice and its
   uclass_priv field contains the struct clk pointer (to the originally created
   one).
 
-* Up till now U-Boot's driver model (DM) CLK operates on udevice (main
-  access to clock is by udevice ops)
-  In the CCF the access to struct clk (embodying pointer to *dev) is
-  possible via dev_get_clk_ptr() (it is a wrapper on dev_get_uclass_priv()).
-
 * To keep things simple the struct udevice's uclass_priv pointer is used to
   store back pointer to corresponding struct clk. However, it is possible to
   modify clk-uclass.c file and add there struct uc_clk_priv, which would have
@@ -45,13 +40,17 @@ Design decisions:
   setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv)) the
   uclass_priv stores the pointer to struct clk.
 
+* Non-CCF clocks do not have a pointer to a clock in clk->dev->priv. In the case
+  of composite clocks, clk->dev->priv may not match clk. Drivers should always
+  use the struct clk which is passed to them, and not clk->dev->priv.
+
 * It is advised to add common clock code (like already added rate and flags) to
   the struct clk, which is a top level description of the clock.
 
 * U-Boot's driver model already provides the facility to automatically allocate
-  (via private_alloc_size) device private data (accessible via dev->priv).
-  It may look appealing to use this feature to allocate private structures for
-  CCF clk devices e.g. divider (struct clk_divider *divider) for IMX6Q clock.
+  (via private_alloc_size) device private data (accessible via dev->priv). It
+  may look appealing to use this feature to allocate private structures for CCF
+  clk devices e.g. divider (struct clk_divider *divider) for IMX6Q clock.
 
   The above feature had not been used for following reasons:
   - The original CCF Linux kernel driver is the "manager" for clocks - it
@@ -64,21 +63,23 @@ Design decisions:
 
 * I've added the clk_get_parent(), which reads parent's dev->uclass_priv to
   provide parent's struct clk pointer. This seems the easiest way to get
-  child/parent relationship for struct clk in U-Boot's udevice based clocks.
+  child/parent relationship for struct clk in U-Boot's udevice based clocks.  In
+  the future arbitrary parents may be supported by adding a get_parent function
+  to clk_ops.
 
 * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in 'struct clk'.
   Clock IP block agnostic flags from 'struct clk_core' (e.g. NOCACHE) have been
-  moved from this struct one level up to 'struct clk'.
+  moved from this struct one level up to 'struct clk'. Many flags are
+  unimplemented at the moment.
 
 * For tests the new ./test/dm/clk_ccf.c and ./drivers/clk/clk_sandbox_ccf.c
   files have been introduced. The latter setups the CCF clock structure for
-  sandbox by reusing, if possible, generic clock primitives - like divier
-  and mux. The former file provides code to tests this setup.
+  sandbox by reusing, if possible, generic clock primitives - like divier and
+  mux. The former file provides code to tests this setup.
 
   For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been introduced.
-  All new primitives added for new architectures must have corresponding test
-  in the two aforementioned files.
-
+  All new primitives added for new architectures must have corresponding test in
+  the two aforementioned files.
 
 Testing (sandbox):
 ==================
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index a5626c33d1..d0f273d47f 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -145,6 +145,14 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 		goto err;
 	}
 
+	if (composite->mux)
+		composite->mux->dev = clk->dev;
+	if (composite->rate)
+		composite->rate->dev = clk->dev;
+	if (composite->gate)
+		composite->gate->dev = clk->dev;
+
+
 	return clk;
 
 err:
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 822e09b084..bfa05f24a3 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -70,8 +70,7 @@ unsigned long divider_recalc_rate(struct clk *hw, unsigned long parent_rate,
 
 static ulong clk_divider_recalc_rate(struct clk *clk)
 {
-	struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_divider *divider = to_clk_divider(clk);
 	unsigned long parent_rate = clk_get_parent_rate(clk);
 	unsigned int val;
 
@@ -150,8 +149,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
 
 static ulong clk_divider_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk_divider *divider = to_clk_divider(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_divider *divider = to_clk_divider(clk);
 	unsigned long parent_rate = clk_get_parent_rate(clk);
 	int value;
 	u32 val;
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 711b0588bc..d2401cf440 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -18,8 +18,7 @@
 
 static ulong clk_factor_recalc_rate(struct clk *clk)
 {
-	struct clk_fixed_factor *fix =
-		to_clk_fixed_factor(dev_get_clk_ptr(clk->dev));
+	struct clk_fixed_factor *fix = to_clk_fixed_factor(clk);
 	unsigned long parent_rate = clk_get_parent_rate(clk);
 	unsigned long long int rate;
 
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 70b8794554..b2933bc24a 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -43,8 +43,7 @@
  */
 static void clk_gate_endisable(struct clk *clk, int enable)
 {
-	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_gate *gate = to_clk_gate(clk);
 	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
 	u32 reg;
 
@@ -86,8 +85,7 @@ static int clk_gate_disable(struct clk *clk)
 
 int clk_gate_is_enabled(struct clk *clk)
 {
-	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_gate *gate = to_clk_gate(clk);
 	u32 reg;
 
 #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 5acc0b8cbd..67b4afef28 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -35,8 +35,7 @@
 int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int flags,
 			 unsigned int val)
 {
-	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_mux *mux = to_clk_mux(clk);
 	int num_parents = mux->num_parents;
 
 	if (table) {
@@ -79,8 +78,7 @@ unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
 
 u8 clk_mux_get_parent(struct clk *clk)
 {
-	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_mux *mux = to_clk_mux(clk);
 	u32 val;
 
 #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
@@ -97,8 +95,7 @@ u8 clk_mux_get_parent(struct clk *clk)
 static int clk_fetch_parent_index(struct clk *clk,
 				  struct clk *parent)
 {
-	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_mux *mux = to_clk_mux(clk);
 
 	int i;
 
@@ -115,8 +112,7 @@ static int clk_fetch_parent_index(struct clk *clk,
 
 static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
 {
-	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
-			dev_get_clk_ptr(clk->dev) : clk);
+	struct clk_mux *mux = to_clk_mux(clk);
 	int index;
 	u32 val;
 	u32 reg;
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index 1b9db6e791..e32c0cb53e 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -37,7 +37,7 @@ struct clk_gate2 {
 
 static int clk_gate2_enable(struct clk *clk)
 {
-	struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev));
+	struct clk_gate2 *gate = to_clk_gate2(clk);
 	u32 reg;
 
 	reg = readl(gate->reg);
@@ -50,7 +50,7 @@ static int clk_gate2_enable(struct clk *clk)
 
 static int clk_gate2_disable(struct clk *clk)
 {
-	struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev));
+	struct clk_gate2 *gate = to_clk_gate2(clk);
 	u32 reg;
 
 	reg = readl(gate->reg);
-- 
2.25.0

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

* [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
  2020-02-02 19:58 ` [PATCH v3 01/12] clk: Always use the supplied struct clk Sean Anderson
@ 2020-02-02 19:58 ` Sean Anderson
  2020-02-06 21:41   ` Lukasz Majewski
  2020-02-02 19:59 ` [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks Sean Anderson
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 19:58 UTC (permalink / raw)
  To: u-boot

clk_composite_ops was shared between all devices in the composite clock driver.
If one clock had a feature (such as supporting set_parent) which another clock
did not, it could call a null pointer dereference.

This patch does three things
1. It adds null-pointer checks to all composite clock functions.
2. It makes clk_composite_ops const and sets its functions at compile-time.
3. It adds some basic sanity checks to num_parents.

The combined effect of these changes is that any of mux, rate, or gate can be
NULL, and composite clocks will still function normally. Previously, at least
mux had to exist, since clk_composite_get_parent was used to determine the
parent for clk_register.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Don't return an error code where a no-op would be fine

 drivers/clk/clk-composite.c | 57 +++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index d0f273d47f..5425f921ff 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -22,7 +22,10 @@ static u8 clk_composite_get_parent(struct clk *clk)
 		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
 	struct clk *mux = composite->mux;
 
-	return clk_mux_get_parent(mux);
+	if (mux)
+		return clk_mux_get_parent(mux);
+	else
+		return 0;
 }
 
 static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
@@ -32,7 +35,10 @@ static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
 	const struct clk_ops *mux_ops = composite->mux_ops;
 	struct clk *mux = composite->mux;
 
-	return mux_ops->set_parent(mux, parent);
+	if (mux && mux_ops)
+		return mux_ops->set_parent(mux, parent);
+	else
+		return -ENOSYS;
 }
 
 static unsigned long clk_composite_recalc_rate(struct clk *clk)
@@ -42,7 +48,10 @@ static unsigned long clk_composite_recalc_rate(struct clk *clk)
 	const struct clk_ops *rate_ops = composite->rate_ops;
 	struct clk *rate = composite->rate;
 
-	return rate_ops->get_rate(rate);
+	if (rate && rate_ops)
+		return rate_ops->get_rate(rate);
+	else
+		return clk_get_parent_rate(clk);
 }
 
 static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
@@ -52,7 +61,10 @@ static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
 	const struct clk_ops *rate_ops = composite->rate_ops;
 	struct clk *clk_rate = composite->rate;
 
-	return rate_ops->set_rate(clk_rate, rate);
+	if (rate && rate_ops)
+		return rate_ops->set_rate(clk_rate, rate);
+	else
+		return clk_get_rate(clk);
 }
 
 static int clk_composite_enable(struct clk *clk)
@@ -62,7 +74,10 @@ static int clk_composite_enable(struct clk *clk)
 	const struct clk_ops *gate_ops = composite->gate_ops;
 	struct clk *gate = composite->gate;
 
-	return gate_ops->enable(gate);
+	if (gate && gate_ops)
+		return gate_ops->enable(gate);
+	else
+		return 0;
 }
 
 static int clk_composite_disable(struct clk *clk)
@@ -72,15 +87,12 @@ static int clk_composite_disable(struct clk *clk)
 	const struct clk_ops *gate_ops = composite->gate_ops;
 	struct clk *gate = composite->gate;
 
-	gate_ops->disable(gate);
-
-	return 0;
+	if (gate && gate_ops)
+		return gate_ops->disable(gate);
+	else
+		return 0;
 }
 
-struct clk_ops clk_composite_ops = {
-	/* This will be set according to clk_register_composite */
-};
-
 struct clk *clk_register_composite(struct device *dev, const char *name,
 				   const char * const *parent_names,
 				   int num_parents, struct clk *mux,
@@ -94,7 +106,9 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 	struct clk *clk;
 	struct clk_composite *composite;
 	int ret;
-	struct clk_ops *composite_ops = &clk_composite_ops;
+
+	if (!num_parents || (num_parents != 1 && !mux))
+		return ERR_PTR(-EINVAL);
 
 	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
 	if (!composite)
@@ -103,8 +117,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 	if (mux && mux_ops) {
 		composite->mux = mux;
 		composite->mux_ops = mux_ops;
-		if (mux_ops->set_parent)
-			composite_ops->set_parent = clk_composite_set_parent;
 		mux->data = (ulong)composite;
 	}
 
@@ -113,11 +125,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 			clk = ERR_PTR(-EINVAL);
 			goto err;
 		}
-		composite_ops->get_rate = clk_composite_recalc_rate;
-
-		/* .set_rate requires either .round_rate or .determine_rate */
-		if (rate_ops->set_rate)
-			composite_ops->set_rate = clk_composite_set_rate;
 
 		composite->rate = rate;
 		composite->rate_ops = rate_ops;
@@ -132,8 +139,6 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 
 		composite->gate = gate;
 		composite->gate_ops = gate_ops;
-		composite_ops->enable = clk_composite_enable;
-		composite_ops->disable = clk_composite_disable;
 		gate->data = (ulong)composite;
 	}
 
@@ -160,6 +165,14 @@ err:
 	return clk;
 }
 
+static const struct clk_ops clk_composite_ops = {
+	.set_parent = clk_composite_set_parent,
+	.get_rate = clk_composite_recalc_rate,
+	.set_rate = clk_composite_set_rate,
+	.enable = clk_composite_enable,
+	.disable = clk_composite_disable,
+};
+
 U_BOOT_DRIVER(clk_composite) = {
 	.name	= UBOOT_DM_CLK_COMPOSITE,
 	.id	= UCLASS_CLK,
-- 
2.25.0

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

* [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
  2020-02-02 19:58 ` [PATCH v3 01/12] clk: Always use the supplied struct clk Sean Anderson
  2020-02-02 19:58 ` [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling Sean Anderson
@ 2020-02-02 19:59 ` Sean Anderson
  2020-02-06 21:45   ` Lukasz Majewski
  2020-02-02 20:01 ` [PATCH v3 04/12] reset: Add generic reset driver Sean Anderson
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 19:59 UTC (permalink / raw)
  To: u-boot

For clocks not in the CCF, their parents will not have UCLASS_CLK, so we just
enable them as normal. The enable count is local to the struct clk, but this
will never result in the actual en-/dis-able op being called (unless the same
struct clk is enabled twice).

For clocks in the CCF, we always traverse up the tree when enabling. Previously,
CCF clocks without id set would be skipped, stopping the traversal too early.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - New.

 drivers/clk/clk-uclass.c | 58 +++++++++++++++++-----------------------
 1 file changed, 25 insertions(+), 33 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 9aa8537004..87d101aab4 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -490,7 +490,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 int clk_enable(struct clk *clk)
 {
 	const struct clk_ops *ops;
-	struct clk *clkp = NULL;
 	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
@@ -499,32 +498,28 @@ int clk_enable(struct clk *clk)
 	ops = clk_dev_ops(clk->dev);
 
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
-		/* Take id 0 as a non-valid clk, such as dummy */
-		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
-			if (clkp->enable_count) {
-				clkp->enable_count++;
-				return 0;
-			}
-			if (clkp->dev->parent &&
-			    device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
-				ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
-				if (ret) {
-					printf("Enable %s failed\n",
-					       clkp->dev->parent->name);
-					return ret;
-				}
+		if (clk->enable_count) {
+			clk->enable_count++;
+			return 0;
+		}
+		if (clk->dev->parent &&
+		    device_get_uclass_id(clk->dev->parent) == UCLASS_CLK) {
+			ret = clk_enable(dev_get_clk_ptr(clk->dev->parent));
+			if (ret) {
+				printf("Enable %s failed\n",
+				       clk->dev->parent->name);
+				return ret;
 			}
 		}
 
 		if (ops->enable) {
 			ret = ops->enable(clk);
 			if (ret) {
-				printf("Enable %s failed\n", clk->dev->name);
+				printf("Enable %s failed (error %d)\n", clk->dev->name, ret);
 				return ret;
 			}
 		}
-		if (clkp)
-			clkp->enable_count++;
+		clk->enable_count++;
 	} else {
 		if (!ops->enable)
 			return -ENOSYS;
@@ -550,7 +545,6 @@ int clk_enable_bulk(struct clk_bulk *bulk)
 int clk_disable(struct clk *clk)
 {
 	const struct clk_ops *ops;
-	struct clk *clkp = NULL;
 	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
@@ -559,29 +553,27 @@ int clk_disable(struct clk *clk)
 	ops = clk_dev_ops(clk->dev);
 
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
-		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
-			if (clkp->enable_count == 0) {
-				printf("clk %s already disabled\n",
-				       clkp->dev->name);
-				return 0;
-			}
-
-			if (--clkp->enable_count > 0)
-				return 0;
+		if (clk->enable_count == 0) {
+			printf("clk %s already disabled\n",
+			       clk->dev->name);
+			return 0;
 		}
 
+		if (--clk->enable_count > 0)
+			return 0;
+
 		if (ops->disable) {
 			ret = ops->disable(clk);
 			if (ret)
 				return ret;
 		}
 
-		if (clkp && clkp->dev->parent &&
-		    device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
-			ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
+		if (clk->dev->parent &&
+		    device_get_uclass_id(clk->dev) == UCLASS_CLK) {
+			ret = clk_disable(dev_get_clk_ptr(clk->dev->parent));
 			if (ret) {
-				printf("Disable %s failed\n",
-				       clkp->dev->parent->name);
+				printf("Disable %s failed (error %d)\n",
+				       clk->dev->parent->name, ret);
 				return ret;
 			}
 		}
-- 
2.25.0

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

* [PATCH v3 04/12] reset: Add generic reset driver
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (2 preceding siblings ...)
  2020-02-02 19:59 ` [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks Sean Anderson
@ 2020-02-02 20:01 ` Sean Anderson
  2020-02-03  0:04   ` Simon Glass
  2020-02-04 11:06   ` Bin Meng
  2020-02-02 20:02 ` [PATCH v3 05/12] dm: Add support for simple-pm-bus Sean Anderson
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:01 UTC (permalink / raw)
  To: u-boot

This patch adds a generic reset driver. It is designed to be useful when one has
a register in a regmap which contains bits that reset other devices. I thought
this seemed like a very generic use, so here is a generic driver. The overall
structure has been modeled on the syscon-reboot driver.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - New

 .../reset/syscon-reset.txt                    | 36 +++++++++
 drivers/reset/Kconfig                         |  6 +-
 drivers/reset/Makefile                        |  1 +
 drivers/reset/reset-syscon.c                  | 79 +++++++++++++++++++
 4 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 doc/device-tree-bindings/reset/syscon-reset.txt
 create mode 100644 drivers/reset/reset-syscon.c

diff --git a/doc/device-tree-bindings/reset/syscon-reset.txt b/doc/device-tree-bindings/reset/syscon-reset.txt
new file mode 100644
index 0000000000..47c1226567
--- /dev/null
+++ b/doc/device-tree-bindings/reset/syscon-reset.txt
@@ -0,0 +1,36 @@
+Generic SYSCON mapped register reset driver
+
+This is a generic reset driver using syscon to map the reset register.
+The reset is generally performed with a write to the reset register
+defined by the register map pointed by syscon reference plus the offset and
+shifted by the reset specifier/
+
+To assert a reset on some device, the equivalent of the following operation is
+performed, where reset_id is the reset specifier from the device's resets
+property. 
+
+	if (BIT(reset_id) & mask)
+		regmap[offset][reset_id] = assert-high;
+
+Required properties:
+- compatible: should contain "syscon-reset"
+- #reset-cells: must be 1
+- regmap: this is phandle to the register map node
+- offset: offset in the register map for the reboot register (in bytes)
+
+Optional properties:
+- mask: accept only the reset specifiers defined by the mask (32 bit)
+- assert-high: Bit to write when asserting a reset. Defaults to 1.
+
+Default will be little endian mode, 32 bit access only.
+
+Example:
+
+	reset-controller {
+		compatible = "syscon-reset";
+		#reset-cells = <1>;
+		regmap = <&sysctl>;
+		offset = <0x20>;
+		mask = <0x27FFFFFF>;
+		assert-high = <0>;
+	};
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 75ccd65799..759d659c82 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -147,5 +147,9 @@ config RESET_IMX7
 	default y
 	help
 	  Support for reset controller on i.MX7/8 SoCs.
-
+config RESET_SYSCON
+	bool "Enable generic syscon reset driver support"
+	depends on DM_RESET
+	help
+	  Support generic syscon mapped register reset devices.
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 0a044d5d8c..433f1eca54 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
+obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o
diff --git a/drivers/reset/reset-syscon.c b/drivers/reset/reset-syscon.c
new file mode 100644
index 0000000000..db58b7705a
--- /dev/null
+++ b/drivers/reset/reset-syscon.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Sean Anderson
+ */
+
+#include <dm.h>
+#include <linux/bitops.h>
+#include <regmap.h>
+#include <reset.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+
+struct syscon_reset_priv {
+	struct regmap *regmap;
+	uint offset;
+	uint mask;
+	bool assert_high;
+};
+
+static int syscon_reset_request(struct reset_ctl *rst)
+{
+	struct syscon_reset_priv *priv = dev_get_priv(rst->dev);
+
+	if (BIT(rst->id) & priv->mask)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int syscon_reset_assert(struct reset_ctl *rst)
+{
+	struct syscon_reset_priv *priv = dev_get_priv(rst->dev);
+
+	return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id),
+				  priv->assert_high);
+}
+
+static int syscon_reset_deassert(struct reset_ctl *rst)
+{
+	struct syscon_reset_priv *priv = dev_get_priv(rst->dev);
+
+	return regmap_update_bits(priv->regmap, priv->offset, BIT(rst->id),
+				  !priv->assert_high);
+}
+
+static const struct reset_ops syscon_reset_ops = {
+	.request = syscon_reset_request,
+	.rst_assert = syscon_reset_assert,
+	.rst_deassert = syscon_reset_deassert,
+};
+
+int syscon_reset_probe(struct udevice *dev)
+{
+	struct syscon_reset_priv *priv = dev_get_priv(dev);
+
+	priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap");
+	if (IS_ERR(priv->regmap))
+		return -ENODEV;
+
+	priv->offset = dev_read_u32_default(dev, "offset", 0);
+	priv->mask = dev_read_u32_default(dev, "mask", 0);
+	priv->assert_high = dev_read_u32_default(dev, "assert-high", true);
+
+	return 0;
+}
+
+static const struct udevice_id syscon_reset_ids[] = {
+	{ .compatible = "syscon-reset" },
+	{ },
+};
+
+U_BOOT_DRIVER(syscon_reset) = {
+	.name = "syscon_reset",
+	.id = UCLASS_RESET,
+	.of_match = syscon_reset_ids,
+	.probe = syscon_reset_probe,
+	.priv_auto_alloc_size = sizeof(struct syscon_reset_priv),
+	.ops = &syscon_reset_ops,
+};
-- 
2.25.0

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

* [PATCH v3 05/12] dm: Add support for simple-pm-bus
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (3 preceding siblings ...)
  2020-02-02 20:01 ` [PATCH v3 04/12] reset: Add generic reset driver Sean Anderson
@ 2020-02-02 20:02 ` Sean Anderson
  2020-02-03  0:04   ` Simon Glass
  2020-02-04 11:13   ` Bin Meng
  2020-02-02 20:04 ` [PATCH v3 06/12] riscv: Add headers for asm/global_data.h Sean Anderson
                   ` (6 subsequent siblings)
  11 siblings, 2 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:02 UTC (permalink / raw)
  To: u-boot

This type of bus is used in Linux to designate busses which have power domains
and/or clocks which need to be enabled before their child devices can be used.
Because power domains are automatically enabled before probing in u-boot, we
just need to enable any clocks present.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - New

 .../bus/simple-pm-bus.txt                     | 44 ++++++++++++++
 drivers/core/simple-bus.c                     | 57 ++++++++++++++++++-
 2 files changed, 99 insertions(+), 2 deletions(-)
 create mode 100644 doc/device-tree-bindings/bus/simple-pm-bus.txt

diff --git a/doc/device-tree-bindings/bus/simple-pm-bus.txt b/doc/device-tree-bindings/bus/simple-pm-bus.txt
new file mode 100644
index 0000000000..6f15037131
--- /dev/null
+++ b/doc/device-tree-bindings/bus/simple-pm-bus.txt
@@ -0,0 +1,44 @@
+Simple Power-Managed Bus
+========================
+
+A Simple Power-Managed Bus is a transparent bus that doesn't need a real
+driver, as it's typically initialized by the boot loader.
+
+However, its bus controller is part of a PM domain, or under the control of a
+functional clock.  Hence, the bus controller's PM domain and/or clock must be
+enabled for child devices connected to the bus (either on-SoC or externally)
+to function.
+
+While "simple-pm-bus" follows the "simple-bus" set of properties, as specified
+in the Devicetree Specification, it is not an extension of "simple-bus".
+
+
+Required properties:
+  - compatible: Must contain at least "simple-pm-bus".
+		Must not contain "simple-bus".
+		It's recommended to let this be preceded by one or more
+		vendor-specific compatible values.
+  - #address-cells, #size-cells, ranges: Must describe the mapping between
+		parent address and child address spaces.
+
+Optional platform-specific properties for clock or PM domain control (at least
+one of them is required):
+  - clocks: Must contain a reference to the functional clock(s),
+  - power-domains: Must contain a reference to the PM domain.
+Please refer to the binding documentation for the clock and/or PM domain
+providers for more details.
+
+
+Example:
+
+	bsc: bus at fec10000 {
+		compatible = "renesas,bsc-sh73a0", "renesas,bsc",
+			     "simple-pm-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0x20000000>;
+		reg = <0xfec10000 0x400>;
+		interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&zb_clk>;
+		power-domains = <&pd_a4s>;
+	};
diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c
index 7fc23ef82d..d94567e98d 100644
--- a/drivers/core/simple-bus.c
+++ b/drivers/core/simple-bus.c
@@ -5,6 +5,11 @@
 
 #include <common.h>
 #include <dm.h>
+#include <clk.h>
+
+#define SIMPLE_BUS 0
+#define SIMPLE_MFD 1
+#define SIMPLE_PM_BUS 2
 
 struct simple_bus_plat {
 	u32 base;
@@ -50,9 +55,55 @@ UCLASS_DRIVER(simple_bus) = {
 	.per_device_platdata_auto_alloc_size = sizeof(struct simple_bus_plat),
 };
 
+static const int generic_simple_bus_probe(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(CLK)
+	int ret;
+	struct clk_bulk *bulk;
+	ulong type = dev_get_driver_data(dev);
+
+	if (type == SIMPLE_PM_BUS) {
+		bulk = kzalloc(sizeof(*bulk), GFP_KERNEL);
+		if (!bulk)
+			return -ENOMEM;
+
+		ret = clk_get_bulk(dev, bulk);
+		if (ret)
+			return ret;
+		
+		ret = clk_enable_bulk(bulk);
+		if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+			clk_release_bulk(bulk);
+			return ret;
+		}
+		dev->priv = bulk;
+	}
+#endif
+	return 0;
+}
+
+static const int generic_simple_bus_remove(struct udevice *dev)
+{
+	int ret = 0;
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk_bulk *bulk;
+	ulong type = dev_get_driver_data(dev);
+
+	if (type == SIMPLE_PM_BUS) {
+		bulk = dev_get_priv(dev);
+		ret = clk_release_bulk(bulk);
+		kfree(bulk);
+		if (ret == -ENOSYS)
+			ret = 0;
+	}
+#endif
+	return ret;
+}
+
 static const struct udevice_id generic_simple_bus_ids[] = {
-	{ .compatible = "simple-bus" },
-	{ .compatible = "simple-mfd" },
+	{ .compatible = "simple-bus", .data = SIMPLE_BUS },
+	{ .compatible = "simple-mfd", .data = SIMPLE_MFD },
+	{ .compatible = "simple-pm-bus", .data = SIMPLE_PM_BUS },
 	{ }
 };
 
@@ -60,5 +111,7 @@ U_BOOT_DRIVER(simple_bus_drv) = {
 	.name	= "generic_simple_bus",
 	.id	= UCLASS_SIMPLE_BUS,
 	.of_match = generic_simple_bus_ids,
+	.probe = generic_simple_bus_probe,
+	.remove = generic_simple_bus_remove,
 	.flags	= DM_FLAG_PRE_RELOC,
 };
-- 
2.25.0

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

* [PATCH v3 06/12] riscv: Add headers for asm/global_data.h
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (4 preceding siblings ...)
  2020-02-02 20:02 ` [PATCH v3 05/12] dm: Add support for simple-pm-bus Sean Anderson
@ 2020-02-02 20:04 ` Sean Anderson
  2020-02-04 11:17   ` Bin Meng
  2020-02-02 20:05 ` [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1 Sean Anderson
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:04 UTC (permalink / raw)
  To: u-boot

This header depended on bd_t and ulong, but did not include the appropriate
headers.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/include/asm/global_data.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
index b74bd7e738..4f0c12b402 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -11,6 +11,8 @@
 #define __ASM_GBL_DATA_H
 
 #include <asm/smp.h>
+#include <asm/u-boot.h>
+#include <linux/compiler.h>
 
 /* Architecture-specific global data */
 struct arch_global_data {
-- 
2.25.0

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (5 preceding siblings ...)
  2020-02-02 20:04 ` [PATCH v3 06/12] riscv: Add headers for asm/global_data.h Sean Anderson
@ 2020-02-02 20:05 ` Sean Anderson
  2020-02-04 11:21   ` Bin Meng
  2020-02-02 20:06 ` [PATCH v3 08/12] riscv: Allow use of reset drivers Sean Anderson
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:05 UTC (permalink / raw)
  To: u-boot

Some older processors (notably the Kendryte K210) use an older version of the
RISC-V privileged specification. The primary changes between the old and new are
in virtual memory, and in the merging of three separate counter enable CSRs.
Using the new CSR on an old processor causes an illegal instruction exception.
This patch adds an option to use the old CSRs instead of the new one.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
Changes for v3:
  - Renamed from "riscv: Add option to disable writes to mcounteren"
  - Added original functionality back for older priv specs.
Changes for v2:
  - Moved forward in the patch series

 arch/riscv/Kconfig           | 10 ++++++++++
 arch/riscv/cpu/cpu.c         |  6 ++++++
 arch/riscv/include/asm/csr.h |  6 ++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 85e15ebffa..87c40f6c4c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -222,6 +222,16 @@ config XIP
 	  from a NOR flash memory without copying the code to ram.
 	  Say yes here if U-Boot boots from flash directly.
 
+config RISCV_PRIV_1_9_1
+	bool "Use version 1.9.1 of the RISC-V priviledged specification"
+	help
+	  Older versions of the RISC-V priviledged specification had
+	  separate counter enable CSRs for each privilege mode. Writing
+	  to the unified mcounteren CSR on a processor implementing the
+	  old specification will result in an illegal instruction
+	  exception. In addition to counter CSR changes, the way virtual
+	  memory is configured was also changed.
+
 config STACK_SIZE_SHIFT
 	int
 	default 14
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index e457f6acbf..83cb6557cd 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -89,7 +89,13 @@ int arch_cpu_init_dm(void)
 		 * Enable perf counters for cycle, time,
 		 * and instret counters only
 		 */
+#ifdef CONFIG_RISCV_PRIV_1_9_1
+		/* FIXME: Can't use the macro for some reason... */
+		csr_write(mscounteren, GENMASK(2, 0));
+		csr_write(mucounteren, GENMASK(2, 0));
+#else
 		csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
+#endif
 
 		/* Disable paging */
 		if (supports_extension('s'))
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index d1520743a2..c16b65d3f3 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -93,7 +93,13 @@
 #define CSR_MISA		0x301
 #define CSR_MIE			0x304
 #define CSR_MTVEC		0x305
+#ifdef RISCV_PRIV_1_9_1
+#define CSR_MUCOUNTEREN         0x320
+#define CSR_MSCOUNTEREN         0x321
+#define CSR_MHCOUNTEREN         0x322
+#else
 #define CSR_MCOUNTEREN		0x306
+#endif
 #define CSR_MSCRATCH		0x340
 #define CSR_MEPC		0x341
 #define CSR_MCAUSE		0x342
-- 
2.25.0

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

* [PATCH v3 08/12] riscv: Allow use of reset drivers
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (6 preceding siblings ...)
  2020-02-02 20:05 ` [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1 Sean Anderson
@ 2020-02-02 20:06 ` Sean Anderson
  2020-02-04 11:22   ` Bin Meng
  2020-02-02 20:07 ` [PATCH v3 09/12] riscv: Add K210 pll support Sean Anderson
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:06 UTC (permalink / raw)
  To: u-boot

Currently, one cannot use a reset driver on RISC-V. Follow the MIPS example, and
disable the default reset handler when the sysreset driver is enabled.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - New

 arch/riscv/lib/reset.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/riscv/lib/reset.c b/arch/riscv/lib/reset.c
index b8cecb309d..6cf6387f10 100644
--- a/arch/riscv/lib/reset.c
+++ b/arch/riscv/lib/reset.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <command.h>
 
+#ifndef CONFIG_SYSRESET
 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	printf("resetting ...\n");
@@ -15,3 +16,4 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	return 0;
 }
+#endif
-- 
2.25.0

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

* [PATCH v3 09/12] riscv: Add K210 pll support
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (7 preceding siblings ...)
  2020-02-02 20:06 ` [PATCH v3 08/12] riscv: Allow use of reset drivers Sean Anderson
@ 2020-02-02 20:07 ` Sean Anderson
  2020-02-02 20:07 ` [PATCH v3 10/12] riscv: Add K210 clock support Sean Anderson
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:07 UTC (permalink / raw)
  To: u-boot

This pll code is primarily based on the code from the kendryte standalone sdk in
lib/drivers/sysctl.c. k210_pll_calc_params is roughly analogous to the algorithm
used to set the pll frequency, but it has been completely rewritten to be
fixed-point based.

Currently I am having problems setting the rate of the PLL. It seems that the
bypass does not work when the PLL is reset and the rate has changed. I may need
to reparent ACLK, which seems like a real pain to do generically. On the upside,
I have identified this PLL as a True Circuits, Inc. model.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Add an option to not include support for setting the pll rate. This saves
    around 1K in the final executable.
  - Remove udelays to suppress warnings
  - Bypass PLL after enabling, instead of before
  - Check if the PLL is enabled already before doing a reset
  - Fix bug with locked mask
  Changes for v2:
  - Rename driver to "k210_clk_pll"
  - Add additional in-line documentation on algorithm and PLLs
  - Restrict the range of internal VCO and reference frequencies
  - Don't load driver before relocation
  - Remove spurious references to mach-k210

 drivers/clk/Kconfig           |   1 +
 drivers/clk/Makefile          |   1 +
 drivers/clk/kendryte/Kconfig  |  12 +
 drivers/clk/kendryte/Makefile |   1 +
 drivers/clk/kendryte/pll.c    | 607 ++++++++++++++++++++++++++++++++++
 drivers/clk/kendryte/pll.h    |  38 +++
 6 files changed, 660 insertions(+)
 create mode 100644 drivers/clk/kendryte/Kconfig
 create mode 100644 drivers/clk/kendryte/Makefile
 create mode 100644 drivers/clk/kendryte/pll.c
 create mode 100644 drivers/clk/kendryte/pll.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 16d4237f89..af75c7c4cf 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -145,6 +145,7 @@ source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/at91/Kconfig"
 source "drivers/clk/exynos/Kconfig"
 source "drivers/clk/imx/Kconfig"
+source "drivers/clk/kendryte/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/owl/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 06131edb9f..4f3893f6fc 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
+obj-$(CONFIG_CLK_K210) += kendryte/
 obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
 obj-$(CONFIG_CLK_OWL) += owl/
 obj-$(CONFIG_CLK_RENESAS) += renesas/
diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig
new file mode 100644
index 0000000000..7b69c8afaf
--- /dev/null
+++ b/drivers/clk/kendryte/Kconfig
@@ -0,0 +1,12 @@
+config CLK_K210
+	bool "Clock support for Kendryte K210"
+	depends on CLK && CLK_CCF
+	help
+	  This enables support clock driver for Kendryte K210 platforms.
+
+config CLK_K210_SET_RATE
+	bool "Enable setting the Kendryte K210 PLL rate"
+	depends on CLK_K210
+	help
+	  Add functionality to calculate new rates for K210 PLLs. Enabling this
+	  feature adds around 1K to U-Boot's final size.
diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile
new file mode 100644
index 0000000000..c56d93ea1c
--- /dev/null
+++ b/drivers/clk/kendryte/Makefile
@@ -0,0 +1 @@
+obj-y += pll.o
diff --git a/drivers/clk/kendryte/pll.c b/drivers/clk/kendryte/pll.c
new file mode 100644
index 0000000000..03aec72fd7
--- /dev/null
+++ b/drivers/clk/kendryte/pll.c
@@ -0,0 +1,607 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+#include "pll.h"
+
+#define LOG_CATEGORY UCLASS_CLK
+#include <asm/io.h>
+/* For DIV_ROUND_DOWN_ULL, defined in linux/kernel.h */
+#include <div64.h>
+#include <dt-bindings/clock/k210-sysctl.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <log.h>
+
+#define CLK_K210_PLL "k210_clk_pll"
+#define to_k210_pll(_clk) container_of(_clk, struct k210_pll, clk)
+
+#ifdef CONFIG_CLK_K210_SET_RATE 
+static int k210_pll_enable(struct clk *clk);
+static int k210_pll_disable(struct clk *clk);
+
+/*
+ * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc.
+ * General-Purpose PLL. The logical layout of the PLL with internal feedback is
+ * approximately the following:
+ *
+ *    +-----------+
+ *    |input clock|
+ *    +-----------+
+ *          |
+ *          v
+ *        +--+
+ *        |/r|
+ *        +--+
+ *          |
+ *          v
+ *  +---------------+
+ *  |reference clock|
+ *  +---------------+
+ *          |
+ *          v
+ * +----------------+
+ * |phase comparator|<--+
+ * +----------------+   |
+ *          |           |
+ *          v   +--------------+
+ *        +---+ |feedback clock|
+ *        |VCO| +--------------+
+ *        +---+         ^
+ *          |    +--+   |
+ *          +--->|/f|---+
+ *          |    +--+
+ *          v
+ *        +---+
+ *        |/od|
+ *        +---+
+ *          |
+ *          v
+ *       +------+
+ *       |output|
+ *       +------+
+ *
+ * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode,
+ * the effect of the division by f is to multiply the input frequency. The
+ * equation for the output rate is
+ * 	rate = (rate_in * f) / (r * od).
+ * Moving knowns to one side of the equation, we get
+ *	rate / rate_in = f / (r * od)
+ * Rearranging slightly,
+ *	abs_error = abs((rate / rate_in) - (f / (r * od))).
+ * To get relative, error, we divide by the expected ratio
+ *	error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in).
+ * Simplifying,
+ *	error = abs(1 - f / (r * od)) / (rate / rate_in)
+ *	error = abs(1 - (f * rate_in) / (r * od * rate))
+ * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate,
+ *	error = abs((f * inv_ratio) / (r * od) - 1)
+ * This is the error used in evaluating parameters.
+ *
+ * r and od are four bits each, while f is six bits. Because r and od are
+ * multiplied together, instead of the full 256 values possible if both bits
+ * were used fully, there are only 97 distinct products. Combined with f, there
+ * are 6208 theoretical settings for the PLL. However, most of these settings
+ * can be ruled out immediately because they do not have the correct ratio.
+ *
+ * In addition to the constraint of approximating the desired ratio, parameters
+ * must also keep internal pll frequencies within acceptable ranges. The
+ * reference clock's minimum and maximum frequencies have a ratio of around 128.
+ * This leaves fairly substantial room to work with, especially since the only
+ * affected parameter is r. The VCO's minimum and maximum frequency have a ratio
+ * of 5, which is considerably more restrictive.
+ *
+ * The r and od factors are stored in a table. This is to make it easy to find
+ * the next-largest product. Some products have multiple factorizations, but
+ * only when one factor has at least a 2.5x ratio to the factors of the other
+ * factorization. This is because any smaller ratio would not make a difference
+ * when ensuring the VCO's frequency is within spec.
+ *
+ * Throughout the calculation function, fixed point arithmetic is used. Because
+ * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit
+ * 32.32 fixed-point numbers are used to represent ratios. In general, to
+ * implement division, the numerator is first multiplied by 2^32. This gives a
+ * result where the whole number part is in the upper 32 bits, and the fraction
+ * is in the lower 32 bits.
+ *
+ * In general, rounding is done to the closest integer. This helps find the best
+ * approximation for the ratio. Rounding in one direction (e.g down) could cause
+ * the function to miss a better ratio with one of the parameters increased by
+ * one.
+ */
+
+/*
+ * The factors table was generated with the following python code:
+ *
+ * def p(x, y):
+ *    return (1.0*x/y > 2.5) or (1.0*y/x > 2.5)
+ *
+ * factors = {}
+ * for i in range(1, 17):
+ *    for j in range(1, 17):
+ *       fs = factors.get(i*j) or []
+ *       if fs == [] or all([
+ *             (p(i, x) and p(i, y)) or (p(j, x) and p(j, y))
+ *             for (x, y) in fs]):
+ *          fs.append((i, j))
+ *          factors[i*j] = fs
+ *
+ * for k, l in sorted(factors.items()):
+ *    for v in l:
+ *       print("PACK(%s, %s)," % v)
+ */
+#define PACK(r, od) ((((r - 1) & 0xF) << 4) | ((od - 1) & 0xF))
+#define UNPACK_R(val) (((val >> 4) & 0xF) + 1)
+#define UNPACK_OD(val) ((val & 0xF) + 1)
+static const u8 factors[] = {
+	PACK(1, 1),
+	PACK(1, 2),
+	PACK(1, 3),
+	PACK(1, 4),
+	PACK(1, 5),
+	PACK(1, 6),
+	PACK(1, 7),
+	PACK(1, 8),
+	PACK(1, 9),
+	PACK(3, 3),
+	PACK(1, 10),
+	PACK(1, 11),
+	PACK(1, 12),
+	PACK(3, 4),
+	PACK(1, 13),
+	PACK(1, 14),
+	PACK(1, 15),
+	PACK(3, 5),
+	PACK(1, 16),
+	PACK(4, 4),
+	PACK(2, 9),
+	PACK(2, 10),
+	PACK(3, 7),
+	PACK(2, 11),
+	PACK(2, 12),
+	PACK(5, 5),
+	PACK(2, 13),
+	PACK(3, 9),
+	PACK(2, 14),
+	PACK(2, 15),
+	PACK(2, 16),
+	PACK(3, 11),
+	PACK(5, 7),
+	PACK(3, 12),
+	PACK(3, 13),
+	PACK(4, 10),
+	PACK(3, 14),
+	PACK(4, 11),
+	PACK(3, 15),
+	PACK(3, 16),
+	PACK(7, 7),
+	PACK(5, 10),
+	PACK(4, 13),
+	PACK(6, 9),
+	PACK(5, 11),
+	PACK(4, 14),
+	PACK(4, 15),
+	PACK(7, 9),
+	PACK(4, 16),
+	PACK(5, 13),
+	PACK(6, 11),
+	PACK(5, 14),
+	PACK(6, 12),
+	PACK(5, 15),
+	PACK(7, 11),
+	PACK(6, 13),
+	PACK(5, 16),
+	PACK(9, 9),
+	PACK(6, 14),
+	PACK(8, 11),
+	PACK(6, 15),
+	PACK(7, 13),
+	PACK(6, 16),
+	PACK(7, 14),
+	PACK(9, 11),
+	PACK(10, 10),
+	PACK(8, 13),
+	PACK(7, 15),
+	PACK(9, 12),
+	PACK(10, 11),
+	PACK(7, 16),
+	PACK(9, 13),
+	PACK(8, 15),
+	PACK(11, 11),
+	PACK(9, 14),
+	PACK(8, 16),
+	PACK(10, 13),
+	PACK(11, 12),
+	PACK(9, 15),
+	PACK(10, 14),
+	PACK(11, 13),
+	PACK(9, 16),
+	PACK(10, 15),
+	PACK(11, 14),
+	PACK(12, 13),
+	PACK(10, 16),
+	PACK(11, 15),
+	PACK(12, 14),
+	PACK(13, 13),
+	PACK(11, 16),
+	PACK(12, 15),
+	PACK(13, 14),
+	PACK(12, 16),
+	PACK(13, 15),
+	PACK(14, 14),
+	PACK(13, 16),
+	PACK(14, 15),
+	PACK(14, 16),
+	PACK(15, 15),
+	PACK(15, 16),
+	PACK(16, 16),
+};
+
+struct k210_pll_params {
+	u8 r;
+	u8 f;
+	u8 od;
+};
+
+static int k210_pll_calc_params(u32 rate, u32 rate_in,
+				struct k210_pll_params *best)
+{
+	int i;
+	s64 error, best_error;
+	u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */
+	u64 max_r;
+	u64 r, f, od;
+
+	/*
+	 * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the
+	 * reference clock frequency. These are not the same limits as below
+	 * because od can reduce the output frequency by 16.
+	 */
+	if (rate > 1750000000 || rate < 21250000)
+		return -EINVAL;
+
+	ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in);
+	inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate);
+	/* Can't increase by more than 64 or reduce by more than 256 */
+	if (rate > rate_in && ratio > (64ULL << 32))
+		return -EINVAL;
+	else if (rate <= rate_in && inv_ratio > (256ULL << 32))
+		return -EINVAL;
+
+	/*
+	 * The reference clock (rate_in / r) must stay between 1.75 GHz and 13
+	 * MHz. There is no minimum, since the only way to get a higher input
+	 * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs
+	 * cannot output frequencies greater than 1.75 GHz, the minimum would
+	 * never be greater than one.
+	 */
+	max_r = DIV_ROUND_DOWN_ULL(rate_in, 13671875);
+
+	/* Variables get immediately incremented, so start at -1th iteration */ 
+	i = -1;
+	f = 0;
+	r = 0;
+	od = 0;
+	error = best_error = S64_MAX;
+	/* do-while here so we always try@least one ratio */
+	do {
+		/*
+		 * Whether we swapped r and od while enforcing frequency limits
+		 */
+		bool swapped = false;
+		u64 last_od = od;
+		u64 last_r = r;
+
+		/*
+		 * Try the next largest value for f (or r and od) and
+		 * recalculate the other parameters based on that
+		 */
+		if (rate > rate_in) {
+			/*
+			 * Skip factors of the same product if we already tried
+			 * out that product
+			 */
+			do {
+				i++;
+				r = UNPACK_R(factors[i]);
+				od = UNPACK_OD(factors[i]);
+			} while (i + 1 < ARRAY_SIZE(factors)
+				 && r * od == last_r * last_od);
+			
+			/* Round close */
+			f = (r * od * ratio + BIT(31)) >> 32;
+			if (f > 64)
+				f = 64;
+		} else {
+			u64 tmp = ++f * inv_ratio;
+			bool round_up = !!(tmp & BIT(31));
+			u32 goal = (tmp >> 32) + round_up;
+			u32 err, last_err;
+
+			/* Get the next r/od pair in factors */
+			while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) {
+				i++;
+				r = UNPACK_R(factors[i]);
+				od = UNPACK_OD(factors[i]);
+			}
+
+			/*
+			 * This is a case of double rounding. If we rounded up
+			 * above, we need to round down (in cases of ties) here.
+			 * This prevents off-by-one errors resulting from
+			 * choosing X+2 over X when X.Y rounds up to X+1 and
+			 * there is no r * od = X+1. For the converse, when X.Y
+			 * is rounded down to X, we should choose X+1 over X-1.
+			 */
+			err = abs(r * od - goal);
+			last_err = abs(last_r * last_od - goal);
+			if (last_err < err || (round_up && (last_err = err))) {
+				i--;
+				r = last_r;
+				od = last_od;
+			}
+		}
+
+		/*
+		 * Enforce limits on internal clock frequencies. If we
+		 * aren't in spec, try swapping r and od. If everything is
+		 * in-spec, calculate the relative error.
+		 */
+		while (true) {
+			/*
+			 * Whether the intermediate frequencies are out-of-spec
+			 */
+			bool out_of_spec = false;
+
+			if (r > max_r) {
+				out_of_spec = true;
+			} else {
+				/*
+				 * There is no way to only divide once; we need
+				 * to examine the frequency with and without the
+				 * effect of od.
+				 */
+				u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
+				if (vco > 1750000000 || vco < 340000000)
+					out_of_spec = true;
+			}
+
+			if (out_of_spec) {
+				if (!swapped) {
+					u64 tmp = r;
+					r = od;
+					od = tmp;
+					swapped = true;
+					continue;
+				} else {
+					/*
+					 * Try looking ahead to see if there are
+					 * additional factors for the same
+					 * product.
+					 */
+					if (i + 1 < ARRAY_SIZE(factors)) {
+						u64 new_r, new_od;
+
+						i++;
+						new_r = UNPACK_R(factors[i]);
+						new_od = UNPACK_OD(factors[i]);
+						if (r * od == new_r * new_od) {
+							r = new_r;
+							od = new_od;
+							swapped = false;
+							continue;
+						}
+						i--;
+					}
+					break;
+				}
+			}
+
+			error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
+			/* The lower 16 bits are spurious */
+			error = abs((error - BIT(32))) >> 16;
+
+			if (error < best_error) {
+				best->r = r;
+				best->f = f;
+				best->od = od;
+				best_error = error;
+			}
+			break;
+		}
+	} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
+
+	if (best_error == S64_MAX)
+		return -EINVAL;
+
+	log_debug("best error %lld\n", best_error);
+	return 0;
+}
+
+static ulong k210_pll_set_rate(struct clk *clk, ulong rate)
+{
+	int err;
+	long long rate_in = clk_get_parent_rate(clk);
+	struct k210_pll_params params = {};
+	struct k210_pll *pll = to_k210_pll(clk);
+	u32 reg;
+	
+	if (rate_in < 0)
+		return rate_in;
+
+	log_debug("Calculating parameters with rate=%lu and rate_in=%lld\n",
+		  rate, rate_in);
+	err = k210_pll_calc_params(rate, rate_in, &params);
+	if (err)
+		return err;
+	log_debug("Got r=%u f=%u od=%u\n", params.r, params.f, params.od);
+
+	/*
+	 * Don't use clk_disable as it might not actually disable the pll due to
+	 * refcounting
+	 */
+	err = k210_pll_disable(clk);
+	if (err)
+		return err;
+
+	reg = readl(pll->reg);
+	reg &= ~K210_PLL_CLKR
+	    & ~K210_PLL_CLKF
+	    & ~K210_PLL_CLKOD
+	    & ~K210_PLL_BWADJ;
+	reg |= FIELD_PREP(K210_PLL_CLKR, params.r - 1)
+	    | FIELD_PREP(K210_PLL_CLKF, params.f - 1)
+	    | FIELD_PREP(K210_PLL_CLKOD, params.od - 1)
+	    | FIELD_PREP(K210_PLL_BWADJ, params.f - 1);
+	writel(reg, pll->reg);
+
+	err = k210_pll_enable(clk);
+	if (err)
+		return err;
+
+	return clk_get_rate(clk);
+}
+#endif /* CONFIG_CLK_K210_SET_RATE */
+
+static ulong k210_pll_get_rate(struct clk *clk)
+{
+
+	long long rate_in = clk_get_parent_rate(clk);
+	struct k210_pll *pll = to_k210_pll(clk);
+	u64 r, f, od;
+	u32 reg = readl(pll->reg);
+
+	if (rate_in < 0)
+		return rate_in;
+
+	if (reg & K210_PLL_BYPASS)
+		return rate_in;
+	
+	r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
+	f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
+	od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
+
+	return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od);
+}
+
+/* Check if the PLL is locked */
+static inline int k210_pll_locked(struct k210_pll *pll)
+{
+	u32 reg = readl(pll->lock);
+
+	return (reg & pll->lock_mask) == pll->lock_mask;
+}
+
+/*
+ * Wait for the PLL to be locked. If the PLL is not locked, try clearing the
+ * slip before retrying
+ */
+static void k210_pll_waitfor_lock(struct k210_pll *pll)
+{
+	while (!k210_pll_locked(pll)) {
+		u32 reg = readl(pll->lock);
+
+		reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP);
+		writel(reg, pll->lock);
+	}
+}
+
+/* Adapted from sysctl_pll_enable */
+static int k210_pll_enable(struct clk *clk)
+{
+	struct k210_pll *pll = to_k210_pll(clk);
+	u32 reg = readl(pll->reg);
+
+	if ((reg | K210_PLL_PWRD) && !(reg | K210_PLL_RESET))
+		return 0;
+
+	reg |= K210_PLL_PWRD;
+	writel(reg, pll->reg);
+
+	/* Ensure reset is low before asserting it */
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+	reg |= K210_PLL_RESET;
+	writel(reg, pll->reg);
+	nop();
+	nop();
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+
+	k210_pll_waitfor_lock(pll);
+
+	reg &= ~K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	return 0;
+}
+
+static int k210_pll_disable(struct clk *clk)
+{
+	struct k210_pll *pll = to_k210_pll(clk);
+	u32 reg = readl(pll->reg);
+
+	/*
+	 * Bypassing before powering off is important so child clocks don't stop
+	 * working. This is especially important for pll0, the indirect parent
+	 * of the cpu clock.
+	 */
+	reg |= K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	reg &= ~K210_PLL_PWRD;
+	writel(reg, pll->reg);
+	return 0;
+}
+
+const struct clk_ops k210_pll_ops = {
+	.get_rate = k210_pll_get_rate,
+#ifdef CONFIG_CLK_K210_SET_RATE
+	.set_rate = k210_pll_set_rate,
+#endif
+	.enable = k210_pll_enable,
+	.disable = k210_pll_disable,
+};
+
+struct k210_pll *k210_clk_comp_pll(void __iomem *reg, void __iomem *lock,
+				       u8 shift, u8 width)
+{
+	struct k210_pll *pll;
+
+	
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return pll;
+	pll->reg = reg;
+	pll->lock = lock;
+	pll->shift = shift;
+	pll->lock_mask = GENMASK(width - 1, 0) << shift;
+	return pll;
+}
+
+struct clk *k210_clk_pll(const char *name, const char *parent_name,
+			 void __iomem *reg, void __iomem *lock, u8 shift,
+			 u8 width)
+{
+	int err;
+	struct k210_pll *pll;
+
+	pll = k210_clk_comp_pll(reg, lock, shift, width);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	err = clk_register(&pll->clk, CLK_K210_PLL, name, parent_name);
+	if (err) {
+		kfree(pll);
+		return ERR_PTR(err);
+	}
+	return &pll->clk;
+}
+
+U_BOOT_DRIVER(k210_pll) = {
+	.name	= CLK_K210_PLL,
+	.id	= UCLASS_CLK,
+	.ops	= &k210_pll_ops,
+};
diff --git a/drivers/clk/kendryte/pll.h b/drivers/clk/kendryte/pll.h
new file mode 100644
index 0000000000..21b000c7e6
--- /dev/null
+++ b/drivers/clk/kendryte/pll.h
@@ -0,0 +1,38 @@
+#ifndef K210_PLL_H
+#define K210_PLL_H
+
+#include <clk.h>
+
+#define K210_PLL_CLKR GENMASK(3, 0)
+#define K210_PLL_CLKF GENMASK(9, 4)
+#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */
+#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */
+#define K210_PLL_RESET BIT(20)
+#define K210_PLL_PWRD BIT(21) /* PoWeReD */
+#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */
+#define K210_PLL_BYPASS BIT(23)
+#define K210_PLL_TEST BIT(24)
+#define K210_PLL_EN BIT(25)
+#define K210_PLL_TEST_EN BIT(26)
+
+#define K210_PLL_LOCK 0
+#define K210_PLL_CLEAR_SLIP 2
+#define K210_PLL_TEST_OUT 3
+
+struct k210_pll {
+	struct clk clk;
+	void __iomem *reg; /* Base PLL register */
+	void __iomem *lock; /* Common PLL lock register */
+	u8 shift; /* Offset of bits in lock register */
+	u8 lock_mask; /* Mask of lock bits to test against, pre-shifted */
+};
+
+extern const struct clk_ops k210_pll_ops;
+
+struct k210_pll *k210_clk_comp_pll(void __iomem *reg, void __iomem *lock,
+				   u8 shift, u8 width);
+struct clk *k210_clk_pll(const char *name, const char *parent_name,
+			 void __iomem *reg, void __iomem *lock, u8 shift,
+			 u8 width);
+
+#endif /* K210_PLL_H */
-- 
2.25.0

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

* [PATCH v3 10/12] riscv: Add K210 clock support
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (8 preceding siblings ...)
  2020-02-02 20:07 ` [PATCH v3 09/12] riscv: Add K210 pll support Sean Anderson
@ 2020-02-02 20:07 ` Sean Anderson
  2020-02-06 21:51   ` Lukasz Majewski
  2020-02-02 20:10 ` [PATCH v3 11/12] riscv: Add device tree for K210 Sean Anderson
  2020-02-02 20:10 ` [PATCH v3 12/12] riscv: Add initial Sipeed Maix support Sean Anderson
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:07 UTC (permalink / raw)
  To: u-boot

Due to the large number of clocks, I decided to use the CCF. The overall
structure is modeled after the imx code. A common pattern is to create a
composite clock composed of several component clocks. For these component
clocks, the clk_register_* functions are not used, since they will be registered
as part of the composite clock. To create these component clocks, several helper
k210_clk_comp_* functions are used. This functionality seems like it would be
useful to other drivers also creating composite clocks, so perhaps some general
versions should be created. I am not particularly attached to the naming
convention, suggestions are welcome.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Removed sysctl struct, replacing it with defines. This is to have the same
    interface to sysctl from C as from the device tree.
  - Fixed clocks having the same id
  - Fixed clocks not using the correct register/bits
  - Aligned the defines in headers
  Changes for v2:
  - Add clk.o to obj-y
  - Don't probe before relocation

 drivers/clk/kendryte/Kconfig            |   2 +-
 drivers/clk/kendryte/Makefile           |   2 +-
 drivers/clk/kendryte/clk.c              | 390 ++++++++++++++++++++++++
 drivers/clk/kendryte/clk.h              |  27 ++
 include/dt-bindings/clock/k210-sysctl.h |  53 ++++
 include/dt-bindings/mfd/k210-sysctl.h   |  38 +++
 6 files changed, 510 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/kendryte/clk.c
 create mode 100644 drivers/clk/kendryte/clk.h
 create mode 100644 include/dt-bindings/clock/k210-sysctl.h
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h

diff --git a/drivers/clk/kendryte/Kconfig b/drivers/clk/kendryte/Kconfig
index 7b69c8afaf..073fca0781 100644
--- a/drivers/clk/kendryte/Kconfig
+++ b/drivers/clk/kendryte/Kconfig
@@ -1,6 +1,6 @@
 config CLK_K210
 	bool "Clock support for Kendryte K210"
-	depends on CLK && CLK_CCF
+	depends on CLK && CLK_CCF && CLK_COMPOSITE_CCF
 	help
 	  This enables support clock driver for Kendryte K210 platforms.
 
diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile
index c56d93ea1c..d26bce954f 100644
--- a/drivers/clk/kendryte/Makefile
+++ b/drivers/clk/kendryte/Makefile
@@ -1 +1 @@
-obj-y += pll.o
+obj-y += clk.o pll.o
diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c
new file mode 100644
index 0000000000..aaa7420c84
--- /dev/null
+++ b/drivers/clk/kendryte/clk.c
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+#include "clk.h"
+
+#include <asm/io.h>
+#include <dt-bindings/clock/k210-sysctl.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dm.h>
+#include <log.h>
+#include <mapmem.h>
+
+#include "pll.h"
+
+static ulong k210_clk_get_rate(struct clk *clk)
+{
+	struct clk *c;
+	int err = clk_get_by_id(clk->id, &c);
+
+	if (err)
+		return err;
+	return clk_get_rate(c);
+}
+
+static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *c;
+	int err = clk_get_by_id(clk->id, &c);
+
+	if (err)
+		return err;
+	return clk_set_rate(c, rate);
+}
+
+static int k210_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk *c, *p;
+	int err = clk_get_by_id(clk->id, &c);
+
+	if (err)
+		return err;
+	
+	err = clk_get_by_id(parent->id, &p);
+	if (err)
+		return err;
+
+	return clk_set_parent(c, p);
+}
+
+static int k210_clk_endisable(struct clk *clk, bool enable)
+{
+	struct clk *c;
+	int err = clk_get_by_id(clk->id, &c);
+
+	if (err)
+		return err;
+	return enable ? clk_enable(c) : clk_disable(c);
+}
+
+static int k210_clk_enable(struct clk *clk)
+{
+	return k210_clk_endisable(clk, true);
+}
+
+static int k210_clk_disable(struct clk *clk)
+{
+	return k210_clk_endisable(clk, false);
+}
+
+static const struct clk_ops k210_clk_ops = {
+	.set_rate = k210_clk_set_rate,
+	.get_rate = k210_clk_get_rate,
+	.set_parent = k210_clk_set_parent,
+	.enable = k210_clk_enable,
+	.disable = k210_clk_disable,
+};
+
+/* The first clock is in0, which is filled in by k210_clk_probe */
+static const char *generic_sels[] = { NULL, "pll0", };
+static const char *aclk_sels[] = { "in0_half", "pll0_half", };
+static const char *pll2_sels[] = { NULL, "pll0", "pll1", };
+
+static struct clk_divider *k210_clk_comp_div_flags(void __iomem *reg, u8 shift,
+						   u8 width, u8 flags)
+{
+	struct clk_divider *div;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return div;
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->flags = flags;
+	return div;
+}
+
+static inline struct clk_divider *k210_clk_comp_div(void __iomem *reg, u8 shift,
+						    u8 width)
+{
+	return k210_clk_comp_div_flags(reg, shift, width, 0);
+}
+
+static struct clk_gate *k210_clk_comp_gate(void __iomem *reg, u8 bit_idx)
+{
+	struct clk_gate *gate;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return gate;
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	return gate;
+}
+
+static struct clk_mux *k210_clk_comp_mux(const char *parent_names[],
+				         u8 num_parents, void __iomem *reg,
+				         u8 shift, u8 width)
+{
+	struct clk_mux *mux;
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return mux;
+	mux->reg = reg;
+	mux->mask = BIT(width) - 1;
+	mux->shift = shift;
+	mux->parent_names = parent_names;
+	mux->num_parents = num_parents;
+	return mux;
+}
+
+static struct clk *k210_clk_comp_nomux(const char *name, const char *parent,
+					 struct clk_divider *div,
+					 struct clk_gate *gate)
+{
+	if (!div || !gate) {
+		kfree(div);
+		kfree(gate);
+		return ERR_PTR(-ENOMEM);
+	}
+	return clk_register_composite(NULL, name, &parent, 1,
+				      NULL, NULL,
+				      &div->clk, &clk_divider_ops,
+				      &gate->clk, &clk_gate_ops, 0);
+}
+
+static struct clk *k210_clk_comp(const char *name, struct clk_divider *div,
+				 struct clk_gate *gate, struct clk_mux *mux)
+{
+	if (!div || !gate || !mux) {
+		kfree(div);
+		kfree(gate);
+		kfree(mux);
+		return ERR_PTR(-ENOMEM);
+	}
+	return clk_register_composite(NULL, name, generic_sels,
+				      ARRAY_SIZE(generic_sels),
+				      &mux->clk, &clk_mux_ops,
+				      &div->clk, &clk_divider_ops,
+				      &gate->clk, &clk_gate_ops, 0);
+}
+
+static int k210_clk_probe(struct udevice *dev)
+{
+	int err;
+	const char *in0;
+	struct clk in0_clk;
+	struct clk_divider *div;
+	struct clk_gate *gate;
+	struct clk_mux *mux;
+	struct k210_pll *pll;
+	void *base;
+
+	base = dev_read_addr_ptr(dev_get_parent(dev));
+	if (!base)
+		return -EINVAL;
+
+	err = clk_get_by_index(dev, 0, &in0_clk);
+	if (err)
+		goto cleanup_base;
+	in0 = in0_clk.dev->name;
+	generic_sels[0] = in0;
+	pll2_sels[0] = in0;
+
+	/* PLLs */
+	clk_dm(K210_CLK_PLL0, k210_clk_pll("pll0", in0, base + K210_SYSCTL_PLL0,
+					   base + K210_SYSCTL_PLL_LOCK, 0, 2));
+	clk_dm(K210_CLK_PLL1, k210_clk_pll("pll1", in0, base + K210_SYSCTL_PLL1,
+					   base + K210_SYSCTL_PLL_LOCK, 8, 1));
+	/* PLL2 is muxed, so set up a composite clock */
+	mux = k210_clk_comp_mux(pll2_sels, ARRAY_SIZE(pll2_sels),
+				base + K210_SYSCTL_PLL2, 26, 2);
+	pll = k210_clk_comp_pll(base + K210_SYSCTL_PLL2,
+				base + K210_SYSCTL_PLL_LOCK, 16, 1);
+	if (!mux || !pll) {
+		kfree(mux);
+		kfree(pll);
+	} else {
+		clk_dm(K210_CLK_PLL2,
+		       clk_register_composite(NULL, "pll2", pll2_sels,
+					      ARRAY_SIZE(pll2_sels),
+					      &mux->clk, &clk_mux_ops,
+					      &pll->clk, &k210_pll_ops,
+					      &pll->clk, &k210_pll_ops, 0));
+	}
+
+	/* Half-frequency clocks for "even" dividers */
+	k210_clk_half("in0_half", in0);
+	k210_clk_half("pll0_half", "pll0");
+	k210_clk_half("pll2_half", "pll2");
+
+	/* Muxed clocks */
+	div = k210_clk_comp_div_flags(base + K210_SYSCTL_SEL0, 1, 2,
+				      CLK_DIVIDER_POWER_OF_TWO);
+	mux = k210_clk_comp_mux(aclk_sels, ARRAY_SIZE(aclk_sels),
+				base + K210_SYSCTL_SEL0, 0, 1);
+	if (!div || !mux) {
+		kfree(div);
+		kfree(mux);
+	} else {
+		clk_dm(K210_CLK_ACLK,
+		       clk_register_composite(NULL, "aclk", aclk_sels,
+					      ARRAY_SIZE(aclk_sels),
+					      &mux->clk, &clk_mux_ops,
+					      &div->clk, &clk_divider_ops,
+					      NULL, NULL, 0));
+	}
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 1, 2);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 9);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				base + K210_SYSCTL_SEL0, 12, 1);
+	clk_dm(K210_CLK_SPI3, k210_clk_comp("spi3", div, gate, mux));
+	
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 0);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 21);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				base + K210_SYSCTL_SEL0, 13, 1);
+	clk_dm(K210_CLK_TIMER0, k210_clk_comp("timer0", div, gate, mux));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 22);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				base + K210_SYSCTL_SEL0, 14, 1);
+	clk_dm(K210_CLK_TIMER1, k210_clk_comp("timer1", div, gate, mux));
+	
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 16);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 23);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				base + K210_SYSCTL_SEL0, 15, 1);
+	clk_dm(K210_CLK_TIMER2, k210_clk_comp("timer2", div, gate, mux));
+
+
+	/* Dividing clocks, no mux */
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 0, 4);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 1);
+	clk_dm(K210_CLK_SRAM0, k210_clk_comp_nomux("sram0", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 4, 4);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 2);
+	clk_dm(K210_CLK_SRAM1, k210_clk_comp_nomux("sram1", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 16, 4);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 0);
+	clk_dm(K210_CLK_ROM, k210_clk_comp_nomux("rom", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 12, 4);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 3);
+	clk_dm(K210_CLK_DVP, k210_clk_comp_nomux("dvp", "aclk", div, gate));
+
+	/*
+	 * XXX: the next three clocks may be using an even divider
+	 * c.f. <https://github.com/kendryte/kendryte-standalone-sdk/issues/99>
+	 */
+	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 3, 3);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 3);
+	clk_dm(K210_CLK_APB0, k210_clk_comp_nomux("apb0", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 6, 3);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 4);
+	clk_dm(K210_CLK_APB1, k210_clk_comp_nomux("apb1", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 9, 3);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 5);
+	clk_dm(K210_CLK_APB2, k210_clk_comp_nomux("apb2", "aclk", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 8, 4);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 2);
+	clk_dm(K210_CLK_AI, k210_clk_comp_nomux("ai", "pll1", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR3, 0, 16);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 10);
+	clk_dm(K210_CLK_I2S0,
+	       k210_clk_comp_nomux("i2s0", "pll2_half", div, gate));
+	
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR3, 16, 16);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 11);
+	clk_dm(K210_CLK_I2S1,
+	       k210_clk_comp_nomux("i2s1", "pll2_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR4, 0, 16);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 12);
+	clk_dm(K210_CLK_I2S2,
+	       k210_clk_comp_nomux("i2s2", "pll2_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR6, 0, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 24);
+	clk_dm(K210_CLK_WDT0,
+	       k210_clk_comp_nomux("wdt0", "in0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR6, 8, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 25);
+	clk_dm(K210_CLK_WDT1,
+	       k210_clk_comp_nomux("wdt1", "in0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 0, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 6);
+	clk_dm(K210_CLK_SPI0,
+	       k210_clk_comp_nomux("spi0", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 8, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 7);
+	clk_dm(K210_CLK_SPI1,
+	       k210_clk_comp_nomux("spi1", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 16, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 8);
+	clk_dm(K210_CLK_SPI2,
+	       k210_clk_comp_nomux("spi2", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 8, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 13);
+	clk_dm(K210_CLK_I2C0,
+	       k210_clk_comp_nomux("i2c0", "pll0_half", div, gate));
+	
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 16, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 14);
+	clk_dm(K210_CLK_I2C1,
+	       k210_clk_comp_nomux("i2c1", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 24, 8);
+	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 15);
+	clk_dm(K210_CLK_I2C2,
+	       k210_clk_comp_nomux("i2c2", "pll0_half", div, gate));
+
+	/* Gated clocks */
+	clk_dm(K210_CLK_CPU,
+	       k210_clk_gate("cpu", "aclk", base + K210_SYSCTL_EN_CENT, 0));
+	clk_dm(K210_CLK_DMA,
+	       k210_clk_gate("dma", "aclk", base + K210_SYSCTL_EN_PERI, 1));
+	clk_dm(K210_CLK_FFT,
+	       k210_clk_gate("fft", "aclk", base + K210_SYSCTL_EN_PERI, 4));
+	clk_dm(K210_CLK_GPIO,
+	       k210_clk_gate("gpio", "apb0", base + K210_SYSCTL_EN_PERI, 5));
+	clk_dm(K210_CLK_UART1,
+	       k210_clk_gate("uart1", "apb0", base + K210_SYSCTL_EN_PERI, 16));
+	clk_dm(K210_CLK_UART2,
+	       k210_clk_gate("uart2", "apb0", base + K210_SYSCTL_EN_PERI, 17));
+	clk_dm(K210_CLK_UART3,
+	       k210_clk_gate("uart3", "apb0", base + K210_SYSCTL_EN_PERI, 18));
+	clk_dm(K210_CLK_FPIOA,
+	       k210_clk_gate("fpioa", "apb0", base + K210_SYSCTL_EN_PERI, 20));
+	clk_dm(K210_CLK_SHA,
+	       k210_clk_gate("sha", "apb0", base + K210_SYSCTL_EN_PERI, 26));
+	clk_dm(K210_CLK_AES,
+	       k210_clk_gate("aes", "apb1", base + K210_SYSCTL_EN_PERI, 19));
+	clk_dm(K210_CLK_OTP,
+	       k210_clk_gate("otp", "apb1", base + K210_SYSCTL_EN_PERI, 27));
+	clk_dm(K210_CLK_RTC,
+	       k210_clk_gate("rtc", in0, base + K210_SYSCTL_EN_PERI, 29));
+
+cleanup_base:
+	unmap_sysmem(base);
+	return err;
+}
+
+static const struct udevice_id k210_clk_ids[] = {
+	{ .compatible = "kendryte,k210-clk" },
+	{ },
+};
+
+U_BOOT_DRIVER(k210_clk) = {
+	.name = "k210_clk",
+	.id = UCLASS_CLK,
+	.of_match = k210_clk_ids,
+	.ops = &k210_clk_ops,
+	.probe = k210_clk_probe,
+};
diff --git a/drivers/clk/kendryte/clk.h b/drivers/clk/kendryte/clk.h
new file mode 100644
index 0000000000..17d0f5de1b
--- /dev/null
+++ b/drivers/clk/kendryte/clk.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef K210_CLK_H
+#define K210_CLK_H
+
+#define LOG_CATEGORY UCLASS_CLK
+#include <linux/types.h>
+#include <linux/clk-provider.h>
+
+static inline struct clk *k210_clk_gate(const char *name,
+					const char *parent_name,
+					void __iomem *reg, u8 bit_idx)
+{
+	return clk_register_gate(NULL, name, parent_name, 0, reg, bit_idx, 0,
+				 NULL);
+}
+
+static inline struct clk *k210_clk_half(const char *name,
+				        const char *parent_name)
+{
+	return clk_register_fixed_factor(NULL, name, parent_name, 0, 1, 2);
+}
+
+#endif /* K210_CLK_H */
diff --git a/include/dt-bindings/clock/k210-sysctl.h b/include/dt-bindings/clock/k210-sysctl.h
new file mode 100644
index 0000000000..7c471f9893
--- /dev/null
+++ b/include/dt-bindings/clock/k210-sysctl.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef CLOCK_K210_SYSCTL_H
+#define CLOCK_K210_SYSCTL_H
+
+/*
+ * Arbitrary identifiers for clocks. 0 is unused since clk_enable thinks it
+ * means "no clock".
+ */
+#define K210_CLK_PLL0   1
+#define K210_CLK_PLL1   2
+#define K210_CLK_PLL2   3
+#define K210_CLK_CPU    4
+#define K210_CLK_SRAM0  5
+#define K210_CLK_SRAM1  6
+#define K210_CLK_APB0   7
+#define K210_CLK_APB1   8
+#define K210_CLK_APB2   9
+#define K210_CLK_ROM    10
+#define K210_CLK_DMA    11
+#define K210_CLK_AI     12
+#define K210_CLK_DVP    13
+#define K210_CLK_FFT    14
+#define K210_CLK_GPIO   15
+#define K210_CLK_SPI0   16
+#define K210_CLK_SPI1   17
+#define K210_CLK_SPI2   18
+#define K210_CLK_SPI3   19
+#define K210_CLK_I2S0   20
+#define K210_CLK_I2S1   21
+#define K210_CLK_I2S2   22
+#define K210_CLK_I2C0   23
+#define K210_CLK_I2C1   24
+#define K210_CLK_I2C2   25
+#define K210_CLK_UART1  26
+#define K210_CLK_UART2  27
+#define K210_CLK_UART3  28
+#define K210_CLK_AES    29
+#define K210_CLK_FPIOA  30
+#define K210_CLK_TIMER0 31
+#define K210_CLK_TIMER1 32
+#define K210_CLK_TIMER2 33
+#define K210_CLK_WDT0   34
+#define K210_CLK_WDT1   35
+#define K210_CLK_SHA    36
+#define K210_CLK_OTP    37
+#define K210_CLK_RTC    40
+#define K210_CLK_ACLK   41
+
+#endif /* CLOCK_K210_SYSCTL_H */
diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
new file mode 100644
index 0000000000..3457240f03
--- /dev/null
+++ b/include/dt-bindings/mfd/k210-sysctl.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef K210_SYSCTL_H
+#define K210_SYSCTL_H
+ 
+/* Taken from kendryte-standalone-sdk/lib/drivers/include/sysctl.h */
+#define K210_SYSCTL_GIT_ID     0x00 /* Git short commit id */
+#define K210_SYSCTL_CLK_FREQ   0x04 /* System clock base frequency */
+#define K210_SYSCTL_PLL0       0x08 /* PLL0 controller */
+#define K210_SYSCTL_PLL1       0x0C /* PLL1 controller */
+#define K210_SYSCTL_PLL2       0x10 /* PLL2 controller */
+#define K210_SYSCTL_PLL_LOCK   0x18 /* PLL lock tester */
+#define K210_SYSCTL_ROM_ERROR  0x1C /* AXI ROM detector */
+#define K210_SYSCTL_SEL0       0x20 /* Clock select controller0 */
+#define K210_SYSCTL_SEL1       0x24 /* Clock select controller1 */
+#define K210_SYSCTL_EN_CENT    0x28 /* Central clock enable */
+#define K210_SYSCTL_EN_PERI    0x2C /* Peripheral clock enable */
+#define K210_SYSCTL_SOFT_RESET 0x30 /* Soft reset ctrl */
+#define K210_SYSCTL_PERI_RESET 0x34 /* Peripheral reset controller */
+#define K210_SYSCTL_THR0       0x38 /* Clock threshold controller 0 */
+#define K210_SYSCTL_THR1       0x3C /* Clock threshold controller 1 */
+#define K210_SYSCTL_THR2       0x40 /* Clock threshold controller 2 */
+#define K210_SYSCTL_THR3       0x44 /* Clock threshold controller 3 */
+#define K210_SYSCTL_THR4       0x48 /* Clock threshold controller 4 */
+#define K210_SYSCTL_THR5       0x4C /* Clock threshold controller 5 */
+#define K210_SYSCTL_THR6       0x50 /* Clock threshold controller 6 */
+#define K210_SYSCTL_MISC       0x54 /* Miscellaneous controller */
+#define K210_SYSCTL_PERI       0x58 /* Peripheral controller */
+#define K210_SYSCTL_SPI_SLEEP  0x5C /* SPI sleep controller */
+#define K210_SYSCTL_RESET_STAT 0x60 /* Reset source status */
+#define K210_SYSCTL_DMA_SEL0   0x64 /* DMA handshake selector */
+#define K210_SYSCTL_DMA_SEL1   0x68 /* DMA handshake selector */
+#define K210_SYSCTL_POWER_SEL  0x6C /* IO Power Mode Select controller */
+
+#endif /* K210_SYSCTL_H */
-- 
2.25.0

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

* [PATCH v3 11/12] riscv: Add device tree for K210
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (9 preceding siblings ...)
  2020-02-02 20:07 ` [PATCH v3 10/12] riscv: Add K210 clock support Sean Anderson
@ 2020-02-02 20:10 ` Sean Anderson
  2020-02-04 11:32   ` Bin Meng
  2020-02-02 20:10 ` [PATCH v3 12/12] riscv: Add initial Sipeed Maix support Sean Anderson
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:10 UTC (permalink / raw)
  To: u-boot

Where possible, I have tried to find compatible drivers based on the layout of
registers. However, I have not tested most of this functionality, and most
devices should be considered descriptive at best. I would appreciate if anyone
could help identify possibly compatible devices, especially for the timers
and rtc.

Should the size of a reg be the size of the documented registers, or the size
of the address space which will be routed to that device?

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Move this patch to the end of the series
  - Add a max frequency for spi3
  - Remov unused compatible strings from spi-flash at 0
  - Add s and u to isa string
  - Fix mmu-type
  - Remove cache-line size since it is unused (in u-boot) and undocumented
    (upstream)
  - Add timer interrupts to clint0
  - Round up various registers
  - Add riscv,max-priority to plic
  - Add apb* busses, since they have clocks which need to be enabled to access
    their devices
  - Change uart compatible strings to "snps,dw-apb-uart", since that appears to
    match their registers
  - Add compatible string for wdt*
  - Add system reset device under sysctl
  - Add reset device under sysctl
  Changes for v2:
  - Model changed to "Sipeed Maix Bit" to match file name
  - Value of stdout-path fixed
  - SD card slot compatible changed to "mmc-spi-slot"
  - "jedec,spi-nor" added to spi flash compatible list
  - Aliases for spi busses added
  - timebase-frequency divided by 50 to match timer speed
  - cpu-frequency renamed to clock-frequency
  - CPUX_intc restyled to cpuX_intc
  - "kendryte,k210-soc" added to soc compatible list for future-proofing
  - PLIC handle renamed to plic0 from pic0
  - K210_RST_SOC removed from sysrst, due to not being located in the
    reset register
  - K210_RST_* numbers changed to match their bit offset within the reset
    register
  - gpio_controller restyled to gpio-controller
  - Added a second clock to the dma binding to match what the driver expects
  - Changed "snps,designware-spi" compatible string to "snps,dw-apb-ssi" to
    match the correct driver
  - Added a name to the spi clocks
  - Added reg-io-width property to spi bindings
  - Assigned a default parent to K210_CLK_SPI3
  - Removed assigned clocks for ACLK and PLLs
  - Removed u-boot,dm-pre-reloc bindings

 arch/riscv/dts/Makefile                 |   1 +
 arch/riscv/dts/k210-maix-bit.dts        |  42 ++
 arch/riscv/dts/k210.dtsi                | 496 ++++++++++++++++++++++++
 include/dt-bindings/reset/k210-sysctl.h |  38 ++
 4 files changed, 577 insertions(+)
 create mode 100644 arch/riscv/dts/k210-maix-bit.dts
 create mode 100644 arch/riscv/dts/k210.dtsi
 create mode 100644 include/dt-bindings/reset/k210-sysctl.h

diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 4f30e6936f..3a6f96c67d 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -2,6 +2,7 @@
 
 dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
 dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb
+dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts
new file mode 100644
index 0000000000..10f36921e0
--- /dev/null
+++ b/arch/riscv/dts/k210-maix-bit.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+/ {
+	model = "Sipeed Maix Bit";
+	compatible = "sipeed,maix-bit", "kendryte,k210";
+
+	chosen {
+		stdout-path = "serial0:115200";
+	};
+};
+
+&uarths0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	slot at 0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		broken-cd;
+		disable-wp;
+	};
+};
+
+&spi3 {
+	status = "okay";
+	spi-max-frequency = <120000000>;
+	spi-flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <120000000>;
+		m25p,fast-read;
+	};
+};
diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
new file mode 100644
index 0000000000..cc46b692e6
--- /dev/null
+++ b/arch/riscv/dts/k210.dtsi
@@ -0,0 +1,496 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <dt-bindings/clock/k210-sysctl.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dt-bindings/reset/k210-sysctl.h>
+
+/ {
+	/*
+	 * Although the K210 is a 64-bit CPU, the address bus is only 32-bits
+	 * wide, and the upper half of all addresses is ignored.
+	 */
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "kendryte,k210";
+
+	aliases {
+		serial0 = &uarths0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+	};
+
+	clocks {
+		in0: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		timebase-frequency = <7800000>;
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			reg = <0>;
+			compatible = "riscv";
+			riscv,isa = "rv64acdfimsu";
+			mmu-type = "sv39";
+			i-cache-size = <0x8000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			clock-frequency = <390000000>;
+			cpu0_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			reg = <1>;
+			compatible = "riscv";
+			riscv,isa = "rv64acdfimsu";
+			mmu-type = "sv39";
+			i-cache-size = <0x8000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			clock-frequency = <390000000>;
+			cpu1_intc: interrupt-controller {
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+			};
+		};
+	};
+
+	sram0: memory at 80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x400000>;
+		clocks = <&sysclk K210_CLK_SRAM0>;
+	};
+
+	sram1: memory at 80400000 {
+		device_type = "memory";
+		reg = <0x80400000 0x400000>;
+		clocks = <&sysclk K210_CLK_SRAM1>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ai_reserved: ai at 80600000 {
+			reg = <0x80600000 0x200000>;
+			reusable;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "kendryte,k210-soc", "simple-bus";
+		ranges;
+		interrupt-parent = <&plic0>;
+
+		clint0: interrupt-controller at 2000000 {
+			compatible = "riscv,clint0";
+			reg = <0x2000000 0x1000>;
+			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
+			                      <&cpu1_intc 3>, <&cpu1_intc 7>;
+			clocks = <&sysclk K210_CLK_CPU>;
+		};
+
+		plic0: interrupt-controller at c000000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "kendryte,k210-plic", "riscv,plic1";
+			reg = <0xC000000 0x4000000>;
+			interrupts-extended = <&cpu0_intc 9>, <&cpu0_intc 11>,
+			                      <&cpu1_intc 9>, <&cpu1_intc 11>;
+			riscv,ndev = <65>;
+			riscv,max-priority = <7>;
+		};
+
+		uarths0: serial at 38000000 {
+			compatible = "sifive,uart0";
+			reg = <0x38000000 0x20>;
+			interrupts = <33>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			status = "disabled";
+		};
+
+		gpio0: gpio-controller at 38001000 {
+			#gpio-cells = <2>;
+			compatible = "none";
+			reg = <0x38001000 0x80>;
+			gpio-controller;
+			interrupts = <34 35 36 37 38 39 40 41
+			              42 43 44 45 46 47 48 49
+			              50 51 52 53 54 55 56 57
+				      58 59 60 61 62 63 64 65>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			status = "disabled";
+		};
+
+		kpu0: kpu at 40600000 {
+			compatible = "none";
+			reg = <0x40800000 0x80>;
+			interrupts = <25>;
+			clocks = <&sysclk K210_CLK_AI>;
+			memory-region = <&ai_reserved>;
+			status = "disabled";
+		};
+
+		fft0: fft at 42000000 {
+			compatible = "none";
+			reg = <0x42000000 0x400000>;
+			interrupts = <26>;
+			clocks = <&sysclk K210_CLK_FFT>;
+			resets = <&sysrst K210_RST_FFT>;
+			status = "disabled";
+		};
+
+		dmac0: dma-controller at 50000000 {
+			compatible = "snps,axi-dma-1.01a";
+			reg = <0x50000000 0x1000>;
+			interrupts = <27 28 29 30 31 32>;
+			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
+			clock-names = "core-clk", "cfgr-clk";
+			resets = <&sysrst K210_RST_DMA>;
+			dma-channels = <6>;
+			snps,dma-masters = <2>;
+			snps,data-width = <5>;
+			snps,block-size = <0x400000 0x400000 0x400000
+			                   0x400000 0x400000 0x400000>;
+			snps,axi-max-burst-len = <256>;
+			status = "disabled";
+		};
+
+		apb0: bus at 50200000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB0>;
+
+			gpio1: gpio-controller at 50200000 {
+				#gpio-cells = <2>;
+				compatible = "none";
+				reg = <0x50200000 0x80>;
+				gpio-controller;
+				interrupts = <23>;
+				clocks = <&sysclk K210_CLK_GPIO>;
+				resets = <&sysrst K210_RST_GPIO>;
+				status = "disabled";
+			};
+
+			uart1: serial at 50210000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <50210000 0x100>;
+				interrupts = <11>;
+				clocks = <&sysclk K210_CLK_UART1>;
+				resets = <&sysrst K210_RST_UART1>;
+				reg-io-width = <4>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart2: serial at 50220000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <50220000 0x100>;
+				interrupts = <12>;
+				clocks = <&sysclk K210_CLK_UART2>;
+				resets = <&sysrst K210_RST_UART2>;
+				reg-io-width = <4>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart3: serial at 50230000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <50230000 0x100>;
+				interrupts = <13>;
+				clocks = <&sysclk K210_CLK_UART3>;
+				resets = <&sysrst K210_RST_UART3>;
+				reg-io-width = <4>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			spi2: spi at 50240000 {
+				compatible = "snps,dw-apb-ssi";
+				spi-slave;
+				reg = <0x50240000 0x120>;
+				interrupts = <2>;
+				clocks = <&sysclk K210_CLK_SPI2>;
+				resets = <&sysrst K210_RST_SPI2>;
+				status = "disabled";
+			};
+
+			i2s0: i2s at 50250000 {
+				compatible = "snps,designware-i2s";
+				reg = <0x50250000 0x200>;
+				interrupts = <5>;
+				clocks = <&sysclk K210_CLK_I2S0>;
+				resets = <&sysrst K210_RST_I2S0>;
+				status = "disabled";
+			};
+
+			apu0: sound at 520250200 {
+				compatible = "none";
+				reg = <0x50250200 0x140>;
+				status = "disabled";
+			};
+
+			i2s1: i2s at 50260000 {
+				compatible = "snps,designware-i2s";
+				reg = <0x50260000 0x200>;
+				interrupts = <6>;
+				clocks = <&sysclk K210_CLK_I2S1>;
+				resets = <&sysrst K210_RST_I2S1>;
+				status = "disabled";
+			};
+
+			i2s2: i2s at 50270000 {
+				compatible = "snps,designware-i2s";
+				reg = <0x50270000 0x200>;
+				interrupts = <7>;
+				clocks = <&sysclk K210_CLK_I2S2>;
+				resets = <&sysrst K210_RST_I2S2>;
+				status = "disabled";
+			};
+
+			i2c0: i2c at 50280000 {
+				compatible = "snps,designware-i2c";
+				reg = <0x50280000 0x100>;
+				interrupts = <8>;
+				clocks = <&sysclk K210_CLK_I2C0>;
+				resets = <&sysrst K210_RST_I2C0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c at 50290000 {
+				compatible = "snps,designware-i2c";
+				reg = <0x50290000 0x100>;
+				interrupts = <9>;
+				clocks = <&sysclk K210_CLK_I2C1>;
+				resets = <&sysrst K210_RST_I2C1>;
+				status = "disabled";
+			};
+
+
+			i2c2: i2c at 502A0000 {
+				compatible = "snps,designware-i2c";
+				reg = <0x502A0000 0x100>;
+				interrupts = <10>;
+				clocks = <&sysclk K210_CLK_I2C2>;
+				resets = <&sysrst K210_RST_I2C2>;
+				status = "disabled";
+			};
+
+			fpioa: pinmux at 502B0000 {
+				#pinctrl-cells = <1>;
+				compatible = "none";
+				reg = <0x502B0000 0x100>;
+				clocks = <&sysclk K210_CLK_FPIOA>;
+				resets = <&sysrst K210_RST_FPIOA>;
+				status = "disabled";
+			};
+
+			sha256: sha256 at 502C0000 {
+				compatible = "none";
+				reg = <0x502C0000 0x40>;
+				clocks = <&sysclk K210_CLK_SHA>;
+				resets = <&sysrst K210_RST_SHA>;
+				status = "disabled";
+			};
+
+			timer0: timer at 502D0000 {
+				compatible = "none";
+				reg = <0x502D0000 0x100>;
+				interrupts = <14 15>;
+				clocks = <&sysclk K210_CLK_TIMER0>;
+				resets = <&sysrst K210_RST_TIMER0>;
+				status = "disabled";
+			};
+
+			timer1: timer at 502E0000 {
+				compatible = "none";
+				reg = <0x502E0000 0x100>;
+				interrupts = <16 17>;
+				clocks = <&sysclk K210_CLK_TIMER1>;
+				resets = <&sysrst K210_RST_TIMER1>;
+				status = "disabled";
+			};
+
+			timer2: timer at 502F0000 {
+				compatible = "none";
+				reg = <0x502F0000 0x100>;
+				interrupts = <18 19>;
+				clocks = <&sysclk K210_CLK_TIMER2>;
+				resets = <&sysrst K210_RST_TIMER2>;
+				status = "disabled";
+			};
+		};
+
+		apb1: bus at 50400000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB1>;
+		
+			wdt0: watchdog at 50400000 {
+				compatible = "snps,dw-wdt";
+				reg = <0x50400000 0x100>;
+				interrupts = <21>;
+				clocks = <&sysclk K210_CLK_WDT0>;
+				resets = <&sysrst K210_RST_WDT0>;
+				status = "disabled";
+			};
+
+			wdt1: watchdog at 50410000 {
+				compatible = "snps,dw-wdt";
+				reg = <0x50410000 0x100>;
+				interrupts = <22>;
+				clocks = <&sysclk K210_CLK_WDT1>;
+				resets = <&sysrst K210_RST_WDT1>;
+				status = "disabled";
+			};
+
+			dvp0: camera at 50430000 {
+				compatible = "none";
+				reg = <0x50430000 0x30>;
+				interrupts = <24>;
+				clocks = <&sysclk K210_CLK_DVP>;
+				resets = <&sysrst K210_RST_DVP>;
+				status = "disabled";
+			};
+
+			sysctl: sysctl at 50440000 {
+				compatible = "kendryte,k210-sysctl",
+					     "syscon", "simple-mfd";
+				reg = <0x50440000 0x80>;
+				reg-io-width = <4>;
+
+				sysclk: clock-controller {
+					compatible = "kendryte,k210-clk";
+					clocks = <&in0>;
+					#clock-cells = <1>;
+				};
+
+				sysrst: reset-controller {
+					compatible = "kendryte,k210-rst",
+						     "syscon-reset";
+					#reset-cells = <1>;
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_PERI_RESET>;
+					mask = <0x27FFFFFF>;
+					assert-high = <1>;
+				};
+
+				reboot {
+					compatible = "syscon-reboot";
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_SOFT_RESET>;
+					mask = <1>;
+					value = <1>;
+				};
+			};
+
+			aes0: aes at 50450000 {
+				compatible = "none";
+				reg = <0x50450000 0x100>;
+				clocks = <&sysclk K210_CLK_AES>;
+				resets = <&sysrst K210_RST_AES>;
+				status = "disabled";
+			};
+
+			rtc: rts at 50460000 {
+				compatible = "none";
+				reg = <0x50460000 0x30>;
+				clocks = <&in0>;
+				resets = <&sysrst K210_RST_RTC>;
+				interrupts = <20>;
+				status = "disabled";
+			};
+		};
+
+		apb2: bus at 52000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB2>;
+
+			spi0: spi at 52000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "snps,dw-apb-ssi";
+				reg = <0x52000000 0x120>;
+				interrupts = <1>;
+				clocks = <&sysclk K210_CLK_SPI0>;
+				clock-names = "ssi_clk";
+				resets = <&sysrst K210_RST_SPI0>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi1: spi at 53000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "snps,dw-apb-ssi";
+				reg = <0x53000000 0x120>;
+				interrupts = <2>;
+				clocks = <&sysclk K210_CLK_SPI1>;
+				clock-names = "ssi_clk";
+				resets = <&sysrst K210_RST_SPI1>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi3: spi at 54000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "snps,dw-apb-ssi";
+				reg = <0x54000000 0x120>;
+				interrupts = <4>;
+				clocks = <&sysclk K210_CLK_SPI3>;
+				clock-names = "ssi_clk";
+				resets = <&sysrst K210_RST_SPI3>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+		};
+
+		rom0: nvmem at 88000000 {
+			reg = <0x88000000 0x4000>;
+			read-only;
+			clocks = <&sysclk K210_CLK_ROM>;
+			resets = <&sysrst K210_RST_ROM>;
+		};
+	};
+};
diff --git a/include/dt-bindings/reset/k210-sysctl.h b/include/dt-bindings/reset/k210-sysctl.h
new file mode 100644
index 0000000000..670e74daaf
--- /dev/null
+++ b/include/dt-bindings/reset/k210-sysctl.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef RESET_K210_SYSCTL_H
+#define RESET_K210_SYSCTL_H
+
+#define K210_RST_ROM 0	
+#define K210_RST_DMA 1	
+#define K210_RST_AI 2	
+#define K210_RST_DVP 3	
+#define K210_RST_FFT 4	
+#define K210_RST_GPIO 5	
+#define K210_RST_SPI0 6	
+#define K210_RST_SPI1 7	
+#define K210_RST_SPI2 8	
+#define K210_RST_SPI3 9	
+#define K210_RST_I2S0 10	
+#define K210_RST_I2S1 11	
+#define K210_RST_I2S2 12	
+#define K210_RST_I2C0 13	
+#define K210_RST_I2C1 14	
+#define K210_RST_I2C2 15	
+#define K210_RST_UART1 16	
+#define K210_RST_UART2 17	
+#define K210_RST_UART3 18	
+#define K210_RST_AES 19	
+#define K210_RST_FPIOA 20	
+#define K210_RST_TIMER0 21	
+#define K210_RST_TIMER1 22	
+#define K210_RST_TIMER2 23	
+#define K210_RST_WDT0 24	
+#define K210_RST_WDT1 25	
+#define K210_RST_SHA 26	
+#define K210_RST_RTC 29	
+
+#endif /* RESET_K210_SYSCTL_H */
-- 
2.25.0

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

* [PATCH v3 12/12] riscv: Add initial Sipeed Maix support
  2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
                   ` (10 preceding siblings ...)
  2020-02-02 20:10 ` [PATCH v3 11/12] riscv: Add device tree for K210 Sean Anderson
@ 2020-02-02 20:10 ` Sean Anderson
  2020-02-04 11:38   ` Bin Meng
  11 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-02 20:10 UTC (permalink / raw)
  To: u-boot

The Sipeed Maix series is a collection of boards built around the RISC-V
Kendryte K210 processor. This processor contains several peripherals to
accelerate neural network processing and other "ai" tasks. This includes a "KPU"
neural network processor, an audio processor supporting beamforming reception,
and a digital video port supporting capture and output at VGA resolution. Other
peripherals include 8M of sram (accessible with and without caching);
remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA
controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but
include spi flash; on-board usb-serial bridges; ports for cameras, displays, and
sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is
supported, but the boards are fairly similar.

Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
Documentation for the Kendryte K210 is located at
<https://kendryte.com/downloads/>. However, hardware details are rather lacking,
so most technical reference has been taken from the standalone sdk located at
<https://github.com/kendryte/kendryte-standalone-sdk>.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
  Changes for v3:
  - Reorder to be last in the patch series
  - Add documentation for the board
  - Generate defconfig with "make savedefconfig"
  - Update Kconfig to imply most features we need
  - Update MAINTAINERS
  Changes for v2:
  - Select CONFIG_SYS_RISCV_NOCOUNTER
  - Imply CONFIG_CLK_K210
  - Remove spurious references to CONFIG_ARCH_K210
  - Remove many configs from defconfig where the defaults were fine
  - Add a few "not set" lines to suppress unneeded defaults
  - Reduce pre-reloc malloc space, now that clocks initialization happens later

 arch/riscv/Kconfig                 |  4 +++
 board/sipeed/maix/Kconfig          | 51 ++++++++++++++++++++++++++++++
 board/sipeed/maix/MAINTAINERS      | 10 ++++++
 board/sipeed/maix/Makefile         |  5 +++
 board/sipeed/maix/maix.c           |  9 ++++++
 configs/sipeed_maix_bitm_defconfig | 10 ++++++
 doc/board/index.rst                |  1 +
 doc/board/kendryte/index.rst       |  9 ++++++
 doc/board/kendryte/k210.rst        | 46 +++++++++++++++++++++++++++
 include/configs/sipeed-maix.h      | 19 +++++++++++
 10 files changed, 164 insertions(+)
 create mode 100644 board/sipeed/maix/Kconfig
 create mode 100644 board/sipeed/maix/MAINTAINERS
 create mode 100644 board/sipeed/maix/Makefile
 create mode 100644 board/sipeed/maix/maix.c
 create mode 100644 configs/sipeed_maix_bitm_defconfig
 create mode 100644 doc/board/kendryte/index.rst
 create mode 100644 doc/board/kendryte/k210.rst
 create mode 100644 include/configs/sipeed-maix.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 87c40f6c4c..81ab35dd2d 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT
 config TARGET_SIFIVE_FU540
 	bool "Support SiFive FU540 Board"
 
+config TARGET_SIPEED_MAIX
+	bool "Support Sipeed Maix Board"
+
 endchoice
 
 config SYS_ICACHE_OFF
@@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig"
 source "board/emulation/qemu-riscv/Kconfig"
 source "board/microchip/mpfs_icicle/Kconfig"
 source "board/sifive/fu540/Kconfig"
+source "board/sipeed/maix/Kconfig"
 
 # platform-specific options below
 source "arch/riscv/cpu/ax25/Kconfig"
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
new file mode 100644
index 0000000000..b23d2448d9
--- /dev/null
+++ b/board/sipeed/maix/Kconfig
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+
+if TARGET_SIPEED_MAIX
+
+config SYS_BOARD
+	default "maix"
+
+config SYS_VENDOR
+	default "sipeed"
+
+config SYS_CPU
+	default "generic"
+
+config SYS_CONFIG_NAME
+	default "sipeed-maix"
+
+config SYS_TEXT_BASE
+	default 0x80000000
+
+config DEFAULT_DEVICE_TREE
+	default "k210-maix-bit"
+
+config NR_CPUS
+	default 2
+
+config NR_DRAM_BANKS
+	default 2
+
+config BOARD_SPECIFIC_OPTIONS
+	def_bool y
+	select GENERIC_RISCV
+	select RISCV_PRIV_1_9_1
+	imply DM_SERIAL
+	imply SIFIVE_SERIAL
+	imply SIFIVE_CLINT
+	imply CLK_CCF
+	imply CLK_COMPOSITE_CCF
+	imply CLK_K210
+	imply DM_RESET
+	imply RESET_SYSCON
+	imply SYSRESET
+	imply SYSRESET_SYSCON
+	imply SPI
+	imply DESIGNWARE_SPI
+	imply SPI_FLASH_GIGADEVICE
+	imply MMC
+	imply MMC_SPI
+	imply MMC_BROKEN_CD
+	imply CMD_MMC
+endif
diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
new file mode 100644
index 0000000000..43cf61fb64
--- /dev/null
+++ b/board/sipeed/maix/MAINTAINERS
@@ -0,0 +1,10 @@
+Sipeed Maix BOARD
+M:	Sean Anderson <seanga2@gmail.com>
+S:	Maintained
+F:	arch/riscv/dts/k210.dtsi
+F:	arch/riscv/dts/k210-maix-bit.dts
+F:	board/sipeed/maix/
+F:	configs/sipeed_maix_defconfig
+F:	drivers/clk/kendryte/
+F:	include/configs/sipeed-maix.h
+F:	include/dt-bindings/*/k210-sysctl.h
diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile
new file mode 100644
index 0000000000..4acff5b31e
--- /dev/null
+++ b/board/sipeed/maix/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2019 Western Digital Corporation or its affiliates.
+
+obj-y += maix.o
diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c
new file mode 100644
index 0000000000..f8e773acf7
--- /dev/null
+++ b/board/sipeed/maix/maix.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+int board_init(void)
+{
+	return 0;
+}
diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig
new file mode 100644
index 0000000000..22d814ec7f
--- /dev/null
+++ b/configs/sipeed_maix_bitm_defconfig
@@ -0,0 +1,10 @@
+CONFIG_RISCV=y
+CONFIG_TARGET_SIPEED_MAIX=y
+CONFIG_ARCH_RV64I=y
+# CONFIG_LEGACY_IMAGE_FORMAT is not set
+# CONFIG_AUTOBOOT is not set
+# CONFIG_NET is not set
+# CONFIG_INPUT is not set
+# CONFIG_MTD is not set
+# CONFIG_DM_ETH is not set
+# CONFIG_EFI_LOADER is not set
diff --git a/doc/board/index.rst b/doc/board/index.rst
index 00e72f57cd..2bd740589b 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -13,6 +13,7 @@ Board-specific doc
    freescale/index
    google/index
    intel/index
+   kendryte/index
    renesas/index
    sifive/index
    xilinx/index
diff --git a/doc/board/kendryte/index.rst b/doc/board/kendryte/index.rst
new file mode 100644
index 0000000000..5cbecd5731
--- /dev/null
+++ b/doc/board/kendryte/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Kendryte
+========
+
+.. toctree::
+   :maxdepth: 2
+
+   k210
diff --git a/doc/board/kendryte/k210.rst b/doc/board/kendryte/k210.rst
new file mode 100644
index 0000000000..14e0c22637
--- /dev/null
+++ b/doc/board/kendryte/k210.rst
@@ -0,0 +1,46 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+K210
+====
+
+The Kendryte K210 processor is a 64-bit RISC-V CPU. This processor contains
+several peripherals to accelerate neural network processing and other "ai"
+tasks. This includes a "KPU" neural network processor, an audio processor
+supporting beamforming reception, and a digital video port supporting capture
+and output at VGA resolution. Other peripherals include 8M of sram (accessible
+with and without caching); remappable pins, including 40 GPIOs; AES, FFT, and
+SHA256 accelerators; a DMA controller; and I2C, I2S, and SPI controllers. Maix
+peripherals vary, but include spi flash; on-board usb-serial bridges; ports for
+cameras, displays, and sd cards; and ESP32 chips. Currently, only the Sipeed
+Maix Bit V2.0 (bitm) is supported, but the boards are fairly similar.
+
+Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
+Documentation for the Kendryte K210 is located at
+<https://kendryte.com/downloads/>. However, hardware details are rather lacking,
+so most technical reference has been taken from the standalone sdk located at
+<https://github.com/kendryte/kendryte-standalone-sdk>.
+
+Build and boot steps
+--------------------
+
+To build u-boot, run
+
+make sipeed_maix_bit_defconfig
+make CROSS_COMPILE=<your cross compile prefix>
+
+To flash u-boot to a maix bit, run
+kflash -tp /dev/<your tty here> -B bit_mic u-boot-dtb.bin
+
+Boot output should look like the following:
+
+U-Boot 2020.01-00455-gad03fd83e1 (Jan 15 2020 - 17:10:24 -0500)
+
+DRAM:  8 MiB
+MMC:   spi at 52000000:slot at 0: 0
+In:    serial at 38000000
+Out:   serial at 38000000
+Err:   serial at 38000000
+=> 
+
+Note that spi does not work! I will try to figure out how to make it work, but
+for now the only way to boot something is to transfer it into ram over serial.
diff --git a/include/configs/sipeed-maix.h b/include/configs/sipeed-maix.h
new file mode 100644
index 0000000000..598f7dfdd0
--- /dev/null
+++ b/include/configs/sipeed-maix.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef CONFIGS_SIPEED_MAIX_H
+#define CONFIGS_SIPEED_MAIX_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_LOAD_ADDR 0x80000000
+#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_LOAD_ADDR
+#define CONFIG_SYS_SDRAM_SIZE SZ_8M
+/* Start just below AI memory */
+#define CONFIG_SYS_INIT_SP_ADDR 0x805FFFFF
+#define CONFIG_SYS_MALLOC_LEN SZ_8K
+#define CONFIG_SYS_CACHELINE_SIZE 64
+
+#endif /* CONFIGS_SIPEED_MAIX_H */
-- 
2.25.0

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

* [PATCH v3 04/12] reset: Add generic reset driver
  2020-02-02 20:01 ` [PATCH v3 04/12] reset: Add generic reset driver Sean Anderson
@ 2020-02-03  0:04   ` Simon Glass
  2020-02-03 23:14     ` Sean Anderson
  2020-02-04 11:06   ` Bin Meng
  1 sibling, 1 reply; 41+ messages in thread
From: Simon Glass @ 2020-02-03  0:04 UTC (permalink / raw)
  To: u-boot

HI Sean,

On Sun, 2 Feb 2020 at 13:01, Sean Anderson <seanga2@gmail.com> wrote:
>
> This patch adds a generic reset driver. It is designed to be useful when one has
> a register in a regmap which contains bits that reset other devices. I thought
> this seemed like a very generic use, so here is a generic driver. The overall
> structure has been modeled on the syscon-reboot driver.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - New
>
>  .../reset/syscon-reset.txt                    | 36 +++++++++
>  drivers/reset/Kconfig                         |  6 +-
>  drivers/reset/Makefile                        |  1 +
>  drivers/reset/reset-syscon.c                  | 79 +++++++++++++++++++
>  4 files changed, 121 insertions(+), 1 deletion(-)
>  create mode 100644 doc/device-tree-bindings/reset/syscon-reset.txt
>  create mode 100644 drivers/reset/reset-syscon.c

Is there a sandbox test for this driver somewhere in your series?

Regards,
Simon

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

* [PATCH v3 05/12] dm: Add support for simple-pm-bus
  2020-02-02 20:02 ` [PATCH v3 05/12] dm: Add support for simple-pm-bus Sean Anderson
@ 2020-02-03  0:04   ` Simon Glass
  2020-02-03 23:15     ` Sean Anderson
  2020-02-04 11:13   ` Bin Meng
  1 sibling, 1 reply; 41+ messages in thread
From: Simon Glass @ 2020-02-03  0:04 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Sun, 2 Feb 2020 at 13:02, Sean Anderson <seanga2@gmail.com> wrote:
>
> This type of bus is used in Linux to designate busses which have power domains
> and/or clocks which need to be enabled before their child devices can be used.
> Because power domains are automatically enabled before probing in u-boot, we
> just need to enable any clocks present.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - New
>
>  .../bus/simple-pm-bus.txt                     | 44 ++++++++++++++
>  drivers/core/simple-bus.c                     | 57 ++++++++++++++++++-
>  2 files changed, 99 insertions(+), 2 deletions(-)
>  create mode 100644 doc/device-tree-bindings/bus/simple-pm-bus.txt

Please can you add a test for this new functionality?

Thanks,
Simon

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

* [PATCH v3 04/12] reset: Add generic reset driver
  2020-02-03  0:04   ` Simon Glass
@ 2020-02-03 23:14     ` Sean Anderson
  0 siblings, 0 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-03 23:14 UTC (permalink / raw)
  To: u-boot

> Is there a sandbox test for this driver somewhere in your series?

There is not. Presumably if such a test were to exist, it would try
asserting different resets, and then check to see if the associated
register got changed. However, I am confused as to where such a test
would be located. There doesn't seem to be a directory for driver tests
under tests/. tests/dm seems to be for uclass testing, and tests/py
seems to be for tests which can work via the console.

--Sean

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

* [PATCH v3 05/12] dm: Add support for simple-pm-bus
  2020-02-03  0:04   ` Simon Glass
@ 2020-02-03 23:15     ` Sean Anderson
  2020-02-05  0:16       ` Simon Glass
  0 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-03 23:15 UTC (permalink / raw)
  To: u-boot

> Please can you add a test for this new functionality?

Should this be separate from test/dm/bus.c? As far as I can tell, that
file tests the concept of busses, and not the bus uclass.

--Sean

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

* [PATCH v3 04/12] reset: Add generic reset driver
  2020-02-02 20:01 ` [PATCH v3 04/12] reset: Add generic reset driver Sean Anderson
  2020-02-03  0:04   ` Simon Glass
@ 2020-02-04 11:06   ` Bin Meng
  2020-02-04 14:14     ` Sean Anderson
  1 sibling, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:06 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, Feb 3, 2020 at 4:01 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> This patch adds a generic reset driver. It is designed to be useful when one has
> a register in a regmap which contains bits that reset other devices. I thought
> this seemed like a very generic use, so here is a generic driver. The overall
> structure has been modeled on the syscon-reboot driver.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - New
>
>  .../reset/syscon-reset.txt                    | 36 +++++++++
>  drivers/reset/Kconfig                         |  6 +-
>  drivers/reset/Makefile                        |  1 +
>  drivers/reset/reset-syscon.c                  | 79 +++++++++++++++++++
>  4 files changed, 121 insertions(+), 1 deletion(-)
>  create mode 100644 doc/device-tree-bindings/reset/syscon-reset.txt
>  create mode 100644 drivers/reset/reset-syscon.c
>
> diff --git a/doc/device-tree-bindings/reset/syscon-reset.txt b/doc/device-tree-bindings/reset/syscon-reset.txt
> new file mode 100644
> index 0000000000..47c1226567
> --- /dev/null
> +++ b/doc/device-tree-bindings/reset/syscon-reset.txt
> @@ -0,0 +1,36 @@
> +Generic SYSCON mapped register reset driver
> +
> +This is a generic reset driver using syscon to map the reset register.
> +The reset is generally performed with a write to the reset register
> +defined by the register map pointed by syscon reference plus the offset and
> +shifted by the reset specifier/
> +
> +To assert a reset on some device, the equivalent of the following operation is
> +performed, where reset_id is the reset specifier from the device's resets
> +property.
> +
> +       if (BIT(reset_id) & mask)
> +               regmap[offset][reset_id] = assert-high;
> +
> +Required properties:
> +- compatible: should contain "syscon-reset"

Shouldn't we follow the same generic "syscon-reboot" device bindings
defined in the Linux kernel?
See Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml

> +- #reset-cells: must be 1
> +- regmap: this is phandle to the register map node
> +- offset: offset in the register map for the reboot register (in bytes)
> +
> +Optional properties:
> +- mask: accept only the reset specifiers defined by the mask (32 bit)
> +- assert-high: Bit to write when asserting a reset. Defaults to 1.
> +
> +Default will be little endian mode, 32 bit access only.
> +
> +Example:
> +
> +       reset-controller {
> +               compatible = "syscon-reset";
> +               #reset-cells = <1>;
> +               regmap = <&sysctl>;
> +               offset = <0x20>;
> +               mask = <0x27FFFFFF>;
> +               assert-high = <0>;
> +       };
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 75ccd65799..759d659c82 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -147,5 +147,9 @@ config RESET_IMX7
>         default y
>         help
>           Support for reset controller on i.MX7/8 SoCs.
> -

nits: this line should not be deleted.

> +config RESET_SYSCON
> +       bool "Enable generic syscon reset driver support"
> +       depends on DM_RESET
> +       help
> +         Support generic syscon mapped register reset devices.
>  endmenu
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 0a044d5d8c..433f1eca54 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -23,3 +23,4 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o
>  obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>  obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o
>  obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
> +obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o

[snip]

Regards,
Bin

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

* [PATCH v3 05/12] dm: Add support for simple-pm-bus
  2020-02-02 20:02 ` [PATCH v3 05/12] dm: Add support for simple-pm-bus Sean Anderson
  2020-02-03  0:04   ` Simon Glass
@ 2020-02-04 11:13   ` Bin Meng
  1 sibling, 0 replies; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:13 UTC (permalink / raw)
  To: u-boot

On Mon, Feb 3, 2020 at 4:02 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> This type of bus is used in Linux to designate busses which have power domains
> and/or clocks which need to be enabled before their child devices can be used.
> Because power domains are automatically enabled before probing in u-boot, we
> just need to enable any clocks present.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - New
>
>  .../bus/simple-pm-bus.txt                     | 44 ++++++++++++++
>  drivers/core/simple-bus.c                     | 57 ++++++++++++++++++-
>  2 files changed, 99 insertions(+), 2 deletions(-)
>  create mode 100644 doc/device-tree-bindings/bus/simple-pm-bus.txt
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

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

* [PATCH v3 06/12] riscv: Add headers for asm/global_data.h
  2020-02-02 20:04 ` [PATCH v3 06/12] riscv: Add headers for asm/global_data.h Sean Anderson
@ 2020-02-04 11:17   ` Bin Meng
  0 siblings, 0 replies; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:17 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, Feb 3, 2020 at 4:04 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> This header depended on bd_t and ulong, but did not include the appropriate
> headers.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>  arch/riscv/include/asm/global_data.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> index b74bd7e738..4f0c12b402 100644
> --- a/arch/riscv/include/asm/global_data.h
> +++ b/arch/riscv/include/asm/global_data.h
> @@ -11,6 +11,8 @@
>  #define __ASM_GBL_DATA_H
>
>  #include <asm/smp.h>
> +#include <asm/u-boot.h>
> +#include <linux/compiler.h>

ulong is from <compiler.h>, not <linux/compiler.h>

>
>  /* Architecture-specific global data */
>  struct arch_global_data {
> --

Regards,
Bin

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-02 20:05 ` [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1 Sean Anderson
@ 2020-02-04 11:21   ` Bin Meng
  2020-02-04 14:19     ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:21 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, Feb 3, 2020 at 4:05 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> Some older processors (notably the Kendryte K210) use an older version of the
> RISC-V privileged specification. The primary changes between the old and new are
> in virtual memory, and in the merging of three separate counter enable CSRs.
> Using the new CSR on an old processor causes an illegal instruction exception.
> This patch adds an option to use the old CSRs instead of the new one.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
> Changes for v3:
>   - Renamed from "riscv: Add option to disable writes to mcounteren"
>   - Added original functionality back for older priv specs.
> Changes for v2:
>   - Moved forward in the patch series
>
>  arch/riscv/Kconfig           | 10 ++++++++++
>  arch/riscv/cpu/cpu.c         |  6 ++++++
>  arch/riscv/include/asm/csr.h |  6 ++++++
>  3 files changed, 22 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 85e15ebffa..87c40f6c4c 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -222,6 +222,16 @@ config XIP
>           from a NOR flash memory without copying the code to ram.
>           Say yes here if U-Boot boots from flash directly.
>
> +config RISCV_PRIV_1_9_1
> +       bool "Use version 1.9.1 of the RISC-V priviledged specification"

typo: privileged

> +       help
> +         Older versions of the RISC-V priviledged specification had

typo: privileged

> +         separate counter enable CSRs for each privilege mode. Writing
> +         to the unified mcounteren CSR on a processor implementing the
> +         old specification will result in an illegal instruction
> +         exception. In addition to counter CSR changes, the way virtual
> +         memory is configured was also changed.
> +
>  config STACK_SIZE_SHIFT
>         int
>         default 14
> diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
> index e457f6acbf..83cb6557cd 100644
> --- a/arch/riscv/cpu/cpu.c
> +++ b/arch/riscv/cpu/cpu.c
> @@ -89,7 +89,13 @@ int arch_cpu_init_dm(void)
>                  * Enable perf counters for cycle, time,
>                  * and instret counters only
>                  */
> +#ifdef CONFIG_RISCV_PRIV_1_9_1
> +               /* FIXME: Can't use the macro for some reason... */

This is weird ...

> +               csr_write(mscounteren, GENMASK(2, 0));
> +               csr_write(mucounteren, GENMASK(2, 0));
> +#else
>                 csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
> +#endif
>
>                 /* Disable paging */
>                 if (supports_extension('s'))
> diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
> index d1520743a2..c16b65d3f3 100644
> --- a/arch/riscv/include/asm/csr.h
> +++ b/arch/riscv/include/asm/csr.h
> @@ -93,7 +93,13 @@
>  #define CSR_MISA               0x301
>  #define CSR_MIE                        0x304
>  #define CSR_MTVEC              0x305
> +#ifdef RISCV_PRIV_1_9_1
> +#define CSR_MUCOUNTEREN         0x320
> +#define CSR_MSCOUNTEREN         0x321
> +#define CSR_MHCOUNTEREN         0x322
> +#else
>  #define CSR_MCOUNTEREN         0x306
> +#endif
>  #define CSR_MSCRATCH           0x340
>  #define CSR_MEPC               0x341
>  #define CSR_MCAUSE             0x342
> --

Other than above,
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Bin

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

* [PATCH v3 08/12] riscv: Allow use of reset drivers
  2020-02-02 20:06 ` [PATCH v3 08/12] riscv: Allow use of reset drivers Sean Anderson
@ 2020-02-04 11:22   ` Bin Meng
  0 siblings, 0 replies; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:22 UTC (permalink / raw)
  To: u-boot

On Mon, Feb 3, 2020 at 4:06 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> Currently, one cannot use a reset driver on RISC-V. Follow the MIPS example, and
> disable the default reset handler when the sysreset driver is enabled.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - New
>
>  arch/riscv/lib/reset.c | 2 ++
>  1 file changed, 2 insertions(+)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

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

* [PATCH v3 11/12] riscv: Add device tree for K210
  2020-02-02 20:10 ` [PATCH v3 11/12] riscv: Add device tree for K210 Sean Anderson
@ 2020-02-04 11:32   ` Bin Meng
  2020-02-04 14:23     ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:32 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, Feb 3, 2020 at 4:10 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> Where possible, I have tried to find compatible drivers based on the layout of
> registers. However, I have not tested most of this functionality, and most
> devices should be considered descriptive at best. I would appreciate if anyone
> could help identify possibly compatible devices, especially for the timers
> and rtc.
>
> Should the size of a reg be the size of the documented registers, or the size
> of the address space which will be routed to that device?

Perhaps we need use the size of the address space routed to that
device, in case there is some undocumented registers we need handle.

>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - Move this patch to the end of the series
>   - Add a max frequency for spi3
>   - Remov unused compatible strings from spi-flash at 0
>   - Add s and u to isa string
>   - Fix mmu-type
>   - Remove cache-line size since it is unused (in u-boot) and undocumented
>     (upstream)
>   - Add timer interrupts to clint0
>   - Round up various registers
>   - Add riscv,max-priority to plic
>   - Add apb* busses, since they have clocks which need to be enabled to access
>     their devices
>   - Change uart compatible strings to "snps,dw-apb-uart", since that appears to
>     match their registers
>   - Add compatible string for wdt*
>   - Add system reset device under sysctl
>   - Add reset device under sysctl
>   Changes for v2:
>   - Model changed to "Sipeed Maix Bit" to match file name
>   - Value of stdout-path fixed
>   - SD card slot compatible changed to "mmc-spi-slot"
>   - "jedec,spi-nor" added to spi flash compatible list
>   - Aliases for spi busses added
>   - timebase-frequency divided by 50 to match timer speed
>   - cpu-frequency renamed to clock-frequency
>   - CPUX_intc restyled to cpuX_intc
>   - "kendryte,k210-soc" added to soc compatible list for future-proofing
>   - PLIC handle renamed to plic0 from pic0
>   - K210_RST_SOC removed from sysrst, due to not being located in the
>     reset register
>   - K210_RST_* numbers changed to match their bit offset within the reset
>     register
>   - gpio_controller restyled to gpio-controller
>   - Added a second clock to the dma binding to match what the driver expects
>   - Changed "snps,designware-spi" compatible string to "snps,dw-apb-ssi" to
>     match the correct driver
>   - Added a name to the spi clocks
>   - Added reg-io-width property to spi bindings
>   - Assigned a default parent to K210_CLK_SPI3
>   - Removed assigned clocks for ACLK and PLLs
>   - Removed u-boot,dm-pre-reloc bindings
>
>  arch/riscv/dts/Makefile                 |   1 +
>  arch/riscv/dts/k210-maix-bit.dts        |  42 ++
>  arch/riscv/dts/k210.dtsi                | 496 ++++++++++++++++++++++++
>  include/dt-bindings/reset/k210-sysctl.h |  38 ++
>  4 files changed, 577 insertions(+)
>  create mode 100644 arch/riscv/dts/k210-maix-bit.dts
>  create mode 100644 arch/riscv/dts/k210.dtsi
>  create mode 100644 include/dt-bindings/reset/k210-sysctl.h
>
> diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
> index 4f30e6936f..3a6f96c67d 100644
> --- a/arch/riscv/dts/Makefile
> +++ b/arch/riscv/dts/Makefile
> @@ -2,6 +2,7 @@
>
>  dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
>  dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb
> +dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
>
>  targets += $(dtb-y)
>
> diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts
> new file mode 100644
> index 0000000000..10f36921e0
> --- /dev/null
> +++ b/arch/riscv/dts/k210-maix-bit.dts
> @@ -0,0 +1,42 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +/ {
> +       model = "Sipeed Maix Bit";
> +       compatible = "sipeed,maix-bit", "kendryte,k210";
> +
> +       chosen {
> +               stdout-path = "serial0:115200";
> +       };
> +};
> +
> +&uarths0 {
> +       status = "okay";
> +};
> +
> +&spi0 {
> +       status = "okay";
> +       slot at 0 {
> +               compatible = "mmc-spi-slot";
> +               reg = <0>;
> +               broken-cd;
> +               disable-wp;
> +       };
> +};
> +
> +&spi3 {
> +       status = "okay";
> +       spi-max-frequency = <120000000>;
> +       spi-flash at 0 {
> +               compatible = "jedec,spi-nor";
> +               reg = <0>;
> +               spi-max-frequency = <120000000>;
> +               m25p,fast-read;
> +       };
> +};
> diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
> new file mode 100644
> index 0000000000..cc46b692e6
> --- /dev/null
> +++ b/arch/riscv/dts/k210.dtsi
> @@ -0,0 +1,496 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#include <dt-bindings/clock/k210-sysctl.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dt-bindings/reset/k210-sysctl.h>
> +
> +/ {
> +       /*
> +        * Although the K210 is a 64-bit CPU, the address bus is only 32-bits
> +        * wide, and the upper half of all addresses is ignored.
> +        */
> +       #address-cells = <1>;
> +       #size-cells = <1>;
> +       compatible = "kendryte,k210";
> +
> +       aliases {
> +               serial0 = &uarths0;
> +               serial1 = &uart1;
> +               serial2 = &uart2;
> +               serial3 = &uart3;
> +               spi0 = &spi0;
> +               spi1 = &spi1;
> +               spi2 = &spi2;
> +               spi3 = &spi3;
> +       };
> +
> +       clocks {
> +               in0: oscillator {
> +                       compatible = "fixed-clock";
> +                       #clock-cells = <0>;
> +                       clock-frequency = <26000000>;
> +               };
> +       };
> +
> +       cpus {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               timebase-frequency = <7800000>;
> +               cpu0: cpu at 0 {
> +                       device_type = "cpu";
> +                       reg = <0>;
> +                       compatible = "riscv";
> +                       riscv,isa = "rv64acdfimsu";
> +                       mmu-type = "sv39";
> +                       i-cache-size = <0x8000>;
> +                       d-cache-size = <0x8000>;
> +                       clocks = <&sysclk K210_CLK_CPU>;
> +                       clock-frequency = <390000000>;

I wonder there is already clocks property, why do we have another
clock-frequency property to provide duplicated information?

> +                       cpu0_intc: interrupt-controller {
> +                               #interrupt-cells = <1>;
> +                               interrupt-controller;
> +                               compatible = "riscv,cpu-intc";
> +                       };
> +               };
> +               cpu1: cpu at 1 {
> +                       device_type = "cpu";
> +                       reg = <1>;
> +                       compatible = "riscv";
> +                       riscv,isa = "rv64acdfimsu";
> +                       mmu-type = "sv39";
> +                       i-cache-size = <0x8000>;
> +                       d-cache-size = <0x8000>;
> +                       clocks = <&sysclk K210_CLK_CPU>;
> +                       clock-frequency = <390000000>;
> +                       cpu1_intc: interrupt-controller {
> +                               #interrupt-cells = <1>;
> +                               interrupt-controller;
> +                               compatible = "riscv,cpu-intc";
> +                       };
> +               };
> +       };
> +
> +       sram0: memory at 80000000 {
> +               device_type = "memory";
> +               reg = <0x80000000 0x400000>;
> +               clocks = <&sysclk K210_CLK_SRAM0>;
> +       };
> +
> +       sram1: memory at 80400000 {
> +               device_type = "memory";
> +               reg = <0x80400000 0x400000>;
> +               clocks = <&sysclk K210_CLK_SRAM1>;
> +       };
> +
> +       reserved-memory {
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               ranges;
> +
> +               ai_reserved: ai at 80600000 {
> +                       reg = <0x80600000 0x200000>;
> +                       reusable;
> +               };
> +       };
> +
> +       soc {
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               compatible = "kendryte,k210-soc", "simple-bus";
> +               ranges;
> +               interrupt-parent = <&plic0>;
> +
> +               clint0: interrupt-controller at 2000000 {
> +                       compatible = "riscv,clint0";
> +                       reg = <0x2000000 0x1000>;
> +                       interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
> +                                             <&cpu1_intc 3>, <&cpu1_intc 7>;
> +                       clocks = <&sysclk K210_CLK_CPU>;
> +               };
> +
> +               plic0: interrupt-controller at c000000 {
> +                       #interrupt-cells = <1>;
> +                       interrupt-controller;
> +                       compatible = "kendryte,k210-plic", "riscv,plic1";
> +                       reg = <0xC000000 0x4000000>;
> +                       interrupts-extended = <&cpu0_intc 9>, <&cpu0_intc 11>,
> +                                             <&cpu1_intc 9>, <&cpu1_intc 11>;
> +                       riscv,ndev = <65>;
> +                       riscv,max-priority = <7>;
> +               };
> +

[snip]

Regards,
Bin

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

* [PATCH v3 12/12] riscv: Add initial Sipeed Maix support
  2020-02-02 20:10 ` [PATCH v3 12/12] riscv: Add initial Sipeed Maix support Sean Anderson
@ 2020-02-04 11:38   ` Bin Meng
  2020-02-04 14:26     ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 11:38 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, Feb 3, 2020 at 4:11 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> The Sipeed Maix series is a collection of boards built around the RISC-V
> Kendryte K210 processor. This processor contains several peripherals to
> accelerate neural network processing and other "ai" tasks. This includes a "KPU"
> neural network processor, an audio processor supporting beamforming reception,
> and a digital video port supporting capture and output at VGA resolution. Other
> peripherals include 8M of sram (accessible with and without caching);
> remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA
> controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but
> include spi flash; on-board usb-serial bridges; ports for cameras, displays, and
> sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is
> supported, but the boards are fairly similar.
>
> Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
> Documentation for the Kendryte K210 is located at
> <https://kendryte.com/downloads/>. However, hardware details are rather lacking,
> so most technical reference has been taken from the standalone sdk located at
> <https://github.com/kendryte/kendryte-standalone-sdk>.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>   Changes for v3:
>   - Reorder to be last in the patch series
>   - Add documentation for the board
>   - Generate defconfig with "make savedefconfig"
>   - Update Kconfig to imply most features we need
>   - Update MAINTAINERS
>   Changes for v2:
>   - Select CONFIG_SYS_RISCV_NOCOUNTER
>   - Imply CONFIG_CLK_K210
>   - Remove spurious references to CONFIG_ARCH_K210
>   - Remove many configs from defconfig where the defaults were fine
>   - Add a few "not set" lines to suppress unneeded defaults
>   - Reduce pre-reloc malloc space, now that clocks initialization happens later
>
>  arch/riscv/Kconfig                 |  4 +++
>  board/sipeed/maix/Kconfig          | 51 ++++++++++++++++++++++++++++++
>  board/sipeed/maix/MAINTAINERS      | 10 ++++++
>  board/sipeed/maix/Makefile         |  5 +++
>  board/sipeed/maix/maix.c           |  9 ++++++
>  configs/sipeed_maix_bitm_defconfig | 10 ++++++
>  doc/board/index.rst                |  1 +
>  doc/board/kendryte/index.rst       |  9 ++++++
>  doc/board/kendryte/k210.rst        | 46 +++++++++++++++++++++++++++
>  include/configs/sipeed-maix.h      | 19 +++++++++++
>  10 files changed, 164 insertions(+)
>  create mode 100644 board/sipeed/maix/Kconfig
>  create mode 100644 board/sipeed/maix/MAINTAINERS
>  create mode 100644 board/sipeed/maix/Makefile
>  create mode 100644 board/sipeed/maix/maix.c
>  create mode 100644 configs/sipeed_maix_bitm_defconfig
>  create mode 100644 doc/board/kendryte/index.rst
>  create mode 100644 doc/board/kendryte/k210.rst
>  create mode 100644 include/configs/sipeed-maix.h
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 87c40f6c4c..81ab35dd2d 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT
>  config TARGET_SIFIVE_FU540
>         bool "Support SiFive FU540 Board"
>
> +config TARGET_SIPEED_MAIX
> +       bool "Support Sipeed Maix Board"
> +
>  endchoice
>
>  config SYS_ICACHE_OFF
> @@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig"
>  source "board/emulation/qemu-riscv/Kconfig"
>  source "board/microchip/mpfs_icicle/Kconfig"
>  source "board/sifive/fu540/Kconfig"
> +source "board/sipeed/maix/Kconfig"
>
>  # platform-specific options below
>  source "arch/riscv/cpu/ax25/Kconfig"
> diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
> new file mode 100644
> index 0000000000..b23d2448d9
> --- /dev/null
> +++ b/board/sipeed/maix/Kconfig
> @@ -0,0 +1,51 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> +
> +if TARGET_SIPEED_MAIX
> +
> +config SYS_BOARD
> +       default "maix"
> +
> +config SYS_VENDOR
> +       default "sipeed"
> +
> +config SYS_CPU
> +       default "generic"
> +
> +config SYS_CONFIG_NAME
> +       default "sipeed-maix"
> +
> +config SYS_TEXT_BASE
> +       default 0x80000000
> +
> +config DEFAULT_DEVICE_TREE
> +       default "k210-maix-bit"
> +
> +config NR_CPUS
> +       default 2
> +
> +config NR_DRAM_BANKS
> +       default 2
> +
> +config BOARD_SPECIFIC_OPTIONS
> +       def_bool y
> +       select GENERIC_RISCV
> +       select RISCV_PRIV_1_9_1
> +       imply DM_SERIAL
> +       imply SIFIVE_SERIAL
> +       imply SIFIVE_CLINT
> +       imply CLK_CCF
> +       imply CLK_COMPOSITE_CCF
> +       imply CLK_K210
> +       imply DM_RESET
> +       imply RESET_SYSCON
> +       imply SYSRESET
> +       imply SYSRESET_SYSCON
> +       imply SPI
> +       imply DESIGNWARE_SPI
> +       imply SPI_FLASH_GIGADEVICE
> +       imply MMC
> +       imply MMC_SPI
> +       imply MMC_BROKEN_CD
> +       imply CMD_MMC
> +endif
> diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
> new file mode 100644
> index 0000000000..43cf61fb64
> --- /dev/null
> +++ b/board/sipeed/maix/MAINTAINERS
> @@ -0,0 +1,10 @@
> +Sipeed Maix BOARD
> +M:     Sean Anderson <seanga2@gmail.com>
> +S:     Maintained
> +F:     arch/riscv/dts/k210.dtsi
> +F:     arch/riscv/dts/k210-maix-bit.dts
> +F:     board/sipeed/maix/
> +F:     configs/sipeed_maix_defconfig
> +F:     drivers/clk/kendryte/
> +F:     include/configs/sipeed-maix.h
> +F:     include/dt-bindings/*/k210-sysctl.h
> diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile
> new file mode 100644
> index 0000000000..4acff5b31e
> --- /dev/null
> +++ b/board/sipeed/maix/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright (c) 2019 Western Digital Corporation or its affiliates.
> +
> +obj-y += maix.o
> diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c
> new file mode 100644
> index 0000000000..f8e773acf7
> --- /dev/null
> +++ b/board/sipeed/maix/maix.c
> @@ -0,0 +1,9 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +int board_init(void)
> +{
> +       return 0;
> +}
> diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig
> new file mode 100644
> index 0000000000..22d814ec7f
> --- /dev/null
> +++ b/configs/sipeed_maix_bitm_defconfig
> @@ -0,0 +1,10 @@
> +CONFIG_RISCV=y
> +CONFIG_TARGET_SIPEED_MAIX=y
> +CONFIG_ARCH_RV64I=y
> +# CONFIG_LEGACY_IMAGE_FORMAT is not set
> +# CONFIG_AUTOBOOT is not set
> +# CONFIG_NET is not set
> +# CONFIG_INPUT is not set
> +# CONFIG_MTD is not set
> +# CONFIG_DM_ETH is not set
> +# CONFIG_EFI_LOADER is not set
> diff --git a/doc/board/index.rst b/doc/board/index.rst
> index 00e72f57cd..2bd740589b 100644
> --- a/doc/board/index.rst
> +++ b/doc/board/index.rst
> @@ -13,6 +13,7 @@ Board-specific doc
>     freescale/index
>     google/index
>     intel/index
> +   kendryte/index

We should use the board vendor name: sipeed/index

>     renesas/index
>     sifive/index
>     xilinx/index
> diff --git a/doc/board/kendryte/index.rst b/doc/board/kendryte/index.rst
> new file mode 100644
> index 0000000000..5cbecd5731
> --- /dev/null
> +++ b/doc/board/kendryte/index.rst
> @@ -0,0 +1,9 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +Kendryte

Sipeed

> +========
> +
> +.. toctree::
> +   :maxdepth: 2
> +
> +   k210

and use the board name here: maix, or k210-maix-bit ?

> diff --git a/doc/board/kendryte/k210.rst b/doc/board/kendryte/k210.rst
> new file mode 100644
> index 0000000000..14e0c22637
> --- /dev/null
> +++ b/doc/board/kendryte/k210.rst
> @@ -0,0 +1,46 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +K210

k210-maix-bit ?

> +====
> +
> +The Kendryte K210 processor is a 64-bit RISC-V CPU. This processor contains
> +several peripherals to accelerate neural network processing and other "ai"
> +tasks. This includes a "KPU" neural network processor, an audio processor
> +supporting beamforming reception, and a digital video port supporting capture
> +and output at VGA resolution. Other peripherals include 8M of sram (accessible
> +with and without caching); remappable pins, including 40 GPIOs; AES, FFT, and
> +SHA256 accelerators; a DMA controller; and I2C, I2S, and SPI controllers. Maix
> +peripherals vary, but include spi flash; on-board usb-serial bridges; ports for
> +cameras, displays, and sd cards; and ESP32 chips. Currently, only the Sipeed
> +Maix Bit V2.0 (bitm) is supported, but the boards are fairly similar.
> +
> +Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
> +Documentation for the Kendryte K210 is located at
> +<https://kendryte.com/downloads/>. However, hardware details are rather lacking,
> +so most technical reference has been taken from the standalone sdk located at
> +<https://github.com/kendryte/kendryte-standalone-sdk>.
> +
> +Build and boot steps
> +--------------------
> +
> +To build u-boot, run
> +
> +make sipeed_maix_bit_defconfig
> +make CROSS_COMPILE=<your cross compile prefix>
> +
> +To flash u-boot to a maix bit, run
> +kflash -tp /dev/<your tty here> -B bit_mic u-boot-dtb.bin
> +
> +Boot output should look like the following:
> +
> +U-Boot 2020.01-00455-gad03fd83e1 (Jan 15 2020 - 17:10:24 -0500)
> +
> +DRAM:  8 MiB
> +MMC:   spi at 52000000:slot at 0: 0
> +In:    serial at 38000000
> +Out:   serial at 38000000
> +Err:   serial at 38000000
> +=>
> +
> +Note that spi does not work! I will try to figure out how to make it work, but
> +for now the only way to boot something is to transfer it into ram over serial.
> diff --git a/include/configs/sipeed-maix.h b/include/configs/sipeed-maix.h
> new file mode 100644
> index 0000000000..598f7dfdd0
> --- /dev/null
> +++ b/include/configs/sipeed-maix.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef CONFIGS_SIPEED_MAIX_H
> +#define CONFIGS_SIPEED_MAIX_H
> +
> +#include <linux/sizes.h>
> +
> +#define CONFIG_SYS_LOAD_ADDR 0x80000000
> +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_LOAD_ADDR
> +#define CONFIG_SYS_SDRAM_SIZE SZ_8M
> +/* Start just below AI memory */
> +#define CONFIG_SYS_INIT_SP_ADDR 0x805FFFFF
> +#define CONFIG_SYS_MALLOC_LEN SZ_8K
> +#define CONFIG_SYS_CACHELINE_SIZE 64
> +
> +#endif /* CONFIGS_SIPEED_MAIX_H */
> --

Regards,
Bin

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

* [PATCH v3 04/12] reset: Add generic reset driver
  2020-02-04 11:06   ` Bin Meng
@ 2020-02-04 14:14     ` Sean Anderson
  0 siblings, 0 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:14 UTC (permalink / raw)
  To: u-boot


On 2/4/20 6:06 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Mon, Feb 3, 2020 at 4:01 AM Sean Anderson <seanga2@gmail.com> wrote:
>> +Required properties:
>> +- compatible: should contain "syscon-reset"
> 
> Shouldn't we follow the same generic "syscon-reboot" device bindings
> defined in the Linux kernel?
> See Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml

This is a different driver. That driver is already in u-boot as
UCLASS_SYSRESET, but this driver is for UCLASS_RESET. I modeled this one
off syscon-reboot.

> nits: this line should not be deleted.

Ok, will restore for v4.

--Sean

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-04 11:21   ` Bin Meng
@ 2020-02-04 14:19     ` Sean Anderson
  2020-02-04 14:38       ` Bin Meng
  0 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:19 UTC (permalink / raw)
  To: u-boot


On 2/4/20 6:21 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Mon, Feb 3, 2020 at 4:05 AM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> Some older processors (notably the Kendryte K210) use an older version of the
>> RISC-V privileged specification. The primary changes between the old and new are
>> in virtual memory, and in the merging of three separate counter enable CSRs.
>> Using the new CSR on an old processor causes an illegal instruction exception.
>> This patch adds an option to use the old CSRs instead of the new one.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> ---
>> Changes for v3:
>>   - Renamed from "riscv: Add option to disable writes to mcounteren"
>>   - Added original functionality back for older priv specs.
>> Changes for v2:
>>   - Moved forward in the patch series
>>
>>  arch/riscv/Kconfig           | 10 ++++++++++
>>  arch/riscv/cpu/cpu.c         |  6 ++++++
>>  arch/riscv/include/asm/csr.h |  6 ++++++
>>  3 files changed, 22 insertions(+)
>>
>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>> index 85e15ebffa..87c40f6c4c 100644
>> --- a/arch/riscv/Kconfig
>> +++ b/arch/riscv/Kconfig
>> @@ -222,6 +222,16 @@ config XIP
>>           from a NOR flash memory without copying the code to ram.
>>           Say yes here if U-Boot boots from flash directly.
>>
>> +config RISCV_PRIV_1_9_1
>> +       bool "Use version 1.9.1 of the RISC-V priviledged specification"
> 
> typo: privileged
> 
>> +       help
>> +         Older versions of the RISC-V priviledged specification had
> 
> typo: privileged

Whoops, will fix that for v4.

>> +         separate counter enable CSRs for each privilege mode. Writing
>> +         to the unified mcounteren CSR on a processor implementing the
>> +         old specification will result in an illegal instruction
>> +         exception. In addition to counter CSR changes, the way virtual
>> +         memory is configured was also changed.
>> +
>>  config STACK_SIZE_SHIFT
>>         int
>>         default 14
>> diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
>> index e457f6acbf..83cb6557cd 100644
>> --- a/arch/riscv/cpu/cpu.c
>> +++ b/arch/riscv/cpu/cpu.c
>> @@ -89,7 +89,13 @@ int arch_cpu_init_dm(void)
>>                  * Enable perf counters for cycle, time,
>>                  * and instret counters only
>>                  */
>> +#ifdef CONFIG_RISCV_PRIV_1_9_1
>> +               /* FIXME: Can't use the macro for some reason... */
> 
> This is weird ...

I believe the macro compiles to "csrs CSR_FOO". At least with my
gcc/binutils (9.2.0/2.33.1) this style is not available for these older
CSRs. Perhaps it would work if we switched to letting it compile with
the numeric CSR as defined earlier in asm/csr.h

--Sean

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

* [PATCH v3 11/12] riscv: Add device tree for K210
  2020-02-04 11:32   ` Bin Meng
@ 2020-02-04 14:23     ` Sean Anderson
  2020-02-04 14:40       ` Bin Meng
  0 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:23 UTC (permalink / raw)
  To: u-boot

On 2/4/20 6:32 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Mon, Feb 3, 2020 at 4:10 AM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> Where possible, I have tried to find compatible drivers based on the layout of
>> registers. However, I have not tested most of this functionality, and most
>> devices should be considered descriptive at best. I would appreciate if anyone
>> could help identify possibly compatible devices, especially for the timers
>> and rtc.
>>
>> Should the size of a reg be the size of the documented registers, or the size
>> of the address space which will be routed to that device?
> 
> Perhaps we need use the size of the address space routed to that
> device, in case there is some undocumented registers we need handle.

Ok, I'll go with the whole address space then.

>> diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
>> new file mode 100644
>> index 0000000000..cc46b692e6
>> --- /dev/null
>> +++ b/arch/riscv/dts/k210.dtsi
>> @@ -0,0 +1,496 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>> + */
>> +
>> +#include <dt-bindings/clock/k210-sysctl.h>
>> +#include <dt-bindings/mfd/k210-sysctl.h>
>> +#include <dt-bindings/reset/k210-sysctl.h>
>> +
>> +/ {
>> +       /*
>> +        * Although the K210 is a 64-bit CPU, the address bus is only 32-bits
>> +        * wide, and the upper half of all addresses is ignored.
>> +        */
>> +       #address-cells = <1>;
>> +       #size-cells = <1>;
>> +       compatible = "kendryte,k210";
>> +
>> +       aliases {
>> +               serial0 = &uarths0;
>> +               serial1 = &uart1;
>> +               serial2 = &uart2;
>> +               serial3 = &uart3;
>> +               spi0 = &spi0;
>> +               spi1 = &spi1;
>> +               spi2 = &spi2;
>> +               spi3 = &spi3;
>> +       };
>> +
>> +       clocks {
>> +               in0: oscillator {
>> +                       compatible = "fixed-clock";
>> +                       #clock-cells = <0>;
>> +                       clock-frequency = <26000000>;
>> +               };
>> +       };
>> +
>> +       cpus {
>> +               #address-cells = <1>;
>> +               #size-cells = <0>;
>> +               timebase-frequency = <7800000>;
>> +               cpu0: cpu at 0 {
>> +                       device_type = "cpu";
>> +                       reg = <0>;
>> +                       compatible = "riscv";
>> +                       riscv,isa = "rv64acdfimsu";
>> +                       mmu-type = "sv39";
>> +                       i-cache-size = <0x8000>;
>> +                       d-cache-size = <0x8000>;
>> +                       clocks = <&sysclk K210_CLK_CPU>;
>> +                       clock-frequency = <390000000>;
> 
> I wonder there is already clocks property, why do we have another
> clock-frequency property to provide duplicated information?

This is for compatibility with the existing riscv cpu driver. There is a
patch [1] to move the driver over to using clocks, but I think you
already expressed that it should be merged into this series (not as a
separate series).

[1] https://patchwork.ozlabs.org/project/uboot/list/?series=156381

--Sean

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

* [PATCH v3 12/12] riscv: Add initial Sipeed Maix support
  2020-02-04 11:38   ` Bin Meng
@ 2020-02-04 14:26     ` Sean Anderson
  2020-02-04 14:42       ` Bin Meng
  0 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:26 UTC (permalink / raw)
  To: u-boot

On 2/4/20 6:38 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Mon, Feb 3, 2020 at 4:11 AM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> The Sipeed Maix series is a collection of boards built around the RISC-V
>> Kendryte K210 processor. This processor contains several peripherals to
>> accelerate neural network processing and other "ai" tasks. This includes a "KPU"
>> neural network processor, an audio processor supporting beamforming reception,
>> and a digital video port supporting capture and output at VGA resolution. Other
>> peripherals include 8M of sram (accessible with and without caching);
>> remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA
>> controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but
>> include spi flash; on-board usb-serial bridges; ports for cameras, displays, and
>> sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is
>> supported, but the boards are fairly similar.
>>
>> Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
>> Documentation for the Kendryte K210 is located at
>> <https://kendryte.com/downloads/>. However, hardware details are rather lacking,
>> so most technical reference has been taken from the standalone sdk located at
>> <https://github.com/kendryte/kendryte-standalone-sdk>.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> ---
>>   Changes for v3:
>>   - Reorder to be last in the patch series
>>   - Add documentation for the board
>>   - Generate defconfig with "make savedefconfig"
>>   - Update Kconfig to imply most features we need
>>   - Update MAINTAINERS
>>   Changes for v2:
>>   - Select CONFIG_SYS_RISCV_NOCOUNTER
>>   - Imply CONFIG_CLK_K210
>>   - Remove spurious references to CONFIG_ARCH_K210
>>   - Remove many configs from defconfig where the defaults were fine
>>   - Add a few "not set" lines to suppress unneeded defaults
>>   - Reduce pre-reloc malloc space, now that clocks initialization happens later
>>
>>  arch/riscv/Kconfig                 |  4 +++
>>  board/sipeed/maix/Kconfig          | 51 ++++++++++++++++++++++++++++++
>>  board/sipeed/maix/MAINTAINERS      | 10 ++++++
>>  board/sipeed/maix/Makefile         |  5 +++
>>  board/sipeed/maix/maix.c           |  9 ++++++
>>  configs/sipeed_maix_bitm_defconfig | 10 ++++++
>>  doc/board/index.rst                |  1 +
>>  doc/board/kendryte/index.rst       |  9 ++++++
>>  doc/board/kendryte/k210.rst        | 46 +++++++++++++++++++++++++++
>>  include/configs/sipeed-maix.h      | 19 +++++++++++
>>  10 files changed, 164 insertions(+)
>>  create mode 100644 board/sipeed/maix/Kconfig
>>  create mode 100644 board/sipeed/maix/MAINTAINERS
>>  create mode 100644 board/sipeed/maix/Makefile
>>  create mode 100644 board/sipeed/maix/maix.c
>>  create mode 100644 configs/sipeed_maix_bitm_defconfig
>>  create mode 100644 doc/board/kendryte/index.rst
>>  create mode 100644 doc/board/kendryte/k210.rst
>>  create mode 100644 include/configs/sipeed-maix.h
>>
>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>> index 87c40f6c4c..81ab35dd2d 100644
>> --- a/arch/riscv/Kconfig
>> +++ b/arch/riscv/Kconfig
>> @@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT
>>  config TARGET_SIFIVE_FU540
>>         bool "Support SiFive FU540 Board"
>>
>> +config TARGET_SIPEED_MAIX
>> +       bool "Support Sipeed Maix Board"
>> +
>>  endchoice
>>
>>  config SYS_ICACHE_OFF
>> @@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig"
>>  source "board/emulation/qemu-riscv/Kconfig"
>>  source "board/microchip/mpfs_icicle/Kconfig"
>>  source "board/sifive/fu540/Kconfig"
>> +source "board/sipeed/maix/Kconfig"
>>
>>  # platform-specific options below
>>  source "arch/riscv/cpu/ax25/Kconfig"
>> diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
>> new file mode 100644
>> index 0000000000..b23d2448d9
>> --- /dev/null
>> +++ b/board/sipeed/maix/Kconfig
>> @@ -0,0 +1,51 @@
>> +# SPDX-License-Identifier: GPL-2.0+
>> +# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>> +
>> +if TARGET_SIPEED_MAIX
>> +
>> +config SYS_BOARD
>> +       default "maix"
>> +
>> +config SYS_VENDOR
>> +       default "sipeed"
>> +
>> +config SYS_CPU
>> +       default "generic"
>> +
>> +config SYS_CONFIG_NAME
>> +       default "sipeed-maix"
>> +
>> +config SYS_TEXT_BASE
>> +       default 0x80000000
>> +
>> +config DEFAULT_DEVICE_TREE
>> +       default "k210-maix-bit"
>> +
>> +config NR_CPUS
>> +       default 2
>> +
>> +config NR_DRAM_BANKS
>> +       default 2
>> +
>> +config BOARD_SPECIFIC_OPTIONS
>> +       def_bool y
>> +       select GENERIC_RISCV
>> +       select RISCV_PRIV_1_9_1
>> +       imply DM_SERIAL
>> +       imply SIFIVE_SERIAL
>> +       imply SIFIVE_CLINT
>> +       imply CLK_CCF
>> +       imply CLK_COMPOSITE_CCF
>> +       imply CLK_K210
>> +       imply DM_RESET
>> +       imply RESET_SYSCON
>> +       imply SYSRESET
>> +       imply SYSRESET_SYSCON
>> +       imply SPI
>> +       imply DESIGNWARE_SPI
>> +       imply SPI_FLASH_GIGADEVICE
>> +       imply MMC
>> +       imply MMC_SPI
>> +       imply MMC_BROKEN_CD
>> +       imply CMD_MMC
>> +endif
>> diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
>> new file mode 100644
>> index 0000000000..43cf61fb64
>> --- /dev/null
>> +++ b/board/sipeed/maix/MAINTAINERS
>> @@ -0,0 +1,10 @@
>> +Sipeed Maix BOARD
>> +M:     Sean Anderson <seanga2@gmail.com>
>> +S:     Maintained
>> +F:     arch/riscv/dts/k210.dtsi
>> +F:     arch/riscv/dts/k210-maix-bit.dts
>> +F:     board/sipeed/maix/
>> +F:     configs/sipeed_maix_defconfig
>> +F:     drivers/clk/kendryte/
>> +F:     include/configs/sipeed-maix.h
>> +F:     include/dt-bindings/*/k210-sysctl.h
>> diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile
>> new file mode 100644
>> index 0000000000..4acff5b31e
>> --- /dev/null
>> +++ b/board/sipeed/maix/Makefile
>> @@ -0,0 +1,5 @@
>> +# SPDX-License-Identifier: GPL-2.0+
>> +#
>> +# Copyright (c) 2019 Western Digital Corporation or its affiliates.
>> +
>> +obj-y += maix.o
>> diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c
>> new file mode 100644
>> index 0000000000..f8e773acf7
>> --- /dev/null
>> +++ b/board/sipeed/maix/maix.c
>> @@ -0,0 +1,9 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>> + */
>> +
>> +int board_init(void)
>> +{
>> +       return 0;
>> +}
>> diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig
>> new file mode 100644
>> index 0000000000..22d814ec7f
>> --- /dev/null
>> +++ b/configs/sipeed_maix_bitm_defconfig
>> @@ -0,0 +1,10 @@
>> +CONFIG_RISCV=y
>> +CONFIG_TARGET_SIPEED_MAIX=y
>> +CONFIG_ARCH_RV64I=y
>> +# CONFIG_LEGACY_IMAGE_FORMAT is not set
>> +# CONFIG_AUTOBOOT is not set
>> +# CONFIG_NET is not set
>> +# CONFIG_INPUT is not set
>> +# CONFIG_MTD is not set
>> +# CONFIG_DM_ETH is not set
>> +# CONFIG_EFI_LOADER is not set
>> diff --git a/doc/board/index.rst b/doc/board/index.rst
>> index 00e72f57cd..2bd740589b 100644
>> --- a/doc/board/index.rst
>> +++ b/doc/board/index.rst
>> @@ -13,6 +13,7 @@ Board-specific doc
>>     freescale/index
>>     google/index
>>     intel/index
>> +   kendryte/index
> 
> We should use the board vendor name: sipeed/index> 

That's what I thought, but everything else in this directory is
organized by CPU manufacturer. For example, it is
doc/board/sifive/fu450.rst, not hifive.rst. Hence the naming scheme
below.

>>     renesas/index
>>     sifive/index
>>     xilinx/index
>> diff --git a/doc/board/kendryte/index.rst b/doc/board/kendryte/index.rst
>> new file mode 100644
>> index 0000000000..5cbecd5731
>> --- /dev/null
>> +++ b/doc/board/kendryte/index.rst
>> @@ -0,0 +1,9 @@
>> +.. SPDX-License-Identifier: GPL-2.0+
>> +
>> +Kendryte
> 
> Sipeed
> 
>> +========
>> +
>> +.. toctree::
>> +   :maxdepth: 2
>> +
>> +   k210
> 
> and use the board name here: maix, or k210-maix-bit ?
> 
>> diff --git a/doc/board/kendryte/k210.rst b/doc/board/kendryte/k210.rst
>> new file mode 100644
>> index 0000000000..14e0c22637
>> --- /dev/null
>> +++ b/doc/board/kendryte/k210.rst
>> @@ -0,0 +1,46 @@
>> +.. SPDX-License-Identifier: GPL-2.0+
>> +
>> +K210
> 
> k210-maix-bit ?
> 
>> +====
>> +
>> +The Kendryte K210 processor is a 64-bit RISC-V CPU. This processor contains
>> +several peripherals to accelerate neural network processing and other "ai"
>> +tasks. This includes a "KPU" neural network processor, an audio processor
>> +supporting beamforming reception, and a digital video port supporting capture
>> +and output at VGA resolution. Other peripherals include 8M of sram (accessible
>> +with and without caching); remappable pins, including 40 GPIOs; AES, FFT, and
>> +SHA256 accelerators; a DMA controller; and I2C, I2S, and SPI controllers. Maix
>> +peripherals vary, but include spi flash; on-board usb-serial bridges; ports for
>> +cameras, displays, and sd cards; and ESP32 chips. Currently, only the Sipeed
>> +Maix Bit V2.0 (bitm) is supported, but the boards are fairly similar.
>> +
>> +Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
>> +Documentation for the Kendryte K210 is located at
>> +<https://kendryte.com/downloads/>. However, hardware details are rather lacking,
>> +so most technical reference has been taken from the standalone sdk located at
>> +<https://github.com/kendryte/kendryte-standalone-sdk>.
>> +
>> +Build and boot steps
>> +--------------------
>> +
>> +To build u-boot, run
>> +
>> +make sipeed_maix_bit_defconfig
>> +make CROSS_COMPILE=<your cross compile prefix>
>> +
>> +To flash u-boot to a maix bit, run
>> +kflash -tp /dev/<your tty here> -B bit_mic u-boot-dtb.bin
>> +
>> +Boot output should look like the following:
>> +
>> +U-Boot 2020.01-00455-gad03fd83e1 (Jan 15 2020 - 17:10:24 -0500)
>> +
>> +DRAM:  8 MiB
>> +MMC:   spi at 52000000:slot at 0: 0
>> +In:    serial at 38000000
>> +Out:   serial at 38000000
>> +Err:   serial at 38000000
>> +=>
>> +
>> +Note that spi does not work! I will try to figure out how to make it work, but
>> +for now the only way to boot something is to transfer it into ram over serial.
>> diff --git a/include/configs/sipeed-maix.h b/include/configs/sipeed-maix.h
>> new file mode 100644
>> index 0000000000..598f7dfdd0
>> --- /dev/null
>> +++ b/include/configs/sipeed-maix.h
>> @@ -0,0 +1,19 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>> + */
>> +
>> +#ifndef CONFIGS_SIPEED_MAIX_H
>> +#define CONFIGS_SIPEED_MAIX_H
>> +
>> +#include <linux/sizes.h>
>> +
>> +#define CONFIG_SYS_LOAD_ADDR 0x80000000
>> +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_LOAD_ADDR
>> +#define CONFIG_SYS_SDRAM_SIZE SZ_8M
>> +/* Start just below AI memory */
>> +#define CONFIG_SYS_INIT_SP_ADDR 0x805FFFFF
>> +#define CONFIG_SYS_MALLOC_LEN SZ_8K
>> +#define CONFIG_SYS_CACHELINE_SIZE 64
>> +
>> +#endif /* CONFIGS_SIPEED_MAIX_H */
>> --
> 
> Regards,
> Bin
> 

--Sean

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-04 14:19     ` Sean Anderson
@ 2020-02-04 14:38       ` Bin Meng
  2020-02-04 14:48         ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 14:38 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Tue, Feb 4, 2020 at 10:19 PM Sean Anderson <seanga2@gmail.com> wrote:
>
>
> On 2/4/20 6:21 AM, Bin Meng wrote:
> > Hi Sean,
> >
> > On Mon, Feb 3, 2020 at 4:05 AM Sean Anderson <seanga2@gmail.com> wrote:
> >>
> >> Some older processors (notably the Kendryte K210) use an older version of the
> >> RISC-V privileged specification. The primary changes between the old and new are
> >> in virtual memory, and in the merging of three separate counter enable CSRs.
> >> Using the new CSR on an old processor causes an illegal instruction exception.
> >> This patch adds an option to use the old CSRs instead of the new one.
> >>
> >> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> >> ---
> >> Changes for v3:
> >>   - Renamed from "riscv: Add option to disable writes to mcounteren"
> >>   - Added original functionality back for older priv specs.
> >> Changes for v2:
> >>   - Moved forward in the patch series
> >>
> >>  arch/riscv/Kconfig           | 10 ++++++++++
> >>  arch/riscv/cpu/cpu.c         |  6 ++++++
> >>  arch/riscv/include/asm/csr.h |  6 ++++++
> >>  3 files changed, 22 insertions(+)
> >>
> >> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >> index 85e15ebffa..87c40f6c4c 100644
> >> --- a/arch/riscv/Kconfig
> >> +++ b/arch/riscv/Kconfig
> >> @@ -222,6 +222,16 @@ config XIP
> >>           from a NOR flash memory without copying the code to ram.
> >>           Say yes here if U-Boot boots from flash directly.
> >>
> >> +config RISCV_PRIV_1_9_1
> >> +       bool "Use version 1.9.1 of the RISC-V priviledged specification"
> >
> > typo: privileged
> >
> >> +       help
> >> +         Older versions of the RISC-V priviledged specification had
> >
> > typo: privileged
>
> Whoops, will fix that for v4.
>
> >> +         separate counter enable CSRs for each privilege mode. Writing
> >> +         to the unified mcounteren CSR on a processor implementing the
> >> +         old specification will result in an illegal instruction
> >> +         exception. In addition to counter CSR changes, the way virtual
> >> +         memory is configured was also changed.
> >> +
> >>  config STACK_SIZE_SHIFT
> >>         int
> >>         default 14
> >> diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
> >> index e457f6acbf..83cb6557cd 100644
> >> --- a/arch/riscv/cpu/cpu.c
> >> +++ b/arch/riscv/cpu/cpu.c
> >> @@ -89,7 +89,13 @@ int arch_cpu_init_dm(void)
> >>                  * Enable perf counters for cycle, time,
> >>                  * and instret counters only
> >>                  */
> >> +#ifdef CONFIG_RISCV_PRIV_1_9_1
> >> +               /* FIXME: Can't use the macro for some reason... */
> >
> > This is weird ...
>
> I believe the macro compiles to "csrs CSR_FOO". At least with my
> gcc/binutils (9.2.0/2.33.1) this style is not available for these older
> CSRs. Perhaps it would work if we switched to letting it compile with
> the numeric CSR as defined earlier in asm/csr.h

It's already using the numeric CSR for csr_write(). Could you double check?

Regards,
Bin

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

* [PATCH v3 11/12] riscv: Add device tree for K210
  2020-02-04 14:23     ` Sean Anderson
@ 2020-02-04 14:40       ` Bin Meng
  0 siblings, 0 replies; 41+ messages in thread
From: Bin Meng @ 2020-02-04 14:40 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Tue, Feb 4, 2020 at 10:23 PM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 2/4/20 6:32 AM, Bin Meng wrote:
> > Hi Sean,
> >
> > On Mon, Feb 3, 2020 at 4:10 AM Sean Anderson <seanga2@gmail.com> wrote:
> >>
> >> Where possible, I have tried to find compatible drivers based on the layout of
> >> registers. However, I have not tested most of this functionality, and most
> >> devices should be considered descriptive at best. I would appreciate if anyone
> >> could help identify possibly compatible devices, especially for the timers
> >> and rtc.
> >>
> >> Should the size of a reg be the size of the documented registers, or the size
> >> of the address space which will be routed to that device?
> >
> > Perhaps we need use the size of the address space routed to that
> > device, in case there is some undocumented registers we need handle.
>
> Ok, I'll go with the whole address space then.
>
> >> diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
> >> new file mode 100644
> >> index 0000000000..cc46b692e6
> >> --- /dev/null
> >> +++ b/arch/riscv/dts/k210.dtsi
> >> @@ -0,0 +1,496 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/*
> >> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> >> + */
> >> +
> >> +#include <dt-bindings/clock/k210-sysctl.h>
> >> +#include <dt-bindings/mfd/k210-sysctl.h>
> >> +#include <dt-bindings/reset/k210-sysctl.h>
> >> +
> >> +/ {
> >> +       /*
> >> +        * Although the K210 is a 64-bit CPU, the address bus is only 32-bits
> >> +        * wide, and the upper half of all addresses is ignored.
> >> +        */
> >> +       #address-cells = <1>;
> >> +       #size-cells = <1>;
> >> +       compatible = "kendryte,k210";
> >> +
> >> +       aliases {
> >> +               serial0 = &uarths0;
> >> +               serial1 = &uart1;
> >> +               serial2 = &uart2;
> >> +               serial3 = &uart3;
> >> +               spi0 = &spi0;
> >> +               spi1 = &spi1;
> >> +               spi2 = &spi2;
> >> +               spi3 = &spi3;
> >> +       };
> >> +
> >> +       clocks {
> >> +               in0: oscillator {
> >> +                       compatible = "fixed-clock";
> >> +                       #clock-cells = <0>;
> >> +                       clock-frequency = <26000000>;
> >> +               };
> >> +       };
> >> +
> >> +       cpus {
> >> +               #address-cells = <1>;
> >> +               #size-cells = <0>;
> >> +               timebase-frequency = <7800000>;
> >> +               cpu0: cpu at 0 {
> >> +                       device_type = "cpu";
> >> +                       reg = <0>;
> >> +                       compatible = "riscv";
> >> +                       riscv,isa = "rv64acdfimsu";
> >> +                       mmu-type = "sv39";
> >> +                       i-cache-size = <0x8000>;
> >> +                       d-cache-size = <0x8000>;
> >> +                       clocks = <&sysclk K210_CLK_CPU>;
> >> +                       clock-frequency = <390000000>;
> >
> > I wonder there is already clocks property, why do we have another
> > clock-frequency property to provide duplicated information?
>
> This is for compatibility with the existing riscv cpu driver. There is a
> patch [1] to move the driver over to using clocks, but I think you
> already expressed that it should be merged into this series (not as a
> separate series).

Yes, so with that 2 patches in this same series, we no longer need
clock-frequency.

>
> [1] https://patchwork.ozlabs.org/project/uboot/list/?series=156381

Regards,
Bin

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

* [PATCH v3 12/12] riscv: Add initial Sipeed Maix support
  2020-02-04 14:26     ` Sean Anderson
@ 2020-02-04 14:42       ` Bin Meng
  2020-02-04 14:49         ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 14:42 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Tue, Feb 4, 2020 at 10:26 PM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 2/4/20 6:38 AM, Bin Meng wrote:
> > Hi Sean,
> >
> > On Mon, Feb 3, 2020 at 4:11 AM Sean Anderson <seanga2@gmail.com> wrote:
> >>
> >> The Sipeed Maix series is a collection of boards built around the RISC-V
> >> Kendryte K210 processor. This processor contains several peripherals to
> >> accelerate neural network processing and other "ai" tasks. This includes a "KPU"
> >> neural network processor, an audio processor supporting beamforming reception,
> >> and a digital video port supporting capture and output at VGA resolution. Other
> >> peripherals include 8M of sram (accessible with and without caching);
> >> remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA
> >> controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but
> >> include spi flash; on-board usb-serial bridges; ports for cameras, displays, and
> >> sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is
> >> supported, but the boards are fairly similar.
> >>
> >> Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
> >> Documentation for the Kendryte K210 is located at
> >> <https://kendryte.com/downloads/>. However, hardware details are rather lacking,
> >> so most technical reference has been taken from the standalone sdk located at
> >> <https://github.com/kendryte/kendryte-standalone-sdk>.
> >>
> >> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> >> ---
> >>   Changes for v3:
> >>   - Reorder to be last in the patch series
> >>   - Add documentation for the board
> >>   - Generate defconfig with "make savedefconfig"
> >>   - Update Kconfig to imply most features we need
> >>   - Update MAINTAINERS
> >>   Changes for v2:
> >>   - Select CONFIG_SYS_RISCV_NOCOUNTER
> >>   - Imply CONFIG_CLK_K210
> >>   - Remove spurious references to CONFIG_ARCH_K210
> >>   - Remove many configs from defconfig where the defaults were fine
> >>   - Add a few "not set" lines to suppress unneeded defaults
> >>   - Reduce pre-reloc malloc space, now that clocks initialization happens later
> >>
> >>  arch/riscv/Kconfig                 |  4 +++
> >>  board/sipeed/maix/Kconfig          | 51 ++++++++++++++++++++++++++++++
> >>  board/sipeed/maix/MAINTAINERS      | 10 ++++++
> >>  board/sipeed/maix/Makefile         |  5 +++
> >>  board/sipeed/maix/maix.c           |  9 ++++++
> >>  configs/sipeed_maix_bitm_defconfig | 10 ++++++
> >>  doc/board/index.rst                |  1 +
> >>  doc/board/kendryte/index.rst       |  9 ++++++
> >>  doc/board/kendryte/k210.rst        | 46 +++++++++++++++++++++++++++
> >>  include/configs/sipeed-maix.h      | 19 +++++++++++
> >>  10 files changed, 164 insertions(+)
> >>  create mode 100644 board/sipeed/maix/Kconfig
> >>  create mode 100644 board/sipeed/maix/MAINTAINERS
> >>  create mode 100644 board/sipeed/maix/Makefile
> >>  create mode 100644 board/sipeed/maix/maix.c
> >>  create mode 100644 configs/sipeed_maix_bitm_defconfig
> >>  create mode 100644 doc/board/kendryte/index.rst
> >>  create mode 100644 doc/board/kendryte/k210.rst
> >>  create mode 100644 include/configs/sipeed-maix.h
> >>
> >> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> >> index 87c40f6c4c..81ab35dd2d 100644
> >> --- a/arch/riscv/Kconfig
> >> +++ b/arch/riscv/Kconfig
> >> @@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT
> >>  config TARGET_SIFIVE_FU540
> >>         bool "Support SiFive FU540 Board"
> >>
> >> +config TARGET_SIPEED_MAIX
> >> +       bool "Support Sipeed Maix Board"
> >> +
> >>  endchoice
> >>
> >>  config SYS_ICACHE_OFF
> >> @@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig"
> >>  source "board/emulation/qemu-riscv/Kconfig"
> >>  source "board/microchip/mpfs_icicle/Kconfig"
> >>  source "board/sifive/fu540/Kconfig"
> >> +source "board/sipeed/maix/Kconfig"
> >>
> >>  # platform-specific options below
> >>  source "arch/riscv/cpu/ax25/Kconfig"
> >> diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
> >> new file mode 100644
> >> index 0000000000..b23d2448d9
> >> --- /dev/null
> >> +++ b/board/sipeed/maix/Kconfig
> >> @@ -0,0 +1,51 @@
> >> +# SPDX-License-Identifier: GPL-2.0+
> >> +# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> >> +
> >> +if TARGET_SIPEED_MAIX
> >> +
> >> +config SYS_BOARD
> >> +       default "maix"
> >> +
> >> +config SYS_VENDOR
> >> +       default "sipeed"
> >> +
> >> +config SYS_CPU
> >> +       default "generic"
> >> +
> >> +config SYS_CONFIG_NAME
> >> +       default "sipeed-maix"
> >> +
> >> +config SYS_TEXT_BASE
> >> +       default 0x80000000
> >> +
> >> +config DEFAULT_DEVICE_TREE
> >> +       default "k210-maix-bit"
> >> +
> >> +config NR_CPUS
> >> +       default 2
> >> +
> >> +config NR_DRAM_BANKS
> >> +       default 2
> >> +
> >> +config BOARD_SPECIFIC_OPTIONS
> >> +       def_bool y
> >> +       select GENERIC_RISCV
> >> +       select RISCV_PRIV_1_9_1
> >> +       imply DM_SERIAL
> >> +       imply SIFIVE_SERIAL
> >> +       imply SIFIVE_CLINT
> >> +       imply CLK_CCF
> >> +       imply CLK_COMPOSITE_CCF
> >> +       imply CLK_K210
> >> +       imply DM_RESET
> >> +       imply RESET_SYSCON
> >> +       imply SYSRESET
> >> +       imply SYSRESET_SYSCON
> >> +       imply SPI
> >> +       imply DESIGNWARE_SPI
> >> +       imply SPI_FLASH_GIGADEVICE
> >> +       imply MMC
> >> +       imply MMC_SPI
> >> +       imply MMC_BROKEN_CD
> >> +       imply CMD_MMC
> >> +endif
> >> diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
> >> new file mode 100644
> >> index 0000000000..43cf61fb64
> >> --- /dev/null
> >> +++ b/board/sipeed/maix/MAINTAINERS
> >> @@ -0,0 +1,10 @@
> >> +Sipeed Maix BOARD
> >> +M:     Sean Anderson <seanga2@gmail.com>
> >> +S:     Maintained
> >> +F:     arch/riscv/dts/k210.dtsi
> >> +F:     arch/riscv/dts/k210-maix-bit.dts
> >> +F:     board/sipeed/maix/
> >> +F:     configs/sipeed_maix_defconfig
> >> +F:     drivers/clk/kendryte/
> >> +F:     include/configs/sipeed-maix.h
> >> +F:     include/dt-bindings/*/k210-sysctl.h
> >> diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile
> >> new file mode 100644
> >> index 0000000000..4acff5b31e
> >> --- /dev/null
> >> +++ b/board/sipeed/maix/Makefile
> >> @@ -0,0 +1,5 @@
> >> +# SPDX-License-Identifier: GPL-2.0+
> >> +#
> >> +# Copyright (c) 2019 Western Digital Corporation or its affiliates.
> >> +
> >> +obj-y += maix.o
> >> diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c
> >> new file mode 100644
> >> index 0000000000..f8e773acf7
> >> --- /dev/null
> >> +++ b/board/sipeed/maix/maix.c
> >> @@ -0,0 +1,9 @@
> >> +// SPDX-License-Identifier: GPL-2.0+
> >> +/*
> >> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> >> + */
> >> +
> >> +int board_init(void)
> >> +{
> >> +       return 0;
> >> +}
> >> diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig
> >> new file mode 100644
> >> index 0000000000..22d814ec7f
> >> --- /dev/null
> >> +++ b/configs/sipeed_maix_bitm_defconfig
> >> @@ -0,0 +1,10 @@
> >> +CONFIG_RISCV=y
> >> +CONFIG_TARGET_SIPEED_MAIX=y
> >> +CONFIG_ARCH_RV64I=y
> >> +# CONFIG_LEGACY_IMAGE_FORMAT is not set
> >> +# CONFIG_AUTOBOOT is not set
> >> +# CONFIG_NET is not set
> >> +# CONFIG_INPUT is not set
> >> +# CONFIG_MTD is not set
> >> +# CONFIG_DM_ETH is not set
> >> +# CONFIG_EFI_LOADER is not set
> >> diff --git a/doc/board/index.rst b/doc/board/index.rst
> >> index 00e72f57cd..2bd740589b 100644
> >> --- a/doc/board/index.rst
> >> +++ b/doc/board/index.rst
> >> @@ -13,6 +13,7 @@ Board-specific doc
> >>     freescale/index
> >>     google/index
> >>     intel/index
> >> +   kendryte/index
> >
> > We should use the board vendor name: sipeed/index>
>
> That's what I thought, but everything else in this directory is
> organized by CPU manufacturer. For example, it is

No it's organized by the board manufacturer. It's just the same vendor
that happens to the the CPU manufacturer.

> doc/board/sifive/fu450.rst, not hifive.rst. Hence the naming scheme

I would vote for changing it to hifive_unleashed.

> below.
>
> >>     renesas/index
> >>     sifive/index
> >>     xilinx/index

[snip]

Regards,
Bin

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-04 14:38       ` Bin Meng
@ 2020-02-04 14:48         ` Sean Anderson
  2020-02-04 16:04           ` Bin Meng
  0 siblings, 1 reply; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:48 UTC (permalink / raw)
  To: u-boot

On 2/4/20 9:38 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Tue, Feb 4, 2020 at 10:19 PM Sean Anderson <seanga2@gmail.com> wrote:
>> I believe the macro compiles to "csrs CSR_FOO". At least with my
>> gcc/binutils (9.2.0/2.33.1) this style is not available for these older
>> CSRs. Perhaps it would work if we switched to letting it compile with
>> the numeric CSR as defined earlier in asm/csr.h
> 
> It's already using the numeric CSR for csr_write(). Could you double check?

Well, the current definition is

#define csr_write(csr, val)					\
({								\
	unsigned long __v = (unsigned long)(val);		\
	__asm__ __volatile__ ("csrw " __ASM_STR(csr) ", %0"	\
			      : : "rK" (__v)			\
			      : "memory");			\
})

and _ASM_STR(csr) evaluates to #csr. I think that results in something
like

__asm__("csrw " "CSR_FOO" ", %0"

In any case, the errors I get are

arch/riscv/cpu/cpu.c: Assembler messages:
arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'
arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'

which doesn't seem like a numeric CSR to me.

--Sean

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

* [PATCH v3 12/12] riscv: Add initial Sipeed Maix support
  2020-02-04 14:42       ` Bin Meng
@ 2020-02-04 14:49         ` Sean Anderson
  0 siblings, 0 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 14:49 UTC (permalink / raw)
  To: u-boot

On 2/4/20 9:42 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Tue, Feb 4, 2020 at 10:26 PM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> On 2/4/20 6:38 AM, Bin Meng wrote:
>>> Hi Sean,
>>>
>>> On Mon, Feb 3, 2020 at 4:11 AM Sean Anderson <seanga2@gmail.com> wrote:
>>>>
>>>> The Sipeed Maix series is a collection of boards built around the RISC-V
>>>> Kendryte K210 processor. This processor contains several peripherals to
>>>> accelerate neural network processing and other "ai" tasks. This includes a "KPU"
>>>> neural network processor, an audio processor supporting beamforming reception,
>>>> and a digital video port supporting capture and output at VGA resolution. Other
>>>> peripherals include 8M of sram (accessible with and without caching);
>>>> remappable pins, including 40 GPIOs; AES, FFT, and SHA256 accelerators; a DMA
>>>> controller; and I2C, I2S, and SPI controllers. Maix peripherals vary, but
>>>> include spi flash; on-board usb-serial bridges; ports for cameras, displays, and
>>>> sd cards; and ESP32 chips. Currently, only the Sipeed Maix Bit V2.0 (bitm) is
>>>> supported, but the boards are fairly similar.
>>>>
>>>> Documentation for Maix boards is located at <http://dl.sipeed.com/MAIX/HDK/>.
>>>> Documentation for the Kendryte K210 is located at
>>>> <https://kendryte.com/downloads/>. However, hardware details are rather lacking,
>>>> so most technical reference has been taken from the standalone sdk located at
>>>> <https://github.com/kendryte/kendryte-standalone-sdk>.
>>>>
>>>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>>>> ---
>>>>   Changes for v3:
>>>>   - Reorder to be last in the patch series
>>>>   - Add documentation for the board
>>>>   - Generate defconfig with "make savedefconfig"
>>>>   - Update Kconfig to imply most features we need
>>>>   - Update MAINTAINERS
>>>>   Changes for v2:
>>>>   - Select CONFIG_SYS_RISCV_NOCOUNTER
>>>>   - Imply CONFIG_CLK_K210
>>>>   - Remove spurious references to CONFIG_ARCH_K210
>>>>   - Remove many configs from defconfig where the defaults were fine
>>>>   - Add a few "not set" lines to suppress unneeded defaults
>>>>   - Reduce pre-reloc malloc space, now that clocks initialization happens later
>>>>
>>>>  arch/riscv/Kconfig                 |  4 +++
>>>>  board/sipeed/maix/Kconfig          | 51 ++++++++++++++++++++++++++++++
>>>>  board/sipeed/maix/MAINTAINERS      | 10 ++++++
>>>>  board/sipeed/maix/Makefile         |  5 +++
>>>>  board/sipeed/maix/maix.c           |  9 ++++++
>>>>  configs/sipeed_maix_bitm_defconfig | 10 ++++++
>>>>  doc/board/index.rst                |  1 +
>>>>  doc/board/kendryte/index.rst       |  9 ++++++
>>>>  doc/board/kendryte/k210.rst        | 46 +++++++++++++++++++++++++++
>>>>  include/configs/sipeed-maix.h      | 19 +++++++++++
>>>>  10 files changed, 164 insertions(+)
>>>>  create mode 100644 board/sipeed/maix/Kconfig
>>>>  create mode 100644 board/sipeed/maix/MAINTAINERS
>>>>  create mode 100644 board/sipeed/maix/Makefile
>>>>  create mode 100644 board/sipeed/maix/maix.c
>>>>  create mode 100644 configs/sipeed_maix_bitm_defconfig
>>>>  create mode 100644 doc/board/kendryte/index.rst
>>>>  create mode 100644 doc/board/kendryte/k210.rst
>>>>  create mode 100644 include/configs/sipeed-maix.h
>>>>
>>>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>>>> index 87c40f6c4c..81ab35dd2d 100644
>>>> --- a/arch/riscv/Kconfig
>>>> +++ b/arch/riscv/Kconfig
>>>> @@ -20,6 +20,9 @@ config TARGET_QEMU_VIRT
>>>>  config TARGET_SIFIVE_FU540
>>>>         bool "Support SiFive FU540 Board"
>>>>
>>>> +config TARGET_SIPEED_MAIX
>>>> +       bool "Support Sipeed Maix Board"
>>>> +
>>>>  endchoice
>>>>
>>>>  config SYS_ICACHE_OFF
>>>> @@ -53,6 +56,7 @@ source "board/AndesTech/ax25-ae350/Kconfig"
>>>>  source "board/emulation/qemu-riscv/Kconfig"
>>>>  source "board/microchip/mpfs_icicle/Kconfig"
>>>>  source "board/sifive/fu540/Kconfig"
>>>> +source "board/sipeed/maix/Kconfig"
>>>>
>>>>  # platform-specific options below
>>>>  source "arch/riscv/cpu/ax25/Kconfig"
>>>> diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
>>>> new file mode 100644
>>>> index 0000000000..b23d2448d9
>>>> --- /dev/null
>>>> +++ b/board/sipeed/maix/Kconfig
>>>> @@ -0,0 +1,51 @@
>>>> +# SPDX-License-Identifier: GPL-2.0+
>>>> +# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>>>> +
>>>> +if TARGET_SIPEED_MAIX
>>>> +
>>>> +config SYS_BOARD
>>>> +       default "maix"
>>>> +
>>>> +config SYS_VENDOR
>>>> +       default "sipeed"
>>>> +
>>>> +config SYS_CPU
>>>> +       default "generic"
>>>> +
>>>> +config SYS_CONFIG_NAME
>>>> +       default "sipeed-maix"
>>>> +
>>>> +config SYS_TEXT_BASE
>>>> +       default 0x80000000
>>>> +
>>>> +config DEFAULT_DEVICE_TREE
>>>> +       default "k210-maix-bit"
>>>> +
>>>> +config NR_CPUS
>>>> +       default 2
>>>> +
>>>> +config NR_DRAM_BANKS
>>>> +       default 2
>>>> +
>>>> +config BOARD_SPECIFIC_OPTIONS
>>>> +       def_bool y
>>>> +       select GENERIC_RISCV
>>>> +       select RISCV_PRIV_1_9_1
>>>> +       imply DM_SERIAL
>>>> +       imply SIFIVE_SERIAL
>>>> +       imply SIFIVE_CLINT
>>>> +       imply CLK_CCF
>>>> +       imply CLK_COMPOSITE_CCF
>>>> +       imply CLK_K210
>>>> +       imply DM_RESET
>>>> +       imply RESET_SYSCON
>>>> +       imply SYSRESET
>>>> +       imply SYSRESET_SYSCON
>>>> +       imply SPI
>>>> +       imply DESIGNWARE_SPI
>>>> +       imply SPI_FLASH_GIGADEVICE
>>>> +       imply MMC
>>>> +       imply MMC_SPI
>>>> +       imply MMC_BROKEN_CD
>>>> +       imply CMD_MMC
>>>> +endif
>>>> diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
>>>> new file mode 100644
>>>> index 0000000000..43cf61fb64
>>>> --- /dev/null
>>>> +++ b/board/sipeed/maix/MAINTAINERS
>>>> @@ -0,0 +1,10 @@
>>>> +Sipeed Maix BOARD
>>>> +M:     Sean Anderson <seanga2@gmail.com>
>>>> +S:     Maintained
>>>> +F:     arch/riscv/dts/k210.dtsi
>>>> +F:     arch/riscv/dts/k210-maix-bit.dts
>>>> +F:     board/sipeed/maix/
>>>> +F:     configs/sipeed_maix_defconfig
>>>> +F:     drivers/clk/kendryte/
>>>> +F:     include/configs/sipeed-maix.h
>>>> +F:     include/dt-bindings/*/k210-sysctl.h
>>>> diff --git a/board/sipeed/maix/Makefile b/board/sipeed/maix/Makefile
>>>> new file mode 100644
>>>> index 0000000000..4acff5b31e
>>>> --- /dev/null
>>>> +++ b/board/sipeed/maix/Makefile
>>>> @@ -0,0 +1,5 @@
>>>> +# SPDX-License-Identifier: GPL-2.0+
>>>> +#
>>>> +# Copyright (c) 2019 Western Digital Corporation or its affiliates.
>>>> +
>>>> +obj-y += maix.o
>>>> diff --git a/board/sipeed/maix/maix.c b/board/sipeed/maix/maix.c
>>>> new file mode 100644
>>>> index 0000000000..f8e773acf7
>>>> --- /dev/null
>>>> +++ b/board/sipeed/maix/maix.c
>>>> @@ -0,0 +1,9 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
>>>> + */
>>>> +
>>>> +int board_init(void)
>>>> +{
>>>> +       return 0;
>>>> +}
>>>> diff --git a/configs/sipeed_maix_bitm_defconfig b/configs/sipeed_maix_bitm_defconfig
>>>> new file mode 100644
>>>> index 0000000000..22d814ec7f
>>>> --- /dev/null
>>>> +++ b/configs/sipeed_maix_bitm_defconfig
>>>> @@ -0,0 +1,10 @@
>>>> +CONFIG_RISCV=y
>>>> +CONFIG_TARGET_SIPEED_MAIX=y
>>>> +CONFIG_ARCH_RV64I=y
>>>> +# CONFIG_LEGACY_IMAGE_FORMAT is not set
>>>> +# CONFIG_AUTOBOOT is not set
>>>> +# CONFIG_NET is not set
>>>> +# CONFIG_INPUT is not set
>>>> +# CONFIG_MTD is not set
>>>> +# CONFIG_DM_ETH is not set
>>>> +# CONFIG_EFI_LOADER is not set
>>>> diff --git a/doc/board/index.rst b/doc/board/index.rst
>>>> index 00e72f57cd..2bd740589b 100644
>>>> --- a/doc/board/index.rst
>>>> +++ b/doc/board/index.rst
>>>> @@ -13,6 +13,7 @@ Board-specific doc
>>>>     freescale/index
>>>>     google/index
>>>>     intel/index
>>>> +   kendryte/index
>>>
>>> We should use the board vendor name: sipeed/index>
>>
>> That's what I thought, but everything else in this directory is
>> organized by CPU manufacturer. For example, it is
> 
> No it's organized by the board manufacturer. It's just the same vendor
> that happens to the the CPU manufacturer.

Ah, ok. I will change this for v4 then.

>> doc/board/sifive/fu450.rst, not hifive.rst. Hence the naming scheme
> 
> I would vote for changing it to hifive_unleashed.
> 
>> below.
>>
>>>>     renesas/index
>>>>     sifive/index
>>>>     xilinx/index
> 
> [snip]
> 
> Regards,
> Bin
> 

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-04 14:48         ` Sean Anderson
@ 2020-02-04 16:04           ` Bin Meng
  2020-02-04 16:07             ` Sean Anderson
  0 siblings, 1 reply; 41+ messages in thread
From: Bin Meng @ 2020-02-04 16:04 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Tue, Feb 4, 2020 at 10:48 PM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 2/4/20 9:38 AM, Bin Meng wrote:
> > Hi Sean,
> >
> > On Tue, Feb 4, 2020 at 10:19 PM Sean Anderson <seanga2@gmail.com> wrote:
> >> I believe the macro compiles to "csrs CSR_FOO". At least with my
> >> gcc/binutils (9.2.0/2.33.1) this style is not available for these older
> >> CSRs. Perhaps it would work if we switched to letting it compile with
> >> the numeric CSR as defined earlier in asm/csr.h
> >
> > It's already using the numeric CSR for csr_write(). Could you double check?
>
> Well, the current definition is
>
> #define csr_write(csr, val)                                     \
> ({                                                              \
>         unsigned long __v = (unsigned long)(val);               \
>         __asm__ __volatile__ ("csrw " __ASM_STR(csr) ", %0"     \
>                               : : "rK" (__v)                    \
>                               : "memory");                      \
> })
>
> and _ASM_STR(csr) evaluates to #csr. I think that results in something
> like
>
> __asm__("csrw " "CSR_FOO" ", %0"

Yes, this generates numeric CSR for us.

>
> In any case, the errors I get are
>
> arch/riscv/cpu/cpu.c: Assembler messages:
> arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'
> arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'
>
> which doesn't seem like a numeric CSR to me.

Oops, I did a careful look and found that's because 'CSR_MSCOUNTEREN'
is undefined.

+#ifdef RISCV_PRIV_1_9_1

This should be: CONFIG_RISCV_PRIV_1_9_1

+#define CSR_MUCOUNTEREN         0x320
+#define CSR_MSCOUNTEREN         0x321
+#define CSR_MHCOUNTEREN         0x322
+#else
 #define CSR_MCOUNTEREN         0x306
+#endif

Regards,
Bin

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

* [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1
  2020-02-04 16:04           ` Bin Meng
@ 2020-02-04 16:07             ` Sean Anderson
  0 siblings, 0 replies; 41+ messages in thread
From: Sean Anderson @ 2020-02-04 16:07 UTC (permalink / raw)
  To: u-boot

On 2/4/20 11:04 AM, Bin Meng wrote:
> Hi Sean,
> 
> On Tue, Feb 4, 2020 at 10:48 PM Sean Anderson <seanga2@gmail.com> wrote:
>> In any case, the errors I get are
>>
>> arch/riscv/cpu/cpu.c: Assembler messages:
>> arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'
>> arch/riscv/cpu/cpu.c:94: Error: unknown CSR `CSR_MSCOUNTEREN'
>>
>> which doesn't seem like a numeric CSR to me.
> 
> Oops, I did a careful look and found that's because 'CSR_MSCOUNTEREN'
> is undefined.
> 
> +#ifdef RISCV_PRIV_1_9_1
> 
> This should be: CONFIG_RISCV_PRIV_1_9_1
> 
> +#define CSR_MUCOUNTEREN         0x320
> +#define CSR_MSCOUNTEREN         0x321
> +#define CSR_MHCOUNTEREN         0x322
> +#else
>  #define CSR_MCOUNTEREN         0x306
> +#endif
> 
> Regards,
> Bin

Ah, good catch, thanks. I'll be sure to fix that for v4.

--Sean

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

* [PATCH v3 05/12] dm: Add support for simple-pm-bus
  2020-02-03 23:15     ` Sean Anderson
@ 2020-02-05  0:16       ` Simon Glass
  0 siblings, 0 replies; 41+ messages in thread
From: Simon Glass @ 2020-02-05  0:16 UTC (permalink / raw)
  To: u-boot

Hi Sean,

On Mon, 3 Feb 2020 at 16:15, Sean Anderson <seanga2@gmail.com> wrote:
>
> > Please can you add a test for this new functionality?
>
> Should this be separate from test/dm/bus.c? As far as I can tell, that
> file tests the concept of busses, and not the bus uclass.

Yes it is fine to add a test/dm/simple-bus.c

Regards,
Simon

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

* [PATCH v3 01/12] clk: Always use the supplied struct clk
  2020-02-02 19:58 ` [PATCH v3 01/12] clk: Always use the supplied struct clk Sean Anderson
@ 2020-02-06 21:21   ` Lukasz Majewski
       [not found]     ` <752D002CFF5D0F4FA35C0100F1D73F3FA46D30F5@ATCPCS16.andestech.com>
  0 siblings, 1 reply; 41+ messages in thread
From: Lukasz Majewski @ 2020-02-06 21:21 UTC (permalink / raw)
  To: u-boot

Hi Sean,

> CCF clocks should always use the struct clock passed to their methods
> for extracting the driver-specific clock information struct.
> Previously, many functions would use the clk->dev->priv if the device
> was bound. This could cause problems with composite clocks. The
> individual clocks in a composite clock did not have the ->dev field
> filled in. This was fine, because the device-specific clock
> information would be used. However, since there was no ->dev, there
> was no way to get the parent clock. This caused the recalc_rate
> method of the CCF divider clock to fail. One option would be to use
> the clk->priv field to get the composite clock and from there get the
> appropriate parent device. However, this would tie the implementation
> to the composite clock. In general, different devices should not rely
> on the contents of ->priv from another device.
> 
> The simple solution to this problem is to just always use the
> supplied struct clock. The composite clock now fills in the ->dev
> pointer of its child clocks. This allows child clocks to make calls
> like clk_get_parent() without issue.
> 
> imx avoided the above problem by using a custom get_rate function
> with composite clocks.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>

Thank you Sean for your CCF enhancement and updating the ccf.txt
documentation entry.

Acked-by: Lukasz Majewski <lukma@denx.de>

I don't mind if RISC-V SoC maintainer pulls the whole series (including
CCF patches).

> ---
>   Changes for v3:
>   - Documented new assumptions in the CCF
>   - Wrapped docs to 80 columns
> 
>  doc/imx/clk/ccf.txt            | 63
> +++++++++++++++++----------------- drivers/clk/clk-composite.c    |
> 8 +++++ drivers/clk/clk-divider.c      |  6 ++--
>  drivers/clk/clk-fixed-factor.c |  3 +-
>  drivers/clk/clk-gate.c         |  6 ++--
>  drivers/clk/clk-mux.c          | 12 +++----
>  drivers/clk/imx/clk-gate2.c    |  4 +--
>  7 files changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/doc/imx/clk/ccf.txt b/doc/imx/clk/ccf.txt
> index 36b60dc438..e40ac360e8 100644
> --- a/doc/imx/clk/ccf.txt
> +++ b/doc/imx/clk/ccf.txt
> @@ -1,42 +1,37 @@
>  Introduction:
>  =============
>  
> -This documentation entry describes the Common Clock Framework [CCF]
> -port from Linux kernel (v5.1.12) to U-Boot.
> +This documentation entry describes the Common Clock Framework [CCF]
> port from +Linux kernel (v5.1.12) to U-Boot.
>  
> -This code is supposed to bring CCF to IMX based devices (imx6q, imx7
> -imx8). Moreover, it also provides some common clock code, which would
> -allow easy porting of CCF Linux code to other platforms.
> +This code is supposed to bring CCF to IMX based devices (imx6q, imx7
> imx8). +Moreover, it also provides some common clock code, which
> would allow easy +porting of CCF Linux code to other platforms.
>  
>  Design decisions:
>  =================
>  
> -* U-Boot's driver model [DM] for clk differs from Linux CCF. The most
> -  notably difference is the lack of support for hierarchical clocks
> and
> -  "clock as a manager driver" (single clock DTS node acts as a
> starting
> -  point for all other clocks).
> +* U-Boot's driver model [DM] for clk differs from Linux CCF. The
> most notably
> +  difference is the lack of support for hierarchical clocks and
> "clock as a
> +  manager driver" (single clock DTS node acts as a starting point
> for all other
> +  clocks).
>  
> -* The clk_get_rate() caches the previously read data if
> CLK_GET_RATE_NOCACHE
> -  is not set (no need for recursive access).
> +* The clk_get_rate() caches the previously read data if
> CLK_GET_RATE_NOCACHE is
> +  not set (no need for recursive access).
>  
> -* On purpose the "manager" clk driver (clk-imx6q.c) is not using
> large
> -  table to store pointers to clocks - e.g.
> clk[IMX6QDL_CLK_USDHC2_SEL] = ....
> -  Instead we use udevice's linked list for the same class
> (UCLASS_CLK). +* On purpose the "manager" clk driver (clk-imx6q.c) is
> not using large table to
> +  store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = ....
> Instead we
> +  use udevice's linked list for the same class (UCLASS_CLK).
>  
>    Rationale:
>    ----------
> -    When porting the code as is from Linux, one would need ~1KiB of
> RAM to
> -    store it. This is way too much if we do plan to use this driver
> in SPL.
> +    When porting the code as is from Linux, one would need ~1KiB of
> RAM to store
> +    it. This is way too much if we do plan to use this driver in SPL.
>  
>  * The "central" structure of this patch series is struct udevice and
> its uclass_priv field contains the struct clk pointer (to the
> originally created one).
>  
> -* Up till now U-Boot's driver model (DM) CLK operates on udevice
> (main
> -  access to clock is by udevice ops)
> -  In the CCF the access to struct clk (embodying pointer to *dev) is
> -  possible via dev_get_clk_ptr() (it is a wrapper on
> dev_get_uclass_priv()). -
>  * To keep things simple the struct udevice's uclass_priv pointer is
> used to store back pointer to corresponding struct clk. However, it
> is possible to modify clk-uclass.c file and add there struct
> uc_clk_priv, which would have @@ -45,13 +40,17 @@ Design decisions:
>    setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv))
> the uclass_priv stores the pointer to struct clk.
>  
> +* Non-CCF clocks do not have a pointer to a clock in clk->dev->priv.
> In the case
> +  of composite clocks, clk->dev->priv may not match clk. Drivers
> should always
> +  use the struct clk which is passed to them, and not clk->dev->priv.
> +
>  * It is advised to add common clock code (like already added rate
> and flags) to the struct clk, which is a top level description of the
> clock. 
>  * U-Boot's driver model already provides the facility to
> automatically allocate
> -  (via private_alloc_size) device private data (accessible via
> dev->priv).
> -  It may look appealing to use this feature to allocate private
> structures for
> -  CCF clk devices e.g. divider (struct clk_divider *divider) for
> IMX6Q clock.
> +  (via private_alloc_size) device private data (accessible via
> dev->priv). It
> +  may look appealing to use this feature to allocate private
> structures for CCF
> +  clk devices e.g. divider (struct clk_divider *divider) for IMX6Q
> clock. 
>    The above feature had not been used for following reasons:
>    - The original CCF Linux kernel driver is the "manager" for clocks
> - it @@ -64,21 +63,23 @@ Design decisions:
>  
>  * I've added the clk_get_parent(), which reads parent's
> dev->uclass_priv to provide parent's struct clk pointer. This seems
> the easiest way to get
> -  child/parent relationship for struct clk in U-Boot's udevice based
> clocks.
> +  child/parent relationship for struct clk in U-Boot's udevice based
> clocks.  In
> +  the future arbitrary parents may be supported by adding a
> get_parent function
> +  to clk_ops.
>  
>  * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in
> 'struct clk'. Clock IP block agnostic flags from 'struct clk_core'
> (e.g. NOCACHE) have been
> -  moved from this struct one level up to 'struct clk'.
> +  moved from this struct one level up to 'struct clk'. Many flags are
> +  unimplemented at the moment.
>  
>  * For tests the new ./test/dm/clk_ccf.c and
> ./drivers/clk/clk_sandbox_ccf.c files have been introduced. The
> latter setups the CCF clock structure for
> -  sandbox by reusing, if possible, generic clock primitives - like
> divier
> -  and mux. The former file provides code to tests this setup.
> +  sandbox by reusing, if possible, generic clock primitives - like
> divier and
> +  mux. The former file provides code to tests this setup.
>  
>    For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been
> introduced.
> -  All new primitives added for new architectures must have
> corresponding test
> -  in the two aforementioned files.
> -
> +  All new primitives added for new architectures must have
> corresponding test in
> +  the two aforementioned files.
>  
>  Testing (sandbox):
>  ==================
> diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> index a5626c33d1..d0f273d47f 100644
> --- a/drivers/clk/clk-composite.c
> +++ b/drivers/clk/clk-composite.c
> @@ -145,6 +145,14 @@ struct clk *clk_register_composite(struct device
> *dev, const char *name, goto err;
>  	}
>  
> +	if (composite->mux)
> +		composite->mux->dev = clk->dev;
> +	if (composite->rate)
> +		composite->rate->dev = clk->dev;
> +	if (composite->gate)
> +		composite->gate->dev = clk->dev;
> +
> +
>  	return clk;
>  
>  err:
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 822e09b084..bfa05f24a3 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -70,8 +70,7 @@ unsigned long divider_recalc_rate(struct clk *hw,
> unsigned long parent_rate, 
>  static ulong clk_divider_recalc_rate(struct clk *clk)
>  {
> -	struct clk_divider *divider =
> to_clk_divider(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_divider *divider = to_clk_divider(clk);
>  	unsigned long parent_rate = clk_get_parent_rate(clk);
>  	unsigned int val;
>  
> @@ -150,8 +149,7 @@ int divider_get_val(unsigned long rate, unsigned
> long parent_rate, 
>  static ulong clk_divider_set_rate(struct clk *clk, unsigned long
> rate) {
> -	struct clk_divider *divider =
> to_clk_divider(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_divider *divider = to_clk_divider(clk);
>  	unsigned long parent_rate = clk_get_parent_rate(clk);
>  	int value;
>  	u32 val;
> diff --git a/drivers/clk/clk-fixed-factor.c
> b/drivers/clk/clk-fixed-factor.c index 711b0588bc..d2401cf440 100644
> --- a/drivers/clk/clk-fixed-factor.c
> +++ b/drivers/clk/clk-fixed-factor.c
> @@ -18,8 +18,7 @@
>  
>  static ulong clk_factor_recalc_rate(struct clk *clk)
>  {
> -	struct clk_fixed_factor *fix =
> -		to_clk_fixed_factor(dev_get_clk_ptr(clk->dev));
> +	struct clk_fixed_factor *fix = to_clk_fixed_factor(clk);
>  	unsigned long parent_rate = clk_get_parent_rate(clk);
>  	unsigned long long int rate;
>  
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index 70b8794554..b2933bc24a 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -43,8 +43,7 @@
>   */
>  static void clk_gate_endisable(struct clk *clk, int enable)
>  {
> -	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_gate *gate = to_clk_gate(clk);
>  	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
>  	u32 reg;
>  
> @@ -86,8 +85,7 @@ static int clk_gate_disable(struct clk *clk)
>  
>  int clk_gate_is_enabled(struct clk *clk)
>  {
> -	struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_gate *gate = to_clk_gate(clk);
>  	u32 reg;
>  
>  #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> index 5acc0b8cbd..67b4afef28 100644
> --- a/drivers/clk/clk-mux.c
> +++ b/drivers/clk/clk-mux.c
> @@ -35,8 +35,7 @@
>  int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int
> flags, unsigned int val)
>  {
> -	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_mux *mux = to_clk_mux(clk);
>  	int num_parents = mux->num_parents;
>  
>  	if (table) {
> @@ -79,8 +78,7 @@ unsigned int clk_mux_index_to_val(u32 *table,
> unsigned int flags, u8 index) 
>  u8 clk_mux_get_parent(struct clk *clk)
>  {
> -	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_mux *mux = to_clk_mux(clk);
>  	u32 val;
>  
>  #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
> @@ -97,8 +95,7 @@ u8 clk_mux_get_parent(struct clk *clk)
>  static int clk_fetch_parent_index(struct clk *clk,
>  				  struct clk *parent)
>  {
> -	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_mux *mux = to_clk_mux(clk);
>  
>  	int i;
>  
> @@ -115,8 +112,7 @@ static int clk_fetch_parent_index(struct clk *clk,
>  
>  static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
>  {
> -	struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> -			dev_get_clk_ptr(clk->dev) : clk);
> +	struct clk_mux *mux = to_clk_mux(clk);
>  	int index;
>  	u32 val;
>  	u32 reg;
> diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
> index 1b9db6e791..e32c0cb53e 100644
> --- a/drivers/clk/imx/clk-gate2.c
> +++ b/drivers/clk/imx/clk-gate2.c
> @@ -37,7 +37,7 @@ struct clk_gate2 {
>  
>  static int clk_gate2_enable(struct clk *clk)
>  {
> -	struct clk_gate2 *gate =
> to_clk_gate2(dev_get_clk_ptr(clk->dev));
> +	struct clk_gate2 *gate = to_clk_gate2(clk);
>  	u32 reg;
>  
>  	reg = readl(gate->reg);
> @@ -50,7 +50,7 @@ static int clk_gate2_enable(struct clk *clk)
>  
>  static int clk_gate2_disable(struct clk *clk)
>  {
> -	struct clk_gate2 *gate =
> to_clk_gate2(dev_get_clk_ptr(clk->dev));
> +	struct clk_gate2 *gate = to_clk_gate2(clk);
>  	u32 reg;
>  
>  	reg = readl(gate->reg);




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200206/d62c0e29/attachment.sig>

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

* [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling
  2020-02-02 19:58 ` [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling Sean Anderson
@ 2020-02-06 21:41   ` Lukasz Majewski
  0 siblings, 0 replies; 41+ messages in thread
From: Lukasz Majewski @ 2020-02-06 21:41 UTC (permalink / raw)
  To: u-boot

Hi Sean,

> clk_composite_ops was shared between all devices in the composite
> clock driver. If one clock had a feature (such as supporting
> set_parent) which another clock did not, it could call a null pointer
> dereference.
> 
> This patch does three things
> 1. It adds null-pointer checks to all composite clock functions.
> 2. It makes clk_composite_ops const and sets its functions at
> compile-time. 3. It adds some basic sanity checks to num_parents.
> 
> The combined effect of these changes is that any of mux, rate, or
> gate can be NULL, and composite clocks will still function normally.
> Previously, at least mux had to exist, since clk_composite_get_parent
> was used to determine the parent for clk_register.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>

Acked-by: Lukasz Majewski <lukma@denx.de>

(Please commit clk related patches with this patch set)

> ---
>   Changes for v3:
>   - Don't return an error code where a no-op would be fine
> 
>  drivers/clk/clk-composite.c | 57
> +++++++++++++++++++++++-------------- 1 file changed, 35
> insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> index d0f273d47f..5425f921ff 100644
> --- a/drivers/clk/clk-composite.c
> +++ b/drivers/clk/clk-composite.c
> @@ -22,7 +22,10 @@ static u8 clk_composite_get_parent(struct clk *clk)
>  		(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
>  	struct clk *mux = composite->mux;
>  
> -	return clk_mux_get_parent(mux);
> +	if (mux)
> +		return clk_mux_get_parent(mux);
> +	else
> +		return 0;
>  }
>  
>  static int clk_composite_set_parent(struct clk *clk, struct clk
> *parent) @@ -32,7 +35,10 @@ static int
> clk_composite_set_parent(struct clk *clk, struct clk *parent) const
> struct clk_ops *mux_ops = composite->mux_ops; struct clk *mux =
> composite->mux; 
> -	return mux_ops->set_parent(mux, parent);
> +	if (mux && mux_ops)
> +		return mux_ops->set_parent(mux, parent);
> +	else
> +		return -ENOSYS;
>  }
>  
>  static unsigned long clk_composite_recalc_rate(struct clk *clk)
> @@ -42,7 +48,10 @@ static unsigned long
> clk_composite_recalc_rate(struct clk *clk) const struct clk_ops
> *rate_ops = composite->rate_ops; struct clk *rate = composite->rate;
>  
> -	return rate_ops->get_rate(rate);
> +	if (rate && rate_ops)
> +		return rate_ops->get_rate(rate);
> +	else
> +		return clk_get_parent_rate(clk);
>  }
>  
>  static ulong clk_composite_set_rate(struct clk *clk, unsigned long
> rate) @@ -52,7 +61,10 @@ static ulong clk_composite_set_rate(struct
> clk *clk, unsigned long rate) const struct clk_ops *rate_ops =
> composite->rate_ops; struct clk *clk_rate = composite->rate;
>  
> -	return rate_ops->set_rate(clk_rate, rate);
> +	if (rate && rate_ops)
> +		return rate_ops->set_rate(clk_rate, rate);
> +	else
> +		return clk_get_rate(clk);
>  }
>  
>  static int clk_composite_enable(struct clk *clk)
> @@ -62,7 +74,10 @@ static int clk_composite_enable(struct clk *clk)
>  	const struct clk_ops *gate_ops = composite->gate_ops;
>  	struct clk *gate = composite->gate;
>  
> -	return gate_ops->enable(gate);
> +	if (gate && gate_ops)
> +		return gate_ops->enable(gate);
> +	else
> +		return 0;
>  }
>  
>  static int clk_composite_disable(struct clk *clk)
> @@ -72,15 +87,12 @@ static int clk_composite_disable(struct clk *clk)
>  	const struct clk_ops *gate_ops = composite->gate_ops;
>  	struct clk *gate = composite->gate;
>  
> -	gate_ops->disable(gate);
> -
> -	return 0;
> +	if (gate && gate_ops)
> +		return gate_ops->disable(gate);
> +	else
> +		return 0;
>  }
>  
> -struct clk_ops clk_composite_ops = {
> -	/* This will be set according to clk_register_composite */
> -};
> -
>  struct clk *clk_register_composite(struct device *dev, const char
> *name, const char * const *parent_names,
>  				   int num_parents, struct clk *mux,
> @@ -94,7 +106,9 @@ struct clk *clk_register_composite(struct device
> *dev, const char *name, struct clk *clk;
>  	struct clk_composite *composite;
>  	int ret;
> -	struct clk_ops *composite_ops = &clk_composite_ops;
> +
> +	if (!num_parents || (num_parents != 1 && !mux))
> +		return ERR_PTR(-EINVAL);
>  
>  	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
>  	if (!composite)
> @@ -103,8 +117,6 @@ struct clk *clk_register_composite(struct device
> *dev, const char *name, if (mux && mux_ops) {
>  		composite->mux = mux;
>  		composite->mux_ops = mux_ops;
> -		if (mux_ops->set_parent)
> -			composite_ops->set_parent =
> clk_composite_set_parent; mux->data = (ulong)composite;
>  	}
>  
> @@ -113,11 +125,6 @@ struct clk *clk_register_composite(struct device
> *dev, const char *name, clk = ERR_PTR(-EINVAL);
>  			goto err;
>  		}
> -		composite_ops->get_rate = clk_composite_recalc_rate;
> -
> -		/* .set_rate requires either .round_rate or
> .determine_rate */
> -		if (rate_ops->set_rate)
> -			composite_ops->set_rate =
> clk_composite_set_rate; 
>  		composite->rate = rate;
>  		composite->rate_ops = rate_ops;
> @@ -132,8 +139,6 @@ struct clk *clk_register_composite(struct device
> *dev, const char *name, 
>  		composite->gate = gate;
>  		composite->gate_ops = gate_ops;
> -		composite_ops->enable = clk_composite_enable;
> -		composite_ops->disable = clk_composite_disable;
>  		gate->data = (ulong)composite;
>  	}
>  
> @@ -160,6 +165,14 @@ err:
>  	return clk;
>  }
>  
> +static const struct clk_ops clk_composite_ops = {
> +	.set_parent = clk_composite_set_parent,
> +	.get_rate = clk_composite_recalc_rate,
> +	.set_rate = clk_composite_set_rate,
> +	.enable = clk_composite_enable,
> +	.disable = clk_composite_disable,
> +};
> +
>  U_BOOT_DRIVER(clk_composite) = {
>  	.name	= UBOOT_DM_CLK_COMPOSITE,
>  	.id	= UCLASS_CLK,




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200206/9c003965/attachment.sig>

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

* [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks
  2020-02-02 19:59 ` [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks Sean Anderson
@ 2020-02-06 21:45   ` Lukasz Majewski
  0 siblings, 0 replies; 41+ messages in thread
From: Lukasz Majewski @ 2020-02-06 21:45 UTC (permalink / raw)
  To: u-boot

Hi Sean,

> For clocks not in the CCF, their parents will not have UCLASS_CLK, so
> we just enable them as normal. The enable count is local to the
> struct clk, but this will never result in the actual en-/dis-able op
> being called (unless the same struct clk is enabled twice).
> 
> For clocks in the CCF, we always traverse up the tree when enabling.
> Previously, CCF clocks without id set would be skipped, stopping the
> traversal too early.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>

Acked-by: Lukasz Majewski <lukma@denx.de>

> ---
>   Changes for v3:
>   - New.
> 
>  drivers/clk/clk-uclass.c | 58
> +++++++++++++++++----------------------- 1 file changed, 25
> insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
> index 9aa8537004..87d101aab4 100644
> --- a/drivers/clk/clk-uclass.c
> +++ b/drivers/clk/clk-uclass.c
> @@ -490,7 +490,6 @@ int clk_set_parent(struct clk *clk, struct clk
> *parent) int clk_enable(struct clk *clk)
>  {
>  	const struct clk_ops *ops;
> -	struct clk *clkp = NULL;
>  	int ret;
>  
>  	debug("%s(clk=%p)\n", __func__, clk);
> @@ -499,32 +498,28 @@ int clk_enable(struct clk *clk)
>  	ops = clk_dev_ops(clk->dev);
>  
>  	if (CONFIG_IS_ENABLED(CLK_CCF)) {
> -		/* Take id 0 as a non-valid clk, such as dummy */
> -		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
> -			if (clkp->enable_count) {
> -				clkp->enable_count++;
> -				return 0;
> -			}
> -			if (clkp->dev->parent &&
> -			    device_get_uclass_id(clkp->dev) ==
> UCLASS_CLK) {
> -				ret =
> clk_enable(dev_get_clk_ptr(clkp->dev->parent));
> -				if (ret) {
> -					printf("Enable %s failed\n",
> -
> clkp->dev->parent->name);
> -					return ret;
> -				}
> +		if (clk->enable_count) {
> +			clk->enable_count++;
> +			return 0;
> +		}
> +		if (clk->dev->parent &&
> +		    device_get_uclass_id(clk->dev->parent) ==
> UCLASS_CLK) {
> +			ret =
> clk_enable(dev_get_clk_ptr(clk->dev->parent));
> +			if (ret) {
> +				printf("Enable %s failed\n",
> +				       clk->dev->parent->name);
> +				return ret;
>  			}
>  		}
>  
>  		if (ops->enable) {
>  			ret = ops->enable(clk);
>  			if (ret) {
> -				printf("Enable %s failed\n",
> clk->dev->name);
> +				printf("Enable %s failed (error
> %d)\n", clk->dev->name, ret); return ret;
>  			}
>  		}
> -		if (clkp)
> -			clkp->enable_count++;
> +		clk->enable_count++;
>  	} else {
>  		if (!ops->enable)
>  			return -ENOSYS;
> @@ -550,7 +545,6 @@ int clk_enable_bulk(struct clk_bulk *bulk)
>  int clk_disable(struct clk *clk)
>  {
>  	const struct clk_ops *ops;
> -	struct clk *clkp = NULL;
>  	int ret;
>  
>  	debug("%s(clk=%p)\n", __func__, clk);
> @@ -559,29 +553,27 @@ int clk_disable(struct clk *clk)
>  	ops = clk_dev_ops(clk->dev);
>  
>  	if (CONFIG_IS_ENABLED(CLK_CCF)) {
> -		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
> -			if (clkp->enable_count == 0) {
> -				printf("clk %s already disabled\n",
> -				       clkp->dev->name);
> -				return 0;
> -			}
> -
> -			if (--clkp->enable_count > 0)
> -				return 0;
> +		if (clk->enable_count == 0) {
> +			printf("clk %s already disabled\n",
> +			       clk->dev->name);
> +			return 0;
>  		}
>  
> +		if (--clk->enable_count > 0)
> +			return 0;
> +
>  		if (ops->disable) {
>  			ret = ops->disable(clk);
>  			if (ret)
>  				return ret;
>  		}
>  
> -		if (clkp && clkp->dev->parent &&
> -		    device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
> -			ret =
> clk_disable(dev_get_clk_ptr(clkp->dev->parent));
> +		if (clk->dev->parent &&
> +		    device_get_uclass_id(clk->dev) == UCLASS_CLK) {
> +			ret =
> clk_disable(dev_get_clk_ptr(clk->dev->parent)); if (ret) {
> -				printf("Disable %s failed\n",
> -				       clkp->dev->parent->name);
> +				printf("Disable %s failed (error
> %d)\n",
> +				       clk->dev->parent->name, ret);
>  				return ret;
>  			}
>  		}




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200206/fd5b0c00/attachment.sig>

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

* [PATCH v3 10/12] riscv: Add K210 clock support
  2020-02-02 20:07 ` [PATCH v3 10/12] riscv: Add K210 clock support Sean Anderson
@ 2020-02-06 21:51   ` Lukasz Majewski
  0 siblings, 0 replies; 41+ messages in thread
From: Lukasz Majewski @ 2020-02-06 21:51 UTC (permalink / raw)
  To: u-boot

Hi Sean,

> Due to the large number of clocks, I decided to use the CCF. The
> overall structure is modeled after the imx code. A common pattern is
> to create a composite clock composed of several component clocks. For
> these component clocks, the clk_register_* functions are not used,
> since they will be registered as part of the composite clock. To
> create these component clocks, several helper k210_clk_comp_*
> functions are used. This functionality seems like it would be useful
> to other drivers also creating composite clocks, so perhaps some
> general versions should be created. I am not particularly attached to
> the naming convention, suggestions are welcome.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>

Reviewed-by: Lukasz Majewski <lukma@denx.de>

> ---
>   Changes for v3:
>   - Removed sysctl struct, replacing it with defines. This is to have
> the same interface to sysctl from C as from the device tree.
>   - Fixed clocks having the same id
>   - Fixed clocks not using the correct register/bits
>   - Aligned the defines in headers
>   Changes for v2:
>   - Add clk.o to obj-y
>   - Don't probe before relocation
> 
>  drivers/clk/kendryte/Kconfig            |   2 +-
>  drivers/clk/kendryte/Makefile           |   2 +-
>  drivers/clk/kendryte/clk.c              | 390
> ++++++++++++++++++++++++ drivers/clk/kendryte/clk.h              |
> 27 ++ include/dt-bindings/clock/k210-sysctl.h |  53 ++++
>  include/dt-bindings/mfd/k210-sysctl.h   |  38 +++
>  6 files changed, 510 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/clk/kendryte/clk.c
>  create mode 100644 drivers/clk/kendryte/clk.h
>  create mode 100644 include/dt-bindings/clock/k210-sysctl.h
>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
> 
> diff --git a/drivers/clk/kendryte/Kconfig
> b/drivers/clk/kendryte/Kconfig index 7b69c8afaf..073fca0781 100644
> --- a/drivers/clk/kendryte/Kconfig
> +++ b/drivers/clk/kendryte/Kconfig
> @@ -1,6 +1,6 @@
>  config CLK_K210
>  	bool "Clock support for Kendryte K210"
> -	depends on CLK && CLK_CCF
> +	depends on CLK && CLK_CCF && CLK_COMPOSITE_CCF
>  	help
>  	  This enables support clock driver for Kendryte K210
> platforms. 
> diff --git a/drivers/clk/kendryte/Makefile
> b/drivers/clk/kendryte/Makefile index c56d93ea1c..d26bce954f 100644
> --- a/drivers/clk/kendryte/Makefile
> +++ b/drivers/clk/kendryte/Makefile
> @@ -1 +1 @@
> -obj-y += pll.o
> +obj-y += clk.o pll.o
> diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c
> new file mode 100644
> index 0000000000..aaa7420c84
> --- /dev/null
> +++ b/drivers/clk/kendryte/clk.c
> @@ -0,0 +1,390 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +#include "clk.h"
> +
> +#include <asm/io.h>
> +#include <dt-bindings/clock/k210-sysctl.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <mapmem.h>
> +
> +#include "pll.h"
> +
> +static ulong k210_clk_get_rate(struct clk *clk)
> +{
> +	struct clk *c;
> +	int err = clk_get_by_id(clk->id, &c);
> +
> +	if (err)
> +		return err;
> +	return clk_get_rate(c);
> +}
> +
> +static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *c;
> +	int err = clk_get_by_id(clk->id, &c);
> +
> +	if (err)
> +		return err;
> +	return clk_set_rate(c, rate);
> +}
> +
> +static int k210_clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct clk *c, *p;
> +	int err = clk_get_by_id(clk->id, &c);
> +
> +	if (err)
> +		return err;
> +	
> +	err = clk_get_by_id(parent->id, &p);
> +	if (err)
> +		return err;
> +
> +	return clk_set_parent(c, p);
> +}
> +
> +static int k210_clk_endisable(struct clk *clk, bool enable)
> +{
> +	struct clk *c;
> +	int err = clk_get_by_id(clk->id, &c);
> +
> +	if (err)
> +		return err;
> +	return enable ? clk_enable(c) : clk_disable(c);
> +}
> +
> +static int k210_clk_enable(struct clk *clk)
> +{
> +	return k210_clk_endisable(clk, true);
> +}
> +
> +static int k210_clk_disable(struct clk *clk)
> +{
> +	return k210_clk_endisable(clk, false);
> +}
> +
> +static const struct clk_ops k210_clk_ops = {
> +	.set_rate = k210_clk_set_rate,
> +	.get_rate = k210_clk_get_rate,
> +	.set_parent = k210_clk_set_parent,
> +	.enable = k210_clk_enable,
> +	.disable = k210_clk_disable,
> +};
> +
> +/* The first clock is in0, which is filled in by k210_clk_probe */
> +static const char *generic_sels[] = { NULL, "pll0", };
> +static const char *aclk_sels[] = { "in0_half", "pll0_half", };
> +static const char *pll2_sels[] = { NULL, "pll0", "pll1", };
> +
> +static struct clk_divider *k210_clk_comp_div_flags(void __iomem
> *reg, u8 shift,
> +						   u8 width, u8
> flags) +{
> +	struct clk_divider *div;
> +
> +	div = kzalloc(sizeof(*div), GFP_KERNEL);
> +	if (!div)
> +		return div;
> +	div->reg = reg;
> +	div->shift = shift;
> +	div->width = width;
> +	div->flags = flags;
> +	return div;
> +}
> +
> +static inline struct clk_divider *k210_clk_comp_div(void __iomem
> *reg, u8 shift,
> +						    u8 width)
> +{
> +	return k210_clk_comp_div_flags(reg, shift, width, 0);
> +}
> +
> +static struct clk_gate *k210_clk_comp_gate(void __iomem *reg, u8
> bit_idx) +{
> +	struct clk_gate *gate;
> +
> +	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +	if (!gate)
> +		return gate;
> +	gate->reg = reg;
> +	gate->bit_idx = bit_idx;
> +	return gate;
> +}
> +
> +static struct clk_mux *k210_clk_comp_mux(const char *parent_names[],
> +				         u8 num_parents, void
> __iomem *reg,
> +				         u8 shift, u8 width)
> +{
> +	struct clk_mux *mux;
> +
> +	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> +	if (!mux)
> +		return mux;
> +	mux->reg = reg;
> +	mux->mask = BIT(width) - 1;
> +	mux->shift = shift;
> +	mux->parent_names = parent_names;
> +	mux->num_parents = num_parents;
> +	return mux;
> +}
> +
> +static struct clk *k210_clk_comp_nomux(const char *name, const char
> *parent,
> +					 struct clk_divider *div,
> +					 struct clk_gate *gate)
> +{
> +	if (!div || !gate) {
> +		kfree(div);
> +		kfree(gate);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +	return clk_register_composite(NULL, name, &parent, 1,
> +				      NULL, NULL,
> +				      &div->clk, &clk_divider_ops,
> +				      &gate->clk, &clk_gate_ops, 0);
> +}
> +
> +static struct clk *k210_clk_comp(const char *name, struct
> clk_divider *div,
> +				 struct clk_gate *gate, struct
> clk_mux *mux) +{
> +	if (!div || !gate || !mux) {
> +		kfree(div);
> +		kfree(gate);
> +		kfree(mux);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +	return clk_register_composite(NULL, name, generic_sels,
> +				      ARRAY_SIZE(generic_sels),
> +				      &mux->clk, &clk_mux_ops,
> +				      &div->clk, &clk_divider_ops,
> +				      &gate->clk, &clk_gate_ops, 0);
> +}
> +
> +static int k210_clk_probe(struct udevice *dev)
> +{
> +	int err;
> +	const char *in0;
> +	struct clk in0_clk;
> +	struct clk_divider *div;
> +	struct clk_gate *gate;
> +	struct clk_mux *mux;
> +	struct k210_pll *pll;
> +	void *base;
> +
> +	base = dev_read_addr_ptr(dev_get_parent(dev));
> +	if (!base)
> +		return -EINVAL;
> +
> +	err = clk_get_by_index(dev, 0, &in0_clk);
> +	if (err)
> +		goto cleanup_base;
> +	in0 = in0_clk.dev->name;
> +	generic_sels[0] = in0;
> +	pll2_sels[0] = in0;
> +
> +	/* PLLs */
> +	clk_dm(K210_CLK_PLL0, k210_clk_pll("pll0", in0, base +
> K210_SYSCTL_PLL0,
> +					   base +
> K210_SYSCTL_PLL_LOCK, 0, 2));
> +	clk_dm(K210_CLK_PLL1, k210_clk_pll("pll1", in0, base +
> K210_SYSCTL_PLL1,
> +					   base +
> K210_SYSCTL_PLL_LOCK, 8, 1));
> +	/* PLL2 is muxed, so set up a composite clock */
> +	mux = k210_clk_comp_mux(pll2_sels, ARRAY_SIZE(pll2_sels),
> +				base + K210_SYSCTL_PLL2, 26, 2);
> +	pll = k210_clk_comp_pll(base + K210_SYSCTL_PLL2,
> +				base + K210_SYSCTL_PLL_LOCK, 16, 1);
> +	if (!mux || !pll) {
> +		kfree(mux);
> +		kfree(pll);
> +	} else {
> +		clk_dm(K210_CLK_PLL2,
> +		       clk_register_composite(NULL, "pll2",
> pll2_sels,
> +					      ARRAY_SIZE(pll2_sels),
> +					      &mux->clk,
> &clk_mux_ops,
> +					      &pll->clk,
> &k210_pll_ops,
> +					      &pll->clk,
> &k210_pll_ops, 0));
> +	}
> +
> +	/* Half-frequency clocks for "even" dividers */
> +	k210_clk_half("in0_half", in0);
> +	k210_clk_half("pll0_half", "pll0");
> +	k210_clk_half("pll2_half", "pll2");
> +
> +	/* Muxed clocks */
> +	div = k210_clk_comp_div_flags(base + K210_SYSCTL_SEL0, 1, 2,
> +				      CLK_DIVIDER_POWER_OF_TWO);
> +	mux = k210_clk_comp_mux(aclk_sels, ARRAY_SIZE(aclk_sels),
> +				base + K210_SYSCTL_SEL0, 0, 1);
> +	if (!div || !mux) {
> +		kfree(div);
> +		kfree(mux);
> +	} else {
> +		clk_dm(K210_CLK_ACLK,
> +		       clk_register_composite(NULL, "aclk",
> aclk_sels,
> +					      ARRAY_SIZE(aclk_sels),
> +					      &mux->clk,
> &clk_mux_ops,
> +					      &div->clk,
> &clk_divider_ops,
> +					      NULL, NULL, 0));
> +	}
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 1, 2);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 9);
> +	mux = k210_clk_comp_mux(generic_sels,
> ARRAY_SIZE(generic_sels),
> +				base + K210_SYSCTL_SEL0, 12, 1);
> +	clk_dm(K210_CLK_SPI3, k210_clk_comp("spi3", div, gate, mux));
> +	
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 0);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 21);
> +	mux = k210_clk_comp_mux(generic_sels,
> ARRAY_SIZE(generic_sels),
> +				base + K210_SYSCTL_SEL0, 13, 1);
> +	clk_dm(K210_CLK_TIMER0, k210_clk_comp("timer0", div, gate,
> mux)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 22);
> +	mux = k210_clk_comp_mux(generic_sels,
> ARRAY_SIZE(generic_sels),
> +				base + K210_SYSCTL_SEL0, 14, 1);
> +	clk_dm(K210_CLK_TIMER1, k210_clk_comp("timer1", div, gate,
> mux));
> +	
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR2, 8, 16);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 23);
> +	mux = k210_clk_comp_mux(generic_sels,
> ARRAY_SIZE(generic_sels),
> +				base + K210_SYSCTL_SEL0, 15, 1);
> +	clk_dm(K210_CLK_TIMER2, k210_clk_comp("timer2", div, gate,
> mux)); +
> +
> +	/* Dividing clocks, no mux */
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 0, 4);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 1);
> +	clk_dm(K210_CLK_SRAM0, k210_clk_comp_nomux("sram0", "aclk",
> div, gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 4, 4);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 2);
> +	clk_dm(K210_CLK_SRAM1, k210_clk_comp_nomux("sram1", "aclk",
> div, gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 16, 4);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 0);
> +	clk_dm(K210_CLK_ROM, k210_clk_comp_nomux("rom", "aclk", div,
> gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 12, 4);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 3);
> +	clk_dm(K210_CLK_DVP, k210_clk_comp_nomux("dvp", "aclk", div,
> gate)); +
> +	/*
> +	 * XXX: the next three clocks may be using an even divider
> +	 * c.f.
> <https://github.com/kendryte/kendryte-standalone-sdk/issues/99>
> +	 */
> +	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 3, 3);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 3);
> +	clk_dm(K210_CLK_APB0, k210_clk_comp_nomux("apb0", "aclk",
> div, gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 6, 3);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 4);
> +	clk_dm(K210_CLK_APB1, k210_clk_comp_nomux("apb1", "aclk",
> div, gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_SEL0, 9, 3);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_CENT, 5);
> +	clk_dm(K210_CLK_APB2, k210_clk_comp_nomux("apb2", "aclk",
> div, gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR0, 8, 4);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 2);
> +	clk_dm(K210_CLK_AI, k210_clk_comp_nomux("ai", "pll1", div,
> gate)); +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR3, 0, 16);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 10);
> +	clk_dm(K210_CLK_I2S0,
> +	       k210_clk_comp_nomux("i2s0", "pll2_half", div, gate));
> +	
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR3, 16, 16);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 11);
> +	clk_dm(K210_CLK_I2S1,
> +	       k210_clk_comp_nomux("i2s1", "pll2_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR4, 0, 16);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 12);
> +	clk_dm(K210_CLK_I2S2,
> +	       k210_clk_comp_nomux("i2s2", "pll2_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR6, 0, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 24);
> +	clk_dm(K210_CLK_WDT0,
> +	       k210_clk_comp_nomux("wdt0", "in0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR6, 8, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 25);
> +	clk_dm(K210_CLK_WDT1,
> +	       k210_clk_comp_nomux("wdt1", "in0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 0, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 6);
> +	clk_dm(K210_CLK_SPI0,
> +	       k210_clk_comp_nomux("spi0", "pll0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 8, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 7);
> +	clk_dm(K210_CLK_SPI1,
> +	       k210_clk_comp_nomux("spi1", "pll0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR1, 16, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 8);
> +	clk_dm(K210_CLK_SPI2,
> +	       k210_clk_comp_nomux("spi2", "pll0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 8, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 13);
> +	clk_dm(K210_CLK_I2C0,
> +	       k210_clk_comp_nomux("i2c0", "pll0_half", div, gate));
> +	
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 16, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 14);
> +	clk_dm(K210_CLK_I2C1,
> +	       k210_clk_comp_nomux("i2c1", "pll0_half", div, gate));
> +
> +	div = k210_clk_comp_div(base + K210_SYSCTL_THR5, 24, 8);
> +	gate = k210_clk_comp_gate(base + K210_SYSCTL_EN_PERI, 15);
> +	clk_dm(K210_CLK_I2C2,
> +	       k210_clk_comp_nomux("i2c2", "pll0_half", div, gate));
> +
> +	/* Gated clocks */
> +	clk_dm(K210_CLK_CPU,
> +	       k210_clk_gate("cpu", "aclk", base +
> K210_SYSCTL_EN_CENT, 0));
> +	clk_dm(K210_CLK_DMA,
> +	       k210_clk_gate("dma", "aclk", base +
> K210_SYSCTL_EN_PERI, 1));
> +	clk_dm(K210_CLK_FFT,
> +	       k210_clk_gate("fft", "aclk", base +
> K210_SYSCTL_EN_PERI, 4));
> +	clk_dm(K210_CLK_GPIO,
> +	       k210_clk_gate("gpio", "apb0", base +
> K210_SYSCTL_EN_PERI, 5));
> +	clk_dm(K210_CLK_UART1,
> +	       k210_clk_gate("uart1", "apb0", base +
> K210_SYSCTL_EN_PERI, 16));
> +	clk_dm(K210_CLK_UART2,
> +	       k210_clk_gate("uart2", "apb0", base +
> K210_SYSCTL_EN_PERI, 17));
> +	clk_dm(K210_CLK_UART3,
> +	       k210_clk_gate("uart3", "apb0", base +
> K210_SYSCTL_EN_PERI, 18));
> +	clk_dm(K210_CLK_FPIOA,
> +	       k210_clk_gate("fpioa", "apb0", base +
> K210_SYSCTL_EN_PERI, 20));
> +	clk_dm(K210_CLK_SHA,
> +	       k210_clk_gate("sha", "apb0", base +
> K210_SYSCTL_EN_PERI, 26));
> +	clk_dm(K210_CLK_AES,
> +	       k210_clk_gate("aes", "apb1", base +
> K210_SYSCTL_EN_PERI, 19));
> +	clk_dm(K210_CLK_OTP,
> +	       k210_clk_gate("otp", "apb1", base +
> K210_SYSCTL_EN_PERI, 27));
> +	clk_dm(K210_CLK_RTC,
> +	       k210_clk_gate("rtc", in0, base + K210_SYSCTL_EN_PERI,
> 29)); +
> +cleanup_base:
> +	unmap_sysmem(base);
> +	return err;
> +}
> +
> +static const struct udevice_id k210_clk_ids[] = {
> +	{ .compatible = "kendryte,k210-clk" },
> +	{ },
> +};
> +
> +U_BOOT_DRIVER(k210_clk) = {
> +	.name = "k210_clk",
> +	.id = UCLASS_CLK,
> +	.of_match = k210_clk_ids,
> +	.ops = &k210_clk_ops,
> +	.probe = k210_clk_probe,
> +};
> diff --git a/drivers/clk/kendryte/clk.h b/drivers/clk/kendryte/clk.h
> new file mode 100644
> index 0000000000..17d0f5de1b
> --- /dev/null
> +++ b/drivers/clk/kendryte/clk.h
> @@ -0,0 +1,27 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef K210_CLK_H
> +#define K210_CLK_H
> +
> +#define LOG_CATEGORY UCLASS_CLK
> +#include <linux/types.h>
> +#include <linux/clk-provider.h>
> +
> +static inline struct clk *k210_clk_gate(const char *name,
> +					const char *parent_name,
> +					void __iomem *reg, u8
> bit_idx) +{
> +	return clk_register_gate(NULL, name, parent_name, 0, reg,
> bit_idx, 0,
> +				 NULL);
> +}
> +
> +static inline struct clk *k210_clk_half(const char *name,
> +				        const char *parent_name)
> +{
> +	return clk_register_fixed_factor(NULL, name, parent_name, 0,
> 1, 2); +}
> +
> +#endif /* K210_CLK_H */
> diff --git a/include/dt-bindings/clock/k210-sysctl.h
> b/include/dt-bindings/clock/k210-sysctl.h new file mode 100644
> index 0000000000..7c471f9893
> --- /dev/null
> +++ b/include/dt-bindings/clock/k210-sysctl.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef CLOCK_K210_SYSCTL_H
> +#define CLOCK_K210_SYSCTL_H
> +
> +/*
> + * Arbitrary identifiers for clocks. 0 is unused since clk_enable
> thinks it
> + * means "no clock".
> + */
> +#define K210_CLK_PLL0   1
> +#define K210_CLK_PLL1   2
> +#define K210_CLK_PLL2   3
> +#define K210_CLK_CPU    4
> +#define K210_CLK_SRAM0  5
> +#define K210_CLK_SRAM1  6
> +#define K210_CLK_APB0   7
> +#define K210_CLK_APB1   8
> +#define K210_CLK_APB2   9
> +#define K210_CLK_ROM    10
> +#define K210_CLK_DMA    11
> +#define K210_CLK_AI     12
> +#define K210_CLK_DVP    13
> +#define K210_CLK_FFT    14
> +#define K210_CLK_GPIO   15
> +#define K210_CLK_SPI0   16
> +#define K210_CLK_SPI1   17
> +#define K210_CLK_SPI2   18
> +#define K210_CLK_SPI3   19
> +#define K210_CLK_I2S0   20
> +#define K210_CLK_I2S1   21
> +#define K210_CLK_I2S2   22
> +#define K210_CLK_I2C0   23
> +#define K210_CLK_I2C1   24
> +#define K210_CLK_I2C2   25
> +#define K210_CLK_UART1  26
> +#define K210_CLK_UART2  27
> +#define K210_CLK_UART3  28
> +#define K210_CLK_AES    29
> +#define K210_CLK_FPIOA  30
> +#define K210_CLK_TIMER0 31
> +#define K210_CLK_TIMER1 32
> +#define K210_CLK_TIMER2 33
> +#define K210_CLK_WDT0   34
> +#define K210_CLK_WDT1   35
> +#define K210_CLK_SHA    36
> +#define K210_CLK_OTP    37
> +#define K210_CLK_RTC    40
> +#define K210_CLK_ACLK   41
> +
> +#endif /* CLOCK_K210_SYSCTL_H */
> diff --git a/include/dt-bindings/mfd/k210-sysctl.h
> b/include/dt-bindings/mfd/k210-sysctl.h new file mode 100644
> index 0000000000..3457240f03
> --- /dev/null
> +++ b/include/dt-bindings/mfd/k210-sysctl.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef K210_SYSCTL_H
> +#define K210_SYSCTL_H
> + 
> +/* Taken from kendryte-standalone-sdk/lib/drivers/include/sysctl.h */
> +#define K210_SYSCTL_GIT_ID     0x00 /* Git short commit id */
> +#define K210_SYSCTL_CLK_FREQ   0x04 /* System clock base frequency */
> +#define K210_SYSCTL_PLL0       0x08 /* PLL0 controller */
> +#define K210_SYSCTL_PLL1       0x0C /* PLL1 controller */
> +#define K210_SYSCTL_PLL2       0x10 /* PLL2 controller */
> +#define K210_SYSCTL_PLL_LOCK   0x18 /* PLL lock tester */
> +#define K210_SYSCTL_ROM_ERROR  0x1C /* AXI ROM detector */
> +#define K210_SYSCTL_SEL0       0x20 /* Clock select controller0 */
> +#define K210_SYSCTL_SEL1       0x24 /* Clock select controller1 */
> +#define K210_SYSCTL_EN_CENT    0x28 /* Central clock enable */
> +#define K210_SYSCTL_EN_PERI    0x2C /* Peripheral clock enable */
> +#define K210_SYSCTL_SOFT_RESET 0x30 /* Soft reset ctrl */
> +#define K210_SYSCTL_PERI_RESET 0x34 /* Peripheral reset controller */
> +#define K210_SYSCTL_THR0       0x38 /* Clock threshold controller 0
> */ +#define K210_SYSCTL_THR1       0x3C /* Clock threshold controller
> 1 */ +#define K210_SYSCTL_THR2       0x40 /* Clock threshold
> controller 2 */ +#define K210_SYSCTL_THR3       0x44 /* Clock
> threshold controller 3 */ +#define K210_SYSCTL_THR4       0x48 /*
> Clock threshold controller 4 */ +#define K210_SYSCTL_THR5       0x4C
> /* Clock threshold controller 5 */ +#define K210_SYSCTL_THR6
> 0x50 /* Clock threshold controller 6 */ +#define K210_SYSCTL_MISC
>   0x54 /* Miscellaneous controller */ +#define K210_SYSCTL_PERI
> 0x58 /* Peripheral controller */ +#define K210_SYSCTL_SPI_SLEEP  0x5C
> /* SPI sleep controller */ +#define K210_SYSCTL_RESET_STAT 0x60 /*
> Reset source status */ +#define K210_SYSCTL_DMA_SEL0   0x64 /* DMA
> handshake selector */ +#define K210_SYSCTL_DMA_SEL1   0x68 /* DMA
> handshake selector */ +#define K210_SYSCTL_POWER_SEL  0x6C /* IO
> Power Mode Select controller */ +
> +#endif /* K210_SYSCTL_H */




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200206/649d4bee/attachment.sig>

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

* [PATCH v3 01/12] clk: Always use the supplied struct clk
       [not found]     ` <752D002CFF5D0F4FA35C0100F1D73F3FA46D30F5@ATCPCS16.andestech.com>
@ 2020-02-12  1:23       ` Rick Chen
  0 siblings, 0 replies; 41+ messages in thread
From: Rick Chen @ 2020-02-12  1:23 UTC (permalink / raw)
  To: u-boot

Hi Lukasz

> From: Lukasz Majewski [mailto:lukma at denx.de]
> Sent: Friday, February 07, 2020 5:22 AM
> To: Sean Anderson
> Cc: U-Boot Mailing List; Rick Jian-Zhi Chen(陳建志); Lukas Auer
> Subject: Re: [PATCH v3 01/12] clk: Always use the supplied struct clk
>
> Hi Sean,
>
> > CCF clocks should always use the struct clock passed to their methods
> > for extracting the driver-specific clock information struct.
> > Previously, many functions would use the clk->dev->priv if the device
> > was bound. This could cause problems with composite clocks. The
> > individual clocks in a composite clock did not have the ->dev field
> > filled in. This was fine, because the device-specific clock
> > information would be used. However, since there was no ->dev, there
> > was no way to get the parent clock. This caused the recalc_rate method
> > of the CCF divider clock to fail. One option would be to use the
> > clk->priv field to get the composite clock and from there get the
> > appropriate parent device. However, this would tie the implementation
> > to the composite clock. In general, different devices should not rely
> > on the contents of ->priv from another device.
> >
> > The simple solution to this problem is to just always use the supplied
> > struct clock. The composite clock now fills in the ->dev pointer of
> > its child clocks. This allows child clocks to make calls like
> > clk_get_parent() without issue.
> >
> > imx avoided the above problem by using a custom get_rate function with
> > composite clocks.
> >
> > Signed-off-by: Sean Anderson <seanga2@gmail.com>
>
> Thank you Sean for your CCF enhancement and updating the ccf.txt documentation entry.
>
> Acked-by: Lukasz Majewski <lukma@denx.de>
>
> I don't mind if RISC-V SoC maintainer pulls the whole series (including CCF patches).

OK
Thanks for your review.

Regards,
Rick

>
> > ---
> >   Changes for v3:
> >   - Documented new assumptions in the CCF
> >   - Wrapped docs to 80 columns
> >
> >  doc/imx/clk/ccf.txt            | 63
> > +++++++++++++++++----------------- drivers/clk/clk-composite.c    |
> > 8 +++++ drivers/clk/clk-divider.c      |  6 ++--
> >  drivers/clk/clk-fixed-factor.c |  3 +-
> >  drivers/clk/clk-gate.c         |  6 ++--
> >  drivers/clk/clk-mux.c          | 12 +++----
> >  drivers/clk/imx/clk-gate2.c    |  4 +--
> >  7 files changed, 51 insertions(+), 51 deletions(-)
> >
> > diff --git a/doc/imx/clk/ccf.txt b/doc/imx/clk/ccf.txt index
> > 36b60dc438..e40ac360e8 100644
> > --- a/doc/imx/clk/ccf.txt
> > +++ b/doc/imx/clk/ccf.txt
> > @@ -1,42 +1,37 @@
> >  Introduction:
> >  =============
> >
> > -This documentation entry describes the Common Clock Framework [CCF]
> > -port from Linux kernel (v5.1.12) to U-Boot.
> > +This documentation entry describes the Common Clock Framework [CCF]
> > port from +Linux kernel (v5.1.12) to U-Boot.
> >
> > -This code is supposed to bring CCF to IMX based devices (imx6q, imx7
> > -imx8). Moreover, it also provides some common clock code, which would
> > -allow easy porting of CCF Linux code to other platforms.
> > +This code is supposed to bring CCF to IMX based devices (imx6q, imx7
> > imx8). +Moreover, it also provides some common clock code, which would
> > allow easy +porting of CCF Linux code to other platforms.
> >
> >  Design decisions:
> >  =================
> >
> > -* U-Boot's driver model [DM] for clk differs from Linux CCF. The most
> > -  notably difference is the lack of support for hierarchical clocks
> > and
> > -  "clock as a manager driver" (single clock DTS node acts as a
> > starting
> > -  point for all other clocks).
> > +* U-Boot's driver model [DM] for clk differs from Linux CCF. The
> > most notably
> > +  difference is the lack of support for hierarchical clocks and
> > "clock as a
> > +  manager driver" (single clock DTS node acts as a starting point
> > for all other
> > +  clocks).
> >
> > -* The clk_get_rate() caches the previously read data if
> > CLK_GET_RATE_NOCACHE
> > -  is not set (no need for recursive access).
> > +* The clk_get_rate() caches the previously read data if
> > CLK_GET_RATE_NOCACHE is
> > +  not set (no need for recursive access).
> >
> > -* On purpose the "manager" clk driver (clk-imx6q.c) is not using
> > large
> > -  table to store pointers to clocks - e.g.
> > clk[IMX6QDL_CLK_USDHC2_SEL] = ....
> > -  Instead we use udevice's linked list for the same class
> > (UCLASS_CLK). +* On purpose the "manager" clk driver (clk-imx6q.c) is
> > not using large table to
> > +  store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = ....
> > Instead we
> > +  use udevice's linked list for the same class (UCLASS_CLK).
> >
> >    Rationale:
> >    ----------
> > -    When porting the code as is from Linux, one would need ~1KiB of
> > RAM to
> > -    store it. This is way too much if we do plan to use this driver
> > in SPL.
> > +    When porting the code as is from Linux, one would need ~1KiB of
> > RAM to store
> > +    it. This is way too much if we do plan to use this driver in SPL.
> >
> >  * The "central" structure of this patch series is struct udevice and
> > its uclass_priv field contains the struct clk pointer (to the
> > originally created one).
> >
> > -* Up till now U-Boot's driver model (DM) CLK operates on udevice
> > (main
> > -  access to clock is by udevice ops)
> > -  In the CCF the access to struct clk (embodying pointer to *dev) is
> > -  possible via dev_get_clk_ptr() (it is a wrapper on
> > dev_get_uclass_priv()). -
> >  * To keep things simple the struct udevice's uclass_priv pointer is
> > used to store back pointer to corresponding struct clk. However, it is
> > possible to modify clk-uclass.c file and add there struct uc_clk_priv,
> > which would have @@ -45,13 +40,17 @@ Design decisions:
> >    setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv))
> > the uclass_priv stores the pointer to struct clk.
> >
> > +* Non-CCF clocks do not have a pointer to a clock in clk->dev->priv.
> > In the case
> > +  of composite clocks, clk->dev->priv may not match clk. Drivers
> > should always
> > +  use the struct clk which is passed to them, and not clk->dev->priv.
> > +
> >  * It is advised to add common clock code (like already added rate and
> > flags) to the struct clk, which is a top level description of the
> > clock.
> >  * U-Boot's driver model already provides the facility to
> > automatically allocate
> > -  (via private_alloc_size) device private data (accessible via
> > dev->priv).
> > -  It may look appealing to use this feature to allocate private
> > structures for
> > -  CCF clk devices e.g. divider (struct clk_divider *divider) for
> > IMX6Q clock.
> > +  (via private_alloc_size) device private data (accessible via
> > dev->priv). It
> > +  may look appealing to use this feature to allocate private
> > structures for CCF
> > +  clk devices e.g. divider (struct clk_divider *divider) for IMX6Q
> > clock.
> >    The above feature had not been used for following reasons:
> >    - The original CCF Linux kernel driver is the "manager" for clocks
> > - it @@ -64,21 +63,23 @@ Design decisions:
> >
> >  * I've added the clk_get_parent(), which reads parent's
> > dev->uclass_priv to provide parent's struct clk pointer. This seems
> > the easiest way to get
> > -  child/parent relationship for struct clk in U-Boot's udevice based
> > clocks.
> > +  child/parent relationship for struct clk in U-Boot's udevice based
> > clocks.  In
> > +  the future arbitrary parents may be supported by adding a
> > get_parent function
> > +  to clk_ops.
> >
> >  * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in
> > 'struct clk'. Clock IP block agnostic flags from 'struct clk_core'
> > (e.g. NOCACHE) have been
> > -  moved from this struct one level up to 'struct clk'.
> > +  moved from this struct one level up to 'struct clk'. Many flags are
> > + unimplemented at the moment.
> >
> >  * For tests the new ./test/dm/clk_ccf.c and
> > ./drivers/clk/clk_sandbox_ccf.c files have been introduced. The latter
> > setups the CCF clock structure for
> > -  sandbox by reusing, if possible, generic clock primitives - like
> > divier
> > -  and mux. The former file provides code to tests this setup.
> > +  sandbox by reusing, if possible, generic clock primitives - like
> > divier and
> > +  mux. The former file provides code to tests this setup.
> >
> >    For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been
> > introduced.
> > -  All new primitives added for new architectures must have
> > corresponding test
> > -  in the two aforementioned files.
> > -
> > +  All new primitives added for new architectures must have
> > corresponding test in
> > +  the two aforementioned files.
> >
> >  Testing (sandbox):
> >  ==================
> > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> > index a5626c33d1..d0f273d47f 100644
> > --- a/drivers/clk/clk-composite.c
> > +++ b/drivers/clk/clk-composite.c
> > @@ -145,6 +145,14 @@ struct clk *clk_register_composite(struct device
> > *dev, const char *name, goto err;
> >       }
> >
> > +     if (composite->mux)
> > +             composite->mux->dev = clk->dev;
> > +     if (composite->rate)
> > +             composite->rate->dev = clk->dev;
> > +     if (composite->gate)
> > +             composite->gate->dev = clk->dev;
> > +
> > +
> >       return clk;
> >
> >  err:
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 822e09b084..bfa05f24a3 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -70,8 +70,7 @@ unsigned long divider_recalc_rate(struct clk *hw,
> > unsigned long parent_rate,  static ulong
> > clk_divider_recalc_rate(struct clk *clk)  {
> > -     struct clk_divider *divider =
> > to_clk_divider(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_divider *divider = to_clk_divider(clk);
> >       unsigned long parent_rate = clk_get_parent_rate(clk);
> >       unsigned int val;
> >
> > @@ -150,8 +149,7 @@ int divider_get_val(unsigned long rate, unsigned
> > long parent_rate,  static ulong clk_divider_set_rate(struct clk *clk,
> > unsigned long
> > rate) {
> > -     struct clk_divider *divider =
> > to_clk_divider(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_divider *divider = to_clk_divider(clk);
> >       unsigned long parent_rate = clk_get_parent_rate(clk);
> >       int value;
> >       u32 val;
> > diff --git a/drivers/clk/clk-fixed-factor.c
> > b/drivers/clk/clk-fixed-factor.c index 711b0588bc..d2401cf440 100644
> > --- a/drivers/clk/clk-fixed-factor.c
> > +++ b/drivers/clk/clk-fixed-factor.c
> > @@ -18,8 +18,7 @@
> >
> >  static ulong clk_factor_recalc_rate(struct clk *clk)  {
> > -     struct clk_fixed_factor *fix =
> > -             to_clk_fixed_factor(dev_get_clk_ptr(clk->dev));
> > +     struct clk_fixed_factor *fix = to_clk_fixed_factor(clk);
> >       unsigned long parent_rate = clk_get_parent_rate(clk);
> >       unsigned long long int rate;
> >
> > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index
> > 70b8794554..b2933bc24a 100644
> > --- a/drivers/clk/clk-gate.c
> > +++ b/drivers/clk/clk-gate.c
> > @@ -43,8 +43,7 @@
> >   */
> >  static void clk_gate_endisable(struct clk *clk, int enable)  {
> > -     struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_gate *gate = to_clk_gate(clk);
> >       int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
> >       u32 reg;
> >
> > @@ -86,8 +85,7 @@ static int clk_gate_disable(struct clk *clk)
> >
> >  int clk_gate_is_enabled(struct clk *clk)  {
> > -     struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_gate *gate = to_clk_gate(clk);
> >       u32 reg;
> >
> >  #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
> > diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index
> > 5acc0b8cbd..67b4afef28 100644
> > --- a/drivers/clk/clk-mux.c
> > +++ b/drivers/clk/clk-mux.c
> > @@ -35,8 +35,7 @@
> >  int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int
> > flags, unsigned int val)  {
> > -     struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_mux *mux = to_clk_mux(clk);
> >       int num_parents = mux->num_parents;
> >
> >       if (table) {
> > @@ -79,8 +78,7 @@ unsigned int clk_mux_index_to_val(u32 *table,
> > unsigned int flags, u8 index)
> >  u8 clk_mux_get_parent(struct clk *clk)  {
> > -     struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_mux *mux = to_clk_mux(clk);
> >       u32 val;
> >
> >  #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF)
> > @@ -97,8 +95,7 @@ u8 clk_mux_get_parent(struct clk *clk)  static int
> > clk_fetch_parent_index(struct clk *clk,
> >                                 struct clk *parent)
> >  {
> > -     struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_mux *mux = to_clk_mux(clk);
> >
> >       int i;
> >
> > @@ -115,8 +112,7 @@ static int clk_fetch_parent_index(struct clk *clk,
> >
> >  static int clk_mux_set_parent(struct clk *clk, struct clk *parent)  {
> > -     struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
> > -                     dev_get_clk_ptr(clk->dev) : clk);
> > +     struct clk_mux *mux = to_clk_mux(clk);
> >       int index;
> >       u32 val;
> >       u32 reg;
> > diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
> > index 1b9db6e791..e32c0cb53e 100644
> > --- a/drivers/clk/imx/clk-gate2.c
> > +++ b/drivers/clk/imx/clk-gate2.c
> > @@ -37,7 +37,7 @@ struct clk_gate2 {
> >
> >  static int clk_gate2_enable(struct clk *clk)  {
> > -     struct clk_gate2 *gate =
> > to_clk_gate2(dev_get_clk_ptr(clk->dev));
> > +     struct clk_gate2 *gate = to_clk_gate2(clk);
> >       u32 reg;
> >
> >       reg = readl(gate->reg);
> > @@ -50,7 +50,7 @@ static int clk_gate2_enable(struct clk *clk)
> >
> >  static int clk_gate2_disable(struct clk *clk)  {
> > -     struct clk_gate2 *gate =
> > to_clk_gate2(dev_get_clk_ptr(clk->dev));
> > +     struct clk_gate2 *gate = to_clk_gate2(clk);
> >       u32 reg;
> >
> >       reg = readl(gate->reg);
>
>
>
>
> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
> CONFIDENTIALITY NOTICE:
>
> This e-mail (and its attachments) may contain confidential and legally privileged information or information protected from disclosure. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein is strictly prohibited. In this case, please immediately notify the sender by return e-mail, delete the message (and any accompanying documents) and destroy all printed hard copies. Thank you for your cooperation.
>
> Copyright ANDES TECHNOLOGY CORPORATION - All Rights Reserved.

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

end of thread, other threads:[~2020-02-12  1:23 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-02 19:56 [PATCH v3 00/12] riscv: Add Sipeed Maix support Sean Anderson
2020-02-02 19:58 ` [PATCH v3 01/12] clk: Always use the supplied struct clk Sean Anderson
2020-02-06 21:21   ` Lukasz Majewski
     [not found]     ` <752D002CFF5D0F4FA35C0100F1D73F3FA46D30F5@ATCPCS16.andestech.com>
2020-02-12  1:23       ` Rick Chen
2020-02-02 19:58 ` [PATCH v3 02/12] clk: Check that ops of composite clock components, exist before calling Sean Anderson
2020-02-06 21:41   ` Lukasz Majewski
2020-02-02 19:59 ` [PATCH v3 03/12] clk: Unconditionally recursively en-/dis-able clocks Sean Anderson
2020-02-06 21:45   ` Lukasz Majewski
2020-02-02 20:01 ` [PATCH v3 04/12] reset: Add generic reset driver Sean Anderson
2020-02-03  0:04   ` Simon Glass
2020-02-03 23:14     ` Sean Anderson
2020-02-04 11:06   ` Bin Meng
2020-02-04 14:14     ` Sean Anderson
2020-02-02 20:02 ` [PATCH v3 05/12] dm: Add support for simple-pm-bus Sean Anderson
2020-02-03  0:04   ` Simon Glass
2020-02-03 23:15     ` Sean Anderson
2020-02-05  0:16       ` Simon Glass
2020-02-04 11:13   ` Bin Meng
2020-02-02 20:04 ` [PATCH v3 06/12] riscv: Add headers for asm/global_data.h Sean Anderson
2020-02-04 11:17   ` Bin Meng
2020-02-02 20:05 ` [PATCH v3 07/12] riscv: Add option to support RISC-V privileged spec 1.9.1 Sean Anderson
2020-02-04 11:21   ` Bin Meng
2020-02-04 14:19     ` Sean Anderson
2020-02-04 14:38       ` Bin Meng
2020-02-04 14:48         ` Sean Anderson
2020-02-04 16:04           ` Bin Meng
2020-02-04 16:07             ` Sean Anderson
2020-02-02 20:06 ` [PATCH v3 08/12] riscv: Allow use of reset drivers Sean Anderson
2020-02-04 11:22   ` Bin Meng
2020-02-02 20:07 ` [PATCH v3 09/12] riscv: Add K210 pll support Sean Anderson
2020-02-02 20:07 ` [PATCH v3 10/12] riscv: Add K210 clock support Sean Anderson
2020-02-06 21:51   ` Lukasz Majewski
2020-02-02 20:10 ` [PATCH v3 11/12] riscv: Add device tree for K210 Sean Anderson
2020-02-04 11:32   ` Bin Meng
2020-02-04 14:23     ` Sean Anderson
2020-02-04 14:40       ` Bin Meng
2020-02-02 20:10 ` [PATCH v3 12/12] riscv: Add initial Sipeed Maix support Sean Anderson
2020-02-04 11:38   ` Bin Meng
2020-02-04 14:26     ` Sean Anderson
2020-02-04 14:42       ` Bin Meng
2020-02-04 14:49         ` Sean Anderson

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