All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] riscv: Add Sipeed Maix support
@ 2019-12-31 22:39 Sean Anderson
  2019-12-31 22:42 ` [PATCH 01/11] clk: Always use the supplied struct clk Sean Anderson
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:39 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/1215326/> and
<https://patchwork.ozlabs.org/patch/1215327/>.
(log: Include missing header for log.h)
(clk: Include missing headers for linux/clk-provider.h)

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

Boot output should look like the following:

U-Boot 2020.01-rc5+ (Dec 31 2019 - 16:05:31 -0500)

CPU:   rv64acdfim
DRAM:  8 MiB
MMC:
In:    serial at 38000000
Out:   serial at 38000000
Err:   serial at 38000000
Model: Sipeed Maix
=>

Sean Anderson (11):
  clk: Always use the supplied struct clk
  clk: Check that ops of composite clock components exist before calling
  riscv: Add headers for asm/global_data.h
  riscv: Add an option to default to RV64I
  riscv: Enable SiFive UART support pre-relocation
  riscv: Add initial Sipeed Maix support
  riscv: Add device tree for K210
  riscv: Add K210 sysctl support
  riscv: Add K210 pll support
  riscv: Add K210 clock support
  riscv: Add option to disable writes to mcounteren

 arch/riscv/Kconfig                      |  16 +
 arch/riscv/cpu/cpu.c                    |   2 +
 arch/riscv/dts/Makefile                 |   1 +
 arch/riscv/dts/k210-maix-bit.dts        |  42 +++
 arch/riscv/dts/k210.dtsi                | 455 ++++++++++++++++++++++++
 arch/riscv/include/asm/global_data.h    |   2 +
 arch/riscv/include/asm/k210_sysctl.h    |  43 +++
 arch/riscv/lib/Makefile                 |   1 +
 arch/riscv/lib/k210_sysctl.c            |  22 ++
 board/sipeed/maix/Kconfig               |  49 +++
 board/sipeed/maix/MAINTAINERS           |  13 +
 board/sipeed/maix/Makefile              |   5 +
 board/sipeed/maix/maix.c                |   9 +
 configs/sipeed_maix_bitm_config         | 139 ++++++++
 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/imx/clk-gate2.c             |   4 +-
 drivers/clk/kendryte/Kconfig            |   7 +
 drivers/clk/kendryte/Makefile           |   1 +
 drivers/clk/kendryte/clk.c              | 391 ++++++++++++++++++++
 drivers/clk/kendryte/clk.h              |  27 ++
 drivers/clk/kendryte/pll.c              | 455 ++++++++++++++++++++++++
 drivers/clk/kendryte/pll.h              |  38 ++
 drivers/serial/serial_sifive.c          |   1 +
 include/configs/sipeed-maix.h           |  19 +
 include/dt-bindings/clock/k210-sysctl.h |  54 +++
 include/dt-bindings/reset/k210-sysctl.h |  39 ++
 32 files changed, 1887 insertions(+), 42 deletions(-)
 create mode 100644 arch/riscv/dts/k210-maix-bit.dts
 create mode 100644 arch/riscv/dts/k210.dtsi
 create mode 100644 arch/riscv/include/asm/k210_sysctl.h
 create mode 100644 arch/riscv/lib/k210_sysctl.c
 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_config
 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 include/configs/sipeed-maix.h
 create mode 100644 include/dt-bindings/clock/k210-sysctl.h
 create mode 100644 include/dt-bindings/reset/k210-sysctl.h

-- 
2.24.1

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

* [PATCH 01/11] clk: Always use the supplied struct clk
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
@ 2019-12-31 22:42 ` Sean Anderson
  2020-01-02  5:01   ` Jagan Teki
  2019-12-31 22:43 ` [PATCH 02/11] clk: Check that ops of composite clock components exist, before calling Sean Anderson
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:42 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>
---
This patch was previously submitted as
<https://patchwork.ozlabs.org/patch/1215335/>.

 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 ++--
 6 files changed, 19 insertions(+), 20 deletions(-)

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.24.1

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

* [PATCH 02/11] clk: Check that ops of composite clock components exist, before calling
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
  2019-12-31 22:42 ` [PATCH 01/11] clk: Always use the supplied struct clk Sean Anderson
@ 2019-12-31 22:43 ` Sean Anderson
  2019-12-31 22:44 ` [PATCH 03/11] riscv: Add headers for asm/global_data.h Sean Anderson
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:43 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>
---
This patch was previously submitted as
<https://patchwork.ozlabs.org/patch/1215337/>.

 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..ea9982fd57 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 -ENOTSUPP;
 }

 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 -ENOTSUPP;
 }

 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 -ENOTSUPP;
 }

 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 -ENOTSUPP;
 }

-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.24.1

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

* [PATCH 03/11] riscv: Add headers for asm/global_data.h
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
  2019-12-31 22:42 ` [PATCH 01/11] clk: Always use the supplied struct clk Sean Anderson
  2019-12-31 22:43 ` [PATCH 02/11] clk: Check that ops of composite clock components exist, before calling Sean Anderson
@ 2019-12-31 22:44 ` Sean Anderson
  2019-12-31 22:45 ` [PATCH 04/11] riscv: Add an option to default to RV64I Sean Anderson
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:44 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.24.1

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

* [PATCH 04/11] riscv: Add an option to default to RV64I
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (2 preceding siblings ...)
  2019-12-31 22:44 ` [PATCH 03/11] riscv: Add headers for asm/global_data.h Sean Anderson
@ 2019-12-31 22:45 ` Sean Anderson
  2019-12-31 22:46 ` [PATCH 05/11] riscv: Enable SiFive UART support pre-relocation Sean Anderson
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:45 UTC (permalink / raw)
  To: u-boot

This allows 64-bit boards to default to the 64-bit instruction set
without changing the current default of 32-bit.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 85e15ebffa..9a7b0334c2 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -60,8 +60,12 @@ source "arch/riscv/cpu/generic/Kconfig"

 # architecture-specific options below

+config ARCH_DEFAULT_RV64I
+	bool
+
 choice
 	prompt "Base ISA"
+	default ARCH_RV64I if ARCH_DEFAULT_RV64I
 	default ARCH_RV32I

 config ARCH_RV32I
-- 
2.24.1

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

* [PATCH 05/11] riscv: Enable SiFive UART support pre-relocation
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (3 preceding siblings ...)
  2019-12-31 22:45 ` [PATCH 04/11] riscv: Add an option to default to RV64I Sean Anderson
@ 2019-12-31 22:46 ` Sean Anderson
  2019-12-31 22:47 ` [PATCH 06/11] riscv: Add initial Sipeed Maix support Sean Anderson
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:46 UTC (permalink / raw)
  To: u-boot

Many other serial drivers are enabled pre-relocation to allow printing of
console messages before relocating. This should also be enabled for the SiFive
serial driver.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 drivers/serial/serial_sifive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
index c142ccdf3d..e103d2520e 100644
--- a/drivers/serial/serial_sifive.c
+++ b/drivers/serial/serial_sifive.c
@@ -203,6 +203,7 @@ U_BOOT_DRIVER(serial_sifive) = {
 	.platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata),
 	.probe = sifive_serial_probe,
 	.ops	= &sifive_serial_ops,
+	.flags = DM_FLAG_PRE_RELOC,
 };

 #ifdef CONFIG_DEBUG_UART_SIFIVE
-- 
2.24.1

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

* [PATCH 06/11] riscv: Add initial Sipeed Maix support
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (4 preceding siblings ...)
  2019-12-31 22:46 ` [PATCH 05/11] riscv: Enable SiFive UART support pre-relocation Sean Anderson
@ 2019-12-31 22:47 ` Sean Anderson
  2019-12-31 22:48 ` [PATCH 07/11] riscv: Add device tree for K210 Sean Anderson
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:47 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>
---
 arch/riscv/Kconfig              |   4 +
 board/sipeed/maix/Kconfig       |  40 ++++++++++
 board/sipeed/maix/MAINTAINERS   |   6 ++
 board/sipeed/maix/Makefile      |   5 ++
 board/sipeed/maix/maix.c        |   9 +++
 configs/sipeed_maix_bitm_config | 136 ++++++++++++++++++++++++++++++++
 include/configs/sipeed-maix.h   |  19 +++++
 7 files changed, 219 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_config
 create mode 100644 include/configs/sipeed-maix.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 9a7b0334c2..62c9616220 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..e64517a5cc
--- /dev/null
+++ b/board/sipeed/maix/Kconfig
@@ -0,0 +1,40 @@
+# 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 NR_CPUS
+	default 2
+
+config NR_DRAM_BANKS
+	default 2
+
+config BOARD_SPECIFIC_OPTIONS
+	def_bool y
+	select GENERIC_RISCV
+	select DM_SERIAL
+	select SIFIVE_SERIAL
+	select ARCH_DEFAULT_RV64I
+	select ENV_IS_NOWHERE
+	imply SIFIVE_CLINT
+	imply SPI
+	imply DM_GPIO
+	imply CMD_GPIO
+	imply SYS_NS16550
+	imply SYS_MALLOC_F
+endif
diff --git a/board/sipeed/maix/MAINTAINERS b/board/sipeed/maix/MAINTAINERS
new file mode 100644
index 0000000000..3632cd1c4c
--- /dev/null
+++ b/board/sipeed/maix/MAINTAINERS
@@ -0,0 +1,6 @@
+Sipeed Maix BOARD
+M:	Sean Anderson <seanga2@gmail.com>
+S:	Maintained
+F:	board/sipeed/maix/
+F:	include/configs/sipeed-maix.h
+F:	configs/sipeed_maix_defconfig
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_config b/configs/sipeed_maix_bitm_config
new file mode 100644
index 0000000000..97a246e307
--- /dev/null
+++ b/configs/sipeed_maix_bitm_config
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+CONFIG_CREATE_ARCH_SYMLINK=y
+CONFIG_RISCV=y
+CONFIG_SYS_ARCH="riscv"
+CONFIG_SYS_CPU="generic"
+CONFIG_SYS_VENDOR="sipeed"
+CONFIG_SYS_BOARD="maix"
+CONFIG_SYS_CONFIG_NAME="sipeed-maix"
+CONFIG_SPL_LDSCRIPT="arch/riscv/cpu/u-boot-spl.lds"
+CONFIG_SYS_TEXT_BASE=0x80000000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
+CONFIG_BOARD_SPECIFIC_OPTIONS=y
+CONFIG_ENV_SIZE=0x1f000
+CONFIG_ERR_PTR_OFFSET=0x0
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_IDENT_STRING=""
+CONFIG_64BIT=y
+CONFIG_TARGET_SIPEED_MAIX=y
+CONFIG_NR_CPUS=2
+CONFIG_GENERIC_RISCV=y
+CONFIG_ARCH_DEFAULT_RV64I=y
+CONFIG_ARCH_RV64I=y
+CONFIG_CMODEL_MEDLOW=y
+CONFIG_RISCV_MMODE=y
+CONFIG_RISCV_ISA_C=y
+CONFIG_RISCV_ISA_A=y
+CONFIG_SIFIVE_CLINT=y
+CONFIG_SHOW_REGS=y
+CONFIG_STACK_SIZE_SHIFT=14
+CONFIG_ARCH_K210=y
+CONFIG_LOCALVERSION=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYS_MALLOC_F=y
+CONFIG_PHYS_64BIT=y
+CONFIG_BUILD_TARGET=""
+CONFIG_SYS_EXTRA_OPTIONS=""
+CONFIG_BOOTSTAGE_RECORD_COUNT=30
+CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=5
+CONFIG_TPL_BOOTSTAGE_RECORD_COUNT=5
+CONFIG_BOOTSTAGE_STASH_SIZE=0x1000
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_LOGLEVEL=8
+CONFIG_SPL_LOGLEVEL=8
+CONFIG_TPL_LOGLEVEL=8
+CONFIG_LOG=y
+CONFIG_LOG_MAX_LEVEL=9
+CONFIG_LOG_DEFAULT_LEVEL=6
+CONFIG_LOG_CONSOLE=y
+CONFIG_LOG_ERROR_RETURN=y
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_DEFAULT_FDT_FILE=""
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_ARCH_EARLY_INIT_R=y
+CONFIG_SPL_SYS_STACK_F_CHECK_BYTE=0xaa
+CONFIG_CMDLINE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_SYS_LONGHELP=y
+CONFIG_SYS_PROMPT="=> "
+CONFIG_SYS_XTRACE="y"
+CONFIG_CMD_ENV_EXISTS=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_BLOCK_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_MTDIDS_DEFAULT=""
+CONFIG_MTDPARTS_DEFAULT=""
+CONFIG_CMD_LOG=y
+CONFIG_SUPPORT_OF_CONTROL=y
+CONFIG_DTC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_MKIMAGE_DTC_PATH="dtc"
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SIMPLE_BUS=y
+CONFIG_DM_DEV_READ_INLINE=y
+CONFIG_BLK=y
+CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_BLOCK_CACHE=y
+CONFIG_CLK=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_CPU=y
+CONFIG_CPU_RISCV=y
+CONFIG_MMC=y
+CONFIG_MMC_WRITE=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_QUIRKS=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SF_DEFAULT_BUS=0
+CONFIG_SF_DEFAULT_CS=0
+CONFIG_SF_DEFAULT_MODE=3
+CONFIG_SF_DEFAULT_SPEED=133000000
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_USE_4K_SECTORS=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_BAUDRATE=115200
+CONFIG_SERIAL_PRESENT=y
+CONFIG_DM_SERIAL=y
+CONFIG_SIFIVE_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_SPI_MEM=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_TIMER=y
+CONFIG_RISCV_TIMER=y
+CONFIG_WATCHDOG_TIMEOUT_MSECS=60000
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_MAX_CLUSTSIZE=65536
+CONFIG_PRINTF=y
+CONFIG_SPRINTF=y
+CONFIG_STRTO=y
+CONFIG_SYS_HZ=1000
+CONFIG_PANIC_HANG=y
+CONFIG_ZLIB=y
+CONFIG_HEXDUMP=y
+CONFIG_OF_LIBFDT=y
+CONFIG_OF_LIBFDT_ASSUME_MASK=0
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.24.1

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

* [PATCH 07/11] riscv: Add device tree for K210
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (5 preceding siblings ...)
  2019-12-31 22:47 ` [PATCH 06/11] riscv: Add initial Sipeed Maix support Sean Anderson
@ 2019-12-31 22:48 ` Sean Anderson
  2019-12-31 22:49 ` [PATCH 08/11] riscv: Add K210 sysctl support Sean Anderson
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:48 UTC (permalink / raw)
  To: u-boot

There is a mirror of ram located at 0x4000000 which is un-cached. This is
probably useful for DMA, but I am unsure of how to describe it in this device
tree.

The cache-line size is undocumented. Emphirical tests suggest that it is 32
bytes, but I've used 64-bytes to be on the safe side.

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 anything
aside from clint0, uarths0, and sysctl should be considered descriptive at best.
I would appreciate if anyone could help identify possibly compatible devices,
especially for the timers, watchdogs, and rtc.

The documentation for pinconf devices indicates that #pinctrl-cells is a
required property, but I am unsure what to put for it. Should that be filled in
by a board-specific device tree?

The sysctl device has multiple different unrelated registers. For the moment, I
have split off sub-devices for each functionality. In addition to clock and
reset control, it also contains DMA handshake registers, and power registers. I
have not described those at the moment, and I would appreciate suggestions on
how to best describe them.

I'm not sure what the value of spi-max-frequency should be for external sd-card
slots. Suggestions are appreciated.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/dts/Makefile                 |   1 +
 arch/riscv/dts/k210-maix-bit.dts        |  42 +++
 arch/riscv/dts/k210.dtsi                | 442 ++++++++++++++++++++++++
 board/sipeed/maix/Kconfig               |   3 +
 configs/sipeed_maix_bitm_config         |   1 +
 include/dt-bindings/clock/k210-sysctl.h |  54 +++
 include/dt-bindings/reset/k210-sysctl.h |  39 +++
 7 files changed, 582 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/clock/k210-sysctl.h
 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..faccf03e8a
--- /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";
+	compatible = "sipeed,maix", "kendryte,k210";
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 debug loglevel=7";
+		stdout-path = "/serial0";
+	};
+};
+
+&uarths0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+	mmc-slot at 0 {
+		compatible = "mmc-slot";
+		reg = <0>;
+		//spi-max-frequency = <???>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	status = "okay";
+	spi-flash at 0 {
+		compatible = "gd25lq64c", "gd25q64";
+		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..c17e206579
--- /dev/null
+++ b/arch/riscv/dts/k210.dtsi
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <dt-bindings/clock/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;
+	};
+
+	clocks {
+		in0: in0 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		timebase-frequency = <390000000>;
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			reg = <0>;
+			compatible = "riscv";
+			riscv,isa = "rv64acdfim";
+			mmu-type = "riscv,sv32";
+			i-cache-size = <0x8000>;
+			i-cache-block-size = <64>; /* bogus */
+			d-cache-size = <0x8000>;
+			d-cache-block-size = <64>; /* bogus */
+			clocks = <&sysclk K210_CLK_CPU>;
+			cpu-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 = "rv64acdfim";
+			mmu-type = "riscv,sv32";
+			i-cache-size = <0x8000>;
+			i-cache-block-size = <64>; /* bogus */
+			d-cache-size = <0x8000>;
+			d-cache-block-size = <64>; /* bogus */
+			clocks = <&sysclk K210_CLK_CPU>;
+			cpu-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 = "simple-bus";
+		ranges;
+		interrupt-parent = <&pic0>;
+		resets = <&sysrst K210_RST_SOC>;
+
+		clint0: interrupt-controller at 2000000 {
+			compatible = "riscv,clint0";
+			reg = <0x2000000 0xC000>;
+			interrupts-extended = <&CPU0_intc 3>,  <&CPU1_intc 3>;
+			clocks = <&sysclk K210_CLK_CPU>;
+		};
+
+		pic0: interrupt-controller at c000000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "riscv,plic1";
+			reg = <0xC000000 0x03FFF008>;
+			interrupts-extended = <&CPU0_intc 11>, <&CPU0_intc 9>,
+			                      <&CPU1_intc 11>, <&CPU1_intc 9>;
+			riscv,ndev = <65>;
+		};
+
+		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 0x44>;
+			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 0x48>;
+			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 0xD00>;
+			interrupts = <27 28 29 30 31 32>;
+			clocks = <&sysclk K210_CLK_DMA>;
+			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";
+		};
+
+		gpio1: gpio-controller at 50200000 {
+			#gpio-cells = <2>;
+			compatible = "none";
+			reg = <0x50200000 0x6C>;
+			gpio-controller;
+			//gpio-ranges = < >;
+			interrupts = <23>;
+			clocks = <&sysclk K210_CLK_GPIO>;
+			resets = <&sysrst K210_RST_GPIO>;
+			status = "disabled";
+		};
+
+		uart1: serial at 50210000 {
+			compatible = "ns16550";
+			reg = <50210000 0xc4>;
+			interrupts = <11>;
+			clocks = <&sysclk K210_CLK_UART1>;
+			resets = <&sysrst K210_RST_UART1>;
+			fifo-size = <8>;
+			no-loopback-test;
+			status = "disabled";
+		};
+
+		uart2: serial at 50220000 {
+			compatible = "ns16550";
+			reg = <50220000 0xc4>;
+			interrupts = <12>;
+			clocks = <&sysclk K210_CLK_UART2>;
+			resets = <&sysrst K210_RST_UART2>;
+			fifo-size = <8>;
+			no-loopback-test;
+			status = "disabled";
+		};
+
+		uart3: serial at 50230000 {
+			compatible = "ns16550";
+			reg = <50230000 0xc4>;
+			interrupts = <13>;
+			clocks = <&sysclk K210_CLK_UART3>;
+			resets = <&sysrst K210_RST_UART3>;
+			fifo-size = <8>;
+			no-loopback-test;
+			status = "disabled";
+		};
+
+		spi2: spi at 50240000 {
+			compatible = "snps,designware-spi";
+			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 0x138>;
+			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 {
+			compatible = "pinconf-single";
+			reg = <0x502B0000 0x100>;
+			//#pinctrl-cells = <???>;
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <0x7fffff>;
+			clocks = <&sysclk K210_CLK_FPIOA>;
+			resets = <&sysrst K210_RST_FPIOA>;
+			status = "disabled";
+		};
+
+		sha256: sha256 at 502C0000 {
+			compatible = "none";
+			reg = <0x502C0000 0x38>;
+			clocks = <&sysclk K210_CLK_SHA>;
+			resets = <&sysrst K210_RST_SHA>;
+			status = "disabled";
+		};
+
+		timer0: timer at 502D0000 {
+			compatible = "none";
+			reg = <0x502D0000 0xC0>;
+			interrupts = <14 15>;
+			clocks = <&sysclk K210_CLK_TIMER0>;
+			resets = <&sysrst K210_RST_TIMER0>;
+			status = "disabled";
+		};
+
+		timer1: timer at 502E0000 {
+			compatible = "none";
+			reg = <0x502E0000 0xC0>;
+			interrupts = <16 17>;
+			clocks = <&sysclk K210_CLK_TIMER1>;
+			resets = <&sysrst K210_RST_TIMER1>;
+			status = "disabled";
+		};
+
+		timer2: timer at 502F0000 {
+			compatible = "none";
+			reg = <0x502F0000 0xC0>;
+			interrupts = <18 19>;
+			clocks = <&sysclk K210_CLK_TIMER2>;
+			resets = <&sysrst K210_RST_TIMER2>;
+			status = "disabled";
+		};
+
+		wdt0: watchdog at 50400000 {
+			compatible = "none";
+			reg = <0x50400000 0x100>;
+			interrupts = <21>;
+			clocks = <&sysclk K210_CLK_WDT0>;
+			resets = <&sysrst K210_RST_WDT0>;
+			status = "disabled";
+		};
+
+		wdt1: watchdog at 50410000 {
+			compatible = "none";
+			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 0x2c>;
+			interrupts = <24>;
+			clocks = <&sysclk K210_CLK_DVP>;
+			resets = <&sysrst K210_RST_DVP>;
+			status = "disabled";
+		};
+
+		sysctl: sysctl at 50440000 {
+			compatible = "kendryte,k210-sysctl", "syscon";
+			reg = <0x50440000 0x80>;
+
+			sysclk: clock-controller {
+				compatible = "kendryte,k210-clk";
+				clocks = <&in0>;
+				#clock-cells = <1>;
+			};
+
+			sysrst: reset-controller {
+				compatible = "kendryte,k210-rst";
+				#reset-cells = <1>;
+			};
+		};
+
+		aes0: aes at 50450000 {
+			compatible = "none";
+			reg = <0x50450000 0x94>;
+			clocks = <&sysclk K210_CLK_AES>;
+			resets = <&sysrst K210_RST_AES>;
+			status = "disabled";
+		};
+
+		rtc: rts at 50460000 {
+			compatible = "none";
+			reg = <0x50460000 0x2C>;
+			clocks = <&in0>;
+			resets = <&sysrst K210_RST_RTC>;
+			interrupts = <20>;
+			status = "disabled";
+		};
+
+		spi0: spi at 52000000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "snps,designware-spi";
+			reg = <0x52000000 0x120>;
+			interrupts = <1>;
+			clocks = <&sysclk K210_CLK_SPI0>;
+			resets = <&sysrst K210_RST_SPI0>;
+			num-cs = <4>;
+			status = "disabled";
+		};
+
+		spi1: spi at 53000000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "snps,designware-spi";
+			reg = <0x53000000 0x120>;
+			interrupts = <2>;
+			clocks = <&sysclk K210_CLK_SPI1>;
+			resets = <&sysrst K210_RST_SPI1>;
+			num-cs = <4>;
+			status = "disabled";
+		};
+
+		spi3: spi at 54000000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "snps,designware-spi";
+			reg = <0x54000000 0x120>;
+			interrupts = <4>;
+			clocks = <&sysclk K210_CLK_SPI3>;
+			resets = <&sysrst K210_RST_SPI3>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		rom0: nvmem at 88000000 {
+			reg = <0x88000000 0x4000>;
+			read-only;
+			clocks = <&sysclk K210_CLK_ROM>;
+			resets = <&sysrst K210_RST_ROM>;
+		};
+	};
+};
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index e64517a5cc..ec9acd61ca 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -18,6 +18,9 @@ config SYS_CONFIG_NAME
 config SYS_TEXT_BASE
 	default 0x80000000

+config DEFAULT_DEVICE_TREE
+	default "k210-maix-bit"
+
 config NR_CPUS
 	default 2

diff --git a/configs/sipeed_maix_bitm_config b/configs/sipeed_maix_bitm_config
index 97a246e307..70bb566cb1 100644
--- a/configs/sipeed_maix_bitm_config
+++ b/configs/sipeed_maix_bitm_config
@@ -18,6 +18,7 @@ CONFIG_BOOTSTAGE_STASH_ADDR=0
 CONFIG_IDENT_STRING=""
 CONFIG_64BIT=y
 CONFIG_TARGET_SIPEED_MAIX=y
+CONFIG_DEFAULT_DEVICE_TREE="k210-maix-bit"
 CONFIG_NR_CPUS=2
 CONFIG_GENERIC_RISCV=y
 CONFIG_ARCH_DEFAULT_RV64I=y
diff --git a/include/dt-bindings/clock/k210-sysctl.h b/include/dt-bindings/clock/k210-sysctl.h
new file mode 100644
index 0000000000..308974baf8
--- /dev/null
+++ b/include/dt-bindings/clock/k210-sysctl.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef CLOCK_K210_SYSCTL_H
+#define CLOCK_K210_SYSCTL_H
+
+/* Clocks as defined by kendryte-standalone-sdk/lib/drivers/include/sysctl.h */
+#define K210_CLK_PLL0 0
+#define K210_CLK_PLL1 1
+#define K210_CLK_PLL2 2
+#define K210_CLK_CPU 3
+#define K210_CLK_SRAM0 4
+#define K210_CLK_SRAM1 5
+#define K210_CLK_APB0 6
+#define K210_CLK_APB1 7
+#define K210_CLK_APB2 8
+#define K210_CLK_ROM 9
+#define K210_CLK_DMA 10
+#define K210_CLK_AI 11
+#define K210_CLK_DVP 12
+#define K210_CLK_FFT 13
+#define K210_CLK_GPIO 14
+#define K210_CLK_SPI0 15
+#define K210_CLK_SPI1 16
+#define K210_CLK_SPI2 17
+#define K210_CLK_SPI3 18
+#define K210_CLK_I2S0 19
+#define K210_CLK_I2S1 20
+#define K210_CLK_I2S2 21
+#define K210_CLK_I2C0 22
+#define K210_CLK_I2C1 23
+#define K210_CLK_I2C2 24
+#define K210_CLK_UART1 25
+#define K210_CLK_UART2 26
+#define K210_CLK_UART3 27
+#define K210_CLK_AES 28
+#define K210_CLK_FPIOA 29
+#define K210_CLK_TIMER0 30
+#define K210_CLK_TIMER1 31
+#define K210_CLK_TIMER2 32
+#define K210_CLK_WDT0 33
+#define K210_CLK_WDT1 34
+#define K210_CLK_SHA 35
+#define K210_CLK_OTP 36
+#define K210_CLK_RTC 37
+#define K210_CLK_ACLK 40
+#define K210_CLK_MAX 40
+
+#define K210_CLK_HCLK 41 /* Unused */
+#define K210_CLK_IN0 42 /* Defined elsewhere in the device tree */
+
+#endif /* CLOCK_K210_SYSCTL_H */
diff --git a/include/dt-bindings/reset/k210-sysctl.h b/include/dt-bindings/reset/k210-sysctl.h
new file mode 100644
index 0000000000..01605224f9
--- /dev/null
+++ b/include/dt-bindings/reset/k210-sysctl.h
@@ -0,0 +1,39 @@
+/* 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_SOC 0
+#define K210_RST_ROM 1
+#define K210_RST_DMA 2
+#define K210_RST_AI 3
+#define K210_RST_DVP 4
+#define K210_RST_FFT 5
+#define K210_RST_GPIO 6
+#define K210_RST_SPI0 7
+#define K210_RST_SPI1 8
+#define K210_RST_SPI2 9
+#define K210_RST_SPI3 10
+#define K210_RST_I2S0 11
+#define K210_RST_I2S1 12
+#define K210_RST_I2S2 13
+#define K210_RST_I2C0 14
+#define K210_RST_I2C1 15
+#define K210_RST_I2C2 16
+#define K210_RST_UART1 17
+#define K210_RST_UART2 18
+#define K210_RST_UART3 19
+#define K210_RST_AES 20
+#define K210_RST_FPIOA 21
+#define K210_RST_TIMER0 22
+#define K210_RST_TIMER1 23
+#define K210_RST_TIMER2 24
+#define K210_RST_WDT0 25
+#define K210_RST_WDT1 26
+#define K210_RST_SHA 27
+#define K210_RST_RTC 28
+
+#endif /* RESET_K210_SYSCTL_H */
-- 
2.24.1

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

* [PATCH 08/11] riscv: Add K210 sysctl support
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (6 preceding siblings ...)
  2019-12-31 22:48 ` [PATCH 07/11] riscv: Add device tree for K210 Sean Anderson
@ 2019-12-31 22:49 ` Sean Anderson
  2019-12-31 22:50 ` [PATCH 09/11] riscv: Add K210 pll support Sean Anderson
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:49 UTC (permalink / raw)
  To: u-boot

This driver does nothing but load its children for the moment. Should it be
using regmap? I'm not sure how that fits into everything.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/Kconfig                   | 11 +++++++
 arch/riscv/Makefile                  |  6 ++++
 arch/riscv/include/asm/k210_sysctl.h | 43 ++++++++++++++++++++++++++++
 arch/riscv/lib/Makefile              |  1 +
 arch/riscv/lib/k210_sysctl.c         | 22 ++++++++++++++
 arch/riscv/mach-k210/Makefile        |  1 +
 board/sipeed/maix/Kconfig            |  2 ++
 configs/sipeed_maix_bitm_config      |  1 +
 8 files changed, 87 insertions(+)
 create mode 100644 arch/riscv/include/asm/k210_sysctl.h
 create mode 100644 arch/riscv/lib/k210_sysctl.c
 create mode 100644 arch/riscv/mach-k210/Makefile

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 62c9616220..13518b0440 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -196,6 +196,14 @@ config RISCV_RDTIME
 	  standard rdtime instruction. This is the case for S-mode U-Boot, and
 	  is useful for processors that support rdtime in M-mode too.

+config K210_SYSCTL
+	bool
+	select SYSCON
+	select SPL_SYSCON if SPL
+	help
+	  The K210 sysctl block holds memory-mapped control and status
+	  registers associated with clocks, resets, power, and dma handshakes.
+
 config SYS_MALLOC_F_LEN
 	default 0x1000

@@ -237,4 +245,7 @@ config STACK_SIZE_SHIFT
 config SPL_LDSCRIPT
 	default "arch/riscv/cpu/u-boot-spl.lds"

+config ARCH_K210
+	bool "Support Kendryte K210 SOCs"
+
 endmenu
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 0b80eb8d86..390178e149 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -30,6 +30,12 @@ ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI) \
 PLATFORM_CPPFLAGS	+= $(ARCH_FLAGS)
 CFLAGS_EFI		+= $(ARCH_FLAGS)

+machine-$(CONFIG_ARCH_K210) += k210
+
+machdirs := $(patsubst %,arch/riscv/mach-%/,$(machine-y))
+PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+libs-y += $(machdirs)
+
 head-y := arch/riscv/cpu/start.o

 libs-y += arch/riscv/cpu/
diff --git a/arch/riscv/include/asm/k210_sysctl.h b/arch/riscv/include/asm/k210_sysctl.h
new file mode 100644
index 0000000000..94170f4f31
--- /dev/null
+++ b/arch/riscv/include/asm/k210_sysctl.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef K210_SYSCTL_H
+#define K210_SYSCTL_H
+
+#include <linux/compiler.h>
+
+/*
+ * sysctl registers
+ * Taken from kendryte-standalone-sdk/lib/drivers/include/sysctl.h
+ */
+struct k210_sysctl {
+	u32 git_id;
+	u32 clk_freq;
+	u32 pll0;
+	u32 pll1;
+	u32 pll2;
+	u32 resv5;
+	u32 pll_lock;
+	u32 rom_error;
+	u32 clk_sel[2];
+	u32 clk_en_cent;
+	u32 clk_en_peri;
+	u32 soft_reset;
+	u32 peri_reset;
+	u32 clk_thr[7];
+	u32 misc;
+	u32 peri;
+	u32 spi_sleep;
+	u32 reset_status;
+	u32 dma_sel0;
+	u32 dma_sel1;
+	u32 power_sel;
+	u32 resv28;
+	u32 resv29;
+	u32 resv30;
+	u32 resv31;
+} __packed;
+
+#endif /* K210_SYSCTL_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index c9179a5ff8..4c31e824d9 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -14,6 +14,7 @@ ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
 obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
 obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
 obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
+obj-$(CONFIG_K210_SYSCTL) += k210_sysctl.o
 else
 obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
 obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
diff --git a/arch/riscv/lib/k210_sysctl.c b/arch/riscv/lib/k210_sysctl.c
new file mode 100644
index 0000000000..f0b66aa36a
--- /dev/null
+++ b/arch/riscv/lib/k210_sysctl.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+#include <asm/k210_sysctl.h>
+
+#include <dm.h>
+
+static const struct udevice_id k210_sysctl_ids[] = {
+	{ .compatible = "kendryte,k210-sysctl", },
+	{ }
+};
+
+U_BOOT_DRIVER(k210_sysctl) = {
+	.name = "k210_sysctl",
+	.id = UCLASS_SYSCON,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind = dm_scan_fdt_dev,
+#endif
+	.of_match = k210_sysctl_ids,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/arch/riscv/mach-k210/Makefile b/arch/riscv/mach-k210/Makefile
new file mode 100644
index 0000000000..6defe5ccb2
--- /dev/null
+++ b/arch/riscv/mach-k210/Makefile
@@ -0,0 +1 @@
+obj-y := sysctl.o
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index ec9acd61ca..257135b2cb 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -34,7 +34,9 @@ config BOARD_SPECIFIC_OPTIONS
 	select SIFIVE_SERIAL
 	select ARCH_DEFAULT_RV64I
 	select ENV_IS_NOWHERE
+	select ARCH_K210
 	imply SIFIVE_CLINT
+	imply K210_SYSCTL
 	imply SPI
 	imply DM_GPIO
 	imply CMD_GPIO
diff --git a/configs/sipeed_maix_bitm_config b/configs/sipeed_maix_bitm_config
index 70bb566cb1..bb2d2e7932 100644
--- a/configs/sipeed_maix_bitm_config
+++ b/configs/sipeed_maix_bitm_config
@@ -28,6 +28,7 @@ CONFIG_RISCV_MMODE=y
 CONFIG_RISCV_ISA_C=y
 CONFIG_RISCV_ISA_A=y
 CONFIG_SIFIVE_CLINT=y
+CONFIG_K210_SYSCTL=y
 CONFIG_SHOW_REGS=y
 CONFIG_STACK_SIZE_SHIFT=14
 CONFIG_ARCH_K210=y
-- 
2.24.1

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

* [PATCH 09/11] riscv: Add K210 pll support
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (7 preceding siblings ...)
  2019-12-31 22:49 ` [PATCH 08/11] riscv: Add K210 sysctl support Sean Anderson
@ 2019-12-31 22:50 ` Sean Anderson
  2019-12-31 22:50 ` [PATCH 10/11] riscv: Add K210 clock support Sean Anderson
  2019-12-31 22:51 ` [PATCH 11/11] riscv: Add option to disable writes to mcounteren Sean Anderson
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:50 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.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/mach-k210/Makefile   |   1 -
 board/sipeed/maix/Kconfig       |   1 +
 configs/sipeed_maix_bitm_config |   1 +
 drivers/clk/Kconfig             |   1 +
 drivers/clk/Makefile            |   1 +
 drivers/clk/kendryte/Kconfig    |   7 +
 drivers/clk/kendryte/Makefile   |   1 +
 drivers/clk/kendryte/pll.c      | 455 ++++++++++++++++++++++++++++++++
 drivers/clk/kendryte/pll.h      |  38 +++
 9 files changed, 505 insertions(+), 1 deletion(-)
 delete mode 100644 arch/riscv/mach-k210/Makefile
 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/arch/riscv/mach-k210/Makefile b/arch/riscv/mach-k210/Makefile
deleted file mode 100644
index 6defe5ccb2..0000000000
--- a/arch/riscv/mach-k210/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-y := sysctl.o
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index 257135b2cb..838f2fb263 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -37,6 +37,7 @@ config BOARD_SPECIFIC_OPTIONS
 	select ARCH_K210
 	imply SIFIVE_CLINT
 	imply K210_SYSCTL
+	imply CLK_K210
 	imply SPI
 	imply DM_GPIO
 	imply CMD_GPIO
diff --git a/configs/sipeed_maix_bitm_config b/configs/sipeed_maix_bitm_config
index bb2d2e7932..f20145feac 100644
--- a/configs/sipeed_maix_bitm_config
+++ b/configs/sipeed_maix_bitm_config
@@ -95,6 +95,7 @@ CONFIG_BLOCK_CACHE=y
 CONFIG_CLK=y
 CONFIG_CLK_CCF=y
 CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_K210=y
 CONFIG_CPU=y
 CONFIG_CPU_RISCV=y
 CONFIG_MMC=y
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..a178d50f5e
--- /dev/null
+++ b/drivers/clk/kendryte/Kconfig
@@ -0,0 +1,7 @@
+config CLK_K210
+	bool "Clock support for Kendryte K210"
+	depends on K210_SYSCTL
+	select CLK
+	select CLK_CCF
+	help
+	  This enables support clock driver for Kendryte K210 platforms.
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..b6aa16cd0d
--- /dev/null
+++ b/drivers/clk/kendryte/pll.c
@@ -0,0 +1,455 @@
+// 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 "clk_k210_pll"
+#define to_k210_pll(_clk) container_of(_clk, struct k210_pll, clk)
+
+static int k210_pll_enable(struct clk *clk);
+static int k210_pll_disable(struct clk *clk);
+
+/*
+ * The k210 PLLs have three factors: r, f, and od. 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 possible settings for the PLL. However, most of these settings can
+ * be ruled out immediately because they do not have the correct ratio. Of these
+ * remaining options, there are at most 97, due to the limited range of f, r,
+ * and od.
+ *
+ * Throughout the calculation function, fixed point arithmetic is used. Because
+ * the range of rate and rate_in may be up to 1.8 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.
+ *
+ * The r and od factors are stored in a table. This is to make it easy to find
+ * the next-largest product.
+ *
+ * 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:
+ * factors = {}
+ * for i in range(1, 17):
+ *  for j in range(1, 17):
+ *   (x, y) = factors.get(i*j) or (17, 1)
+ *   # Pick "balanced" factors
+ *   if abs(i - j) < abs(x - y):
+ *    factors[i*j] = (i, j)
+ * for k, v in sorted(factors.items()):
+ *  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(2, 2),
+	PACK(1, 5),
+	PACK(2, 3),
+	PACK(1, 7),
+	PACK(2, 4),
+	PACK(3, 3),
+	PACK(2, 5),
+	PACK(1, 11),
+	PACK(3, 4),
+	PACK(1, 13),
+	PACK(2, 7),
+	PACK(3, 5),
+	PACK(4, 4),
+	PACK(3, 6),
+	PACK(4, 5),
+	PACK(3, 7),
+	PACK(2, 11),
+	PACK(4, 6),
+	PACK(5, 5),
+	PACK(2, 13),
+	PACK(3, 9),
+	PACK(4, 7),
+	PACK(5, 6),
+	PACK(4, 8),
+	PACK(3, 11),
+	PACK(5, 7),
+	PACK(6, 6),
+	PACK(3, 13),
+	PACK(5, 8),
+	PACK(6, 7),
+	PACK(4, 11),
+	PACK(5, 9),
+	PACK(6, 8),
+	PACK(7, 7),
+	PACK(5, 10),
+	PACK(4, 13),
+	PACK(6, 9),
+	PACK(5, 11),
+	PACK(7, 8),
+	PACK(6, 10),
+	PACK(7, 9),
+	PACK(8, 8),
+	PACK(5, 13),
+	PACK(6, 11),
+	PACK(7, 10),
+	PACK(8, 9),
+	PACK(5, 15),
+	PACK(7, 11),
+	PACK(6, 13),
+	PACK(8, 10),
+	PACK(9, 9),
+	PACK(7, 12),
+	PACK(8, 11),
+	PACK(9, 10),
+	PACK(7, 13),
+	PACK(8, 12),
+	PACK(7, 14),
+	PACK(9, 11),
+	PACK(10, 10),
+	PACK(8, 13),
+	PACK(7, 15),
+	PACK(9, 12),
+	PACK(10, 11),
+	PACK(8, 14),
+	PACK(9, 13),
+	PACK(10, 12),
+	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(12, 12),
+	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 r, f, od;
+
+	/* Can't go over 1.8 GHz */
+	if (rate > 1800000000)
+		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;
+
+	/* Variables get immediately incremented, so start at -1th iteration */
+	i = -1;
+	f = 0;
+	r = 0;
+	od = 0;
+	best_error = S64_MAX;
+	/* do-while here so we always try@least one ratio */
+	do {
+		/*
+		 * Try the next largest value for f (or r and od) and
+		 * recalculate the other parameters based on that
+		 */
+		if (rate > rate_in) {
+			i++;
+			r = UNPACK_R(factors[i]);
+			od = UNPACK_OD(factors[i]);
+			
+			/* Round close */
+			f = (r * od * ratio + BIT(31)) >> 32;
+			if (f > 64)
+				f = 64;
+
+		} else {
+			u64 last_od = od;
+			u64 last_r = r;
+			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;
+			}
+		}
+		/* 32.0 * 32.32 = 64.32 */
+		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;
+		}
+	} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
+
+	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);
+}
+
+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 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);
+		udelay(1);
+	}
+}
+
+/* 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);
+
+	reg &= ~K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	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);
+	/* FIXME: this doesn't really have to be a whole microsecond */
+	udelay(1);
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+
+	k210_pll_waitfor_lock(pll);
+	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,
+	.set_rate = k210_pll_set_rate,
+	.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(shift + width, 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,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/kendryte/pll.h b/drivers/clk/kendryte/pll.h
new file mode 100644
index 0000000000..6a8734a295
--- /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)
+#define K210_PLL_BWADJ GENMASK(19, 14)
+#define K210_PLL_RESET BIT(20)
+#define K210_PLL_PWRD BIT(21)
+#define K210_PLL_INTFB BIT(22)
+#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.24.1

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

* [PATCH 10/11] riscv: Add K210 clock support
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (8 preceding siblings ...)
  2019-12-31 22:50 ` [PATCH 09/11] riscv: Add K210 pll support Sean Anderson
@ 2019-12-31 22:50 ` Sean Anderson
  2019-12-31 22:51 ` [PATCH 11/11] riscv: Add option to disable writes to mcounteren Sean Anderson
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:50 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>
---
 arch/riscv/Kconfig              |   3 -
 arch/riscv/Makefile             |   6 -
 arch/riscv/dts/k210.dtsi        |  13 ++
 board/sipeed/maix/Kconfig       |   4 +-
 configs/sipeed_maix_bitm_config |   1 -
 drivers/clk/kendryte/clk.c      | 391 ++++++++++++++++++++++++++++++++
 drivers/clk/kendryte/clk.h      |  27 +++
 7 files changed, 434 insertions(+), 11 deletions(-)
 create mode 100644 drivers/clk/kendryte/clk.c
 create mode 100644 drivers/clk/kendryte/clk.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 13518b0440..d85235a378 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -245,7 +245,4 @@ config STACK_SIZE_SHIFT
 config SPL_LDSCRIPT
 	default "arch/riscv/cpu/u-boot-spl.lds"

-config ARCH_K210
-	bool "Support Kendryte K210 SOCs"
-
 endmenu
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 390178e149..0b80eb8d86 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -30,12 +30,6 @@ ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI) \
 PLATFORM_CPPFLAGS	+= $(ARCH_FLAGS)
 CFLAGS_EFI		+= $(ARCH_FLAGS)

-machine-$(CONFIG_ARCH_K210) += k210
-
-machdirs := $(patsubst %,arch/riscv/mach-%/,$(machine-y))
-PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
-libs-y += $(machdirs)
-
 head-y := arch/riscv/cpu/start.o

 libs-y += arch/riscv/cpu/
diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi
index c17e206579..5e86fe3fdc 100644
--- a/arch/riscv/dts/k210.dtsi
+++ b/arch/riscv/dts/k210.dtsi
@@ -27,6 +27,7 @@
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <26000000>;
+			u-boot,dm-pre-reloc;
 		};
 	};

@@ -371,6 +372,18 @@
 				compatible = "kendryte,k210-clk";
 				clocks = <&in0>;
 				#clock-cells = <1>;
+				assigned-clocks = <&sysclk K210_CLK_ACLK>,
+				                  <&sysclk K210_CLK_PLL0>,
+				                  <&sysclk K210_CLK_PLL1>,
+						  <&sysclk K210_CLK_PLL2>;
+				assigned-clock-parents = <&sysclk K210_CLK_PLL0>,
+				                         <0>,
+							 <0>,
+							 <&in0>;
+				assigned-clock-rates = <793000000>,
+				                       <390000000>,
+						       <390000000>,
+						       <793000000>;
 			};

 			sysrst: reset-controller {
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index 838f2fb263..6a25086ef4 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -27,6 +27,9 @@ config NR_CPUS
 config NR_DRAM_BANKS
 	default 2

+config SYS_MALLOC_F_LEN
+	default 0x8000
+
 config BOARD_SPECIFIC_OPTIONS
 	def_bool y
 	select GENERIC_RISCV
@@ -34,7 +37,6 @@ config BOARD_SPECIFIC_OPTIONS
 	select SIFIVE_SERIAL
 	select ARCH_DEFAULT_RV64I
 	select ENV_IS_NOWHERE
-	select ARCH_K210
 	imply SIFIVE_CLINT
 	imply K210_SYSCTL
 	imply CLK_K210
diff --git a/configs/sipeed_maix_bitm_config b/configs/sipeed_maix_bitm_config
index f20145feac..0088748ae0 100644
--- a/configs/sipeed_maix_bitm_config
+++ b/configs/sipeed_maix_bitm_config
@@ -31,7 +31,6 @@ CONFIG_SIFIVE_CLINT=y
 CONFIG_K210_SYSCTL=y
 CONFIG_SHOW_REGS=y
 CONFIG_STACK_SIZE_SHIFT=14
-CONFIG_ARCH_K210=y
 CONFIG_LOCALVERSION=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYS_MALLOC_F=y
diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c
new file mode 100644
index 0000000000..2781ee94e3
--- /dev/null
+++ b/drivers/clk/kendryte/clk.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+#include "clk.h"
+
+#include <asm/io.h>
+#include <asm/k210_sysctl.h>
+#include <dt-bindings/clock/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;
+	struct k210_sysctl *sysctl;
+
+	sysctl = dev_read_addr_ptr(dev_get_parent(dev));
+	if (!sysctl)
+		return -EINVAL;
+
+	err = clk_get_by_index(dev, 0, &in0_clk);
+	if (err)
+		goto cleanup_sysctl;
+	in0 = in0_clk.dev->name;
+	generic_sels[0] = in0;
+	pll2_sels[0] = in0;
+
+	/* PLLs */
+	clk_dm(K210_CLK_PLL0, k210_clk_pll("pll0", in0, &sysctl->pll0,
+					   &sysctl->pll_lock, 0, 2));
+	clk_dm(K210_CLK_PLL1, k210_clk_pll("pll1", in0, &sysctl->pll1,
+					   &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),
+				&sysctl->pll2, 26, 2);
+	pll = k210_clk_comp_pll(&sysctl->pll2, &sysctl->pll_lock, 16, 1);
+	if (!mux || !pll) {
+		kfree(mux);
+		kfree(pll);
+	} else {
+		clk_dm(K210_CLK_PLL0,
+		       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(&sysctl->clk_sel[0], 1, 2,
+				      CLK_DIVIDER_POWER_OF_TWO);
+	/* ACLK has no gate */
+	mux = k210_clk_comp_mux(aclk_sels, ARRAY_SIZE(generic_sels),
+				&sysctl->clk_sel[0], 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(&sysctl->clk_sel[0], 1, 2);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 9);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				&sysctl->clk_sel[0], 12, 1);
+	clk_dm(K210_CLK_SPI3, k210_clk_comp("spi3", div, gate, mux));
+	
+	div = k210_clk_comp_div(&sysctl->clk_thr[2], 8, 0);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 21);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				&sysctl->clk_sel[0], 12, 1);
+	clk_dm(K210_CLK_TIMER0, k210_clk_comp("timer0", div, gate, mux));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[2], 8, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 22);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				&sysctl->clk_sel[0], 12, 1);
+	clk_dm(K210_CLK_TIMER1, k210_clk_comp("timer1", div, gate, mux));
+	
+	div = k210_clk_comp_div(&sysctl->clk_thr[2], 8, 16);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 23);
+	mux = k210_clk_comp_mux(generic_sels, ARRAY_SIZE(generic_sels),
+				&sysctl->clk_sel[0], 12, 1);
+	clk_dm(K210_CLK_TIMER2, k210_clk_comp("timer2", div, gate, mux));
+
+
+	/* Dividing clocks, no mux */
+	div = k210_clk_comp_div(&sysctl->clk_thr[0], 0, 4);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_cent, 1);
+	clk_dm(K210_CLK_SRAM0, k210_clk_comp_nomux("sram0", "aclk", div, gate));
+
+	div = k210_clk_comp_div( &sysctl->clk_thr[0], 4, 4);
+	gate = k210_clk_comp_gate( &sysctl->clk_en_cent, 2);
+	clk_dm(K210_CLK_SRAM1, k210_clk_comp_nomux("sram1", "aclk", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[0], 16, 4);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 0);
+	clk_dm(K210_CLK_ROM, k210_clk_comp_nomux("rom", "aclk", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[0], 12, 4);
+	gate = k210_clk_comp_gate(&sysctl->clk_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(&sysctl->clk_sel[0], 3, 3);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_cent, 3);
+	clk_dm(K210_CLK_APB0, k210_clk_comp_nomux("apb0", "aclk", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_sel[0], 6, 3);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_cent, 4);
+	clk_dm(K210_CLK_APB1, k210_clk_comp_nomux("apb1", "aclk", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_sel[0], 9, 3);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_cent, 5);
+	clk_dm(K210_CLK_APB1, k210_clk_comp_nomux("apb2", "aclk", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[0], 8, 4);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 2);
+	clk_dm(K210_CLK_APB1, k210_clk_comp_nomux("ai", "pll1", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[3], 0, 16);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 10);
+	clk_dm(K210_CLK_I2S0,
+	       k210_clk_comp_nomux("i2s0", "pll2_half", div, gate));
+	
+	div = k210_clk_comp_div(&sysctl->clk_thr[3], 16, 16);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 11);
+	clk_dm(K210_CLK_I2S1,
+	       k210_clk_comp_nomux("i2s1", "pll2_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[4], 0, 16);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 12);
+	clk_dm(K210_CLK_I2S2,
+	       k210_clk_comp_nomux("i2s2", "pll2_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[6], 0, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 24);
+	clk_dm(K210_CLK_WDT0,
+	       k210_clk_comp_nomux("wdt0", "in0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[6], 8, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 25);
+	clk_dm(K210_CLK_WDT1,
+	       k210_clk_comp_nomux("wdt1", "in0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[1], 0, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 6);
+	clk_dm(K210_CLK_SPI0,
+	       k210_clk_comp_nomux("spi0", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[1], 8, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 7);
+	clk_dm(K210_CLK_SPI1,
+	       k210_clk_comp_nomux("spi1", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[1], 16, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 8);
+	clk_dm(K210_CLK_SPI2,
+	       k210_clk_comp_nomux("spi2", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[5], 8, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 13);
+	clk_dm(K210_CLK_SPI2,
+	       k210_clk_comp_nomux("i2c0", "pll0_half", div, gate));
+	
+	div = k210_clk_comp_div(&sysctl->clk_thr[5], 16, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 14);
+	clk_dm(K210_CLK_SPI2,
+	       k210_clk_comp_nomux("i2c1", "pll0_half", div, gate));
+
+	div = k210_clk_comp_div(&sysctl->clk_thr[5], 24, 8);
+	gate = k210_clk_comp_gate(&sysctl->clk_en_peri, 15);
+	clk_dm(K210_CLK_SPI2,
+	       k210_clk_comp_nomux("i2c2", "pll0_half", div, gate));
+
+	/* Gated clocks */
+	clk_dm(K210_CLK_CPU,
+	       k210_clk_gate("cpu", "aclk", &sysctl->clk_en_cent, 0));
+	clk_dm(K210_CLK_DMA,
+	       k210_clk_gate("dma", "aclk", &sysctl->clk_en_peri, 1));
+	clk_dm(K210_CLK_FFT,
+	       k210_clk_gate("fft", "aclk", &sysctl->clk_en_peri, 4));
+	clk_dm(K210_CLK_GPIO,
+	       k210_clk_gate("gpio", "apb0", &sysctl->clk_en_peri, 5));
+	clk_dm(K210_CLK_UART1,
+	       k210_clk_gate("uart1", "apb0", &sysctl->clk_en_peri, 16));
+	clk_dm(K210_CLK_UART2,
+	       k210_clk_gate("uart2", "apb0", &sysctl->clk_en_peri, 17));
+	clk_dm(K210_CLK_UART3,
+	       k210_clk_gate("uart3", "apb0", &sysctl->clk_en_peri, 18));
+	clk_dm(K210_CLK_FPIOA,
+	       k210_clk_gate("fpioa", "apb0", &sysctl->clk_en_peri, 20));
+	clk_dm(K210_CLK_SHA,
+	       k210_clk_gate("sha", "apb0", &sysctl->clk_en_peri, 26));
+	clk_dm(K210_CLK_AES,
+	       k210_clk_gate("aes", "apb1", &sysctl->clk_en_peri, 19));
+	clk_dm(K210_CLK_OTP,
+	       k210_clk_gate("otp", "apb1", &sysctl->clk_en_peri, 27));
+	clk_dm(K210_CLK_RTC,
+	       k210_clk_gate("rtc", in0, &sysctl->clk_en_peri, 29));
+
+cleanup_sysctl:
+	unmap_sysmem(sysctl);
+	return err;
+}
+
+static const struct udevice_id k210_clk_ids[] = {
+	{ .compatible = "kendryte,k210-clk" },
+	{ },
+};
+
+U_BOOT_DRIVER(k210_clk) = {
+	.name = "clk_k210",
+	.id = UCLASS_CLK,
+	.of_match = k210_clk_ids,
+	.ops = &k210_clk_ops,
+	.probe = k210_clk_probe,
+	.flags = DM_FLAG_PRE_RELOC,
+};
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 */
-- 
2.24.1

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

* [PATCH 11/11] riscv: Add option to disable writes to mcounteren
  2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
                   ` (9 preceding siblings ...)
  2019-12-31 22:50 ` [PATCH 10/11] riscv: Add K210 clock support Sean Anderson
@ 2019-12-31 22:51 ` Sean Anderson
  10 siblings, 0 replies; 13+ messages in thread
From: Sean Anderson @ 2019-12-31 22:51 UTC (permalink / raw)
  To: u-boot

On the kendryte k210, writes to mcounteren result in an illegal instruction
exception.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---
 arch/riscv/cpu/cpu.c            | 2 ++
 board/sipeed/maix/Kconfig       | 1 +
 configs/sipeed_maix_bitm_config | 1 +
 3 files changed, 4 insertions(+)

diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index e457f6acbf..df9eae663c 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -89,7 +89,9 @@ int arch_cpu_init_dm(void)
 		 * Enable perf counters for cycle, time,
 		 * and instret counters only
 		 */
+#ifndef CONFIG_SYS_RISCV_NOCOUNTER
 		csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
+#endif

 		/* Disable paging */
 		if (supports_extension('s'))
diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig
index 6a25086ef4..c456c47fb2 100644
--- a/board/sipeed/maix/Kconfig
+++ b/board/sipeed/maix/Kconfig
@@ -37,6 +37,7 @@ config BOARD_SPECIFIC_OPTIONS
 	select SIFIVE_SERIAL
 	select ARCH_DEFAULT_RV64I
 	select ENV_IS_NOWHERE
+	select SYS_RISCV_NOCOUNTER
 	imply SIFIVE_CLINT
 	imply K210_SYSCTL
 	imply CLK_K210
diff --git a/configs/sipeed_maix_bitm_config b/configs/sipeed_maix_bitm_config
index 0088748ae0..73075e3016 100644
--- a/configs/sipeed_maix_bitm_config
+++ b/configs/sipeed_maix_bitm_config
@@ -30,6 +30,7 @@ CONFIG_RISCV_ISA_A=y
 CONFIG_SIFIVE_CLINT=y
 CONFIG_K210_SYSCTL=y
 CONFIG_SHOW_REGS=y
+CONFIG_SYS_RISCV_NOCOUNTER=y
 CONFIG_STACK_SIZE_SHIFT=14
 CONFIG_LOCALVERSION=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-- 
2.24.1

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

* [PATCH 01/11] clk: Always use the supplied struct clk
  2019-12-31 22:42 ` [PATCH 01/11] clk: Always use the supplied struct clk Sean Anderson
@ 2020-01-02  5:01   ` Jagan Teki
  0 siblings, 0 replies; 13+ messages in thread
From: Jagan Teki @ 2020-01-02  5:01 UTC (permalink / raw)
  To: u-boot

+ Lukasz

On Wed, Jan 1, 2020 at 4:12 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> 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>
> ---

Acked-by: Jagan Teki <jagan@amarulasolutions.com>

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

end of thread, other threads:[~2020-01-02  5:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-31 22:39 [PATCH 00/11] riscv: Add Sipeed Maix support Sean Anderson
2019-12-31 22:42 ` [PATCH 01/11] clk: Always use the supplied struct clk Sean Anderson
2020-01-02  5:01   ` Jagan Teki
2019-12-31 22:43 ` [PATCH 02/11] clk: Check that ops of composite clock components exist, before calling Sean Anderson
2019-12-31 22:44 ` [PATCH 03/11] riscv: Add headers for asm/global_data.h Sean Anderson
2019-12-31 22:45 ` [PATCH 04/11] riscv: Add an option to default to RV64I Sean Anderson
2019-12-31 22:46 ` [PATCH 05/11] riscv: Enable SiFive UART support pre-relocation Sean Anderson
2019-12-31 22:47 ` [PATCH 06/11] riscv: Add initial Sipeed Maix support Sean Anderson
2019-12-31 22:48 ` [PATCH 07/11] riscv: Add device tree for K210 Sean Anderson
2019-12-31 22:49 ` [PATCH 08/11] riscv: Add K210 sysctl support Sean Anderson
2019-12-31 22:50 ` [PATCH 09/11] riscv: Add K210 pll support Sean Anderson
2019-12-31 22:50 ` [PATCH 10/11] riscv: Add K210 clock support Sean Anderson
2019-12-31 22:51 ` [PATCH 11/11] riscv: Add option to disable writes to mcounteren 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.