diff options
37 files changed, 2171 insertions, 303 deletions
@@ -422,6 +422,14 @@ config SYS_SRAM_SIZE default 0x10000 if TARGET_TRICORDER default 0x0 +config EXAMPLES + bool "Compile API examples" + depends on !SANDBOX + default y if ARCH_QEMU + help + U-Boot provides an API for standalone applications. Examples are + provided in directory examples/. + endmenu # General setup menu "Boot images" diff --git a/MAINTAINERS b/MAINTAINERS index ed5e354873..fb9ba37984 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -935,7 +935,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 @@ -960,6 +962,7 @@ M: Simon Glass <sjg@chromium.org> S: Maintained F: arch/sandbox/ F: doc/arch/sandbox.rst +F: include/dt-bindings/*/sandbox*.h SH M: Marek Vasut <marek.vasut+renesas@gmail.com> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index abbc89a889..a067a07676 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,7 +12,6 @@ config ARM64 if ARM64 config POSITION_INDEPENDENT bool "Generate position-independent pre-relocation code" - select INIT_SP_RELATIVE help U-Boot expects to be linked to a specific hard-coded address, and to be loaded to and run from that address. This option lifts that @@ -23,6 +22,8 @@ config POSITION_INDEPENDENT config INIT_SP_RELATIVE bool "Specify the early stack pointer relative to the .bss section" + default n if ARCH_QEMU + default y if POSITION_INDEPENDENT help U-Boot typically uses a hard-coded value for the stack pointer before relocation. Enable this option to instead calculate the @@ -76,7 +77,7 @@ config GIC_V3_ITS config STATIC_RELA bool - default y if ARM64 && !POSITION_INDEPENDENT + default y if ARM64 config DMA_ADDR_T_64BIT bool @@ -932,7 +933,6 @@ config ARCH_OWL config ARCH_QEMU bool "QEMU Virtual Platform" - select ARCH_SUPPORT_TFABOOT select DM select DM_SERIAL select OF_CONTROL @@ -1801,8 +1801,13 @@ config TFABOOT depends on ARCH_SUPPORT_TFABOOT default n help - Enabling this will make a U-Boot binary that is capable of being - booted via TF-A (Trusted Firmware for Cortex-A). + Some platforms support the setup of secure registers (for instance + for CPU errata handling) or provide secure services like PSCI. + Those services could also be provided by other firmware parts + like TF-A (Trusted Firmware for Cortex-A), in which case U-Boot + does not need to (and cannot) execute this code. + Enabling this option will make a U-Boot binary that is relying + on other firmware layers to provide secure functionality. config TI_SECURE_DEVICE bool "HS Device Type Support" diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index e5c2856cf5..662449156b 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -83,7 +83,8 @@ save_boot_params_ret: pie_fixup: adr x0, _start /* x0 <- Runtime value of _start */ ldr x1, _TEXT_BASE /* x1 <- Linked value of _start */ - sub x9, x0, x1 /* x9 <- Run-vs-link offset */ + subs x9, x0, x1 /* x9 <- Run-vs-link offset */ + beq pie_fixup_done adrp x2, __rel_dyn_start /* x2 <- Runtime &__rel_dyn_start */ add x2, x2, #:lo12:__rel_dyn_start adrp x3, __rel_dyn_end /* x3 <- Runtime &__rel_dyn_end */ diff --git a/arch/arm/mach-aspeed/ast2500/Makefile b/arch/arm/mach-aspeed/ast2500/Makefile index 4c27c8fc46..db70432ad0 100644 --- a/arch/arm/mach-aspeed/ast2500/Makefile +++ b/arch/arm/mach-aspeed/ast2500/Makefile @@ -1,3 +1,3 @@ obj-y += lowlevel_init.o obj-y += board_common.o -obj-y += clk_ast2500.o sdram_ast2500.o +obj-y += clk_ast2500.o diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts index 5b32c5fd5f..c2beec602c 100644 --- a/arch/riscv/dts/k210-maix-bit.dts +++ b/arch/riscv/dts/k210-maix-bit.dts @@ -8,6 +8,7 @@ #include "k210.dtsi" #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> / { model = "Sipeed Maix Bit 2.0"; @@ -17,6 +18,32 @@ stdout-path = "serial0:115200"; }; + 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"; @@ -39,9 +66,97 @@ }; &uarths0 { + pinctrl-0 = <&fpioa_uarths>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gpio0 { + pinctrl-0 = <&fpioa_gpiohs>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gpio1 { + pinctrl-0 = <&fpioa_gpio>; + pinctrl-names = "default"; status = "okay"; }; &i2s0 { #sound-dai-cells = <1>; + pinctrl-0 = <&fpioa_i2s0>; + pinctrl-names = "default"; +}; + +&fpioa { + status = "okay"; + + fpioa_uarths: uarths { + pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, + <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; + }; + + fpioa_gpio: gpio { + 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)>; + }; + + fpioa_gpiohs: gpiohs { + 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(30, K210_PCF_GPIOHS14)>, + <K210_FPIOA(31, K210_PCF_GPIOHS15)>, + <K210_FPIOA(32, K210_PCF_GPIOHS16)>, + <K210_FPIOA(33, K210_PCF_GPIOHS17)>, + <K210_FPIOA(34, K210_PCF_GPIOHS18)>, + <K210_FPIOA(35, K210_PCF_GPIOHS19)>; + }; + + fpioa_i2s0: i2s0 { + pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>, + <K210_FPIOA(19, K210_PCF_I2S0_WS)>, + <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>; + }; + + fpioa_dvp: dvp { + 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)>; + }; + + fpioa_spi0: spi0 { + 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 */ + }; + + fpioa_spi1: spi1 { + 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)>; + }; +}; + +&dvp0 { + pinctrl-0 = <&fpioa_dvp>; + pinctrl-names = "default"; }; diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi index 84cff51c36..7605c01f3c 100644 --- a/arch/riscv/dts/k210.dtsi +++ b/arch/riscv/dts/k210.dtsi @@ -5,6 +5,7 @@ #include <dt-bindings/clock/k210-sysctl.h> #include <dt-bindings/mfd/k210-sysctl.h> +#include <dt-bindings/pinctrl/k210-pinctrl.h> #include <dt-bindings/reset/k210-sysctl.h> / { @@ -368,7 +369,18 @@ reg = <0x502B0000 0x100>; clocks = <&sysclk K210_CLK_FPIOA>; resets = <&sysrst K210_RST_FPIOA>; + kendryte,sysctl = <&sysctl>; + kendryte,power-offset = <K210_SYSCTL_POWER_SEL>; + pinctrl-0 = <&fpioa_jtag>; + pinctrl-names = "default"; status = "disabled"; + + fpioa_jtag: jtag { + 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)>; + }; }; sha256: sha256@502C0000 { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index cc372806a0..c7d1376911 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -2,6 +2,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/sandbox-gpio.h> +#include <dt-bindings/pinctrl/sandbox-pinmux.h> / { model = "sandbox"; @@ -558,7 +559,7 @@ default_off { gpios = <&gpio_a 6 0>; - label = "sandbox:default_off"; + /* label intentionally omitted */ default-state = "off"; }; }; @@ -1094,30 +1095,60 @@ pinctrl { compatible = "sandbox,pinctrl"; - pinctrl-names = "default"; - pinctrl-0 = <&gpios>; + pinctrl-names = "default", "alternate"; + pinctrl-0 = <&pinctrl_gpios>, <&pinctrl_i2s>; + pinctrl-1 = <&pinctrl_spi>, <&pinctrl_i2c>; - gpios: gpios { + pinctrl_gpios: gpios { gpio0 { - pins = "GPIO0"; + pins = "P5"; + function = "GPIO"; bias-pull-up; input-disable; }; gpio1 { - pins = "GPIO1"; + pins = "P6"; + function = "GPIO"; output-high; drive-open-drain; }; gpio2 { - pins = "GPIO2"; + pinmux = <SANDBOX_PINMUX(7, SANDBOX_PINMUX_GPIO)>; bias-pull-down; input-enable; }; gpio3 { - pins = "GPIO3"; + pinmux = <SANDBOX_PINMUX(8, SANDBOX_PINMUX_GPIO)>; bias-disable; }; }; + + pinctrl_i2c: i2c { + groups { + groups = "I2C_UART"; + function = "I2C"; + }; + + pins { + pins = "P0", "P1"; + drive-open-drain; + }; + }; + + pinctrl_i2s: i2s { + groups = "SPI_I2S"; + function = "I2S"; + }; + + pinctrl_spi: spi { + groups = "SPI_I2S"; + function = "SPI"; + + cs { + pinmux = <SANDBOX_PINMUX(5, SANDBOX_PINMUX_CS)>, + <SANDBOX_PINMUX(6, SANDBOX_PINMUX_CS)>; + }; + }; }; hwspinlock@0 { diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig index 0cdcd32adc..4c42dd2087 100644 --- a/board/sipeed/maix/Kconfig +++ b/board/sipeed/maix/Kconfig @@ -44,4 +44,13 @@ config BOARD_SPECIFIC_OPTIONS imply RESET_SYSCON imply SYSRESET imply SYSRESET_SYSCON + imply PINCTRL + imply PINCONF + imply PINCTRL_K210 + imply DM_GPIO + imply DWAPB_GPIO + imply SIFIVE_GPIO + imply CMD_GPIO + imply LED + imply LED_GPIO endif diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig index 31ea2d342f..4450e7ced4 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_QEMU=y CONFIG_NR_DRAM_BANKS=1 +CONFIG_POSITION_INDEPENDENT=y CONFIG_ENV_SIZE=0x40000 CONFIG_ENV_SECT_SIZE=0x40000 CONFIG_AHCI=y diff --git a/doc/api/index.rst b/doc/api/index.rst index b7eb5725f2..1c261bcb73 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -9,6 +9,7 @@ U-Boot API documentation dfu efi linker_lists + pinctrl rng serial unicode diff --git a/doc/api/pinctrl.rst b/doc/api/pinctrl.rst new file mode 100644 index 0000000000..043bd57efa --- /dev/null +++ b/doc/api/pinctrl.rst @@ -0,0 +1,7 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Pinctrl and Pinmux +================== + +.. kernel-doc:: include/dm/pinctrl.h + :internal: diff --git a/doc/board/sipeed/maix.rst b/doc/board/sipeed/maix.rst index 3f791b42fa..92f2d112a9 100644 --- a/doc/board/sipeed/maix.rst +++ b/doc/board/sipeed/maix.rst @@ -199,7 +199,7 @@ To run legacy images, use the ``bootm`` command: Load Address: 80000000 Entry Point: 80000000 - $ picocom -b 115200 /dev/ttyUSB0i + $ picocom -b 115200 /dev/ttyUSB0 => loady ## Ready for binary (ymodem) download to 0x80000000 at 115200 bps... C @@ -230,6 +230,66 @@ To run legacy images, use the ``bootm`` command: argv[0] = "<NULL>" Hit any key to exit ... +Pin Assignment +-------------- + +The K210 contains a Fully Programmable I/O Array (FPIOA), which can remap any of +its 256 input functions to any any of 48 output pins. The following table has +the default pin assignments for the BitM. + +===== ========== ======= +Pin Function Comment +===== ========== ======= +IO_0 JTAG_TCLK +IO_1 JTAG_TDI +IO_2 JTAG_TMS +IO_3 JTAG_TDO +IO_4 UARTHS_RX +IO_5 UARTHS_TX +IO_6 Not set +IO_7 Not set +IO_8 GPIO_0 +IO_9 GPIO_1 +IO_10 GPIO_2 +IO_11 GPIO_3 +IO_12 GPIO_4 Green LED +IO_13 GPIO_5 Red LED +IO_14 GPIO_6 Blue LED +IO_15 GPIO_7 +IO_16 GPIOHS_0 ISP +IO_17 GPIOHS_1 +IO_18 I2S0_SCLK MIC CLK +IO_19 I2S0_WS MIC WS +IO_20 I2S0_IN_D0 MIC SD +IO_21 GPIOHS_5 +IO_22 GPIOHS_6 +IO_23 GPIOHS_7 +IO_24 GPIOHS_8 +IO_25 GPIOHS_9 +IO_26 SPI1_D1 MMC MISO +IO_27 SPI1_SCLK MMC CLK +IO_28 SPI1_D0 MMC MOSI +IO_29 GPIOHS_13 MMC CS +IO_30 GPIOHS_14 +IO_31 GPIOHS_15 +IO_32 GPIOHS_16 +IO_33 GPIOHS_17 +IO_34 GPIOHS_18 +IO_35 GPIOHS_19 +IO_36 GPIOHS_20 Panel CS +IO_37 GPIOHS_21 Panel RST +IO_38 GPIOHS_22 Panel DC +IO_39 SPI0_SCK Panel WR +IO_40 SCCP_SDA +IO_41 SCCP_SCLK +IO_42 DVP_RST +IO_43 DVP_VSYNC +IO_44 DVP_PWDN +IO_45 DVP_HSYNC +IO_46 DVP_XCLK +IO_47 DVP_PCLK +===== ========== ======= + Over- and Under-clocking ------------------------ @@ -408,7 +468,7 @@ Address Size Description 0x8801C000 0x1000 riscv priv spec 1.9 config 0x8801D000 0x2000 flattened device tree (contains only addresses and interrupts) -0x8801f000 0x1000 credits +0x8801F000 0x1000 credits ========== ========= =========== Links 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..06a9cc060f --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt @@ -0,0 +1,102 @@ +Kendryte K210 FPIOA + +This binding describes the Fully-Programmable Input/Output Array (FPIOA) found +in 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 + +Required properties for pin-configuration nodes or sub-nodes are: +- groups: list of power groups to which the configuration applies. Valid groups + are: + A0, A1, A2, B0, B1, B2, C0, C1 + (either this or "pinmux" must be specified) +- pinmux: integer array representing pin multiplexing configuration. In addition + to the 256 standard functions, each pin can also output the direction + indicator (DO) of any function. This signal is high whenever the function + would normally drive the output. Helper macros to ease assembling the "pinmux" + arguments from the pin and function are provided by the FPIOA header file at: + <dt-bindings/pinctrl/k210-pinctrl.h> + Integer values in the "pinmux" argument list are assembled as: + ((PIN << 16) | (DO << 8) | (FUNC)) + Valid values for PIN are numbers 0 through 47. + Valid values for DO are 0 or 1. + Valid values for FUNC are numbers 0 through 255. For a complete list of + acceptable functions, consult the FPIOA header file. + (either this or "groups" must be specified) + +Optional properties for "pinmux" nodes are: + bias-disable, bias-pull-down, bias-pull-up, drive-strength, + drive-strength-ua, input-enable, input-disable, input-schmitt-enable, + input-schmitt-disable, output-low, output-high, output-enable, + output-disable, slew-rate, output-polarity-invert, input-polarity-invert + +Optional properties for "groups" nodes are: + power-source + +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. +- input- and output-polarity-invert: Invert the polarity of either the input or + the output, respectively. +- power-source: Controls the output voltage of a bank of pins. Either + K210_PC_POWER_1V8 or K210_PC_POWER_3V3 may be specified. +- slew-rate: Specifying this property reduces the slew rate. + +Example: +fpioa: pinmux@502B0000 { + compatible = "kendryte,k210-fpioa"; + reg = <0x502B0000 0x100>; + kendryte,sysctl = <&sysctl>; + kendryte,power-offset = <K210_SYSCTL_POWER_SEL>; + + /* JTAG running at 3.3V and driven at 11 mA */ + fpioa_jtag: jtag { + voltage { + group = "A0"; + power-source = <K210_PC_POWER_3V3>; + }; + + jtag { + pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCK)>, + <K210_FPIOA(1, K210_PCF_JTAG_TDI)>, + <K210_FPIOA(2, K210_PCF_JTAG_TMS)>, + <K210_FPIOA(3, K210_PCF_JTAG_TDO)>; + drive-strength = <11>; + } + }; + + /* I2C configured for use with a TCA9800 level shifter */ + fpioa_i2c: i2c { + i2c { + pinmux = <K210_FPIOA(6, K210_PCF_I2C0_SCLK)>, + <K210_FPIOA(7, K210_PCF_I2C0_SDA)>; + }; + + direction { + pinmux = <K210_FPIOA_DO(8, K210_PCF_I2C0_SDA)>; + output-polarity-invert; + }; + }; + + /* UART with an active-high TX status LED */ + fpioa_uart1: uart1 { + uart { + pinmux = <K210_FPIOA(9, K210_PCF_UART1_TX)>, + <K210_FPIOA(10, K210_PCF_UART1_RX)>; + }; + + status { + pinmux = <K210_FPIOA_DO(11, K210_PCF_UART1_TX)>; + }; + }; +}; diff --git a/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt b/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt index b73c96d24f..603796f169 100644 --- a/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt +++ b/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt @@ -119,7 +119,8 @@ For example: The contents of each of those pin configuration child nodes is defined entirely by the binding for the individual pin controller device. There -exists no common standard for this content. +exists no common standard for this content. The pinctrl framework only +provides generic helper bindings that the pin controller driver can use. The pin configuration nodes need not be direct children of the pin controller device; they may be grandchildren, for example. Whether this is legal, and @@ -156,6 +157,29 @@ state_2_node_a { pins = "mfio29", "mfio30"; }; +For hardware where pin multiplexing configurations have to be specified for +each single pin the number of required sub-nodes containing "pin" and +"function" properties can quickly escalate and become hard to write and +maintain. + +For cases like this, the pin controller driver may use the pinmux helper +property, where the pin identifier is provided with mux configuration settings +in a pinmux group. A pinmux group consists of the pin identifier and mux +settings represented as a single integer or an array of integers. + +The pinmux property accepts an array of pinmux groups, each of them describing +a single pin multiplexing configuration. + +pincontroller { + state_0_node_a { + pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...; + }; +}; + +Each individual pin controller driver bindings documentation shall specify +how pin IDs and pin multiplexing configuration are defined and assembled +together in a pinmux group. + == Generic pin configuration node content == Many data items that are represented in a pin configuration node are common @@ -168,12 +192,15 @@ structure of the DT nodes that contain these properties. Supported generic properties are: pins - the list of pins that properties in the node - apply to (either this or "group" has to be + apply to (either this, "group" or "pinmux" has to be specified) group - the group to apply the properties to, if the driver supports configuration of whole groups rather than - individual pins (either this or "pins" has to be - specified) + individual pins (either this, "pins" or "pinmux" has + to be specified) +pinmux - the list of numeric pin ids and their mux settings + that properties in the node apply to (either this, + "pins" or "groups" have to be specified) bias-disable - disable any pin bias bias-high-impedance - high impedance mode ("third-state", "floating") bias-bus-hold - latch weakly @@ -184,17 +211,30 @@ drive-push-pull - drive actively high and low drive-open-drain - drive with open drain drive-open-source - drive with open source drive-strength - sink or source at most X mA -input-enable - enable input on pin (no effect on output) -input-disable - disable input on pin (no effect on output) +drive-strength-microamp - sink or source at most X uA +input-enable - enable input on pin (no effect on output, such as + enabling an input buffer) +input-disable - disable input on pin (no effect on output, such as + disabling an input buffer) input-schmitt-enable - enable schmitt-trigger mode input-schmitt-disable - disable schmitt-trigger mode input-debounce - debounce mode with debound time X power-source - select between different power supplies low-power-enable - enable low power mode low-power-disable - disable low power mode +output-disable - disable output on a pin (such as disable an output + buffer) +output-enable - enable output on a pin without actively driving it + (such as enabling an output buffer) output-low - set the pin to output mode with low level output-high - set the pin to output mode with high level +sleep-hardware-state - indicate this is sleep related state which will be programmed + into the registers for the sleep state. slew-rate - set the slew rate +skew-delay - this affects the expected clock skew on input pins + and the delay before latching a value to an output + pin. Typically indicates how many double-inverters are + used to delay the signal. For example: @@ -216,6 +256,12 @@ state_2_node_a { bias-pull-up; }; }; +state_3_node_a { + mux { + pinmux = <GPIOx_PINm_MUXn>, <GPIOx_PINj_MUXk)>; + input-enable; + }; +}; Some of the generic properties take arguments. For those that do, the arguments are described below. @@ -224,11 +270,18 @@ arguments are described below. binding for the hardware defines: - Whether the entries are integers or strings, and their meaning. +- pinmux takes a list of pin IDs and mux settings as required argument. The + specific bindings for the hardware defines: + - How pin IDs and mux settings are defined and assembled together in a single + integer or an array of integers. + - bias-pull-up, -down and -pin-default take as optional argument on hardware supporting it the pull strength in Ohm. bias-disable will disable the pull. - drive-strength takes as argument the target strength in mA. +- drive-strength-microamp takes as argument the target strength in uA. + - input-debounce takes the debounce time in usec as argument or 0 to disable debouncing diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e5e3518194..37916e7771 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -40,7 +40,7 @@ struct gpio_dwapb_platdata { const char *name; int bank; int pins; - fdt_addr_t base; + void __iomem *base; }; static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin) @@ -66,13 +66,6 @@ static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin, return 0; } -static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin) -{ - struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); - return !!(readl(plat->base + GPIO_EXT_PORT(plat->bank)) & (1 << pin)); -} - - static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); @@ -98,6 +91,18 @@ static int dwapb_gpio_get_function(struct udevice *dev, unsigned offset) return GPIOF_INPUT; } +static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + u32 value; + + if (dwapb_gpio_get_function(dev, pin) == GPIOF_OUTPUT) + value = readl(plat->base + GPIO_SWPORT_DR(plat->bank)); + else + value = readl(plat->base + GPIO_EXT_PORT(plat->bank)); + return !!(value & BIT(pin)); +} + static const struct dm_gpio_ops gpio_dwapb_ops = { .direction_input = dwapb_gpio_direction_input, .direction_output = dwapb_gpio_direction_output, @@ -176,7 +181,7 @@ static int gpio_dwapb_bind(struct udevice *dev) if (!plat) return -ENOMEM; - plat->base = base; + plat->base = (void *)base; plat->bank = bank; plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0); @@ -186,7 +191,15 @@ static int gpio_dwapb_bind(struct udevice *dev) * Fall back to node name. This means accessing pins * via bank name won't work. */ - plat->name = ofnode_get_name(node); + char name[32]; + + snprintf(name, sizeof(name), "%s_", + ofnode_get_name(node)); + plat->name = strdup(name); + if (!plat->name) { + kfree(plat); + return -ENOMEM; + } } ret = device_bind_ofnode(dev, dev->driver, plat->name, diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c index ef9b61ee62..2cdb0269f4 100644 --- a/drivers/led/led_gpio.c +++ b/drivers/led/led_gpio.c @@ -99,11 +99,8 @@ static int led_gpio_bind(struct udevice *parent) const char *label; label = ofnode_read_string(node, "label"); - if (!label) { - debug("%s: node %s has no label\n", __func__, - ofnode_get_name(node)); - return -EINVAL; - } + if (!label) + label = ofnode_get_name(node); ret = device_bind_driver_to_node(parent, "gpio_led", ofnode_get_name(node), node, &dev); diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 048583f39b..77fb851114 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -291,6 +291,13 @@ config ASPEED_AST2500_PINCTRL uses Generic Pinctrl framework and is compatible with the Linux driver, i.e. it uses the same device tree configuration. +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. endif source "drivers/pinctrl/broadcom/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 507dd3a926..05b71f2f13 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) += pinctrl-kendryte.o obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MTK) += mediatek/ obj-$(CONFIG_PINCTRL_MSCC) += mscc/ diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c index 313aeccb1e..3c8e24088c 100644 --- a/drivers/pinctrl/pinctrl-generic.c +++ b/drivers/pinctrl/pinctrl-generic.c @@ -227,6 +227,13 @@ static int pinconf_enable_setting(struct udevice *dev, bool is_group, } #endif +enum pinmux_subnode_type { + PST_NONE = 0, + PST_PIN, + PST_GROUP, + PST_PINMUX, +}; + /** * pinctrl_generic_set_state_one() - set state for a certain pin/group * Apply all pin multiplexing and pin configurations specified by @config @@ -234,13 +241,15 @@ static int pinconf_enable_setting(struct udevice *dev, bool is_group, * * @dev: pin controller device * @config: pseudo device pointing to config node - * @is_group: target of operation (true: pin group, false: pin) - * @selector: pin selector or group selector, depending on @is_group + * @subnode_type: target of operation (pin, group, or pin specified by a pinmux + * group) + * @selector: pin selector or group selector, depending on @subnode_type * @return: 0 on success, or negative error code on failure */ static int pinctrl_generic_set_state_one(struct udevice *dev, struct udevice *config, - bool is_group, unsigned selector) + enum pinmux_subnode_type subnode_type, + unsigned selector) { const char *propname; const void *value; @@ -248,17 +257,22 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, int len, func_selector, param, ret; u32 arg, default_val; + assert(subnode_type != PST_NONE); + dev_for_each_property(property, config) { value = dev_read_prop_by_prop(&property, &propname, &len); if (!value) return -EINVAL; - if (!strcmp(propname, "function")) { + /* pinmux subnodes already have their muxing set */ + if (subnode_type != PST_PINMUX && + !strcmp(propname, "function")) { func_selector = pinmux_func_name_to_selector(dev, value); if (func_selector < 0) return func_selector; - ret = pinmux_enable_setting(dev, is_group, + ret = pinmux_enable_setting(dev, + subnode_type == PST_GROUP, selector, func_selector); } else { @@ -272,7 +286,8 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, else arg = default_val; - ret = pinconf_enable_setting(dev, is_group, + ret = pinconf_enable_setting(dev, + subnode_type == PST_GROUP, selector, param, arg); } @@ -284,6 +299,41 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, } /** + * pinctrl_generic_get_subnode_type() - determine whether there is a valid + * pins, groups, or pinmux property in the config node + * + * @dev: pin controller device + * @config: pseudo device pointing to config node + * @count: number of specifiers contained within the property + * @return: the type of the subnode, or PST_NONE + */ +static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev, + struct udevice *config, + int *count) +{ + const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + + *count = dev_read_string_count(config, "pins"); + if (*count >= 0) + return PST_PIN; + + *count = dev_read_string_count(config, "groups"); + if (*count >= 0) + return PST_GROUP; + + if (ops->pinmux_property_set) { + *count = dev_read_size(config, "pinmux"); + if (*count >= 0 && !(*count % sizeof(u32))) { + *count /= sizeof(u32); + return PST_PINMUX; + } + } + + *count = 0; + return PST_NONE; +} + +/** * pinctrl_generic_set_state_subnode() - apply all settings in config node * * @dev: pin controller device @@ -293,38 +343,55 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, static int pinctrl_generic_set_state_subnode(struct udevice *dev, struct udevice *config) { - const char *subnode_target_type = "pins"; - bool is_group = false; + enum pinmux_subnode_type subnode_type; const char *name; - int strings_count, selector, i, ret; - - strings_count = dev_read_string_count(config, subnode_target_type); - if (strings_count < 0) { - subnode_target_type = "groups"; - is_group = true; - strings_count = dev_read_string_count(config, - subnode_target_type); - if (strings_count < 0) { + int count, selector, i, ret, scratch; + const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */ + + subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count); + + debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name, + count); + + if (subnode_type == PST_PINMUX) { + pinmux_groups = dev_read_prop(config, "pinmux", &scratch); + if (!pinmux_groups) + return -EINVAL; + } + + for (i = 0; i < count; i++) { + switch (subnode_type) { + case PST_PIN: + ret = dev_read_string_index(config, "pins", i, &name); + if (ret) + return ret; + selector = pinctrl_pin_name_to_selector(dev, name); + break; + case PST_GROUP: + ret = dev_read_string_index(config, "groups", i, &name); + if (ret) + return ret; + selector = pinctrl_group_name_to_selector(dev, name); + break; + case PST_PINMUX: { + const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + u32 pinmux_group = fdt32_to_cpu(pinmux_groups[i]); + + /* Checked for in pinctrl_generic_get_subnode_type */ + selector = ops->pinmux_property_set(dev, pinmux_group); + break; + } + case PST_NONE: + default: /* skip this node; may contain config child nodes */ return 0; } - } - - for (i = 0; i < strings_count; i++) { - ret = dev_read_string_index(config, subnode_target_type, i, - &name); - if (ret) - return ret; - if (is_group) - selector = pinctrl_group_name_to_selector(dev, name); - else - selector = pinctrl_pin_name_to_selector(dev, name); if (selector < 0) return selector; - ret = pinctrl_generic_set_state_one(dev, config, - is_group, selector); + ret = pinctrl_generic_set_state_one(dev, config, subnode_type, + selector); if (ret) return ret; } diff --git a/drivers/pinctrl/pinctrl-kendryte.c b/drivers/pinctrl/pinctrl-kendryte.c new file mode 100644 index 0000000000..5ad049d955 --- /dev/null +++ b/drivers/pinctrl/pinctrl-kendryte.c @@ -0,0 +1,737 @@ +// 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 <linux/bitfield.h> +#include <linux/bitops.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 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) + +#define K210_PG_FUNC GENMASK(7, 0) +#define K210_PG_DO BIT(8) +#define K210_PG_PIN GENMASK(22, 16) + +#define PIN_CONFIG_OUTPUT_INVERT (PIN_CONFIG_END + 1) +#define PIN_CONFIG_INPUT_INVERT (PIN_CONFIG_END + 2) + +struct k210_fpioa { + u32 pins[48]; + u32 tie_en[8]; + u32 tie_val[8]; +}; + +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 */ +}; + +#ifdef CONFIG_CMD_PINMUX +static const char k210_pc_pin_names[][6] = { +#define PIN(i) \ + [i] = "IO_" #i + 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]; +} +#endif /* CONFIG_CMD_PINMUX */ + +/* 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, +}; + +static const u32 k210_pc_mode_id_to_mode[] = { +#define DEFAULT(mode) \ + [K210_PC_DEFAULT_##mode] = K210_PC_MODE_##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 { +#ifdef CONFIG_CMD_PINMUX + char name[15]; +#endif + u8 mode_id; +}; + +static const struct k210_pcf_info k210_pcf_infos[] = { +#ifdef CONFIG_CMD_PINMUX +#define FUNC(id, mode) \ + [K210_PCF_##id] = { \ + .name = #id, \ + .mode_id = K210_PC_DEFAULT_##mode \ + } +#else +#define FUNC(id, mode) \ + [K210_PCF_##id] = { \ + .mode_id = K210_PC_DEFAULT_##mode \ + } +#endif + 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_HSYNC, 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 +}; + +static int k210_pc_pinmux_set(struct udevice *dev, u32 pinmux_group) +{ + unsigned pin = FIELD_GET(K210_PG_PIN, pinmux_group); + bool do_oe = FIELD_GET(K210_PG_DO, pinmux_group); + unsigned func = FIELD_GET(K210_PG_FUNC, pinmux_group); + struct k210_pc_priv *priv = dev_get_priv(dev); + const struct k210_pcf_info *info = &k210_pcf_infos[func]; + u32 mode = k210_pc_mode_id_to_mode[info->mode_id]; + u32 val = func | mode | (do_oe ? K210_PC_DO_OE : 0); + + debug("%s(%.8x): IO_%.2u = %3u | %.8x\n", __func__, pinmux_group, pin, + func, mode); + + writel(val, &priv->fpioa->pins[pin]); + return pin; +} + +/* 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, + K210_FPIOA(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; + case PIN_CONFIG_OUTPUT_INVERT: + if (argument) + val |= K210_PC_DO_INV; + else + val &= ~K210_PC_DO_INV; + break; + case PIN_CONFIG_INPUT_INVERT: + if (argument) + val |= K210_PC_DI_INV; + else + val &= ~K210_PC_DI_INV; + 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 { + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_CMD_PINMUX +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; +} +#endif + +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 }, + { "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1}, + { "input-polarity-invert", PIN_CONFIG_INPUT_INVERT, 1}, +}; + +static const struct pinctrl_ops k210_pc_pinctrl_ops = { +#ifdef CONFIG_CMD_PINMUX + .get_pins_count = k210_pc_get_pins_count, + .get_pin_name = k210_pc_get_pin_name, +#endif + .get_groups_count = k210_pc_get_groups_count, + .get_group_name = k210_pc_get_group_name, + .pinmux_property_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, +#ifdef CONFIG_CMD_PINMUX + .get_pin_muxing = k210_pc_get_pin_muxing, +#endif +}; + +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; + + debug("%s: fpioa = %p sysctl = %p power offset = %x\n", __func__, + priv->fpioa, (void *)priv->sysctl->ranges[0].start, + priv->power_offset); + + /* 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/pinctrl-sandbox.c b/drivers/pinctrl/pinctrl-sandbox.c index ac0119d198..d27f74248d 100644 --- a/drivers/pinctrl/pinctrl-sandbox.c +++ b/drivers/pinctrl/pinctrl-sandbox.c @@ -1,57 +1,70 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> */ -/* #define DEBUG */ - #include <common.h> #include <dm.h> -#include <log.h> #include <dm/pinctrl.h> +#include <dt-bindings/pinctrl/sandbox-pinmux.h> +#include <log.h> #include <linux/bitops.h> +/* + * This driver emulates a pin controller with the following rules: + * - The pinctrl config for each pin must be set individually + * - The first three pins (P0-P2) must be muxed as a group + * - The next two pins (P3-P4) must be muxed as a group + * - The last four pins (P5-P8) must be muxed individually + */ + static const char * const sandbox_pins[] = { - "SCL", - "SDA", - "TX", - "RX", - "W1", - "GPIO0", - "GPIO1", - "GPIO2", - "GPIO3", +#define PIN(x) \ + [x] = "P" #x + PIN(0), + PIN(1), + PIN(2), + PIN(3), + PIN(4), + PIN(5), + PIN(6), + PIN(7), + PIN(8), +#undef PIN }; -static const char * const sandbox_pins_muxing[] = { - "I2C SCL", - "I2C SDA", - "Uart TX", - "Uart RX", - "1-wire gpio", - "gpio", - "gpio", - "gpio", - "gpio", +static const char * const sandbox_pins_muxing[][2] = { + { "UART TX", "I2C SCL" }, + { "UART RX", "I2C SDA" }, + { "SPI SCLK", "I2S SCK" }, + { "SPI MOSI", "I2S SD" }, + { "SPI MISO", "I2S WS" }, + { "GPIO0", "SPI CS0" }, + { "GPIO1", "SPI CS1" }, + { "GPIO2", "PWM0" }, + { "GPIO3", "PWM1" }, }; +#define SANDBOX_GROUP_I2C_UART 0 +#define SANDBOX_GROUP_SPI_I2S 1 + static const char * const sandbox_groups[] = { - "i2c", - "serial_a", - "serial_b", - "spi", - "w1", + [SANDBOX_GROUP_I2C_UART] = "I2C_UART", + [SANDBOX_GROUP_SPI_I2S] = "SPI_I2S", }; static const char * const sandbox_functions[] = { - "i2c", - "serial", - "spi", - "w1", - "gpio", - "gpio", - "gpio", - "gpio", +#define FUNC(id) \ + [SANDBOX_PINMUX_##id] = #id + FUNC(UART), + FUNC(I2C), + FUNC(SPI), + FUNC(I2S), + FUNC(GPIO), + FUNC(CS), + FUNC(PWM), +#undef FUNC }; static const struct pinconf_param sandbox_conf_params[] = { @@ -68,9 +81,12 @@ static const struct pinconf_param sandbox_conf_params[] = { { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, }; -/* bitfield used to save param and value of each pin/selector */ -static unsigned int sandbox_pins_param[ARRAY_SIZE(sandbox_pins)]; -static unsigned int sandbox_pins_value[ARRAY_SIZE(sandbox_pins)]; +/* Bitfield used to save param and value of each pin/selector */ +struct sandbox_pinctrl_priv { + unsigned int mux; + unsigned int pins_param[ARRAY_SIZE(sandbox_pins)]; + unsigned int pins_value[ARRAY_SIZE(sandbox_pins)]; +}; static int sandbox_get_pins_count(struct udevice *dev) { @@ -87,16 +103,18 @@ static int sandbox_get_pin_muxing(struct udevice *dev, char *buf, int size) { const struct pinconf_param *p; + struct sandbox_pinctrl_priv *priv = dev_get_priv(dev); int i; - snprintf(buf, size, "%s", sandbox_pins_muxing[selector]); + snprintf(buf, size, "%s", + sandbox_pins_muxing[selector][!!(priv->mux & BIT(selector))]); - if (sandbox_pins_param[selector]) { + if (priv->pins_param[selector]) { for (i = 0, p = sandbox_conf_params; i < ARRAY_SIZE(sandbox_conf_params); i++, p++) { - if ((sandbox_pins_param[selector] & BIT(p->param)) && - (!!(sandbox_pins_value[selector] & BIT(p->param)) == + if ((priv->pins_param[selector] & BIT(p->param)) && + (!!(priv->pins_value[selector] & BIT(p->param)) == p->default_value)) { strncat(buf, " ", size); strncat(buf, p->property, size); @@ -133,12 +151,32 @@ static const char *sandbox_get_function_name(struct udevice *dev, static int sandbox_pinmux_set(struct udevice *dev, unsigned pin_selector, unsigned func_selector) { + int mux; + struct sandbox_pinctrl_priv *priv = dev_get_priv(dev); + debug("sandbox pinmux: pin = %d (%s), function = %d (%s)\n", pin_selector, sandbox_get_pin_name(dev, pin_selector), func_selector, sandbox_get_function_name(dev, func_selector)); - sandbox_pins_param[pin_selector] = 0; - sandbox_pins_value[pin_selector] = 0; + if (pin_selector < 5) + return -EINVAL; + + switch (func_selector) { + case SANDBOX_PINMUX_GPIO: + mux = 0; + break; + case SANDBOX_PINMUX_CS: + case SANDBOX_PINMUX_PWM: + mux = BIT(pin_selector); + break; + default: + return -EINVAL; + } + + priv->mux &= ~BIT(pin_selector); + priv->mux |= mux; + priv->pins_param[pin_selector] = 0; + priv->pins_value[pin_selector] = 0; return 0; } @@ -147,25 +185,75 @@ static int sandbox_pinmux_group_set(struct udevice *dev, unsigned group_selector, unsigned func_selector) { + bool mux; + int i, group_start, group_end; + struct sandbox_pinctrl_priv *priv = dev_get_priv(dev); + unsigned int mask; + debug("sandbox pinmux: group = %d (%s), function = %d (%s)\n", group_selector, sandbox_get_group_name(dev, group_selector), func_selector, sandbox_get_function_name(dev, func_selector)); + if (group_selector == SANDBOX_GROUP_I2C_UART) { + group_start = 0; + group_end = 1; + + if (func_selector == SANDBOX_PINMUX_UART) + mux = false; + else if (func_selector == SANDBOX_PINMUX_I2C) + mux = true; + else + return -EINVAL; + } else if (group_selector == SANDBOX_GROUP_SPI_I2S) { + group_start = 2; + group_end = 4; + + if (func_selector == SANDBOX_PINMUX_SPI) + mux = false; + else if (func_selector == SANDBOX_PINMUX_I2S) + mux = true; + else + return -EINVAL; + } else { + return -EINVAL; + } + + mask = GENMASK(group_end, group_start); + priv->mux &= ~mask; + priv->mux |= mux ? mask : 0; + + for (i = group_start; i < group_end; i++) { + priv->pins_param[i] = 0; + priv->pins_value[i] = 0; + } + return 0; } +static int sandbox_pinmux_property_set(struct udevice *dev, u32 pinmux_group) +{ + int ret; + unsigned pin_selector = pinmux_group & 0xFFFF; + unsigned func_selector = pinmux_group >> 16; + + ret = sandbox_pinmux_set(dev, pin_selector, func_selector); + return ret ? ret : pin_selector; +} + static int sandbox_pinconf_set(struct udevice *dev, unsigned pin_selector, unsigned param, unsigned argument) { + struct sandbox_pinctrl_priv *priv = dev_get_priv(dev); + debug("sandbox pinconf: pin = %d (%s), param = %d, arg = %d\n", pin_selector, sandbox_get_pin_name(dev, pin_selector), param, argument); - sandbox_pins_param[pin_selector] |= BIT(param); + priv->pins_param[pin_selector] |= BIT(param); if (argument) - sandbox_pins_value[pin_selector] |= BIT(param); + priv->pins_value[pin_selector] |= BIT(param); else - sandbox_pins_value[pin_selector] &= ~BIT(param); + priv->pins_value[pin_selector] &= ~BIT(param); return 0; } @@ -191,6 +279,7 @@ const struct pinctrl_ops sandbox_pinctrl_ops = { .get_function_name = sandbox_get_function_name, .pinmux_set = sandbox_pinmux_set, .pinmux_group_set = sandbox_pinmux_group_set, + .pinmux_property_set = sandbox_pinmux_property_set, .pinconf_num_params = ARRAY_SIZE(sandbox_conf_params), .pinconf_params = sandbox_conf_params, .pinconf_set = sandbox_pinconf_set, @@ -207,5 +296,6 @@ U_BOOT_DRIVER(sandbox_pinctrl) = { .name = "sandbox_pinctrl", .id = UCLASS_PINCTRL, .of_match = sandbox_pinctrl_match, + .priv_auto_alloc_size = sizeof(struct sandbox_pinctrl_priv), .ops = &sandbox_pinctrl_ops, }; diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index a0e859afd6..a270e13b26 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -73,6 +73,7 @@ config IMXRT_SDRAM to support external memories like sdram, psram & nand. This driver is for the sdram memory interface with the SEMC. +source "drivers/ram/aspeed/Kconfig" source "drivers/ram/rockchip/Kconfig" source "drivers/ram/sifive/Kconfig" source "drivers/ram/stm32mp1/Kconfig" diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile index d685a579a0..209a78c06f 100644 --- a/drivers/ram/Makefile +++ b/drivers/ram/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_K3_AM654_DDRSS) += k3-am654-ddrss.o obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ +obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_K3_J721E_DDRSS) += k3-j721e/ obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o diff --git a/drivers/ram/aspeed/Kconfig b/drivers/ram/aspeed/Kconfig new file mode 100644 index 0000000000..020c913188 --- /dev/null +++ b/drivers/ram/aspeed/Kconfig @@ -0,0 +1,10 @@ +if RAM || SPL_RAM +config ASPEED_DDR4_DUALX8 + bool "Enable Dual X8 DDR4 die" + depends on DM && OF_CONTROL && ARCH_ASPEED + default n + help + Say Y if dual X8 DDR4 die is used on the board. The aspeed ddr sdram + controller needs to know if the memory chip mounted on the board is dual + x8 die or not. Or it may get the wrong size of the memory space. +endif diff --git a/drivers/ram/aspeed/Makefile b/drivers/ram/aspeed/Makefile new file mode 100644 index 0000000000..af604f8a4b --- /dev/null +++ b/drivers/ram/aspeed/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +obj-$(CONFIG_ASPEED_AST2500) += sdram_ast2500.o
\ No newline at end of file diff --git a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c b/drivers/ram/aspeed/sdram_ast2500.c index 8536a70a19..9f4304cb66 100644 --- a/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c +++ b/drivers/ram/aspeed/sdram_ast2500.c @@ -247,7 +247,7 @@ static int ast2500_sdrammc_init_ddr4(struct dram_info *info) | SDRAM_PCR_RESETN_DIS | SDRAM_PCR_RGAP_CTRL_EN | SDRAM_PCR_ODT_EN | SDRAM_PCR_ODT_EXT_EN; const u32 conf = (SDRAM_CONF_CAP_1024M << SDRAM_CONF_CAP_SHIFT) -#ifdef CONFIG_DUALX8_RAM +#ifdef CONFIG_ASPEED_DDR4_DUALX8 | SDRAM_CONF_DUALX8 #endif | SDRAM_CONF_SCRAMBLE | SDRAM_CONF_SCRAMBLE_PAT2 | SDRAM_CONF_DDR4; diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c index 12f09a7a39..7caa6c550c 100644 --- a/drivers/watchdog/designware_wdt.c +++ b/drivers/watchdog/designware_wdt.c @@ -130,7 +130,7 @@ static int designware_wdt_probe(struct udevice *dev) if (ret) return ret; - priv->clk_khz = clk_get_rate(&clk); + priv->clk_khz = clk_get_rate(&clk) / 1000; if (!priv->clk_khz) return -EINVAL; #else diff --git a/examples/Makefile b/examples/Makefile index d440bc5655..bf518bd221 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ -ifndef CONFIG_SANDBOX +ifdef CONFIG_EXAMPLES ifdef FTRACE subdir-ccflags-y += -finstrument-functions -DFTRACE diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h index bc8b7c5c12..273fa1a7d7 100644 --- a/include/configs/qemu-arm.h +++ b/include/configs/qemu-arm.h @@ -45,13 +45,7 @@ #define CONFIG_SYS_CBSIZE 512 #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE -#ifdef CONFIG_TFABOOT -#define CONFIG_SYS_FLASH_BASE 0x4000000 -#define CONFIG_SYS_MAX_FLASH_BANKS 1 -#else -#define CONFIG_SYS_FLASH_BASE 0x0 -#define CONFIG_SYS_MAX_FLASH_BANKS 2 -#endif +#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT 2 #define CONFIG_SYS_MAX_FLASH_SECT 256 /* Sector: 256K, Bank: 64M */ #define CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index 692e5fc8cb..1bdc8d3cbd 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@com> */ #ifndef __PINCTRL_H @@ -11,11 +11,10 @@ /** * struct pinconf_param - pin config parameters - * - * @property: property name in DT nodes - * @param: ID for this config parameter - * @default_value: default value for this config parameter used in case - * no value is specified in DT nodes + * @property: Property name in DT nodes + * @param: ID for this config parameter + * @default_value: default value for this config parameter used in case + * no value is specified in DT nodes */ struct pinconf_param { const char * const property; @@ -27,106 +26,274 @@ struct pinconf_param { * struct pinctrl_ops - pin control operations, to be implemented by * pin controller drivers. * - * The @set_state is the only mandatory operation. You can implement your - * pinctrl driver with its own @set_state. In this case, the other callbacks - * are not required. Otherwise, generic pinctrl framework is also available; - * use pinctrl_generic_set_state for @set_state, and implement other operations + * set_state() is the only mandatory operation. You can implement your pinctrl + * driver with its own @set_state. In this case, the other callbacks are not + * required. Otherwise, generic pinctrl framework is also available; use + * pinctrl_generic_set_state for @set_state, and implement other operations * depending on your necessity. - * - * @get_pins_count: return number of selectable named pins available - * in this driver. (necessary to parse "pins" property in DTS) - * @get_pin_name: return the pin name of the pin selector, - * called by the core to figure out which pin it shall do - * operations to. (necessary to parse "pins" property in DTS) - * @get_groups_count: return number of selectable named groups available - * in this driver. (necessary to parse "groups" property in DTS) - * @get_group_name: return the group name of the group selector, - * called by the core to figure out which pin group it shall do - * operations to. (necessary to parse "groups" property in DTS) - * @get_functions_count: return number of selectable named functions available - * in this driver. (necessary for pin-muxing) - * @get_function_name: return the function name of the muxing selector, - * called by the core to figure out which mux setting it shall map a - * certain device to. (necessary for pin-muxing) - * @pinmux_set: enable a certain muxing function with a certain pin. - * The @func_selector selects a certain function whereas @pin_selector - * selects a certain pin to be used. On simple controllers one of them - * may be ignored. (necessary for pin-muxing against a single pin) - * @pinmux_group_set: enable a certain muxing function with a certain pin - * group. The @func_selector selects a certain function whereas - * @group_selector selects a certain set of pins to be used. On simple - * controllers one of them may be ignored. - * (necessary for pin-muxing against a pin group) - * @pinconf_num_params: number of driver-specific parameters to be parsed - * from device trees (necessary for pin-configuration) - * @pinconf_params: list of driver_specific parameters to be parsed from - * device trees (necessary for pin-configuration) - * @pinconf_set: configure an individual pin with a given parameter. - * (necessary for pin-configuration against a single pin) - * @pinconf_group_set: configure all pins in a group with a given parameter. - * (necessary for pin-configuration against a pin group) - * @set_state: do pinctrl operations specified by @config, a pseudo device - * pointing a config node. (necessary for pinctrl_full) - * @set_state_simple: do needed pinctrl operations for a peripherl @periph. - * (necessary for pinctrl_simple) - * @get_pin_muxing: display the muxing of a given pin. - * @gpio_request_enable: requests and enables GPIO on a certain pin. - * Implement this only if you can mux every pin individually as GPIO. The - * affected GPIO range is passed along with an offset(pin number) into that - * specific GPIO range - function selectors and pin groups are orthogonal - * to this, the core will however make sure the pins do not collide. - * @gpio_disable_free: free up GPIO muxing on a certain pin, the reverse of - * @gpio_request_enable */ struct pinctrl_ops { + /** + * @get_pins_count: Get the number of selectable pins + * + * @dev: Pinctrl device to use + * + * This function is necessary to parse the "pins" property in DTS. + * + * @Return: + * number of selectable named pins available in this driver + */ int (*get_pins_count)(struct udevice *dev); + + /** + * @get_pin_name: Get the name of a pin + * + * @dev: Pinctrl device of the pin + * + * @selector: The pin selector + * + * This function is called by the core to figure out which pin it will + * do operations to. This function is necessary to parse the "pins" + * property in DTS. + * + * @Return: const pointer to the name of the pin + */ const char *(*get_pin_name)(struct udevice *dev, unsigned selector); + + /** + * @get_groups_count: Get the number of selectable groups + * + * @dev: Pinctrl device to use + * + * This function is necessary to parse the "groups" property in DTS. + * + * @Return: + * number of selectable named groups available in the driver + */ int (*get_groups_count)(struct udevice *dev); + + /** + * @get_group_name: Get the name of a group + * + * @dev: Pinctrl device of the group + * + * @selector: The group selector + * + * This function is called by the core to figure out which group it + * will do operations to. This function is necessary to parse the + * "groups" property in DTS. + * + * @Return: Pointer to the name of the group + */ const char *(*get_group_name)(struct udevice *dev, unsigned selector); + + /** + * @get_functions_count: Get the number of selectable functions + * + * @dev: Pinctrl device to use + * + * This function is necessary for pin-muxing. + * + * @Return: + * number of selectable named functions available in this driver + */ int (*get_functions_count)(struct udevice *dev); + + /** + * @get_function_name: Get the name of a function + * + * @dev: Pinmux device of the function + * + * @selector: The function selector + * + * This function is called by the core to figure out which mux setting + * it will map a certain device to. This function is necessary for + * pin-muxing. + * + * @Return: + * Pointer to the function name of the muxing selector + */ const char *(*get_function_name)(struct udevice *dev, unsigned selector); + + /** + * @pinmux_set: Mux a pin to a function + * + * @dev: Pinctrl device to use + * + * @pin_selector: The pin selector + * + * @func_selector: The func selector + * + * On simple controllers one of @pin_selector or @func_selector may be + * ignored. This function is necessary for pin-muxing against a single + * pin. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*pinmux_set)(struct udevice *dev, unsigned pin_selector, unsigned func_selector); + + /** + * @pinmux_group_set: Mux a group of pins to a function + * + * @dev: Pinctrl device to use + * + * @group_selector: The group selector + * + * @func_selector: The func selector + * + * On simple controllers one of @group_selector or @func_selector may be + * ignored. This function is necessary for pin-muxing against a group of + * pins. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*pinmux_group_set)(struct udevice *dev, unsigned group_selector, unsigned func_selector); + + /** + * @pinmux_property_set: Enable a pinmux group + * + * @dev: Pinctrl device to use + * + * @pinmux_group: A u32 representing the pin identifier and mux + * settings. The exact format of a pinmux group is left + * up to the driver. + * + * Mux a single pin to a single function based on a driver-specific + * pinmux group. This function is necessary for parsing the "pinmux" + * property in DTS, and for pin-muxing against a pinmux group. + * + * @Return: + * Pin selector for the muxed pin if OK, or negative error code on + * failure + */ + int (*pinmux_property_set)(struct udevice *dev, u32 pinmux_group); + + /** + * @pinconf_num_params: + * Number of driver-specific parameters to be parsed from device + * trees. This member is necessary for pin configuration. + */ unsigned int pinconf_num_params; + + /** + * @pinconf_params: + * List of driver-specific parameters to be parsed from the device + * tree. This member is necessary for pin configuration. + */ const struct pinconf_param *pinconf_params; + + /** + * @pinconf_set: Configure an individual pin with a parameter + * + * @dev: Pinctrl device to use + * + * @pin_selector: The pin selector + * + * @param: An &enum pin_config_param from @pinconf_params + * + * @argument: The argument to this param from the device tree, or + * @pinconf_params.default_value + * + * This function is necessary for pin configuration against a single + * pin. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*pinconf_set)(struct udevice *dev, unsigned pin_selector, unsigned param, unsigned argument); + + /** + * @pinconf_group_set: Configure all pins in a group with a parameter + * + * @dev: Pinctrl device to use + * + * @pin_selector: The group selector + * + * @param: A &enum pin_config_param from + * @pinconf_params + * + * @argument: The argument to this param from the device tree, or + * @pinconf_params.default_value + * + * This function is necessary for pin configuration against a group of + * pins. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*pinconf_group_set)(struct udevice *dev, unsigned group_selector, unsigned param, unsigned argument); + + /** + * @set_state: Configure a pinctrl device + * + * @dev: Pinctrl device to use + * + * @config: Pseudo device pointing a config node + * + * This function is required to be implemented by all pinctrl drivers. + * Drivers may set this member to pinctrl_generic_set_state(), which + * will call other functions in &struct pinctrl_ops to parse + * @config. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*set_state)(struct udevice *dev, struct udevice *config); - /* for pinctrl-simple */ + /** + * @set_state_simple: Configure a pinctrl device + * + * @dev: Pinctrl device to use + * + * @config: Pseudo-device pointing a config node + * + * This function is usually a simpler version of set_state(). Only the + * first pinctrl device on the system is supported by this function. + * + * @Return: 0 if OK, or negative error code on failure + */ int (*set_state_simple)(struct udevice *dev, struct udevice *periph); + /** - * request() - Request a particular pinctrl function + * @request: Request a particular pinctrl function + * + * @dev: Device to adjust (%UCLASS_PINCTRL) + * + * @func: Function number (driver-specific) * * This activates the selected function. * - * @dev: Device to adjust (UCLASS_PINCTRL) - * @func: Function number (driver-specific) - * @return 0 if OK, -ve on error + * @Return: 0 if OK, or negative error code on failure */ int (*request)(struct udevice *dev, int func, int flags); /** - * get_periph_id() - get the peripheral ID for a device + * @get_periph_id: Get the peripheral ID for a device + * + * @dev: Pinctrl device to use for decoding + * + * @periph: Device to check * * This generally looks at the peripheral's device tree node to work * out the peripheral ID. The return value is normally interpreted as - * enum periph_id. so long as this is defined by the platform (which it + * &enum periph_id. so long as this is defined by the platform (which it * should be). * - * @dev: Pinctrl device to use for decoding - * @periph: Device to check - * @return peripheral ID of @periph, or -ENOENT on error + * @Return: + * Peripheral ID of @periph, or %-ENOENT on error */ int (*get_periph_id)(struct udevice *dev, struct udevice *periph); /** - * get_gpio_mux() - get the mux value for a particular GPIO + * @get_gpio_mux: Get the mux value for a particular GPIO + * + * @dev: Pinctrl device to use + * + * @banknum: GPIO bank number + * + * @index: GPIO index within the bank * * This allows the raw mux value for a GPIO to be obtained. It is * useful for displaying the function being used by that GPIO, such @@ -134,46 +301,60 @@ struct pinctrl_ops { * subsystem and should not be used by generic code. Typically it is * used by a GPIO driver with knowledge of the SoC pinctrl setup. * - * @dev: Pinctrl device to use - * @banknum: GPIO bank number - * @index: GPIO index within the bank - * @return mux value (SoC-specific, e.g. 0 for input, 1 for output) + * @Return: + * Mux value (SoC-specific, e.g. 0 for input, 1 for output) */ int (*get_gpio_mux)(struct udevice *dev, int banknum, int index); /** - * get_pin_muxing() - show pin muxing + * @get_pin_muxing: Show pin muxing + * + * @dev: Pinctrl device to use + * + * @selector: Pin selector + * + * @buf: Buffer to fill with pin muxing description + * + * @size: Size of @buf * * This allows to display the muxing of a given pin. It's useful for - * debug purpose to know if a pin is configured as GPIO or as an - * alternate function and which one. - * Typically it is used by a PINCTRL driver with knowledge of the SoC - * pinctrl setup. - * - * @dev: Pinctrl device to use - * @selector: Pin selector - * @buf Pin's muxing description - * @size Pin's muxing description length - * return 0 if OK, -ve on error + * debug purposes to know if a pin is configured as GPIO or as an + * alternate function and which one. Typically it is used by a PINCTRL + * driver with knowledge of the SoC pinctrl setup. + * + * @Return: 0 if OK, or negative error code on failure */ int (*get_pin_muxing)(struct udevice *dev, unsigned int selector, char *buf, int size); /** - * gpio_request_enable: requests and enables GPIO on a certain pin. + * @gpio_request_enable: Request and enable GPIO on a certain pin. + * + * @dev: Pinctrl device to use + * + * @selector: Pin selector + * + * Implement this only if you can mux every pin individually as GPIO. + * The affected GPIO range is passed along with an offset(pin number) + * into that specific GPIO range - function selectors and pin groups are + * orthogonal to this, the core will however make sure the pins do not + * collide. * - * @dev: Pinctrl device to use - * @selector: Pin selector - * return 0 if OK, -ve on error + * @Return: + * 0 if OK, or negative error code on failure */ int (*gpio_request_enable)(struct udevice *dev, unsigned int selector); /** - * gpio_disable_free: free up GPIO muxing on a certain pin. + * @gpio_disable_free: Free up GPIO muxing on a certain pin. * - * @dev: Pinctrl device to use - * @selector: Pin selector - * return 0 if OK, -ve on error + * @dev: Pinctrl device to use + * + * @selector: Pin selector + * + * This function is the reverse of @gpio_request_enable. + * + * @Return: 0 if OK, or negative error code on failure */ int (*gpio_disable_free)(struct udevice *dev, unsigned int selector); }; @@ -181,27 +362,26 @@ struct pinctrl_ops { #define pinctrl_get_ops(dev) ((struct pinctrl_ops *)(dev)->driver->ops) /** - * Generic pin configuration paramters + * enum pin_config_param - Generic pin configuration parameters * - * enum pin_config_param - possible pin configuration parameters - * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it + * @PIN_CONFIG_BIAS_BUS_HOLD: The pin will be set to weakly latch so that it * weakly drives the last value on a tristate bus, also known as a "bus * holder", "bus keeper" or "repeater". This allows another device on the * bus to change the value by driving the bus high or low and switching to * tristate. The argument is ignored. - * @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a + * @PIN_CONFIG_BIAS_DISABLE: Disable any pin bias on the pin, a * transition from say pull-up to pull-down implies that you disable * pull-up in the process, this setting disables all biasing. - * @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: the pin will be set to a high impedance + * @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: The pin will be set to a high impedance * mode, also know as "third-state" (tristate) or "high-Z" or "floating". * On output pins this effectively disconnects the pin, which is useful * if for example some other pin is going to drive the signal connected * to it for a while. Pins used for input are usually always high * impedance. - * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high + * @PIN_CONFIG_BIAS_PULL_DOWN: The pin will be pulled down (usually with high * impedance to GROUND). If the argument is != 0 pull-down is enabled, * if it is 0, pull-down is total, i.e. the pin is connected to GROUND. - * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based + * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: The pin will be pulled up or down based * on embedded knowledge of the controller hardware, like current mux * function. The pull direction and possibly strength too will normally * be decided completely inside the hardware block and not be readable @@ -209,67 +389,67 @@ struct pinctrl_ops { * If the argument is != 0 pull up/down is enabled, if it is 0, the * configuration is ignored. The proper way to disable it is to use * @PIN_CONFIG_BIAS_DISABLE. - * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high + * @PIN_CONFIG_BIAS_PULL_UP: The pin will be pulled up (usually with high * impedance to VDD). If the argument is != 0 pull-up is enabled, * if it is 0, pull-up is total, i.e. the pin is connected to VDD. - * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open + * @PIN_CONFIG_DRIVE_OPEN_DRAIN: The pin will be driven with open drain (open * collector) which means it is usually wired with other output ports * which are then pulled up with an external resistor. Setting this * config will enable open drain mode, the argument is ignored. - * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source + * @PIN_CONFIG_DRIVE_OPEN_SOURCE: The pin will be driven with open source * (open emitter). Setting this config will enable open source mode, the * argument is ignored. - * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and + * @PIN_CONFIG_DRIVE_PUSH_PULL: The pin will be driven actively high and * low, this is the most typical case and is typically achieved with two * active transistors on the output. Setting this config will enable * push-pull mode, the argument is ignored. - * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current + * @PIN_CONFIG_DRIVE_STRENGTH: The pin will sink or source at most the current * passed as argument. The argument is in mA. - * @PIN_CONFIG_DRIVE_STRENGTH_UA: the pin will sink or source at most the current - * passed as argument. The argument is in uA. - * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode, + * @PIN_CONFIG_DRIVE_STRENGTH_UA: The pin will sink or source at most the + * current passed as argument. The argument is in uA. + * @PIN_CONFIG_INPUT_DEBOUNCE: This will configure the pin to debounce mode, * which means it will wait for signals to settle when reading inputs. The * argument gives the debounce time in usecs. Setting the * argument to zero turns debouncing off. - * @PIN_CONFIG_INPUT_ENABLE: enable the pin's input. Note that this does not + * @PIN_CONFIG_INPUT_ENABLE: Enable the pin's input. Note that this does not * affect the pin's ability to drive output. 1 enables input, 0 disables * input. - * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in + * @PIN_CONFIG_INPUT_SCHMITT: This will configure an input pin to run in * schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis, * the threshold value is given on a custom format as argument when * setting pins to this mode. - * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin. + * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: Control schmitt-trigger mode on the pin. * If the argument != 0, schmitt-trigger mode is enabled. If it's 0, * schmitt-trigger mode is disabled. - * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power + * @PIN_CONFIG_LOW_POWER_MODE: This will configure the pin for low power * operation, if several modes of operation are supported these can be * passed in the argument on a custom form, else just use argument 1 * to indicate low power mode, argument 0 turns low power mode off. - * @PIN_CONFIG_OUTPUT_ENABLE: this will enable the pin's output mode + * @PIN_CONFIG_OUTPUT_ENABLE: This will enable the pin's output mode * without driving a value there. For most platforms this reduces to * enable the output buffers and then let the pin controller current * configuration (eg. the currently selected mux function) drive values on * the line. Use argument 1 to enable output mode, argument 0 to disable * it. - * @PIN_CONFIG_OUTPUT: this will configure the pin as an output and drive a + * @PIN_CONFIG_OUTPUT: This will configure the pin as an output and drive a * value on the line. Use argument 1 to indicate high level, argument 0 to * indicate low level. (Please see Documentation/driver-api/pinctl.rst, * section "GPIO mode pitfalls" for a discussion around this parameter.) - * @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power + * @PIN_CONFIG_POWER_SOURCE: If the pin can select between different power * supplies, the argument to this parameter (on a custom format) tells * the driver which alternative power source to use. - * @PIN_CONFIG_SLEEP_HARDWARE_STATE: indicate this is sleep related state. - * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to + * @PIN_CONFIG_SLEEP_HARDWARE_STATE: Indicate this is sleep related state. + * @PIN_CONFIG_SLEW_RATE: If the pin can select slew rate, the argument to * this parameter (on a custom format) tells the driver which alternative * slew rate to use. - * @PIN_CONFIG_SKEW_DELAY: if the pin has programmable skew rate (on inputs) + * @PIN_CONFIG_SKEW_DELAY: If the pin has programmable skew rate (on inputs) * or latch delay (on outputs) this parameter (in a custom format) * specifies the clock skew or latch delay. It typically controls how * many double inverters are put in front of the line. - * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if + * @PIN_CONFIG_END: This is the last enumerator for pin configurations, if * you need to pass in custom configurations to the pin controller, use * PIN_CONFIG_END+1 as the base offset. - * @PIN_CONFIG_MAX: this is the maximum configuration value that can be + * @PIN_CONFIG_MAX: This is the maximum configuration value that can be * presented using the packed format. */ enum pin_config_param { @@ -301,13 +481,14 @@ enum pin_config_param { #if CONFIG_IS_ENABLED(PINCTRL_GENERIC) /** - * pinctrl_generic_set_state() - generic set_state operation + * pinctrl_generic_set_state() - Generic set_state operation + * @pctldev: Pinctrl device to use + * @config: Config device (pseudo device), pointing a config node in DTS + * * Parse the DT node of @config and its children and handle generic properties * such as "pins", "groups", "functions", and pin configuration parameters. * - * @pctldev: pinctrl device - * @config: config device (pseudo device), pointing a config node in DTS - * @return: 0 on success, or negative error code on failure + * Return: 0 on success, or negative error code on failure */ int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config); #else @@ -320,11 +501,11 @@ static inline int pinctrl_generic_set_state(struct udevice *pctldev, #if CONFIG_IS_ENABLED(PINCTRL) /** - * pinctrl_select_state() - set a device to a given state + * pinctrl_select_state() - Set a device to a given state + * @dev: Peripheral device + * @statename: State name, like "default" * - * @dev: peripheral device - * @statename: state name, like "default" - * @return: 0 on success, or negative error code on failure + * Return: 0 on success, or negative error code on failure */ int pinctrl_select_state(struct udevice *dev, const char *statename); #else @@ -337,40 +518,43 @@ static inline int pinctrl_select_state(struct udevice *dev, /** * pinctrl_request() - Request a particular pinctrl function - * - * @dev: Device to check (UCLASS_PINCTRL) + * @dev: Pinctrl device to use * @func: Function number (driver-specific) * @flags: Flags (driver-specific) - * @return 0 if OK, -ve on error + * + * Return: 0 if OK, or negative error code on failure */ int pinctrl_request(struct udevice *dev, int func, int flags); /** * pinctrl_request_noflags() - Request a particular pinctrl function + * @dev: Pinctrl device to use + * @func: Function number (driver-specific) * * This is similar to pinctrl_request() but uses 0 for @flags. * - * @dev: Device to check (UCLASS_PINCTRL) - * @func: Function number (driver-specific) - * @return 0 if OK, -ve on error + * Return: 0 if OK, or negative error code on failure */ int pinctrl_request_noflags(struct udevice *dev, int func); /** - * pinctrl_get_periph_id() - get the peripheral ID for a device + * pinctrl_get_periph_id() - Get the peripheral ID for a device + * @dev: Pinctrl device to use for decoding + * @periph: Device to check * * This generally looks at the peripheral's device tree node to work out the * peripheral ID. The return value is normally interpreted as enum periph_id. * so long as this is defined by the platform (which it should be). * - * @dev: Pinctrl device to use for decoding - * @periph: Device to check - * @return peripheral ID of @periph, or -ENOENT on error + * Return: Peripheral ID of @periph, or -ENOENT on error */ int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph); /** * pinctrl_get_gpio_mux() - get the mux value for a particular GPIO + * @dev: Pinctrl device to use + * @banknum: GPIO bank number + * @index: GPIO index within the bank * * This allows the raw mux value for a GPIO to be obtained. It is * useful for displaying the function being used by that GPIO, such @@ -378,66 +562,64 @@ int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph); * subsystem and should not be used by generic code. Typically it is * used by a GPIO driver with knowledge of the SoC pinctrl setup. * - * @dev: Pinctrl device to use - * @banknum: GPIO bank number - * @index: GPIO index within the bank - * @return mux value (SoC-specific, e.g. 0 for input, 1 for output) + * Return: Mux value (SoC-specific, e.g. 0 for input, 1 for output) */ int pinctrl_get_gpio_mux(struct udevice *dev, int banknum, int index); /** * pinctrl_get_pin_muxing() - Returns the muxing description + * @dev: Pinctrl device to use + * @selector: Pin index within pin-controller + * @buf: Pin's muxing description + * @size: Pin's muxing description length * * This allows to display the muxing description of the given pin for * debug purpose * - * @dev: Pinctrl device to use - * @selector Pin index within pin-controller - * @buf Pin's muxing description - * @size Pin's muxing description length - * @return 0 if OK, -ve on error + * Return: 0 if OK, or negative error code on failure */ int pinctrl_get_pin_muxing(struct udevice *dev, int selector, char *buf, int size); /** - * pinctrl_get_pins_count() - display pin-controller pins number + * pinctrl_get_pins_count() - Display pin-controller pins number + * @dev: Pinctrl device to use * * This allows to know the number of pins owned by a given pin-controller * - * @dev: Pinctrl device to use - * @return pins number if OK, -ve on error + * Return: Number of pins if OK, or negative error code on failure */ int pinctrl_get_pins_count(struct udevice *dev); /** * pinctrl_get_pin_name() - Returns the pin's name + * @dev: Pinctrl device to use + * @selector: Pin index within pin-controller + * @buf: Buffer to fill with the name of the pin + * @size: Size of @buf * * This allows to display the pin's name for debug purpose * - * @dev: Pinctrl device to use - * @selector Pin index within pin-controller - * @buf Pin's name - * @return 0 if OK, -ve on error + * Return: 0 if OK, or negative error code on failure */ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, int size); /** - * pinctrl_gpio_request() - request a single pin to be used as GPIO + * pinctrl_gpio_request() - Request a single pin to be used as GPIO + * @dev: GPIO peripheral device + * @offset: GPIO pin offset from the GPIO controller * - * @dev: GPIO peripheral device - * @offset: the GPIO pin offset from the GPIO controller - * @return: 0 on success, or negative error code on failure + * Return: 0 on success, or negative error code on failure */ int pinctrl_gpio_request(struct udevice *dev, unsigned offset); /** - * pinctrl_gpio_free() - free a single pin used as GPIO + * pinctrl_gpio_free() - Free a single pin used as GPIO + * @dev: GPIO peripheral device + * @offset: GPIO pin offset from the GPIO controller * - * @dev: GPIO peripheral device - * @offset: the GPIO pin offset from the GPIO controller - * @return: 0 on success, or negative error code on failure + * Return: 0 on success, or negative error code on failure */ int pinctrl_gpio_free(struct udevice *dev, unsigned offset); diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h new file mode 100644 index 0000000000..26c1f23b0f --- /dev/null +++ b/include/dt-bindings/pinctrl/k210-pinctrl.h @@ -0,0 +1,277 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#ifndef DT_K210_PINCTRL_H +#define DT_K210_PINCTRL_H + +/* + * Full list of FPIOA functions from + * kendryte-standalone-sdk/lib/drivers/include/fpioa.h + */ +#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_HSYNC 136 /* DVP Horizontal Sync */ +#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 */ + +#define K210_FPIOA(pin, func) (((pin) << 16) | (func)) +#define K210_FPIOA_DO(pin, func) (((pin) << 16) | (1 << 8) | (func)) + +#define K210_PC_POWER_3V3 0 +#define K210_PC_POWER_1V8 1 + +#endif /* DT_K210_PINCTRL_H */ diff --git a/include/dt-bindings/pinctrl/sandbox-pinmux.h b/include/dt-bindings/pinctrl/sandbox-pinmux.h new file mode 100644 index 0000000000..891af072e5 --- /dev/null +++ b/include/dt-bindings/pinctrl/sandbox-pinmux.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#ifndef SANDBOX_PINMUX_H +#define SANDBOX_PINMUX_H + +#define SANDBOX_PINMUX_UART 0 +#define SANDBOX_PINMUX_I2C 1 +#define SANDBOX_PINMUX_SPI 2 +#define SANDBOX_PINMUX_I2S 3 +#define SANDBOX_PINMUX_GPIO 4 +#define SANDBOX_PINMUX_CS 5 +#define SANDBOX_PINMUX_PWM 6 + +#define SANDBOX_PINMUX(pin, func) ((func) << 16 | (pin)) + +#endif /* SANDBOX_PINMUX_H */ diff --git a/test/dm/Makefile b/test/dm/Makefile index 70ba1b6695..e2b0798388 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -81,4 +81,7 @@ obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o +ifneq ($(CONFIG_PINMUX),) +obj-$(CONFIG_PINCONF) += pinmux.o +endif endif diff --git a/test/dm/led.c b/test/dm/led.c index 8b587d0a22..ac6ee36394 100644 --- a/test/dm/led.c +++ b/test/dm/led.c @@ -40,7 +40,8 @@ static int dm_test_led_default_state(struct unit_test_state *uts) ut_assertok(led_get_by_label("sandbox:default_on", &dev)); ut_asserteq(LEDST_ON, led_get_state(dev)); - ut_assertok(led_get_by_label("sandbox:default_off", &dev)); + /* Also tests default label behaviour */ + ut_assertok(led_get_by_label("default_off", &dev)); ut_asserteq(LEDST_OFF, led_get_state(dev)); return 0; diff --git a/test/dm/pinmux.c b/test/dm/pinmux.c new file mode 100644 index 0000000000..047184d4bc --- /dev/null +++ b/test/dm/pinmux.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/test.h> +#include <test/ut.h> + +static int dm_test_pinmux(struct unit_test_state *uts) +{ + char buf[64]; + struct udevice *dev; + +#define test_muxing(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "pinctrl", &dev)); + test_muxing(0, "UART TX."); + test_muxing(1, "UART RX."); + test_muxing(2, "I2S SCK."); + test_muxing(3, "I2S SD."); + test_muxing(4, "I2S WS."); + test_muxing(5, "GPIO0 bias-pull-up input-disable."); + test_muxing(6, "GPIO1 drive-open-drain."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "alternate")); + test_muxing(0, "I2C SCL drive-open-drain."); + test_muxing(1, "I2C SDA drive-open-drain."); + test_muxing(2, "SPI SCLK."); + test_muxing(3, "SPI MOSI."); + test_muxing(4, "SPI MISO."); + test_muxing(5, "SPI CS0."); + test_muxing(6, "SPI CS1."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "0")); + test_muxing(0, "I2C SCL drive-open-drain."); + test_muxing(1, "I2C SDA drive-open-drain."); + test_muxing(2, "I2S SCK."); + test_muxing(3, "I2S SD."); + test_muxing(4, "I2S WS."); + test_muxing(5, "GPIO0 bias-pull-up input-disable."); + test_muxing(6, "GPIO1 drive-open-drain."); + test_muxing(7, "GPIO2 bias-pull-down input-enable."); + test_muxing(8, "GPIO3 bias-disable."); + + return 0; +} +DM_TEST(dm_test_pinmux, UT_TESTF_SCAN_FDT); diff --git a/test/py/tests/test_pinmux.py b/test/py/tests/test_pinmux.py index 4e6df992a4..0cbbae000c 100644 --- a/test/py/tests/test_pinmux.py +++ b/test/py/tests/test_pinmux.py @@ -28,15 +28,15 @@ def test_pinmux_status_all(u_boot_console): assert ('a6 : gpio output .' in output) assert ('pinctrl:' in output) - assert ('SCL : I2C SCL.' in output) - assert ('SDA : I2C SDA.' in output) - assert ('TX : Uart TX.' in output) - assert ('RX : Uart RX.' in output) - assert ('W1 : 1-wire gpio.' in output) - assert ('GPIO0 : gpio bias-pull-up input-disable.' in output) - assert ('GPIO1 : gpio drive-open-drain.' in output) - assert ('GPIO2 : gpio bias-pull-down input-enable.' in output) - assert ('GPIO3 : gpio bias-disable.' in output) + assert ('P0 : UART TX.' in output) + assert ('P1 : UART RX.' in output) + assert ('P2 : I2S SCK.' in output) + assert ('P3 : I2S SD.' in output) + assert ('P4 : I2S WS.' in output) + assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) + assert ('P6 : GPIO1 drive-open-drain.' in output) + assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) + assert ('P8 : GPIO3 bias-disable.' in output) @pytest.mark.buildconfigspec('cmd_pinmux') @pytest.mark.boardspec('sandbox') @@ -73,12 +73,12 @@ def test_pinmux_status(u_boot_console): assert (not 'pinctrl-gpio:' in output) assert (not 'pinctrl:' in output) - assert ('SCL : I2C SCL.' in output) - assert ('SDA : I2C SDA.' in output) - assert ('TX : Uart TX.' in output) - assert ('RX : Uart RX.' in output) - assert ('W1 : 1-wire gpio.' in output) - assert ('GPIO0 : gpio bias-pull-up input-disable.' in output) - assert ('GPIO1 : gpio drive-open-drain.' in output) - assert ('GPIO2 : gpio bias-pull-down input-enable.' in output) - assert ('GPIO3 : gpio bias-disable.' in output) + assert ('P0 : UART TX.' in output) + assert ('P1 : UART RX.' in output) + assert ('P2 : I2S SCK.' in output) + assert ('P3 : I2S SD.' in output) + assert ('P4 : I2S WS.' in output) + assert ('P5 : GPIO0 bias-pull-up input-disable.' in output) + assert ('P6 : GPIO1 drive-open-drain.' in output) + assert ('P7 : GPIO2 bias-pull-down input-enable.' in output) + assert ('P8 : GPIO3 bias-disable.' in output) |