Linux-RISC-V Archive on lore.kernel.org
 help / color / Atom feed
From: Sean Anderson <seanga2@gmail.com>
To: linux-riscv@lists.infradead.org
Subject: Re: [PATCH 06/10] riscv: Add Kendryte K210 SoC support
Date: Fri, 14 Feb 2020 15:31:18 -0500
Message-ID: <b84a50f2-5998-9a7c-83d2-4b837059970a@gmail.com> (raw)
In-Reply-To: <20200212103432.660256-7-damien.lemoal@wdc.com>

Hi Damien/Chistopher,

I'm working on adding k210 support to U-Boot [1], so I'm interested in
how you've tackled these problems. Hopefully, we can keep the
implementations broadly similar, to make it easier to correct bugs in
the future. In part

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

On 2/12/20 5:34 AM, Damien Le Moal wrote:
> From: Christoph Hellwig <hch@lst.de>
> 
> Add support for the Kendryte K210 RISC-V SoC. For now, this support
> only provides a simple sysctl driver allowing to setup the CPU and
> uart clock. This support is enabled through the new Kconfig option
> SOC_KENDRYTE and defines the config option CONFIG_K210_SYSCTL
> to enable the K210 SoC sysctl driver compilation.
> 
> The sysctl driver also registers an early SoC initialization function
> allowing enabling the general purpose use of the 2MB of SRAM normally
> reserved for the SoC AI engine. This initialization function is
> automatically called before the dt early initialization using the flat
> dt root node compatible property matching the value "kendryte,k210".
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs            |   6 +
>  drivers/soc/Kconfig                |   1 +
>  drivers/soc/Makefile               |   1 +
>  drivers/soc/kendryte/Kconfig       |  14 ++
>  drivers/soc/kendryte/Makefile      |   3 +
>  drivers/soc/kendryte/k210-sysctl.c | 245 +++++++++++++++++++++++++++++
>  6 files changed, 270 insertions(+)
>  create mode 100644 drivers/soc/kendryte/Kconfig
>  create mode 100644 drivers/soc/kendryte/Makefile
>  create mode 100644 drivers/soc/kendryte/k210-sysctl.c
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index d325b67d00df..4d5d4a65b2a2 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -10,4 +10,10 @@ config SOC_SIFIVE
>  	help
>  	  This enables support for SiFive SoC platform hardware.
>  
> +config SOC_KENDRYTE
> +	bool "Kendryte K210 SoC"
> +	depends on !MMU
> +	help
> +	  This enables support for Kendryte K210 SoC hardware.
> +
>  endmenu
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index 1778f8c62861..425ab6f7e375 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -22,5 +22,6 @@ source "drivers/soc/ux500/Kconfig"
>  source "drivers/soc/versatile/Kconfig"
>  source "drivers/soc/xilinx/Kconfig"
>  source "drivers/soc/zte/Kconfig"
> +source "drivers/soc/kendryte/Kconfig"
>  
>  endmenu
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 8b49d782a1ab..af58063bb989 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -28,3 +28,4 @@ obj-$(CONFIG_ARCH_U8500)	+= ux500/
>  obj-$(CONFIG_PLAT_VERSATILE)	+= versatile/
>  obj-y				+= xilinx/
>  obj-$(CONFIG_ARCH_ZX)		+= zte/
> +obj-$(CONFIG_SOC_KENDRYTE)	+= kendryte/
> diff --git a/drivers/soc/kendryte/Kconfig b/drivers/soc/kendryte/Kconfig
> new file mode 100644
> index 000000000000..49785b1b0217
> --- /dev/null
> +++ b/drivers/soc/kendryte/Kconfig
> @@ -0,0 +1,14 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +if SOC_KENDRYTE
> +
> +config K210_SYSCTL
> +	bool "Kendryte K210 system controller"
> +	default y
> +	depends on RISCV
> +	help
> +	  Enables controlling the K210 various clocks and to enable
> +	  general purpose use of the extra 2MB of SRAM normally
> +	  reserved for the AI engine.
> +
> +endif
> diff --git a/drivers/soc/kendryte/Makefile b/drivers/soc/kendryte/Makefile
> new file mode 100644
> index 000000000000..002d9ce95c0d
> --- /dev/null
> +++ b/drivers/soc/kendryte/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_K210_SYSCTL)	+= k210-sysctl.o
> diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
> new file mode 100644
> index 000000000000..7d4ecd954af0
> --- /dev/null
> +++ b/drivers/soc/kendryte/k210-sysctl.c
> @@ -0,0 +1,245 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Christoph Hellwig.
> + * Copyright (c) 2019 Western Digital Corporation or its affiliates.
> + */
> +#include <linux/types.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <asm/soc.h>
> +
> +#define K210_SYSCTL_CLK0_FREQ		26000000UL
> +
> +/* Registers base address */
> +#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
> +
> +/* Registers */
> +#define K210_SYSCTL_PLL0		0x08
> +#define K210_SYSCTL_PLL1		0x0c
> +/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
> +#define   PLL_RESET		(1 << 20)
> +#define   PLL_PWR		(1 << 21)
> +#define   PLL_INTFB		(1 << 22)
> +#define   PLL_BYPASS		(1 << 23)
> +#define   PLL_TEST		(1 << 24)
> +#define   PLL_OUT_EN		(1 << 25)
> +#define   PLL_TEST_EN		(1 << 26)
> +#define K210_SYSCTL_PLL_LOCK		0x18
> +#define   PLL0_LOCK1		(1 << 0)
> +#define   PLL0_LOCK2		(1 << 1)
> +#define   PLL0_SLIP_CLEAR	(1 << 2)
> +#define   PLL0_TEST_CLK_OUT	(1 << 3)
> +#define   PLL1_LOCK1		(1 << 8)
> +#define   PLL1_LOCK2		(1 << 9)
> +#define   PLL1_SLIP_CLEAR	(1 << 10)
> +#define   PLL1_TEST_CLK_OUT	(1 << 11)
> +#define   PLL2_LOCK1		(1 << 16)
> +#define   PLL2_LOCK2		(1 << 16)
> +#define   PLL2_SLIP_CLEAR	(1 << 18)
> +#define   PLL2_TEST_CLK_OUT	(1 << 19)
> +#define K210_SYSCTL_CLKSEL0	0x20
> +#define   CLKSEL_ACLK		(1 << 0)
> +#define K210_SYSCTL_CLKEN_CENT		0x28
> +#define   CLKEN_CPU		(1 << 0)
> +#define   CLKEN_SRAM0		(1 << 1)
> +#define   CLKEN_SRAM1		(1 << 2)
> +#define   CLKEN_APB0		(1 << 3)
> +#define   CLKEN_APB1		(1 << 4)
> +#define   CLKEN_APB2		(1 << 5)
> +#define K210_SYSCTL_CLKEN_PERI		0x2c
> +#define   CLKEN_ROM		(1 << 0)
> +#define   CLKEN_DMA		(1 << 1)
> +#define   CLKEN_AI		(1 << 2)
> +#define   CLKEN_DVP		(1 << 3)
> +#define   CLKEN_FFT		(1 << 4)
> +#define   CLKEN_GPIO		(1 << 5)
> +#define   CLKEN_SPI0		(1 << 6)
> +#define   CLKEN_SPI1		(1 << 7)
> +#define   CLKEN_SPI2		(1 << 8)
> +#define   CLKEN_SPI3		(1 << 9)
> +#define   CLKEN_I2S0		(1 << 10)
> +#define   CLKEN_I2S1		(1 << 11)
> +#define   CLKEN_I2S2		(1 << 12)
> +#define   CLKEN_I2C0		(1 << 13)
> +#define   CLKEN_I2C1		(1 << 14)
> +#define   CLKEN_I2C2		(1 << 15)
> +#define   CLKEN_UART1		(1 << 16)
> +#define   CLKEN_UART2		(1 << 17)
> +#define   CLKEN_UART3		(1 << 18)
> +#define   CLKEN_AES		(1 << 19)
> +#define   CLKEN_FPIO		(1 << 20)
> +#define   CLKEN_TIMER0		(1 << 21)
> +#define   CLKEN_TIMER1		(1 << 22)
> +#define   CLKEN_TIMER2		(1 << 23)
> +#define   CLKEN_WDT0		(1 << 24)
> +#define   CLKEN_WDT1		(1 << 25)
> +#define   CLKEN_SHA		(1 << 26)
> +#define   CLKEN_OTP		(1 << 27)
> +#define   CLKEN_RTC		(1 << 29)
> +
> +struct k210_sysctl {
> +	void __iomem		*regs;
> +	struct clk_hw		hw;
> +};
> +
> +static void k210_set_bits(u32 val, void __iomem *reg)
> +{
> +	writel(readl(reg) | val, reg);
> +}
> +
> +static void k210_clear_bits(u32 val, void __iomem *reg)
> +{
> +	writel(readl(reg) & ~val, reg);
> +}
> +
> +static void k210_pll1_enable(void __iomem *regs)
> +{
> +	u32 val;
> +
> +	val = readl(regs + K210_SYSCTL_PLL1);
> +	val &= ~0xfffff;
> +	val |= (59 << 4) | (3 << 10) | (59 << 15);

Can this be done with symbolic constants? Additionally, I believe bwadj
needs to be set to the value you use for f (at least when using internal
feedback). There is a datasheet floating around under the name
"TCITSMCN40GGPMPLLA1_guide" which has more information about the PLL's
internals.

> +	writel(val, regs + K210_SYSCTL_PLL1);
> +
> +	k210_clear_bits(PLL_BYPASS, regs + K210_SYSCTL_PLL1);
> +	k210_set_bits(PLL_PWR, regs + K210_SYSCTL_PLL1);
> +
> +	/*
> +	 * Reset the pll. The magic NOPs come from the Kendryte reference SDK.
> +	 */
> +	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> +	k210_set_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> +	nop();
> +	nop();
> +	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> +
> +	for (;;) {
> +		val = readl(regs + K210_SYSCTL_PLL_LOCK);
> +		if (val & PLL1_LOCK2)
> +			break;
> +		writel(val | PLL1_SLIP_CLEAR, regs + K210_SYSCTL_PLL_LOCK);
> +	}
> +
> +	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL1);
> +}
> +
> +static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw,
> +		unsigned long parent_rate)
> +{
> +	struct k210_sysctl *s = container_of(hw, struct k210_sysctl, hw);
> +	u32 clksel0, pll0;
> +	u64 pll0_freq, clkr0, clkf0, clkod0;
> +
> +	/*
> +	 * If the clock selector is not set, use the base frequency.
> +	 * Otherwise, use PLL0 frequency with a frequency divisor.
> +	 */
> +	clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0);
> +	if (!(clksel0 & CLKSEL_ACLK))
> +		return K210_SYSCTL_CLK0_FREQ;
> +
> +	/*
> +	 * Get PLL0 frequency:
> +	 * freq = base frequency * clkf0 / (clkr0 * clkod0)
> +	 */
> +	pll0 = readl(s->regs + K210_SYSCTL_PLL0);
> +	clkr0 = 1 + (pll0 & 0x0000000f);
> +	clkf0 = 1 + ((pll0 & 0x000003f0) >> 4);
> +	clkod0 = 1 + ((pll0 & 0x00003c00) >> 10);

Can you do this with FIELD_GET and GENMASK instead?

> +	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
> +
> +	/* Get the frequency divisor from the clock selector */
> +	return pll0_freq / (2ULL << ((clksel0 & 0x00000006) >> 1));

Same thing here.

> +}
> +
> +static const struct clk_ops k210_sysctl_clk_ops = {
> +	.recalc_rate	= k210_sysctl_clk_recalc_rate,
> +};
> +
> +static const struct clk_init_data k210_clk_init_data = {
> +	.name		= "k210-sysctl-pll1",
> +	.ops		= &k210_sysctl_clk_ops,
> +};
> +
> +static int k210_sysctl_probe(struct platform_device *pdev)
> +{
> +	struct k210_sysctl *s;
> +	int error;
> +
> +	pr_info("Kendryte K210 SoC sysctl\n");
> +
> +	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
> +	if (!s)
> +		return -ENOMEM;
> +
> +	s->regs = devm_ioremap_resource(&pdev->dev,
> +			platform_get_resource(pdev, IORESOURCE_MEM, 0));
> +	if (IS_ERR(s->regs))
> +		return PTR_ERR(s->regs);
> +
> +	s->hw.init = &k210_clk_init_data;
> +	error = devm_clk_hw_register(&pdev->dev, &s->hw);
> +	if (error) {
> +		dev_err(&pdev->dev, "failed to register clk");
> +		return error;
> +	}
> +
> +	error = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
> +					    &s->hw);
> +	if (error) {
> +		dev_err(&pdev->dev, "adding clk provider failed\n");
> +		return error;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id k210_sysctl_of_match[] = {
> +	{ .compatible = "kendryte,k210-sysctl", },
> +	{}
> +};
> +
> +static struct platform_driver k210_sysctl_driver = {
> +	.driver	= {
> +		.name		= "k210-sysctl",
> +		.of_match_table	= k210_sysctl_of_match,
> +	},
> +	.probe			= k210_sysctl_probe,
> +};
> +
> +static int __init k210_sysctl_init(void)
> +{
> +	return platform_driver_register(&k210_sysctl_driver);
> +}
> +core_initcall(k210_sysctl_init);
> +
> +/*
> + * This needs to be called very early during initialization, given that
> + * PLL1 needs to be enabled to be able to use all SRAM.
> + */
> +static void __init k210_soc_early_init(const void *fdt)
> +{
> +	void __iomem *regs;
> +
> +	regs = ioremap(K210_SYSCTL_SYSCTL_BASE_ADDR, 0x1000);
> +	if (!regs)
> +		panic("K210 sysctl ioremap");
> +
> +	/* Enable PLL1 to make the KPU SRAM useable */
> +	k210_pll1_enable(regs);
> +
> +	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0);
> +
> +	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
> +		      regs + K210_SYSCTL_CLKEN_CENT);
> +	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
> +		      regs + K210_SYSCTL_CLKEN_PERI);
> +
> +	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0);
> +
> +	iounmap(regs);
> +}
> +SOC_EARLY_INIT_DECLARE("kendryte,k210", k210_soc_early_init);

--Sean


  reply index

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-12 10:34 [PATCH 00/10] Kendryte k210 SoC boards support Damien Le Moal
2020-02-12 10:34 ` [PATCH 01/10] riscv: Fix gitignore Damien Le Moal
2020-02-20  0:15   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 02/10] riscv: Force flat memory model with no-mmu Damien Le Moal
2020-02-14 20:18   ` Sean Anderson
2020-02-15  2:15     ` Damien Le Moal
2020-02-15  2:26       ` Sean Anderson
2020-02-15  2:40         ` Damien Le Moal
2020-03-02  3:48   ` Anup Patel
2020-03-04 18:38   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 03/10] riscv: Unaligned load/store handling for M_MODE Damien Le Moal
2020-03-02  3:57   ` Anup Patel
2020-03-04 19:28   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 04/10] riscv: Add BUILTIN_DTB support Damien Le Moal
2020-03-02  3:58   ` Anup Patel
2020-03-04 19:28   ` Palmer Dabbelt
2020-03-05  4:58     ` Anup Patel
2020-03-05  5:14       ` Damien Le Moal
2020-03-05  5:37         ` Anup Patel
2020-03-05  6:13           ` Damien Le Moal
2020-03-08  6:10             ` Anup Patel
2020-03-05  8:18         ` Atish Patra
2020-03-07  0:02           ` Sean Anderson
2020-03-07  1:51             ` Atish Patra
2020-03-07  2:08               ` Sean Anderson
2020-03-06 23:56         ` Sean Anderson
2020-02-12 10:34 ` [PATCH 05/10] riscv: Add SOC early init support Damien Le Moal
2020-03-04 19:28   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 06/10] riscv: Add Kendryte K210 SoC support Damien Le Moal
2020-02-14 20:31   ` Sean Anderson [this message]
2020-03-04 19:38   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 07/10] riscv: Select required drivers for Kendryte SOC Damien Le Moal
2020-03-02  3:59   ` Anup Patel
2020-03-04 19:44   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 08/10] riscv: Add Kendryte K210 device tree Damien Le Moal
2020-02-14 20:51   ` Sean Anderson
2020-02-15  2:34     ` Damien Le Moal
2020-02-15  2:48       ` Sean Anderson
2020-02-15  3:00         ` Damien Le Moal
2020-02-18 14:12           ` Carlos Eduardo de Paula
2020-02-18 14:18             ` Sean Anderson
2020-02-18 14:30               ` Carlos Eduardo de Paula
2020-02-18 17:48                 ` Sean Anderson
2020-02-18 19:26                   ` Carlos Eduardo de Paula
2020-02-19  9:06                     ` Wladimir J. van der Laan
2020-02-19 22:28                       ` Sean Anderson
2020-02-20 10:48                         ` Wladimir J. van der Laan
2020-02-22 19:07                       ` Wladimir J. van der Laan
2020-04-01 17:55                         ` Drew Fustini
2020-04-02  2:24                           ` Damien Le Moal
2020-02-19  8:50                   ` Wladimir J. van der Laan
2020-02-27 19:43       ` Sean Anderson
2020-03-02  4:06   ` Anup Patel
2020-03-02  4:15     ` Damien Le Moal
2020-03-02  4:22       ` Anup Patel
2020-03-02  4:51         ` Damien Le Moal
2020-03-02  5:05           ` Anup Patel
2020-03-02  5:08             ` Damien Le Moal
2020-03-07  0:18               ` Sean Anderson
2020-03-07  4:11                 ` Anup Patel
2020-03-04 19:44   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 09/10] riscv: Kendryte K210 default config Damien Le Moal
2020-03-02  4:07   ` Anup Patel
2020-03-04 19:44   ` Palmer Dabbelt
2020-02-12 10:34 ` [PATCH 10/10] riscv: create a loader.bin for the kendryte kflash.py tool Damien Le Moal
2020-03-02  4:08   ` Anup Patel
2020-03-04 19:44   ` Palmer Dabbelt
2020-02-14 15:05 ` [PATCH 00/10] Kendryte k210 SoC boards support Carlos Eduardo de Paula
2020-02-15  2:02   ` Damien Le Moal
2020-02-17 13:28     ` Carlos Eduardo de Paula
2020-02-26 21:31       ` Carlos Eduardo de Paula
2020-02-27  2:18         ` Damien Le Moal
2020-02-28 20:32 ` Sean Anderson
2020-03-02  3:01   ` Damien Le Moal
2020-03-02  3:53     ` Sean Anderson
2020-03-02  4:11       ` Damien Le Moal
2020-03-02  4:18         ` Sean Anderson
2020-03-02  4:54           ` Damien Le Moal
2020-03-02  4:56             ` Sean Anderson
2020-03-02  5:03               ` Damien Le Moal
2020-03-02  4:17       ` Anup Patel
2020-03-02  4:21         ` Sean Anderson
2020-03-02  4:48         ` Damien Le Moal
2020-03-02  4:51           ` Damien Le Moal
2020-03-02  5:02           ` Sean Anderson
2020-03-02  5:11             ` Damien Le Moal
2020-03-02  5:25               ` Sean Anderson
2020-03-02  5:43                 ` Damien Le Moal
2020-03-04 19:44 ` Palmer Dabbelt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b84a50f2-5998-9a7c-83d2-4b837059970a@gmail.com \
    --to=seanga2@gmail.com \
    --cc=linux-riscv@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-RISC-V Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-riscv/0 linux-riscv/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-riscv linux-riscv/ https://lore.kernel.org/linux-riscv \
		linux-riscv@lists.infradead.org
	public-inbox-index linux-riscv

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-riscv


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git