All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 00/10] RISC-V Kendryte K210 support improvements
@ 2021-01-12  0:58 Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 01/10] clk: Add RISC-V Canaan Kendryte K210 clock driver Damien Le Moal
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

This series of patches improves support for boards based on the Canaan
Kendryte K210 RISC-V dual core SoC. Minimal support for this SoC is
already included in the kernel. These patches complete it, enabling
support for most peripherals present on the SoC as well as introducing
device trees for the various K210 boards available on the market today
from SiPeed and Kendryte.

The patches here are the remaining patches of the series not applied
yet. Patch 1 adds the SoC clock driver and patch 2 adds the pinctrl
driver.

Patches 3 to 8 update the existing K210 device tree and add new
device tree files for several K210 based boards: MAIX Bit, MAIXDUINO,
MAIX Dock and MAIX Go boards from SiPeed and the KD233 development
board from Canaan.

Finally the last two patches updates the k210 nommu defconfig to include
the newly implemented drivers and provide a new default configuration
file enabling SD card support.

A lot of the work on the device tree and on the K210 drivers come from
the work by Sean Anderson for the U-Boot project support of the K210
SoC. Sean also helped with debugging many aspects of this series.

A tree with all patches applied is available here:
https://github.com/damien-lemoal/linux, k210-sysctl-v24 branch.
A demonstration of this series used on a SiPeed MAIX Dock
board together with an I2C servo controller can be seen here:
https://damien-lemoal.github.io/linux-robot-arm/#example

This tree was used to build userspace busybox environment image that is
then copied onto an SD card formatted with ext2:
https://github.com/damien-lemoal/buildroot
Of note is that running this userspace environment requires a revert of
commit 2217b982624680d19a80ebb4600d05c8586c4f96 introduced during the
5.9 development cycle. Without this revert, execution of the init
process fails. A problem with the riscv port of elf2flt is suspected but
not confirmed. I am now starting to investigate this problem.

Reviews and comments are as always much welcome.

Changes from v10:
* Rebased on riscv tree fixes+for-next branches. Patches already applied
  to these branches were removed from this series.
* Fixed the clock driver and pinctrl driver patch titles to indicate the
  correct target sub-components.
* Applied reviewed-by tags from Anup.

Changes from v9:
* Added patch 6 to avoid DTS compilation errors after patch 9 is
  applied and until patch 16 is applied.

Changes from v8:
* Addressed Rob's comments on the sysctl driver bindings documentation
* Fixed a typo in the fpios driver bindings documentation

Changes from v7:
* Removed the __init annotation for the drivers reset, pinctrl and
  sysctl drivers probe functions as suggested by Geert. Also removed
  the __refdata annotation for the struct platform_driver variables of
  these drivers.

Changes from v6:
* Annotate struct platform_driver variables with __refdata to avoid
  section mismatch compilation errors
* Add empty sentinel entry to of_device_id tables of the sysctl, reset
  and pinctrl drivers.

Changes from v5:
* Addressed Philipp's comment on the reset controller driver
* Added patch 6 to reduce the size of the clock driver patch
  (now patch 12).

Changes from v4:
* Simplified reset controller driver using of_xlate callback as
  suggested by Philipp
* Fixed compilation error when using other configs than one of the
  nommu_k210 defconfigs.
* Addressed most clock driver comments from Stephen.
* Removed CONFIG_GPIO_SYSFS from defconfigs
* Rebased on 5.10-rc7

Changes from V3:
* Add one entry per driver in MAINTAINERS file

Changes from V2:
* Add MAINTAINERS file entry for the SoC support, listing myself as
  maintainer.
* Removed use of postcore_initcall() for declaring the drivers, using
  the regular builtin_platform_driver() instead.
* Fixed fpio pinctrl driver bindings documentation as commented by
  Geert: removed input-schmitt and added input-schmitt-disable, fixed
  typo and added input-disable and output-disable.
* Fixed device tree to have cs-gpios active low, as per the default, as
  active high necessity was an artifact of the gpio level double
  inversion bug fixed recently.
* Removed CONFIG_VT from defconfigs to reduce the kernel image size as
  suggested by Geert.

Changes from v1:
* Improved DT bindings documentation
* SPI and GPIO patches removed from this series (and being processed
  directly through the relevant subsystems directly)
* Improved device trees
* Various cleanup and improvments of the drivers

Damien Le Moal (10):
  clk: Add RISC-V Canaan Kendryte K210 clock driver
  pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
  riscv: Update Canaan Kendryte K210 device tree
  riscv: Add SiPeed MAIX BiT board device tree
  riscv: Add SiPeed MAIX DOCK board device tree
  riscv: Add SiPeed MAIX GO board device tree
  riscv: Add SiPeed MAIXDUINO board device tree
  riscv: Add Kendryte KD233 board device tree
  riscv: Update Canaan Kendryte K210 defconfig
  riscv: Add Canaan Kendryte K210 SD card defconfig

 MAINTAINERS                                   |    8 +
 arch/riscv/Kconfig.socs                       |    3 +-
 arch/riscv/boot/dts/canaan/canaan_kd233.dts   |  178 +++
 arch/riscv/boot/dts/canaan/k210.dts           |   23 -
 arch/riscv/boot/dts/canaan/k210.dtsi          |  551 ++++++++-
 arch/riscv/boot/dts/canaan/k210_generic.dts   |   46 +
 .../riscv/boot/dts/canaan/sipeed_maix_bit.dts |  227 ++++
 .../boot/dts/canaan/sipeed_maix_dock.dts      |  229 ++++
 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts |  237 ++++
 .../boot/dts/canaan/sipeed_maixduino.dts      |  201 ++++
 arch/riscv/configs/nommu_k210_defconfig       |   44 +-
 .../riscv/configs/nommu_k210_sdcard_defconfig |   92 ++
 drivers/clk/Kconfig                           |    8 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/clk-k210.c                        | 1005 +++++++++++++++++
 drivers/pinctrl/Kconfig                       |   13 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/pinctrl-k210.c                |  985 ++++++++++++++++
 drivers/soc/canaan/Kconfig                    |   18 +-
 drivers/soc/canaan/Makefile                   |    2 +-
 drivers/soc/canaan/k210-sysctl.c              |  205 +---
 include/dt-bindings/clock/k210-clk.h          |    1 -
 include/soc/canaan/k210-sysctl.h              |    2 +
 23 files changed, 3844 insertions(+), 236 deletions(-)
 create mode 100644 arch/riscv/boot/dts/canaan/canaan_kd233.dts
 delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
 create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
 create mode 100644 arch/riscv/configs/nommu_k210_sdcard_defconfig
 create mode 100644 drivers/clk/clk-k210.c
 create mode 100644 drivers/pinctrl/pinctrl-k210.c

Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: linux-clk@vger.kernel.org
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-gpio@vger.kernel.org

-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 01/10] clk: Add RISC-V Canaan Kendryte K210 clock driver
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Damien Le Moal
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add a clock provider driver for the Canaan Kendryte K210 RISC-V SoC.
This new driver with the compatible string "canaan,k210-clk" implements
support for the full clock structure of the K210 SoC. Since it is
required for the correct operation of the SoC, this driver is
selected by default for compilation when the SOC_CANAAN option is
selected.

With this change, the k210-sysctl driver is turned into a simple
platform driver which enables its power bus clock and triggers
populating its child nodes. This driver is also automatically selected
for compilation with the selection of SOC_CANAAN. The sysctl driver
retains the SOC early initialization code, but the implementation now
relies on the new function k210_clk_early_init() provided by the new
clk-k210 driver.

The clock structure implemented and many of the coding ideas for the
driver come from the work by Sean Anderson on the K210 support for the
U-Boot project.

Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: linux-clk@vger.kernel.org
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 MAINTAINERS                      |    1 +
 drivers/clk/Kconfig              |    8 +
 drivers/clk/Makefile             |    1 +
 drivers/clk/clk-k210.c           | 1005 ++++++++++++++++++++++++++++++
 drivers/soc/canaan/Kconfig       |   18 +-
 drivers/soc/canaan/Makefile      |    2 +-
 drivers/soc/canaan/k210-sysctl.c |  205 ++----
 include/soc/canaan/k210-sysctl.h |    2 +
 8 files changed, 1064 insertions(+), 178 deletions(-)
 create mode 100644 drivers/clk/clk-k210.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 380a446d4d4d..637b79eba693 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3872,6 +3872,7 @@ CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER
 M:	Damien Le Moal <damien.lemoal@wdc.com>
 L:	linux-riscv@lists.infradead.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
 F:	drivers/soc/canaan/
 F:	include/soc/canaan/
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 85856cff506c..cb971f6632e2 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -368,6 +368,14 @@ config COMMON_CLK_FIXED_MMIO
 	help
 	  Support for Memory Mapped IO Fixed clocks
 
+config COMMON_CLK_K210
+	bool "Clock driver for the Canaan Kendryte K210 SoC"
+	depends on COMMON_CLK && OF
+	depends on RISCV && SOC_CANAAN
+	default SOC_CANAAN
+	help
+	  Support for the Canaan Kendryte K210 RISC-V SoC clocks.
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index dbdc590e7de3..5f8f9f135df5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_COMMON_CLK_ASPEED)		+= clk-aspeed.o
 obj-$(CONFIG_MACH_ASPEED_G6)		+= clk-ast2600.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)			+= clk-hsdk-pll.o
+obj-$(CONFIG_COMMON_CLK_K210)		+= clk-k210.o
 obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)	+= clk-lochnagar.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
new file mode 100644
index 000000000000..1d528395527c
--- /dev/null
+++ b/drivers/clk/clk-k210.c
@@ -0,0 +1,1005 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ */
+#define pr_fmt(fmt)     "k210-clk: " fmt
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <asm/soc.h>
+#include <soc/canaan/k210-sysctl.h>
+
+#include <dt-bindings/clock/k210-clk.h>
+
+/*
+ * Clocks parameters.
+ */
+struct k210_clk_cfg {
+	const char *name;
+	u8 gate_reg;
+	u8 gate_bit;
+	u8 div_reg;
+	u8 div_shift;
+	u8 div_width;
+	u8 div_type;
+	u8 mux_reg;
+	u8 mux_bit;
+};
+
+enum k210_clk_div_type {
+	K210_DIV_NONE,
+	K210_DIV_ONE_BASED,
+	K210_DIV_DOUBLE_ONE_BASED,
+	K210_DIV_POWER_OF_TWO,
+};
+
+#define K210_GATE(_reg, _bit)	\
+	.gate_reg = (_reg),	\
+	.gate_bit = (_bit)
+#define K210_DIV(_reg, _shift, _width, _type)	\
+	.div_reg = (_reg),			\
+	.div_shift = (_shift),			\
+	.div_width = (_width),			\
+	.div_type = (_type)
+#define K210_MUX(_reg, _bit)	\
+	.mux_reg = (_reg),	\
+	.mux_bit = (_bit)
+
+static struct k210_clk_cfg k210_clks[K210_NUM_CLKS] = {
+
+	/* Gated clocks, no mux, no divider */
+	[K210_CLK_CPU] = {
+		.name = "cpu",
+		K210_GATE(K210_SYSCTL_EN_CENT, 0)
+	},
+	[K210_CLK_DMA] = {
+		.name = "dma",
+		K210_GATE(K210_SYSCTL_EN_PERI, 1)
+	},
+	[K210_CLK_FFT] = {
+		.name = "fft",
+		K210_GATE(K210_SYSCTL_EN_PERI, 4)
+	},
+	[K210_CLK_GPIO] = {
+		.name = "gpio",
+		K210_GATE(K210_SYSCTL_EN_PERI, 5)
+	},
+	[K210_CLK_UART1] = {
+		.name = "uart1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 16)
+	},
+	[K210_CLK_UART2] = {
+		.name = "uart2",
+		K210_GATE(K210_SYSCTL_EN_PERI, 17)
+	},
+	[K210_CLK_UART3] = {
+		.name = "uart3",
+		K210_GATE(K210_SYSCTL_EN_PERI, 18)
+	},
+	[K210_CLK_FPIOA] = {
+		.name = "fpioa",
+		K210_GATE(K210_SYSCTL_EN_PERI, 20)
+	},
+	[K210_CLK_SHA] = {
+		.name = "sha",
+		K210_GATE(K210_SYSCTL_EN_PERI, 26)
+	},
+	[K210_CLK_AES] = {
+		.name = "aes",
+		K210_GATE(K210_SYSCTL_EN_PERI, 19)
+	},
+	[K210_CLK_OTP] = {
+		.name = "otp",
+		K210_GATE(K210_SYSCTL_EN_PERI, 27)
+	},
+	[K210_CLK_RTC] = {
+		.name = "rtc",
+		K210_GATE(K210_SYSCTL_EN_PERI, 29)
+	},
+
+	/* Gated divider clocks */
+	[K210_CLK_SRAM0] = {
+		.name = "sram0",
+		K210_GATE(K210_SYSCTL_EN_CENT, 1),
+		K210_DIV(K210_SYSCTL_THR0, 0, 4, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_SRAM1] = {
+		.name = "sram1",
+		K210_GATE(K210_SYSCTL_EN_CENT, 2),
+		K210_DIV(K210_SYSCTL_THR0, 4, 4, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_ROM] = {
+		.name = "rom",
+		K210_GATE(K210_SYSCTL_EN_PERI, 0),
+		K210_DIV(K210_SYSCTL_THR0, 16, 4, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_DVP] = {
+		.name = "dvp",
+		K210_GATE(K210_SYSCTL_EN_PERI, 3),
+		K210_DIV(K210_SYSCTL_THR0, 12, 4, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_APB0] = {
+		.name = "apb0",
+		K210_GATE(K210_SYSCTL_EN_CENT, 3),
+		K210_DIV(K210_SYSCTL_SEL0, 3, 3, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_APB1] = {
+		.name = "apb1",
+		K210_GATE(K210_SYSCTL_EN_CENT, 4),
+		K210_DIV(K210_SYSCTL_SEL0, 6, 3, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_APB2] = {
+		.name = "apb2",
+		K210_GATE(K210_SYSCTL_EN_CENT, 5),
+		K210_DIV(K210_SYSCTL_SEL0, 9, 3, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_AI] = {
+		.name = "ai",
+		K210_GATE(K210_SYSCTL_EN_PERI, 2),
+		K210_DIV(K210_SYSCTL_THR0, 8, 4, K210_DIV_ONE_BASED)
+	},
+	[K210_CLK_SPI0] = {
+		.name = "spi0",
+		K210_GATE(K210_SYSCTL_EN_PERI, 6),
+		K210_DIV(K210_SYSCTL_THR1, 0, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI1] = {
+		.name = "spi1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 7),
+		K210_DIV(K210_SYSCTL_THR1, 8, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI2] = {
+		.name = "spi2",
+		K210_GATE(K210_SYSCTL_EN_PERI, 8),
+		K210_DIV(K210_SYSCTL_THR1, 16, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C0] = {
+		.name = "i2c0",
+		K210_GATE(K210_SYSCTL_EN_PERI, 13),
+		K210_DIV(K210_SYSCTL_THR5, 8, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C1] = {
+		.name = "i2c1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 14),
+		K210_DIV(K210_SYSCTL_THR5, 16, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C2] = {
+		.name = "i2c2",
+		K210_GATE(K210_SYSCTL_EN_PERI, 15),
+		K210_DIV(K210_SYSCTL_THR5, 24, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT0] = {
+		.name = "wdt0",
+		K210_GATE(K210_SYSCTL_EN_PERI, 24),
+		K210_DIV(K210_SYSCTL_THR6, 0, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT1] = {
+		.name = "wdt1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 25),
+		K210_DIV(K210_SYSCTL_THR6, 8, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S0] = {
+		.name = "i2s0",
+		K210_GATE(K210_SYSCTL_EN_PERI, 10),
+		K210_DIV(K210_SYSCTL_THR3, 0, 16, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1] = {
+		.name = "i2s1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 11),
+		K210_DIV(K210_SYSCTL_THR3, 16, 16, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2] = {
+		.name = "i2s2",
+		K210_GATE(K210_SYSCTL_EN_PERI, 12),
+		K210_DIV(K210_SYSCTL_THR4, 0, 16, K210_DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Divider clocks, no gate, no mux */
+	[K210_CLK_I2S0_M] = {
+		.name = "i2s0_m",
+		K210_DIV(K210_SYSCTL_THR4, 16, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1_M] = {
+		.name = "i2s1_m",
+		K210_DIV(K210_SYSCTL_THR4, 24, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2_M] = {
+		.name = "i2s2_m",
+		K210_DIV(K210_SYSCTL_THR4, 0, 8, K210_DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Muxed gated divider clocks */
+	[K210_CLK_SPI3] = {
+		.name = "spi3",
+		K210_GATE(K210_SYSCTL_EN_PERI, 9),
+		K210_DIV(K210_SYSCTL_THR1, 24, 8, K210_DIV_DOUBLE_ONE_BASED),
+		K210_MUX(K210_SYSCTL_SEL0, 12)
+	},
+	[K210_CLK_TIMER0] = {
+		.name = "timer0",
+		K210_GATE(K210_SYSCTL_EN_PERI, 21),
+		K210_DIV(K210_SYSCTL_THR2,  0, 8, K210_DIV_DOUBLE_ONE_BASED),
+		K210_MUX(K210_SYSCTL_SEL0, 13)
+	},
+	[K210_CLK_TIMER1] = {
+		.name = "timer1",
+		K210_GATE(K210_SYSCTL_EN_PERI, 22),
+		K210_DIV(K210_SYSCTL_THR2, 8, 8, K210_DIV_DOUBLE_ONE_BASED),
+		K210_MUX(K210_SYSCTL_SEL0, 14)
+	},
+	[K210_CLK_TIMER2] = {
+		.name = "timer2",
+		K210_GATE(K210_SYSCTL_EN_PERI, 23),
+		K210_DIV(K210_SYSCTL_THR2, 16, 8, K210_DIV_DOUBLE_ONE_BASED),
+		K210_MUX(K210_SYSCTL_SEL0, 15)
+	},
+};
+
+/*
+ * PLL control register bits.
+ */
+#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		(1 << 20)
+#define K210_PLL_PWRD		(1 << 21)
+#define K210_PLL_INTFB		(1 << 22)
+#define K210_PLL_BYPASS		(1 << 23)
+#define K210_PLL_TEST		(1 << 24)
+#define K210_PLL_EN		(1 << 25)
+#define K210_PLL_SEL		GENMASK(27, 26) /* PLL2 only */
+
+/*
+ * PLL lock register bits.
+ */
+#define K210_PLL_LOCK		0
+#define K210_PLL_CLEAR_SLIP	2
+#define K210_PLL_TEST_OUT	3
+
+/*
+ * Clock selector register bits.
+ */
+#define K210_ACLK_SEL		BIT(0)
+#define K210_ACLK_DIV		GENMASK(2, 1)
+
+/*
+ * PLLs.
+ */
+enum k210_pll_id {
+	K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM
+};
+
+struct k210_pll {
+	enum k210_pll_id id;
+	void __iomem *reg;
+	void __iomem *lock;
+	u8 lock_shift;
+	u8 lock_width;
+	struct clk_hw hw;
+};
+#define to_k210_pll(hw)	container_of(hw, struct k210_pll, hw)
+
+/*
+ * PLLs configuration: by default PLL0 runs at 780 MHz and PLL1 at 299 MHz.
+ * The first 2 SRAM banks depend on ACLK/CPU clock which is by default PLL0
+ * rate divided by 2. Set PLL1 to 390 MHz so that the third SRAM bank has the
+ * same clock as the first 2.
+ */
+struct k210_pll_cfg {
+	u32 reg;
+	u8 lock_shift;
+	u8 lock_width;
+	u32 r;
+	u32 f;
+	u32 od;
+	u32 bwadj;
+};
+
+static struct k210_pll_cfg k210_plls_cfg[] = {
+	{ K210_SYSCTL_PLL0,  0, 2, 0, 59, 1, 59 }, /* 780 MHz */
+	{ K210_SYSCTL_PLL1,  8, 1, 0, 59, 3, 59 }, /* 390 MHz */
+	{ K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */
+};
+
+/*
+ * Indexes in the parents array of clocks used as parents to other clocks.
+ */
+enum k210_parent_idx {
+	K210_PARENT_IN0 = 0,
+	K210_PARENT_PLL0,
+	K210_PARENT_PLL1,
+	K210_PARENT_PLL2,
+	K210_PARENT_ACLK,
+	K210_PARENT_APB0,
+	K210_PARENT_APB1,
+	K210_PARENT_NUM_CLKS,
+};
+
+/**
+ * struct k210_clk - Driver data
+ * @regs: system controller registers start address
+ * @clk_lock: clock setting spinlock
+ * @plls: SoC PLLs descriptors
+ * @aclk: ACLK clock
+ * @clks: All other clocks
+ * @parents: array of pointers to clocks used as parents for muxed clocks.
+ * @clk_data: clock specifier translation for all clocks
+ */
+struct k210_clk {
+	void __iomem			*regs;
+	spinlock_t			clk_lock;
+	struct k210_pll			plls[K210_PLL_NUM];
+	struct clk_hw			aclk;
+	struct clk_hw			clks[K210_NUM_CLKS];
+	const struct clk_hw		*parents[K210_PARENT_NUM_CLKS];
+	struct clk_hw_onecell_data	*clk_data;
+};
+
+static struct k210_clk *kcl;
+
+/*
+ * Set ACLK parent selector: 0 for IN0, 1 for PLL0.
+ */
+static void k210_aclk_set_selector(u8 sel)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+
+	if (sel)
+		reg |= K210_ACLK_SEL;
+	else
+		reg &= K210_ACLK_SEL;
+	writel(reg, kcl->regs + K210_SYSCTL_SEL0);
+}
+
+static void k210_init_pll(struct k210_pll *pll, enum k210_pll_id id,
+			  void __iomem *base)
+{
+	pll->id = id;
+	pll->lock = base + K210_SYSCTL_PLL_LOCK;
+	pll->reg = base + k210_plls_cfg[id].reg;
+	pll->lock_shift = k210_plls_cfg[id].lock_shift;
+	pll->lock_width = k210_plls_cfg[id].lock_width;
+}
+
+static void k210_pll_wait_for_lock(struct k210_pll *pll)
+{
+	u32 reg, mask = GENMASK(pll->lock_shift + pll->lock_width - 1,
+				pll->lock_shift);
+
+	while (true) {
+		reg = readl(pll->lock);
+		if ((reg & mask) == mask)
+			break;
+
+		reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP);
+		writel(reg, pll->lock);
+	}
+}
+
+static bool k210_pll_hw_is_enabled(struct k210_pll *pll)
+{
+	u32 reg = readl(pll->reg);
+	u32 mask = K210_PLL_PWRD | K210_PLL_EN;
+
+	if (reg & K210_PLL_RESET)
+		return false;
+
+	return (reg & mask) == mask;
+}
+
+static void k210_pll_enable_hw(struct k210_pll *pll)
+{
+	struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id];
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	if (k210_pll_hw_is_enabled(pll))
+		goto unlock;
+
+	/*
+	 * For PLL0, we need to re-parent ACLK to IN0 to keep the CPU cores and
+	 * SRAM running.
+	 */
+	if (pll->id == K210_PLL0)
+		k210_aclk_set_selector(0);
+
+	/* Set PLL factors */
+	reg = readl(pll->reg);
+	reg &= ~GENMASK(19, 0);
+	reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r);
+	reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f);
+	reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od);
+	reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj);
+	reg |= K210_PLL_PWRD;
+	writel(reg, pll->reg);
+
+	/*
+	 * Reset the PLL: ensure reset is low before asserting it.
+	 * The magic NOPs come from the Kendryte reference SDK.
+	 */
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+	reg |= K210_PLL_RESET;
+	writel(reg, pll->reg);
+	nop();
+	nop();
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+
+	k210_pll_wait_for_lock(pll);
+
+	reg &= ~K210_PLL_BYPASS;
+	reg |= K210_PLL_EN;
+	writel(reg, pll->reg);
+
+	if (pll->id == K210_PLL0)
+		k210_aclk_set_selector(1);
+
+unlock:
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static void k210_pll_disable_hw(struct k210_pll *pll)
+{
+	unsigned long flags;
+	u32 reg;
+
+	/*
+	 * Bypassing before powering off is important so child clocks do not
+	 * stop working. This is especially important for pll0, the indirect
+	 * parent of the cpu clock.
+	 */
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(pll->reg);
+	reg |= K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	reg &= ~K210_PLL_PWRD;
+	reg &= ~K210_PLL_EN;
+	writel(reg, pll->reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_pll_enable(struct clk_hw *hw)
+{
+	k210_pll_enable_hw(to_k210_pll(hw));
+
+	return 0;
+}
+
+static void k210_pll_disable(struct clk_hw *hw)
+{
+	k210_pll_disable_hw(to_k210_pll(hw));
+}
+
+static int k210_pll_is_enabled(struct clk_hw *hw)
+{
+	return k210_pll_hw_is_enabled(to_k210_pll(hw));
+}
+
+static unsigned long k210_pll_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg = readl(pll->reg);
+	u32 r, f, od;
+
+	if (reg & K210_PLL_BYPASS)
+		return parent_rate;
+
+	if (!(reg & K210_PLL_PWRD))
+		return 0;
+
+	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 (u64)parent_rate * f / (r * od);
+}
+
+static const struct clk_ops k210_pll_ops = {
+	.enable		= k210_pll_enable,
+	.disable	= k210_pll_disable,
+	.is_enabled	= k210_pll_is_enabled,
+	.recalc_rate	= k210_pll_get_rate,
+};
+
+static int k210_pll2_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	reg = readl(pll->reg);
+	reg &= ~K210_PLL_SEL;
+	reg |= FIELD_PREP(K210_PLL_SEL, index);
+	writel(reg, pll->reg);
+
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static u8 k210_pll2_get_parent(struct clk_hw *hw)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg = readl(pll->reg);
+
+	return FIELD_GET(K210_PLL_SEL, reg);
+}
+
+static const struct clk_ops k210_pll2_ops = {
+	.enable		= k210_pll_enable,
+	.disable	= k210_pll_disable,
+	.is_enabled	= k210_pll_is_enabled,
+	.recalc_rate	= k210_pll_get_rate,
+	.set_parent	= k210_pll2_set_parent,
+	.get_parent	= k210_pll2_get_parent,
+};
+
+static int k210_register_pll(struct k210_pll *pll, const char *name,
+			     int num_parents, const struct clk_ops *ops)
+{
+	struct clk_init_data init = {};
+
+	init.name = name;
+	init.parent_hws = kcl->parents;
+	init.num_parents = num_parents;
+	init.ops = ops;
+	pll->hw.init = &init;
+
+	return clk_hw_register(NULL, &pll->hw);
+}
+
+static int k210_register_plls(struct device_node *np)
+{
+	int i, ret;
+
+	for (i = 0; i < K210_PLL_NUM; i++)
+		k210_init_pll(&kcl->plls[i], i, kcl->regs);
+
+	/* PLL0 and PLL1 only have IN0 as parent */
+	ret = k210_register_pll(&kcl->plls[K210_PLL0], "pll0", 1,
+				&k210_pll_ops);
+	if (ret) {
+		pr_err("%pOFP: register PLL0 failed\n", np);
+		return ret;
+	}
+	kcl->parents[K210_PARENT_PLL0] = &kcl->plls[K210_PLL0].hw;
+
+	ret = k210_register_pll(&kcl->plls[K210_PLL1], "pll1", 1,
+				&k210_pll_ops);
+	if (ret) {
+		pr_err("%pOFP: register PLL1 failed\n", np);
+		return ret;
+	}
+	kcl->parents[K210_PARENT_PLL1] = &kcl->plls[K210_PLL1].hw;
+
+	/* PLL2 has IN0, PLL0 and PLL1 as parents */
+	ret = k210_register_pll(&kcl->plls[K210_PLL2], "pll2", 3,
+				&k210_pll2_ops);
+	if (ret) {
+		pr_err("%pOFP: register PLL2 failed\n", np);
+		return ret;
+	}
+	kcl->parents[K210_PARENT_PLL2] = &kcl->plls[K210_PLL2].hw;
+
+	return 0;
+}
+
+static int k210_aclk_set_parent(struct clk_hw *hw, u8 index)
+{
+	k210_aclk_set_selector(index);
+
+	return 0;
+}
+
+static u8 k210_aclk_get_parent(struct clk_hw *hw)
+{
+	u32 sel;
+
+	sel = readl(kcl->regs + K210_SYSCTL_SEL0) & K210_ACLK_SEL;
+
+	return sel ? 1 : 0;
+}
+
+static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+	unsigned int shift;
+
+	if (!(reg & 0x1))
+		return parent_rate;
+
+	shift = FIELD_GET(K210_ACLK_DIV, reg);
+
+	return parent_rate / (2UL << shift);
+}
+
+static const struct clk_ops k210_aclk_ops = {
+	.set_parent	= k210_aclk_set_parent,
+	.get_parent	= k210_aclk_get_parent,
+	.recalc_rate	= k210_aclk_get_rate,
+};
+
+static int k210_register_aclk(struct device_node *np)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	/* ACLK has IN0 and PLL0 as parents */
+	init.name = "aclk";
+	init.parent_hws = kcl->parents;
+	init.num_parents = 2;
+	init.ops = &k210_aclk_ops;
+	kcl->aclk.init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->aclk);
+	if (ret) {
+		pr_err("%pOFP: register aclk failed\n", np);
+		return ret;
+	}
+
+	kcl->parents[K210_PARENT_ACLK] = &kcl->aclk;
+
+	return 0;
+}
+
+#define to_k210_clk_id(hw)	((unsigned int)((hw) - &kcl->clks[0]))
+#define to_k210_clk_cfg(hw)	(&k210_clks[to_k210_clk_id(hw)])
+
+static u32 k210_clk_get_div_val(struct k210_clk_cfg *kclk)
+{
+	u32 reg = readl(kcl->regs + kclk->div_reg);
+
+	return (reg >> kclk->div_shift) & GENMASK(kclk->div_width - 1, 0);
+}
+
+static unsigned long k210_clk_divider(struct k210_clk_cfg *kclk,
+				      u32 div_val)
+{
+	switch (kclk->div_type) {
+	case K210_DIV_ONE_BASED:
+		return div_val + 1;
+	case K210_DIV_DOUBLE_ONE_BASED:
+		return (div_val + 1) * 2;
+	case K210_DIV_POWER_OF_TWO:
+		return 2UL << div_val;
+	case K210_DIV_NONE:
+	default:
+		return 0;
+	}
+}
+
+static int k210_clk_enable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg |= BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static void k210_clk_disable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg &= ~BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->mux_reg) {
+		if (WARN_ON(index != 0))
+			return -EINVAL;
+		return 0;
+	}
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	if (index)
+		reg |= BIT(kclk->mux_bit);
+	else
+		reg &= ~BIT(kclk->mux_bit);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static u8 k210_clk_get_parent(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg, idx;
+
+	if (!kclk->mux_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	idx = (reg & BIT(kclk->mux_bit)) ? 1 : 0;
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return idx;
+}
+
+static unsigned long k210_clk_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long divider;
+
+	if (!kclk->div_reg)
+		return parent_rate;
+
+	divider = k210_clk_divider(kclk, k210_clk_get_div_val(kclk));
+	if (WARN_ON(!divider))
+		return 0;
+
+	return parent_rate / divider;
+}
+
+static const struct clk_ops k210_clk_ops = {
+	.enable		= k210_clk_enable,
+	.disable	= k210_clk_disable,
+	.set_parent	= k210_clk_set_parent,
+	.get_parent	= k210_clk_get_parent,
+	.recalc_rate	= k210_clk_get_rate,
+};
+
+static struct clk_hw *k210_register_clk(int id, enum k210_parent_idx parent_idx,
+					int num_parents, unsigned long flags)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = k210_clks[id].name;
+	init.parent_hws = &kcl->parents[parent_idx];
+	init.num_parents = num_parents;
+	init.flags = flags;
+	init.ops = &k210_clk_ops;
+	kcl->clks[id].init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->clks[id]);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &kcl->clks[id];
+}
+
+static inline struct clk_hw *k210_register_mux_clk(int id)
+{
+	/*
+	 * All muxed clocks have IN0 and PLL0 as parents: these are the
+	 * first two entries of the parents array.
+	 */
+	return k210_register_clk(id, K210_PARENT_IN0, 2, 0);
+}
+
+static inline struct clk_hw *k210_register_critical_clk(int id,
+					enum k210_parent_idx parent_idx)
+{
+	return k210_register_clk(id, parent_idx, 1, CLK_IS_CRITICAL);
+}
+
+static inline struct clk_hw *k210_register_child(int id,
+					enum k210_parent_idx parent_idx)
+{
+	return k210_register_clk(id, parent_idx, 1, 0);
+}
+
+static inline struct clk_hw *k210_register_in0_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_IN0);
+}
+
+static inline struct clk_hw *k210_register_pll0_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_PLL0);
+}
+
+static inline struct clk_hw *k210_register_pll2_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_PLL2);
+}
+
+static inline struct clk_hw *k210_register_aclk_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_ACLK);
+}
+
+static inline struct clk_hw *k210_register_apb0_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_APB0);
+}
+
+static inline struct clk_hw *k210_register_apb1_child(int id)
+{
+	return k210_register_child(id, K210_PARENT_APB1);
+}
+
+static void __init k210_clk_init(struct device_node *np)
+{
+	struct device_node *sysctl_np;
+	struct clk_hw **hws;
+	struct clk *in0;
+	int i, ret;
+
+	kcl = kzalloc(sizeof(*kcl), GFP_KERNEL);
+	if (!kcl)
+		return;
+
+	kcl->clk_data = kzalloc(struct_size(kcl->clk_data, hws, K210_NUM_CLKS),
+				GFP_KERNEL);
+	if (!kcl->clk_data)
+		return;
+
+	sysctl_np = of_get_parent(np);
+	kcl->regs = of_iomap(sysctl_np, 0);
+	of_node_put(sysctl_np);
+	if (!kcl->regs) {
+		pr_err("%pOFP: failed to map registers\n", np);
+		return;
+	}
+
+	spin_lock_init(&kcl->clk_lock);
+	kcl->clk_data->num = K210_NUM_CLKS;
+	hws = kcl->clk_data->hws;
+	for (i = 0; i < K210_NUM_CLKS; i++)
+		hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	/* Get the system base fixed-rate 26MHz oscillator clock */
+	in0 = of_clk_get(np, 0);
+	if (IS_ERR(in0)) {
+		pr_err("%pOFP: failed to get base fixed-rate oscillator\n", np);
+		return;
+	}
+	kcl->parents[K210_PARENT_IN0] = __clk_get_hw(in0);
+
+	ret = k210_register_plls(np);
+	if (ret)
+		return;
+
+	ret = k210_register_aclk(np);
+	if (ret)
+		return;
+
+	/*
+	 * Critical clocks: there are no consumers of the SRAM clocks,
+	 * including the AI clock for the third SRAM bank. The CPU clock
+	 * is only referenced by the uarths serial device and so would be
+	 * disabled if the serial console is disabled. Mark all these clocks
+	 * as critical so that they are never disabled by the core clock
+	 * management.
+	 */
+	hws[K210_CLK_CPU] =
+		k210_register_critical_clk(K210_CLK_CPU, K210_PARENT_ACLK);
+	hws[K210_CLK_SRAM0] =
+		k210_register_critical_clk(K210_CLK_SRAM0, K210_PARENT_ACLK);
+	hws[K210_CLK_SRAM1] =
+		k210_register_critical_clk(K210_CLK_SRAM1, K210_PARENT_ACLK);
+	hws[K210_CLK_AI] =
+		 k210_register_critical_clk(K210_CLK_AI, K210_PARENT_PLL1);
+
+	/* Clocks with aclk as source */
+	hws[K210_CLK_DMA] = k210_register_aclk_child(K210_CLK_DMA);
+	hws[K210_CLK_FFT] = k210_register_aclk_child(K210_CLK_FFT);
+	hws[K210_CLK_ROM] = k210_register_aclk_child(K210_CLK_ROM);
+	hws[K210_CLK_DVP] = k210_register_aclk_child(K210_CLK_DVP);
+	hws[K210_CLK_APB0] = k210_register_aclk_child(K210_CLK_APB0);
+	hws[K210_CLK_APB1] = k210_register_aclk_child(K210_CLK_APB1);
+	hws[K210_CLK_APB2] = k210_register_aclk_child(K210_CLK_APB2);
+
+	/* Clocks with PLL0 as source */
+	hws[K210_CLK_SPI0] = k210_register_pll0_child(K210_CLK_SPI0);
+	hws[K210_CLK_SPI1] = k210_register_pll0_child(K210_CLK_SPI1);
+	hws[K210_CLK_SPI2] = k210_register_pll0_child(K210_CLK_SPI2);
+	hws[K210_CLK_I2C0] = k210_register_pll0_child(K210_CLK_I2C0);
+	hws[K210_CLK_I2C1] = k210_register_pll0_child(K210_CLK_I2C1);
+	hws[K210_CLK_I2C2] = k210_register_pll0_child(K210_CLK_I2C2);
+
+	/* Clocks with PLL2 as source */
+	hws[K210_CLK_I2S0] = k210_register_pll2_child(K210_CLK_I2S0);
+	hws[K210_CLK_I2S1] = k210_register_pll2_child(K210_CLK_I2S1);
+	hws[K210_CLK_I2S2] = k210_register_pll2_child(K210_CLK_I2S2);
+	hws[K210_CLK_I2S0_M] = k210_register_pll2_child(K210_CLK_I2S0_M);
+	hws[K210_CLK_I2S1_M] = k210_register_pll2_child(K210_CLK_I2S1_M);
+	hws[K210_CLK_I2S2_M] = k210_register_pll2_child(K210_CLK_I2S2_M);
+
+	/* Clocks with IN0 as source */
+	hws[K210_CLK_WDT0] = k210_register_in0_child(K210_CLK_WDT0);
+	hws[K210_CLK_WDT1] = k210_register_in0_child(K210_CLK_WDT1);
+	hws[K210_CLK_RTC] = k210_register_in0_child(K210_CLK_RTC);
+
+	/* Clocks with APB0 as source */
+	kcl->parents[K210_PARENT_APB0] = hws[K210_CLK_APB0];
+	hws[K210_CLK_GPIO] = k210_register_apb0_child(K210_CLK_GPIO);
+	hws[K210_CLK_UART1] = k210_register_apb0_child(K210_CLK_UART1);
+	hws[K210_CLK_UART2] = k210_register_apb0_child(K210_CLK_UART2);
+	hws[K210_CLK_UART3] = k210_register_apb0_child(K210_CLK_UART3);
+	hws[K210_CLK_FPIOA] = k210_register_apb0_child(K210_CLK_FPIOA);
+	hws[K210_CLK_SHA] = k210_register_apb0_child(K210_CLK_SHA);
+
+	/* Clocks with APB1 as source */
+	kcl->parents[K210_PARENT_APB1] = hws[K210_CLK_APB1];
+	hws[K210_CLK_AES] = k210_register_apb1_child(K210_CLK_AES);
+	hws[K210_CLK_OTP] = k210_register_apb1_child(K210_CLK_OTP);
+
+	/* Mux clocks with in0 or pll0 as source */
+	hws[K210_CLK_SPI3] = k210_register_mux_clk(K210_CLK_SPI3);
+	hws[K210_CLK_TIMER0] = k210_register_mux_clk(K210_CLK_TIMER0);
+	hws[K210_CLK_TIMER1] = k210_register_mux_clk(K210_CLK_TIMER1);
+	hws[K210_CLK_TIMER2] = k210_register_mux_clk(K210_CLK_TIMER2);
+
+	for (i = 0; i < K210_NUM_CLKS; i++) {
+		if (IS_ERR(hws[i])) {
+			pr_err("%pOFP: register clock %s failed %ld\n",
+			       np, k210_clks[i].name, PTR_ERR(hws[i]));
+			return;
+		}
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, kcl->clk_data);
+	if (ret) {
+		pr_err("%pOFP: add clock provider failed %d\n", np, ret);
+		return;
+	}
+
+	pr_info("%pOFP: CPU running at %lu MHz\n",
+		np, clk_hw_get_rate(hws[K210_CLK_CPU]) / 1000000);
+}
+
+CLK_OF_DECLARE(k210_clk, "canaan,k210-clk", k210_clk_init);
+
+/*
+ * Enable PLL1 to be able to use the AI SRAM.
+ */
+void __init k210_clk_early_init(void __iomem *regs)
+{
+	struct k210_pll pll1;
+
+	/* Make sure ACLK selector is set to PLL0 */
+	k210_aclk_set_selector(1);
+
+	/* Startup PLL1 to enable the aisram bank for general memory use */
+	k210_init_pll(&pll1, K210_PLL1, regs);
+	k210_pll_enable_hw(&pll1);
+}
diff --git a/drivers/soc/canaan/Kconfig b/drivers/soc/canaan/Kconfig
index 5232d13f07e5..8179b69518b4 100644
--- a/drivers/soc/canaan/Kconfig
+++ b/drivers/soc/canaan/Kconfig
@@ -1,14 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
 
-if SOC_CANAAN
-
-config K210_SYSCTL
+config SOC_K210_SYSCTL
 	bool "Canaan Kendryte K210 SoC system controller"
-	default y
-	depends on RISCV
+	depends on RISCV && SOC_CANAAN && OF
+	default SOC_CANAAN
+        select PM
+        select SIMPLE_PM_BUS
+        select SYSCON
+        select MFD_SYSCON
 	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
+	  Canaan Kendryte K210 SoC system controller driver.
diff --git a/drivers/soc/canaan/Makefile b/drivers/soc/canaan/Makefile
index 002d9ce95c0d..570280ad7967 100644
--- a/drivers/soc/canaan/Makefile
+++ b/drivers/soc/canaan/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_K210_SYSCTL)	+= k210-sysctl.o
+obj-$(CONFIG_SOC_K210_SYSCTL)	+= k210-sysctl.o
diff --git a/drivers/soc/canaan/k210-sysctl.c b/drivers/soc/canaan/k210-sysctl.c
index 60b474c33d45..27a346c406bc 100644
--- a/drivers/soc/canaan/k210-sysctl.c
+++ b/drivers/soc/canaan/k210-sysctl.c
@@ -3,165 +3,45 @@
  * 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 <linux/bitfield.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 #include <asm/soc.h>
 
 #include <soc/canaan/k210-sysctl.h>
 
-#define K210_SYSCTL_CLK0_FREQ		26000000UL
-
-/* Registers base address */
-#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
-
-/* Register bits */
-/* K210_SYSCTL_PLL1: clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
-#define PLL_RESET		(1 << 20)
-#define PLL_PWR			(1 << 21)
-#define PLL_BYPASS		(1 << 23)
-#define PLL_OUT_EN		(1 << 25)
-/* K210_SYSCTL_PLL_LOCK */
-#define PLL1_LOCK1		(1 << 8)
-#define PLL1_LOCK2		(1 << 9)
-#define PLL1_SLIP_CLEAR		(1 << 10)
-/* K210_SYSCTL_SEL0 */
-#define CLKSEL_ACLK		(1 << 0)
-/* K210_SYSCTL_CLKEN_CENT */
-#define CLKEN_CPU		(1 << 0)
-#define CLKEN_SRAM0		(1 << 1)
-#define CLKEN_SRAM1		(1 << 2)
-/* K210_SYSCTL_EN_PERI */
-#define CLKEN_ROM		(1 << 0)
-#define CLKEN_TIMER0		(1 << 21)
-#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 &= ~GENMASK(19, 0);				/* clkr1 = 0 */
-	val |= FIELD_PREP(GENMASK(9, 4), 0x3B);		/* clkf1 = 59 */
-	val |= FIELD_PREP(GENMASK(13, 10), 0x3);	/* clkod1 = 3 */
-	val |= FIELD_PREP(GENMASK(19, 14), 0x3B);	/* bwadj1 = 59 */
-	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_SEL0);
-	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 + FIELD_GET(GENMASK(3, 0), pll0);
-	clkf0 = 1 + FIELD_GET(GENMASK(9, 4), pll0);
-	clkod0 = 1 + FIELD_GET(GENMASK(13, 10), pll0);
-	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
-
-	/* Get the frequency divisor from the clock selector */
-	return pll0_freq / (2ULL << FIELD_GET(0x00000006, clksel0));
-}
-
-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;
+	struct device *dev = &pdev->dev;
+	struct clk *pclk;
+	int ret;
+
+	dev_info(dev, "K210 system controller\n");
+
+	/* Get power bus clock */
+	pclk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pclk))
+		return dev_err_probe(dev, PTR_ERR(pclk),
+				     "Get bus clock failed\n");
+
+	ret = clk_prepare_enable(pclk);
+	if (ret) {
+		dev_err(dev, "Enable bus clock failed\n");
+		return ret;
 	}
 
-	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;
-	}
+	/* Populate children */
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		dev_err(dev, "Populate platform failed %d\n", ret);
 
-	return 0;
+	return ret;
 }
 
 static const struct of_device_id k210_sysctl_of_match[] = {
-	{ .compatible = "kendryte,k210-sysctl", },
-	{}
+	{ .compatible = "canaan,k210-sysctl", },
+	{ /* sentinel */ },
 };
 
 static struct platform_driver k210_sysctl_driver = {
@@ -171,12 +51,13 @@ static struct platform_driver k210_sysctl_driver = {
 	},
 	.probe			= k210_sysctl_probe,
 };
+builtin_platform_driver(k210_sysctl_driver);
 
-static int __init k210_sysctl_init(void)
-{
-	return platform_driver_register(&k210_sysctl_driver);
-}
-core_initcall(k210_sysctl_init);
+/*
+ * System controller registers base address and size.
+ */
+#define K210_SYSCTL_BASE_ADDR	0x50440000ULL
+#define K210_SYSCTL_BASE_SIZE	0x1000
 
 /*
  * This needs to be called very early during initialization, given that
@@ -184,24 +65,14 @@ core_initcall(k210_sysctl_init);
  */
 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);
+	void __iomem *sysctl_base;
 
-	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
-		      regs + K210_SYSCTL_EN_CENT);
-	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
-		      regs + K210_SYSCTL_EN_PERI);
+	sysctl_base = ioremap(K210_SYSCTL_BASE_ADDR, K210_SYSCTL_BASE_SIZE);
+	if (!sysctl_base)
+		panic("k210-sysctl: ioremap failed");
 
-	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_SEL0);
+	k210_clk_early_init(sysctl_base);
 
-	iounmap(regs);
+	iounmap(sysctl_base);
 }
-SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
+SOC_EARLY_INIT_DECLARE(k210_soc, "canaan,kendryte-k210", k210_soc_early_init);
diff --git a/include/soc/canaan/k210-sysctl.h b/include/soc/canaan/k210-sysctl.h
index 2e037db68f35..0c2b2c2dabca 100644
--- a/include/soc/canaan/k210-sysctl.h
+++ b/include/soc/canaan/k210-sysctl.h
@@ -38,4 +38,6 @@
 #define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
 #define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
 
+void k210_clk_early_init(void __iomem *regs);
+
 #endif
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 01/10] clk: Add RISC-V Canaan Kendryte K210 clock driver Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-14 23:32   ` Palmer Dabbelt
  2021-01-12  0:58 ` [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree Damien Le Moal
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the pinctrl-k210.c pinctrl driver for the Canaan Kendryte K210
field programmable IO array (FPIOA) to allow configuring the SoC pin
functions. The K210 has 48 programmable pins which can take any of 256
possible functions.

This patch is inspired from the k210 pinctrl driver for the u-boot
project and contains many direct contributions from Sean Anderson.

The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210
SOC FPIOA DRIVER" with myself listed as maintainer for this driver.

Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-gpio@vger.kernel.org
Signed-off-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 MAINTAINERS                    |   7 +
 arch/riscv/Kconfig.socs        |   1 +
 drivers/pinctrl/Kconfig        |  13 +
 drivers/pinctrl/Makefile       |   1 +
 drivers/pinctrl/pinctrl-k210.c | 985 +++++++++++++++++++++++++++++++++
 5 files changed, 1007 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-k210.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 637b79eba693..1a7a1e4092e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3860,6 +3860,13 @@ W:	https://github.com/Cascoda/ca8210-linux.git
 F:	Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
 F:	drivers/net/ieee802154/ca8210.c
 
+CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
+M:	Damien Le Moal <damien.lemoal@wdc.com>
+L:	linux-riscv@lists.infradead.org
+L:	linux-gpio@vger.kernel.org (pinctrl driver)
+F:	Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
+F:	drivers/pinctrl/pinctrl-k210.c
+
 CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
 M:	Damien Le Moal <damien.lemoal@wdc.com>
 L:	linux-kernel@vger.kernel.org
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 57e53219c500..6402746c68f3 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -30,6 +30,7 @@ config SOC_CANAAN
 	select SERIAL_SIFIVE_CONSOLE if TTY
 	select SIFIVE_PLIC
 	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
 	help
 	  This enables support for Canaan Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index d4b2f2e2ed75..cd437e3cc255 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -394,6 +394,19 @@ config PINCTRL_MICROCHIP_SGPIO
 	  connect control signals from SFP modules and to act as an
 	  LED controller.
 
+config PINCTRL_K210
+	bool "Pinctrl driver for the Canaan Kendryte K210 SoC"
+	depends on RISCV && SOC_CANAAN && OF
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select REGMAP_MMIO
+	default SOC_CANAAN
+	help
+	  Add support for the Canaan Kendryte K210 RISC-V SOC Field
+	  Programmable IO Array (FPIOA) controller.
+
 source "drivers/pinctrl/actions/Kconfig"
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 5bb9bb6cc3ce..152c8fe51726 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO)	+= pinctrl-microchip-sgpio.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
+obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
 
 obj-y				+= actions/
 obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
new file mode 100644
index 000000000000..8a733cf77ba0
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-k210.c
@@ -0,0 +1,985 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/k210-fpioa.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+/*
+ * The K210 only implements 8 drive levels, even though
+ * there is register space for 16
+ */
+#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
+#define K210_PC_DRIVE_SHIFT	8
+#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_MAX	7
+#define K210_PC_MODE_MASK	GENMASK(23, 12)
+
+/*
+ * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
+ * where FUNCTION_OE is a physical signal from the function.
+ */
+#define K210_PC_OE		BIT(12) /* Output Enable */
+#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
+#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
+#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
+#define K210_PC_PU		BIT(16) /* Pull Up */
+#define K210_PC_PD		BIT(17) /* Pull Down */
+/* Strong pull up not implemented on K210 */
+#define K210_PC_SL		BIT(19) /* reduce SLew rate */
+/* Same semantics as OE above */
+#define K210_PC_IE		BIT(20) /* Input Enable */
+#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
+#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
+#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
+#define K210_PC_DI		BIT(31) /* raw Data Input */
+
+#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
+
+#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
+#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
+#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
+				 K210_PC_OE | K210_PC_PU)
+#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
+				 K210_PC_OE_INV | K210_PC_IE_INV)
+#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
+				 K210_PC_MODE_OUT | K210_PC_OE_INV)
+#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
+
+#define K210_PG_FUNC		GENMASK(7, 0)
+#define K210_PG_DO		BIT(8)
+#define K210_PG_PIN		GENMASK(22, 16)
+
+/*
+ * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
+ * @pins: 48 32-bits IO pin registers
+ * @tie_en: 256 (one per function) input tie enable bits
+ * @tie_val: 256 (one per function) input tie value bits
+ */
+struct k210_fpioa {
+	u32 pins[48];
+	u32 tie_en[8];
+	u32 tie_val[8];
+};
+
+struct k210_fpioa_data {
+
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+
+	struct k210_fpioa __iomem *fpioa;
+	struct regmap *sysctl_map;
+	u32 power_offset;
+	struct clk *clk;
+	struct clk *pclk;
+};
+
+#define K210_PIN_NAME(i)	("IO_" #i)
+#define K210_PIN(i)		[(i)] = PINCTRL_PIN((i), K210_PIN_NAME(i))
+
+static const struct pinctrl_pin_desc k210_pins[] = {
+	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
+	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
+	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
+	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
+	K210_PIN(12), K210_PIN(13), K210_PIN(14),
+	K210_PIN(15), K210_PIN(16), K210_PIN(17),
+	K210_PIN(18), K210_PIN(19), K210_PIN(20),
+	K210_PIN(21), K210_PIN(22), K210_PIN(23),
+	K210_PIN(24), K210_PIN(25), K210_PIN(26),
+	K210_PIN(27), K210_PIN(28), K210_PIN(29),
+	K210_PIN(30), K210_PIN(31), K210_PIN(32),
+	K210_PIN(33), K210_PIN(34), K210_PIN(35),
+	K210_PIN(36), K210_PIN(37), K210_PIN(38),
+	K210_PIN(39), K210_PIN(40), K210_PIN(41),
+	K210_PIN(42), K210_PIN(43), K210_PIN(44),
+	K210_PIN(45), K210_PIN(46), K210_PIN(47)
+};
+
+#define K210_NPINS ARRAY_SIZE(k210_pins)
+
+/*
+ * Pin groups: each of the 48 programmable pins is a group.
+ * To this are added 8 power domain groups, which for the purposes of
+ * the pin subsystem, contain no pins. The power domain groups only exist
+ * to set the power level. The id should never be used (since there are
+ * no pins 48-55).
+ */
+static const char *const k210_group_names[] = {
+	/* The first 48 groups are for pins, one each */
+	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
+	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
+	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
+	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
+	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
+	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
+	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
+	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
+	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
+	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
+	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
+	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
+	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
+	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
+	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
+	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
+	[48] = "A0", [49] = "A1", [50] = "A2",
+	[51] = "B3", [52] = "B4", [53] = "B5",
+	[54] = "C6", [55] = "C7"
+};
+
+#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
+
+enum k210_pinctrl_mode_id {
+	K210_PC_DEFAULT_DISABLED,
+	K210_PC_DEFAULT_IN,
+	K210_PC_DEFAULT_IN_TIE,
+	K210_PC_DEFAULT_OUT,
+	K210_PC_DEFAULT_I2C,
+	K210_PC_DEFAULT_SCCB,
+	K210_PC_DEFAULT_SPI,
+	K210_PC_DEFAULT_GPIO,
+	K210_PC_DEFAULT_INT13,
+};
+
+#define K210_PC_DEFAULT(mode) \
+	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
+
+static const u32 k210_pinconf_mode_id_to_mode[] = {
+	[K210_PC_DEFAULT_DISABLED] = 0,
+	K210_PC_DEFAULT(IN),
+	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
+	K210_PC_DEFAULT(OUT),
+	K210_PC_DEFAULT(I2C),
+	K210_PC_DEFAULT(SCCB),
+	K210_PC_DEFAULT(SPI),
+	K210_PC_DEFAULT(GPIO),
+	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
+};
+
+#undef DEFAULT
+
+/*
+ * Pin functions configuration information.
+ */
+struct k210_pcf_info {
+	char name[15];
+	u8 mode_id;
+};
+
+#define K210_FUNC(id, mode)				\
+	[K210_PCF_##id] = {				\
+		.name = #id,				\
+		.mode_id = K210_PC_DEFAULT_##mode	\
+	}
+
+static const struct k210_pcf_info k210_pcf_infos[] = {
+	K210_FUNC(JTAG_TCLK,		IN),
+	K210_FUNC(JTAG_TDI,		IN),
+	K210_FUNC(JTAG_TMS,		IN),
+	K210_FUNC(JTAG_TDO,		OUT),
+	K210_FUNC(SPI0_D0,		SPI),
+	K210_FUNC(SPI0_D1,		SPI),
+	K210_FUNC(SPI0_D2,		SPI),
+	K210_FUNC(SPI0_D3,		SPI),
+	K210_FUNC(SPI0_D4,		SPI),
+	K210_FUNC(SPI0_D5,		SPI),
+	K210_FUNC(SPI0_D6,		SPI),
+	K210_FUNC(SPI0_D7,		SPI),
+	K210_FUNC(SPI0_SS0,		OUT),
+	K210_FUNC(SPI0_SS1,		OUT),
+	K210_FUNC(SPI0_SS2,		OUT),
+	K210_FUNC(SPI0_SS3,		OUT),
+	K210_FUNC(SPI0_ARB,		IN_TIE),
+	K210_FUNC(SPI0_SCLK,		OUT),
+	K210_FUNC(UARTHS_RX,		IN),
+	K210_FUNC(UARTHS_TX,		OUT),
+	K210_FUNC(RESV6,		IN),
+	K210_FUNC(RESV7,		IN),
+	K210_FUNC(CLK_SPI1,		OUT),
+	K210_FUNC(CLK_I2C1,		OUT),
+	K210_FUNC(GPIOHS0,		GPIO),
+	K210_FUNC(GPIOHS1,		GPIO),
+	K210_FUNC(GPIOHS2,		GPIO),
+	K210_FUNC(GPIOHS3,		GPIO),
+	K210_FUNC(GPIOHS4,		GPIO),
+	K210_FUNC(GPIOHS5,		GPIO),
+	K210_FUNC(GPIOHS6,		GPIO),
+	K210_FUNC(GPIOHS7,		GPIO),
+	K210_FUNC(GPIOHS8,		GPIO),
+	K210_FUNC(GPIOHS9,		GPIO),
+	K210_FUNC(GPIOHS10,		GPIO),
+	K210_FUNC(GPIOHS11,		GPIO),
+	K210_FUNC(GPIOHS12,		GPIO),
+	K210_FUNC(GPIOHS13,		GPIO),
+	K210_FUNC(GPIOHS14,		GPIO),
+	K210_FUNC(GPIOHS15,		GPIO),
+	K210_FUNC(GPIOHS16,		GPIO),
+	K210_FUNC(GPIOHS17,		GPIO),
+	K210_FUNC(GPIOHS18,		GPIO),
+	K210_FUNC(GPIOHS19,		GPIO),
+	K210_FUNC(GPIOHS20,		GPIO),
+	K210_FUNC(GPIOHS21,		GPIO),
+	K210_FUNC(GPIOHS22,		GPIO),
+	K210_FUNC(GPIOHS23,		GPIO),
+	K210_FUNC(GPIOHS24,		GPIO),
+	K210_FUNC(GPIOHS25,		GPIO),
+	K210_FUNC(GPIOHS26,		GPIO),
+	K210_FUNC(GPIOHS27,		GPIO),
+	K210_FUNC(GPIOHS28,		GPIO),
+	K210_FUNC(GPIOHS29,		GPIO),
+	K210_FUNC(GPIOHS30,		GPIO),
+	K210_FUNC(GPIOHS31,		GPIO),
+	K210_FUNC(GPIO0,		GPIO),
+	K210_FUNC(GPIO1,		GPIO),
+	K210_FUNC(GPIO2,		GPIO),
+	K210_FUNC(GPIO3,		GPIO),
+	K210_FUNC(GPIO4,		GPIO),
+	K210_FUNC(GPIO5,		GPIO),
+	K210_FUNC(GPIO6,		GPIO),
+	K210_FUNC(GPIO7,		GPIO),
+	K210_FUNC(UART1_RX,		IN),
+	K210_FUNC(UART1_TX,		OUT),
+	K210_FUNC(UART2_RX,		IN),
+	K210_FUNC(UART2_TX,		OUT),
+	K210_FUNC(UART3_RX,		IN),
+	K210_FUNC(UART3_TX,		OUT),
+	K210_FUNC(SPI1_D0,		SPI),
+	K210_FUNC(SPI1_D1,		SPI),
+	K210_FUNC(SPI1_D2,		SPI),
+	K210_FUNC(SPI1_D3,		SPI),
+	K210_FUNC(SPI1_D4,		SPI),
+	K210_FUNC(SPI1_D5,		SPI),
+	K210_FUNC(SPI1_D6,		SPI),
+	K210_FUNC(SPI1_D7,		SPI),
+	K210_FUNC(SPI1_SS0,		OUT),
+	K210_FUNC(SPI1_SS1,		OUT),
+	K210_FUNC(SPI1_SS2,		OUT),
+	K210_FUNC(SPI1_SS3,		OUT),
+	K210_FUNC(SPI1_ARB,		IN_TIE),
+	K210_FUNC(SPI1_SCLK,		OUT),
+	K210_FUNC(SPI2_D0,		SPI),
+	K210_FUNC(SPI2_SS,		IN),
+	K210_FUNC(SPI2_SCLK,		IN),
+	K210_FUNC(I2S0_MCLK,		OUT),
+	K210_FUNC(I2S0_SCLK,		OUT),
+	K210_FUNC(I2S0_WS,		OUT),
+	K210_FUNC(I2S0_IN_D0,		IN),
+	K210_FUNC(I2S0_IN_D1,		IN),
+	K210_FUNC(I2S0_IN_D2,		IN),
+	K210_FUNC(I2S0_IN_D3,		IN),
+	K210_FUNC(I2S0_OUT_D0,		OUT),
+	K210_FUNC(I2S0_OUT_D1,		OUT),
+	K210_FUNC(I2S0_OUT_D2,		OUT),
+	K210_FUNC(I2S0_OUT_D3,		OUT),
+	K210_FUNC(I2S1_MCLK,		OUT),
+	K210_FUNC(I2S1_SCLK,		OUT),
+	K210_FUNC(I2S1_WS,		OUT),
+	K210_FUNC(I2S1_IN_D0,		IN),
+	K210_FUNC(I2S1_IN_D1,		IN),
+	K210_FUNC(I2S1_IN_D2,		IN),
+	K210_FUNC(I2S1_IN_D3,		IN),
+	K210_FUNC(I2S1_OUT_D0,		OUT),
+	K210_FUNC(I2S1_OUT_D1,		OUT),
+	K210_FUNC(I2S1_OUT_D2,		OUT),
+	K210_FUNC(I2S1_OUT_D3,		OUT),
+	K210_FUNC(I2S2_MCLK,		OUT),
+	K210_FUNC(I2S2_SCLK,		OUT),
+	K210_FUNC(I2S2_WS,		OUT),
+	K210_FUNC(I2S2_IN_D0,		IN),
+	K210_FUNC(I2S2_IN_D1,		IN),
+	K210_FUNC(I2S2_IN_D2,		IN),
+	K210_FUNC(I2S2_IN_D3,		IN),
+	K210_FUNC(I2S2_OUT_D0,		OUT),
+	K210_FUNC(I2S2_OUT_D1,		OUT),
+	K210_FUNC(I2S2_OUT_D2,		OUT),
+	K210_FUNC(I2S2_OUT_D3,		OUT),
+	K210_FUNC(RESV0,		DISABLED),
+	K210_FUNC(RESV1,		DISABLED),
+	K210_FUNC(RESV2,		DISABLED),
+	K210_FUNC(RESV3,		DISABLED),
+	K210_FUNC(RESV4,		DISABLED),
+	K210_FUNC(RESV5,		DISABLED),
+	K210_FUNC(I2C0_SCLK,		I2C),
+	K210_FUNC(I2C0_SDA,		I2C),
+	K210_FUNC(I2C1_SCLK,		I2C),
+	K210_FUNC(I2C1_SDA,		I2C),
+	K210_FUNC(I2C2_SCLK,		I2C),
+	K210_FUNC(I2C2_SDA,		I2C),
+	K210_FUNC(DVP_XCLK,		OUT),
+	K210_FUNC(DVP_RST,		OUT),
+	K210_FUNC(DVP_PWDN,		OUT),
+	K210_FUNC(DVP_VSYNC,		IN),
+	K210_FUNC(DVP_HSYNC,		IN),
+	K210_FUNC(DVP_PCLK,		IN),
+	K210_FUNC(DVP_D0,		IN),
+	K210_FUNC(DVP_D1,		IN),
+	K210_FUNC(DVP_D2,		IN),
+	K210_FUNC(DVP_D3,		IN),
+	K210_FUNC(DVP_D4,		IN),
+	K210_FUNC(DVP_D5,		IN),
+	K210_FUNC(DVP_D6,		IN),
+	K210_FUNC(DVP_D7,		IN),
+	K210_FUNC(SCCB_SCLK,		SCCB),
+	K210_FUNC(SCCB_SDA,		SCCB),
+	K210_FUNC(UART1_CTS,		IN),
+	K210_FUNC(UART1_DSR,		IN),
+	K210_FUNC(UART1_DCD,		IN),
+	K210_FUNC(UART1_RI,		IN),
+	K210_FUNC(UART1_SIR_IN,		IN),
+	K210_FUNC(UART1_DTR,		OUT),
+	K210_FUNC(UART1_RTS,		OUT),
+	K210_FUNC(UART1_OUT2,		OUT),
+	K210_FUNC(UART1_OUT1,		OUT),
+	K210_FUNC(UART1_SIR_OUT,	OUT),
+	K210_FUNC(UART1_BAUD,		OUT),
+	K210_FUNC(UART1_RE,		OUT),
+	K210_FUNC(UART1_DE,		OUT),
+	K210_FUNC(UART1_RS485_EN,	OUT),
+	K210_FUNC(UART2_CTS,		IN),
+	K210_FUNC(UART2_DSR,		IN),
+	K210_FUNC(UART2_DCD,		IN),
+	K210_FUNC(UART2_RI,		IN),
+	K210_FUNC(UART2_SIR_IN,		IN),
+	K210_FUNC(UART2_DTR,		OUT),
+	K210_FUNC(UART2_RTS,		OUT),
+	K210_FUNC(UART2_OUT2,		OUT),
+	K210_FUNC(UART2_OUT1,		OUT),
+	K210_FUNC(UART2_SIR_OUT,	OUT),
+	K210_FUNC(UART2_BAUD,		OUT),
+	K210_FUNC(UART2_RE,		OUT),
+	K210_FUNC(UART2_DE,		OUT),
+	K210_FUNC(UART2_RS485_EN,	OUT),
+	K210_FUNC(UART3_CTS,		IN),
+	K210_FUNC(UART3_DSR,		IN),
+	K210_FUNC(UART3_DCD,		IN),
+	K210_FUNC(UART3_RI,		IN),
+	K210_FUNC(UART3_SIR_IN,		IN),
+	K210_FUNC(UART3_DTR,		OUT),
+	K210_FUNC(UART3_RTS,		OUT),
+	K210_FUNC(UART3_OUT2,		OUT),
+	K210_FUNC(UART3_OUT1,		OUT),
+	K210_FUNC(UART3_SIR_OUT,	OUT),
+	K210_FUNC(UART3_BAUD,		OUT),
+	K210_FUNC(UART3_RE,		OUT),
+	K210_FUNC(UART3_DE,		OUT),
+	K210_FUNC(UART3_RS485_EN,	OUT),
+	K210_FUNC(TIMER0_TOGGLE1,	OUT),
+	K210_FUNC(TIMER0_TOGGLE2,	OUT),
+	K210_FUNC(TIMER0_TOGGLE3,	OUT),
+	K210_FUNC(TIMER0_TOGGLE4,	OUT),
+	K210_FUNC(TIMER1_TOGGLE1,	OUT),
+	K210_FUNC(TIMER1_TOGGLE2,	OUT),
+	K210_FUNC(TIMER1_TOGGLE3,	OUT),
+	K210_FUNC(TIMER1_TOGGLE4,	OUT),
+	K210_FUNC(TIMER2_TOGGLE1,	OUT),
+	K210_FUNC(TIMER2_TOGGLE2,	OUT),
+	K210_FUNC(TIMER2_TOGGLE3,	OUT),
+	K210_FUNC(TIMER2_TOGGLE4,	OUT),
+	K210_FUNC(CLK_SPI2,		OUT),
+	K210_FUNC(CLK_I2C2,		OUT),
+	K210_FUNC(INTERNAL0,		OUT),
+	K210_FUNC(INTERNAL1,		OUT),
+	K210_FUNC(INTERNAL2,		OUT),
+	K210_FUNC(INTERNAL3,		OUT),
+	K210_FUNC(INTERNAL4,		OUT),
+	K210_FUNC(INTERNAL5,		OUT),
+	K210_FUNC(INTERNAL6,		OUT),
+	K210_FUNC(INTERNAL7,		OUT),
+	K210_FUNC(INTERNAL8,		OUT),
+	K210_FUNC(INTERNAL9,		IN),
+	K210_FUNC(INTERNAL10,		IN),
+	K210_FUNC(INTERNAL11,		IN),
+	K210_FUNC(INTERNAL12,		IN),
+	K210_FUNC(INTERNAL13,		INT13),
+	K210_FUNC(INTERNAL14,		I2C),
+	K210_FUNC(INTERNAL15,		IN),
+	K210_FUNC(INTERNAL16,		IN),
+	K210_FUNC(INTERNAL17,		IN),
+	K210_FUNC(CONSTANT,		DISABLED),
+	K210_FUNC(INTERNAL18,		IN),
+	K210_FUNC(DEBUG0,		OUT),
+	K210_FUNC(DEBUG1,		OUT),
+	K210_FUNC(DEBUG2,		OUT),
+	K210_FUNC(DEBUG3,		OUT),
+	K210_FUNC(DEBUG4,		OUT),
+	K210_FUNC(DEBUG5,		OUT),
+	K210_FUNC(DEBUG6,		OUT),
+	K210_FUNC(DEBUG7,		OUT),
+	K210_FUNC(DEBUG8,		OUT),
+	K210_FUNC(DEBUG9,		OUT),
+	K210_FUNC(DEBUG10,		OUT),
+	K210_FUNC(DEBUG11,		OUT),
+	K210_FUNC(DEBUG12,		OUT),
+	K210_FUNC(DEBUG13,		OUT),
+	K210_FUNC(DEBUG14,		OUT),
+	K210_FUNC(DEBUG15,		OUT),
+	K210_FUNC(DEBUG16,		OUT),
+	K210_FUNC(DEBUG17,		OUT),
+	K210_FUNC(DEBUG18,		OUT),
+	K210_FUNC(DEBUG19,		OUT),
+	K210_FUNC(DEBUG20,		OUT),
+	K210_FUNC(DEBUG21,		OUT),
+	K210_FUNC(DEBUG22,		OUT),
+	K210_FUNC(DEBUG23,		OUT),
+	K210_FUNC(DEBUG24,		OUT),
+	K210_FUNC(DEBUG25,		OUT),
+	K210_FUNC(DEBUG26,		OUT),
+	K210_FUNC(DEBUG27,		OUT),
+	K210_FUNC(DEBUG28,		OUT),
+	K210_FUNC(DEBUG29,		OUT),
+	K210_FUNC(DEBUG30,		OUT),
+	K210_FUNC(DEBUG31,		OUT),
+};
+
+#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
+#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
+
+static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
+	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
+	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
+};
+
+/*
+ * Max drive strength in uA.
+ */
+static const int k210_pinconf_drive_strength[] = {
+	[0] = 11200,
+	[1] = 16800,
+	[2] = 22300,
+	[3] = 27800,
+	[4] = 33300,
+	[5] = 38700,
+	[6] = 44100,
+	[7] = 49500,
+};
+
+static int k210_pinconf_get_drive(unsigned int max_strength_ua)
+{
+	int i;
+
+	for (i = K210_PC_DRIVE_MAX; i; i--) {
+		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
+					 u32 pin, u32 func)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	const struct k210_pcf_info *info = &k210_pcf_infos[func];
+	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
+	u32 val = func | mode;
+
+	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
+		pin, info->name, func, val);
+
+	writel(val, &pdata->fpioa->pins[pin]);
+}
+
+static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
+				  unsigned int pin,
+				  unsigned int param, unsigned int arg)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	u32 val = readl(&pdata->fpioa->pins[pin]);
+	int drive;
+
+	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
+		pin, param, arg);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		val &= ~K210_PC_BIAS_MASK;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		arg *= 1000;
+		fallthrough;
+	case PIN_CONFIG_DRIVE_STRENGTH_UA:
+		drive = k210_pinconf_get_drive(arg);
+		if (drive < 0)
+			return drive;
+		val &= ~K210_PC_DRIVE_MASK;
+		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_IE;
+		else
+			val &= ~K210_PC_IE;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		if (arg)
+			val |= K210_PC_ST;
+		else
+			val &= ~K210_PC_ST;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
+		val = readl(&pdata->fpioa->pins[pin]);
+		val |= K210_PC_MODE_OUT;
+		if (!arg)
+			val |= K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_OE;
+		else
+			val &= ~K210_PC_OE;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		if (arg)
+			val |= K210_PC_SL;
+		else
+			val &= ~K210_PC_SL;
+		break;
+	case PIN_CONFIG_OUTPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DO_INV;
+		else
+			val &= ~K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_INPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DI_INV;
+		else
+			val &= ~K210_PC_DI_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(val, &pdata->fpioa->pins[pin]);
+
+	return 0;
+}
+
+static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *configs, unsigned int num_configs)
+{
+	unsigned int param, arg;
+	int i, ret;
+
+	if (WARN_ON(pin >= K210_NPINS))
+		return -EINVAL;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				  struct seq_file *s, unsigned int pin)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
+}
+
+static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
+				  unsigned int selector, unsigned long *configs,
+				  unsigned int num_configs)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int param, arg;
+	u32 bit;
+	int i;
+
+	/* Pins should be configured with pinmux, not groups*/
+	if (selector < K210_NPINS)
+		return -EINVAL;
+
+	/* Otherwise it's a power domain */
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		if (param != PIN_CONFIG_POWER_SOURCE)
+			return -EINVAL;
+
+		arg = pinconf_to_config_argument(configs[i]);
+		bit = BIT(selector - K210_NPINS);
+		regmap_update_bits(pdata->sysctl_map,
+				   pdata->power_offset,
+				   bit, arg ? bit : 0);
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned int selector)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int ret;
+	u32 val;
+
+	if (selector < K210_NPINS)
+		return k210_pinconf_dbg_show(pctldev, s, selector);
+
+	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
+	if (ret) {
+		dev_err(pdata->dev, "Failed to read power reg\n");
+		return;
+	}
+
+	seq_printf(s, "%s: %s V", k210_group_names[selector],
+		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
+}
+
+static const struct pinconf_ops k210_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_set = k210_pinconf_set,
+	.pin_config_group_set = k210_pinconf_group_set,
+	.pin_config_dbg_show = k210_pinconf_dbg_show,
+	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
+};
+
+static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(k210_pcf_infos);
+}
+
+static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
+						 unsigned int selector)
+{
+	return k210_pcf_infos[selector].name;
+}
+
+static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+					   unsigned int selector,
+					   const char * const **groups,
+					   unsigned int * const num_groups)
+{
+	/* Any function can be mapped to any pin */
+	*groups = k210_group_names;
+	*num_groups = K210_NPINS;
+
+	return 0;
+}
+
+static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
+			       unsigned int function,
+			       unsigned int group)
+{
+	/* Can't mux power domains */
+	if (group >= K210_NPINS)
+		return -EINVAL;
+
+	k210_pinmux_set_pin_function(pctldev, group, function);
+
+	return 0;
+}
+
+static const struct pinmux_ops k210_pinmux_ops = {
+	.get_functions_count = k210_pinmux_get_function_count,
+	.get_function_name = k210_pinmux_get_function_name,
+	.get_function_groups = k210_pinmux_get_function_groups,
+	.set_mux = k210_pinmux_set_mux,
+	.strict = true,
+};
+
+static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return K210_NGROUPS;
+}
+
+static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+					       unsigned int group)
+{
+	return k210_group_names[group];
+}
+
+static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int group,
+				       const unsigned int **pins,
+				       unsigned int *npins)
+{
+	if (group >= K210_NPINS) {
+		*pins = NULL;
+		*npins = 0;
+		return 0;
+	}
+
+	*pins = &k210_pins[group].number;
+	*npins = 1;
+
+	return 0;
+}
+
+static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s, unsigned int offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+					  struct device_node *np,
+					  struct pinctrl_map **map,
+					  unsigned int *reserved_maps,
+					  unsigned int *num_maps)
+{
+	struct property *prop;
+	const __be32 *p;
+	int ret, pinmux_groups;
+	u32 pinmux_group;
+	unsigned long *configs = NULL;
+	unsigned int num_configs = 0;
+	unsigned int reserve = 0;
+
+	ret = of_property_count_strings(np, "groups");
+	if (!ret)
+		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
+						reserved_maps, num_maps,
+						PIN_MAP_TYPE_CONFIGS_GROUP);
+
+	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
+	if (pinmux_groups <= 0) {
+		/* Ignore this node */
+		return 0;
+	}
+
+	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+					      &num_configs);
+	if (ret < 0) {
+		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
+			np);
+		return ret;
+	}
+
+	reserve = pinmux_groups * (1 + num_configs);
+	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
+					reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
+		const char *group_name, *func_name;
+		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
+		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
+
+		if (pin >= K210_NPINS) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		group_name = k210_group_names[pin];
+		func_name = k210_pcf_infos[func].name;
+
+		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
+			np->name, pin, func_name);
+
+		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
+						num_maps, group_name,
+						func_name);
+		if (ret < 0) {
+			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
+				np, ret);
+			goto exit;
+		}
+
+		if (num_configs) {
+			ret = pinctrl_utils_add_map_configs(pctldev, map,
+					reserved_maps, num_maps, group_name,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_PIN);
+			if (ret < 0) {
+				dev_err(pctldev->dev,
+					"%pOF add configs map failed %d\n",
+					np, ret);
+				goto exit;
+			}
+		}
+	}
+
+	ret = 0;
+
+exit:
+	kfree(configs);
+	return ret;
+}
+
+static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				       struct device_node *np_config,
+				       struct pinctrl_map **map,
+				       unsigned int *num_maps)
+{
+	unsigned int reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
+					     &reserved_maps, num_maps);
+	if (ret < 0)
+		goto err;
+
+	for_each_available_child_of_node(np_config, np) {
+		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
+						     &reserved_maps, num_maps);
+		if (ret < 0)
+			goto err;
+	}
+	return 0;
+
+err:
+	pinctrl_utils_free_map(pctldev, *map, *num_maps);
+	return ret;
+}
+
+
+static const struct pinctrl_ops k210_pinctrl_ops = {
+	.get_groups_count = k210_pinctrl_get_groups_count,
+	.get_group_name = k210_pinctrl_get_group_name,
+	.get_group_pins = k210_pinctrl_get_group_pins,
+	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
+	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static struct pinctrl_desc k210_pinctrl_desc = {
+	.name = "k210-pinctrl",
+	.pins = k210_pins,
+	.npins = K210_NPINS,
+	.pctlops = &k210_pinctrl_ops,
+	.pmxops = &k210_pinmux_ops,
+	.confops = &k210_pinconf_ops,
+	.custom_params = k210_pinconf_custom_params,
+	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
+};
+
+static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
+{
+	struct k210_fpioa __iomem *fpioa = pdata->fpioa;
+	u32 val;
+	int i, j;
+
+	dev_dbg(pdata->dev, "Init pin ties\n");
+
+	/* Init pin functions input ties */
+	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
+		val = 0;
+		for (j = 0; j < 32; j++) {
+			if (k210_pcf_infos[i * 32 + j].mode_id ==
+			    K210_PC_DEFAULT_IN_TIE) {
+				dev_dbg(pdata->dev,
+					"tie_en function %d (%s)\n",
+					i * 32 + j,
+					k210_pcf_infos[i * 32 + j].name);
+				val |= BIT(j);
+			}
+		}
+
+		/* Set value before enable */
+		writel(val, &fpioa->tie_val[i]);
+		writel(val, &fpioa->tie_en[i]);
+	}
+}
+
+static int k210_fpioa_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct k210_fpioa_data *pdata;
+	int ret;
+
+	dev_info(dev, "K210 FPIOA pin controller\n");
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = dev;
+	platform_set_drvdata(pdev, pdata);
+
+	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pdata->fpioa))
+		return PTR_ERR(pdata->fpioa);
+
+	pdata->clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(pdata->clk))
+		return PTR_ERR(pdata->clk);
+
+	ret = clk_prepare_enable(pdata->clk);
+	if (ret)
+		return ret;
+
+	pdata->pclk = devm_clk_get_optional(dev, "pclk");
+	if (!IS_ERR(pdata->pclk))
+		clk_prepare_enable(pdata->pclk);
+
+	pdata->sysctl_map =
+		syscon_regmap_lookup_by_phandle_args(np,
+						"canaan,k210-sysctl-power",
+						1, &pdata->power_offset);
+	if (IS_ERR(pdata->sysctl_map))
+		return PTR_ERR(pdata->sysctl_map);
+
+	k210_fpioa_init_ties(pdata);
+
+	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
+	if (IS_ERR(pdata->pctl))
+		return PTR_ERR(pdata->pctl);
+
+	return 0;
+}
+
+static const struct of_device_id k210_fpioa_dt_ids[] = {
+	{ .compatible = "canaan,k210-fpioa" },
+	{ /* sentinel */ },
+};
+
+static struct platform_driver k210_fpioa_driver = {
+	.probe	= k210_fpioa_probe,
+	.driver = {
+		.name		= "k210-fpioa",
+		.of_match_table	= k210_fpioa_dt_ids,
+	},
+};
+builtin_platform_driver(k210_fpioa_driver);
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 01/10] clk: Add RISC-V Canaan Kendryte K210 clock driver Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-14 23:32   ` Palmer Dabbelt
  2021-01-12  0:58 ` [PATCH v11 04/10] riscv: Add SiPeed MAIX BiT board " Damien Le Moal
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Update the Canaan Kendryte K210 base device tree k210.dtsi to define
all peripherals of the SoC, their clocks and reset lines. The device
tree file k210.dts is renamed to k210_generic.dts and becomes the
default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
configuration option. No device beside the serial console is defined by
this device tree. This makes this generic device tree suitable for use
with a builtin initramfs with all known K210 based boards.

These changes result in the K210_CLK_ACLK clock ID to be unused and
removed from the dt-bindings k210-clk.h header file.

Most updates to the k210.dtsi file come from Sean Anderson's work on
U-Boot support for the K210.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 arch/riscv/Kconfig.socs                     |   2 +-
 arch/riscv/boot/dts/canaan/k210.dts         |  23 -
 arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
 arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
 include/dt-bindings/clock/k210-clk.h        |   1 -
 5 files changed, 573 insertions(+), 50 deletions(-)
 delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
 create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 6402746c68f3..7efcece8896c 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -51,7 +51,7 @@ config SOC_CANAAN_K210_DTB_SOURCE
 	string "Source file for the Canaan Kendryte K210 builtin DTB"
 	depends on SOC_CANAAN
 	depends on SOC_CANAAN_K210_DTB_BUILTIN
-	default "k210"
+	default "k210_generic"
 	help
 	  Base name (without suffix, relative to arch/riscv/boot/dts/canaan)
 	  for the DTS file that will be used to produce the DTB linked into the
diff --git a/arch/riscv/boot/dts/canaan/k210.dts b/arch/riscv/boot/dts/canaan/k210.dts
deleted file mode 100644
index 0d1f28fce6b2..000000000000
--- a/arch/riscv/boot/dts/canaan/k210.dts
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2020 Western Digital Corporation or its affiliates.
- */
-
-/dts-v1/;
-
-#include "k210.dtsi"
-
-/ {
-	model = "Kendryte K210 generic";
-	compatible = "kendryte,k210";
-
-	chosen {
-		bootargs = "earlycon console=ttySIF0";
-		stdout-path = "serial0";
-	};
-};
-
-&uarths0 {
-	status = "okay";
-};
-
diff --git a/arch/riscv/boot/dts/canaan/k210.dtsi b/arch/riscv/boot/dts/canaan/k210.dtsi
index 354b263195a3..196096eedd73 100644
--- a/arch/riscv/boot/dts/canaan/k210.dtsi
+++ b/arch/riscv/boot/dts/canaan/k210.dtsi
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  */
 #include <dt-bindings/clock/k210-clk.h>
+#include <dt-bindings/pinctrl/k210-fpioa.h>
+#include <dt-bindings/reset/k210-rst.h>
 
 / {
 	/*
@@ -12,10 +14,29 @@ / {
 	 */
 	#address-cells = <1>;
 	#size-cells = <1>;
-	compatible = "kendryte,k210";
+	compatible = "canaan,kendryte-k210";
 
 	aliases {
+		cpu0 = &cpu0;
+		cpu1 = &cpu1;
+		dma0 = &dmac0;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1_0;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		pinctrl0 = &fpioa;
 		serial0 = &uarths0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		timer0 = &timer0;
+		timer1 = &timer1;
+		timer2 = &timer2;
 	};
 
 	/*
@@ -30,14 +51,14 @@ cpus {
 		timebase-frequency = <7800000>;
 		cpu0: cpu@0 {
 			device_type = "cpu";
+			compatible = "canaan,k210", "sifive,rocket0", "riscv";
 			reg = <0>;
-			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
+			d-cache-size = <0x8000>;
 			cpu0_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -46,14 +67,14 @@ cpu0_intc: interrupt-controller {
 		};
 		cpu1: cpu@1 {
 			device_type = "cpu";
+			compatible = "canaan,k210", "sifive,rocket0", "riscv";
 			reg = <1>;
-			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
+			d-cache-size = <0x8000>;
 			cpu1_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -64,10 +85,15 @@ cpu1_intc: interrupt-controller {
 
 	sram: memory@80000000 {
 		device_type = "memory";
+		compatible = "canaan,k210-sram";
 		reg = <0x80000000 0x400000>,
 		      <0x80400000 0x200000>,
 		      <0x80600000 0x200000>;
 		reg-names = "sram0", "sram1", "aisram";
+		clocks = <&sysclk K210_CLK_SRAM0>,
+			 <&sysclk K210_CLK_SRAM1>,
+			 <&sysclk K210_CLK_AI>;
+		clock-names = "sram0", "sram1", "aisram";
 	};
 
 	clocks {
@@ -81,40 +107,515 @@ in0: oscillator {
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "kendryte,k210-soc", "simple-bus";
+		compatible = "canaan,k210-soc", "simple-bus";
 		ranges;
 		interrupt-parent = <&plic0>;
 
-		sysctl: sysctl@50440000 {
-			compatible = "kendryte,k210-sysctl", "simple-mfd";
-			reg = <0x50440000 0x1000>;
-			#clock-cells = <1>;
+		debug0: debug@0 {
+			compatible = "canaan,k210-debug", "riscv,debug";
+			reg = <0x0 0x1000>;
+			status = "disabled";
+		};
+
+		rom0: nvmem@1000 {
+			reg = <0x1000 0x1000>;
+			read-only;
+			status = "disabled";
 		};
 
 		clint0: clint@2000000 {
 			#interrupt-cells = <1>;
-			compatible = "riscv,clint0";
+			compatible = "canaan,k210-clint", "riscv,clint0";
 			reg = <0x2000000 0xC000>;
-			interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
-						&cpu1_intc 3 &cpu1_intc 7>;
+			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
+					      <&cpu1_intc 3>, <&cpu1_intc 7>;
 		};
 
-		plic0: interrupt-controller@c000000 {
+		plic0: interrupt-controller@C000000 {
 			#interrupt-cells = <1>;
-			interrupt-controller;
-			compatible = "kendryte,k210-plic0", "riscv,plic0";
+			compatible = "canaan,k210-plic", "riscv,plic0";
 			reg = <0xC000000 0x4000000>;
-			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 0xffffffff>,
-					      <&cpu1_intc 11>, <&cpu1_intc 0xffffffff>;
+			interrupt-controller;
+			interrupts-extended = <&cpu0_intc 11>,
+					      <&cpu1_intc 11>;
 			riscv,ndev = <65>;
 			riscv,max-priority = <7>;
 		};
 
 		uarths0: serial@38000000 {
-			compatible = "kendryte,k210-uarths", "sifive,uart0";
+			compatible = "canaan,k210-uarths", "sifive,uart0";
 			reg = <0x38000000 0x1000>;
 			interrupts = <33>;
-			clocks = <&sysctl K210_CLK_CPU>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			status = "disabled";
+		};
+
+		gpio0: gpio-controller@38001000 {
+			#interrupt-cells = <2>;
+			#gpio-cells = <2>;
+			compatible = "canaan,k210-gpiohs", "sifive,gpio0";
+			reg = <0x38001000 0x1000>;
+			interrupt-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>;
+			gpio-controller;
+			ngpios = <32>;
+			status = "disabled";
+		};
+
+		kpu0: kpu@40800000 {
+			compatible = "canaan,k210-kpu";
+			reg = <0x40800000 0xc00000>;
+			interrupts = <25>;
+			clocks = <&sysclk K210_CLK_AI>;
+			status = "disabled";
+		};
+
+		fft0: fft@42000000 {
+			compatible = "canaan,k210-fft";
+			reg = <0x42000000 0x400000>;
+			interrupts = <26>;
+			clocks = <&sysclk K210_CLK_FFT>;
+			resets = <&sysrst K210_RST_FFT>;
+			status = "disabled";
+		};
+
+		dmac0: dma-controller@50000000 {
+			compatible = "canaan,k210-dmac", "snps,axi-dma-1.01a";
+			reg = <0x50000000 0x1000>;
+			interrupts = <27 28 29 30 31 32>;
+			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
+			clock-names = "core-clk", "cfgr-clk";
+			resets = <&sysrst K210_RST_DMA>;
+			dma-channels = <6>;
+			snps,dma-masters = <2>;
+			snps,priority = <0 1 2 3 4 5>;
+			snps,data-width = <5>;
+			snps,block-size = <0x200000 0x200000 0x200000
+					   0x200000 0x200000 0x200000>;
+			snps,axi-max-burst-len = <256>;
+			status = "disabled";
+		};
+
+		apb0: bus@50200000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "canaan,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB0>;
+
+			gpio1: gpio-controller@50200000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,k210-gpio",
+					     "snps,dw-apb-gpio";
+				reg = <0x50200000 0x80>;
+				clocks = <&sysclk K210_CLK_APB0>,
+					 <&sysclk K210_CLK_GPIO>;
+				clock-names = "bus", "db";
+				resets = <&sysrst K210_RST_GPIO>;
+				status = "disabled";
+
+				gpio1_0: gpio1@0 {
+					#gpio-cells = <2>;
+					#interrupt-cells = <2>;
+					compatible = "snps,dw-apb-gpio-port";
+					reg = <0>;
+					interrupt-controller;
+					interrupts = <23>;
+					gpio-controller;
+					ngpios = <8>;
+				};
+			};
+
+			uart1: serial@50210000 {
+				compatible = "canaan,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50210000 0x100>;
+				interrupts = <11>;
+				clocks = <&sysclk K210_CLK_UART1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART1>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart2: serial@50220000 {
+				compatible = "canaan,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50220000 0x100>;
+				interrupts = <12>;
+				clocks = <&sysclk K210_CLK_UART2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART2>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart3: serial@50230000 {
+				compatible = "canaan,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50230000 0x100>;
+				interrupts = <13>;
+				clocks = <&sysclk K210_CLK_UART3>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART3>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			spi2: spi@50240000 {
+				compatible = "canaan,k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				spi-slave;
+				reg = <0x50240000 0x100>;
+				interrupts = <3>;
+				clocks = <&sysclk K210_CLK_SPI2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI2>;
+				spi-max-frequency = <25000000>;
+				status = "disabled";
+			};
+
+			i2s0: i2s@50250000 {
+				compatible = "canaan,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50250000 0x200>;
+				interrupts = <5>;
+				clocks = <&sysclk K210_CLK_I2S0>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S0>;
+				status = "disabled";
+			};
+
+			apu0: sound@520250200 {
+				compatible = "canaan,k210-apu";
+				reg = <0x50250200 0x200>;
+				status = "disabled";
+			};
+
+			i2s1: i2s@50260000 {
+				compatible = "canaan,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50260000 0x200>;
+				interrupts = <6>;
+				clocks = <&sysclk K210_CLK_I2S1>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S1>;
+				status = "disabled";
+			};
+
+			i2s2: i2s@50270000 {
+				compatible = "canaan,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50270000 0x200>;
+				interrupts = <7>;
+				clocks = <&sysclk K210_CLK_I2S2>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S2>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@50280000 {
+				compatible = "canaan,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50280000 0x100>;
+				interrupts = <8>;
+				clocks = <&sysclk K210_CLK_I2C0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@50290000 {
+				compatible = "canaan,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50290000 0x100>;
+				interrupts = <9>;
+				clocks = <&sysclk K210_CLK_I2C1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C1>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@502A0000 {
+				compatible = "canaan,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x502A0000 0x100>;
+				interrupts = <10>;
+				clocks = <&sysclk K210_CLK_I2C2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C2>;
+				status = "disabled";
+			};
+
+			fpioa: pinmux@502B0000 {
+				compatible = "canaan,k210-fpioa";
+				reg = <0x502B0000 0x100>;
+				clocks = <&sysclk K210_CLK_FPIOA>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_FPIOA>;
+				canaan,k210-sysctl-power = <&sysctl 108>;
+				status = "disabled";
+			};
+
+			sha256: sha256@502C0000 {
+				compatible = "canaan,k210-sha256";
+				reg = <0x502C0000 0x100>;
+				clocks = <&sysclk K210_CLK_SHA>;
+				resets = <&sysrst K210_RST_SHA>;
+				status = "disabled";
+			};
+
+			timer0: timer@502D0000 {
+				compatible = "canaan,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502D0000 0x100>;
+				interrupts = <14 15>;
+				clocks = <&sysclk K210_CLK_TIMER0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER0>;
+				status = "disabled";
+			};
+
+			timer1: timer@502E0000 {
+				compatible = "canaan,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502E0000 0x100>;
+				interrupts = <16 17>;
+				clocks = <&sysclk K210_CLK_TIMER1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER1>;
+				status = "disabled";
+			};
+
+			timer2: timer@502F0000 {
+				compatible = "canaan,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502F0000 0x100>;
+				interrupts = <18 19>;
+				clocks = <&sysclk K210_CLK_TIMER2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER2>;
+				status = "disabled";
+			};
+		};
+
+		apb1: bus@50400000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "canaan,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB1>;
+
+			wdt0: watchdog@50400000 {
+				compatible = "canaan,k210-wdt", "snps,dw-wdt";
+				reg = <0x50400000 0x100>;
+				interrupts = <21>;
+				clocks = <&sysclk K210_CLK_WDT0>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT0>;
+				status = "disabled";
+			};
+
+			wdt1: watchdog@50410000 {
+				compatible = "canaan,k210-wdt", "snps,dw-wdt";
+				reg = <0x50410000 0x100>;
+				interrupts = <22>;
+				clocks = <&sysclk K210_CLK_WDT1>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT1>;
+				status = "disabled";
+			};
+
+			otp0: nvmem@50420000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "canaan,k210-otp";
+				reg = <0x50420000 0x100>,
+				      <0x88000000 0x20000>;
+				reg-names = "reg", "mem";
+				clocks = <&sysclk K210_CLK_ROM>;
+				resets = <&sysrst K210_RST_ROM>;
+				read-only;
+				status = "disabled";
+
+				/* Bootloader */
+				firmware@00000 {
+					reg = <0x00000 0xC200>;
+				};
+
+				/*
+				 * config string as described in RISC-V
+				 * privileged spec 1.9
+				 */
+				config-1-9@1c000 {
+					reg = <0x1C000 0x1000>;
+				};
+
+				/*
+				 * Device tree containing only registers,
+				 * interrupts, and cpus
+				 */
+				fdt@1d000 {
+					reg = <0x1D000 0x2000>;
+				};
+
+				/* CPU/ROM credits */
+				credits@1f000 {
+					reg = <0x1F000 0x1000>;
+				};
+			};
+
+			dvp0: camera@50430000 {
+				compatible = "canaan,k210-dvp";
+				reg = <0x50430000 0x100>;
+				interrupts = <24>;
+				clocks = <&sysclk K210_CLK_DVP>;
+				resets = <&sysrst K210_RST_DVP>;
+				canaan,k210-misc-offset = <&sysctl 84>;
+				status = "disabled";
+			};
+
+			sysctl: syscon@50440000 {
+				compatible = "canaan,k210-sysctl",
+					     "syscon", "simple-mfd";
+				reg = <0x50440000 0x100>;
+				clocks = <&sysclk K210_CLK_APB1>;
+				clock-names = "pclk";
+
+				sysclk: clock-controller {
+					#clock-cells = <1>;
+					compatible = "canaan,k210-clk";
+					clocks = <&in0>;
+				};
+
+				sysrst: reset-controller {
+					compatible = "canaan,k210-rst";
+					#reset-cells = <1>;
+				};
+
+				reboot: syscon-reboot {
+					compatible = "syscon-reboot";
+					regmap = <&sysctl>;
+					offset = <48>;
+					mask = <1>;
+					value = <1>;
+				};
+			};
+
+			aes0: aes@50450000 {
+				compatible = "canaan,k210-aes";
+				reg = <0x50450000 0x100>;
+				clocks = <&sysclk K210_CLK_AES>;
+				resets = <&sysrst K210_RST_AES>;
+				status = "disabled";
+			};
+
+			rtc: rtc@50460000 {
+				compatible = "canaan,k210-rtc";
+				reg = <0x50460000 0x100>;
+				clocks = <&in0>;
+				resets = <&sysrst K210_RST_RTC>;
+				interrupts = <20>;
+				status = "disabled";
+			};
+		};
+
+		apb2: bus@52000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "canaan,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB2>;
+
+			spi0: spi@52000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x52000000 0x100>;
+				interrupts = <1>;
+				clocks = <&sysclk K210_CLK_SPI0>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI0>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi1: spi@53000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x53000000 0x100>;
+				interrupts = <2>;
+				clocks = <&sysclk K210_CLK_SPI1>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI1>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi3: spi@54000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,k210-ssi",
+					     "snps,dwc-ssi-1.01a";
+				reg = <0x54000000 0x200>;
+				interrupts = <4>;
+				clocks = <&sysclk K210_CLK_SPI3>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI3>;
+				reset-names = "spi";
+				/* Could possibly go up to 200 MHz */
+				spi-max-frequency = <100000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
 		};
 	};
 };
diff --git a/arch/riscv/boot/dts/canaan/k210_generic.dts b/arch/riscv/boot/dts/canaan/k210_generic.dts
new file mode 100644
index 000000000000..396c8ca4d24d
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/k210_generic.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte K210 generic";
+	compatible = "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&jtag_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	jtag_pins: jtag-pinmux {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	uarths_pins: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
diff --git a/include/dt-bindings/clock/k210-clk.h b/include/dt-bindings/clock/k210-clk.h
index a48176ad3c23..b2de702cbf75 100644
--- a/include/dt-bindings/clock/k210-clk.h
+++ b/include/dt-bindings/clock/k210-clk.h
@@ -9,7 +9,6 @@
 /*
  * Kendryte K210 SoC clock identifiers (arbitrary values).
  */
-#define K210_CLK_ACLK	0
 #define K210_CLK_CPU	0
 #define K210_CLK_SRAM0	1
 #define K210_CLK_SRAM1	2
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 04/10] riscv: Add SiPeed MAIX BiT board device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (2 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 05/10] riscv: Add SiPeed MAIX DOCK " Damien Le Moal
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the device tree sipeed_maix_bit.dts for the SiPeed MAIX BiT and
MAIX BiTm boards. This device tree enables LEDs, gpio, i2c and spi/mmc
SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 .../riscv/boot/dts/canaan/sipeed_maix_bit.dts | 227 ++++++++++++++++++
 1 file changed, 227 insertions(+)
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts

diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
new file mode 100644
index 000000000000..a5a40f9cf812
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX BiT";
+	compatible = "sipeed,maix-bitm", "sipeed,maix-bit",
+		     "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-names = "default";
+	pinctrl-0 = <&jtag_pinctrl>;
+	status = "okay";
+
+	jtag_pinctrl: jtag-pinmux {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	uarths_pinctrl: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	gpio_pinctrl: gpio-pinmux {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	gpiohs_pinctrl: gpiohs-pinmux {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	i2s0_pinctrl: i2s0-pinmux {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	dvp_pinctrl: dvp-pinmux {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	spi0_pinctrl: spi0-pinmux {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	spi1_pinctrl: spi1-pinmux {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_GPIOHS13)>; /* cs */
+	};
+
+	i2c1_pinctrl: i2c1-pinmux {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&gpiohs_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&gpio_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&i2s0_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pinctrl>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&dvp_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&spi0_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
+		spi-max-frequency = <15000000>;
+		spi-cs-high;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&spi1_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <25000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 05/10] riscv: Add SiPeed MAIX DOCK board device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (3 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 04/10] riscv: Add SiPeed MAIX BiT board " Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 06/10] riscv: Add SiPeed MAIX GO " Damien Le Moal
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the device tree sipeed_maix_dock.dts for the SiPeed MAIX DOCK m1
and m1w boards. This device tree enables LEDs, gpio, i2c and spi/mmc
SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 .../boot/dts/canaan/sipeed_maix_dock.dts      | 229 ++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts

diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
new file mode 100644
index 000000000000..abeaa9bad761
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX Dock";
+	compatible = "sipeed,maix-dock-m1wm", "sipeed,maix-dock-m1",
+		     "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		/*
+		 * Note: the board specification document green on gpio #4,
+		 * red on gpio #5 and blue on gpio #6. However, the board
+		 * is actually wired differently as defined here.
+		 */
+		blue {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		green {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&jtag_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	jtag_pinctrl: jtag-pinmux {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	uarths_pinctrl: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	gpio_pinctrl: gpio-pinmux {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	gpiohs_pinctrl: gpiohs-pinmux {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	i2s0_pinctrl: i2s0-pinmux {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	dvp_pinctrl: dvp-pinmux {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	spi0_pinctrl: spi0-pinmux {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	spi1_pinctrl: spi1-pinmux {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_GPIOHS13)>; /* cs */
+	};
+
+	i2c1_pinctrl: i2c1-pinmux {
+		pinmux = <K210_FPIOA(9, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&gpiohs_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&gpio_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&i2s0_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pinctrl>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&dvp_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&spi0_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&spi1_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <25000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 06/10] riscv: Add SiPeed MAIX GO board device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (4 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 05/10] riscv: Add SiPeed MAIX DOCK " Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 07/10] riscv: Add SiPeed MAIXDUINO " Damien Le Moal
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the device tree sipeed_maix_go.dts for the SiPeed MAIX GO board.
This device tree enables buttons, LEDs, gpio, i2c and spi/mmc SD card
devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts | 237 ++++++++++++++++++
 1 file changed, 237 insertions(+)
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts

diff --git a/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
new file mode 100644
index 000000000000..c3294dfaa3c6
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX GO";
+	compatible = "sipeed,maix-go", "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		up {
+			label = "UP";
+			linux,code = <BTN_1>;
+			gpios = <&gpio1_0 7 GPIO_ACTIVE_LOW>;
+		};
+
+		press {
+			label = "PRESS";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		down {
+			label = "DOWN";
+			linux,code = <BTN_2>;
+			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&jtag_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	jtag_pinctrl: jtag-pinmux {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	uarths_pinctrl: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	gpio_pinctrl: gpio-pinmux {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	gpiohs_pinctrl: gpiohs-pinmux {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	i2s0_pinctrl: i2s0-pinmux {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	dvp_pinctrl: dvp-pinmux {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	spi0_pinctrl: spi0-pinmux {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	spi1_pinctrl: spi1-pinmux {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_GPIOHS13)>; /* cs */
+	};
+
+	i2c1_pinctrl: i2c1-pinmux {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&gpiohs_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&gpio_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&i2s0_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pinctrl>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&dvp_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&spi0_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&spi1_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <25000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 07/10] riscv: Add SiPeed MAIXDUINO board device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (5 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 06/10] riscv: Add SiPeed MAIX GO " Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 08/10] riscv: Add Kendryte KD233 " Damien Le Moal
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the device tree sipeed_maixduino.dts for the SiPeed MAIXDUINO board.
This device tree enables LEDs and spi/mmc SD card device. Additionally,
gpios and i2c are also enabled and mapped to the board header pins as
indicated on the board itself.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 .../boot/dts/canaan/sipeed_maixduino.dts      | 201 ++++++++++++++++++
 1 file changed, 201 insertions(+)
 create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maixduino.dts

diff --git a/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
new file mode 100644
index 000000000000..681f12b46894
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIXDUINO";
+	compatible = "sipeed,maixduino", "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	status = "okay";
+
+	uarths_pinctrl: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
+	};
+
+	gpio_pinctrl: gpio-pinmux {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>;
+	};
+
+	gpiohs_pinctrl: gpiohs-pinmux {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,  /* BOOT */
+			 <K210_FPIOA(21, K210_PCF_GPIOHS2)>,  /* Header "2" */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS3)>,  /* Header "3" */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS4)>,  /* Header "4" */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS5)>,  /* Header "5" */
+			 <K210_FPIOA(32, K210_PCF_GPIOHS6)>,  /* Header "6" */
+			 <K210_FPIOA(15, K210_PCF_GPIOHS7)>,  /* Header "7" */
+			 <K210_FPIOA(14, K210_PCF_GPIOHS8)>,  /* Header "8" */
+			 <K210_FPIOA(13, K210_PCF_GPIOHS9)>,  /* Header "9" */
+			 <K210_FPIOA(12, K210_PCF_GPIOHS10)>, /* Header "10" */
+			 <K210_FPIOA(11, K210_PCF_GPIOHS11)>, /* Header "11" */
+			 <K210_FPIOA(10, K210_PCF_GPIOHS12)>, /* Header "12" */
+			 <K210_FPIOA(3,  K210_PCF_GPIOHS13)>; /* Header "13" */
+	};
+
+	i2s0_pinctrl: i2s0-pinmux {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	spi1_pinctrl: spi1-pinmux {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_GPIO2)>; /* cs */
+	};
+
+	i2c1_pinctrl: i2c1-pinmux {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>, /* Header "scl" */
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;  /* Header "sda" */
+	};
+
+	i2s1_pinctrl: i2s1-pinmux {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S1_WS)>,
+			 <K210_FPIOA(34, K210_PCF_I2S1_IN_D0)>,
+			 <K210_FPIOA(35, K210_PCF_I2S1_SCLK)>;
+	};
+
+	spi0_pinctrl: spi0-pinmux {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	dvp_pinctrl: dvp-pinmux {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&gpiohs_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&gpio_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&i2s0_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pinctrl>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&dvp_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&spi0_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&spi1_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio1_0 2 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <25000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 08/10] riscv: Add Kendryte KD233 board device tree
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (6 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 07/10] riscv: Add SiPeed MAIXDUINO " Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 09/10] riscv: Update Canaan Kendryte K210 defconfig Damien Le Moal
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Add the device tree canaan_kd233.dts for the Canaan Kendryte KD233
development board.  This device tree enables LEDs, some gpios and
spi/mmc SD card device. The WS2812B RGB LED and the 10 positions rotary
dip switch present on the board are left undefined.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 arch/riscv/boot/dts/canaan/canaan_kd233.dts | 178 ++++++++++++++++++++
 1 file changed, 178 insertions(+)
 create mode 100644 arch/riscv/boot/dts/canaan/canaan_kd233.dts

diff --git a/arch/riscv/boot/dts/canaan/canaan_kd233.dts b/arch/riscv/boot/dts/canaan/canaan_kd233.dts
new file mode 100644
index 000000000000..44852a27df93
--- /dev/null
+++ b/arch/riscv/boot/dts/canaan/canaan_kd233.dts
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte KD233";
+	compatible = "canaan,kendryte-kd233",
+		     "canaan,kendryte-k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led1 {
+			gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		key0 {
+			label = "KEY0";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&jtag_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	jtag_pinctrl: jtag-pinmux {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	uarths_pinctrl: uarths-pinmux {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	spi0_pinctrl: spi0-pinmux {
+		pinmux = <K210_FPIOA(6, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(7, K210_PCF_SPI0_SCLK)>, /* wr */
+			 <K210_FPIOA(8, K210_PCF_GPIOHS21)>;  /* dc */
+	};
+
+	dvp_pinctrl: dvp-pinmux {
+		pinmux = <K210_FPIOA(9, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(11, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(12, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(13, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(14, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(15, K210_PCF_DVP_PCLK)>,
+			 <K210_FPIOA(17, K210_PCF_DVP_HSYNC)>;
+	};
+
+	gpiohs_pinctrl: gpiohs-pinmux {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(20, K210_PCF_GPIOHS4)>, /* Rot. dip sw line 8 */
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>, /* Rot. dip sw line 4 */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>, /* Rot. dip sw line 2 */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>, /* Rot. dip sw line 1 */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(26, K210_PCF_GPIOHS10)>;
+	};
+
+	spi1_pinctrl: spi1-pinmux {
+		pinmux = <K210_FPIOA(29, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(30, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(31, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>; /* cs */
+	};
+
+	i2s0_pinctrl: i2s0-pinmux {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S0_IN_D0)>,
+			 <K210_FPIOA(34, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(35, K210_PCF_I2S0_SCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&uarths_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&gpiohs_pinctrl>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&i2s0_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&dvp0 {
+	pinctrl-0 = <&dvp_pinctrl>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&spi0_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+
+	panel@0 {
+		compatible = "ilitek,ili9341";
+		reg = <0>;
+		dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&spi1_pinctrl>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <25000000>;
+		broken-cd;
+	};
+};
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 09/10] riscv: Update Canaan Kendryte K210 defconfig
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (7 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 08/10] riscv: Add Kendryte KD233 " Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 10/10] riscv: Add Canaan Kendryte K210 SD card defconfig Damien Le Moal
  2021-01-12  1:07   ` Damien Le Moal
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

Update the Kendryte k210 nommu default configuration file
(nommu_k210_defconfig) to include device drivers for reset, reboot,
I2C, SPI, gpio and LEDs support. Virtual Terminal support is also
disabled as no terminal devices are supported and enabled. Disabling
CONFIG_VT (removing the no longer needed override for
CONFIG_VGA_CONSOLE) reduces the kernel image size by about 65 KB.

This default configuration remains suitable for a system using an
initramfs cpio file linked into the kernel image.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 arch/riscv/configs/nommu_k210_defconfig | 44 ++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig
index 368a28cf1467..b16a2a12c82a 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -1,17 +1,19 @@
 # CONFIG_CPU_ISOLATION is not set
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=13
 CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_FORCE=y
+# CONFIG_RD_GZIP is not set
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
 # CONFIG_RD_XZ is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
+# CONFIG_RD_ZSTD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSFS_SYSCALL is not set
 # CONFIG_FHANDLE is not set
 # CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_SIGNALFD is not set
 # CONFIG_TIMERFD is not set
@@ -25,15 +27,17 @@ CONFIG_EMBEDDED=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLOB=y
-# CONFIG_SLAB_MERGE_DEFAULT is not set
 # CONFIG_MMU is not set
 CONFIG_SOC_CANAAN=y
+CONFIG_SOC_CANAAN_K210_DTB_SOURCE="k210_generic"
 CONFIG_MAXPHYSMEM_2GB=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_CMDLINE="earlycon console=ttySIF0"
 CONFIG_CMDLINE_FORCE=y
-CONFIG_JUMP_LABEL=y
+# CONFIG_SECCOMP is not set
+# CONFIG_STACKPROTECTOR is not set
+# CONFIG_GCC_PLUGINS is not set
 # CONFIG_BLOCK is not set
 CONFIG_BINFMT_FLAT=y
 # CONFIG_COREDUMP is not set
@@ -41,23 +45,47 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_ALLOW_DEV_COREDUMP is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_LDISC_AUTOLOAD is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_DEVMEM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+# CONFIG_SPI_MEM is not set
+CONFIG_SPI_DESIGNWARE=y
+CONFIG_SPI_DW_MMIO=y
+# CONFIG_GPIO_CDEV_V1 is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_USER=y
 # CONFIG_VIRTIO_MENU is not set
+# CONFIG_VHOST_MENU is not set
+# CONFIG_SURFACE_PLATFORMS is not set
+# CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_LSM="[]"
 CONFIG_PRINTK_TIME=y
+# CONFIG_SYMBOLIC_ERRNAME is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_DEBUG_MISC is not set
 CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v11 10/10] riscv: Add Canaan Kendryte K210 SD card defconfig
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
                   ` (8 preceding siblings ...)
  2021-01-12  0:58 ` [PATCH v11 09/10] riscv: Update Canaan Kendryte K210 defconfig Damien Le Moal
@ 2021-01-12  0:58 ` Damien Le Moal
  2021-01-12  1:07   ` Damien Le Moal
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  0:58 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv; +Cc: Sean Anderson

The nommu_k210_defconfig default configuration allows booting a Canaan
Kendryte K210 SoC based boards using an embedded intramfs cpio file.
Modifying this configuration to enable support for the board SD card is
not trivial for all users. To help beginners getting started with these
boards, add the nommu_k210_sdcard_defconfig default configuration file
to set all configuration options necessary to use the board mmc-spi sd
card for the root file system.

This new configuration adds support for the block layer, the mmc-spi
driver and modifies the boot options to specify the rootfs device as
mmcblk0p1 (first partition of the sd card block device). The ext2 file
system is selected by default to encourage its use as that results in
only about 4KB added to the kernel image size. As ext2 does not have
journaling, the boot options specify a read-only mount of the file
system. Similarly to the smaller nommu_k210_defconfig, this new default
configuration disables virtual terminal support to reduce the kernel
image size.

The default device tree selected is unchanged, specifying the simple
"k210_generic" device tree file. The user must change this setting to
specify the device tree suitable for the board being used
(sipeed_maix_bit, sipeed_maix_dock, sipeed_maix_go, sipeed_maixduino or
canaan_kd233).

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
---
 .../riscv/configs/nommu_k210_sdcard_defconfig | 92 +++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 arch/riscv/configs/nommu_k210_sdcard_defconfig

diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig
new file mode 100644
index 000000000000..61f887f65419
--- /dev/null
+++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig
@@ -0,0 +1,92 @@
+# CONFIG_CPU_ISOLATION is not set
+CONFIG_LOG_BUF_SHIFT=13
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_SYSFS_SYSCALL is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_IO_URING is not set
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_MEMBARRIER is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLOB=y
+# CONFIG_MMU is not set
+CONFIG_SOC_CANAAN=y
+CONFIG_SOC_CANAAN_K210_DTB_SOURCE="k210_generic"
+CONFIG_MAXPHYSMEM_2GB=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_CMDLINE="earlycon console=ttySIF0 rootdelay=2 root=/dev/mmcblk0p1 ro"
+CONFIG_CMDLINE_FORCE=y
+# CONFIG_SECCOMP is not set
+# CONFIG_STACKPROTECTOR is not set
+# CONFIG_GCC_PLUGINS is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
+CONFIG_BINFMT_FLAT=y
+# CONFIG_COREDUMP is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_LDISC_AUTOLOAD is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_DEVMEM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+# CONFIG_SPI_MEM is not set
+CONFIG_SPI_DESIGNWARE=y
+CONFIG_SPI_DW_MMIO=y
+# CONFIG_GPIO_CDEV_V1 is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_PWRSEQ_EMMC is not set
+# CONFIG_PWRSEQ_SIMPLE is not set
+CONFIG_MMC_SPI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_USER=y
+# CONFIG_VIRTIO_MENU is not set
+# CONFIG_VHOST_MENU is not set
+# CONFIG_SURFACE_PLATFORMS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_LSM="[]"
+CONFIG_PRINTK_TIME=y
+# CONFIG_SYMBOLIC_ERRNAME is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_DEBUG_MISC is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
-- 
2.29.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 00/10] RISC-V Kendryte K210 support improvements
  2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
@ 2021-01-12  1:07   ` Damien Le Moal
  2021-01-12  0:58 ` [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Damien Le Moal
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  1:07 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv
  Cc: Sean Anderson, Stephen Boyd, linux-clk, Linus Walleij, linux-gpio

On 2021/01/12 9:58, Damien Le Moal wrote:
> This series of patches improves support for boards based on the Canaan
> Kendryte K210 RISC-V dual core SoC. Minimal support for this SoC is
> already included in the kernel. These patches complete it, enabling
> support for most peripherals present on the SoC as well as introducing
> device trees for the various K210 boards available on the market today
> from SiPeed and Kendryte.
> 
> The patches here are the remaining patches of the series not applied
> yet. Patch 1 adds the SoC clock driver and patch 2 adds the pinctrl
> driver.

I screwed up with my git-send-email setup and patch 1 and 2 went only to Palmer
and the riscv list. I resent these eparately to Stephen/linux-clk and
Linus/linux-gpio respectively (suppress-cc and other related cc&to control
options interactions are a bit obscure to me...).

My apologies for the mess. Please let me know if I should resend correctly the
entire series.

> 
> Patches 3 to 8 update the existing K210 device tree and add new
> device tree files for several K210 based boards: MAIX Bit, MAIXDUINO,
> MAIX Dock and MAIX Go boards from SiPeed and the KD233 development
> board from Canaan.
> 
> Finally the last two patches updates the k210 nommu defconfig to include
> the newly implemented drivers and provide a new default configuration
> file enabling SD card support.
> 
> A lot of the work on the device tree and on the K210 drivers come from
> the work by Sean Anderson for the U-Boot project support of the K210
> SoC. Sean also helped with debugging many aspects of this series.
> 
> A tree with all patches applied is available here:
> https://github.com/damien-lemoal/linux, k210-sysctl-v24 branch.
> A demonstration of this series used on a SiPeed MAIX Dock
> board together with an I2C servo controller can be seen here:
> https://damien-lemoal.github.io/linux-robot-arm/#example
> 
> This tree was used to build userspace busybox environment image that is
> then copied onto an SD card formatted with ext2:
> https://github.com/damien-lemoal/buildroot
> Of note is that running this userspace environment requires a revert of
> commit 2217b982624680d19a80ebb4600d05c8586c4f96 introduced during the
> 5.9 development cycle. Without this revert, execution of the init
> process fails. A problem with the riscv port of elf2flt is suspected but
> not confirmed. I am now starting to investigate this problem.
> 
> Reviews and comments are as always much welcome.
> 
> Changes from v10:
> * Rebased on riscv tree fixes+for-next branches. Patches already applied
>   to these branches were removed from this series.
> * Fixed the clock driver and pinctrl driver patch titles to indicate the
>   correct target sub-components.
> * Applied reviewed-by tags from Anup.
> 
> Changes from v9:
> * Added patch 6 to avoid DTS compilation errors after patch 9 is
>   applied and until patch 16 is applied.
> 
> Changes from v8:
> * Addressed Rob's comments on the sysctl driver bindings documentation
> * Fixed a typo in the fpios driver bindings documentation
> 
> Changes from v7:
> * Removed the __init annotation for the drivers reset, pinctrl and
>   sysctl drivers probe functions as suggested by Geert. Also removed
>   the __refdata annotation for the struct platform_driver variables of
>   these drivers.
> 
> Changes from v6:
> * Annotate struct platform_driver variables with __refdata to avoid
>   section mismatch compilation errors
> * Add empty sentinel entry to of_device_id tables of the sysctl, reset
>   and pinctrl drivers.
> 
> Changes from v5:
> * Addressed Philipp's comment on the reset controller driver
> * Added patch 6 to reduce the size of the clock driver patch
>   (now patch 12).
> 
> Changes from v4:
> * Simplified reset controller driver using of_xlate callback as
>   suggested by Philipp
> * Fixed compilation error when using other configs than one of the
>   nommu_k210 defconfigs.
> * Addressed most clock driver comments from Stephen.
> * Removed CONFIG_GPIO_SYSFS from defconfigs
> * Rebased on 5.10-rc7
> 
> Changes from V3:
> * Add one entry per driver in MAINTAINERS file
> 
> Changes from V2:
> * Add MAINTAINERS file entry for the SoC support, listing myself as
>   maintainer.
> * Removed use of postcore_initcall() for declaring the drivers, using
>   the regular builtin_platform_driver() instead.
> * Fixed fpio pinctrl driver bindings documentation as commented by
>   Geert: removed input-schmitt and added input-schmitt-disable, fixed
>   typo and added input-disable and output-disable.
> * Fixed device tree to have cs-gpios active low, as per the default, as
>   active high necessity was an artifact of the gpio level double
>   inversion bug fixed recently.
> * Removed CONFIG_VT from defconfigs to reduce the kernel image size as
>   suggested by Geert.
> 
> Changes from v1:
> * Improved DT bindings documentation
> * SPI and GPIO patches removed from this series (and being processed
>   directly through the relevant subsystems directly)
> * Improved device trees
> * Various cleanup and improvments of the drivers
> 
> Damien Le Moal (10):
>   clk: Add RISC-V Canaan Kendryte K210 clock driver
>   pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
>   riscv: Update Canaan Kendryte K210 device tree
>   riscv: Add SiPeed MAIX BiT board device tree
>   riscv: Add SiPeed MAIX DOCK board device tree
>   riscv: Add SiPeed MAIX GO board device tree
>   riscv: Add SiPeed MAIXDUINO board device tree
>   riscv: Add Kendryte KD233 board device tree
>   riscv: Update Canaan Kendryte K210 defconfig
>   riscv: Add Canaan Kendryte K210 SD card defconfig
> 
>  MAINTAINERS                                   |    8 +
>  arch/riscv/Kconfig.socs                       |    3 +-
>  arch/riscv/boot/dts/canaan/canaan_kd233.dts   |  178 +++
>  arch/riscv/boot/dts/canaan/k210.dts           |   23 -
>  arch/riscv/boot/dts/canaan/k210.dtsi          |  551 ++++++++-
>  arch/riscv/boot/dts/canaan/k210_generic.dts   |   46 +
>  .../riscv/boot/dts/canaan/sipeed_maix_bit.dts |  227 ++++
>  .../boot/dts/canaan/sipeed_maix_dock.dts      |  229 ++++
>  arch/riscv/boot/dts/canaan/sipeed_maix_go.dts |  237 ++++
>  .../boot/dts/canaan/sipeed_maixduino.dts      |  201 ++++
>  arch/riscv/configs/nommu_k210_defconfig       |   44 +-
>  .../riscv/configs/nommu_k210_sdcard_defconfig |   92 ++
>  drivers/clk/Kconfig                           |    8 +
>  drivers/clk/Makefile                          |    1 +
>  drivers/clk/clk-k210.c                        | 1005 +++++++++++++++++
>  drivers/pinctrl/Kconfig                       |   13 +
>  drivers/pinctrl/Makefile                      |    1 +
>  drivers/pinctrl/pinctrl-k210.c                |  985 ++++++++++++++++
>  drivers/soc/canaan/Kconfig                    |   18 +-
>  drivers/soc/canaan/Makefile                   |    2 +-
>  drivers/soc/canaan/k210-sysctl.c              |  205 +---
>  include/dt-bindings/clock/k210-clk.h          |    1 -
>  include/soc/canaan/k210-sysctl.h              |    2 +
>  23 files changed, 3844 insertions(+), 236 deletions(-)
>  create mode 100644 arch/riscv/boot/dts/canaan/canaan_kd233.dts
>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
>  create mode 100644 arch/riscv/configs/nommu_k210_sdcard_defconfig
>  create mode 100644 drivers/clk/clk-k210.c
>  create mode 100644 drivers/pinctrl/pinctrl-k210.c
> 
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: linux-gpio@vger.kernel.org
> 


-- 
Damien Le Moal
Western Digital Research

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

* Re: [PATCH v11 00/10] RISC-V Kendryte K210 support improvements
@ 2021-01-12  1:07   ` Damien Le Moal
  0 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-12  1:07 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv
  Cc: Stephen Boyd, linux-gpio, Linus Walleij, linux-clk, Sean Anderson

On 2021/01/12 9:58, Damien Le Moal wrote:
> This series of patches improves support for boards based on the Canaan
> Kendryte K210 RISC-V dual core SoC. Minimal support for this SoC is
> already included in the kernel. These patches complete it, enabling
> support for most peripherals present on the SoC as well as introducing
> device trees for the various K210 boards available on the market today
> from SiPeed and Kendryte.
> 
> The patches here are the remaining patches of the series not applied
> yet. Patch 1 adds the SoC clock driver and patch 2 adds the pinctrl
> driver.

I screwed up with my git-send-email setup and patch 1 and 2 went only to Palmer
and the riscv list. I resent these eparately to Stephen/linux-clk and
Linus/linux-gpio respectively (suppress-cc and other related cc&to control
options interactions are a bit obscure to me...).

My apologies for the mess. Please let me know if I should resend correctly the
entire series.

> 
> Patches 3 to 8 update the existing K210 device tree and add new
> device tree files for several K210 based boards: MAIX Bit, MAIXDUINO,
> MAIX Dock and MAIX Go boards from SiPeed and the KD233 development
> board from Canaan.
> 
> Finally the last two patches updates the k210 nommu defconfig to include
> the newly implemented drivers and provide a new default configuration
> file enabling SD card support.
> 
> A lot of the work on the device tree and on the K210 drivers come from
> the work by Sean Anderson for the U-Boot project support of the K210
> SoC. Sean also helped with debugging many aspects of this series.
> 
> A tree with all patches applied is available here:
> https://github.com/damien-lemoal/linux, k210-sysctl-v24 branch.
> A demonstration of this series used on a SiPeed MAIX Dock
> board together with an I2C servo controller can be seen here:
> https://damien-lemoal.github.io/linux-robot-arm/#example
> 
> This tree was used to build userspace busybox environment image that is
> then copied onto an SD card formatted with ext2:
> https://github.com/damien-lemoal/buildroot
> Of note is that running this userspace environment requires a revert of
> commit 2217b982624680d19a80ebb4600d05c8586c4f96 introduced during the
> 5.9 development cycle. Without this revert, execution of the init
> process fails. A problem with the riscv port of elf2flt is suspected but
> not confirmed. I am now starting to investigate this problem.
> 
> Reviews and comments are as always much welcome.
> 
> Changes from v10:
> * Rebased on riscv tree fixes+for-next branches. Patches already applied
>   to these branches were removed from this series.
> * Fixed the clock driver and pinctrl driver patch titles to indicate the
>   correct target sub-components.
> * Applied reviewed-by tags from Anup.
> 
> Changes from v9:
> * Added patch 6 to avoid DTS compilation errors after patch 9 is
>   applied and until patch 16 is applied.
> 
> Changes from v8:
> * Addressed Rob's comments on the sysctl driver bindings documentation
> * Fixed a typo in the fpios driver bindings documentation
> 
> Changes from v7:
> * Removed the __init annotation for the drivers reset, pinctrl and
>   sysctl drivers probe functions as suggested by Geert. Also removed
>   the __refdata annotation for the struct platform_driver variables of
>   these drivers.
> 
> Changes from v6:
> * Annotate struct platform_driver variables with __refdata to avoid
>   section mismatch compilation errors
> * Add empty sentinel entry to of_device_id tables of the sysctl, reset
>   and pinctrl drivers.
> 
> Changes from v5:
> * Addressed Philipp's comment on the reset controller driver
> * Added patch 6 to reduce the size of the clock driver patch
>   (now patch 12).
> 
> Changes from v4:
> * Simplified reset controller driver using of_xlate callback as
>   suggested by Philipp
> * Fixed compilation error when using other configs than one of the
>   nommu_k210 defconfigs.
> * Addressed most clock driver comments from Stephen.
> * Removed CONFIG_GPIO_SYSFS from defconfigs
> * Rebased on 5.10-rc7
> 
> Changes from V3:
> * Add one entry per driver in MAINTAINERS file
> 
> Changes from V2:
> * Add MAINTAINERS file entry for the SoC support, listing myself as
>   maintainer.
> * Removed use of postcore_initcall() for declaring the drivers, using
>   the regular builtin_platform_driver() instead.
> * Fixed fpio pinctrl driver bindings documentation as commented by
>   Geert: removed input-schmitt and added input-schmitt-disable, fixed
>   typo and added input-disable and output-disable.
> * Fixed device tree to have cs-gpios active low, as per the default, as
>   active high necessity was an artifact of the gpio level double
>   inversion bug fixed recently.
> * Removed CONFIG_VT from defconfigs to reduce the kernel image size as
>   suggested by Geert.
> 
> Changes from v1:
> * Improved DT bindings documentation
> * SPI and GPIO patches removed from this series (and being processed
>   directly through the relevant subsystems directly)
> * Improved device trees
> * Various cleanup and improvments of the drivers
> 
> Damien Le Moal (10):
>   clk: Add RISC-V Canaan Kendryte K210 clock driver
>   pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
>   riscv: Update Canaan Kendryte K210 device tree
>   riscv: Add SiPeed MAIX BiT board device tree
>   riscv: Add SiPeed MAIX DOCK board device tree
>   riscv: Add SiPeed MAIX GO board device tree
>   riscv: Add SiPeed MAIXDUINO board device tree
>   riscv: Add Kendryte KD233 board device tree
>   riscv: Update Canaan Kendryte K210 defconfig
>   riscv: Add Canaan Kendryte K210 SD card defconfig
> 
>  MAINTAINERS                                   |    8 +
>  arch/riscv/Kconfig.socs                       |    3 +-
>  arch/riscv/boot/dts/canaan/canaan_kd233.dts   |  178 +++
>  arch/riscv/boot/dts/canaan/k210.dts           |   23 -
>  arch/riscv/boot/dts/canaan/k210.dtsi          |  551 ++++++++-
>  arch/riscv/boot/dts/canaan/k210_generic.dts   |   46 +
>  .../riscv/boot/dts/canaan/sipeed_maix_bit.dts |  227 ++++
>  .../boot/dts/canaan/sipeed_maix_dock.dts      |  229 ++++
>  arch/riscv/boot/dts/canaan/sipeed_maix_go.dts |  237 ++++
>  .../boot/dts/canaan/sipeed_maixduino.dts      |  201 ++++
>  arch/riscv/configs/nommu_k210_defconfig       |   44 +-
>  .../riscv/configs/nommu_k210_sdcard_defconfig |   92 ++
>  drivers/clk/Kconfig                           |    8 +
>  drivers/clk/Makefile                          |    1 +
>  drivers/clk/clk-k210.c                        | 1005 +++++++++++++++++
>  drivers/pinctrl/Kconfig                       |   13 +
>  drivers/pinctrl/Makefile                      |    1 +
>  drivers/pinctrl/pinctrl-k210.c                |  985 ++++++++++++++++
>  drivers/soc/canaan/Kconfig                    |   18 +-
>  drivers/soc/canaan/Makefile                   |    2 +-
>  drivers/soc/canaan/k210-sysctl.c              |  205 +---
>  include/dt-bindings/clock/k210-clk.h          |    1 -
>  include/soc/canaan/k210-sysctl.h              |    2 +
>  23 files changed, 3844 insertions(+), 236 deletions(-)
>  create mode 100644 arch/riscv/boot/dts/canaan/canaan_kd233.dts
>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_bit.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_dock.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maix_go.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/sipeed_maixduino.dts
>  create mode 100644 arch/riscv/configs/nommu_k210_sdcard_defconfig
>  create mode 100644 drivers/clk/clk-k210.c
>  create mode 100644 drivers/pinctrl/pinctrl-k210.c
> 
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: linux-gpio@vger.kernel.org
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-12  0:58 ` [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree Damien Le Moal
@ 2021-01-14 23:32   ` Palmer Dabbelt
       [not found]     ` <9d32abd1-ffb4-a887-a40d-fc173a371d23@gmail.com>
                       ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Palmer Dabbelt @ 2021-01-14 23:32 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, seanga2

On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
> all peripherals of the SoC, their clocks and reset lines. The device
> tree file k210.dts is renamed to k210_generic.dts and becomes the
> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
> configuration option. No device beside the serial console is defined by
> this device tree. This makes this generic device tree suitable for use
> with a builtin initramfs with all known K210 based boards.
>
> These changes result in the K210_CLK_ACLK clock ID to be unused and
> removed from the dt-bindings k210-clk.h header file.
>
> Most updates to the k210.dtsi file come from Sean Anderson's work on
> U-Boot support for the K210.
>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> Reviewed-by: Anup Patel <anup@brainfault.org>
> ---
>  arch/riscv/Kconfig.socs                     |   2 +-
>  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>  include/dt-bindings/clock/k210-clk.h        |   1 -
>  5 files changed, 573 insertions(+), 50 deletions(-)
>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts

[Snipping this to the relevant bits, in case you missed it before.]

> @@ -81,40 +107,515 @@ in0: oscillator {
>  	soc {
>  		#address-cells = <1>;
>  		#size-cells = <1>;
> -		compatible = "kendryte,k210-soc", "simple-bus";
> +		compatible = "canaan,k210-soc", "simple-bus";
>  		ranges;
>  		interrupt-parent = <&plic0>;
>
> -		sysctl: sysctl@50440000 {
> -			compatible = "kendryte,k210-sysctl", "simple-mfd";
> -			reg = <0x50440000 0x1000>;
> -			#clock-cells = <1>;
> +		debug0: debug@0 {
> +			compatible = "canaan,k210-debug", "riscv,debug";

I'm still getting lots of warnings about undocumented DT compatible strings
from checpatch.  Some of them might be in flight, but I don't see many of them
(including both of these debug ones) having been defined anywhere.  We went
through a whole process to sort out the SiFive DT naming conventions, I don't
want to just circumvent that for the Canaan stuff by merging it as-is.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
  2021-01-12  0:58 ` [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Damien Le Moal
@ 2021-01-14 23:32   ` Palmer Dabbelt
  2021-01-15  0:17     ` Damien Le Moal
  0 siblings, 1 reply; 24+ messages in thread
From: Palmer Dabbelt @ 2021-01-14 23:32 UTC (permalink / raw)
  To: linus.walleij; +Cc: Damien Le Moal, linux-riscv, seanga2

On Mon, 11 Jan 2021 16:58:40 PST (-0800), Damien Le Moal wrote:
> Add the pinctrl-k210.c pinctrl driver for the Canaan Kendryte K210
> field programmable IO array (FPIOA) to allow configuring the SoC pin
> functions. The K210 has 48 programmable pins which can take any of 256
> possible functions.
>
> This patch is inspired from the k210 pinctrl driver for the u-boot
> project and contains many direct contributions from Sean Anderson.
>
> The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210
> SOC FPIOA DRIVER" with myself listed as maintainer for this driver.
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: linux-gpio@vger.kernel.org

IDK if something's screwed up on my end, but I don't see these CCs locally.
Lore does have it in the GPIO list, though, so maybe it made it.  Either way,
if I'm going to take this through the RISC-V tree then I'd much prefer to have
at least an Ack.  I'd also be happy to have it go through the GPIO tree, as
this is largely stand-alone -- the DT bindings are on riscv/for-next, but I'd
be happy to split them out into a shared tag or just put them in through your
tree if that's easier.

> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  MAINTAINERS                    |   7 +
>  arch/riscv/Kconfig.socs        |   1 +
>  drivers/pinctrl/Kconfig        |  13 +
>  drivers/pinctrl/Makefile       |   1 +
>  drivers/pinctrl/pinctrl-k210.c | 985 +++++++++++++++++++++++++++++++++
>  5 files changed, 1007 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl-k210.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 637b79eba693..1a7a1e4092e2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3860,6 +3860,13 @@ W:	https://github.com/Cascoda/ca8210-linux.git
>  F:	Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
>  F:	drivers/net/ieee802154/ca8210.c
>
> +CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
> +M:	Damien Le Moal <damien.lemoal@wdc.com>
> +L:	linux-riscv@lists.infradead.org
> +L:	linux-gpio@vger.kernel.org (pinctrl driver)
> +F:	Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
> +F:	drivers/pinctrl/pinctrl-k210.c
> +
>  CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
>  M:	Damien Le Moal <damien.lemoal@wdc.com>
>  L:	linux-kernel@vger.kernel.org
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 57e53219c500..6402746c68f3 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -30,6 +30,7 @@ config SOC_CANAAN
>  	select SERIAL_SIFIVE_CONSOLE if TTY
>  	select SIFIVE_PLIC
>  	select ARCH_HAS_RESET_CONTROLLER
> +	select PINCTRL
>  	help
>  	  This enables support for Canaan Kendryte K210 SoC platform hardware.
>
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index d4b2f2e2ed75..cd437e3cc255 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -394,6 +394,19 @@ config PINCTRL_MICROCHIP_SGPIO
>  	  connect control signals from SFP modules and to act as an
>  	  LED controller.
>
> +config PINCTRL_K210
> +	bool "Pinctrl driver for the Canaan Kendryte K210 SoC"
> +	depends on RISCV && SOC_CANAAN && OF
> +	select GENERIC_PINMUX_FUNCTIONS
> +	select GENERIC_PINCONF
> +	select GPIOLIB
> +	select OF_GPIO
> +	select REGMAP_MMIO
> +	default SOC_CANAAN
> +	help
> +	  Add support for the Canaan Kendryte K210 RISC-V SOC Field
> +	  Programmable IO Array (FPIOA) controller.
> +
>  source "drivers/pinctrl/actions/Kconfig"
>  source "drivers/pinctrl/aspeed/Kconfig"
>  source "drivers/pinctrl/bcm/Kconfig"
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 5bb9bb6cc3ce..152c8fe51726 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
>  obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
>  obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO)	+= pinctrl-microchip-sgpio.o
>  obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
> +obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
>
>  obj-y				+= actions/
>  obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
> diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
> new file mode 100644
> index 000000000000..8a733cf77ba0
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-k210.c
> @@ -0,0 +1,985 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#include <linux/io.h>
> +#include <linux/of_device.h>
> +#include <linux/clk.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/platform_device.h>
> +#include <linux/bitfield.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> +#include <linux/io.h>
> +
> +#include <dt-bindings/pinctrl/k210-fpioa.h>
> +
> +#include "core.h"
> +#include "pinconf.h"
> +#include "pinctrl-utils.h"
> +
> +/*
> + * The K210 only implements 8 drive levels, even though
> + * there is register space for 16
> + */
> +#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
> +#define K210_PC_DRIVE_SHIFT	8
> +#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
> +#define K210_PC_DRIVE_MAX	7
> +#define K210_PC_MODE_MASK	GENMASK(23, 12)
> +
> +/*
> + * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
> + * where FUNCTION_OE is a physical signal from the function.
> + */
> +#define K210_PC_OE		BIT(12) /* Output Enable */
> +#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
> +#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
> +#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
> +#define K210_PC_PU		BIT(16) /* Pull Up */
> +#define K210_PC_PD		BIT(17) /* Pull Down */
> +/* Strong pull up not implemented on K210 */
> +#define K210_PC_SL		BIT(19) /* reduce SLew rate */
> +/* Same semantics as OE above */
> +#define K210_PC_IE		BIT(20) /* Input Enable */
> +#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
> +#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
> +#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
> +#define K210_PC_DI		BIT(31) /* raw Data Input */
> +
> +#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
> +
> +#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
> +#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
> +#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
> +				 K210_PC_OE | K210_PC_PU)
> +#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
> +				 K210_PC_OE_INV | K210_PC_IE_INV)
> +#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
> +				 K210_PC_MODE_OUT | K210_PC_OE_INV)
> +#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
> +
> +#define K210_PG_FUNC		GENMASK(7, 0)
> +#define K210_PG_DO		BIT(8)
> +#define K210_PG_PIN		GENMASK(22, 16)
> +
> +/*
> + * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
> + * @pins: 48 32-bits IO pin registers
> + * @tie_en: 256 (one per function) input tie enable bits
> + * @tie_val: 256 (one per function) input tie value bits
> + */
> +struct k210_fpioa {
> +	u32 pins[48];
> +	u32 tie_en[8];
> +	u32 tie_val[8];
> +};
> +
> +struct k210_fpioa_data {
> +
> +	struct device *dev;
> +	struct pinctrl_dev *pctl;
> +
> +	struct k210_fpioa __iomem *fpioa;
> +	struct regmap *sysctl_map;
> +	u32 power_offset;
> +	struct clk *clk;
> +	struct clk *pclk;
> +};
> +
> +#define K210_PIN_NAME(i)	("IO_" #i)
> +#define K210_PIN(i)		[(i)] = PINCTRL_PIN((i), K210_PIN_NAME(i))
> +
> +static const struct pinctrl_pin_desc k210_pins[] = {
> +	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
> +	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
> +	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
> +	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
> +	K210_PIN(12), K210_PIN(13), K210_PIN(14),
> +	K210_PIN(15), K210_PIN(16), K210_PIN(17),
> +	K210_PIN(18), K210_PIN(19), K210_PIN(20),
> +	K210_PIN(21), K210_PIN(22), K210_PIN(23),
> +	K210_PIN(24), K210_PIN(25), K210_PIN(26),
> +	K210_PIN(27), K210_PIN(28), K210_PIN(29),
> +	K210_PIN(30), K210_PIN(31), K210_PIN(32),
> +	K210_PIN(33), K210_PIN(34), K210_PIN(35),
> +	K210_PIN(36), K210_PIN(37), K210_PIN(38),
> +	K210_PIN(39), K210_PIN(40), K210_PIN(41),
> +	K210_PIN(42), K210_PIN(43), K210_PIN(44),
> +	K210_PIN(45), K210_PIN(46), K210_PIN(47)
> +};
> +
> +#define K210_NPINS ARRAY_SIZE(k210_pins)
> +
> +/*
> + * Pin groups: each of the 48 programmable pins is a group.
> + * To this are added 8 power domain groups, which for the purposes of
> + * the pin subsystem, contain no pins. The power domain groups only exist
> + * to set the power level. The id should never be used (since there are
> + * no pins 48-55).
> + */
> +static const char *const k210_group_names[] = {
> +	/* The first 48 groups are for pins, one each */
> +	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
> +	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
> +	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
> +	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
> +	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
> +	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
> +	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
> +	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
> +	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
> +	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
> +	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
> +	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
> +	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
> +	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
> +	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
> +	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
> +	[48] = "A0", [49] = "A1", [50] = "A2",
> +	[51] = "B3", [52] = "B4", [53] = "B5",
> +	[54] = "C6", [55] = "C7"
> +};
> +
> +#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
> +
> +enum k210_pinctrl_mode_id {
> +	K210_PC_DEFAULT_DISABLED,
> +	K210_PC_DEFAULT_IN,
> +	K210_PC_DEFAULT_IN_TIE,
> +	K210_PC_DEFAULT_OUT,
> +	K210_PC_DEFAULT_I2C,
> +	K210_PC_DEFAULT_SCCB,
> +	K210_PC_DEFAULT_SPI,
> +	K210_PC_DEFAULT_GPIO,
> +	K210_PC_DEFAULT_INT13,
> +};
> +
> +#define K210_PC_DEFAULT(mode) \
> +	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
> +
> +static const u32 k210_pinconf_mode_id_to_mode[] = {
> +	[K210_PC_DEFAULT_DISABLED] = 0,
> +	K210_PC_DEFAULT(IN),
> +	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
> +	K210_PC_DEFAULT(OUT),
> +	K210_PC_DEFAULT(I2C),
> +	K210_PC_DEFAULT(SCCB),
> +	K210_PC_DEFAULT(SPI),
> +	K210_PC_DEFAULT(GPIO),
> +	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
> +};
> +
> +#undef DEFAULT
> +
> +/*
> + * Pin functions configuration information.
> + */
> +struct k210_pcf_info {
> +	char name[15];
> +	u8 mode_id;
> +};
> +
> +#define K210_FUNC(id, mode)				\
> +	[K210_PCF_##id] = {				\
> +		.name = #id,				\
> +		.mode_id = K210_PC_DEFAULT_##mode	\
> +	}
> +
> +static const struct k210_pcf_info k210_pcf_infos[] = {
> +	K210_FUNC(JTAG_TCLK,		IN),
> +	K210_FUNC(JTAG_TDI,		IN),
> +	K210_FUNC(JTAG_TMS,		IN),
> +	K210_FUNC(JTAG_TDO,		OUT),
> +	K210_FUNC(SPI0_D0,		SPI),
> +	K210_FUNC(SPI0_D1,		SPI),
> +	K210_FUNC(SPI0_D2,		SPI),
> +	K210_FUNC(SPI0_D3,		SPI),
> +	K210_FUNC(SPI0_D4,		SPI),
> +	K210_FUNC(SPI0_D5,		SPI),
> +	K210_FUNC(SPI0_D6,		SPI),
> +	K210_FUNC(SPI0_D7,		SPI),
> +	K210_FUNC(SPI0_SS0,		OUT),
> +	K210_FUNC(SPI0_SS1,		OUT),
> +	K210_FUNC(SPI0_SS2,		OUT),
> +	K210_FUNC(SPI0_SS3,		OUT),
> +	K210_FUNC(SPI0_ARB,		IN_TIE),
> +	K210_FUNC(SPI0_SCLK,		OUT),
> +	K210_FUNC(UARTHS_RX,		IN),
> +	K210_FUNC(UARTHS_TX,		OUT),
> +	K210_FUNC(RESV6,		IN),
> +	K210_FUNC(RESV7,		IN),
> +	K210_FUNC(CLK_SPI1,		OUT),
> +	K210_FUNC(CLK_I2C1,		OUT),
> +	K210_FUNC(GPIOHS0,		GPIO),
> +	K210_FUNC(GPIOHS1,		GPIO),
> +	K210_FUNC(GPIOHS2,		GPIO),
> +	K210_FUNC(GPIOHS3,		GPIO),
> +	K210_FUNC(GPIOHS4,		GPIO),
> +	K210_FUNC(GPIOHS5,		GPIO),
> +	K210_FUNC(GPIOHS6,		GPIO),
> +	K210_FUNC(GPIOHS7,		GPIO),
> +	K210_FUNC(GPIOHS8,		GPIO),
> +	K210_FUNC(GPIOHS9,		GPIO),
> +	K210_FUNC(GPIOHS10,		GPIO),
> +	K210_FUNC(GPIOHS11,		GPIO),
> +	K210_FUNC(GPIOHS12,		GPIO),
> +	K210_FUNC(GPIOHS13,		GPIO),
> +	K210_FUNC(GPIOHS14,		GPIO),
> +	K210_FUNC(GPIOHS15,		GPIO),
> +	K210_FUNC(GPIOHS16,		GPIO),
> +	K210_FUNC(GPIOHS17,		GPIO),
> +	K210_FUNC(GPIOHS18,		GPIO),
> +	K210_FUNC(GPIOHS19,		GPIO),
> +	K210_FUNC(GPIOHS20,		GPIO),
> +	K210_FUNC(GPIOHS21,		GPIO),
> +	K210_FUNC(GPIOHS22,		GPIO),
> +	K210_FUNC(GPIOHS23,		GPIO),
> +	K210_FUNC(GPIOHS24,		GPIO),
> +	K210_FUNC(GPIOHS25,		GPIO),
> +	K210_FUNC(GPIOHS26,		GPIO),
> +	K210_FUNC(GPIOHS27,		GPIO),
> +	K210_FUNC(GPIOHS28,		GPIO),
> +	K210_FUNC(GPIOHS29,		GPIO),
> +	K210_FUNC(GPIOHS30,		GPIO),
> +	K210_FUNC(GPIOHS31,		GPIO),
> +	K210_FUNC(GPIO0,		GPIO),
> +	K210_FUNC(GPIO1,		GPIO),
> +	K210_FUNC(GPIO2,		GPIO),
> +	K210_FUNC(GPIO3,		GPIO),
> +	K210_FUNC(GPIO4,		GPIO),
> +	K210_FUNC(GPIO5,		GPIO),
> +	K210_FUNC(GPIO6,		GPIO),
> +	K210_FUNC(GPIO7,		GPIO),
> +	K210_FUNC(UART1_RX,		IN),
> +	K210_FUNC(UART1_TX,		OUT),
> +	K210_FUNC(UART2_RX,		IN),
> +	K210_FUNC(UART2_TX,		OUT),
> +	K210_FUNC(UART3_RX,		IN),
> +	K210_FUNC(UART3_TX,		OUT),
> +	K210_FUNC(SPI1_D0,		SPI),
> +	K210_FUNC(SPI1_D1,		SPI),
> +	K210_FUNC(SPI1_D2,		SPI),
> +	K210_FUNC(SPI1_D3,		SPI),
> +	K210_FUNC(SPI1_D4,		SPI),
> +	K210_FUNC(SPI1_D5,		SPI),
> +	K210_FUNC(SPI1_D6,		SPI),
> +	K210_FUNC(SPI1_D7,		SPI),
> +	K210_FUNC(SPI1_SS0,		OUT),
> +	K210_FUNC(SPI1_SS1,		OUT),
> +	K210_FUNC(SPI1_SS2,		OUT),
> +	K210_FUNC(SPI1_SS3,		OUT),
> +	K210_FUNC(SPI1_ARB,		IN_TIE),
> +	K210_FUNC(SPI1_SCLK,		OUT),
> +	K210_FUNC(SPI2_D0,		SPI),
> +	K210_FUNC(SPI2_SS,		IN),
> +	K210_FUNC(SPI2_SCLK,		IN),
> +	K210_FUNC(I2S0_MCLK,		OUT),
> +	K210_FUNC(I2S0_SCLK,		OUT),
> +	K210_FUNC(I2S0_WS,		OUT),
> +	K210_FUNC(I2S0_IN_D0,		IN),
> +	K210_FUNC(I2S0_IN_D1,		IN),
> +	K210_FUNC(I2S0_IN_D2,		IN),
> +	K210_FUNC(I2S0_IN_D3,		IN),
> +	K210_FUNC(I2S0_OUT_D0,		OUT),
> +	K210_FUNC(I2S0_OUT_D1,		OUT),
> +	K210_FUNC(I2S0_OUT_D2,		OUT),
> +	K210_FUNC(I2S0_OUT_D3,		OUT),
> +	K210_FUNC(I2S1_MCLK,		OUT),
> +	K210_FUNC(I2S1_SCLK,		OUT),
> +	K210_FUNC(I2S1_WS,		OUT),
> +	K210_FUNC(I2S1_IN_D0,		IN),
> +	K210_FUNC(I2S1_IN_D1,		IN),
> +	K210_FUNC(I2S1_IN_D2,		IN),
> +	K210_FUNC(I2S1_IN_D3,		IN),
> +	K210_FUNC(I2S1_OUT_D0,		OUT),
> +	K210_FUNC(I2S1_OUT_D1,		OUT),
> +	K210_FUNC(I2S1_OUT_D2,		OUT),
> +	K210_FUNC(I2S1_OUT_D3,		OUT),
> +	K210_FUNC(I2S2_MCLK,		OUT),
> +	K210_FUNC(I2S2_SCLK,		OUT),
> +	K210_FUNC(I2S2_WS,		OUT),
> +	K210_FUNC(I2S2_IN_D0,		IN),
> +	K210_FUNC(I2S2_IN_D1,		IN),
> +	K210_FUNC(I2S2_IN_D2,		IN),
> +	K210_FUNC(I2S2_IN_D3,		IN),
> +	K210_FUNC(I2S2_OUT_D0,		OUT),
> +	K210_FUNC(I2S2_OUT_D1,		OUT),
> +	K210_FUNC(I2S2_OUT_D2,		OUT),
> +	K210_FUNC(I2S2_OUT_D3,		OUT),
> +	K210_FUNC(RESV0,		DISABLED),
> +	K210_FUNC(RESV1,		DISABLED),
> +	K210_FUNC(RESV2,		DISABLED),
> +	K210_FUNC(RESV3,		DISABLED),
> +	K210_FUNC(RESV4,		DISABLED),
> +	K210_FUNC(RESV5,		DISABLED),
> +	K210_FUNC(I2C0_SCLK,		I2C),
> +	K210_FUNC(I2C0_SDA,		I2C),
> +	K210_FUNC(I2C1_SCLK,		I2C),
> +	K210_FUNC(I2C1_SDA,		I2C),
> +	K210_FUNC(I2C2_SCLK,		I2C),
> +	K210_FUNC(I2C2_SDA,		I2C),
> +	K210_FUNC(DVP_XCLK,		OUT),
> +	K210_FUNC(DVP_RST,		OUT),
> +	K210_FUNC(DVP_PWDN,		OUT),
> +	K210_FUNC(DVP_VSYNC,		IN),
> +	K210_FUNC(DVP_HSYNC,		IN),
> +	K210_FUNC(DVP_PCLK,		IN),
> +	K210_FUNC(DVP_D0,		IN),
> +	K210_FUNC(DVP_D1,		IN),
> +	K210_FUNC(DVP_D2,		IN),
> +	K210_FUNC(DVP_D3,		IN),
> +	K210_FUNC(DVP_D4,		IN),
> +	K210_FUNC(DVP_D5,		IN),
> +	K210_FUNC(DVP_D6,		IN),
> +	K210_FUNC(DVP_D7,		IN),
> +	K210_FUNC(SCCB_SCLK,		SCCB),
> +	K210_FUNC(SCCB_SDA,		SCCB),
> +	K210_FUNC(UART1_CTS,		IN),
> +	K210_FUNC(UART1_DSR,		IN),
> +	K210_FUNC(UART1_DCD,		IN),
> +	K210_FUNC(UART1_RI,		IN),
> +	K210_FUNC(UART1_SIR_IN,		IN),
> +	K210_FUNC(UART1_DTR,		OUT),
> +	K210_FUNC(UART1_RTS,		OUT),
> +	K210_FUNC(UART1_OUT2,		OUT),
> +	K210_FUNC(UART1_OUT1,		OUT),
> +	K210_FUNC(UART1_SIR_OUT,	OUT),
> +	K210_FUNC(UART1_BAUD,		OUT),
> +	K210_FUNC(UART1_RE,		OUT),
> +	K210_FUNC(UART1_DE,		OUT),
> +	K210_FUNC(UART1_RS485_EN,	OUT),
> +	K210_FUNC(UART2_CTS,		IN),
> +	K210_FUNC(UART2_DSR,		IN),
> +	K210_FUNC(UART2_DCD,		IN),
> +	K210_FUNC(UART2_RI,		IN),
> +	K210_FUNC(UART2_SIR_IN,		IN),
> +	K210_FUNC(UART2_DTR,		OUT),
> +	K210_FUNC(UART2_RTS,		OUT),
> +	K210_FUNC(UART2_OUT2,		OUT),
> +	K210_FUNC(UART2_OUT1,		OUT),
> +	K210_FUNC(UART2_SIR_OUT,	OUT),
> +	K210_FUNC(UART2_BAUD,		OUT),
> +	K210_FUNC(UART2_RE,		OUT),
> +	K210_FUNC(UART2_DE,		OUT),
> +	K210_FUNC(UART2_RS485_EN,	OUT),
> +	K210_FUNC(UART3_CTS,		IN),
> +	K210_FUNC(UART3_DSR,		IN),
> +	K210_FUNC(UART3_DCD,		IN),
> +	K210_FUNC(UART3_RI,		IN),
> +	K210_FUNC(UART3_SIR_IN,		IN),
> +	K210_FUNC(UART3_DTR,		OUT),
> +	K210_FUNC(UART3_RTS,		OUT),
> +	K210_FUNC(UART3_OUT2,		OUT),
> +	K210_FUNC(UART3_OUT1,		OUT),
> +	K210_FUNC(UART3_SIR_OUT,	OUT),
> +	K210_FUNC(UART3_BAUD,		OUT),
> +	K210_FUNC(UART3_RE,		OUT),
> +	K210_FUNC(UART3_DE,		OUT),
> +	K210_FUNC(UART3_RS485_EN,	OUT),
> +	K210_FUNC(TIMER0_TOGGLE1,	OUT),
> +	K210_FUNC(TIMER0_TOGGLE2,	OUT),
> +	K210_FUNC(TIMER0_TOGGLE3,	OUT),
> +	K210_FUNC(TIMER0_TOGGLE4,	OUT),
> +	K210_FUNC(TIMER1_TOGGLE1,	OUT),
> +	K210_FUNC(TIMER1_TOGGLE2,	OUT),
> +	K210_FUNC(TIMER1_TOGGLE3,	OUT),
> +	K210_FUNC(TIMER1_TOGGLE4,	OUT),
> +	K210_FUNC(TIMER2_TOGGLE1,	OUT),
> +	K210_FUNC(TIMER2_TOGGLE2,	OUT),
> +	K210_FUNC(TIMER2_TOGGLE3,	OUT),
> +	K210_FUNC(TIMER2_TOGGLE4,	OUT),
> +	K210_FUNC(CLK_SPI2,		OUT),
> +	K210_FUNC(CLK_I2C2,		OUT),
> +	K210_FUNC(INTERNAL0,		OUT),
> +	K210_FUNC(INTERNAL1,		OUT),
> +	K210_FUNC(INTERNAL2,		OUT),
> +	K210_FUNC(INTERNAL3,		OUT),
> +	K210_FUNC(INTERNAL4,		OUT),
> +	K210_FUNC(INTERNAL5,		OUT),
> +	K210_FUNC(INTERNAL6,		OUT),
> +	K210_FUNC(INTERNAL7,		OUT),
> +	K210_FUNC(INTERNAL8,		OUT),
> +	K210_FUNC(INTERNAL9,		IN),
> +	K210_FUNC(INTERNAL10,		IN),
> +	K210_FUNC(INTERNAL11,		IN),
> +	K210_FUNC(INTERNAL12,		IN),
> +	K210_FUNC(INTERNAL13,		INT13),
> +	K210_FUNC(INTERNAL14,		I2C),
> +	K210_FUNC(INTERNAL15,		IN),
> +	K210_FUNC(INTERNAL16,		IN),
> +	K210_FUNC(INTERNAL17,		IN),
> +	K210_FUNC(CONSTANT,		DISABLED),
> +	K210_FUNC(INTERNAL18,		IN),
> +	K210_FUNC(DEBUG0,		OUT),
> +	K210_FUNC(DEBUG1,		OUT),
> +	K210_FUNC(DEBUG2,		OUT),
> +	K210_FUNC(DEBUG3,		OUT),
> +	K210_FUNC(DEBUG4,		OUT),
> +	K210_FUNC(DEBUG5,		OUT),
> +	K210_FUNC(DEBUG6,		OUT),
> +	K210_FUNC(DEBUG7,		OUT),
> +	K210_FUNC(DEBUG8,		OUT),
> +	K210_FUNC(DEBUG9,		OUT),
> +	K210_FUNC(DEBUG10,		OUT),
> +	K210_FUNC(DEBUG11,		OUT),
> +	K210_FUNC(DEBUG12,		OUT),
> +	K210_FUNC(DEBUG13,		OUT),
> +	K210_FUNC(DEBUG14,		OUT),
> +	K210_FUNC(DEBUG15,		OUT),
> +	K210_FUNC(DEBUG16,		OUT),
> +	K210_FUNC(DEBUG17,		OUT),
> +	K210_FUNC(DEBUG18,		OUT),
> +	K210_FUNC(DEBUG19,		OUT),
> +	K210_FUNC(DEBUG20,		OUT),
> +	K210_FUNC(DEBUG21,		OUT),
> +	K210_FUNC(DEBUG22,		OUT),
> +	K210_FUNC(DEBUG23,		OUT),
> +	K210_FUNC(DEBUG24,		OUT),
> +	K210_FUNC(DEBUG25,		OUT),
> +	K210_FUNC(DEBUG26,		OUT),
> +	K210_FUNC(DEBUG27,		OUT),
> +	K210_FUNC(DEBUG28,		OUT),
> +	K210_FUNC(DEBUG29,		OUT),
> +	K210_FUNC(DEBUG30,		OUT),
> +	K210_FUNC(DEBUG31,		OUT),
> +};
> +
> +#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
> +#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
> +
> +static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
> +	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
> +	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
> +};
> +
> +/*
> + * Max drive strength in uA.
> + */
> +static const int k210_pinconf_drive_strength[] = {
> +	[0] = 11200,
> +	[1] = 16800,
> +	[2] = 22300,
> +	[3] = 27800,
> +	[4] = 33300,
> +	[5] = 38700,
> +	[6] = 44100,
> +	[7] = 49500,
> +};
> +
> +static int k210_pinconf_get_drive(unsigned int max_strength_ua)
> +{
> +	int i;
> +
> +	for (i = K210_PC_DRIVE_MAX; i; i--) {
> +		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
> +			return i;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
> +					 u32 pin, u32 func)
> +{
> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> +	const struct k210_pcf_info *info = &k210_pcf_infos[func];
> +	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
> +	u32 val = func | mode;
> +
> +	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
> +		pin, info->name, func, val);
> +
> +	writel(val, &pdata->fpioa->pins[pin]);
> +}
> +
> +static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
> +				  unsigned int pin,
> +				  unsigned int param, unsigned int arg)
> +{
> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> +	u32 val = readl(&pdata->fpioa->pins[pin]);
> +	int drive;
> +
> +	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
> +		pin, param, arg);
> +
> +	switch (param) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		val &= ~K210_PC_BIAS_MASK;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		if (!arg)
> +			return -EINVAL;
> +		val |= K210_PC_PD;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		if (!arg)
> +			return -EINVAL;
> +		val |= K210_PC_PD;
> +		break;
> +	case PIN_CONFIG_DRIVE_STRENGTH:
> +		arg *= 1000;
> +		fallthrough;
> +	case PIN_CONFIG_DRIVE_STRENGTH_UA:
> +		drive = k210_pinconf_get_drive(arg);
> +		if (drive < 0)
> +			return drive;
> +		val &= ~K210_PC_DRIVE_MASK;
> +		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
> +		break;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		if (arg)
> +			val |= K210_PC_IE;
> +		else
> +			val &= ~K210_PC_IE;
> +		break;
> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +		if (arg)
> +			val |= K210_PC_ST;
> +		else
> +			val &= ~K210_PC_ST;
> +		break;
> +	case PIN_CONFIG_OUTPUT:
> +		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
> +		val = readl(&pdata->fpioa->pins[pin]);
> +		val |= K210_PC_MODE_OUT;
> +		if (!arg)
> +			val |= K210_PC_DO_INV;
> +		break;
> +	case PIN_CONFIG_OUTPUT_ENABLE:
> +		if (arg)
> +			val |= K210_PC_OE;
> +		else
> +			val &= ~K210_PC_OE;
> +		break;
> +	case PIN_CONFIG_SLEW_RATE:
> +		if (arg)
> +			val |= K210_PC_SL;
> +		else
> +			val &= ~K210_PC_SL;
> +		break;
> +	case PIN_CONFIG_OUTPUT_INVERT:
> +		if (arg)
> +			val |= K210_PC_DO_INV;
> +		else
> +			val &= ~K210_PC_DO_INV;
> +		break;
> +	case PIN_CONFIG_INPUT_INVERT:
> +		if (arg)
> +			val |= K210_PC_DI_INV;
> +		else
> +			val &= ~K210_PC_DI_INV;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	writel(val, &pdata->fpioa->pins[pin]);
> +
> +	return 0;
> +}
> +
> +static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
> +			    unsigned long *configs, unsigned int num_configs)
> +{
> +	unsigned int param, arg;
> +	int i, ret;
> +
> +	if (WARN_ON(pin >= K210_NPINS))
> +		return -EINVAL;
> +
> +	for (i = 0; i < num_configs; i++) {
> +		param = pinconf_to_config_param(configs[i]);
> +		arg = pinconf_to_config_argument(configs[i]);
> +		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +				  struct seq_file *s, unsigned int pin)
> +{
> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> +
> +	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
> +}
> +
> +static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
> +				  unsigned int selector, unsigned long *configs,
> +				  unsigned int num_configs)
> +{
> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> +	unsigned int param, arg;
> +	u32 bit;
> +	int i;
> +
> +	/* Pins should be configured with pinmux, not groups*/
> +	if (selector < K210_NPINS)
> +		return -EINVAL;
> +
> +	/* Otherwise it's a power domain */
> +	for (i = 0; i < num_configs; i++) {
> +		param = pinconf_to_config_param(configs[i]);
> +		if (param != PIN_CONFIG_POWER_SOURCE)
> +			return -EINVAL;
> +
> +		arg = pinconf_to_config_argument(configs[i]);
> +		bit = BIT(selector - K210_NPINS);
> +		regmap_update_bits(pdata->sysctl_map,
> +				   pdata->power_offset,
> +				   bit, arg ? bit : 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
> +					struct seq_file *s,
> +					unsigned int selector)
> +{
> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> +	int ret;
> +	u32 val;
> +
> +	if (selector < K210_NPINS)
> +		return k210_pinconf_dbg_show(pctldev, s, selector);
> +
> +	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
> +	if (ret) {
> +		dev_err(pdata->dev, "Failed to read power reg\n");
> +		return;
> +	}
> +
> +	seq_printf(s, "%s: %s V", k210_group_names[selector],
> +		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
> +}
> +
> +static const struct pinconf_ops k210_pinconf_ops = {
> +	.is_generic = true,
> +	.pin_config_set = k210_pinconf_set,
> +	.pin_config_group_set = k210_pinconf_group_set,
> +	.pin_config_dbg_show = k210_pinconf_dbg_show,
> +	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
> +};
> +
> +static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
> +{
> +	return ARRAY_SIZE(k210_pcf_infos);
> +}
> +
> +static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
> +						 unsigned int selector)
> +{
> +	return k210_pcf_infos[selector].name;
> +}
> +
> +static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
> +					   unsigned int selector,
> +					   const char * const **groups,
> +					   unsigned int * const num_groups)
> +{
> +	/* Any function can be mapped to any pin */
> +	*groups = k210_group_names;
> +	*num_groups = K210_NPINS;
> +
> +	return 0;
> +}
> +
> +static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
> +			       unsigned int function,
> +			       unsigned int group)
> +{
> +	/* Can't mux power domains */
> +	if (group >= K210_NPINS)
> +		return -EINVAL;
> +
> +	k210_pinmux_set_pin_function(pctldev, group, function);
> +
> +	return 0;
> +}
> +
> +static const struct pinmux_ops k210_pinmux_ops = {
> +	.get_functions_count = k210_pinmux_get_function_count,
> +	.get_function_name = k210_pinmux_get_function_name,
> +	.get_function_groups = k210_pinmux_get_function_groups,
> +	.set_mux = k210_pinmux_set_mux,
> +	.strict = true,
> +};
> +
> +static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
> +{
> +	return K210_NGROUPS;
> +}
> +
> +static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
> +					       unsigned int group)
> +{
> +	return k210_group_names[group];
> +}
> +
> +static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
> +				       unsigned int group,
> +				       const unsigned int **pins,
> +				       unsigned int *npins)
> +{
> +	if (group >= K210_NPINS) {
> +		*pins = NULL;
> +		*npins = 0;
> +		return 0;
> +	}
> +
> +	*pins = &k210_pins[group].number;
> +	*npins = 1;
> +
> +	return 0;
> +}
> +
> +static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
> +				      struct seq_file *s, unsigned int offset)
> +{
> +	seq_printf(s, "%s", dev_name(pctldev->dev));
> +}
> +
> +static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
> +					  struct device_node *np,
> +					  struct pinctrl_map **map,
> +					  unsigned int *reserved_maps,
> +					  unsigned int *num_maps)
> +{
> +	struct property *prop;
> +	const __be32 *p;
> +	int ret, pinmux_groups;
> +	u32 pinmux_group;
> +	unsigned long *configs = NULL;
> +	unsigned int num_configs = 0;
> +	unsigned int reserve = 0;
> +
> +	ret = of_property_count_strings(np, "groups");
> +	if (!ret)
> +		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
> +						reserved_maps, num_maps,
> +						PIN_MAP_TYPE_CONFIGS_GROUP);
> +
> +	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
> +	if (pinmux_groups <= 0) {
> +		/* Ignore this node */
> +		return 0;
> +	}
> +
> +	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
> +					      &num_configs);
> +	if (ret < 0) {
> +		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
> +			np);
> +		return ret;
> +	}
> +
> +	reserve = pinmux_groups * (1 + num_configs);
> +	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
> +					reserve);
> +	if (ret < 0)
> +		goto exit;
> +
> +	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
> +		const char *group_name, *func_name;
> +		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
> +		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
> +
> +		if (pin >= K210_NPINS) {
> +			ret = -EINVAL;
> +			goto exit;
> +		}
> +
> +		group_name = k210_group_names[pin];
> +		func_name = k210_pcf_infos[func].name;
> +
> +		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
> +			np->name, pin, func_name);
> +
> +		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
> +						num_maps, group_name,
> +						func_name);
> +		if (ret < 0) {
> +			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
> +				np, ret);
> +			goto exit;
> +		}
> +
> +		if (num_configs) {
> +			ret = pinctrl_utils_add_map_configs(pctldev, map,
> +					reserved_maps, num_maps, group_name,
> +					configs, num_configs,
> +					PIN_MAP_TYPE_CONFIGS_PIN);
> +			if (ret < 0) {
> +				dev_err(pctldev->dev,
> +					"%pOF add configs map failed %d\n",
> +					np, ret);
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +	ret = 0;
> +
> +exit:
> +	kfree(configs);
> +	return ret;
> +}
> +
> +static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
> +				       struct device_node *np_config,
> +				       struct pinctrl_map **map,
> +				       unsigned int *num_maps)
> +{
> +	unsigned int reserved_maps;
> +	struct device_node *np;
> +	int ret;
> +
> +	reserved_maps = 0;
> +	*map = NULL;
> +	*num_maps = 0;
> +
> +	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
> +					     &reserved_maps, num_maps);
> +	if (ret < 0)
> +		goto err;
> +
> +	for_each_available_child_of_node(np_config, np) {
> +		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
> +						     &reserved_maps, num_maps);
> +		if (ret < 0)
> +			goto err;
> +	}
> +	return 0;
> +
> +err:
> +	pinctrl_utils_free_map(pctldev, *map, *num_maps);
> +	return ret;
> +}
> +
> +
> +static const struct pinctrl_ops k210_pinctrl_ops = {
> +	.get_groups_count = k210_pinctrl_get_groups_count,
> +	.get_group_name = k210_pinctrl_get_group_name,
> +	.get_group_pins = k210_pinctrl_get_group_pins,
> +	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
> +	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
> +	.dt_free_map = pinconf_generic_dt_free_map,
> +};
> +
> +static struct pinctrl_desc k210_pinctrl_desc = {
> +	.name = "k210-pinctrl",
> +	.pins = k210_pins,
> +	.npins = K210_NPINS,
> +	.pctlops = &k210_pinctrl_ops,
> +	.pmxops = &k210_pinmux_ops,
> +	.confops = &k210_pinconf_ops,
> +	.custom_params = k210_pinconf_custom_params,
> +	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
> +};
> +
> +static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
> +{
> +	struct k210_fpioa __iomem *fpioa = pdata->fpioa;
> +	u32 val;
> +	int i, j;
> +
> +	dev_dbg(pdata->dev, "Init pin ties\n");
> +
> +	/* Init pin functions input ties */
> +	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
> +		val = 0;
> +		for (j = 0; j < 32; j++) {
> +			if (k210_pcf_infos[i * 32 + j].mode_id ==
> +			    K210_PC_DEFAULT_IN_TIE) {
> +				dev_dbg(pdata->dev,
> +					"tie_en function %d (%s)\n",
> +					i * 32 + j,
> +					k210_pcf_infos[i * 32 + j].name);
> +				val |= BIT(j);
> +			}
> +		}
> +
> +		/* Set value before enable */
> +		writel(val, &fpioa->tie_val[i]);
> +		writel(val, &fpioa->tie_en[i]);
> +	}
> +}
> +
> +static int k210_fpioa_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct k210_fpioa_data *pdata;
> +	int ret;
> +
> +	dev_info(dev, "K210 FPIOA pin controller\n");
> +
> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return -ENOMEM;
> +
> +	pdata->dev = dev;
> +	platform_set_drvdata(pdev, pdata);
> +
> +	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(pdata->fpioa))
> +		return PTR_ERR(pdata->fpioa);
> +
> +	pdata->clk = devm_clk_get(dev, "ref");
> +	if (IS_ERR(pdata->clk))
> +		return PTR_ERR(pdata->clk);
> +
> +	ret = clk_prepare_enable(pdata->clk);
> +	if (ret)
> +		return ret;
> +
> +	pdata->pclk = devm_clk_get_optional(dev, "pclk");
> +	if (!IS_ERR(pdata->pclk))
> +		clk_prepare_enable(pdata->pclk);
> +
> +	pdata->sysctl_map =
> +		syscon_regmap_lookup_by_phandle_args(np,
> +						"canaan,k210-sysctl-power",
> +						1, &pdata->power_offset);
> +	if (IS_ERR(pdata->sysctl_map))
> +		return PTR_ERR(pdata->sysctl_map);
> +
> +	k210_fpioa_init_ties(pdata);
> +
> +	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
> +	if (IS_ERR(pdata->pctl))
> +		return PTR_ERR(pdata->pctl);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id k210_fpioa_dt_ids[] = {
> +	{ .compatible = "canaan,k210-fpioa" },
> +	{ /* sentinel */ },
> +};
> +
> +static struct platform_driver k210_fpioa_driver = {
> +	.probe	= k210_fpioa_probe,
> +	.driver = {
> +		.name		= "k210-fpioa",
> +		.of_match_table	= k210_fpioa_dt_ids,
> +	},
> +};
> +builtin_platform_driver(k210_fpioa_driver);

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
       [not found]     ` <9d32abd1-ffb4-a887-a40d-fc173a371d23@gmail.com>
@ 2021-01-15  0:06       ` Sean Anderson
  2021-01-15  0:35         ` Sean Anderson
  0 siblings, 1 reply; 24+ messages in thread
From: Sean Anderson @ 2021-01-15  0:06 UTC (permalink / raw)
  To: Palmer Dabbelt, Damien Le Moal; +Cc: linux-riscv


On 1/14/21 7:01 PM, Sean Anderson wrote:
> 
> On 1/14/21 6:32 PM, Palmer Dabbelt wrote:
>> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>>> all peripherals of the SoC, their clocks and reset lines. The device
>>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>>> configuration option. No device beside the serial console is defined by
>>> this device tree. This makes this generic device tree suitable for use
>>> with a builtin initramfs with all known K210 based boards.
>>>
>>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>>> removed from the dt-bindings k210-clk.h header file.
>>>
>>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>>> U-Boot support for the K210.
>>>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> Reviewed-by: Anup Patel <anup@brainfault.org>
>>> ---
>>>  arch/riscv/Kconfig.socs                     |   2 +-
>>>  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>>  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>>  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>>  include/dt-bindings/clock/k210-clk.h        |   1 -
>>>  5 files changed, 573 insertions(+), 50 deletions(-)
>>>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>>
>> [Snipping this to the relevant bits, in case you missed it before.]
>>
>>> @@ -81,40 +107,515 @@ in0: oscillator {
>>>      soc {
>>>          #address-cells = <1>;
>>>          #size-cells = <1>;
>>> -        compatible = "kendryte,k210-soc", "simple-bus";
>>> +        compatible = "canaan,k210-soc", "simple-bus";
>>>          ranges;
>>>          interrupt-parent = <&plic0>;
>>>
>>> -        sysctl: sysctl@50440000 {
>>> -            compatible = "kendryte,k210-sysctl", "simple-mfd";
>>> -            reg = <0x50440000 0x1000>;
>>> -            #clock-cells = <1>;
>>> +        debug0: debug@0 {
>>> +            compatible = "canaan,k210-debug", "riscv,debug";
>>
>> I'm still getting lots of warnings about undocumented DT compatible strings
>> from checpatch.  Some of them might be in flight, but I don't see many of them
>> (including both of these debug ones) having been defined anywhere.  We went
>> through a whole process to sort out the SiFive DT naming conventions, I don't
>> want to just circumvent that for the Canaan stuff by merging it as-is.
> 
> As far as I'm aware, it's recommended practice to add device-specific compatible
> 

Here it's because "riscv,debug" doesn't exist. This is the "debug"
device as described in the debug spec. AFAIK Linux never needs to
configure this device. It could probably be removed.

I am going to try and go through the list of nonexistant compatibles and
see if there are any other devices like this (nothing else like it in
Linux).

--Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
  2021-01-14 23:32   ` Palmer Dabbelt
@ 2021-01-15  0:17     ` Damien Le Moal
  2021-01-15  0:39       ` Sean Anderson
  0 siblings, 1 reply; 24+ messages in thread
From: Damien Le Moal @ 2021-01-15  0:17 UTC (permalink / raw)
  To: Palmer Dabbelt, linus.walleij; +Cc: linux-riscv, seanga2

On 2021/01/15 8:32, Palmer Dabbelt wrote:
> On Mon, 11 Jan 2021 16:58:40 PST (-0800), Damien Le Moal wrote:
>> Add the pinctrl-k210.c pinctrl driver for the Canaan Kendryte K210
>> field programmable IO array (FPIOA) to allow configuring the SoC pin
>> functions. The K210 has 48 programmable pins which can take any of 256
>> possible functions.
>>
>> This patch is inspired from the k210 pinctrl driver for the u-boot
>> project and contains many direct contributions from Sean Anderson.
>>
>> The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210
>> SOC FPIOA DRIVER" with myself listed as maintainer for this driver.
>>
>> Cc: Linus Walleij <linus.walleij@linaro.org>
>> Cc: linux-gpio@vger.kernel.org
> 
> IDK if something's screwed up on my end, but I don't see these CCs locally.

It's me who messed up my git-send-email command. I can't get it to send a patch
series using only the CC per patch instead of coalescing all the CC references
and sending all patches to everyone, which I would like to avoid. Still digging
the option usage to figure that one out. I was doing --dry-run tests but the
patches still were sent... Anyway, I sent this and the clock driver patch
separately to the gpio and clk lists.

> Lore does have it in the GPIO list, though, so maybe it made it.  Either way,
> if I'm going to take this through the RISC-V tree then I'd much prefer to have
> at least an Ack.  I'd also be happy to have it go through the GPIO tree, as
> this is largely stand-alone -- the DT bindings are on riscv/for-next, but I'd
> be happy to split them out into a shared tag or just put them in through your
> tree if that's easier.

Yes, I think this one can go through the gpio tree.

Linus,

Could you review this patch please ?

> 
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  MAINTAINERS                    |   7 +
>>  arch/riscv/Kconfig.socs        |   1 +
>>  drivers/pinctrl/Kconfig        |  13 +
>>  drivers/pinctrl/Makefile       |   1 +
>>  drivers/pinctrl/pinctrl-k210.c | 985 +++++++++++++++++++++++++++++++++
>>  5 files changed, 1007 insertions(+)
>>  create mode 100644 drivers/pinctrl/pinctrl-k210.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 637b79eba693..1a7a1e4092e2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -3860,6 +3860,13 @@ W:	https://github.com/Cascoda/ca8210-linux.git
>>  F:	Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
>>  F:	drivers/net/ieee802154/ca8210.c
>>
>> +CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
>> +M:	Damien Le Moal <damien.lemoal@wdc.com>
>> +L:	linux-riscv@lists.infradead.org
>> +L:	linux-gpio@vger.kernel.org (pinctrl driver)
>> +F:	Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
>> +F:	drivers/pinctrl/pinctrl-k210.c
>> +
>>  CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
>>  M:	Damien Le Moal <damien.lemoal@wdc.com>
>>  L:	linux-kernel@vger.kernel.org
>> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
>> index 57e53219c500..6402746c68f3 100644
>> --- a/arch/riscv/Kconfig.socs
>> +++ b/arch/riscv/Kconfig.socs
>> @@ -30,6 +30,7 @@ config SOC_CANAAN
>>  	select SERIAL_SIFIVE_CONSOLE if TTY
>>  	select SIFIVE_PLIC
>>  	select ARCH_HAS_RESET_CONTROLLER
>> +	select PINCTRL
>>  	help
>>  	  This enables support for Canaan Kendryte K210 SoC platform hardware.
>>
>> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
>> index d4b2f2e2ed75..cd437e3cc255 100644
>> --- a/drivers/pinctrl/Kconfig
>> +++ b/drivers/pinctrl/Kconfig
>> @@ -394,6 +394,19 @@ config PINCTRL_MICROCHIP_SGPIO
>>  	  connect control signals from SFP modules and to act as an
>>  	  LED controller.
>>
>> +config PINCTRL_K210
>> +	bool "Pinctrl driver for the Canaan Kendryte K210 SoC"
>> +	depends on RISCV && SOC_CANAAN && OF
>> +	select GENERIC_PINMUX_FUNCTIONS
>> +	select GENERIC_PINCONF
>> +	select GPIOLIB
>> +	select OF_GPIO
>> +	select REGMAP_MMIO
>> +	default SOC_CANAAN
>> +	help
>> +	  Add support for the Canaan Kendryte K210 RISC-V SOC Field
>> +	  Programmable IO Array (FPIOA) controller.
>> +
>>  source "drivers/pinctrl/actions/Kconfig"
>>  source "drivers/pinctrl/aspeed/Kconfig"
>>  source "drivers/pinctrl/bcm/Kconfig"
>> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
>> index 5bb9bb6cc3ce..152c8fe51726 100644
>> --- a/drivers/pinctrl/Makefile
>> +++ b/drivers/pinctrl/Makefile
>> @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
>>  obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
>>  obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO)	+= pinctrl-microchip-sgpio.o
>>  obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
>> +obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
>>
>>  obj-y				+= actions/
>>  obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
>> diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
>> new file mode 100644
>> index 000000000000..8a733cf77ba0
>> --- /dev/null
>> +++ b/drivers/pinctrl/pinctrl-k210.c
>> @@ -0,0 +1,985 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
>> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>> + */
>> +#include <linux/io.h>
>> +#include <linux/of_device.h>
>> +#include <linux/clk.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/bitfield.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +#include <linux/pinctrl/pinctrl.h>
>> +#include <linux/pinctrl/pinmux.h>
>> +#include <linux/pinctrl/pinconf.h>
>> +#include <linux/pinctrl/pinconf-generic.h>
>> +#include <linux/io.h>
>> +
>> +#include <dt-bindings/pinctrl/k210-fpioa.h>
>> +
>> +#include "core.h"
>> +#include "pinconf.h"
>> +#include "pinctrl-utils.h"
>> +
>> +/*
>> + * The K210 only implements 8 drive levels, even though
>> + * there is register space for 16
>> + */
>> +#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
>> +#define K210_PC_DRIVE_SHIFT	8
>> +#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
>> +#define K210_PC_DRIVE_MAX	7
>> +#define K210_PC_MODE_MASK	GENMASK(23, 12)
>> +
>> +/*
>> + * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
>> + * where FUNCTION_OE is a physical signal from the function.
>> + */
>> +#define K210_PC_OE		BIT(12) /* Output Enable */
>> +#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
>> +#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
>> +#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
>> +#define K210_PC_PU		BIT(16) /* Pull Up */
>> +#define K210_PC_PD		BIT(17) /* Pull Down */
>> +/* Strong pull up not implemented on K210 */
>> +#define K210_PC_SL		BIT(19) /* reduce SLew rate */
>> +/* Same semantics as OE above */
>> +#define K210_PC_IE		BIT(20) /* Input Enable */
>> +#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
>> +#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
>> +#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
>> +#define K210_PC_DI		BIT(31) /* raw Data Input */
>> +
>> +#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
>> +
>> +#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
>> +#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
>> +#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
>> +				 K210_PC_OE | K210_PC_PU)
>> +#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
>> +				 K210_PC_OE_INV | K210_PC_IE_INV)
>> +#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
>> +				 K210_PC_MODE_OUT | K210_PC_OE_INV)
>> +#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
>> +
>> +#define K210_PG_FUNC		GENMASK(7, 0)
>> +#define K210_PG_DO		BIT(8)
>> +#define K210_PG_PIN		GENMASK(22, 16)
>> +
>> +/*
>> + * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
>> + * @pins: 48 32-bits IO pin registers
>> + * @tie_en: 256 (one per function) input tie enable bits
>> + * @tie_val: 256 (one per function) input tie value bits
>> + */
>> +struct k210_fpioa {
>> +	u32 pins[48];
>> +	u32 tie_en[8];
>> +	u32 tie_val[8];
>> +};
>> +
>> +struct k210_fpioa_data {
>> +
>> +	struct device *dev;
>> +	struct pinctrl_dev *pctl;
>> +
>> +	struct k210_fpioa __iomem *fpioa;
>> +	struct regmap *sysctl_map;
>> +	u32 power_offset;
>> +	struct clk *clk;
>> +	struct clk *pclk;
>> +};
>> +
>> +#define K210_PIN_NAME(i)	("IO_" #i)
>> +#define K210_PIN(i)		[(i)] = PINCTRL_PIN((i), K210_PIN_NAME(i))
>> +
>> +static const struct pinctrl_pin_desc k210_pins[] = {
>> +	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
>> +	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
>> +	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
>> +	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
>> +	K210_PIN(12), K210_PIN(13), K210_PIN(14),
>> +	K210_PIN(15), K210_PIN(16), K210_PIN(17),
>> +	K210_PIN(18), K210_PIN(19), K210_PIN(20),
>> +	K210_PIN(21), K210_PIN(22), K210_PIN(23),
>> +	K210_PIN(24), K210_PIN(25), K210_PIN(26),
>> +	K210_PIN(27), K210_PIN(28), K210_PIN(29),
>> +	K210_PIN(30), K210_PIN(31), K210_PIN(32),
>> +	K210_PIN(33), K210_PIN(34), K210_PIN(35),
>> +	K210_PIN(36), K210_PIN(37), K210_PIN(38),
>> +	K210_PIN(39), K210_PIN(40), K210_PIN(41),
>> +	K210_PIN(42), K210_PIN(43), K210_PIN(44),
>> +	K210_PIN(45), K210_PIN(46), K210_PIN(47)
>> +};
>> +
>> +#define K210_NPINS ARRAY_SIZE(k210_pins)
>> +
>> +/*
>> + * Pin groups: each of the 48 programmable pins is a group.
>> + * To this are added 8 power domain groups, which for the purposes of
>> + * the pin subsystem, contain no pins. The power domain groups only exist
>> + * to set the power level. The id should never be used (since there are
>> + * no pins 48-55).
>> + */
>> +static const char *const k210_group_names[] = {
>> +	/* The first 48 groups are for pins, one each */
>> +	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
>> +	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
>> +	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
>> +	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
>> +	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
>> +	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
>> +	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
>> +	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
>> +	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
>> +	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
>> +	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
>> +	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
>> +	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
>> +	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
>> +	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
>> +	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
>> +	[48] = "A0", [49] = "A1", [50] = "A2",
>> +	[51] = "B3", [52] = "B4", [53] = "B5",
>> +	[54] = "C6", [55] = "C7"
>> +};
>> +
>> +#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
>> +
>> +enum k210_pinctrl_mode_id {
>> +	K210_PC_DEFAULT_DISABLED,
>> +	K210_PC_DEFAULT_IN,
>> +	K210_PC_DEFAULT_IN_TIE,
>> +	K210_PC_DEFAULT_OUT,
>> +	K210_PC_DEFAULT_I2C,
>> +	K210_PC_DEFAULT_SCCB,
>> +	K210_PC_DEFAULT_SPI,
>> +	K210_PC_DEFAULT_GPIO,
>> +	K210_PC_DEFAULT_INT13,
>> +};
>> +
>> +#define K210_PC_DEFAULT(mode) \
>> +	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
>> +
>> +static const u32 k210_pinconf_mode_id_to_mode[] = {
>> +	[K210_PC_DEFAULT_DISABLED] = 0,
>> +	K210_PC_DEFAULT(IN),
>> +	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
>> +	K210_PC_DEFAULT(OUT),
>> +	K210_PC_DEFAULT(I2C),
>> +	K210_PC_DEFAULT(SCCB),
>> +	K210_PC_DEFAULT(SPI),
>> +	K210_PC_DEFAULT(GPIO),
>> +	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
>> +};
>> +
>> +#undef DEFAULT
>> +
>> +/*
>> + * Pin functions configuration information.
>> + */
>> +struct k210_pcf_info {
>> +	char name[15];
>> +	u8 mode_id;
>> +};
>> +
>> +#define K210_FUNC(id, mode)				\
>> +	[K210_PCF_##id] = {				\
>> +		.name = #id,				\
>> +		.mode_id = K210_PC_DEFAULT_##mode	\
>> +	}
>> +
>> +static const struct k210_pcf_info k210_pcf_infos[] = {
>> +	K210_FUNC(JTAG_TCLK,		IN),
>> +	K210_FUNC(JTAG_TDI,		IN),
>> +	K210_FUNC(JTAG_TMS,		IN),
>> +	K210_FUNC(JTAG_TDO,		OUT),
>> +	K210_FUNC(SPI0_D0,		SPI),
>> +	K210_FUNC(SPI0_D1,		SPI),
>> +	K210_FUNC(SPI0_D2,		SPI),
>> +	K210_FUNC(SPI0_D3,		SPI),
>> +	K210_FUNC(SPI0_D4,		SPI),
>> +	K210_FUNC(SPI0_D5,		SPI),
>> +	K210_FUNC(SPI0_D6,		SPI),
>> +	K210_FUNC(SPI0_D7,		SPI),
>> +	K210_FUNC(SPI0_SS0,		OUT),
>> +	K210_FUNC(SPI0_SS1,		OUT),
>> +	K210_FUNC(SPI0_SS2,		OUT),
>> +	K210_FUNC(SPI0_SS3,		OUT),
>> +	K210_FUNC(SPI0_ARB,		IN_TIE),
>> +	K210_FUNC(SPI0_SCLK,		OUT),
>> +	K210_FUNC(UARTHS_RX,		IN),
>> +	K210_FUNC(UARTHS_TX,		OUT),
>> +	K210_FUNC(RESV6,		IN),
>> +	K210_FUNC(RESV7,		IN),
>> +	K210_FUNC(CLK_SPI1,		OUT),
>> +	K210_FUNC(CLK_I2C1,		OUT),
>> +	K210_FUNC(GPIOHS0,		GPIO),
>> +	K210_FUNC(GPIOHS1,		GPIO),
>> +	K210_FUNC(GPIOHS2,		GPIO),
>> +	K210_FUNC(GPIOHS3,		GPIO),
>> +	K210_FUNC(GPIOHS4,		GPIO),
>> +	K210_FUNC(GPIOHS5,		GPIO),
>> +	K210_FUNC(GPIOHS6,		GPIO),
>> +	K210_FUNC(GPIOHS7,		GPIO),
>> +	K210_FUNC(GPIOHS8,		GPIO),
>> +	K210_FUNC(GPIOHS9,		GPIO),
>> +	K210_FUNC(GPIOHS10,		GPIO),
>> +	K210_FUNC(GPIOHS11,		GPIO),
>> +	K210_FUNC(GPIOHS12,		GPIO),
>> +	K210_FUNC(GPIOHS13,		GPIO),
>> +	K210_FUNC(GPIOHS14,		GPIO),
>> +	K210_FUNC(GPIOHS15,		GPIO),
>> +	K210_FUNC(GPIOHS16,		GPIO),
>> +	K210_FUNC(GPIOHS17,		GPIO),
>> +	K210_FUNC(GPIOHS18,		GPIO),
>> +	K210_FUNC(GPIOHS19,		GPIO),
>> +	K210_FUNC(GPIOHS20,		GPIO),
>> +	K210_FUNC(GPIOHS21,		GPIO),
>> +	K210_FUNC(GPIOHS22,		GPIO),
>> +	K210_FUNC(GPIOHS23,		GPIO),
>> +	K210_FUNC(GPIOHS24,		GPIO),
>> +	K210_FUNC(GPIOHS25,		GPIO),
>> +	K210_FUNC(GPIOHS26,		GPIO),
>> +	K210_FUNC(GPIOHS27,		GPIO),
>> +	K210_FUNC(GPIOHS28,		GPIO),
>> +	K210_FUNC(GPIOHS29,		GPIO),
>> +	K210_FUNC(GPIOHS30,		GPIO),
>> +	K210_FUNC(GPIOHS31,		GPIO),
>> +	K210_FUNC(GPIO0,		GPIO),
>> +	K210_FUNC(GPIO1,		GPIO),
>> +	K210_FUNC(GPIO2,		GPIO),
>> +	K210_FUNC(GPIO3,		GPIO),
>> +	K210_FUNC(GPIO4,		GPIO),
>> +	K210_FUNC(GPIO5,		GPIO),
>> +	K210_FUNC(GPIO6,		GPIO),
>> +	K210_FUNC(GPIO7,		GPIO),
>> +	K210_FUNC(UART1_RX,		IN),
>> +	K210_FUNC(UART1_TX,		OUT),
>> +	K210_FUNC(UART2_RX,		IN),
>> +	K210_FUNC(UART2_TX,		OUT),
>> +	K210_FUNC(UART3_RX,		IN),
>> +	K210_FUNC(UART3_TX,		OUT),
>> +	K210_FUNC(SPI1_D0,		SPI),
>> +	K210_FUNC(SPI1_D1,		SPI),
>> +	K210_FUNC(SPI1_D2,		SPI),
>> +	K210_FUNC(SPI1_D3,		SPI),
>> +	K210_FUNC(SPI1_D4,		SPI),
>> +	K210_FUNC(SPI1_D5,		SPI),
>> +	K210_FUNC(SPI1_D6,		SPI),
>> +	K210_FUNC(SPI1_D7,		SPI),
>> +	K210_FUNC(SPI1_SS0,		OUT),
>> +	K210_FUNC(SPI1_SS1,		OUT),
>> +	K210_FUNC(SPI1_SS2,		OUT),
>> +	K210_FUNC(SPI1_SS3,		OUT),
>> +	K210_FUNC(SPI1_ARB,		IN_TIE),
>> +	K210_FUNC(SPI1_SCLK,		OUT),
>> +	K210_FUNC(SPI2_D0,		SPI),
>> +	K210_FUNC(SPI2_SS,		IN),
>> +	K210_FUNC(SPI2_SCLK,		IN),
>> +	K210_FUNC(I2S0_MCLK,		OUT),
>> +	K210_FUNC(I2S0_SCLK,		OUT),
>> +	K210_FUNC(I2S0_WS,		OUT),
>> +	K210_FUNC(I2S0_IN_D0,		IN),
>> +	K210_FUNC(I2S0_IN_D1,		IN),
>> +	K210_FUNC(I2S0_IN_D2,		IN),
>> +	K210_FUNC(I2S0_IN_D3,		IN),
>> +	K210_FUNC(I2S0_OUT_D0,		OUT),
>> +	K210_FUNC(I2S0_OUT_D1,		OUT),
>> +	K210_FUNC(I2S0_OUT_D2,		OUT),
>> +	K210_FUNC(I2S0_OUT_D3,		OUT),
>> +	K210_FUNC(I2S1_MCLK,		OUT),
>> +	K210_FUNC(I2S1_SCLK,		OUT),
>> +	K210_FUNC(I2S1_WS,		OUT),
>> +	K210_FUNC(I2S1_IN_D0,		IN),
>> +	K210_FUNC(I2S1_IN_D1,		IN),
>> +	K210_FUNC(I2S1_IN_D2,		IN),
>> +	K210_FUNC(I2S1_IN_D3,		IN),
>> +	K210_FUNC(I2S1_OUT_D0,		OUT),
>> +	K210_FUNC(I2S1_OUT_D1,		OUT),
>> +	K210_FUNC(I2S1_OUT_D2,		OUT),
>> +	K210_FUNC(I2S1_OUT_D3,		OUT),
>> +	K210_FUNC(I2S2_MCLK,		OUT),
>> +	K210_FUNC(I2S2_SCLK,		OUT),
>> +	K210_FUNC(I2S2_WS,		OUT),
>> +	K210_FUNC(I2S2_IN_D0,		IN),
>> +	K210_FUNC(I2S2_IN_D1,		IN),
>> +	K210_FUNC(I2S2_IN_D2,		IN),
>> +	K210_FUNC(I2S2_IN_D3,		IN),
>> +	K210_FUNC(I2S2_OUT_D0,		OUT),
>> +	K210_FUNC(I2S2_OUT_D1,		OUT),
>> +	K210_FUNC(I2S2_OUT_D2,		OUT),
>> +	K210_FUNC(I2S2_OUT_D3,		OUT),
>> +	K210_FUNC(RESV0,		DISABLED),
>> +	K210_FUNC(RESV1,		DISABLED),
>> +	K210_FUNC(RESV2,		DISABLED),
>> +	K210_FUNC(RESV3,		DISABLED),
>> +	K210_FUNC(RESV4,		DISABLED),
>> +	K210_FUNC(RESV5,		DISABLED),
>> +	K210_FUNC(I2C0_SCLK,		I2C),
>> +	K210_FUNC(I2C0_SDA,		I2C),
>> +	K210_FUNC(I2C1_SCLK,		I2C),
>> +	K210_FUNC(I2C1_SDA,		I2C),
>> +	K210_FUNC(I2C2_SCLK,		I2C),
>> +	K210_FUNC(I2C2_SDA,		I2C),
>> +	K210_FUNC(DVP_XCLK,		OUT),
>> +	K210_FUNC(DVP_RST,		OUT),
>> +	K210_FUNC(DVP_PWDN,		OUT),
>> +	K210_FUNC(DVP_VSYNC,		IN),
>> +	K210_FUNC(DVP_HSYNC,		IN),
>> +	K210_FUNC(DVP_PCLK,		IN),
>> +	K210_FUNC(DVP_D0,		IN),
>> +	K210_FUNC(DVP_D1,		IN),
>> +	K210_FUNC(DVP_D2,		IN),
>> +	K210_FUNC(DVP_D3,		IN),
>> +	K210_FUNC(DVP_D4,		IN),
>> +	K210_FUNC(DVP_D5,		IN),
>> +	K210_FUNC(DVP_D6,		IN),
>> +	K210_FUNC(DVP_D7,		IN),
>> +	K210_FUNC(SCCB_SCLK,		SCCB),
>> +	K210_FUNC(SCCB_SDA,		SCCB),
>> +	K210_FUNC(UART1_CTS,		IN),
>> +	K210_FUNC(UART1_DSR,		IN),
>> +	K210_FUNC(UART1_DCD,		IN),
>> +	K210_FUNC(UART1_RI,		IN),
>> +	K210_FUNC(UART1_SIR_IN,		IN),
>> +	K210_FUNC(UART1_DTR,		OUT),
>> +	K210_FUNC(UART1_RTS,		OUT),
>> +	K210_FUNC(UART1_OUT2,		OUT),
>> +	K210_FUNC(UART1_OUT1,		OUT),
>> +	K210_FUNC(UART1_SIR_OUT,	OUT),
>> +	K210_FUNC(UART1_BAUD,		OUT),
>> +	K210_FUNC(UART1_RE,		OUT),
>> +	K210_FUNC(UART1_DE,		OUT),
>> +	K210_FUNC(UART1_RS485_EN,	OUT),
>> +	K210_FUNC(UART2_CTS,		IN),
>> +	K210_FUNC(UART2_DSR,		IN),
>> +	K210_FUNC(UART2_DCD,		IN),
>> +	K210_FUNC(UART2_RI,		IN),
>> +	K210_FUNC(UART2_SIR_IN,		IN),
>> +	K210_FUNC(UART2_DTR,		OUT),
>> +	K210_FUNC(UART2_RTS,		OUT),
>> +	K210_FUNC(UART2_OUT2,		OUT),
>> +	K210_FUNC(UART2_OUT1,		OUT),
>> +	K210_FUNC(UART2_SIR_OUT,	OUT),
>> +	K210_FUNC(UART2_BAUD,		OUT),
>> +	K210_FUNC(UART2_RE,		OUT),
>> +	K210_FUNC(UART2_DE,		OUT),
>> +	K210_FUNC(UART2_RS485_EN,	OUT),
>> +	K210_FUNC(UART3_CTS,		IN),
>> +	K210_FUNC(UART3_DSR,		IN),
>> +	K210_FUNC(UART3_DCD,		IN),
>> +	K210_FUNC(UART3_RI,		IN),
>> +	K210_FUNC(UART3_SIR_IN,		IN),
>> +	K210_FUNC(UART3_DTR,		OUT),
>> +	K210_FUNC(UART3_RTS,		OUT),
>> +	K210_FUNC(UART3_OUT2,		OUT),
>> +	K210_FUNC(UART3_OUT1,		OUT),
>> +	K210_FUNC(UART3_SIR_OUT,	OUT),
>> +	K210_FUNC(UART3_BAUD,		OUT),
>> +	K210_FUNC(UART3_RE,		OUT),
>> +	K210_FUNC(UART3_DE,		OUT),
>> +	K210_FUNC(UART3_RS485_EN,	OUT),
>> +	K210_FUNC(TIMER0_TOGGLE1,	OUT),
>> +	K210_FUNC(TIMER0_TOGGLE2,	OUT),
>> +	K210_FUNC(TIMER0_TOGGLE3,	OUT),
>> +	K210_FUNC(TIMER0_TOGGLE4,	OUT),
>> +	K210_FUNC(TIMER1_TOGGLE1,	OUT),
>> +	K210_FUNC(TIMER1_TOGGLE2,	OUT),
>> +	K210_FUNC(TIMER1_TOGGLE3,	OUT),
>> +	K210_FUNC(TIMER1_TOGGLE4,	OUT),
>> +	K210_FUNC(TIMER2_TOGGLE1,	OUT),
>> +	K210_FUNC(TIMER2_TOGGLE2,	OUT),
>> +	K210_FUNC(TIMER2_TOGGLE3,	OUT),
>> +	K210_FUNC(TIMER2_TOGGLE4,	OUT),
>> +	K210_FUNC(CLK_SPI2,		OUT),
>> +	K210_FUNC(CLK_I2C2,		OUT),
>> +	K210_FUNC(INTERNAL0,		OUT),
>> +	K210_FUNC(INTERNAL1,		OUT),
>> +	K210_FUNC(INTERNAL2,		OUT),
>> +	K210_FUNC(INTERNAL3,		OUT),
>> +	K210_FUNC(INTERNAL4,		OUT),
>> +	K210_FUNC(INTERNAL5,		OUT),
>> +	K210_FUNC(INTERNAL6,		OUT),
>> +	K210_FUNC(INTERNAL7,		OUT),
>> +	K210_FUNC(INTERNAL8,		OUT),
>> +	K210_FUNC(INTERNAL9,		IN),
>> +	K210_FUNC(INTERNAL10,		IN),
>> +	K210_FUNC(INTERNAL11,		IN),
>> +	K210_FUNC(INTERNAL12,		IN),
>> +	K210_FUNC(INTERNAL13,		INT13),
>> +	K210_FUNC(INTERNAL14,		I2C),
>> +	K210_FUNC(INTERNAL15,		IN),
>> +	K210_FUNC(INTERNAL16,		IN),
>> +	K210_FUNC(INTERNAL17,		IN),
>> +	K210_FUNC(CONSTANT,		DISABLED),
>> +	K210_FUNC(INTERNAL18,		IN),
>> +	K210_FUNC(DEBUG0,		OUT),
>> +	K210_FUNC(DEBUG1,		OUT),
>> +	K210_FUNC(DEBUG2,		OUT),
>> +	K210_FUNC(DEBUG3,		OUT),
>> +	K210_FUNC(DEBUG4,		OUT),
>> +	K210_FUNC(DEBUG5,		OUT),
>> +	K210_FUNC(DEBUG6,		OUT),
>> +	K210_FUNC(DEBUG7,		OUT),
>> +	K210_FUNC(DEBUG8,		OUT),
>> +	K210_FUNC(DEBUG9,		OUT),
>> +	K210_FUNC(DEBUG10,		OUT),
>> +	K210_FUNC(DEBUG11,		OUT),
>> +	K210_FUNC(DEBUG12,		OUT),
>> +	K210_FUNC(DEBUG13,		OUT),
>> +	K210_FUNC(DEBUG14,		OUT),
>> +	K210_FUNC(DEBUG15,		OUT),
>> +	K210_FUNC(DEBUG16,		OUT),
>> +	K210_FUNC(DEBUG17,		OUT),
>> +	K210_FUNC(DEBUG18,		OUT),
>> +	K210_FUNC(DEBUG19,		OUT),
>> +	K210_FUNC(DEBUG20,		OUT),
>> +	K210_FUNC(DEBUG21,		OUT),
>> +	K210_FUNC(DEBUG22,		OUT),
>> +	K210_FUNC(DEBUG23,		OUT),
>> +	K210_FUNC(DEBUG24,		OUT),
>> +	K210_FUNC(DEBUG25,		OUT),
>> +	K210_FUNC(DEBUG26,		OUT),
>> +	K210_FUNC(DEBUG27,		OUT),
>> +	K210_FUNC(DEBUG28,		OUT),
>> +	K210_FUNC(DEBUG29,		OUT),
>> +	K210_FUNC(DEBUG30,		OUT),
>> +	K210_FUNC(DEBUG31,		OUT),
>> +};
>> +
>> +#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
>> +#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
>> +
>> +static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
>> +	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
>> +	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
>> +};
>> +
>> +/*
>> + * Max drive strength in uA.
>> + */
>> +static const int k210_pinconf_drive_strength[] = {
>> +	[0] = 11200,
>> +	[1] = 16800,
>> +	[2] = 22300,
>> +	[3] = 27800,
>> +	[4] = 33300,
>> +	[5] = 38700,
>> +	[6] = 44100,
>> +	[7] = 49500,
>> +};
>> +
>> +static int k210_pinconf_get_drive(unsigned int max_strength_ua)
>> +{
>> +	int i;
>> +
>> +	for (i = K210_PC_DRIVE_MAX; i; i--) {
>> +		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
>> +			return i;
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
>> +					 u32 pin, u32 func)
>> +{
>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>> +	const struct k210_pcf_info *info = &k210_pcf_infos[func];
>> +	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
>> +	u32 val = func | mode;
>> +
>> +	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
>> +		pin, info->name, func, val);
>> +
>> +	writel(val, &pdata->fpioa->pins[pin]);
>> +}
>> +
>> +static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
>> +				  unsigned int pin,
>> +				  unsigned int param, unsigned int arg)
>> +{
>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>> +	u32 val = readl(&pdata->fpioa->pins[pin]);
>> +	int drive;
>> +
>> +	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
>> +		pin, param, arg);
>> +
>> +	switch (param) {
>> +	case PIN_CONFIG_BIAS_DISABLE:
>> +		val &= ~K210_PC_BIAS_MASK;
>> +		break;
>> +	case PIN_CONFIG_BIAS_PULL_DOWN:
>> +		if (!arg)
>> +			return -EINVAL;
>> +		val |= K210_PC_PD;
>> +		break;
>> +	case PIN_CONFIG_BIAS_PULL_UP:
>> +		if (!arg)
>> +			return -EINVAL;
>> +		val |= K210_PC_PD;
>> +		break;
>> +	case PIN_CONFIG_DRIVE_STRENGTH:
>> +		arg *= 1000;
>> +		fallthrough;
>> +	case PIN_CONFIG_DRIVE_STRENGTH_UA:
>> +		drive = k210_pinconf_get_drive(arg);
>> +		if (drive < 0)
>> +			return drive;
>> +		val &= ~K210_PC_DRIVE_MASK;
>> +		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
>> +		break;
>> +	case PIN_CONFIG_INPUT_ENABLE:
>> +		if (arg)
>> +			val |= K210_PC_IE;
>> +		else
>> +			val &= ~K210_PC_IE;
>> +		break;
>> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
>> +		if (arg)
>> +			val |= K210_PC_ST;
>> +		else
>> +			val &= ~K210_PC_ST;
>> +		break;
>> +	case PIN_CONFIG_OUTPUT:
>> +		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
>> +		val = readl(&pdata->fpioa->pins[pin]);
>> +		val |= K210_PC_MODE_OUT;
>> +		if (!arg)
>> +			val |= K210_PC_DO_INV;
>> +		break;
>> +	case PIN_CONFIG_OUTPUT_ENABLE:
>> +		if (arg)
>> +			val |= K210_PC_OE;
>> +		else
>> +			val &= ~K210_PC_OE;
>> +		break;
>> +	case PIN_CONFIG_SLEW_RATE:
>> +		if (arg)
>> +			val |= K210_PC_SL;
>> +		else
>> +			val &= ~K210_PC_SL;
>> +		break;
>> +	case PIN_CONFIG_OUTPUT_INVERT:
>> +		if (arg)
>> +			val |= K210_PC_DO_INV;
>> +		else
>> +			val &= ~K210_PC_DO_INV;
>> +		break;
>> +	case PIN_CONFIG_INPUT_INVERT:
>> +		if (arg)
>> +			val |= K210_PC_DI_INV;
>> +		else
>> +			val &= ~K210_PC_DI_INV;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	writel(val, &pdata->fpioa->pins[pin]);
>> +
>> +	return 0;
>> +}
>> +
>> +static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
>> +			    unsigned long *configs, unsigned int num_configs)
>> +{
>> +	unsigned int param, arg;
>> +	int i, ret;
>> +
>> +	if (WARN_ON(pin >= K210_NPINS))
>> +		return -EINVAL;
>> +
>> +	for (i = 0; i < num_configs; i++) {
>> +		param = pinconf_to_config_param(configs[i]);
>> +		arg = pinconf_to_config_argument(configs[i]);
>> +		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
>> +				  struct seq_file *s, unsigned int pin)
>> +{
>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>> +
>> +	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
>> +}
>> +
>> +static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
>> +				  unsigned int selector, unsigned long *configs,
>> +				  unsigned int num_configs)
>> +{
>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>> +	unsigned int param, arg;
>> +	u32 bit;
>> +	int i;
>> +
>> +	/* Pins should be configured with pinmux, not groups*/
>> +	if (selector < K210_NPINS)
>> +		return -EINVAL;
>> +
>> +	/* Otherwise it's a power domain */
>> +	for (i = 0; i < num_configs; i++) {
>> +		param = pinconf_to_config_param(configs[i]);
>> +		if (param != PIN_CONFIG_POWER_SOURCE)
>> +			return -EINVAL;
>> +
>> +		arg = pinconf_to_config_argument(configs[i]);
>> +		bit = BIT(selector - K210_NPINS);
>> +		regmap_update_bits(pdata->sysctl_map,
>> +				   pdata->power_offset,
>> +				   bit, arg ? bit : 0);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
>> +					struct seq_file *s,
>> +					unsigned int selector)
>> +{
>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>> +	int ret;
>> +	u32 val;
>> +
>> +	if (selector < K210_NPINS)
>> +		return k210_pinconf_dbg_show(pctldev, s, selector);
>> +
>> +	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
>> +	if (ret) {
>> +		dev_err(pdata->dev, "Failed to read power reg\n");
>> +		return;
>> +	}
>> +
>> +	seq_printf(s, "%s: %s V", k210_group_names[selector],
>> +		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
>> +}
>> +
>> +static const struct pinconf_ops k210_pinconf_ops = {
>> +	.is_generic = true,
>> +	.pin_config_set = k210_pinconf_set,
>> +	.pin_config_group_set = k210_pinconf_group_set,
>> +	.pin_config_dbg_show = k210_pinconf_dbg_show,
>> +	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
>> +};
>> +
>> +static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
>> +{
>> +	return ARRAY_SIZE(k210_pcf_infos);
>> +}
>> +
>> +static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
>> +						 unsigned int selector)
>> +{
>> +	return k210_pcf_infos[selector].name;
>> +}
>> +
>> +static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
>> +					   unsigned int selector,
>> +					   const char * const **groups,
>> +					   unsigned int * const num_groups)
>> +{
>> +	/* Any function can be mapped to any pin */
>> +	*groups = k210_group_names;
>> +	*num_groups = K210_NPINS;
>> +
>> +	return 0;
>> +}
>> +
>> +static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
>> +			       unsigned int function,
>> +			       unsigned int group)
>> +{
>> +	/* Can't mux power domains */
>> +	if (group >= K210_NPINS)
>> +		return -EINVAL;
>> +
>> +	k210_pinmux_set_pin_function(pctldev, group, function);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct pinmux_ops k210_pinmux_ops = {
>> +	.get_functions_count = k210_pinmux_get_function_count,
>> +	.get_function_name = k210_pinmux_get_function_name,
>> +	.get_function_groups = k210_pinmux_get_function_groups,
>> +	.set_mux = k210_pinmux_set_mux,
>> +	.strict = true,
>> +};
>> +
>> +static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
>> +{
>> +	return K210_NGROUPS;
>> +}
>> +
>> +static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
>> +					       unsigned int group)
>> +{
>> +	return k210_group_names[group];
>> +}
>> +
>> +static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
>> +				       unsigned int group,
>> +				       const unsigned int **pins,
>> +				       unsigned int *npins)
>> +{
>> +	if (group >= K210_NPINS) {
>> +		*pins = NULL;
>> +		*npins = 0;
>> +		return 0;
>> +	}
>> +
>> +	*pins = &k210_pins[group].number;
>> +	*npins = 1;
>> +
>> +	return 0;
>> +}
>> +
>> +static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
>> +				      struct seq_file *s, unsigned int offset)
>> +{
>> +	seq_printf(s, "%s", dev_name(pctldev->dev));
>> +}
>> +
>> +static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
>> +					  struct device_node *np,
>> +					  struct pinctrl_map **map,
>> +					  unsigned int *reserved_maps,
>> +					  unsigned int *num_maps)
>> +{
>> +	struct property *prop;
>> +	const __be32 *p;
>> +	int ret, pinmux_groups;
>> +	u32 pinmux_group;
>> +	unsigned long *configs = NULL;
>> +	unsigned int num_configs = 0;
>> +	unsigned int reserve = 0;
>> +
>> +	ret = of_property_count_strings(np, "groups");
>> +	if (!ret)
>> +		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
>> +						reserved_maps, num_maps,
>> +						PIN_MAP_TYPE_CONFIGS_GROUP);
>> +
>> +	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
>> +	if (pinmux_groups <= 0) {
>> +		/* Ignore this node */
>> +		return 0;
>> +	}
>> +
>> +	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
>> +					      &num_configs);
>> +	if (ret < 0) {
>> +		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
>> +			np);
>> +		return ret;
>> +	}
>> +
>> +	reserve = pinmux_groups * (1 + num_configs);
>> +	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
>> +					reserve);
>> +	if (ret < 0)
>> +		goto exit;
>> +
>> +	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
>> +		const char *group_name, *func_name;
>> +		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
>> +		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
>> +
>> +		if (pin >= K210_NPINS) {
>> +			ret = -EINVAL;
>> +			goto exit;
>> +		}
>> +
>> +		group_name = k210_group_names[pin];
>> +		func_name = k210_pcf_infos[func].name;
>> +
>> +		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
>> +			np->name, pin, func_name);
>> +
>> +		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
>> +						num_maps, group_name,
>> +						func_name);
>> +		if (ret < 0) {
>> +			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
>> +				np, ret);
>> +			goto exit;
>> +		}
>> +
>> +		if (num_configs) {
>> +			ret = pinctrl_utils_add_map_configs(pctldev, map,
>> +					reserved_maps, num_maps, group_name,
>> +					configs, num_configs,
>> +					PIN_MAP_TYPE_CONFIGS_PIN);
>> +			if (ret < 0) {
>> +				dev_err(pctldev->dev,
>> +					"%pOF add configs map failed %d\n",
>> +					np, ret);
>> +				goto exit;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = 0;
>> +
>> +exit:
>> +	kfree(configs);
>> +	return ret;
>> +}
>> +
>> +static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
>> +				       struct device_node *np_config,
>> +				       struct pinctrl_map **map,
>> +				       unsigned int *num_maps)
>> +{
>> +	unsigned int reserved_maps;
>> +	struct device_node *np;
>> +	int ret;
>> +
>> +	reserved_maps = 0;
>> +	*map = NULL;
>> +	*num_maps = 0;
>> +
>> +	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
>> +					     &reserved_maps, num_maps);
>> +	if (ret < 0)
>> +		goto err;
>> +
>> +	for_each_available_child_of_node(np_config, np) {
>> +		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
>> +						     &reserved_maps, num_maps);
>> +		if (ret < 0)
>> +			goto err;
>> +	}
>> +	return 0;
>> +
>> +err:
>> +	pinctrl_utils_free_map(pctldev, *map, *num_maps);
>> +	return ret;
>> +}
>> +
>> +
>> +static const struct pinctrl_ops k210_pinctrl_ops = {
>> +	.get_groups_count = k210_pinctrl_get_groups_count,
>> +	.get_group_name = k210_pinctrl_get_group_name,
>> +	.get_group_pins = k210_pinctrl_get_group_pins,
>> +	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
>> +	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
>> +	.dt_free_map = pinconf_generic_dt_free_map,
>> +};
>> +
>> +static struct pinctrl_desc k210_pinctrl_desc = {
>> +	.name = "k210-pinctrl",
>> +	.pins = k210_pins,
>> +	.npins = K210_NPINS,
>> +	.pctlops = &k210_pinctrl_ops,
>> +	.pmxops = &k210_pinmux_ops,
>> +	.confops = &k210_pinconf_ops,
>> +	.custom_params = k210_pinconf_custom_params,
>> +	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
>> +};
>> +
>> +static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
>> +{
>> +	struct k210_fpioa __iomem *fpioa = pdata->fpioa;
>> +	u32 val;
>> +	int i, j;
>> +
>> +	dev_dbg(pdata->dev, "Init pin ties\n");
>> +
>> +	/* Init pin functions input ties */
>> +	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
>> +		val = 0;
>> +		for (j = 0; j < 32; j++) {
>> +			if (k210_pcf_infos[i * 32 + j].mode_id ==
>> +			    K210_PC_DEFAULT_IN_TIE) {
>> +				dev_dbg(pdata->dev,
>> +					"tie_en function %d (%s)\n",
>> +					i * 32 + j,
>> +					k210_pcf_infos[i * 32 + j].name);
>> +				val |= BIT(j);
>> +			}
>> +		}
>> +
>> +		/* Set value before enable */
>> +		writel(val, &fpioa->tie_val[i]);
>> +		writel(val, &fpioa->tie_en[i]);
>> +	}
>> +}
>> +
>> +static int k210_fpioa_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct device_node *np = dev->of_node;
>> +	struct k210_fpioa_data *pdata;
>> +	int ret;
>> +
>> +	dev_info(dev, "K210 FPIOA pin controller\n");
>> +
>> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>> +	if (!pdata)
>> +		return -ENOMEM;
>> +
>> +	pdata->dev = dev;
>> +	platform_set_drvdata(pdev, pdata);
>> +
>> +	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
>> +	if (IS_ERR(pdata->fpioa))
>> +		return PTR_ERR(pdata->fpioa);
>> +
>> +	pdata->clk = devm_clk_get(dev, "ref");
>> +	if (IS_ERR(pdata->clk))
>> +		return PTR_ERR(pdata->clk);
>> +
>> +	ret = clk_prepare_enable(pdata->clk);
>> +	if (ret)
>> +		return ret;
>> +
>> +	pdata->pclk = devm_clk_get_optional(dev, "pclk");
>> +	if (!IS_ERR(pdata->pclk))
>> +		clk_prepare_enable(pdata->pclk);
>> +
>> +	pdata->sysctl_map =
>> +		syscon_regmap_lookup_by_phandle_args(np,
>> +						"canaan,k210-sysctl-power",
>> +						1, &pdata->power_offset);
>> +	if (IS_ERR(pdata->sysctl_map))
>> +		return PTR_ERR(pdata->sysctl_map);
>> +
>> +	k210_fpioa_init_ties(pdata);
>> +
>> +	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
>> +	if (IS_ERR(pdata->pctl))
>> +		return PTR_ERR(pdata->pctl);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id k210_fpioa_dt_ids[] = {
>> +	{ .compatible = "canaan,k210-fpioa" },
>> +	{ /* sentinel */ },
>> +};
>> +
>> +static struct platform_driver k210_fpioa_driver = {
>> +	.probe	= k210_fpioa_probe,
>> +	.driver = {
>> +		.name		= "k210-fpioa",
>> +		.of_match_table	= k210_fpioa_dt_ids,
>> +	},
>> +};
>> +builtin_platform_driver(k210_fpioa_driver);
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-14 23:32   ` Palmer Dabbelt
       [not found]     ` <9d32abd1-ffb4-a887-a40d-fc173a371d23@gmail.com>
@ 2021-01-15  0:33     ` Damien Le Moal
  2021-01-15  5:56     ` Damien Le Moal
  2 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-15  0:33 UTC (permalink / raw)
  To: Palmer Dabbelt; +Cc: linux-riscv, seanga2

On 2021/01/15 8:32, Palmer Dabbelt wrote:
> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>> all peripherals of the SoC, their clocks and reset lines. The device
>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>> configuration option. No device beside the serial console is defined by
>> this device tree. This makes this generic device tree suitable for use
>> with a builtin initramfs with all known K210 based boards.
>>
>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>> removed from the dt-bindings k210-clk.h header file.
>>
>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>> U-Boot support for the K210.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> Reviewed-by: Anup Patel <anup@brainfault.org>
>> ---
>>  arch/riscv/Kconfig.socs                     |   2 +-
>>  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>  include/dt-bindings/clock/k210-clk.h        |   1 -
>>  5 files changed, 573 insertions(+), 50 deletions(-)
>>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
> 
> [Snipping this to the relevant bits, in case you missed it before.]
> 
>> @@ -81,40 +107,515 @@ in0: oscillator {
>>  	soc {
>>  		#address-cells = <1>;
>>  		#size-cells = <1>;
>> -		compatible = "kendryte,k210-soc", "simple-bus";
>> +		compatible = "canaan,k210-soc", "simple-bus";
>>  		ranges;
>>  		interrupt-parent = <&plic0>;
>>
>> -		sysctl: sysctl@50440000 {
>> -			compatible = "kendryte,k210-sysctl", "simple-mfd";
>> -			reg = <0x50440000 0x1000>;
>> -			#clock-cells = <1>;
>> +		debug0: debug@0 {
>> +			compatible = "canaan,k210-debug", "riscv,debug";
> 
> I'm still getting lots of warnings about undocumented DT compatible strings
> from checpatch.  Some of them might be in flight, but I don't see many of them
> (including both of these debug ones) having been defined anywhere.  We went
> through a whole process to sort out the SiFive DT naming conventions, I don't
> want to just circumvent that for the Canaan stuff by merging it as-is.
> 

As mentioned in my previous reply about this, I am aware of the warnings and I
am ignoring them. The reason is that I really would like to keep the DTs as-is,
describing all pieces of the SoC, even the nodes that do not have Linux support
yet. Doing so, we end up with what amounts to the best public documentation ever
 for this SoC and the boards as what is available publicly from the SoC and
boards vendors is not great (that is an understatement). All this information
was extracted from the Kendryte SDK and from board design CAD prints (available
from https://dl.sipeed.com/MAIX). Sean did most of that for the MAIX Bit board
and I added other boards and some corrections. I really do not wish anybody to
have to do this again to figure out the memory mapping, clocks, reset lines, and
pinctrl mapping. That was hard and painful.

Having these unsupported DT nodes around will also allow us to point to them for
people who want to start getting involved with risc-v & Linux and want a project
to start with. I see these boards as cheap hardware for hobbyist and educational
tools rather than production hardware. I am having a blast building a biped
walking robot with a MAIX Bit as the controller right now...

So unless you keep insisting, I would like to keep the DTs as they are. The
naming convention of all nodes in the DT is fine and follows the
"vendor,soc-function" pattern. All unsupported nodes are also marked with
"status = disabled;" so they do not cause any problem.

Thoughts ?

-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-15  0:06       ` Sean Anderson
@ 2021-01-15  0:35         ` Sean Anderson
  2021-01-15  1:03           ` Damien Le Moal
  0 siblings, 1 reply; 24+ messages in thread
From: Sean Anderson @ 2021-01-15  0:35 UTC (permalink / raw)
  To: Palmer Dabbelt, Damien Le Moal; +Cc: linux-riscv

On 1/14/21 7:06 PM, Sean Anderson wrote:
> 
> On 1/14/21 7:01 PM, Sean Anderson wrote:
>>
>> On 1/14/21 6:32 PM, Palmer Dabbelt wrote:
>>> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>>>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>>>> all peripherals of the SoC, their clocks and reset lines. The device
>>>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>>>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>>>> configuration option. No device beside the serial console is defined by
>>>> this device tree. This makes this generic device tree suitable for use
>>>> with a builtin initramfs with all known K210 based boards.
>>>>
>>>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>>>> removed from the dt-bindings k210-clk.h header file.
>>>>
>>>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>>>> U-Boot support for the K210.
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>> Reviewed-by: Anup Patel <anup@brainfault.org>
>>>> ---
>>>>  arch/riscv/Kconfig.socs                     |   2 +-
>>>>  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>>>  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>>>  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>>>  include/dt-bindings/clock/k210-clk.h        |   1 -
>>>>  5 files changed, 573 insertions(+), 50 deletions(-)
>>>>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>>>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>>>
>>> [Snipping this to the relevant bits, in case you missed it before.]
>>>
>>>> @@ -81,40 +107,515 @@ in0: oscillator {
>>>>      soc {
>>>>          #address-cells = <1>;
>>>>          #size-cells = <1>;
>>>> -        compatible = "kendryte,k210-soc", "simple-bus";
>>>> +        compatible = "canaan,k210-soc", "simple-bus";
>>>>          ranges;
>>>>          interrupt-parent = <&plic0>;
>>>>
>>>> -        sysctl: sysctl@50440000 {
>>>> -            compatible = "kendryte,k210-sysctl", "simple-mfd";
>>>> -            reg = <0x50440000 0x1000>;
>>>> -            #clock-cells = <1>;
>>>> +        debug0: debug@0 {
>>>> +            compatible = "canaan,k210-debug", "riscv,debug";
>>>
>>> I'm still getting lots of warnings about undocumented DT compatible strings
>>> from checpatch.  Some of them might be in flight, but I don't see many of them
>>> (including both of these debug ones) having been defined anywhere.  We went
>>> through a whole process to sort out the SiFive DT naming conventions, I don't
>>> want to just circumvent that for the Canaan stuff by merging it as-is.
>>
>> As far as I'm aware, it's recommended practice to add device-specific compatible
>>
> 
> Here it's because "riscv,debug" doesn't exist. This is the "debug"
> device as described in the debug spec. AFAIK Linux never needs to
> configure this device. It could probably be removed.
> 
> I am going to try and go through the list of nonexistant compatibles and
> see if there are any other devices like this (nothing else like it in
> Linux).
> 
> --Sean

Ok, here is the (abbreviated) output:


> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
> cpu@0: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']

This is a device-specific compatible string as recommended by the
current DT docs.

> cpu@0: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']

This should be added (though it is technically incorrect).

(perhaps a version number should be added like 'riscv,sv39-1.10')

> cpu@0: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']

Should probably be fixed, as the g is redundant. However, this is
probably not a good warning going forward, as more exotic combinations
of extensions are implemented.

> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
> cpu@1: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
> 
> cpu@1: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
> cpu@1: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']

see above

> serial@38000000: compatible:0: 'canaan,k210-uarths' is not one of ['sifive,fu540-c000-uart', 'sifive,fu740-c000-uart']

device-specific, and intentional

> gpio-controller@38001000: compatible:0: 'canaan,k210-gpiohs' is not one of ['sifive,fu540-c000-gpio', 'sifive,fu740-c000-gpio']

ditto

> gpio-controller@38001000: 'ngpios' does not match any of the regexes: 'pinctrl-[0-9]+'

known shortcoming with this dt property, but alas

> gpio-controller@50200000: $nodename:0: 'gpio-controller@50200000' does not match '^gpio@[0-9a-f]+$'

This matches devicetree/bindings/gpio/snps,dw-apb-gpio.yaml

> gpio-controller@50200000: compatible: ['canaan,k210-gpio', 'snps,dw-apb-gpio'] is too long
> gpio-controller@50200000: compatible: Additional items are not allowed ('snps,dw-apb-gpio' was unexpected)
> gpio-controller@50200000: 'gpio1@0' does not match any of the regexes: '^gpio-(port|controller)@[0-9a-f]+$', 'pinctrl-[0-9]+'
> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
> 
> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
> 
> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']

More device-specific strings.

> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']

ditto

> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
> 
> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
> 
> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long

ditto

> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
> timer@502D0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
> 
> timer@502D0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'

`resets` is the correct name for this property.

> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
> timer@502E0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']

More device-specific.

> timer@502E0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
> timer@502F0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
> 
> timer@502F0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
> watchdog@50400000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
> 
> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
> watchdog@50410000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
> 
> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
> 
> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
> 
> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is not valid under any of the given schemas (Possible causes of the failure):
> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is too long
> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']

Ok, so the vast majority of these warnings are from unknown compatible
strings. IMO this is not an issue, but the simple fix is to just add
these strings to the yaml files.

--Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver
  2021-01-15  0:17     ` Damien Le Moal
@ 2021-01-15  0:39       ` Sean Anderson
  0 siblings, 0 replies; 24+ messages in thread
From: Sean Anderson @ 2021-01-15  0:39 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linus.walleij; +Cc: linux-riscv

On 1/14/21 7:17 PM, Damien Le Moal wrote:
> On 2021/01/15 8:32, Palmer Dabbelt wrote:
>> On Mon, 11 Jan 2021 16:58:40 PST (-0800), Damien Le Moal wrote:
>>> Add the pinctrl-k210.c pinctrl driver for the Canaan Kendryte K210
>>> field programmable IO array (FPIOA) to allow configuring the SoC pin
>>> functions. The K210 has 48 programmable pins which can take any of 256
>>> possible functions.
>>>
>>> This patch is inspired from the k210 pinctrl driver for the u-boot
>>> project and contains many direct contributions from Sean Anderson.
>>>
>>> The MAINTAINERS file is updated, adding the entry "CANAAN/KENDRYTE K210
>>> SOC FPIOA DRIVER" with myself listed as maintainer for this driver.
>>>
>>> Cc: Linus Walleij <linus.walleij@linaro.org>
>>> Cc: linux-gpio@vger.kernel.org
>>
>> IDK if something's screwed up on my end, but I don't see these CCs locally.
> 
> It's me who messed up my git-send-email command. I can't get it to send a patch
> series using only the CC per patch instead of coalescing all the CC references
> and sending all patches to everyone, which I would like to avoid. Still digging
> the option usage to figure that one out. I was doing --dry-run tests but the
> patches still were sent... Anyway, I sent this and the clock driver patch
> separately to the gpio and clk lists.

There's always u-boot's patman. I find it very helpful for CC-ing
relevant people and managing changelogs.

https://gitlab.denx.de/u-boot/u-boot/blob/master/tools/patman/README

--Sean

> 
>> Lore does have it in the GPIO list, though, so maybe it made it.  Either way,
>> if I'm going to take this through the RISC-V tree then I'd much prefer to have
>> at least an Ack.  I'd also be happy to have it go through the GPIO tree, as
>> this is largely stand-alone -- the DT bindings are on riscv/for-next, but I'd
>> be happy to split them out into a shared tag or just put them in through your
>> tree if that's easier.
> 
> Yes, I think this one can go through the gpio tree.
> 
> Linus,
> 
> Could you review this patch please ?
> 
>>
>>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> ---
>>>   MAINTAINERS                    |   7 +
>>>   arch/riscv/Kconfig.socs        |   1 +
>>>   drivers/pinctrl/Kconfig        |  13 +
>>>   drivers/pinctrl/Makefile       |   1 +
>>>   drivers/pinctrl/pinctrl-k210.c | 985 +++++++++++++++++++++++++++++++++
>>>   5 files changed, 1007 insertions(+)
>>>   create mode 100644 drivers/pinctrl/pinctrl-k210.c
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 637b79eba693..1a7a1e4092e2 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -3860,6 +3860,13 @@ W:	https://github.com/Cascoda/ca8210-linux.git
>>>   F:	Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
>>>   F:	drivers/net/ieee802154/ca8210.c
>>>
>>> +CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
>>> +M:	Damien Le Moal <damien.lemoal@wdc.com>
>>> +L:	linux-riscv@lists.infradead.org
>>> +L:	linux-gpio@vger.kernel.org (pinctrl driver)
>>> +F:	Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
>>> +F:	drivers/pinctrl/pinctrl-k210.c
>>> +
>>>   CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
>>>   M:	Damien Le Moal <damien.lemoal@wdc.com>
>>>   L:	linux-kernel@vger.kernel.org
>>> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
>>> index 57e53219c500..6402746c68f3 100644
>>> --- a/arch/riscv/Kconfig.socs
>>> +++ b/arch/riscv/Kconfig.socs
>>> @@ -30,6 +30,7 @@ config SOC_CANAAN
>>>   	select SERIAL_SIFIVE_CONSOLE if TTY
>>>   	select SIFIVE_PLIC
>>>   	select ARCH_HAS_RESET_CONTROLLER
>>> +	select PINCTRL
>>>   	help
>>>   	  This enables support for Canaan Kendryte K210 SoC platform hardware.
>>>
>>> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
>>> index d4b2f2e2ed75..cd437e3cc255 100644
>>> --- a/drivers/pinctrl/Kconfig
>>> +++ b/drivers/pinctrl/Kconfig
>>> @@ -394,6 +394,19 @@ config PINCTRL_MICROCHIP_SGPIO
>>>   	  connect control signals from SFP modules and to act as an
>>>   	  LED controller.
>>>
>>> +config PINCTRL_K210
>>> +	bool "Pinctrl driver for the Canaan Kendryte K210 SoC"
>>> +	depends on RISCV && SOC_CANAAN && OF
>>> +	select GENERIC_PINMUX_FUNCTIONS
>>> +	select GENERIC_PINCONF
>>> +	select GPIOLIB
>>> +	select OF_GPIO
>>> +	select REGMAP_MMIO
>>> +	default SOC_CANAAN
>>> +	help
>>> +	  Add support for the Canaan Kendryte K210 RISC-V SOC Field
>>> +	  Programmable IO Array (FPIOA) controller.
>>> +
>>>   source "drivers/pinctrl/actions/Kconfig"
>>>   source "drivers/pinctrl/aspeed/Kconfig"
>>>   source "drivers/pinctrl/bcm/Kconfig"
>>> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
>>> index 5bb9bb6cc3ce..152c8fe51726 100644
>>> --- a/drivers/pinctrl/Makefile
>>> +++ b/drivers/pinctrl/Makefile
>>> @@ -48,6 +48,7 @@ obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
>>>   obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
>>>   obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO)	+= pinctrl-microchip-sgpio.o
>>>   obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
>>> +obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
>>>
>>>   obj-y				+= actions/
>>>   obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
>>> diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
>>> new file mode 100644
>>> index 000000000000..8a733cf77ba0
>>> --- /dev/null
>>> +++ b/drivers/pinctrl/pinctrl-k210.c
>>> @@ -0,0 +1,985 @@
>>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>> +/*
>>> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
>>> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>>> + */
>>> +#include <linux/io.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/mfd/syscon.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/bitfield.h>
>>> +#include <linux/regmap.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/pinctrl/pinctrl.h>
>>> +#include <linux/pinctrl/pinmux.h>
>>> +#include <linux/pinctrl/pinconf.h>
>>> +#include <linux/pinctrl/pinconf-generic.h>
>>> +#include <linux/io.h>
>>> +
>>> +#include <dt-bindings/pinctrl/k210-fpioa.h>
>>> +
>>> +#include "core.h"
>>> +#include "pinconf.h"
>>> +#include "pinctrl-utils.h"
>>> +
>>> +/*
>>> + * The K210 only implements 8 drive levels, even though
>>> + * there is register space for 16
>>> + */
>>> +#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
>>> +#define K210_PC_DRIVE_SHIFT	8
>>> +#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
>>> +#define K210_PC_DRIVE_MAX	7
>>> +#define K210_PC_MODE_MASK	GENMASK(23, 12)
>>> +
>>> +/*
>>> + * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
>>> + * where FUNCTION_OE is a physical signal from the function.
>>> + */
>>> +#define K210_PC_OE		BIT(12) /* Output Enable */
>>> +#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
>>> +#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
>>> +#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
>>> +#define K210_PC_PU		BIT(16) /* Pull Up */
>>> +#define K210_PC_PD		BIT(17) /* Pull Down */
>>> +/* Strong pull up not implemented on K210 */
>>> +#define K210_PC_SL		BIT(19) /* reduce SLew rate */
>>> +/* Same semantics as OE above */
>>> +#define K210_PC_IE		BIT(20) /* Input Enable */
>>> +#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
>>> +#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
>>> +#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
>>> +#define K210_PC_DI		BIT(31) /* raw Data Input */
>>> +
>>> +#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
>>> +
>>> +#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
>>> +#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
>>> +#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
>>> +				 K210_PC_OE | K210_PC_PU)
>>> +#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
>>> +				 K210_PC_OE_INV | K210_PC_IE_INV)
>>> +#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
>>> +				 K210_PC_MODE_OUT | K210_PC_OE_INV)
>>> +#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
>>> +
>>> +#define K210_PG_FUNC		GENMASK(7, 0)
>>> +#define K210_PG_DO		BIT(8)
>>> +#define K210_PG_PIN		GENMASK(22, 16)
>>> +
>>> +/*
>>> + * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
>>> + * @pins: 48 32-bits IO pin registers
>>> + * @tie_en: 256 (one per function) input tie enable bits
>>> + * @tie_val: 256 (one per function) input tie value bits
>>> + */
>>> +struct k210_fpioa {
>>> +	u32 pins[48];
>>> +	u32 tie_en[8];
>>> +	u32 tie_val[8];
>>> +};
>>> +
>>> +struct k210_fpioa_data {
>>> +
>>> +	struct device *dev;
>>> +	struct pinctrl_dev *pctl;
>>> +
>>> +	struct k210_fpioa __iomem *fpioa;
>>> +	struct regmap *sysctl_map;
>>> +	u32 power_offset;
>>> +	struct clk *clk;
>>> +	struct clk *pclk;
>>> +};
>>> +
>>> +#define K210_PIN_NAME(i)	("IO_" #i)
>>> +#define K210_PIN(i)		[(i)] = PINCTRL_PIN((i), K210_PIN_NAME(i))
>>> +
>>> +static const struct pinctrl_pin_desc k210_pins[] = {
>>> +	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
>>> +	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
>>> +	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
>>> +	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
>>> +	K210_PIN(12), K210_PIN(13), K210_PIN(14),
>>> +	K210_PIN(15), K210_PIN(16), K210_PIN(17),
>>> +	K210_PIN(18), K210_PIN(19), K210_PIN(20),
>>> +	K210_PIN(21), K210_PIN(22), K210_PIN(23),
>>> +	K210_PIN(24), K210_PIN(25), K210_PIN(26),
>>> +	K210_PIN(27), K210_PIN(28), K210_PIN(29),
>>> +	K210_PIN(30), K210_PIN(31), K210_PIN(32),
>>> +	K210_PIN(33), K210_PIN(34), K210_PIN(35),
>>> +	K210_PIN(36), K210_PIN(37), K210_PIN(38),
>>> +	K210_PIN(39), K210_PIN(40), K210_PIN(41),
>>> +	K210_PIN(42), K210_PIN(43), K210_PIN(44),
>>> +	K210_PIN(45), K210_PIN(46), K210_PIN(47)
>>> +};
>>> +
>>> +#define K210_NPINS ARRAY_SIZE(k210_pins)
>>> +
>>> +/*
>>> + * Pin groups: each of the 48 programmable pins is a group.
>>> + * To this are added 8 power domain groups, which for the purposes of
>>> + * the pin subsystem, contain no pins. The power domain groups only exist
>>> + * to set the power level. The id should never be used (since there are
>>> + * no pins 48-55).
>>> + */
>>> +static const char *const k210_group_names[] = {
>>> +	/* The first 48 groups are for pins, one each */
>>> +	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
>>> +	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
>>> +	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
>>> +	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
>>> +	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
>>> +	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
>>> +	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
>>> +	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
>>> +	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
>>> +	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
>>> +	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
>>> +	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
>>> +	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
>>> +	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
>>> +	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
>>> +	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
>>> +	[48] = "A0", [49] = "A1", [50] = "A2",
>>> +	[51] = "B3", [52] = "B4", [53] = "B5",
>>> +	[54] = "C6", [55] = "C7"
>>> +};
>>> +
>>> +#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
>>> +
>>> +enum k210_pinctrl_mode_id {
>>> +	K210_PC_DEFAULT_DISABLED,
>>> +	K210_PC_DEFAULT_IN,
>>> +	K210_PC_DEFAULT_IN_TIE,
>>> +	K210_PC_DEFAULT_OUT,
>>> +	K210_PC_DEFAULT_I2C,
>>> +	K210_PC_DEFAULT_SCCB,
>>> +	K210_PC_DEFAULT_SPI,
>>> +	K210_PC_DEFAULT_GPIO,
>>> +	K210_PC_DEFAULT_INT13,
>>> +};
>>> +
>>> +#define K210_PC_DEFAULT(mode) \
>>> +	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
>>> +
>>> +static const u32 k210_pinconf_mode_id_to_mode[] = {
>>> +	[K210_PC_DEFAULT_DISABLED] = 0,
>>> +	K210_PC_DEFAULT(IN),
>>> +	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
>>> +	K210_PC_DEFAULT(OUT),
>>> +	K210_PC_DEFAULT(I2C),
>>> +	K210_PC_DEFAULT(SCCB),
>>> +	K210_PC_DEFAULT(SPI),
>>> +	K210_PC_DEFAULT(GPIO),
>>> +	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
>>> +};
>>> +
>>> +#undef DEFAULT
>>> +
>>> +/*
>>> + * Pin functions configuration information.
>>> + */
>>> +struct k210_pcf_info {
>>> +	char name[15];
>>> +	u8 mode_id;
>>> +};
>>> +
>>> +#define K210_FUNC(id, mode)				\
>>> +	[K210_PCF_##id] = {				\
>>> +		.name = #id,				\
>>> +		.mode_id = K210_PC_DEFAULT_##mode	\
>>> +	}
>>> +
>>> +static const struct k210_pcf_info k210_pcf_infos[] = {
>>> +	K210_FUNC(JTAG_TCLK,		IN),
>>> +	K210_FUNC(JTAG_TDI,		IN),
>>> +	K210_FUNC(JTAG_TMS,		IN),
>>> +	K210_FUNC(JTAG_TDO,		OUT),
>>> +	K210_FUNC(SPI0_D0,		SPI),
>>> +	K210_FUNC(SPI0_D1,		SPI),
>>> +	K210_FUNC(SPI0_D2,		SPI),
>>> +	K210_FUNC(SPI0_D3,		SPI),
>>> +	K210_FUNC(SPI0_D4,		SPI),
>>> +	K210_FUNC(SPI0_D5,		SPI),
>>> +	K210_FUNC(SPI0_D6,		SPI),
>>> +	K210_FUNC(SPI0_D7,		SPI),
>>> +	K210_FUNC(SPI0_SS0,		OUT),
>>> +	K210_FUNC(SPI0_SS1,		OUT),
>>> +	K210_FUNC(SPI0_SS2,		OUT),
>>> +	K210_FUNC(SPI0_SS3,		OUT),
>>> +	K210_FUNC(SPI0_ARB,		IN_TIE),
>>> +	K210_FUNC(SPI0_SCLK,		OUT),
>>> +	K210_FUNC(UARTHS_RX,		IN),
>>> +	K210_FUNC(UARTHS_TX,		OUT),
>>> +	K210_FUNC(RESV6,		IN),
>>> +	K210_FUNC(RESV7,		IN),
>>> +	K210_FUNC(CLK_SPI1,		OUT),
>>> +	K210_FUNC(CLK_I2C1,		OUT),
>>> +	K210_FUNC(GPIOHS0,		GPIO),
>>> +	K210_FUNC(GPIOHS1,		GPIO),
>>> +	K210_FUNC(GPIOHS2,		GPIO),
>>> +	K210_FUNC(GPIOHS3,		GPIO),
>>> +	K210_FUNC(GPIOHS4,		GPIO),
>>> +	K210_FUNC(GPIOHS5,		GPIO),
>>> +	K210_FUNC(GPIOHS6,		GPIO),
>>> +	K210_FUNC(GPIOHS7,		GPIO),
>>> +	K210_FUNC(GPIOHS8,		GPIO),
>>> +	K210_FUNC(GPIOHS9,		GPIO),
>>> +	K210_FUNC(GPIOHS10,		GPIO),
>>> +	K210_FUNC(GPIOHS11,		GPIO),
>>> +	K210_FUNC(GPIOHS12,		GPIO),
>>> +	K210_FUNC(GPIOHS13,		GPIO),
>>> +	K210_FUNC(GPIOHS14,		GPIO),
>>> +	K210_FUNC(GPIOHS15,		GPIO),
>>> +	K210_FUNC(GPIOHS16,		GPIO),
>>> +	K210_FUNC(GPIOHS17,		GPIO),
>>> +	K210_FUNC(GPIOHS18,		GPIO),
>>> +	K210_FUNC(GPIOHS19,		GPIO),
>>> +	K210_FUNC(GPIOHS20,		GPIO),
>>> +	K210_FUNC(GPIOHS21,		GPIO),
>>> +	K210_FUNC(GPIOHS22,		GPIO),
>>> +	K210_FUNC(GPIOHS23,		GPIO),
>>> +	K210_FUNC(GPIOHS24,		GPIO),
>>> +	K210_FUNC(GPIOHS25,		GPIO),
>>> +	K210_FUNC(GPIOHS26,		GPIO),
>>> +	K210_FUNC(GPIOHS27,		GPIO),
>>> +	K210_FUNC(GPIOHS28,		GPIO),
>>> +	K210_FUNC(GPIOHS29,		GPIO),
>>> +	K210_FUNC(GPIOHS30,		GPIO),
>>> +	K210_FUNC(GPIOHS31,		GPIO),
>>> +	K210_FUNC(GPIO0,		GPIO),
>>> +	K210_FUNC(GPIO1,		GPIO),
>>> +	K210_FUNC(GPIO2,		GPIO),
>>> +	K210_FUNC(GPIO3,		GPIO),
>>> +	K210_FUNC(GPIO4,		GPIO),
>>> +	K210_FUNC(GPIO5,		GPIO),
>>> +	K210_FUNC(GPIO6,		GPIO),
>>> +	K210_FUNC(GPIO7,		GPIO),
>>> +	K210_FUNC(UART1_RX,		IN),
>>> +	K210_FUNC(UART1_TX,		OUT),
>>> +	K210_FUNC(UART2_RX,		IN),
>>> +	K210_FUNC(UART2_TX,		OUT),
>>> +	K210_FUNC(UART3_RX,		IN),
>>> +	K210_FUNC(UART3_TX,		OUT),
>>> +	K210_FUNC(SPI1_D0,		SPI),
>>> +	K210_FUNC(SPI1_D1,		SPI),
>>> +	K210_FUNC(SPI1_D2,		SPI),
>>> +	K210_FUNC(SPI1_D3,		SPI),
>>> +	K210_FUNC(SPI1_D4,		SPI),
>>> +	K210_FUNC(SPI1_D5,		SPI),
>>> +	K210_FUNC(SPI1_D6,		SPI),
>>> +	K210_FUNC(SPI1_D7,		SPI),
>>> +	K210_FUNC(SPI1_SS0,		OUT),
>>> +	K210_FUNC(SPI1_SS1,		OUT),
>>> +	K210_FUNC(SPI1_SS2,		OUT),
>>> +	K210_FUNC(SPI1_SS3,		OUT),
>>> +	K210_FUNC(SPI1_ARB,		IN_TIE),
>>> +	K210_FUNC(SPI1_SCLK,		OUT),
>>> +	K210_FUNC(SPI2_D0,		SPI),
>>> +	K210_FUNC(SPI2_SS,		IN),
>>> +	K210_FUNC(SPI2_SCLK,		IN),
>>> +	K210_FUNC(I2S0_MCLK,		OUT),
>>> +	K210_FUNC(I2S0_SCLK,		OUT),
>>> +	K210_FUNC(I2S0_WS,		OUT),
>>> +	K210_FUNC(I2S0_IN_D0,		IN),
>>> +	K210_FUNC(I2S0_IN_D1,		IN),
>>> +	K210_FUNC(I2S0_IN_D2,		IN),
>>> +	K210_FUNC(I2S0_IN_D3,		IN),
>>> +	K210_FUNC(I2S0_OUT_D0,		OUT),
>>> +	K210_FUNC(I2S0_OUT_D1,		OUT),
>>> +	K210_FUNC(I2S0_OUT_D2,		OUT),
>>> +	K210_FUNC(I2S0_OUT_D3,		OUT),
>>> +	K210_FUNC(I2S1_MCLK,		OUT),
>>> +	K210_FUNC(I2S1_SCLK,		OUT),
>>> +	K210_FUNC(I2S1_WS,		OUT),
>>> +	K210_FUNC(I2S1_IN_D0,		IN),
>>> +	K210_FUNC(I2S1_IN_D1,		IN),
>>> +	K210_FUNC(I2S1_IN_D2,		IN),
>>> +	K210_FUNC(I2S1_IN_D3,		IN),
>>> +	K210_FUNC(I2S1_OUT_D0,		OUT),
>>> +	K210_FUNC(I2S1_OUT_D1,		OUT),
>>> +	K210_FUNC(I2S1_OUT_D2,		OUT),
>>> +	K210_FUNC(I2S1_OUT_D3,		OUT),
>>> +	K210_FUNC(I2S2_MCLK,		OUT),
>>> +	K210_FUNC(I2S2_SCLK,		OUT),
>>> +	K210_FUNC(I2S2_WS,		OUT),
>>> +	K210_FUNC(I2S2_IN_D0,		IN),
>>> +	K210_FUNC(I2S2_IN_D1,		IN),
>>> +	K210_FUNC(I2S2_IN_D2,		IN),
>>> +	K210_FUNC(I2S2_IN_D3,		IN),
>>> +	K210_FUNC(I2S2_OUT_D0,		OUT),
>>> +	K210_FUNC(I2S2_OUT_D1,		OUT),
>>> +	K210_FUNC(I2S2_OUT_D2,		OUT),
>>> +	K210_FUNC(I2S2_OUT_D3,		OUT),
>>> +	K210_FUNC(RESV0,		DISABLED),
>>> +	K210_FUNC(RESV1,		DISABLED),
>>> +	K210_FUNC(RESV2,		DISABLED),
>>> +	K210_FUNC(RESV3,		DISABLED),
>>> +	K210_FUNC(RESV4,		DISABLED),
>>> +	K210_FUNC(RESV5,		DISABLED),
>>> +	K210_FUNC(I2C0_SCLK,		I2C),
>>> +	K210_FUNC(I2C0_SDA,		I2C),
>>> +	K210_FUNC(I2C1_SCLK,		I2C),
>>> +	K210_FUNC(I2C1_SDA,		I2C),
>>> +	K210_FUNC(I2C2_SCLK,		I2C),
>>> +	K210_FUNC(I2C2_SDA,		I2C),
>>> +	K210_FUNC(DVP_XCLK,		OUT),
>>> +	K210_FUNC(DVP_RST,		OUT),
>>> +	K210_FUNC(DVP_PWDN,		OUT),
>>> +	K210_FUNC(DVP_VSYNC,		IN),
>>> +	K210_FUNC(DVP_HSYNC,		IN),
>>> +	K210_FUNC(DVP_PCLK,		IN),
>>> +	K210_FUNC(DVP_D0,		IN),
>>> +	K210_FUNC(DVP_D1,		IN),
>>> +	K210_FUNC(DVP_D2,		IN),
>>> +	K210_FUNC(DVP_D3,		IN),
>>> +	K210_FUNC(DVP_D4,		IN),
>>> +	K210_FUNC(DVP_D5,		IN),
>>> +	K210_FUNC(DVP_D6,		IN),
>>> +	K210_FUNC(DVP_D7,		IN),
>>> +	K210_FUNC(SCCB_SCLK,		SCCB),
>>> +	K210_FUNC(SCCB_SDA,		SCCB),
>>> +	K210_FUNC(UART1_CTS,		IN),
>>> +	K210_FUNC(UART1_DSR,		IN),
>>> +	K210_FUNC(UART1_DCD,		IN),
>>> +	K210_FUNC(UART1_RI,		IN),
>>> +	K210_FUNC(UART1_SIR_IN,		IN),
>>> +	K210_FUNC(UART1_DTR,		OUT),
>>> +	K210_FUNC(UART1_RTS,		OUT),
>>> +	K210_FUNC(UART1_OUT2,		OUT),
>>> +	K210_FUNC(UART1_OUT1,		OUT),
>>> +	K210_FUNC(UART1_SIR_OUT,	OUT),
>>> +	K210_FUNC(UART1_BAUD,		OUT),
>>> +	K210_FUNC(UART1_RE,		OUT),
>>> +	K210_FUNC(UART1_DE,		OUT),
>>> +	K210_FUNC(UART1_RS485_EN,	OUT),
>>> +	K210_FUNC(UART2_CTS,		IN),
>>> +	K210_FUNC(UART2_DSR,		IN),
>>> +	K210_FUNC(UART2_DCD,		IN),
>>> +	K210_FUNC(UART2_RI,		IN),
>>> +	K210_FUNC(UART2_SIR_IN,		IN),
>>> +	K210_FUNC(UART2_DTR,		OUT),
>>> +	K210_FUNC(UART2_RTS,		OUT),
>>> +	K210_FUNC(UART2_OUT2,		OUT),
>>> +	K210_FUNC(UART2_OUT1,		OUT),
>>> +	K210_FUNC(UART2_SIR_OUT,	OUT),
>>> +	K210_FUNC(UART2_BAUD,		OUT),
>>> +	K210_FUNC(UART2_RE,		OUT),
>>> +	K210_FUNC(UART2_DE,		OUT),
>>> +	K210_FUNC(UART2_RS485_EN,	OUT),
>>> +	K210_FUNC(UART3_CTS,		IN),
>>> +	K210_FUNC(UART3_DSR,		IN),
>>> +	K210_FUNC(UART3_DCD,		IN),
>>> +	K210_FUNC(UART3_RI,		IN),
>>> +	K210_FUNC(UART3_SIR_IN,		IN),
>>> +	K210_FUNC(UART3_DTR,		OUT),
>>> +	K210_FUNC(UART3_RTS,		OUT),
>>> +	K210_FUNC(UART3_OUT2,		OUT),
>>> +	K210_FUNC(UART3_OUT1,		OUT),
>>> +	K210_FUNC(UART3_SIR_OUT,	OUT),
>>> +	K210_FUNC(UART3_BAUD,		OUT),
>>> +	K210_FUNC(UART3_RE,		OUT),
>>> +	K210_FUNC(UART3_DE,		OUT),
>>> +	K210_FUNC(UART3_RS485_EN,	OUT),
>>> +	K210_FUNC(TIMER0_TOGGLE1,	OUT),
>>> +	K210_FUNC(TIMER0_TOGGLE2,	OUT),
>>> +	K210_FUNC(TIMER0_TOGGLE3,	OUT),
>>> +	K210_FUNC(TIMER0_TOGGLE4,	OUT),
>>> +	K210_FUNC(TIMER1_TOGGLE1,	OUT),
>>> +	K210_FUNC(TIMER1_TOGGLE2,	OUT),
>>> +	K210_FUNC(TIMER1_TOGGLE3,	OUT),
>>> +	K210_FUNC(TIMER1_TOGGLE4,	OUT),
>>> +	K210_FUNC(TIMER2_TOGGLE1,	OUT),
>>> +	K210_FUNC(TIMER2_TOGGLE2,	OUT),
>>> +	K210_FUNC(TIMER2_TOGGLE3,	OUT),
>>> +	K210_FUNC(TIMER2_TOGGLE4,	OUT),
>>> +	K210_FUNC(CLK_SPI2,		OUT),
>>> +	K210_FUNC(CLK_I2C2,		OUT),
>>> +	K210_FUNC(INTERNAL0,		OUT),
>>> +	K210_FUNC(INTERNAL1,		OUT),
>>> +	K210_FUNC(INTERNAL2,		OUT),
>>> +	K210_FUNC(INTERNAL3,		OUT),
>>> +	K210_FUNC(INTERNAL4,		OUT),
>>> +	K210_FUNC(INTERNAL5,		OUT),
>>> +	K210_FUNC(INTERNAL6,		OUT),
>>> +	K210_FUNC(INTERNAL7,		OUT),
>>> +	K210_FUNC(INTERNAL8,		OUT),
>>> +	K210_FUNC(INTERNAL9,		IN),
>>> +	K210_FUNC(INTERNAL10,		IN),
>>> +	K210_FUNC(INTERNAL11,		IN),
>>> +	K210_FUNC(INTERNAL12,		IN),
>>> +	K210_FUNC(INTERNAL13,		INT13),
>>> +	K210_FUNC(INTERNAL14,		I2C),
>>> +	K210_FUNC(INTERNAL15,		IN),
>>> +	K210_FUNC(INTERNAL16,		IN),
>>> +	K210_FUNC(INTERNAL17,		IN),
>>> +	K210_FUNC(CONSTANT,		DISABLED),
>>> +	K210_FUNC(INTERNAL18,		IN),
>>> +	K210_FUNC(DEBUG0,		OUT),
>>> +	K210_FUNC(DEBUG1,		OUT),
>>> +	K210_FUNC(DEBUG2,		OUT),
>>> +	K210_FUNC(DEBUG3,		OUT),
>>> +	K210_FUNC(DEBUG4,		OUT),
>>> +	K210_FUNC(DEBUG5,		OUT),
>>> +	K210_FUNC(DEBUG6,		OUT),
>>> +	K210_FUNC(DEBUG7,		OUT),
>>> +	K210_FUNC(DEBUG8,		OUT),
>>> +	K210_FUNC(DEBUG9,		OUT),
>>> +	K210_FUNC(DEBUG10,		OUT),
>>> +	K210_FUNC(DEBUG11,		OUT),
>>> +	K210_FUNC(DEBUG12,		OUT),
>>> +	K210_FUNC(DEBUG13,		OUT),
>>> +	K210_FUNC(DEBUG14,		OUT),
>>> +	K210_FUNC(DEBUG15,		OUT),
>>> +	K210_FUNC(DEBUG16,		OUT),
>>> +	K210_FUNC(DEBUG17,		OUT),
>>> +	K210_FUNC(DEBUG18,		OUT),
>>> +	K210_FUNC(DEBUG19,		OUT),
>>> +	K210_FUNC(DEBUG20,		OUT),
>>> +	K210_FUNC(DEBUG21,		OUT),
>>> +	K210_FUNC(DEBUG22,		OUT),
>>> +	K210_FUNC(DEBUG23,		OUT),
>>> +	K210_FUNC(DEBUG24,		OUT),
>>> +	K210_FUNC(DEBUG25,		OUT),
>>> +	K210_FUNC(DEBUG26,		OUT),
>>> +	K210_FUNC(DEBUG27,		OUT),
>>> +	K210_FUNC(DEBUG28,		OUT),
>>> +	K210_FUNC(DEBUG29,		OUT),
>>> +	K210_FUNC(DEBUG30,		OUT),
>>> +	K210_FUNC(DEBUG31,		OUT),
>>> +};
>>> +
>>> +#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
>>> +#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
>>> +
>>> +static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
>>> +	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
>>> +	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
>>> +};
>>> +
>>> +/*
>>> + * Max drive strength in uA.
>>> + */
>>> +static const int k210_pinconf_drive_strength[] = {
>>> +	[0] = 11200,
>>> +	[1] = 16800,
>>> +	[2] = 22300,
>>> +	[3] = 27800,
>>> +	[4] = 33300,
>>> +	[5] = 38700,
>>> +	[6] = 44100,
>>> +	[7] = 49500,
>>> +};
>>> +
>>> +static int k210_pinconf_get_drive(unsigned int max_strength_ua)
>>> +{
>>> +	int i;
>>> +
>>> +	for (i = K210_PC_DRIVE_MAX; i; i--) {
>>> +		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
>>> +			return i;
>>> +	}
>>> +
>>> +	return -EINVAL;
>>> +}
>>> +
>>> +static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
>>> +					 u32 pin, u32 func)
>>> +{
>>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>>> +	const struct k210_pcf_info *info = &k210_pcf_infos[func];
>>> +	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
>>> +	u32 val = func | mode;
>>> +
>>> +	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
>>> +		pin, info->name, func, val);
>>> +
>>> +	writel(val, &pdata->fpioa->pins[pin]);
>>> +}
>>> +
>>> +static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
>>> +				  unsigned int pin,
>>> +				  unsigned int param, unsigned int arg)
>>> +{
>>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>>> +	u32 val = readl(&pdata->fpioa->pins[pin]);
>>> +	int drive;
>>> +
>>> +	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
>>> +		pin, param, arg);
>>> +
>>> +	switch (param) {
>>> +	case PIN_CONFIG_BIAS_DISABLE:
>>> +		val &= ~K210_PC_BIAS_MASK;
>>> +		break;
>>> +	case PIN_CONFIG_BIAS_PULL_DOWN:
>>> +		if (!arg)
>>> +			return -EINVAL;
>>> +		val |= K210_PC_PD;
>>> +		break;
>>> +	case PIN_CONFIG_BIAS_PULL_UP:
>>> +		if (!arg)
>>> +			return -EINVAL;
>>> +		val |= K210_PC_PD;
>>> +		break;
>>> +	case PIN_CONFIG_DRIVE_STRENGTH:
>>> +		arg *= 1000;
>>> +		fallthrough;
>>> +	case PIN_CONFIG_DRIVE_STRENGTH_UA:
>>> +		drive = k210_pinconf_get_drive(arg);
>>> +		if (drive < 0)
>>> +			return drive;
>>> +		val &= ~K210_PC_DRIVE_MASK;
>>> +		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
>>> +		break;
>>> +	case PIN_CONFIG_INPUT_ENABLE:
>>> +		if (arg)
>>> +			val |= K210_PC_IE;
>>> +		else
>>> +			val &= ~K210_PC_IE;
>>> +		break;
>>> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
>>> +		if (arg)
>>> +			val |= K210_PC_ST;
>>> +		else
>>> +			val &= ~K210_PC_ST;
>>> +		break;
>>> +	case PIN_CONFIG_OUTPUT:
>>> +		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
>>> +		val = readl(&pdata->fpioa->pins[pin]);
>>> +		val |= K210_PC_MODE_OUT;
>>> +		if (!arg)
>>> +			val |= K210_PC_DO_INV;
>>> +		break;
>>> +	case PIN_CONFIG_OUTPUT_ENABLE:
>>> +		if (arg)
>>> +			val |= K210_PC_OE;
>>> +		else
>>> +			val &= ~K210_PC_OE;
>>> +		break;
>>> +	case PIN_CONFIG_SLEW_RATE:
>>> +		if (arg)
>>> +			val |= K210_PC_SL;
>>> +		else
>>> +			val &= ~K210_PC_SL;
>>> +		break;
>>> +	case PIN_CONFIG_OUTPUT_INVERT:
>>> +		if (arg)
>>> +			val |= K210_PC_DO_INV;
>>> +		else
>>> +			val &= ~K210_PC_DO_INV;
>>> +		break;
>>> +	case PIN_CONFIG_INPUT_INVERT:
>>> +		if (arg)
>>> +			val |= K210_PC_DI_INV;
>>> +		else
>>> +			val &= ~K210_PC_DI_INV;
>>> +		break;
>>> +	default:
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	writel(val, &pdata->fpioa->pins[pin]);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
>>> +			    unsigned long *configs, unsigned int num_configs)
>>> +{
>>> +	unsigned int param, arg;
>>> +	int i, ret;
>>> +
>>> +	if (WARN_ON(pin >= K210_NPINS))
>>> +		return -EINVAL;
>>> +
>>> +	for (i = 0; i < num_configs; i++) {
>>> +		param = pinconf_to_config_param(configs[i]);
>>> +		arg = pinconf_to_config_argument(configs[i]);
>>> +		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
>>> +		if (ret)
>>> +			return ret;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
>>> +				  struct seq_file *s, unsigned int pin)
>>> +{
>>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>>> +
>>> +	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
>>> +}
>>> +
>>> +static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
>>> +				  unsigned int selector, unsigned long *configs,
>>> +				  unsigned int num_configs)
>>> +{
>>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>>> +	unsigned int param, arg;
>>> +	u32 bit;
>>> +	int i;
>>> +
>>> +	/* Pins should be configured with pinmux, not groups*/
>>> +	if (selector < K210_NPINS)
>>> +		return -EINVAL;
>>> +
>>> +	/* Otherwise it's a power domain */
>>> +	for (i = 0; i < num_configs; i++) {
>>> +		param = pinconf_to_config_param(configs[i]);
>>> +		if (param != PIN_CONFIG_POWER_SOURCE)
>>> +			return -EINVAL;
>>> +
>>> +		arg = pinconf_to_config_argument(configs[i]);
>>> +		bit = BIT(selector - K210_NPINS);
>>> +		regmap_update_bits(pdata->sysctl_map,
>>> +				   pdata->power_offset,
>>> +				   bit, arg ? bit : 0);
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
>>> +					struct seq_file *s,
>>> +					unsigned int selector)
>>> +{
>>> +	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
>>> +	int ret;
>>> +	u32 val;
>>> +
>>> +	if (selector < K210_NPINS)
>>> +		return k210_pinconf_dbg_show(pctldev, s, selector);
>>> +
>>> +	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
>>> +	if (ret) {
>>> +		dev_err(pdata->dev, "Failed to read power reg\n");
>>> +		return;
>>> +	}
>>> +
>>> +	seq_printf(s, "%s: %s V", k210_group_names[selector],
>>> +		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
>>> +}
>>> +
>>> +static const struct pinconf_ops k210_pinconf_ops = {
>>> +	.is_generic = true,
>>> +	.pin_config_set = k210_pinconf_set,
>>> +	.pin_config_group_set = k210_pinconf_group_set,
>>> +	.pin_config_dbg_show = k210_pinconf_dbg_show,
>>> +	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
>>> +};
>>> +
>>> +static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
>>> +{
>>> +	return ARRAY_SIZE(k210_pcf_infos);
>>> +}
>>> +
>>> +static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
>>> +						 unsigned int selector)
>>> +{
>>> +	return k210_pcf_infos[selector].name;
>>> +}
>>> +
>>> +static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
>>> +					   unsigned int selector,
>>> +					   const char * const **groups,
>>> +					   unsigned int * const num_groups)
>>> +{
>>> +	/* Any function can be mapped to any pin */
>>> +	*groups = k210_group_names;
>>> +	*num_groups = K210_NPINS;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
>>> +			       unsigned int function,
>>> +			       unsigned int group)
>>> +{
>>> +	/* Can't mux power domains */
>>> +	if (group >= K210_NPINS)
>>> +		return -EINVAL;
>>> +
>>> +	k210_pinmux_set_pin_function(pctldev, group, function);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct pinmux_ops k210_pinmux_ops = {
>>> +	.get_functions_count = k210_pinmux_get_function_count,
>>> +	.get_function_name = k210_pinmux_get_function_name,
>>> +	.get_function_groups = k210_pinmux_get_function_groups,
>>> +	.set_mux = k210_pinmux_set_mux,
>>> +	.strict = true,
>>> +};
>>> +
>>> +static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
>>> +{
>>> +	return K210_NGROUPS;
>>> +}
>>> +
>>> +static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
>>> +					       unsigned int group)
>>> +{
>>> +	return k210_group_names[group];
>>> +}
>>> +
>>> +static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
>>> +				       unsigned int group,
>>> +				       const unsigned int **pins,
>>> +				       unsigned int *npins)
>>> +{
>>> +	if (group >= K210_NPINS) {
>>> +		*pins = NULL;
>>> +		*npins = 0;
>>> +		return 0;
>>> +	}
>>> +
>>> +	*pins = &k210_pins[group].number;
>>> +	*npins = 1;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
>>> +				      struct seq_file *s, unsigned int offset)
>>> +{
>>> +	seq_printf(s, "%s", dev_name(pctldev->dev));
>>> +}
>>> +
>>> +static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
>>> +					  struct device_node *np,
>>> +					  struct pinctrl_map **map,
>>> +					  unsigned int *reserved_maps,
>>> +					  unsigned int *num_maps)
>>> +{
>>> +	struct property *prop;
>>> +	const __be32 *p;
>>> +	int ret, pinmux_groups;
>>> +	u32 pinmux_group;
>>> +	unsigned long *configs = NULL;
>>> +	unsigned int num_configs = 0;
>>> +	unsigned int reserve = 0;
>>> +
>>> +	ret = of_property_count_strings(np, "groups");
>>> +	if (!ret)
>>> +		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
>>> +						reserved_maps, num_maps,
>>> +						PIN_MAP_TYPE_CONFIGS_GROUP);
>>> +
>>> +	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
>>> +	if (pinmux_groups <= 0) {
>>> +		/* Ignore this node */
>>> +		return 0;
>>> +	}
>>> +
>>> +	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
>>> +					      &num_configs);
>>> +	if (ret < 0) {
>>> +		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
>>> +			np);
>>> +		return ret;
>>> +	}
>>> +
>>> +	reserve = pinmux_groups * (1 + num_configs);
>>> +	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
>>> +					reserve);
>>> +	if (ret < 0)
>>> +		goto exit;
>>> +
>>> +	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
>>> +		const char *group_name, *func_name;
>>> +		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
>>> +		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
>>> +
>>> +		if (pin >= K210_NPINS) {
>>> +			ret = -EINVAL;
>>> +			goto exit;
>>> +		}
>>> +
>>> +		group_name = k210_group_names[pin];
>>> +		func_name = k210_pcf_infos[func].name;
>>> +
>>> +		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
>>> +			np->name, pin, func_name);
>>> +
>>> +		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
>>> +						num_maps, group_name,
>>> +						func_name);
>>> +		if (ret < 0) {
>>> +			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
>>> +				np, ret);
>>> +			goto exit;
>>> +		}
>>> +
>>> +		if (num_configs) {
>>> +			ret = pinctrl_utils_add_map_configs(pctldev, map,
>>> +					reserved_maps, num_maps, group_name,
>>> +					configs, num_configs,
>>> +					PIN_MAP_TYPE_CONFIGS_PIN);
>>> +			if (ret < 0) {
>>> +				dev_err(pctldev->dev,
>>> +					"%pOF add configs map failed %d\n",
>>> +					np, ret);
>>> +				goto exit;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	ret = 0;
>>> +
>>> +exit:
>>> +	kfree(configs);
>>> +	return ret;
>>> +}
>>> +
>>> +static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
>>> +				       struct device_node *np_config,
>>> +				       struct pinctrl_map **map,
>>> +				       unsigned int *num_maps)
>>> +{
>>> +	unsigned int reserved_maps;
>>> +	struct device_node *np;
>>> +	int ret;
>>> +
>>> +	reserved_maps = 0;
>>> +	*map = NULL;
>>> +	*num_maps = 0;
>>> +
>>> +	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
>>> +					     &reserved_maps, num_maps);
>>> +	if (ret < 0)
>>> +		goto err;
>>> +
>>> +	for_each_available_child_of_node(np_config, np) {
>>> +		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
>>> +						     &reserved_maps, num_maps);
>>> +		if (ret < 0)
>>> +			goto err;
>>> +	}
>>> +	return 0;
>>> +
>>> +err:
>>> +	pinctrl_utils_free_map(pctldev, *map, *num_maps);
>>> +	return ret;
>>> +}
>>> +
>>> +
>>> +static const struct pinctrl_ops k210_pinctrl_ops = {
>>> +	.get_groups_count = k210_pinctrl_get_groups_count,
>>> +	.get_group_name = k210_pinctrl_get_group_name,
>>> +	.get_group_pins = k210_pinctrl_get_group_pins,
>>> +	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
>>> +	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
>>> +	.dt_free_map = pinconf_generic_dt_free_map,
>>> +};
>>> +
>>> +static struct pinctrl_desc k210_pinctrl_desc = {
>>> +	.name = "k210-pinctrl",
>>> +	.pins = k210_pins,
>>> +	.npins = K210_NPINS,
>>> +	.pctlops = &k210_pinctrl_ops,
>>> +	.pmxops = &k210_pinmux_ops,
>>> +	.confops = &k210_pinconf_ops,
>>> +	.custom_params = k210_pinconf_custom_params,
>>> +	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
>>> +};
>>> +
>>> +static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
>>> +{
>>> +	struct k210_fpioa __iomem *fpioa = pdata->fpioa;
>>> +	u32 val;
>>> +	int i, j;
>>> +
>>> +	dev_dbg(pdata->dev, "Init pin ties\n");
>>> +
>>> +	/* Init pin functions input ties */
>>> +	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
>>> +		val = 0;
>>> +		for (j = 0; j < 32; j++) {
>>> +			if (k210_pcf_infos[i * 32 + j].mode_id ==
>>> +			    K210_PC_DEFAULT_IN_TIE) {
>>> +				dev_dbg(pdata->dev,
>>> +					"tie_en function %d (%s)\n",
>>> +					i * 32 + j,
>>> +					k210_pcf_infos[i * 32 + j].name);
>>> +				val |= BIT(j);
>>> +			}
>>> +		}
>>> +
>>> +		/* Set value before enable */
>>> +		writel(val, &fpioa->tie_val[i]);
>>> +		writel(val, &fpioa->tie_en[i]);
>>> +	}
>>> +}
>>> +
>>> +static int k210_fpioa_probe(struct platform_device *pdev)
>>> +{
>>> +	struct device *dev = &pdev->dev;
>>> +	struct device_node *np = dev->of_node;
>>> +	struct k210_fpioa_data *pdata;
>>> +	int ret;
>>> +
>>> +	dev_info(dev, "K210 FPIOA pin controller\n");
>>> +
>>> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>>> +	if (!pdata)
>>> +		return -ENOMEM;
>>> +
>>> +	pdata->dev = dev;
>>> +	platform_set_drvdata(pdev, pdata);
>>> +
>>> +	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
>>> +	if (IS_ERR(pdata->fpioa))
>>> +		return PTR_ERR(pdata->fpioa);
>>> +
>>> +	pdata->clk = devm_clk_get(dev, "ref");
>>> +	if (IS_ERR(pdata->clk))
>>> +		return PTR_ERR(pdata->clk);
>>> +
>>> +	ret = clk_prepare_enable(pdata->clk);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	pdata->pclk = devm_clk_get_optional(dev, "pclk");
>>> +	if (!IS_ERR(pdata->pclk))
>>> +		clk_prepare_enable(pdata->pclk);
>>> +
>>> +	pdata->sysctl_map =
>>> +		syscon_regmap_lookup_by_phandle_args(np,
>>> +						"canaan,k210-sysctl-power",
>>> +						1, &pdata->power_offset);
>>> +	if (IS_ERR(pdata->sysctl_map))
>>> +		return PTR_ERR(pdata->sysctl_map);
>>> +
>>> +	k210_fpioa_init_ties(pdata);
>>> +
>>> +	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
>>> +	if (IS_ERR(pdata->pctl))
>>> +		return PTR_ERR(pdata->pctl);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct of_device_id k210_fpioa_dt_ids[] = {
>>> +	{ .compatible = "canaan,k210-fpioa" },
>>> +	{ /* sentinel */ },
>>> +};
>>> +
>>> +static struct platform_driver k210_fpioa_driver = {
>>> +	.probe	= k210_fpioa_probe,
>>> +	.driver = {
>>> +		.name		= "k210-fpioa",
>>> +		.of_match_table	= k210_fpioa_dt_ids,
>>> +	},
>>> +};
>>> +builtin_platform_driver(k210_fpioa_driver);
>>
> 
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-15  0:35         ` Sean Anderson
@ 2021-01-15  1:03           ` Damien Le Moal
  2021-01-15  1:14             ` Sean Anderson
  0 siblings, 1 reply; 24+ messages in thread
From: Damien Le Moal @ 2021-01-15  1:03 UTC (permalink / raw)
  To: Sean Anderson, Palmer Dabbelt; +Cc: linux-riscv, Linus Walleij

On 2021/01/15 9:35, Sean Anderson wrote:
> On 1/14/21 7:06 PM, Sean Anderson wrote:
>>
>> On 1/14/21 7:01 PM, Sean Anderson wrote:
>>>
>>> On 1/14/21 6:32 PM, Palmer Dabbelt wrote:
>>>> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>>>>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>>>>> all peripherals of the SoC, their clocks and reset lines. The device
>>>>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>>>>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>>>>> configuration option. No device beside the serial console is defined by
>>>>> this device tree. This makes this generic device tree suitable for use
>>>>> with a builtin initramfs with all known K210 based boards.
>>>>>
>>>>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>>>>> removed from the dt-bindings k210-clk.h header file.
>>>>>
>>>>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>>>>> U-Boot support for the K210.
>>>>>
>>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>>> Reviewed-by: Anup Patel <anup@brainfault.org>
>>>>> ---
>>>>>  arch/riscv/Kconfig.socs                     |   2 +-
>>>>>  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>>>>  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>>>>  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>>>>  include/dt-bindings/clock/k210-clk.h        |   1 -
>>>>>  5 files changed, 573 insertions(+), 50 deletions(-)
>>>>>  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>>>>  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>>>>
>>>> [Snipping this to the relevant bits, in case you missed it before.]
>>>>
>>>>> @@ -81,40 +107,515 @@ in0: oscillator {
>>>>>      soc {
>>>>>          #address-cells = <1>;
>>>>>          #size-cells = <1>;
>>>>> -        compatible = "kendryte,k210-soc", "simple-bus";
>>>>> +        compatible = "canaan,k210-soc", "simple-bus";
>>>>>          ranges;
>>>>>          interrupt-parent = <&plic0>;
>>>>>
>>>>> -        sysctl: sysctl@50440000 {
>>>>> -            compatible = "kendryte,k210-sysctl", "simple-mfd";
>>>>> -            reg = <0x50440000 0x1000>;
>>>>> -            #clock-cells = <1>;
>>>>> +        debug0: debug@0 {
>>>>> +            compatible = "canaan,k210-debug", "riscv,debug";
>>>>
>>>> I'm still getting lots of warnings about undocumented DT compatible strings
>>>> from checpatch.  Some of them might be in flight, but I don't see many of them
>>>> (including both of these debug ones) having been defined anywhere.  We went
>>>> through a whole process to sort out the SiFive DT naming conventions, I don't
>>>> want to just circumvent that for the Canaan stuff by merging it as-is.
>>>
>>> As far as I'm aware, it's recommended practice to add device-specific compatible
>>>
>>
>> Here it's because "riscv,debug" doesn't exist. This is the "debug"
>> device as described in the debug spec. AFAIK Linux never needs to
>> configure this device. It could probably be removed.
>>
>> I am going to try and go through the list of nonexistant compatibles and
>> see if there are any other devices like this (nothing else like it in
>> Linux).
>>
>> --Sean
> 
> Ok, here is the (abbreviated) output:
> 
> 
>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>> cpu@0: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
> 
> This is a device-specific compatible string as recommended by the
> current DT docs.
> 
>> cpu@0: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
> 
> This should be added (though it is technically incorrect).

will do.

> 
> (perhaps a version number should be added like 'riscv,sv39-1.10')
> 
>> cpu@0: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
> 
> Should probably be fixed, as the g is redundant. However, this is
> probably not a good warning going forward, as more exotic combinations
> of extensions are implemented.

I had removed the "g" here. I guess I messed up a rebase and it is back. Will
fix that.

> 
>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>> cpu@1: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
>>
>> cpu@1: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
>> cpu@1: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
> 
> see above
> 
>> serial@38000000: compatible:0: 'canaan,k210-uarths' is not one of ['sifive,fu540-c000-uart', 'sifive,fu740-c000-uart']
> 
> device-specific, and intentional

We can add this one to the sifive serial yaml.

> 
>> gpio-controller@38001000: compatible:0: 'canaan,k210-gpiohs' is not one of ['sifive,fu540-c000-gpio', 'sifive,fu740-c000-gpio']
> 
> ditto
> 
>> gpio-controller@38001000: 'ngpios' does not match any of the regexes: 'pinctrl-[0-9]+'
> 
> known shortcoming with this dt property, but alas

Yes. The driver was fixed. But the yaml is behind I guess. Will send a patch for
this one.

> 
>> gpio-controller@50200000: $nodename:0: 'gpio-controller@50200000' does not match '^gpio@[0-9a-f]+$'
> 
> This matches devicetree/bindings/gpio/snps,dw-apb-gpio.yaml

This may be similar to the ngpios problem: the core expect something while the
yaml defines something older... Will have a look.

> 
>> gpio-controller@50200000: compatible: ['canaan,k210-gpio', 'snps,dw-apb-gpio'] is too long
>> gpio-controller@50200000: compatible: Additional items are not allowed ('snps,dw-apb-gpio' was unexpected)

I wonder if we can just remove 'canaan,k210-gpio' here ?

>> gpio-controller@50200000: 'gpio1@0' does not match any of the regexes: '^gpio-(port|controller)@[0-9a-f]+$', 'pinctrl-[0-9]+'

Not sure what to do about this one.

>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>
>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>
>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
> 
> More device-specific strings.
> 
>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
> 
> ditto

Actually a false warning from checkpatch. canaan,k210-spi was already added to
the DW spi yaml.

> 
>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>
>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>
>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
> 
> ditto
> 
>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>> timer@502D0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>
>> timer@502D0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
> 
> `resets` is the correct name for this property.
> 
>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>> timer@502E0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
> 
> More device-specific.
> 
>> timer@502E0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>> timer@502F0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>
>> timer@502F0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>> watchdog@50400000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>
>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>> watchdog@50410000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>
>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>
>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']

canaan,k210-spi is already added to the dw spi doc. Will check that again.
canaan,k210-ssi is missing though but since there is no quirk associated with
it, we should not need to mention it in the yaml.

>>
>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is not valid under any of the given schemas (Possible causes of the failure):
>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is too long
>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
> 
> Ok, so the vast majority of these warnings are from unknown compatible
> strings. IMO this is not an issue, but the simple fix is to just add
> these strings to the yaml files.

We could, but given that checkpatch spits out warnings for the ones already
added, we should probably start with fixing checkpatch :)

And there are some nodes that have no drive in Linux, so no yaml. So a warning
will remain for these but I do not want to remove the nodes.

Thansk for checking all this !


> 
> --Sean
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-15  1:03           ` Damien Le Moal
@ 2021-01-15  1:14             ` Sean Anderson
  2021-01-15  1:18               ` Damien Le Moal
  0 siblings, 1 reply; 24+ messages in thread
From: Sean Anderson @ 2021-01-15  1:14 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt; +Cc: linux-riscv, Linus Walleij

On 1/14/21 8:03 PM, Damien Le Moal wrote:
> On 2021/01/15 9:35, Sean Anderson wrote:
>> On 1/14/21 7:06 PM, Sean Anderson wrote:
>>>
>>> On 1/14/21 7:01 PM, Sean Anderson wrote:
>>>>
>>>> On 1/14/21 6:32 PM, Palmer Dabbelt wrote:
>>>>> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>>>>>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>>>>>> all peripherals of the SoC, their clocks and reset lines. The device
>>>>>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>>>>>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>>>>>> configuration option. No device beside the serial console is defined by
>>>>>> this device tree. This makes this generic device tree suitable for use
>>>>>> with a builtin initramfs with all known K210 based boards.
>>>>>>
>>>>>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>>>>>> removed from the dt-bindings k210-clk.h header file.
>>>>>>
>>>>>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>>>>>> U-Boot support for the K210.
>>>>>>
>>>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>>>> Reviewed-by: Anup Patel <anup@brainfault.org>
>>>>>> ---
>>>>>>   arch/riscv/Kconfig.socs                     |   2 +-
>>>>>>   arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>>>>>   arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>>>>>   arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>>>>>   include/dt-bindings/clock/k210-clk.h        |   1 -
>>>>>>   5 files changed, 573 insertions(+), 50 deletions(-)
>>>>>>   delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>>>>>   create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>>>>>
>>>>> [Snipping this to the relevant bits, in case you missed it before.]
>>>>>
>>>>>> @@ -81,40 +107,515 @@ in0: oscillator {
>>>>>>       soc {
>>>>>>           #address-cells = <1>;
>>>>>>           #size-cells = <1>;
>>>>>> -        compatible = "kendryte,k210-soc", "simple-bus";
>>>>>> +        compatible = "canaan,k210-soc", "simple-bus";
>>>>>>           ranges;
>>>>>>           interrupt-parent = <&plic0>;
>>>>>>
>>>>>> -        sysctl: sysctl@50440000 {
>>>>>> -            compatible = "kendryte,k210-sysctl", "simple-mfd";
>>>>>> -            reg = <0x50440000 0x1000>;
>>>>>> -            #clock-cells = <1>;
>>>>>> +        debug0: debug@0 {
>>>>>> +            compatible = "canaan,k210-debug", "riscv,debug";
>>>>>
>>>>> I'm still getting lots of warnings about undocumented DT compatible strings
>>>>> from checpatch.  Some of them might be in flight, but I don't see many of them
>>>>> (including both of these debug ones) having been defined anywhere.  We went
>>>>> through a whole process to sort out the SiFive DT naming conventions, I don't
>>>>> want to just circumvent that for the Canaan stuff by merging it as-is.
>>>>
>>>> As far as I'm aware, it's recommended practice to add device-specific compatible
>>>>
>>>
>>> Here it's because "riscv,debug" doesn't exist. This is the "debug"
>>> device as described in the debug spec. AFAIK Linux never needs to
>>> configure this device. It could probably be removed.
>>>
>>> I am going to try and go through the list of nonexistant compatibles and
>>> see if there are any other devices like this (nothing else like it in
>>> Linux).
>>>
>>> --Sean
>>
>> Ok, here is the (abbreviated) output:
>>
>>
>>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>>> cpu@0: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
>>
>> This is a device-specific compatible string as recommended by the
>> current DT docs.
>>
>>> cpu@0: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
>>
>> This should be added (though it is technically incorrect).
> 
> will do.
> 
>>
>> (perhaps a version number should be added like 'riscv,sv39-1.10')
>>
>>> cpu@0: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
>>
>> Should probably be fixed, as the g is redundant. However, this is
>> probably not a good warning going forward, as more exotic combinations
>> of extensions are implemented.
> 
> I had removed the "g" here. I guess I messed up a rebase and it is back. Will
> fix that.
> 
>>
>>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>>> cpu@1: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
>>>
>>> cpu@1: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
>>> cpu@1: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
>>
>> see above
>>
>>> serial@38000000: compatible:0: 'canaan,k210-uarths' is not one of ['sifive,fu540-c000-uart', 'sifive,fu740-c000-uart']
>>
>> device-specific, and intentional
> 
> We can add this one to the sifive serial yaml.
> 
>>
>>> gpio-controller@38001000: compatible:0: 'canaan,k210-gpiohs' is not one of ['sifive,fu540-c000-gpio', 'sifive,fu740-c000-gpio']
>>
>> ditto
>>
>>> gpio-controller@38001000: 'ngpios' does not match any of the regexes: 'pinctrl-[0-9]+'
>>
>> known shortcoming with this dt property, but alas
> 
> Yes. The driver was fixed. But the yaml is behind I guess. Will send a patch for
> this one.
> 
>>
>>> gpio-controller@50200000: $nodename:0: 'gpio-controller@50200000' does not match '^gpio@[0-9a-f]+$'
>>
>> This matches devicetree/bindings/gpio/snps,dw-apb-gpio.yaml
> 
> This may be similar to the ngpios problem: the core expect something while the
> yaml defines something older... Will have a look.
> 
>>
>>> gpio-controller@50200000: compatible: ['canaan,k210-gpio', 'snps,dw-apb-gpio'] is too long
>>> gpio-controller@50200000: compatible: Additional items are not allowed ('snps,dw-apb-gpio' was unexpected)
> 
> I wonder if we can just remove 'canaan,k210-gpio' here ?
> 
>>> gpio-controller@50200000: 'gpio1@0' does not match any of the regexes: '^gpio-(port|controller)@[0-9a-f]+$', 'pinctrl-[0-9]+'
> 
> Not sure what to do about this one.
> 
>>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>>
>>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>>
>>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>
>> More device-specific strings.
>>
>>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>
>> ditto
> 
> Actually a false warning from checkpatch. canaan,k210-spi was already added to
> the DW spi yaml.
> 
>>
>>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>>
>>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>>
>>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>
>> ditto
>>
>>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>> timer@502D0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>>
>>> timer@502D0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>
>> `resets` is the correct name for this property.
>>
>>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>> timer@502E0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>
>> More device-specific.
>>
>>> timer@502E0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>> timer@502F0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>>
>>> timer@502F0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>>> watchdog@50400000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>>
>>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>>> watchdog@50410000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>>
>>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>>
>>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
> 
> canaan,k210-spi is already added to the dw spi doc. Will check that again.
> canaan,k210-ssi is missing though but since there is no quirk associated with
> it, we should not need to mention it in the yaml.
> 
>>>
>>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is not valid under any of the given schemas (Possible causes of the failure):
>>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is too long
>>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>
>> Ok, so the vast majority of these warnings are from unknown compatible
>> strings. IMO this is not an issue, but the simple fix is to just add
>> these strings to the yaml files.
> 
> We could, but given that checkpatch spits out warnings for the ones already
> added, we should probably start with fixing checkpatch :)

Well, it could also be that I was on the wrong branch, or had some old
build artifacts.

> 
> And there are some nodes that have no drive in Linux, so no yaml. So a warning
> will remain for these but I do not want to remove the nodes.
> 
> Thansk for checking all this !

Just install dt-schema and you can check it too ;)

--Sean

> 
> 
>>
>> --Sean
>>
> 
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-15  1:14             ` Sean Anderson
@ 2021-01-15  1:18               ` Damien Le Moal
  0 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-15  1:18 UTC (permalink / raw)
  To: Sean Anderson, Palmer Dabbelt; +Cc: linux-riscv, Linus Walleij

On 2021/01/15 10:14, Sean Anderson wrote:
> On 1/14/21 8:03 PM, Damien Le Moal wrote:
>> On 2021/01/15 9:35, Sean Anderson wrote:
>>> On 1/14/21 7:06 PM, Sean Anderson wrote:
>>>>
>>>> On 1/14/21 7:01 PM, Sean Anderson wrote:
>>>>>
>>>>> On 1/14/21 6:32 PM, Palmer Dabbelt wrote:
>>>>>> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
>>>>>>> Update the Canaan Kendryte K210 base device tree k210.dtsi to define
>>>>>>> all peripherals of the SoC, their clocks and reset lines. The device
>>>>>>> tree file k210.dts is renamed to k210_generic.dts and becomes the
>>>>>>> default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
>>>>>>> configuration option. No device beside the serial console is defined by
>>>>>>> this device tree. This makes this generic device tree suitable for use
>>>>>>> with a builtin initramfs with all known K210 based boards.
>>>>>>>
>>>>>>> These changes result in the K210_CLK_ACLK clock ID to be unused and
>>>>>>> removed from the dt-bindings k210-clk.h header file.
>>>>>>>
>>>>>>> Most updates to the k210.dtsi file come from Sean Anderson's work on
>>>>>>> U-Boot support for the K210.
>>>>>>>
>>>>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>>>>> Reviewed-by: Anup Patel <anup@brainfault.org>
>>>>>>> ---
>>>>>>>   arch/riscv/Kconfig.socs                     |   2 +-
>>>>>>>   arch/riscv/boot/dts/canaan/k210.dts         |  23 -
>>>>>>>   arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
>>>>>>>   arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
>>>>>>>   include/dt-bindings/clock/k210-clk.h        |   1 -
>>>>>>>   5 files changed, 573 insertions(+), 50 deletions(-)
>>>>>>>   delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
>>>>>>>   create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
>>>>>>
>>>>>> [Snipping this to the relevant bits, in case you missed it before.]
>>>>>>
>>>>>>> @@ -81,40 +107,515 @@ in0: oscillator {
>>>>>>>       soc {
>>>>>>>           #address-cells = <1>;
>>>>>>>           #size-cells = <1>;
>>>>>>> -        compatible = "kendryte,k210-soc", "simple-bus";
>>>>>>> +        compatible = "canaan,k210-soc", "simple-bus";
>>>>>>>           ranges;
>>>>>>>           interrupt-parent = <&plic0>;
>>>>>>>
>>>>>>> -        sysctl: sysctl@50440000 {
>>>>>>> -            compatible = "kendryte,k210-sysctl", "simple-mfd";
>>>>>>> -            reg = <0x50440000 0x1000>;
>>>>>>> -            #clock-cells = <1>;
>>>>>>> +        debug0: debug@0 {
>>>>>>> +            compatible = "canaan,k210-debug", "riscv,debug";
>>>>>>
>>>>>> I'm still getting lots of warnings about undocumented DT compatible strings
>>>>>> from checpatch.  Some of them might be in flight, but I don't see many of them
>>>>>> (including both of these debug ones) having been defined anywhere.  We went
>>>>>> through a whole process to sort out the SiFive DT naming conventions, I don't
>>>>>> want to just circumvent that for the Canaan stuff by merging it as-is.
>>>>>
>>>>> As far as I'm aware, it's recommended practice to add device-specific compatible
>>>>>
>>>>
>>>> Here it's because "riscv,debug" doesn't exist. This is the "debug"
>>>> device as described in the debug spec. AFAIK Linux never needs to
>>>> configure this device. It could probably be removed.
>>>>
>>>> I am going to try and go through the list of nonexistant compatibles and
>>>> see if there are any other devices like this (nothing else like it in
>>>> Linux).
>>>>
>>>> --Sean
>>>
>>> Ok, here is the (abbreviated) output:
>>>
>>>
>>>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> cpu@0: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>>>> cpu@0: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
>>>
>>> This is a device-specific compatible string as recommended by the
>>> current DT docs.
>>>
>>>> cpu@0: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
>>>
>>> This should be added (though it is technically incorrect).
>>
>> will do.
>>
>>>
>>> (perhaps a version number should be added like 'riscv,sv39-1.10')
>>>
>>>> cpu@0: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
>>>
>>> Should probably be fixed, as the g is redundant. However, this is
>>> probably not a good warning going forward, as more exotic combinations
>>> of extensions are implemented.
>>
>> I had removed the "g" here. I guess I messed up a rebase and it is back. Will
>> fix that.
>>
>>>
>>>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> cpu@1: compatible: ['canaan,k210', 'sifive,rocket0', 'riscv'] is too long
>>>> cpu@1: compatible:0: 'canaan,k210' is not one of ['sifive,rocket0', 'sifive,bullet0', 'sifive,e5', 'sifive,e7', 'sifive,e51', 'sifive,e71', 'sifive,u54-mc', 'sifive,u74-mc', 'sifive,u54', 'sifive,u74', 'sifive,u5', 'sifive,u7']
>>>>
>>>> cpu@1: mmu-type:0: 'none' is not one of ['riscv,sv32', 'riscv,sv39', 'riscv,sv48']
>>>> cpu@1: riscv,isa:0: 'rv64imafdgc' is not one of ['rv64imac', 'rv64imafdc']
>>>
>>> see above
>>>
>>>> serial@38000000: compatible:0: 'canaan,k210-uarths' is not one of ['sifive,fu540-c000-uart', 'sifive,fu740-c000-uart']
>>>
>>> device-specific, and intentional
>>
>> We can add this one to the sifive serial yaml.
>>
>>>
>>>> gpio-controller@38001000: compatible:0: 'canaan,k210-gpiohs' is not one of ['sifive,fu540-c000-gpio', 'sifive,fu740-c000-gpio']
>>>
>>> ditto
>>>
>>>> gpio-controller@38001000: 'ngpios' does not match any of the regexes: 'pinctrl-[0-9]+'
>>>
>>> known shortcoming with this dt property, but alas
>>
>> Yes. The driver was fixed. But the yaml is behind I guess. Will send a patch for
>> this one.
>>
>>>
>>>> gpio-controller@50200000: $nodename:0: 'gpio-controller@50200000' does not match '^gpio@[0-9a-f]+$'
>>>
>>> This matches devicetree/bindings/gpio/snps,dw-apb-gpio.yaml
>>
>> This may be similar to the ngpios problem: the core expect something while the
>> yaml defines something older... Will have a look.
>>
>>>
>>>> gpio-controller@50200000: compatible: ['canaan,k210-gpio', 'snps,dw-apb-gpio'] is too long
>>>> gpio-controller@50200000: compatible: Additional items are not allowed ('snps,dw-apb-gpio' was unexpected)
>>
>> I wonder if we can just remove 'canaan,k210-gpio' here ?
>>
>>>> gpio-controller@50200000: 'gpio1@0' does not match any of the regexes: '^gpio-(port|controller)@[0-9a-f]+$', 'pinctrl-[0-9]+'
>>
>> Not sure what to do about this one.
>>
>>>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> serial@50210000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>>> serial@50210000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>>>
>>>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> serial@50220000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>>> serial@50220000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>>>
>>>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> serial@50230000: compatible: ['canaan,k210-uart', 'snps,dw-apb-uart'] is too long
>>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['renesas,r9a06g032-uart', 'renesas,r9a06g033-uart']
>>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['rockchip,px30-uart', 'rockchip,rk3036-uart', 'rockchip,rk3066-uart', 'rockchip,rk3188-uart', 'rockchip,rk3288-uart', 'rockchip,rk3308-uart', 'rockchip,rk3328-uart', 'rockchip,rk3368-uart', 'rockchip,rk3399-uart', 'rockchip,rv1108-uart']
>>>> serial@50230000: compatible:0: 'canaan,k210-uart' is not one of ['brcm,bcm11351-dw-apb-uart', 'brcm,bcm21664-dw-apb-uart']
>>>
>>> More device-specific strings.
>>>
>>>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> spi@50240000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>>> spi@50240000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>>
>>> ditto
>>
>> Actually a false warning from checkpatch. canaan,k210-spi was already added to
>> the DW spi yaml.
>>
>>>
>>>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> i2c@50280000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>>>
>>>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> i2c@50290000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>>>
>>>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> i2c@502A0000: compatible: ['canaan,k210-i2c', 'snps,designware-i2c'] is too long
>>>
>>> ditto
>>>
>>>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> timer@502D0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>>> timer@502D0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>>>
>>>> timer@502D0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>>
>>> `resets` is the correct name for this property.
>>>
>>>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> timer@502E0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>>> timer@502E0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>>
>>> More device-specific.
>>>
>>>> timer@502E0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> timer@502F0000: compatible: ['canaan,k210-timer', 'snps,dw-apb-timer'] is too long
>>>> timer@502F0000: compatible:0: 'canaan,k210-timer' is not one of ['snps,dw-apb-timer-sp', 'snps,dw-apb-timer-osc']
>>>>
>>>> timer@502F0000: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+'
>>>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> watchdog@50400000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>>>> watchdog@50400000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>>>
>>>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> watchdog@50410000: compatible: ['canaan,k210-wdt', 'snps,dw-wdt'] is too long
>>>> watchdog@50410000: compatible:0: 'canaan,k210-wdt' is not one of ['rockchip,rk3066-wdt', 'rockchip,rk3188-wdt', 'rockchip,rk3288-wdt', 'rockchip,rk3368-wdt']
>>>>
>>>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> spi@52000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>>> spi@52000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>>>
>>>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> spi@53000000: compatible: ['canaan,k210-spi', 'snps,dw-apb-ssi-4.01', 'snps,dw-apb-ssi'] is too long
>>>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>>> spi@53000000: compatible:0: 'canaan,k210-spi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>
>> canaan,k210-spi is already added to the dw spi doc. Will check that again.
>> canaan,k210-ssi is missing though but since there is no quirk associated with
>> it, we should not need to mention it in the yaml.
>>
>>>>
>>>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is not valid under any of the given schemas (Possible causes of the failure):
>>>> spi@54000000: compatible: ['canaan,k210-ssi', 'snps,dwc-ssi-1.01a'] is too long
>>>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['snps,dw-apb-ssi', 'snps,dwc-ssi-1.01a']
>>>> spi@54000000: compatible:0: 'canaan,k210-ssi' is not one of ['mscc,ocelot-spi', 'mscc,jaguar2-spi']
>>>
>>> Ok, so the vast majority of these warnings are from unknown compatible
>>> strings. IMO this is not an issue, but the simple fix is to just add
>>> these strings to the yaml files.
>>
>> We could, but given that checkpatch spits out warnings for the ones already
>> added, we should probably start with fixing checkpatch :)
> 
> Well, it could also be that I was on the wrong branch, or had some old
> build artifacts.

Any branch based on 5.11 has the DW SPI fixes already. That was queued during
the last cycle.

> 
>>
>> And there are some nodes that have no drive in Linux, so no yaml. So a warning
>> will remain for these but I do not want to remove the nodes.
>>
>> Thansk for checking all this !
> 
> Just install dt-schema and you can check it too ;)

I have that installed already. Will rerun the check to reduce the amount of
warnings.

> 
> --Sean
> 
>>
>>
>>>
>>> --Sean
>>>
>>
>>
> 
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree
  2021-01-14 23:32   ` Palmer Dabbelt
       [not found]     ` <9d32abd1-ffb4-a887-a40d-fc173a371d23@gmail.com>
  2021-01-15  0:33     ` Damien Le Moal
@ 2021-01-15  5:56     ` Damien Le Moal
  2 siblings, 0 replies; 24+ messages in thread
From: Damien Le Moal @ 2021-01-15  5:56 UTC (permalink / raw)
  To: palmer; +Cc: linux-riscv, seanga2

On Thu, 2021-01-14 at 15:32 -0800, Palmer Dabbelt wrote:
> On Mon, 11 Jan 2021 16:58:41 PST (-0800), Damien Le Moal wrote:
> > Update the Canaan Kendryte K210 base device tree k210.dtsi to define
> > all peripherals of the SoC, their clocks and reset lines. The device
> > tree file k210.dts is renamed to k210_generic.dts and becomes the
> > default value selection of the SOC_CANAAN_K210_DTB_BUILTIN_SOURCE
> > configuration option. No device beside the serial console is defined by
> > this device tree. This makes this generic device tree suitable for use
> > with a builtin initramfs with all known K210 based boards.
> > 
> > These changes result in the K210_CLK_ACLK clock ID to be unused and
> > removed from the dt-bindings k210-clk.h header file.
> > 
> > Most updates to the k210.dtsi file come from Sean Anderson's work on
> > U-Boot support for the K210.
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > Reviewed-by: Anup Patel <anup@brainfault.org>
> > ---
> >  arch/riscv/Kconfig.socs                     |   2 +-
> >  arch/riscv/boot/dts/canaan/k210.dts         |  23 -
> >  arch/riscv/boot/dts/canaan/k210.dtsi        | 551 +++++++++++++++++++-
> >  arch/riscv/boot/dts/canaan/k210_generic.dts |  46 ++
> >  include/dt-bindings/clock/k210-clk.h        |   1 -
> >  5 files changed, 573 insertions(+), 50 deletions(-)
> >  delete mode 100644 arch/riscv/boot/dts/canaan/k210.dts
> >  create mode 100644 arch/riscv/boot/dts/canaan/k210_generic.dts
> 
> [Snipping this to the relevant bits, in case you missed it before.]
> 
> > @@ -81,40 +107,515 @@ in0: oscillator {
> >  	soc {
> >  		#address-cells = <1>;
> >  		#size-cells = <1>;
> > -		compatible = "kendryte,k210-soc", "simple-bus";
> > +		compatible = "canaan,k210-soc", "simple-bus";
> >  		ranges;
> >  		interrupt-parent = <&plic0>;
> > 
> > -		sysctl: sysctl@50440000 {
> > -			compatible = "kendryte,k210-sysctl", "simple-mfd";
> > -			reg = <0x50440000 0x1000>;
> > -			#clock-cells = <1>;
> > +		debug0: debug@0 {
> > +			compatible = "canaan,k210-debug", "riscv,debug";
> 
> I'm still getting lots of warnings about undocumented DT compatible strings
> from checpatch.  Some of them might be in flight, but I don't see many of them
> (including both of these debug ones) having been defined anywhere.  We went
> through a whole process to sort out the SiFive DT naming conventions, I don't
> want to just circumvent that for the Canaan stuff by merging it as-is.

I fixed all warnings generated by make dtbs_check. Nothing shows up now.
I removed most of the "canaan,k210-xxx" compatible strings for nodes that have
a well defined driver, according to the driver binding docs (that is the same
as other boards/SoC which do not add an SoC specific compatible string). That
is only for the IP blocks that do not need a specific tweak/quirk. The
DesignWare SPI is the exception, but that one is already documented. For the
ones I did not remove, I added documentation (e.g. boards under
riscv/canaan.yaml). I also fixed several nodes and several existing yaml files.
E.g. The sifive gpio requires a clocks property but the K210 sifive gpio does
not have any software controllable clock defined. So for that one, there is a
cannan,k210-gpiohs compatible string added and the clocks property is made
optional if that string is used.

What remains is some checkpatch.pl warnings about undocumented compatible
strings for the disabled nodes that have no Linux driver. But I am not removing
these.

Finishing polishing the clock driver and retesting now. I will soon send v12
with these fixes.


-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

end of thread, other threads:[~2021-01-15  5:56 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-12  0:58 [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 01/10] clk: Add RISC-V Canaan Kendryte K210 clock driver Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 02/10] pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver Damien Le Moal
2021-01-14 23:32   ` Palmer Dabbelt
2021-01-15  0:17     ` Damien Le Moal
2021-01-15  0:39       ` Sean Anderson
2021-01-12  0:58 ` [PATCH v11 03/10] riscv: Update Canaan Kendryte K210 device tree Damien Le Moal
2021-01-14 23:32   ` Palmer Dabbelt
     [not found]     ` <9d32abd1-ffb4-a887-a40d-fc173a371d23@gmail.com>
2021-01-15  0:06       ` Sean Anderson
2021-01-15  0:35         ` Sean Anderson
2021-01-15  1:03           ` Damien Le Moal
2021-01-15  1:14             ` Sean Anderson
2021-01-15  1:18               ` Damien Le Moal
2021-01-15  0:33     ` Damien Le Moal
2021-01-15  5:56     ` Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 04/10] riscv: Add SiPeed MAIX BiT board " Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 05/10] riscv: Add SiPeed MAIX DOCK " Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 06/10] riscv: Add SiPeed MAIX GO " Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 07/10] riscv: Add SiPeed MAIXDUINO " Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 08/10] riscv: Add Kendryte KD233 " Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 09/10] riscv: Update Canaan Kendryte K210 defconfig Damien Le Moal
2021-01-12  0:58 ` [PATCH v11 10/10] riscv: Add Canaan Kendryte K210 SD card defconfig Damien Le Moal
2021-01-12  1:07 ` [PATCH v11 00/10] RISC-V Kendryte K210 support improvements Damien Le Moal
2021-01-12  1:07   ` Damien Le Moal

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.