From: Sean Anderson <seanga2@gmail.com>
To: Damien Le Moal <damien.lemoal@wdc.com>,
linux-riscv@lists.infradead.org,
Palmer Dabbelt <palmer@dabbelt.com>
Cc: Anup Patel <Anup.Patel@wdc.com>
Subject: Re: [PATCH v2 4/9] riscv: Add Kendryte K210 SoC support
Date: Thu, 12 Mar 2020 14:19:19 -0400 [thread overview]
Message-ID: <ad9c6b53-0c41-aeaa-d772-af9be6787257@gmail.com> (raw)
In-Reply-To: <20200312051107.1454880-5-damien.lemoal@wdc.com>
On 3/12/20 1:11 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>
> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.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 3078b2de0b2d..69071578e181 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -34,4 +34,10 @@ config SOC_VIRT
> help
> This enables support for QEMU Virt Machine.
>
> +config SOC_KENDRYTE
> + bool "Kendryte K210 SoC"
> + depends on !MMU
> + help
> + This enables support for Kendryte K210 SoC platform 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)
I think the preferred style is to use BIT(20), etc.
> +#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
Can you use GENMASK here?
> +#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);
Again, can this be done with GENMASK and FIELD_PREP?
> + 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);
Same thing here, use FIELD_GET instead please.
> + pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
> +
> + /* Get the frequency divisor from the clock selector */
> + return pll0_freq / (2ULL << ((clksel0 & 0x00000006) >> 1));
> +}
> +
> +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
next prev parent reply other threads:[~2020-03-12 18:19 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-12 5:10 [PATCH v2 0/9] Kendryte k210 SoC boards support Damien Le Moal
2020-03-12 5:10 ` [PATCH v2 1/9] riscv: Unaligned load/store handling for M_MODE Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 2/9] riscv: Add BUILTIN_DTB support Damien Le Moal
2020-03-12 20:03 ` Atish Patra
2020-03-12 5:11 ` [PATCH v2 3/9] riscv: Add SOC early init support Damien Le Moal
2020-03-12 18:21 ` Sean Anderson
2020-03-13 5:52 ` Damien Le Moal
2020-03-12 19:50 ` Atish Patra
2020-03-12 20:53 ` Atish Patra
2020-03-13 6:42 ` Damien Le Moal
2020-03-13 21:10 ` Atish Patra
2020-03-16 0:34 ` Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 4/9] riscv: Add Kendryte K210 SoC support Damien Le Moal
2020-03-12 18:19 ` Sean Anderson [this message]
2020-03-13 5:43 ` Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 5/9] riscv: Select required drivers for Kendryte SOC Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 6/9] riscv: Add Kendryte K210 device tree Damien Le Moal
2020-03-12 18:16 ` Sean Anderson
2020-03-13 5:29 ` Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 7/9] riscv: Kendryte K210 default config Damien Le Moal
2020-03-12 19:03 ` Atish Patra
2020-03-13 5:52 ` Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 8/9] riscv: create a loader.bin boot image for Kendryte SoC Damien Le Moal
2020-03-12 5:11 ` [PATCH v2 9/9] riscv: Do not initialize PMP on " Damien Le Moal
2020-03-12 15:20 ` Sean Anderson
2020-03-12 18:10 ` Atish Patra
2020-03-12 18:14 ` Sean Anderson
2020-03-12 18:29 ` Atish Patra
2020-03-12 18:49 ` Sean Anderson
2020-03-12 19:12 ` Atish Patra
2020-03-12 20:09 ` Sean Anderson
2020-03-13 6:03 ` Damien Le Moal
2020-03-13 5:40 ` Anup Patel
2020-03-13 5:25 ` Damien Le Moal
2020-03-13 5:47 ` Atish Patra
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=ad9c6b53-0c41-aeaa-d772-af9be6787257@gmail.com \
--to=seanga2@gmail.com \
--cc=Anup.Patel@wdc.com \
--cc=damien.lemoal@wdc.com \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox