[PATCH v5 13/33] pinctrl: Add support for Kendryte K210 FPIOA

Rick Chen
2020-03-04T06:47:43Z

Hi Sean

> The Fully-Programmable Input/Output Array (FPIOA) device controls pin
> multiplexing on the K210. The FPIOA can remap any supported function to any
> multifunctional IO pin. It can also perform basic GPIO functions, such as
> reading the current value of a pin.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> ---
>
> Changes in v5:
> - New
>
> MAINTAINERS | 2 +
> .../pinctrl/kendryte,k210-fpioa.txt | 116 +++
> drivers/pinctrl/Kconfig | 1 +
> drivers/pinctrl/Makefile | 1 +
> drivers/pinctrl/kendryte/Kconfig | 7 +
> drivers/pinctrl/kendryte/Makefile | 1 +
> drivers/pinctrl/kendryte/pinctrl.c | 663 ++++++++++++++++++
> drivers/pinctrl/kendryte/pinctrl.h | 325 +++++++++
> include/dt-bindings/pinctrl/k210-pinctrl.h | 12 +
> 9 files changed, 1128 insertions(+)
> create mode 100644 doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt
> create mode 100644 drivers/pinctrl/kendryte/Kconfig
> create mode 100644 drivers/pinctrl/kendryte/Makefile
> create mode 100644 drivers/pinctrl/kendryte/pinctrl.c
> create mode 100644 drivers/pinctrl/kendryte/pinctrl.h
> create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h
>

Please checkpatch and fix

total: 3 errors, 13 warnings, 5 checks, 1147 lines checked

Thanks
Rick

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8e9e0569ba..8725bcf9af 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -809,7 +809,9 @@ RISC-V KENDRYTE
> M: Sean Anderson <seanga2@gmail.com>
> S: Maintained
> F: doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt
> +F: doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt
> F: drivers/clk/kendryte/
> +F: drivers/pinctrl/kendryte/
> F: include/kendryte/
>
> RNG
> diff --git a/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt b/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt
> new file mode 100644
> index 0000000000..299ce65304
> --- /dev/null
> +++ b/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt
> @@ -0,0 +1,116 @@
> +Kendryte K210 FPIOA
> +
> +This binding describes the Fully-Programmable Input/Output Array found on
> +Kendryte K210 SoCs. Any of the 256 functions can be mapped to any of the 48
> +pins.
> +
> +Required properties:
> +- compatible: should be "kendryte,k210-fpioa"
> +- reg: address and length of the FPIOA registers
> +- kendryte,sysctl: phandle to the "sysctl" register map node
> +- kendryte,power-offset: offset in the register map of the power bank control
> + register (in bytes)
> +
> +Configuration nodes
> +
> +Pin configuration nodes are documented in pinctrl-bindings.txt
> +
> +Valid values for pins, groups, and function names:
> +
> +pins:
> + "IO_X", where X is a number from 0 to 47.
> +
> +groups:
> + A0, A1, A2, B0, B1, B2, C0, C1
> +
> +functions:
> + JTAG_TCLK, JTAG_TDI, JTAG_TMS, JTAG_TDO, SPI0_D0, SPI0_D1, SPI0_D2,
> + SPI0_D3, SPI0_D4, SPI0_D5, SPI0_D6, SPI0_D7, SPI0_SS0, SPI0_SS1,
> + SPI0_SS2, SPI0_SS3, SPI0_ARB, SPI0_SCLK, UARTHS_RX, UARTHS_TX, RESV6,
> + RESV7, CLK_SPI1, CLK_I2C1, GPIOHS0, GPIOHS1, GPIOHS2, GPIOHS3, GPIOHS4,
> + GPIOHS5, GPIOHS6, GPIOHS7, GPIOHS8, GPIOHS9, GPIOHS10, GPIOHS11,
> + GPIOHS12, GPIOHS13, GPIOHS14, GPIOHS15, GPIOHS16, GPIOHS17, GPIOHS18,
> + GPIOHS19, GPIOHS20, GPIOHS21, GPIOHS22, GPIOHS23, GPIOHS24, GPIOHS25,
> + GPIOHS26, GPIOHS27, GPIOHS28, GPIOHS29, GPIOHS30, GPIOHS31, GPIO0,
> + GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, UART1_RX, UART1_TX,
> + UART2_RX, UART2_TX, UART3_RX, UART3_TX, SPI1_D0, SPI1_D1, SPI1_D2,
> + SPI1_D3, SPI1_D4, SPI1_D5, SPI1_D6, SPI1_D7, SPI1_SS0, SPI1_SS1,
> + SPI1_SS2, SPI1_SS3, SPI1_ARB, SPI1_SCLK, SPI2_D0, SPI2_SS, SPI2_SCLK,
> + I2S0_MCLK, I2S0_SCLK, I2S0_WS, I2S0_IN_D0, I2S0_IN_D1, I2S0_IN_D2,
> + I2S0_IN_D3, I2S0_OUT_D0, I2S0_OUT_D1, I2S0_OUT_D2, I2S0_OUT_D3,
> + I2S1_MCLK, I2S1_SCLK, I2S1_WS, I2S1_IN_D0, I2S1_IN_D1, I2S1_IN_D2,
> + I2S1_IN_D3, I2S1_OUT_D0, I2S1_OUT_D1, I2S1_OUT_D2, I2S1_OUT_D3,
> + I2S2_MCLK, I2S2_SCLK, I2S2_WS, I2S2_IN_D0, I2S2_IN_D1, I2S2_IN_D2,
> + I2S2_IN_D3, I2S2_OUT_D0, I2S2_OUT_D1, I2S2_OUT_D2, I2S2_OUT_D3, RESV0,
> + RESV1, RESV2, RESV3, RESV4, RESV5, I2C0_SCLK, I2C0_SDA, I2C1_SCLK,
> + I2C1_SDA, I2C2_SCLK, I2C2_SDA, DVP_XCLK, DVP_RST, DVP_PWDN, DVP_VSYNC,
> + DVP_HREF, DVP_PCLK, DVP_D0, DVP_D1, DVP_D2, DVP_D3, DVP_D4, DVP_D5,
> + DVP_D6, DVP_D7, SCCB_SCLK, SCCB_SDA, UART1_CTS, UART1_DSR, UART1_DCD,
> + UART1_RI, UART1_SIR_IN, UART1_DTR, UART1_RTS, UART1_OUT2, UART1_OUT1,
> + UART1_SIR_OUT, UART1_BAUD, UART1_RE, UART1_DE, UART1_RS485_EN,
> + UART2_CTS, UART2_DSR, UART2_DCD, UART2_RI, UART2_SIR_IN, UART2_DTR,
> + UART2_RTS, UART2_OUT2, UART2_OUT1, UART2_SIR_OUT, UART2_BAUD, UART2_RE,
> + UART2_DE, UART2_RS485_EN, UART3_CTS, UART3_DSR, UART3_DCD, UART3_RI,
> + UART3_SIR_IN, UART3_DTR, UART3_RTS, UART3_OUT2, UART3_OUT1,
> + UART3_SIR_OUT, UART3_BAUD, UART3_RE, UART3_DE, UART3_RS485_EN,
> + TIMER0_TOGGLE1, TIMER0_TOGGLE2, TIMER0_TOGGLE3, TIMER0_TOGGLE4,
> + TIMER1_TOGGLE1, TIMER1_TOGGLE2, TIMER1_TOGGLE3, TIMER1_TOGGLE4,
> + TIMER2_TOGGLE1, TIMER2_TOGGLE2, TIMER2_TOGGLE3, TIMER2_TOGGLE4,
> + CLK_SPI2, CLK_I2C2, INTERNAL0, INTERNAL1, INTERNAL2, INTERNAL3,
> + INTERNAL4, INTERNAL5, INTERNAL6, INTERNAL7, INTERNAL8, INTERNAL9,
> + INTERNAL10, INTERNAL11, INTERNAL12, INTERNAL13, INTERNAL14, INTERNAL15,
> + INTERNAL16, INTERNAL17, CONSTANT, INTERNAL18, DEBUG0, DEBUG1, DEBUG2,
> + DEBUG3, DEBUG4, DEBUG5, DEBUG6, DEBUG7, DEBUG8, DEBUG9, DEBUG10,
> + DEBUG11, DEBUG12, DEBUG13, DEBUG14, DEBUG15, DEBUG16, DEBUG17, DEBUG18,
> + DEBUG19, DEBUG20, DEBUG21, DEBUG22, DEBUG23, DEBUG24, DEBUG25, DEBUG26,
> + DEBUG27, DEBUG28, DEBUG29, DEBUG30, DEBUG31
> +
> +Valid properties include:
> + bias-disable, bias-pull-down, bias-pull-up, drive-strength,
> + drive-strength-ua, input-enable, input-disable, input-schmitt-enable,
> + input-schmitt-disable, power-source, output-low, output-high,
> + output-enable, output-disable, slew-rate
> +
> +Notes on specific properties include:
> +- bias-pull-up, -down, and -pin-default: The pull strength cannot be configured.
> +- drive-strength: There are 8 drive strength settings between 11 and 50 mA
> +- power-source: Controls the output voltage of a bank of pins. Either
> + K210_PC_POWER_1V8 or K210_PC_POWER_3V3 may be specified. This property cannot
> + be specified for individual pins.
> +- slew-rate: Specifying this property reduces the slew rate
> +
> +Example:
> +fpioa: pinmux at 502B0000 {
> + compatible = "kendryte,k210-fpioa";
> + reg = <0x502B0000 0x100>;
> + kendryte,sysctl = <&sysctl>;
> + kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +
> + fpioa_jtag: jtag {
> + voltage {
> + group = "A0";
> + power-source = <K210_PC_POWER_3V3>;
> + };
> + tck {
> + function = "JTAG_TCLK";
> + pins = "IO_0";
> + };
> + tdi {
> + function = "JTAG_TDI";
> + pins = "IO_1";
> + };
> + tms {
> + function = "JTAG_TMS";
> + pins = "IO_2";
> + };
> + tdo {
> + function = "JTAG_TDO";
> + pins = "IO_3";
> + };
> + };
> +
> + fpioa_isp: isp {
> + function = "GPIOHS0";
> + pins = "IO_16";
> + };
> +};
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 83e39b9de3..9ec56c7735 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -289,6 +289,7 @@ endif
> source "drivers/pinctrl/broadcom/Kconfig"
> source "drivers/pinctrl/exynos/Kconfig"
> source "drivers/pinctrl/intel/Kconfig"
> +source "drivers/pinctrl/kendryte/Kconfig"
> source "drivers/pinctrl/mediatek/Kconfig"
> source "drivers/pinctrl/meson/Kconfig"
> source "drivers/pinctrl/mscc/Kconfig"
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 4f662c4f6d..1fe66fed3c 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
> obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
> obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o
> obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
> +obj-$(CONFIG_PINCTRL_K210) += kendryte/
> obj-$(CONFIG_PINCTRL_MESON) += meson/
> obj-$(CONFIG_PINCTRL_MTK) += mediatek/
> obj-$(CONFIG_PINCTRL_MSCC) += mscc/
> diff --git a/drivers/pinctrl/kendryte/Kconfig b/drivers/pinctrl/kendryte/Kconfig
> new file mode 100644
> index 0000000000..6fc10e9516
> --- /dev/null
> +++ b/drivers/pinctrl/kendryte/Kconfig
> @@ -0,0 +1,7 @@
> +config PINCTRL_K210
> + bool "Kendryte K210 Fully-Programmable Input/Output Array driver"
> + depends on DM && PINCTRL_GENERIC
> + help
> + Support pin multiplexing on the K210. The "FPIOA" can remap any
> + supported function to any multifunctional IO pin. It can also perform
> + basic GPIO functions, such as reading the current value of a pin.
> diff --git a/drivers/pinctrl/kendryte/Makefile b/drivers/pinctrl/kendryte/Makefile
> new file mode 100644
> index 0000000000..1c10d7a929
> --- /dev/null
> +++ b/drivers/pinctrl/kendryte/Makefile
> @@ -0,0 +1 @@
> +obj-y += pinctrl.o
> diff --git a/drivers/pinctrl/kendryte/pinctrl.c b/drivers/pinctrl/kendryte/pinctrl.c
> new file mode 100644
> index 0000000000..3f7de0e706
> --- /dev/null
> +++ b/drivers/pinctrl/kendryte/pinctrl.c
> @@ -0,0 +1,663 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <dt-bindings/pinctrl/k210-pinctrl.h>
> +#include <mapmem.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +#include <asm/io.h>
> +#include <linux/err.h>
> +#include "pinctrl.h"
> +
> +struct k210_pc_priv {
> + struct clk clk;
> + struct k210_fpioa __iomem *fpioa; /* FPIOA register */
> + struct regmap *sysctl; /* Sysctl regmap */
> + u32 power_offset; /* Power bank register offset */
> +};
> +
> +#define PIN(i) [i] = "IO_" #i
> +static const char k210_pc_pin_names[][6] = {
> + PIN(0),
> + PIN(1),
> + PIN(2),
> + PIN(3),
> + PIN(4),
> + PIN(5),
> + PIN(6),
> + PIN(7),
> + PIN(8),
> + PIN(9),
> + PIN(10),
> + PIN(11),
> + PIN(12),
> + PIN(13),
> + PIN(14),
> + PIN(15),
> + PIN(16),
> + PIN(17),
> + PIN(18),
> + PIN(19),
> + PIN(20),
> + PIN(21),
> + PIN(22),
> + PIN(23),
> + PIN(24),
> + PIN(25),
> + PIN(26),
> + PIN(27),
> + PIN(28),
> + PIN(29),
> + PIN(30),
> + PIN(31),
> + PIN(32),
> + PIN(33),
> + PIN(34),
> + PIN(35),
> + PIN(36),
> + PIN(37),
> + PIN(38),
> + PIN(39),
> + PIN(40),
> + PIN(41),
> + PIN(42),
> + PIN(43),
> + PIN(44),
> + PIN(45),
> + PIN(46),
> + PIN(47),
> +};
> +#undef PIN
> +
> +static int k210_pc_get_pins_count(struct udevice *dev)
> +{
> + return ARRAY_SIZE(k210_pc_pin_names);
> +};
> +
> +static const char *k210_pc_get_pin_name(struct udevice *dev, unsigned selector)
> +{
> + return k210_pc_pin_names[selector];
> +}
> +
> +/* These are just power domains */
> +static const char k210_pc_group_names[][3] = {
> + [0] = "A0",
> + [1] = "A1",
> + [2] = "A2",
> + [3] = "B0",
> + [4] = "B1",
> + [5] = "B2",
> + [6] = "C0",
> + [7] = "C1",
> +};
> +
> +static int k210_pc_get_groups_count(struct udevice *dev)
> +{
> + return ARRAY_SIZE(k210_pc_group_names);
> +}
> +
> +static const char *k210_pc_get_group_name(struct udevice *dev,
> + unsigned selector)
> +{
> + return k210_pc_group_names[selector];
> +}
> +
> +enum k210_pc_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_SPI,
> + K210_PC_DEFAULT_GPIO,
> + K210_PC_DEFAULT_INT13,
> +};
> +
> +#define DEFAULT(mode) [K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
> +static const u32 k210_pc_mode_id_to_mode[] = {
> + [K210_PC_DEFAULT_DISABLED] = 0,
> + DEFAULT(IN),
> + [K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
> + DEFAULT(OUT),
> + DEFAULT(I2C),
> + DEFAULT(SPI),
> + DEFAULT(GPIO),
> + [K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
> +};
> +#undef DEFAULT
> +
> +/* This saves around 2K vs having a pointer+mode */
> +struct k210_pcf_info {
> + char name[15];
> + u8 mode_id;
> +};
> +
> +#define FUNC(id, mode) [K210_PCF_##id] = { \
> + .name = #id, \
> + .mode_id = K210_PC_DEFAULT_##mode \
> +}
> +static const struct k210_pcf_info k210_pcf_infos[] = {
> + FUNC(JTAG_TCLK, IN),
> + FUNC(JTAG_TDI, IN),
> + FUNC(JTAG_TMS, IN),
> + FUNC(JTAG_TDO, OUT),
> + FUNC(SPI0_D0, SPI),
> + FUNC(SPI0_D1, SPI),
> + FUNC(SPI0_D2, SPI),
> + FUNC(SPI0_D3, SPI),
> + FUNC(SPI0_D4, SPI),
> + FUNC(SPI0_D5, SPI),
> + FUNC(SPI0_D6, SPI),
> + FUNC(SPI0_D7, SPI),
> + FUNC(SPI0_SS0, OUT),
> + FUNC(SPI0_SS1, OUT),
> + FUNC(SPI0_SS2, OUT),
> + FUNC(SPI0_SS3, OUT),
> + FUNC(SPI0_ARB, IN_TIE),
> + FUNC(SPI0_SCLK, OUT),
> + FUNC(UARTHS_RX, IN),
> + FUNC(UARTHS_TX, OUT),
> + FUNC(RESV6, IN),
> + FUNC(RESV7, IN),
> + FUNC(CLK_SPI1, OUT),
> + FUNC(CLK_I2C1, OUT),
> + FUNC(GPIOHS0, GPIO),
> + FUNC(GPIOHS1, GPIO),
> + FUNC(GPIOHS2, GPIO),
> + FUNC(GPIOHS3, GPIO),
> + FUNC(GPIOHS4, GPIO),
> + FUNC(GPIOHS5, GPIO),
> + FUNC(GPIOHS6, GPIO),
> + FUNC(GPIOHS7, GPIO),
> + FUNC(GPIOHS8, GPIO),
> + FUNC(GPIOHS9, GPIO),
> + FUNC(GPIOHS10, GPIO),
> + FUNC(GPIOHS11, GPIO),
> + FUNC(GPIOHS12, GPIO),
> + FUNC(GPIOHS13, GPIO),
> + FUNC(GPIOHS14, GPIO),
> + FUNC(GPIOHS15, GPIO),
> + FUNC(GPIOHS16, GPIO),
> + FUNC(GPIOHS17, GPIO),
> + FUNC(GPIOHS18, GPIO),
> + FUNC(GPIOHS19, GPIO),
> + FUNC(GPIOHS20, GPIO),
> + FUNC(GPIOHS21, GPIO),
> + FUNC(GPIOHS22, GPIO),
> + FUNC(GPIOHS23, GPIO),
> + FUNC(GPIOHS24, GPIO),
> + FUNC(GPIOHS25, GPIO),
> + FUNC(GPIOHS26, GPIO),
> + FUNC(GPIOHS27, GPIO),
> + FUNC(GPIOHS28, GPIO),
> + FUNC(GPIOHS29, GPIO),
> + FUNC(GPIOHS30, GPIO),
> + FUNC(GPIOHS31, GPIO),
> + FUNC(GPIO0, GPIO),
> + FUNC(GPIO1, GPIO),
> + FUNC(GPIO2, GPIO),
> + FUNC(GPIO3, GPIO),
> + FUNC(GPIO4, GPIO),
> + FUNC(GPIO5, GPIO),
> + FUNC(GPIO6, GPIO),
> + FUNC(GPIO7, GPIO),
> + FUNC(UART1_RX, IN),
> + FUNC(UART1_TX, OUT),
> + FUNC(UART2_RX, IN),
> + FUNC(UART2_TX, OUT),
> + FUNC(UART3_RX, IN),
> + FUNC(UART3_TX, OUT),
> + FUNC(SPI1_D0, SPI),
> + FUNC(SPI1_D1, SPI),
> + FUNC(SPI1_D2, SPI),
> + FUNC(SPI1_D3, SPI),
> + FUNC(SPI1_D4, SPI),
> + FUNC(SPI1_D5, SPI),
> + FUNC(SPI1_D6, SPI),
> + FUNC(SPI1_D7, SPI),
> + FUNC(SPI1_SS0, OUT),
> + FUNC(SPI1_SS1, OUT),
> + FUNC(SPI1_SS2, OUT),
> + FUNC(SPI1_SS3, OUT),
> + FUNC(SPI1_ARB, IN_TIE),
> + FUNC(SPI1_SCLK, OUT),
> + FUNC(SPI2_D0, SPI),
> + FUNC(SPI2_SS, IN),
> + FUNC(SPI2_SCLK, IN),
> + FUNC(I2S0_MCLK, OUT),
> + FUNC(I2S0_SCLK, OUT),
> + FUNC(I2S0_WS, OUT),
> + FUNC(I2S0_IN_D0, IN),
> + FUNC(I2S0_IN_D1, IN),
> + FUNC(I2S0_IN_D2, IN),
> + FUNC(I2S0_IN_D3, IN),
> + FUNC(I2S0_OUT_D0, OUT),
> + FUNC(I2S0_OUT_D1, OUT),
> + FUNC(I2S0_OUT_D2, OUT),
> + FUNC(I2S0_OUT_D3, OUT),
> + FUNC(I2S1_MCLK, OUT),
> + FUNC(I2S1_SCLK, OUT),
> + FUNC(I2S1_WS, OUT),
> + FUNC(I2S1_IN_D0, IN),
> + FUNC(I2S1_IN_D1, IN),
> + FUNC(I2S1_IN_D2, IN),
> + FUNC(I2S1_IN_D3, IN),
> + FUNC(I2S1_OUT_D0, OUT),
> + FUNC(I2S1_OUT_D1, OUT),
> + FUNC(I2S1_OUT_D2, OUT),
> + FUNC(I2S1_OUT_D3, OUT),
> + FUNC(I2S2_MCLK, OUT),
> + FUNC(I2S2_SCLK, OUT),
> + FUNC(I2S2_WS, OUT),
> + FUNC(I2S2_IN_D0, IN),
> + FUNC(I2S2_IN_D1, IN),
> + FUNC(I2S2_IN_D2, IN),
> + FUNC(I2S2_IN_D3, IN),
> + FUNC(I2S2_OUT_D0, OUT),
> + FUNC(I2S2_OUT_D1, OUT),
> + FUNC(I2S2_OUT_D2, OUT),
> + FUNC(I2S2_OUT_D3, OUT),
> + FUNC(RESV0, DISABLED),
> + FUNC(RESV1, DISABLED),
> + FUNC(RESV2, DISABLED),
> + FUNC(RESV3, DISABLED),
> + FUNC(RESV4, DISABLED),
> + FUNC(RESV5, DISABLED),
> + FUNC(I2C0_SCLK, I2C),
> + FUNC(I2C0_SDA, I2C),
> + FUNC(I2C1_SCLK, I2C),
> + FUNC(I2C1_SDA, I2C),
> + FUNC(I2C2_SCLK, I2C),
> + FUNC(I2C2_SDA, I2C),
> + FUNC(DVP_XCLK, OUT),
> + FUNC(DVP_RST, OUT),
> + FUNC(DVP_PWDN, OUT),
> + FUNC(DVP_VSYNC, IN),
> + FUNC(DVP_HREF, IN),
> + FUNC(DVP_PCLK, IN),
> + FUNC(DVP_D0, IN),
> + FUNC(DVP_D1, IN),
> + FUNC(DVP_D2, IN),
> + FUNC(DVP_D3, IN),
> + FUNC(DVP_D4, IN),
> + FUNC(DVP_D5, IN),
> + FUNC(DVP_D6, IN),
> + FUNC(DVP_D7, IN),
> + FUNC(SCCB_SCLK, I2C),
> + FUNC(SCCB_SDA, I2C),
> + FUNC(UART1_CTS, IN),
> + FUNC(UART1_DSR, IN),
> + FUNC(UART1_DCD, IN),
> + FUNC(UART1_RI, IN),
> + FUNC(UART1_SIR_IN, IN),
> + FUNC(UART1_DTR, OUT),
> + FUNC(UART1_RTS, OUT),
> + FUNC(UART1_OUT2, OUT),
> + FUNC(UART1_OUT1, OUT),
> + FUNC(UART1_SIR_OUT, OUT),
> + FUNC(UART1_BAUD, OUT),
> + FUNC(UART1_RE, OUT),
> + FUNC(UART1_DE, OUT),
> + FUNC(UART1_RS485_EN, OUT),
> + FUNC(UART2_CTS, IN),
> + FUNC(UART2_DSR, IN),
> + FUNC(UART2_DCD, IN),
> + FUNC(UART2_RI, IN),
> + FUNC(UART2_SIR_IN, IN),
> + FUNC(UART2_DTR, OUT),
> + FUNC(UART2_RTS, OUT),
> + FUNC(UART2_OUT2, OUT),
> + FUNC(UART2_OUT1, OUT),
> + FUNC(UART2_SIR_OUT, OUT),
> + FUNC(UART2_BAUD, OUT),
> + FUNC(UART2_RE, OUT),
> + FUNC(UART2_DE, OUT),
> + FUNC(UART2_RS485_EN, OUT),
> + FUNC(UART3_CTS, IN),
> + FUNC(UART3_DSR, IN),
> + FUNC(UART3_DCD, IN),
> + FUNC(UART3_RI, IN),
> + FUNC(UART3_SIR_IN, IN),
> + FUNC(UART3_DTR, OUT),
> + FUNC(UART3_RTS, OUT),
> + FUNC(UART3_OUT2, OUT),
> + FUNC(UART3_OUT1, OUT),
> + FUNC(UART3_SIR_OUT, OUT),
> + FUNC(UART3_BAUD, OUT),
> + FUNC(UART3_RE, OUT),
> + FUNC(UART3_DE, OUT),
> + FUNC(UART3_RS485_EN, OUT),
> + FUNC(TIMER0_TOGGLE1, OUT),
> + FUNC(TIMER0_TOGGLE2, OUT),
> + FUNC(TIMER0_TOGGLE3, OUT),
> + FUNC(TIMER0_TOGGLE4, OUT),
> + FUNC(TIMER1_TOGGLE1, OUT),
> + FUNC(TIMER1_TOGGLE2, OUT),
> + FUNC(TIMER1_TOGGLE3, OUT),
> + FUNC(TIMER1_TOGGLE4, OUT),
> + FUNC(TIMER2_TOGGLE1, OUT),
> + FUNC(TIMER2_TOGGLE2, OUT),
> + FUNC(TIMER2_TOGGLE3, OUT),
> + FUNC(TIMER2_TOGGLE4, OUT),
> + FUNC(CLK_SPI2, OUT),
> + FUNC(CLK_I2C2, OUT),
> + FUNC(INTERNAL0, OUT),
> + FUNC(INTERNAL1, OUT),
> + FUNC(INTERNAL2, OUT),
> + FUNC(INTERNAL3, OUT),
> + FUNC(INTERNAL4, OUT),
> + FUNC(INTERNAL5, OUT),
> + FUNC(INTERNAL6, OUT),
> + FUNC(INTERNAL7, OUT),
> + FUNC(INTERNAL8, OUT),
> + FUNC(INTERNAL9, IN),
> + FUNC(INTERNAL10, IN),
> + FUNC(INTERNAL11, IN),
> + FUNC(INTERNAL12, IN),
> + FUNC(INTERNAL13, INT13),
> + FUNC(INTERNAL14, I2C),
> + FUNC(INTERNAL15, IN),
> + FUNC(INTERNAL16, IN),
> + FUNC(INTERNAL17, IN),
> + FUNC(CONSTANT, DISABLED),
> + FUNC(INTERNAL18, IN),
> + FUNC(DEBUG0, OUT),
> + FUNC(DEBUG1, OUT),
> + FUNC(DEBUG2, OUT),
> + FUNC(DEBUG3, OUT),
> + FUNC(DEBUG4, OUT),
> + FUNC(DEBUG5, OUT),
> + FUNC(DEBUG6, OUT),
> + FUNC(DEBUG7, OUT),
> + FUNC(DEBUG8, OUT),
> + FUNC(DEBUG9, OUT),
> + FUNC(DEBUG10, OUT),
> + FUNC(DEBUG11, OUT),
> + FUNC(DEBUG12, OUT),
> + FUNC(DEBUG13, OUT),
> + FUNC(DEBUG14, OUT),
> + FUNC(DEBUG15, OUT),
> + FUNC(DEBUG16, OUT),
> + FUNC(DEBUG17, OUT),
> + FUNC(DEBUG18, OUT),
> + FUNC(DEBUG19, OUT),
> + FUNC(DEBUG20, OUT),
> + FUNC(DEBUG21, OUT),
> + FUNC(DEBUG22, OUT),
> + FUNC(DEBUG23, OUT),
> + FUNC(DEBUG24, OUT),
> + FUNC(DEBUG25, OUT),
> + FUNC(DEBUG26, OUT),
> + FUNC(DEBUG27, OUT),
> + FUNC(DEBUG28, OUT),
> + FUNC(DEBUG29, OUT),
> + FUNC(DEBUG30, OUT),
> + FUNC(DEBUG31, OUT),
> +};
> +#undef FUNC
> +
> +int k210_pc_get_functions_count(struct udevice *dev)
> +{
> + return ARRAY_SIZE(k210_pcf_infos);
> +}
> +
> +static const char *k210_pc_get_function_name(struct udevice *dev,
> + unsigned selector)
> +{
> + return k210_pcf_infos[selector].name;
> +}
> +
> +static int k210_pc_pinmux_set(struct udevice *dev, unsigned pin_selector,
> + unsigned func_selector)
> +{
> + struct k210_pc_priv *priv = dev_get_priv(dev);
> + const struct k210_pcf_info *info = &k210_pcf_infos[func_selector];
> + u32 mode = k210_pc_mode_id_to_mode[info->mode_id];
> + u32 val = func_selector | mode;
> +
> + log_debug("setting pin %s to %s with mode %.8x\n",
> + k210_pc_pin_names[pin_selector], info->name, mode);
> + writel(val, &priv->fpioa->pins[pin_selector]);
> + return 0;
> +}
> +
> +/* Max drive strength in uA */
> +static const int k210_pc_drive_strength[] = {
> + [0] = 11200,
> + [1] = 16800,
> + [2] = 22300,
> + [3] = 27800,
> + [4] = 33300,
> + [5] = 38700,
> + [6] = 44100,
> + [7] = 49500,
> +};
> +
> +static int k210_pc_get_drive(unsigned max_strength_ua)
> +{
> + int i;
> +
> + for (i = K210_PC_DRIVE_MAX; i; i--)
> + if (k210_pc_drive_strength[i] < max_strength_ua)
> + return i;
> +
> + return -EINVAL;
> +}
> +
> +static int k210_pc_pinconf_set(struct udevice *dev, unsigned pin_selector,
> + unsigned param, unsigned argument)
> +{
> + struct k210_pc_priv *priv = dev_get_priv(dev);
> + u32 val = readl(&priv->fpioa->pins[pin_selector]);
> +
> + switch (param) {
> + case PIN_CONFIG_BIAS_DISABLE:
> + val &= ~K210_PC_BIAS_MASK;
> + break;
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + if (argument)
> + val |= K210_PC_PD;
> + else
> + return -EINVAL;
> + break;
> + case PIN_CONFIG_BIAS_PULL_UP:
> + if (argument)
> + val |= K210_PC_PD;
> + else
> + return -EINVAL;
> + break;
> + case PIN_CONFIG_DRIVE_STRENGTH:
> + argument *= 1000;
> + case PIN_CONFIG_DRIVE_STRENGTH_UA: {
> + int drive = k210_pc_get_drive(argument);
> +
> + if (IS_ERR_VALUE(drive))
> + return drive;
> + val &= ~K210_PC_DRIVE_MASK;
> + val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
> + break;
> + }
> + case PIN_CONFIG_INPUT_ENABLE:
> + if (argument)
> + val |= K210_PC_IE;
> + else
> + val &= ~K210_PC_IE;
> + break;
> + case PIN_CONFIG_INPUT_SCHMITT:
> + argument = 1;
> + case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> + if (argument)
> + val |= K210_PC_ST;
> + else
> + val &= ~K210_PC_ST;
> + break;
> + case PIN_CONFIG_OUTPUT:
> + k210_pc_pinmux_set(dev, pin_selector, K210_PCF_CONSTANT);
> + val = readl(&priv->fpioa->pins[pin_selector]);
> + val |= K210_PC_MODE_OUT;
> +
> + if (!argument)
> + val |= K210_PC_DO_INV;
> + break;
> + case PIN_CONFIG_OUTPUT_ENABLE:
> + if (argument)
> + val |= K210_PC_OE;
> + else
> + val &= ~K210_PC_OE;
> + break;
> + case PIN_CONFIG_SLEW_RATE:
> + if (argument)
> + val |= K210_PC_SL;
> + else
> + val &= ~K210_PC_SL;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + writel(val, &priv->fpioa->pins[pin_selector]);
> + return 0;
> +}
> +
> +static int k210_pc_pinconf_group_set(struct udevice *dev,
> + unsigned group_selector, unsigned param,
> + unsigned argument)
> +{
> + struct k210_pc_priv *priv = dev_get_priv(dev);
> +
> + if (param == PIN_CONFIG_POWER_SOURCE) {
> + u32 bit = BIT(group_selector);
> +
> + regmap_update_bits(priv->sysctl, priv->power_offset, bit,
> + argument ? bit : 0);
> + } else {
> + int i, ret;
> +
> + for (i = 0; i < 6; i++) {
> + ret = k210_pc_pinconf_set(dev, group_selector * 6 + i,
> + param, argument);
> + if (ret)
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int k210_pc_get_pin_muxing(struct udevice *dev, unsigned int selector,
> + char *buf, int size)
> +{
> + struct k210_pc_priv *priv = dev_get_priv(dev);
> + u32 val = readl(&priv->fpioa->pins[selector]);
> + const struct k210_pcf_info *info = &k210_pcf_infos[val & K210_PCF_MASK];
> +
> + strncpy(buf, info->name, min((size_t)size, sizeof(info->name)));
> + return 0;
> +}
> +
> +static const struct pinconf_param k210_pc_pinconf_params[] = {
> + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
> + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
> + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
> + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX },
> + { "drive-strength-ua", PIN_CONFIG_DRIVE_STRENGTH_UA, U32_MAX },
> + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
> + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
> + { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
> + { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
> + { "power-source", PIN_CONFIG_POWER_SOURCE, K210_PC_POWER_1V8 },
> + { "output-low", PIN_CONFIG_OUTPUT, 0 },
> + { "output-high", PIN_CONFIG_OUTPUT, 1 },
> + { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
> + { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
> + { "slew-rate", PIN_CONFIG_SLEW_RATE, 1 },
> +};
> +
> +static const struct pinctrl_ops k210_pc_pinctrl_ops = {
> + .get_pins_count = k210_pc_get_pins_count,
> + .get_pin_name = k210_pc_get_pin_name,
> + .get_groups_count = k210_pc_get_groups_count,
> + .get_group_name = k210_pc_get_group_name,
> + .get_functions_count = k210_pc_get_functions_count,
> + .get_function_name = k210_pc_get_function_name,
> + .pinmux_set = k210_pc_pinmux_set,
> + .pinconf_num_params = ARRAY_SIZE(k210_pc_pinconf_params),
> + .pinconf_params = k210_pc_pinconf_params,
> + .pinconf_set = k210_pc_pinconf_set,
> + .pinconf_group_set = k210_pc_pinconf_group_set,
> + .set_state = pinctrl_generic_set_state,
> + .get_pin_muxing = k210_pc_get_pin_muxing,
> +};
> +
> +static int k210_pc_probe(struct udevice *dev)
> +{
> + int ret, i, j;
> + struct k210_pc_priv *priv = dev_get_priv(dev);
> +
> + priv->fpioa = dev_read_addr_ptr(dev);
> + if (!priv->fpioa)
> + return -EINVAL;
> +
> + ret = clk_get_by_index(dev, 0, &priv->clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_enable(&priv->clk);
> + if (ret && ret != -ENOSYS && ret != -ENOTSUPP)
> + goto err;
> +
> + priv->sysctl = syscon_regmap_lookup_by_phandle(dev, "kendryte,sysctl");
> + if (IS_ERR(priv->sysctl)) {
> + ret = -ENODEV;
> + goto err;
> + }
> +
> + ret = dev_read_u32(dev, "kendryte,power-offset", &priv->power_offset);
> + if (ret)
> + goto err;
> +
> + log_debug("fpioa = %p sysctl = %p power offset = %x\n", priv->fpioa,
> + (void *)priv->sysctl->ranges[0].start, priv->power_offset);
> +
> + /* Disable all pins */
> + for (i = 6; i < ARRAY_SIZE(k210_pc_pin_names); i++)
> + k210_pc_pinmux_set(dev, i, K210_PCF_CONSTANT);
> +
> + /* Init input ties */
> + for (i = 0; i < ARRAY_SIZE(priv->fpioa->tie_en); i++) {
> + u32 val = 0;
> +
> + for (j = 0; j < 32; j++)
> + if (k210_pcf_infos[i * 32 + j].mode_id ==
> + K210_PC_DEFAULT_IN_TIE)
> + val |= BIT(j);
> + writel(val, &priv->fpioa->tie_en[i]);
> + writel(val, &priv->fpioa->tie_val[i]);
> + }
> +
> + return 0;
> +
> +err:
> + clk_free(&priv->clk);
> + return ret;
> +}
> +
> +static const struct udevice_id k210_pc_ids[] = {
> + { .compatible = "kendryte,k210-fpioa" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_k210) = {
> + .name = "pinctrl_k210",
> + .id = UCLASS_PINCTRL,
> + .of_match = k210_pc_ids,
> + .probe = k210_pc_probe,
> + .priv_auto_alloc_size = sizeof(struct k210_pc_priv),
> + .ops = &k210_pc_pinctrl_ops,
> +};
> diff --git a/drivers/pinctrl/kendryte/pinctrl.h b/drivers/pinctrl/kendryte/pinctrl.h
> new file mode 100644
> index 0000000000..de434700c3
> --- /dev/null
> +++ b/drivers/pinctrl/kendryte/pinctrl.h
> @@ -0,0 +1,325 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef K210_PINCTRL_H
> +#define K210_PINCTRL_H
> +
> +#include <linux/bitfield.h>
> +
> +/*
> + * Full list of PinCtrl Functions from
> + * kendryte-standalone-sdk/lib/drivers/include/fpioa.h
> + */
> +#define K210_PCF_SHIFT 0
> +#define K210_PCF_MASK GENMASK(7, 0)
> +#define K210_PCF_JTAG_TCLK 0 /* JTAG Test Clock */
> +#define K210_PCF_JTAG_TDI 1 /* JTAG Test Data In */
> +#define K210_PCF_JTAG_TMS 2 /* JTAG Test Mode Select */
> +#define K210_PCF_JTAG_TDO 3 /* JTAG Test Data Out */
> +#define K210_PCF_SPI0_D0 4 /* SPI0 Data 0 */
> +#define K210_PCF_SPI0_D1 5 /* SPI0 Data 1 */
> +#define K210_PCF_SPI0_D2 6 /* SPI0 Data 2 */
> +#define K210_PCF_SPI0_D3 7 /* SPI0 Data 3 */
> +#define K210_PCF_SPI0_D4 8 /* SPI0 Data 4 */
> +#define K210_PCF_SPI0_D5 9 /* SPI0 Data 5 */
> +#define K210_PCF_SPI0_D6 10 /* SPI0 Data 6 */
> +#define K210_PCF_SPI0_D7 11 /* SPI0 Data 7 */
> +#define K210_PCF_SPI0_SS0 12 /* SPI0 Chip Select 0 */
> +#define K210_PCF_SPI0_SS1 13 /* SPI0 Chip Select 1 */
> +#define K210_PCF_SPI0_SS2 14 /* SPI0 Chip Select 2 */
> +#define K210_PCF_SPI0_SS3 15 /* SPI0 Chip Select 3 */
> +#define K210_PCF_SPI0_ARB 16 /* SPI0 Arbitration */
> +#define K210_PCF_SPI0_SCLK 17 /* SPI0 Serial Clock */
> +#define K210_PCF_UARTHS_RX 18 /* UART High speed Receiver */
> +#define K210_PCF_UARTHS_TX 19 /* UART High speed Transmitter */
> +#define K210_PCF_RESV6 20 /* Reserved function */
> +#define K210_PCF_RESV7 21 /* Reserved function */
> +#define K210_PCF_CLK_SPI1 22 /* Clock SPI1 */
> +#define K210_PCF_CLK_I2C1 23 /* Clock I2C1 */
> +#define K210_PCF_GPIOHS0 24 /* GPIO High speed 0 */
> +#define K210_PCF_GPIOHS1 25 /* GPIO High speed 1 */
> +#define K210_PCF_GPIOHS2 26 /* GPIO High speed 2 */
> +#define K210_PCF_GPIOHS3 27 /* GPIO High speed 3 */
> +#define K210_PCF_GPIOHS4 28 /* GPIO High speed 4 */
> +#define K210_PCF_GPIOHS5 29 /* GPIO High speed 5 */
> +#define K210_PCF_GPIOHS6 30 /* GPIO High speed 6 */
> +#define K210_PCF_GPIOHS7 31 /* GPIO High speed 7 */
> +#define K210_PCF_GPIOHS8 32 /* GPIO High speed 8 */
> +#define K210_PCF_GPIOHS9 33 /* GPIO High speed 9 */
> +#define K210_PCF_GPIOHS10 34 /* GPIO High speed 10 */
> +#define K210_PCF_GPIOHS11 35 /* GPIO High speed 11 */
> +#define K210_PCF_GPIOHS12 36 /* GPIO High speed 12 */
> +#define K210_PCF_GPIOHS13 37 /* GPIO High speed 13 */
> +#define K210_PCF_GPIOHS14 38 /* GPIO High speed 14 */
> +#define K210_PCF_GPIOHS15 39 /* GPIO High speed 15 */
> +#define K210_PCF_GPIOHS16 40 /* GPIO High speed 16 */
> +#define K210_PCF_GPIOHS17 41 /* GPIO High speed 17 */
> +#define K210_PCF_GPIOHS18 42 /* GPIO High speed 18 */
> +#define K210_PCF_GPIOHS19 43 /* GPIO High speed 19 */
> +#define K210_PCF_GPIOHS20 44 /* GPIO High speed 20 */
> +#define K210_PCF_GPIOHS21 45 /* GPIO High speed 21 */
> +#define K210_PCF_GPIOHS22 46 /* GPIO High speed 22 */
> +#define K210_PCF_GPIOHS23 47 /* GPIO High speed 23 */
> +#define K210_PCF_GPIOHS24 48 /* GPIO High speed 24 */
> +#define K210_PCF_GPIOHS25 49 /* GPIO High speed 25 */
> +#define K210_PCF_GPIOHS26 50 /* GPIO High speed 26 */
> +#define K210_PCF_GPIOHS27 51 /* GPIO High speed 27 */
> +#define K210_PCF_GPIOHS28 52 /* GPIO High speed 28 */
> +#define K210_PCF_GPIOHS29 53 /* GPIO High speed 29 */
> +#define K210_PCF_GPIOHS30 54 /* GPIO High speed 30 */
> +#define K210_PCF_GPIOHS31 55 /* GPIO High speed 31 */
> +#define K210_PCF_GPIO0 56 /* GPIO pin 0 */
> +#define K210_PCF_GPIO1 57 /* GPIO pin 1 */
> +#define K210_PCF_GPIO2 58 /* GPIO pin 2 */
> +#define K210_PCF_GPIO3 59 /* GPIO pin 3 */
> +#define K210_PCF_GPIO4 60 /* GPIO pin 4 */
> +#define K210_PCF_GPIO5 61 /* GPIO pin 5 */
> +#define K210_PCF_GPIO6 62 /* GPIO pin 6 */
> +#define K210_PCF_GPIO7 63 /* GPIO pin 7 */
> +#define K210_PCF_UART1_RX 64 /* UART1 Receiver */
> +#define K210_PCF_UART1_TX 65 /* UART1 Transmitter */
> +#define K210_PCF_UART2_RX 66 /* UART2 Receiver */
> +#define K210_PCF_UART2_TX 67 /* UART2 Transmitter */
> +#define K210_PCF_UART3_RX 68 /* UART3 Receiver */
> +#define K210_PCF_UART3_TX 69 /* UART3 Transmitter */
> +#define K210_PCF_SPI1_D0 70 /* SPI1 Data 0 */
> +#define K210_PCF_SPI1_D1 71 /* SPI1 Data 1 */
> +#define K210_PCF_SPI1_D2 72 /* SPI1 Data 2 */
> +#define K210_PCF_SPI1_D3 73 /* SPI1 Data 3 */
> +#define K210_PCF_SPI1_D4 74 /* SPI1 Data 4 */
> +#define K210_PCF_SPI1_D5 75 /* SPI1 Data 5 */
> +#define K210_PCF_SPI1_D6 76 /* SPI1 Data 6 */
> +#define K210_PCF_SPI1_D7 77 /* SPI1 Data 7 */
> +#define K210_PCF_SPI1_SS0 78 /* SPI1 Chip Select 0 */
> +#define K210_PCF_SPI1_SS1 79 /* SPI1 Chip Select 1 */
> +#define K210_PCF_SPI1_SS2 80 /* SPI1 Chip Select 2 */
> +#define K210_PCF_SPI1_SS3 81 /* SPI1 Chip Select 3 */
> +#define K210_PCF_SPI1_ARB 82 /* SPI1 Arbitration */
> +#define K210_PCF_SPI1_SCLK 83 /* SPI1 Serial Clock */
> +#define K210_PCF_SPI2_D0 84 /* SPI2 Data 0 */
> +#define K210_PCF_SPI2_SS 85 /* SPI2 Select */
> +#define K210_PCF_SPI2_SCLK 86 /* SPI2 Serial Clock */
> +#define K210_PCF_I2S0_MCLK 87 /* I2S0 Master Clock */
> +#define K210_PCF_I2S0_SCLK 88 /* I2S0 Serial Clock(BCLK) */
> +#define K210_PCF_I2S0_WS 89 /* I2S0 Word Select(LRCLK) */
> +#define K210_PCF_I2S0_IN_D0 90 /* I2S0 Serial Data Input 0 */
> +#define K210_PCF_I2S0_IN_D1 91 /* I2S0 Serial Data Input 1 */
> +#define K210_PCF_I2S0_IN_D2 92 /* I2S0 Serial Data Input 2 */
> +#define K210_PCF_I2S0_IN_D3 93 /* I2S0 Serial Data Input 3 */
> +#define K210_PCF_I2S0_OUT_D0 94 /* I2S0 Serial Data Output 0 */
> +#define K210_PCF_I2S0_OUT_D1 95 /* I2S0 Serial Data Output 1 */
> +#define K210_PCF_I2S0_OUT_D2 96 /* I2S0 Serial Data Output 2 */
> +#define K210_PCF_I2S0_OUT_D3 97 /* I2S0 Serial Data Output 3 */
> +#define K210_PCF_I2S1_MCLK 98 /* I2S1 Master Clock */
> +#define K210_PCF_I2S1_SCLK 99 /* I2S1 Serial Clock(BCLK) */
> +#define K210_PCF_I2S1_WS 100 /* I2S1 Word Select(LRCLK) */
> +#define K210_PCF_I2S1_IN_D0 101 /* I2S1 Serial Data Input 0 */
> +#define K210_PCF_I2S1_IN_D1 102 /* I2S1 Serial Data Input 1 */
> +#define K210_PCF_I2S1_IN_D2 103 /* I2S1 Serial Data Input 2 */
> +#define K210_PCF_I2S1_IN_D3 104 /* I2S1 Serial Data Input 3 */
> +#define K210_PCF_I2S1_OUT_D0 105 /* I2S1 Serial Data Output 0 */
> +#define K210_PCF_I2S1_OUT_D1 106 /* I2S1 Serial Data Output 1 */
> +#define K210_PCF_I2S1_OUT_D2 107 /* I2S1 Serial Data Output 2 */
> +#define K210_PCF_I2S1_OUT_D3 108 /* I2S1 Serial Data Output 3 */
> +#define K210_PCF_I2S2_MCLK 109 /* I2S2 Master Clock */
> +#define K210_PCF_I2S2_SCLK 110 /* I2S2 Serial Clock(BCLK) */
> +#define K210_PCF_I2S2_WS 111 /* I2S2 Word Select(LRCLK) */
> +#define K210_PCF_I2S2_IN_D0 112 /* I2S2 Serial Data Input 0 */
> +#define K210_PCF_I2S2_IN_D1 113 /* I2S2 Serial Data Input 1 */
> +#define K210_PCF_I2S2_IN_D2 114 /* I2S2 Serial Data Input 2 */
> +#define K210_PCF_I2S2_IN_D3 115 /* I2S2 Serial Data Input 3 */
> +#define K210_PCF_I2S2_OUT_D0 116 /* I2S2 Serial Data Output 0 */
> +#define K210_PCF_I2S2_OUT_D1 117 /* I2S2 Serial Data Output 1 */
> +#define K210_PCF_I2S2_OUT_D2 118 /* I2S2 Serial Data Output 2 */
> +#define K210_PCF_I2S2_OUT_D3 119 /* I2S2 Serial Data Output 3 */
> +#define K210_PCF_RESV0 120 /* Reserved function */
> +#define K210_PCF_RESV1 121 /* Reserved function */
> +#define K210_PCF_RESV2 122 /* Reserved function */
> +#define K210_PCF_RESV3 123 /* Reserved function */
> +#define K210_PCF_RESV4 124 /* Reserved function */
> +#define K210_PCF_RESV5 125 /* Reserved function */
> +#define K210_PCF_I2C0_SCLK 126 /* I2C0 Serial Clock */
> +#define K210_PCF_I2C0_SDA 127 /* I2C0 Serial Data */
> +#define K210_PCF_I2C1_SCLK 128 /* I2C1 Serial Clock */
> +#define K210_PCF_I2C1_SDA 129 /* I2C1 Serial Data */
> +#define K210_PCF_I2C2_SCLK 130 /* I2C2 Serial Clock */
> +#define K210_PCF_I2C2_SDA 131 /* I2C2 Serial Data */
> +#define K210_PCF_DVP_XCLK 132 /* DVP System Clock */
> +#define K210_PCF_DVP_RST 133 /* DVP System Reset */
> +#define K210_PCF_DVP_PWDN 134 /* DVP Power Down Mode */
> +#define K210_PCF_DVP_VSYNC 135 /* DVP Vertical Sync */
> +#define K210_PCF_DVP_HREF 136 /* DVP Horizontal Reference output */
> +#define K210_PCF_DVP_PCLK 137 /* Pixel Clock */
> +#define K210_PCF_DVP_D0 138 /* Data Bit 0 */
> +#define K210_PCF_DVP_D1 139 /* Data Bit 1 */
> +#define K210_PCF_DVP_D2 140 /* Data Bit 2 */
> +#define K210_PCF_DVP_D3 141 /* Data Bit 3 */
> +#define K210_PCF_DVP_D4 142 /* Data Bit 4 */
> +#define K210_PCF_DVP_D5 143 /* Data Bit 5 */
> +#define K210_PCF_DVP_D6 144 /* Data Bit 6 */
> +#define K210_PCF_DVP_D7 145 /* Data Bit 7 */
> +#define K210_PCF_SCCB_SCLK 146 /* Serial Camera Control Bus Clock */
> +#define K210_PCF_SCCB_SDA 147 /* Serial Camera Control Bus Data */
> +#define K210_PCF_UART1_CTS 148 /* UART1 Clear To Send */
> +#define K210_PCF_UART1_DSR 149 /* UART1 Data Set Ready */
> +#define K210_PCF_UART1_DCD 150 /* UART1 Data Carrier Detect */
> +#define K210_PCF_UART1_RI 151 /* UART1 Ring Indicator */
> +#define K210_PCF_UART1_SIR_IN 152 /* UART1 Serial Infrared Input */
> +#define K210_PCF_UART1_DTR 153 /* UART1 Data Terminal Ready */
> +#define K210_PCF_UART1_RTS 154 /* UART1 Request To Send */
> +#define K210_PCF_UART1_OUT2 155 /* UART1 User-designated Output 2 */
> +#define K210_PCF_UART1_OUT1 156 /* UART1 User-designated Output 1 */
> +#define K210_PCF_UART1_SIR_OUT 157 /* UART1 Serial Infrared Output */
> +#define K210_PCF_UART1_BAUD 158 /* UART1 Transmit Clock Output */
> +#define K210_PCF_UART1_RE 159 /* UART1 Receiver Output Enable */
> +#define K210_PCF_UART1_DE 160 /* UART1 Driver Output Enable */
> +#define K210_PCF_UART1_RS485_EN 161 /* UART1 RS485 Enable */
> +#define K210_PCF_UART2_CTS 162 /* UART2 Clear To Send */
> +#define K210_PCF_UART2_DSR 163 /* UART2 Data Set Ready */
> +#define K210_PCF_UART2_DCD 164 /* UART2 Data Carrier Detect */
> +#define K210_PCF_UART2_RI 165 /* UART2 Ring Indicator */
> +#define K210_PCF_UART2_SIR_IN 166 /* UART2 Serial Infrared Input */
> +#define K210_PCF_UART2_DTR 167 /* UART2 Data Terminal Ready */
> +#define K210_PCF_UART2_RTS 168 /* UART2 Request To Send */
> +#define K210_PCF_UART2_OUT2 169 /* UART2 User-designated Output 2 */
> +#define K210_PCF_UART2_OUT1 170 /* UART2 User-designated Output 1 */
> +#define K210_PCF_UART2_SIR_OUT 171 /* UART2 Serial Infrared Output */
> +#define K210_PCF_UART2_BAUD 172 /* UART2 Transmit Clock Output */
> +#define K210_PCF_UART2_RE 173 /* UART2 Receiver Output Enable */
> +#define K210_PCF_UART2_DE 174 /* UART2 Driver Output Enable */
> +#define K210_PCF_UART2_RS485_EN 175 /* UART2 RS485 Enable */
> +#define K210_PCF_UART3_CTS 176 /* UART3 Clear To Send */
> +#define K210_PCF_UART3_DSR 177 /* UART3 Data Set Ready */
> +#define K210_PCF_UART3_DCD 178 /* UART3 Data Carrier Detect */
> +#define K210_PCF_UART3_RI 179 /* UART3 Ring Indicator */
> +#define K210_PCF_UART3_SIR_IN 180 /* UART3 Serial Infrared Input */
> +#define K210_PCF_UART3_DTR 181 /* UART3 Data Terminal Ready */
> +#define K210_PCF_UART3_RTS 182 /* UART3 Request To Send */
> +#define K210_PCF_UART3_OUT2 183 /* UART3 User-designated Output 2 */
> +#define K210_PCF_UART3_OUT1 184 /* UART3 User-designated Output 1 */
> +#define K210_PCF_UART3_SIR_OUT 185 /* UART3 Serial Infrared Output */
> +#define K210_PCF_UART3_BAUD 186 /* UART3 Transmit Clock Output */
> +#define K210_PCF_UART3_RE 187 /* UART3 Receiver Output Enable */
> +#define K210_PCF_UART3_DE 188 /* UART3 Driver Output Enable */
> +#define K210_PCF_UART3_RS485_EN 189 /* UART3 RS485 Enable */
> +#define K210_PCF_TIMER0_TOGGLE1 190 /* TIMER0 Toggle Output 1 */
> +#define K210_PCF_TIMER0_TOGGLE2 191 /* TIMER0 Toggle Output 2 */
> +#define K210_PCF_TIMER0_TOGGLE3 192 /* TIMER0 Toggle Output 3 */
> +#define K210_PCF_TIMER0_TOGGLE4 193 /* TIMER0 Toggle Output 4 */
> +#define K210_PCF_TIMER1_TOGGLE1 194 /* TIMER1 Toggle Output 1 */
> +#define K210_PCF_TIMER1_TOGGLE2 195 /* TIMER1 Toggle Output 2 */
> +#define K210_PCF_TIMER1_TOGGLE3 196 /* TIMER1 Toggle Output 3 */
> +#define K210_PCF_TIMER1_TOGGLE4 197 /* TIMER1 Toggle Output 4 */
> +#define K210_PCF_TIMER2_TOGGLE1 198 /* TIMER2 Toggle Output 1 */
> +#define K210_PCF_TIMER2_TOGGLE2 199 /* TIMER2 Toggle Output 2 */
> +#define K210_PCF_TIMER2_TOGGLE3 200 /* TIMER2 Toggle Output 3 */
> +#define K210_PCF_TIMER2_TOGGLE4 201 /* TIMER2 Toggle Output 4 */
> +#define K210_PCF_CLK_SPI2 202 /* Clock SPI2 */
> +#define K210_PCF_CLK_I2C2 203 /* Clock I2C2 */
> +#define K210_PCF_INTERNAL0 204 /* Internal function signal 0 */
> +#define K210_PCF_INTERNAL1 205 /* Internal function signal 1 */
> +#define K210_PCF_INTERNAL2 206 /* Internal function signal 2 */
> +#define K210_PCF_INTERNAL3 207 /* Internal function signal 3 */
> +#define K210_PCF_INTERNAL4 208 /* Internal function signal 4 */
> +#define K210_PCF_INTERNAL5 209 /* Internal function signal 5 */
> +#define K210_PCF_INTERNAL6 210 /* Internal function signal 6 */
> +#define K210_PCF_INTERNAL7 211 /* Internal function signal 7 */
> +#define K210_PCF_INTERNAL8 212 /* Internal function signal 8 */
> +#define K210_PCF_INTERNAL9 213 /* Internal function signal 9 */
> +#define K210_PCF_INTERNAL10 214 /* Internal function signal 10 */
> +#define K210_PCF_INTERNAL11 215 /* Internal function signal 11 */
> +#define K210_PCF_INTERNAL12 216 /* Internal function signal 12 */
> +#define K210_PCF_INTERNAL13 217 /* Internal function signal 13 */
> +#define K210_PCF_INTERNAL14 218 /* Internal function signal 14 */
> +#define K210_PCF_INTERNAL15 219 /* Internal function signal 15 */
> +#define K210_PCF_INTERNAL16 220 /* Internal function signal 16 */
> +#define K210_PCF_INTERNAL17 221 /* Internal function signal 17 */
> +#define K210_PCF_CONSTANT 222 /* Constant function */
> +#define K210_PCF_INTERNAL18 223 /* Internal function signal 18 */
> +#define K210_PCF_DEBUG0 224 /* Debug function 0 */
> +#define K210_PCF_DEBUG1 225 /* Debug function 1 */
> +#define K210_PCF_DEBUG2 226 /* Debug function 2 */
> +#define K210_PCF_DEBUG3 227 /* Debug function 3 */
> +#define K210_PCF_DEBUG4 228 /* Debug function 4 */
> +#define K210_PCF_DEBUG5 229 /* Debug function 5 */
> +#define K210_PCF_DEBUG6 230 /* Debug function 6 */
> +#define K210_PCF_DEBUG7 231 /* Debug function 7 */
> +#define K210_PCF_DEBUG8 232 /* Debug function 8 */
> +#define K210_PCF_DEBUG9 233 /* Debug function 9 */
> +#define K210_PCF_DEBUG10 234 /* Debug function 10 */
> +#define K210_PCF_DEBUG11 235 /* Debug function 11 */
> +#define K210_PCF_DEBUG12 236 /* Debug function 12 */
> +#define K210_PCF_DEBUG13 237 /* Debug function 13 */
> +#define K210_PCF_DEBUG14 238 /* Debug function 14 */
> +#define K210_PCF_DEBUG15 239 /* Debug function 15 */
> +#define K210_PCF_DEBUG16 240 /* Debug function 16 */
> +#define K210_PCF_DEBUG17 241 /* Debug function 17 */
> +#define K210_PCF_DEBUG18 242 /* Debug function 18 */
> +#define K210_PCF_DEBUG19 243 /* Debug function 19 */
> +#define K210_PCF_DEBUG20 244 /* Debug function 20 */
> +#define K210_PCF_DEBUG21 245 /* Debug function 21 */
> +#define K210_PCF_DEBUG22 246 /* Debug function 22 */
> +#define K210_PCF_DEBUG23 247 /* Debug function 23 */
> +#define K210_PCF_DEBUG24 248 /* Debug function 24 */
> +#define K210_PCF_DEBUG25 249 /* Debug function 25 */
> +#define K210_PCF_DEBUG26 250 /* Debug function 26 */
> +#define K210_PCF_DEBUG27 251 /* Debug function 27 */
> +#define K210_PCF_DEBUG28 252 /* Debug function 28 */
> +#define K210_PCF_DEBUG29 253 /* Debug function 29 */
> +#define K210_PCF_DEBUG30 254 /* Debug function 30 */
> +#define K210_PCF_DEBUG31 255 /* Debug function 31 */
> +
> +/*
> + * The K210 only implements 8 drive levels, even though there is register space
> + * for 16
> + */
> +#define K210_PC_DRIVE_SHIFT 8
> +#define K210_PC_DRIVE_MASK GENMASK(11, 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 function-controlled Output Enable */
> +#define K210_PC_DO_OE BIT(14) /* set Data Out to the Output Enable signal */
> +#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 to prevent overshoot */
> +/* Same semantics as OE above */
> +#define K210_PC_IE BIT(20) /* Input Enable */
> +#define K210_PC_IE_INV BIT(21) /* INVert function-controlled 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_IE_INV | K210_PC_SL | \
> + K210_PC_OE | K210_PC_OE_INV | K210_PC_PU)
> +#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)
> +
> +struct k210_fpioa {
> + u32 pins[48];
> + u32 tie_en[8];
> + u32 tie_val[8];
> +};
> +
> +#endif /* K210_PINCTRL_H */
> diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h
> new file mode 100644
> index 0000000000..6d44ea765b
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/k210-pinctrl.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + */
> +
> +#ifndef DT_K210_PINCTRL_H
> +#define DT_K210_PINCTRL_H
> +
> +#define K210_PC_POWER_3V3 0
> +#define K210_PC_POWER_1V8 1
> +
> +#endif /* DT_K210_PINCTRL_H */
> --
> 2.25.0
>