diff --git a/Documentation/devicetree/bindings/pinctrl/hisilicon,hi3798mv200-ioconfig.yaml b/Documentation/devicetree/bindings/pinctrl/hisilicon,hi3798mv200-ioconfig.yaml new file mode 100644 index 00000000000000..d3d16fa9677af7 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/hisilicon,hi3798mv200-ioconfig.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/hisilicon,hi3798mv200-ioconfig.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HiSilicon Hi3798MV200 SoC IOCONFIG module + +maintainers: + - Yang Xiwen + +description: Hi3798MV200 IOCONFIG pinmux&pinconf controller + +properties: + compatible: + const: hisilicon,hi3798mv200-ioconfig + + reg: + maxItems: 1 + + "#pinctrl-cells": + const: 1 + +patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/hi3798mv200-iocfg-pin-state" + - patternProperties: + "-pins?$": + $ref: "#/$defs/hi3798mv200-iocfg-pin-state" + unevaluatedProperties: false + +$defs: + hi3798mv200-iocfg-pin-state: + $ref: hisilicon,histb-pinctrl-common.yaml#/$defs/histb-pin-state + unevaluatedProperties: false + + properties: + pins: + items: + enum: [ Y19, W19, AA20, Y20, V19, Y21, W20, W21, V20, V21, U20, U21, + T18, T19, T20, R20, R21, P20, R19, K18, J17, J18, H17, H18, K20, + K19, J20, J19, H21, H20, H19, G20, G19, F21, F20, F19, E20, E19, + D21, E18, C20, D19, B21, B18, C17, B17, A17, C16, B16, B4, C4, A3, + B3, A2, B2, A6, C6, C5, C3, D4, D3, B1, C2, C1, A5, D5 ] + + function: + enum: [ gpio, bootsel, clkout, emmc, fe_led, hdmitx, i2c_scl, i2c_sda, + i2s_clk, i2s_data, i2s_ws, jtag, nand, pmc, rgmii, rmii, sata, sdio, + sim, spdif, spi, spi_flash, tsi0_d0, tsi0_d1, tsi0_data, tsi1_data, + tsi2_data, tsi3_data, tso, tsi_clk, tsi_sync, tsi_valid, uart ] + +allOf: + - $ref: hisilicon,histb-pinctrl-common.yaml# + +required: + - compatible + - reg + +unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/pinctrl/hisilicon,histb-pinctrl-common.yaml b/Documentation/devicetree/bindings/pinctrl/hisilicon,histb-pinctrl-common.yaml new file mode 100644 index 00000000000000..1cdc1669f9ac24 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/hisilicon,histb-pinctrl-common.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/hisilicon,histb-pinctrl-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HiSilicon HiSTB SoCs Pinctrl Controller + +maintainers: + - Yang Xiwen + +description: | + Pinctrl for HiSilicon HiSTB SoCs are commonly separated into two parts. Most + pins are controlled via IOCONFIG register space, the rest are controlled + within sysctrl core. + + Both support per-pin pinmux and pinconf settings. Though the register fields + and offsets may differ. + +allOf: + - $ref: pinctrl.yaml# + +addtionalProperties: true + +$defs: + histb-pin-state: + properties: + pins: + items: + pattern: "^[A-Z]+[0-9]+$" + + drive-strength: + minimum: 1 + maximum: 16 + + slew-rate: + enum: [0, 1] + + bias-pull-down: true + bias-pull-up: true + bias-disable: true + input-schmitt-enable: true + + function: true + + required: + - pins + - function + + allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + + unevaluatedProperties: false +... diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 8163a5983166a8..5b02d4f49a7915 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -542,6 +542,7 @@ source "drivers/pinctrl/bcm/Kconfig" source "drivers/pinctrl/berlin/Kconfig" source "drivers/pinctrl/cirrus/Kconfig" source "drivers/pinctrl/freescale/Kconfig" +source "drivers/pinctrl/hisilicon/Kconfig" source "drivers/pinctrl/intel/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/meson/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 1071f301cc70b6..8f7c4f651ce7cb 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -59,6 +59,7 @@ obj-y += bcm/ obj-$(CONFIG_PINCTRL_BERLIN) += berlin/ obj-y += cirrus/ obj-y += freescale/ +obj-$(CONFIG_PINCTRL_HISILICON) += hisilicon/ obj-$(CONFIG_X86) += intel/ obj-y += mediatek/ obj-$(CONFIG_PINCTRL_MESON) += meson/ diff --git a/drivers/pinctrl/hisilicon/Kconfig b/drivers/pinctrl/hisilicon/Kconfig new file mode 100644 index 00000000000000..d4ff99ea5716a1 --- /dev/null +++ b/drivers/pinctrl/hisilicon/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +if (ARCH_HISI || COMPILE_TEST) + +config PINCTRL_HISILICON + bool + +config PINCTRL_HISTB + tristate "HiSilicon HiSTB SoCs pinctrl framework" + select PINCTRL_HISILICON + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + + help + Support HiSTB SoCs pinctrl module + +menu "HiSTB pinctrl drivers" + depends on PINCTRL_HISTB + +config PINCTRL_HI3798MV2X + tristate "HiSilicon Hi3798MV2X pinctrl driver" + depends on PINCTRL_HISTB + help + Support IOCONFIG core on Hi3798MV2X SoCs + +endmenu + +endif diff --git a/drivers/pinctrl/hisilicon/Makefile b/drivers/pinctrl/hisilicon/Makefile new file mode 100644 index 00000000000000..5afb64d4b6540c --- /dev/null +++ b/drivers/pinctrl/hisilicon/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright 2024 (r) Yang Xiwen + +obj-$(CONFIG_PINCTRL_HISTB) += pinctrl-histb.o +obj-$(CONFIG_PINCTRL_HI3798MV2X) += pinctrl-hi3798mv2x.o diff --git a/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c b/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c new file mode 100644 index 00000000000000..10141a902952bd --- /dev/null +++ b/drivers/pinctrl/hisilicon/pinctrl-hi3798mv2x.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * IOCONFIG driver for Hi3798MV2x SoCs + * + * Copyright 2024 (r) Yang Xiwen + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../core.h" +#include "../pinconf.h" +#include "../pinmux.h" + +#include "pinctrl-histb.h" + +// The sequence is important! +enum hi3798mv2x_ioconfig_pins { + INVALID = -1, + Y19, + W19, + AA20, + Y20, + V19, + Y21, + W20, + W21, + V20, + V21, + U20, + U21, + T18, + T19, + T20, + R20, + R21, + P20, + R19, + K18, + J17, + J18, + H17, + H18, + K20, + K19, + J20, + J19, + H21, + H20, + H19, + G20, + G19, + F21, + F20, + F19, + E20, + E19, + D21, + E18, + C20, + D19, + B21, + B18, + C17, + B17, + A17, + C16, + B16, + B4, + C4, + A3, + B3, + A2, + B2, + A6, + C6, + C5, + C3, + D4, + D3, + B1, + C2, + C1, + A5, + D5, +}; + +enum hi3798mv2x_pin_funcs { + HI3798MV2X_INVALID = -1, + HI3798MV2X_GPIO = HISTB_PIN_FUNCTION_GPIO, + HI3798MV2X_BOOT_SEL, + HI3798MV2X_CLKOUT_25M, + HI3798MV2X_EMMC, + /* Fast Ethernet PHY LED */ + HI3798MV2X_FE_LED, + HI3798MV2X_HDMITX, + HI3798MV2X_I2C_SCL, + HI3798MV2X_I2C_SDA, + HI3798MV2X_I2S_CLK, + HI3798MV2X_I2S_DATA, + HI3798MV2X_I2S_WS, + HI3798MV2X_JTAG, + HI3798MV2X_NAND, + HI3798MV2X_PMC, + HI3798MV2X_RGMII, + HI3798MV2X_RMII, + HI3798MV2X_SATA, + HI3798MV2X_SDIO, + HI3798MV2X_SIM, + HI3798MV2X_SPDIF, + HI3798MV2X_SPI, + HI3798MV2X_SPI_FLASH, + /* + * workaround for pin E19 + * + * This pin can be either D0 or D1, + * so the common property is not adequate to select a function + */ + HI3798MV2X_TSI0_D0, + HI3798MV2X_TSI0_D1, + HI3798MV2X_TSI0_DATA, + HI3798MV2X_TSI1_DATA, + HI3798MV2X_TSI2_DATA, + HI3798MV2X_TSI3_DATA, + HI3798MV2X_TSO, + HI3798MV2X_TSI_CLK, + HI3798MV2X_TSI_SYNC, + HI3798MV2X_TSI_VALID, + HI3798MV2X_UART, + HI3798MV2X_FUNCTION_COUNT, +}; + +static const char *const hi3798mv2x_pinctrl_function_names[] = { + [HI3798MV2X_GPIO] = "gpio", + [HI3798MV2X_BOOT_SEL] = "bootsel", + [HI3798MV2X_CLKOUT_25M] = "clkout", + [HI3798MV2X_EMMC] = "emmc", + /* Fast Ethernet PHY LED */ + [HI3798MV2X_FE_LED] = "fe_led", + [HI3798MV2X_HDMITX] = "hdmitx", + [HI3798MV2X_I2C_SCL] = "i2c_scl", + [HI3798MV2X_I2C_SDA] = "i2c_sda", + [HI3798MV2X_I2S_CLK] = "i2s_clk", + [HI3798MV2X_I2S_DATA] = "i2s_data", + [HI3798MV2X_I2S_WS] = "i2s_ws", + [HI3798MV2X_JTAG] = "jtag", + [HI3798MV2X_NAND] = "nand", + [HI3798MV2X_PMC] = "pmc", + [HI3798MV2X_RGMII] = "rgmii", + [HI3798MV2X_RMII] = "rmii", + [HI3798MV2X_SATA] = "sata", + [HI3798MV2X_SDIO] = "sdio", + [HI3798MV2X_SIM] = "sim", + [HI3798MV2X_SPDIF] = "spdif", + [HI3798MV2X_SPI] = "spi", + [HI3798MV2X_SPI_FLASH] = "spi_flash", + /* + * workaround for pin E19 + * + * This pin can be either D0 or D1, + * so the common property is not adequate to select a function + */ + [HI3798MV2X_TSI0_D0] = "tsi0_d0", + [HI3798MV2X_TSI0_D1] = "tsi0_d1", + /* DOCSIS */ + [HI3798MV2X_TSI0_DATA] = "tsi0_data", + [HI3798MV2X_TSI1_DATA] = "tsi1_data", + [HI3798MV2X_TSI2_DATA] = "tsi2_data", + [HI3798MV2X_TSI3_DATA] = "tsi3_data", + [HI3798MV2X_TSO] = "tso", + [HI3798MV2X_TSI_CLK] = "tsi_clk", + [HI3798MV2X_TSI_SYNC] = "tsi_sync", + [HI3798MV2X_TSI_VALID] = "tsi_valid", + [HI3798MV2X_UART] = "uart", +}; + +/* FIXME: use struct pinfunction instead */ +static const struct { + const char *const *pins; + unsigned int cnt; +} hi3798mv2x_ioconfig_function_tbl[] = { + // all pins can be set to GPIO + [HI3798MV2X_GPIO] = { NULL, 0 }, + [HI3798MV2X_BOOT_SEL] = { (const char *[]){ "AA20", "C3", "B1", }, 3 }, + [HI3798MV2X_CLKOUT_25M] = { (const char *[]){ "A5", }, 1 }, + [HI3798MV2X_EMMC] = { (const char *[]){ "V19", "Y21", "W20", "W21", "V20", "V21", "U20", "U21", "T18", "T20", "R20", "R21", }, 12 }, + [HI3798MV2X_FE_LED] = { (const char *[]){ "A6", "C6", }, 2 }, + [HI3798MV2X_HDMITX] = { (const char *[]){ "B17", "A17", "C16", "B16", }, 4 }, + [HI3798MV2X_I2C_SCL] = { (const char *[]){ "R19", "K20", "F19", "E19", "C20", "D19", }, 6 }, + [HI3798MV2X_I2C_SDA] = { (const char *[]){ "P20", "H18", "E20", "D19", "B21", }, 5 }, + [HI3798MV2X_I2S_CLK] = { (const char *[]){ "J20", "H21", "H20", "G19", "F21", "F20", "F19", "E19", "D21", "D19", }, 10 }, + [HI3798MV2X_I2S_DATA] = { (const char *[]){ "H21", "H20", "H19", "G20", "F21", "C20", "B21", }, 7 }, + [HI3798MV2X_I2S_WS] = { (const char *[]){ "J19", "H19", "G19", "E20", "E18", }, 5 }, + [HI3798MV2X_JTAG] = { (const char *[]){ "K20", "K19", "J20", "J19", "H21", "B18", }, 6 }, + [HI3798MV2X_NAND] = { (const char *[]){ "Y19", "W19", "AA20", "Y20", "V19", "Y21", "W20", "W21", "V20", "V21", "U20", "U21", "T18", "T19", "T20", "R20", "R21", }, 17 }, + [HI3798MV2X_PMC] = { (const char *[]){ "P20", "R19", "D5", }, 3 }, + [HI3798MV2X_RGMII] = { (const char *[]){ "B4", "C4", "A3", "B3", "A2", "B2", "A6", "C6", "C5", "C3", "D4", "D3", "B1", "C2", "C1", "A5", "D5", }, 17 }, + [HI3798MV2X_RMII] = { (const char *[]){ "B4", "C4", "A3", "B3", "A2", "B2", "C5", "B1", "C2", "C1", }, 10 }, + [HI3798MV2X_SATA] = { (const char *[]){ "K18", "J17", }, 2 }, + [HI3798MV2X_SDIO] = { (const char *[]){ "F20", "F19", "E20", "E19", "D21", "E18", "C20", "D19", "B21", "B4", "C4", "A3", "B3", "A2", "B2", "C5", "C2", "C1", }, 18 }, + [HI3798MV2X_SIM] = { (const char *[]){ "K18", "J17", "J18", "H17", "H18", "K20", "K19", "J20", "J19", "H21", }, 10 }, + [HI3798MV2X_SPDIF] = { (const char *[]){ "C17", }, 1 }, + [HI3798MV2X_SPI] = { (const char *[]){ "K20", "K19", "J20", "J19", }, 4 }, + [HI3798MV2X_SPI_FLASH] = { (const char *[]){ "H20", "H19", "G20", "G19", "F21", "F20", }, 6 }, + [HI3798MV2X_TSI0_D0] = { (const char *[]){ "E19", }, 1 }, + [HI3798MV2X_TSI0_D1] = { (const char *[]){ "E19", }, 1 }, + [HI3798MV2X_TSI0_DATA] = { (const char *[]){ "K18", "J17", "J18", "H17", "H18", "F19", "E20", "D21", "D19", }, 9 }, + [HI3798MV2X_TSI1_DATA] = { (const char *[]){ "J17", "J18", "H19", "G20", "E18", }, 5 }, + [HI3798MV2X_TSI2_DATA] = { (const char *[]){ "H18", }, 1 }, + [HI3798MV2X_TSI3_DATA] = { (const char *[]){ "J18", }, 1 }, + [HI3798MV2X_TSO] = { (const char *[]){ "H20", "H19", "G20", "G19", }, 4 }, + [HI3798MV2X_TSI_CLK] = { (const char *[]){ "K18", "H17", "G19", "F19", "D21", "E18", "C20", "B21", }, 8 }, + [HI3798MV2X_TSI_SYNC] = { (const char *[]){ "J17", "H19", "E19", }, 3 }, + [HI3798MV2X_TSI_VALID] = { (const char *[]){ "J17", "H17", "H18", "F21", "D21", "E18", "C20", }, 7 }, + [HI3798MV2X_UART] = { (const char *[]){ "K18", "J17", "J18", "H17", "K19", "J20", "J19", "H21", "A6", "C6", "D4", "D3", }, 12 }, +}; + +/* Frequentely used drive strength table */ +#define DRIVE_STRENGTH_TABLE_SAMPLE_A ((const u8[]){ 4, 3, 2, 1, 0 }) +#define DRIVE_STRENGTH_TABLE_SAMPLE_B ((const u8[]){ 18, 17, 16, 15, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 0 }) + +static const struct pinctrl_pin_desc hi3798mv2x_ioconfig_pins[] = { + HISTB_PIN(Y19, "Y19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_NAND, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), + HISTB_PIN_FLAG_NOPD), + HISTB_PIN(W19, "W19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_NAND, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), + HISTB_PIN_FLAG_NOPD), + HISTB_PIN(AA20, "AA20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_BOOT_SEL, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(Y20, "Y20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_NAND, 0x1 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(V19, "V19", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(Y21, "Y21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(W20, "W20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(W21, "W21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(V20, "V20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(V21, "V21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(U20, "U20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(U21, "U21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(T18, "T18", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(T19, "T19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]) { { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_NAND, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(T20, "T20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(R20, "R20", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(R21, "R21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_GPIO, 0x0 }, { HI3798MV2X_NAND, 0x1 }, + { HI3798MV2X_EMMC, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(P20, "P20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_PMC, 0x0 }, { HI3798MV2X_I2C_SDA, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(R19, "R19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]) + { { HI3798MV2X_PMC, 0x0 }, { HI3798MV2X_I2C_SCL, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(K18, "K18", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]) { { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SATA, 0x1 }, { HI3798MV2X_UART, 0x2 }, + { HI3798MV2X_TSI0_DATA, 0x3 }, { HI3798MV2X_TSI_CLK, 0x4 }, + { HI3798MV2X_SIM, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(J17, "J17", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]) { { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SATA, 0x1 }, { HI3798MV2X_UART, 0x2 }, + { HI3798MV2X_TSI_SYNC, 0x3 }, { HI3798MV2X_TSI1_DATA, 0x4 }, + { HI3798MV2X_TSI0_DATA, 0x5 }, { HI3798MV2X_TSI_VALID, 0x6 }, + { HI3798MV2X_SIM, 0x7 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(J18, "J18", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_UART, 0x1 }, { HI3798MV2X_TSI1_DATA, 0x2 }, + { HI3798MV2X_TSI0_DATA, 0x3 }, { HI3798MV2X_TSI3_DATA, 0x4 }, + { HI3798MV2X_SIM, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(H17, "H17", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_UART, 0x1 }, { HI3798MV2X_TSI_CLK, 0x2 }, + { HI3798MV2X_TSI0_DATA, 0x3 }, { HI3798MV2X_TSI_VALID, 0x4 }, + { HI3798MV2X_SIM, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(H18, "H18", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2C_SDA, 0x1 }, { HI3798MV2X_TSI_VALID, 0x2 }, + { HI3798MV2X_TSI0_DATA, 0x3 }, { HI3798MV2X_TSI2_DATA, 0x4 }, + { HI3798MV2X_SIM, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(K20, "K20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_I2C_SCL, 0x1 }, { HI3798MV2X_SPI, 0x2 }, { HI3798MV2X_SIM, 0x3 }, + { HI3798MV2X_GPIO, 0x4 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(K19, "K19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_SPI, 0x1 }, { HI3798MV2X_SIM, 0x2 }, { HI3798MV2X_GPIO, 0x3 }, + { HI3798MV2X_UART, 0x4 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(J20, "J20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_I2S_CLK, 0x1 }, { HI3798MV2X_SPI, 0x2 }, + { HI3798MV2X_SIM, 0x3 }, { HI3798MV2X_GPIO, 0x4 }, + { HI3798MV2X_UART, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(J19, "J19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_I2S_WS, 0x1 }, { HI3798MV2X_SPI, 0x2 }, + { HI3798MV2X_SIM, 0x3 }, { HI3798MV2X_GPIO, 0x4 }, + { HI3798MV2X_UART, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(H21, "H21", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_I2S_CLK, 0x1 }, { HI3798MV2X_I2S_DATA, 0x2 }, + { HI3798MV2X_SIM, 0x3 }, { HI3798MV2X_GPIO, 0x4 }, + { HI3798MV2X_UART, 0x5 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(H20, "H20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2S_CLK, 0x1 }, { HI3798MV2X_I2S_DATA, 0x2 }, + { HI3798MV2X_SPI_FLASH, 0x3 }, { HI3798MV2X_TSO, 0x4 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_NOPD), + HISTB_PIN(H19, "H19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2S_WS, 0x1 }, { HI3798MV2X_I2S_DATA, 0x2 }, + { HI3798MV2X_TSI_SYNC, 0x3 }, { HI3798MV2X_TSI1_DATA, 0x4 }, + { HI3798MV2X_SPI_FLASH, 0x5 }, { HI3798MV2X_TSO, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(G20, "G20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2S_DATA, 0x1 }, { HI3798MV2X_TSI1_DATA, 0x3 }, + { HI3798MV2X_SPI_FLASH, 0x5 }, { HI3798MV2X_TSO, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_NOPD), + HISTB_PIN(G19, "G19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2S_CLK, 0x1 }, { HI3798MV2X_I2S_WS, 0x2 }, + { HI3798MV2X_TSI_CLK, 0x3 }, { HI3798MV2X_SPI_FLASH, 0x5 }, + { HI3798MV2X_TSO, 0x6 }, { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_NOPD), + HISTB_PIN(F21, "F21", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_I2S_DATA, 0x1 }, { HI3798MV2X_I2S_CLK, 0x2 }, + { HI3798MV2X_TSI_VALID, 0x3 }, { HI3798MV2X_SPI_FLASH, 0x5 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(F20, "F20", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_I2S_CLK, 0x2 }, + { HI3798MV2X_SPI_FLASH, 0x4 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(F19, "F19", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_I2C_SCL, 0x3 }, + { HI3798MV2X_I2S_CLK, 0x4 }, { HI3798MV2X_TSI0_DATA, 0x5 }, + { HI3798MV2X_TSI_CLK, 0x6 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(E20, "E20", ((const u8[]){ 18, 16, 14, 12, 5, 4, 2, 1, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_I2S_WS, 0x4 }, + { HI3798MV2X_TSI0_DATA, 0x5 }, { HI3798MV2X_I2C_SDA, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(E19, "E19", ((const u8[]){ 18, 16, 14, 12, 5, 4, 2, 1, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_TSI0_D1, 0x2 }, + { HI3798MV2X_TSI_SYNC, 0x3 }, { HI3798MV2X_I2S_CLK, 0x4 }, + { HI3798MV2X_TSI0_D0, 0x5 }, { HI3798MV2X_I2C_SCL, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(D21, "D21", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_TSI0_DATA, 0x3 }, + { HI3798MV2X_I2S_CLK, 0x4 }, { HI3798MV2X_TSI_CLK, 0x5 }, + { HI3798MV2X_TSI_VALID, 0x6 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(E18, "E18", ((const u8[]){ 18, 16, 14, 12, 5, 4, 2, 1, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_TSI_CLK, 0x3 }, + { HI3798MV2X_I2S_WS, 0x4 }, { HI3798MV2X_TSI_VALID, 0x5 }, + { HI3798MV2X_TSI1_DATA, 0x6 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C20, "C20", ((const u8[]){ 18, 16, 14, 12, 5, 4, 2, 1, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_TSI_CLK, 0x2 }, + { HI3798MV2X_TSI_VALID, 0x3 }, { HI3798MV2X_I2S_DATA, 0x4 }, + { HI3798MV2X_I2C_SCL, 0x5 }, { HI3798MV2X_TSI_VALID, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(D19, "D19", ((const u8[]){ 18, 16, 14, 12, 5, 4, 2, 1, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_I2C_SCL, 0x3 }, + { HI3798MV2X_I2S_CLK, 0x4 }, { HI3798MV2X_I2C_SDA, 0x5 }, + { HI3798MV2X_TSI0_DATA, 0x6 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(B21, "B21", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SDIO, 0x1 }, { HI3798MV2X_I2C_SDA, 0x3 }, + { HI3798MV2X_I2S_DATA, 0x4 }, { HI3798MV2X_TSI_CLK, 0x6 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(B18, "B18", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_JTAG, 0x0 }, + { HI3798MV2X_GPIO, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C17, "C17", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_SPDIF, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(B17, "B17", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_HDMITX, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(A17, "A17", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_HDMITX, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C16, "C16", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_HDMITX, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(B16, "B16", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_HDMITX, 0x1 }, + { HI3798MV2X_GPIO, 0x2 }, { HISTB_PIN_FUNCTION_EOF } }), + HISTB_PIN_FLAG_NOPU | HISTB_PIN_FLAG_NOPD | HISTB_PIN_FLAG_NOSR), + HISTB_PIN(B4, "B4", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, + { HI3798MV2X_SDIO, 0x3 }, { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(C4, "C4", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(A3, "A3", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(B3, "B3", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(A2, "A2", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(B2, "B2", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(A6, "A6", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_UART, 0x2 }, { HI3798MV2X_FE_LED, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C6, "C6", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_UART, 0x2 }, { HI3798MV2X_FE_LED, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C5, "C5", DRIVE_STRENGTH_TABLE_SAMPLE_A, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, + { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(C3, "C3", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_BOOT_SEL, 0x2 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(D4, "D4", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_UART, 0x2 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(D3, "D3", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_UART, 0x2 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(B1, "B1", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + { HI3798MV2X_RGMII, 0x1 }, { HI3798MV2X_RMII, 0x2 }, + { HI3798MV2X_BOOT_SEL, 0x3 }, { HISTB_PIN_FUNCTION_EOF } }), + HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(C2, "C2", ((const u8[]){ 18, 16, 14, 12, 10, 8, 6, 4, 0 }), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_RGMII, 0x1 }, + { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, { HI3798MV2X_GPIO, 0x4 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(C1, "C1", DRIVE_STRENGTH_TABLE_SAMPLE_B, + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_RGMII, 0x1 }, + { HI3798MV2X_RMII, 0x2 }, { HI3798MV2X_SDIO, 0x3 }, { HI3798MV2X_GPIO, 0x4 }, + { HISTB_PIN_FUNCTION_EOF } }), HISTB_PIN_FLAG_SCHMITT), + HISTB_PIN(A5, "A5", ((const u8 *)NULL), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_GPIO, 0x0 }, + {HI3798MV2X_CLKOUT_25M, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), 0), + HISTB_PIN(D5, "D5", ((const u8 *)NULL), + ((const struct histb_pin_mux_desc[]){ { HI3798MV2X_PMC, 0x0 }, + { HI3798MV2X_GPIO, 0x1 }, { HISTB_PIN_FUNCTION_EOF } }), + HISTB_PIN_FLAG_NOPU | HISTB_PIN_FLAG_NOPD | HISTB_PIN_FLAG_NOSR), +}; + +static int hi3798mv2x_ioconfig_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct pinctrl_desc *pctldesc; + struct pinctrl_dev *pctl_dev; + struct device *dev = &pdev->dev; + int i, ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + pctldesc = devm_kzalloc(dev, sizeof(*pctldesc), GFP_KERNEL); + if (!pctldesc) + return -ENOMEM; + + pctldesc->name = "hi3798mv2x-ioconfig"; + pctldesc->owner = THIS_MODULE; + pctldesc->pctlops = &histb_pinctrl_pctl_ops; + pctldesc->pmxops = &histb_pinctrl_pinmux_ops; + pctldesc->confops = &histb_pinctrl_pinconf_ops; + pctldesc->pins = hi3798mv2x_ioconfig_pins; + pctldesc->npins = ARRAY_SIZE(hi3798mv2x_ioconfig_pins); + + ret = devm_pinctrl_register_and_init(dev, pctldesc, base, &pctl_dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to register pinctrl device\n"); + + for (i = 0; i < pctldesc->npins; i++) { + ret = pinctrl_generic_add_group(pctl_dev, pctldesc->pins[i].name, + &pctldesc->pins[i].number, 1, NULL); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to register groups\n"); + } + + for (i = 0; i < HI3798MV2X_FUNCTION_COUNT; i++) { + ret = pinmux_generic_add_function(pctl_dev, hi3798mv2x_pinctrl_function_names[i], + hi3798mv2x_ioconfig_function_tbl[i].pins, + hi3798mv2x_ioconfig_function_tbl[i].cnt, NULL); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to register functions\n"); + } + + return pinctrl_enable(pctl_dev); +} + +static const struct of_device_id hi3798mv2x_pinctrl_match[] = { + { .compatible = "hisilicon,hi3798mv200-ioconfig", }, + { }, +}; +MODULE_DEVICE_TABLE(of, hi3798mv2x_pinctrl_match); + +static struct platform_driver hi3798mv2x_pinctrl_driver = { + .probe = hi3798mv2x_ioconfig_probe, + .driver = { + .name = "hi3798mv2x-ioconfig", + .of_match_table = hi3798mv2x_pinctrl_match, + }, +}; + +module_platform_driver(hi3798mv2x_pinctrl_driver); + +MODULE_AUTHOR("Yang Xiwen "); +MODULE_DESCRIPTION("IOCONFIG pinctrl driver for Hi3798MV2x SoC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/hisilicon/pinctrl-histb.c b/drivers/pinctrl/hisilicon/pinctrl-histb.c new file mode 100644 index 00000000000000..8fc180d79e0501 --- /dev/null +++ b/drivers/pinctrl/hisilicon/pinctrl-histb.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * IOCONFIG pinctrl driver for HiSTB SoCs + * + * Copyright 2024 (r) Yang Xiwen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../core.h" +#include "../pinconf.h" +#include "../pinmux.h" + +#include "pinctrl-histb.h" + +static int histb_pinctrl_pinmux_set(struct pinctrl_dev *pctldev, unsigned int func_selector, + unsigned int group_selector) +{ + const struct pin_desc *pin = pin_desc_get(pctldev, group_selector); + const struct histb_pin_data *data = pin->drv_data; + const struct histb_pin_mux_desc *mux = data->func_tbl; + u32 reg; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + group_selector; + bool found = false; + + while (mux->func != HISTB_PIN_FUNCTION_EOF) { + if (mux->func == func_selector) { + reg = readl(pin_reg); + reg &= ~HISTB_PIN_FUNC_MASK; + reg |= mux->bits; + writel(reg, pin_reg); + + found = true; + break; + } + mux++; + } + + if (!found) { + dev_err(pctldev->dev, "Unable to set pin %s to the given function %s\n", + pin_get_name(pctldev, group_selector), + pinmux_generic_get_function_name(pctldev, func_selector)); + return -ENOENT; + } + + return 0; +} + +static int histb_pinctrl_gpio_request(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + return histb_pinctrl_pinmux_set(pctldev, HISTB_PIN_FUNCTION_GPIO, pin); +} + +enum histb_pinctrl_bias_status { + BIAS_DISABLE = 0, + BIAS_PULL_DOWN = BIT(0), + BIAS_PULL_UP = BIT(1), + // if both pull up and pull down are detected + BIAS_INVALID = BIT(0) | BIT(1), +}; + +static int histb_pinctrl_set_bias(struct pinctrl_dev *pctldev, unsigned int selector, + enum histb_pinctrl_bias_status status) +{ + struct histb_pin_data *priv = pin_desc_get(pctldev, selector)->drv_data; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + u32 reg; + bool not_supported; + + switch (status) { + case BIAS_DISABLE: + not_supported = false; + break; + case BIAS_PULL_DOWN: + not_supported = priv->flags & HISTB_PIN_FLAG_NOPD; + break; + case BIAS_PULL_UP: + not_supported = priv->flags & HISTB_PIN_FLAG_NOPU; + break; + case BIAS_INVALID: + not_supported = true; + break; + } + + if (not_supported) + return -ENOTSUPP; + + reg = readl(pin_reg); + reg &= ~(HISTB_PIN_PULLDOWN | HISTB_PIN_PULLUP); + + switch (status) { + case BIAS_DISABLE: + break; + case BIAS_PULL_DOWN: + reg |= HISTB_PIN_PULLDOWN; + break; + case BIAS_PULL_UP: + reg |= HISTB_PIN_PULLUP; + break; + case BIAS_INVALID: + // Can't reach here. + break; + } + + writel(reg, pin_reg); + + return 0; +} + +static enum histb_pinctrl_bias_status +histb_pinctrl_get_bias_status(struct pinctrl_dev *pctldev, unsigned int selector) +{ + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + u32 reg = readl(pin_reg); + enum histb_pinctrl_bias_status ret = BIAS_DISABLE; + + if (reg & HISTB_PIN_PULLDOWN) + ret = BIAS_PULL_DOWN; + + if (reg & HISTB_PIN_PULLUP) + ret |= BIAS_PULL_UP; + + return ret; +} + +static int histb_pinctrl_set_slew_rate(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned long argument) +{ + struct histb_pin_data *priv = pin_desc_get(pctldev, selector)->drv_data; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + u32 reg; + + if (priv->flags & HISTB_PIN_FLAG_NOSR || argument > 1) + return -ENOTSUPP; + + reg = readl(pin_reg); + if (argument) + reg |= HISTB_PIN_SLEWRATE; + else + reg &= ~HISTB_PIN_SLEWRATE; + + writel(reg, pin_reg); + + return 0; +} + +static bool histb_pinctrl_get_slew_rate(struct pinctrl_dev *pctldev, unsigned int selector) +{ + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + + return readl(pin_reg) & HISTB_PIN_SLEWRATE; +} + +static int histb_pinctrl_endisable_schmitt(struct pinctrl_dev *pctldev, unsigned int selector, + bool enable) +{ + struct histb_pin_data *priv = pin_desc_get(pctldev, selector)->drv_data; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + u32 reg; + + if (priv->flags & HISTB_PIN_FLAG_SCHMITT) + return -ENOTSUPP; + + reg = readl(pin_reg); + if (enable) + reg |= HISTB_PIN_SCHMITT; + else + reg &= ~HISTB_PIN_SCHMITT; + + writel(reg, pin_reg); + + return 0; +} + +static bool histb_pinctrl_get_schmitt(struct pinctrl_dev *pctldev, unsigned int selector) +{ + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + + return readl(pin_reg) & HISTB_PIN_SCHMITT; +} + +static int histb_pinctrl_set_drive_strength(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int argument) +{ + struct histb_pin_data *priv = pin_desc_get(pctldev, selector)->drv_data; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + int i = -1; + u32 reg; + + if (unlikely(argument == 0 || !priv->drv_tbl)) + return -ENOTSUPP; + + // calculate the largest drive-strength that does not exceeds the given value + // if the lowest value is still too large, use that anyway + // TODO: use bsearch()? + while (priv->drv_tbl[++i] > argument) + ; + + if (!priv->drv_tbl[i]) + i--; + + reg = readl(pin_reg); + reg &= ~HISTB_PIN_DRV_MASK; + reg |= FIELD_PREP(HISTB_PIN_DRV_MASK, i); + + writel(reg, pin_reg); + + return 0; +} + +static unsigned int histb_pinctrl_get_drive_strength(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct histb_pin_data *priv = pin_desc_get(pctldev, selector)->drv_data; + void __iomem *pin_reg = (u32 *)pinctrl_dev_get_drvdata(pctldev) + selector; + + if (!priv->drv_tbl) + return 0; + + return priv->drv_tbl[FIELD_GET(HISTB_PIN_DRV_MASK, readl(pin_reg))]; +} + +static int histb_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + enum histb_pinctrl_bias_status bias; + ulong argument; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + bias = histb_pinctrl_get_bias_status(pctldev, pin); + argument = bias == BIAS_DISABLE; + break; + case PIN_CONFIG_BIAS_PULL_UP: + bias = histb_pinctrl_get_bias_status(pctldev, pin); + argument = !!(bias & BIAS_PULL_UP); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + bias = histb_pinctrl_get_bias_status(pctldev, pin); + argument = !!(bias & BIAS_PULL_DOWN); + break; + case PIN_CONFIG_SLEW_RATE: + argument = histb_pinctrl_get_slew_rate(pctldev, pin); + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + argument = histb_pinctrl_get_schmitt(pctldev, pin); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + argument = histb_pinctrl_get_drive_strength(pctldev, pin); + if (argument == 0) + return -ENOTSUPP; + break; + default: + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, argument); + + return 0; +} + +static int histb_pinctrl_pinconf_set_single(struct pinctrl_dev *pctldev, unsigned int pin_selector, + enum pin_config_param param, unsigned int argument) +{ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + return histb_pinctrl_set_bias(pctldev, pin_selector, BIAS_DISABLE); + case PIN_CONFIG_BIAS_PULL_UP: + return histb_pinctrl_set_bias(pctldev, pin_selector, BIAS_PULL_UP); + case PIN_CONFIG_BIAS_PULL_DOWN: + return histb_pinctrl_set_bias(pctldev, pin_selector, BIAS_PULL_DOWN); + case PIN_CONFIG_SLEW_RATE: + return histb_pinctrl_set_slew_rate(pctldev, pin_selector, argument); + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + return histb_pinctrl_endisable_schmitt(pctldev, pin_selector, argument); + case PIN_CONFIG_DRIVE_STRENGTH: + return histb_pinctrl_set_drive_strength(pctldev, pin_selector, argument); + default: + break; + } + + dev_err(pctldev->dev, "can't handle given config %d\n", param); + return -EINVAL; +} + +static int histb_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + int i, ret; + + for (i = 0; i < num_configs; i++) { + ret = histb_pinctrl_pinconf_set_single(pctldev, pin, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret) + return ret; + } + + return 0; +} + +const struct pinctrl_ops histb_pinctrl_pctl_ops = { + .get_groups_count = pinctrl_generic_get_group_count, + .get_group_name = pinctrl_generic_get_group_name, + .get_group_pins = pinctrl_generic_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +const struct pinmux_ops histb_pinctrl_pinmux_ops = { + .get_functions_count = pinmux_generic_get_function_count, + .get_function_name = pinmux_generic_get_function_name, + .get_function_groups = pinmux_generic_get_function_groups, + .set_mux = histb_pinctrl_pinmux_set, + .gpio_request_enable = histb_pinctrl_gpio_request, + .strict = true, +}; + +const struct pinconf_ops histb_pinctrl_pinconf_ops = { + .is_generic = true, + .pin_config_get = histb_pinctrl_pinconf_get, + .pin_config_set = histb_pinctrl_pinconf_set, + .pin_config_config_dbg_show = pinconf_generic_dump_config, +}; diff --git a/drivers/pinctrl/hisilicon/pinctrl-histb.h b/drivers/pinctrl/hisilicon/pinctrl-histb.h new file mode 100644 index 00000000000000..89f8d1248132b5 --- /dev/null +++ b/drivers/pinctrl/hisilicon/pinctrl-histb.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include + +/* per-register bit definition */ +#define HISTB_PIN_SCHMITT BIT(14) +#define HISTB_PIN_PULLDOWN BIT(13) +#define HISTB_PIN_PULLUP BIT(12) +#define HISTB_PIN_SLEWRATE BIT(8) +#define HISTB_PIN_DRV_MASK GENMASK(7, 4) +#define HISTB_PIN_FUNC_MASK GENMASK(2, 0) + +/** + * @histb_pin_desc flags + * + * @HISTB_PIN_FLAG_NOPU: This pin does not support "bias-pullup" + * @HISTB_PIN_FLAG_NOPD: This pin does not support "bias-pulldown" + * @HISTB_PIN_FLAG_NOSR: This pin does not support "slew-rate" + * @HISTB_PIN_FLAG_SCHMITT: This pin supports setting input schmitt + */ +#define HISTB_PIN_FLAG_NOPU BIT(0) +#define HISTB_PIN_FLAG_NOPD BIT(1) +#define HISTB_PIN_FLAG_NOSR BIT(2) +#define HISTB_PIN_FLAG_SCHMITT BIT(3) + +/* Reserve function 0 for GPIO */ +#define HISTB_PIN_FUNCTION_GPIO 0 +#define HISTB_PIN_FUNCTION_EOF 0xFFFFFFFF + +/** + * histb_pin_mux_desc - a descriptor for one function of a pin + * + * @func: the enumeration for the function + * @bits: the bits pattern for this function + */ +struct histb_pin_mux_desc { + u32 func; + u32 bits; +}; + +/** + * histb_pin_data - full info of a pin + * + * @drv_tbl: drive strength table, end with 0 + * @func_tbl: pinmux table, end with { } + * @flags: pin flags, see HISTB_PIN_FLAG_* macros + */ +struct histb_pin_data { + const u8 *drv_tbl; + const struct histb_pin_mux_desc *func_tbl; + u32 flags; +}; + +/** + * HISTB_PIN() - a helper macro for initializing histb pin desc + */ +#define HISTB_PIN(_index, _name, _drv_tbl, _func_tbl, _flag) { \ + .number = _index, \ + .name = _name, \ + .drv_data = &(struct histb_pin_data){ \ + .drv_tbl = _drv_tbl, \ + .func_tbl = _func_tbl, \ + .flags = _flag, \ + } \ +} + +struct pinctrl_ops; +struct pinmux_ops; +struct pinconf_ops; + +extern const struct pinctrl_ops histb_pinctrl_pctl_ops; +extern const struct pinmux_ops histb_pinctrl_pinmux_ops; +extern const struct pinconf_ops histb_pinctrl_pinconf_ops;