From 656e6cc86b96be88f99f6f3ef1df3ef3122a8766 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Thu, 8 Dec 2016 12:22:29 +0200 Subject: [PATCH] arm64: mvebu: pinctrl: Add pin control driver for A8K family Add a DM port of Marvell pin control driver. The A8K SoC family contains several silicone dies interconnected in a single package. Every die is normally equipped with its own pin controller unit. There are 2 pin controllers in A70x0 SoC and 3 in A80x0 SoC. Signed-off-by: Konstantin Porotchkin Reviewed-by: Simon Glass Cc: Simon Glass Cc: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa Signed-off-by: Stefan Roese --- arch/arm/include/asm/arch-armada8k/soc-info.h | 17 ++ .../pinctrl/marvell,armada-apn806-pinctrl.txt | 25 ++ .../pinctrl/marvell,armada-cp110-pinctrl.txt | 270 +++++++++++++++++++++ .../pinctrl/marvell,mvebu-pinctrl.txt | 113 +++++++++ drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/mvebu/Kconfig | 7 + drivers/pinctrl/mvebu/Makefile | 7 + drivers/pinctrl/mvebu/pinctrl-mvebu.c | 179 ++++++++++++++ drivers/pinctrl/mvebu/pinctrl-mvebu.h | 31 +++ 10 files changed, 651 insertions(+) create mode 100644 arch/arm/include/asm/arch-armada8k/soc-info.h create mode 100644 doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt create mode 100644 doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt create mode 100644 doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt create mode 100644 drivers/pinctrl/mvebu/Kconfig create mode 100644 drivers/pinctrl/mvebu/Makefile create mode 100644 drivers/pinctrl/mvebu/pinctrl-mvebu.c create mode 100644 drivers/pinctrl/mvebu/pinctrl-mvebu.h diff --git a/arch/arm/include/asm/arch-armada8k/soc-info.h b/arch/arm/include/asm/arch-armada8k/soc-info.h new file mode 100644 index 0000000..bae3995 --- /dev/null +++ b/arch/arm/include/asm/arch-armada8k/soc-info.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0 + * https://spdx.org/licenses + */ + +#ifndef _SOC_INFO_H_ +#define _SOC_INFO_H_ + +/* Pin Ctrl driver definitions */ +#define BITS_PER_PIN 4 +#define PIN_FUNC_MASK ((1 << BITS_PER_PIN) - 1) +#define PIN_REG_SHIFT 3 +#define PIN_FIELD_MASK ((1 << PIN_REG_SHIFT) - 1) + +#endif /* _SOC_INFO_H_ */ diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt new file mode 100644 index 0000000..51f2f2c --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt @@ -0,0 +1,25 @@ + Functions of Armada APN806 pin controller + Function 0x0 for any MPP ID activates GPIO pin mode +---------------------------------------------------------------------- +MPP# 0x1 0x2 0x3 0x4 +---------------------------------------------------------------------- +0 SDIO_CLK - SPI0_CLK - +1 SDIO_CMD - SPI0_MISO - +2 SDIO_D[0] - SPI0_MOSI - +3 SDIO_D[1] - SPI0_CS0n - +4 SDIO_D[2] - I2C0_SDA SPI0_CS1n +5 SDIO_D[3] - I2C0_SCK - +6 SDIO_DS - - - +7 SDIO_D[4] - UART1_RXD - +8 SDIO_D[5] - UART1_TXD - +9 SDIO_D[6] - SPI0_CS1n - +10 SDIO_D[7] - - - +11 - - UART0_TXD - +12 SDIO_CARD_PW_OFF SDIO_HW_RST - - +13 - - - - +14 - - - - +15 - - - - +16 - - - - +17 - - - - +18 - - - - +19 - - UART0_RXD - diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt new file mode 100644 index 0000000..3adcf3a --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt @@ -0,0 +1,270 @@ + Functions of Armada CP110 pin controller + Function 0x0 for any MPP ID activates GPIO pin mode + Function 0xc for any MPP ID activates DEBUG_BUS pin mode +------------------------------------------------------------------------------- +MPP# 0x1 0x2 0x3 0x4 +------------------------------------------------------------------------------- +0 DEV_ALE[1] AU_I2SMCLK GE0_RXD[3] TDM_PCLK +1 DEV_ALE[0] AU_I2SDO_SPDIFO GE0_RXD[2] TDM_DRX +2 DEV_AD[15] AU_I2SEXTCLK GE0_RXD[1] TDM_DTX +3 DEV_AD[14] AU_I2SLRCLK GE0_RXD[0] TDM_FSYNC +4 DEV_AD[13] AU_I2SBCLK GE0_RXCTL TDM_RSTn +5 DEV_AD[12] AU_I2SDI GE0_RXCLK TDM_INTn +6 DEV_AD[11] - GE0_TXD[3] SPI0_CSn[2] +7 DEV_AD[10] - GE0_TXD[2] SPI0_CSn[1] +8 DEV_AD[9] - GE0_TXD[1] SPI0_CSn[0] +9 DEV_AD[8] - GE0_TXD[0] SPI0_MOSI +10 DEV_READYn - GE0_TXCTL SPI0_MISO +11 DEV_WEn[1] - GE0_TXCLKOUT SPI0_CLK +12 DEV_CLK_OUT NF_RBn[1] SPI1_CSn[1] GE0_RXCLK +13 DEV_BURSTn NF_RBn[0] SPI1_MISO GE0_RXCTL +14 DEV_BOOTCSn DEV_CSn[0] SPI1_CSn[0] SPI0_CSn[3] +15 DEV_AD[7] - SPI1_MOSI - +16 DEV_AD[6] - SPI1_CLK - +17 DEV_AD[5] - - GE0_TXD[3] +18 DEV_AD[4] - - GE0_TXD[2] +19 DEV_AD[3] - - GE0_TXD[1] +20 DEV_AD[2] - - GE0_TXD[0] +21 DEV_AD[1] - - GE0_TXCTL +22 DEV_AD[0] - - GE0_TXCLKOUT +23 DEV_A[1] - - - +24 DEV_A[0] - - - +25 DEV_OEn - - - - +26 DEV_WEn[0] - - - +27 DEV_CSn[0] SPI1_MISO MSS_GPIO[4] GE0_RXD[3] +28 DEV_CSn[1] SPI1_CSn[0] MSS_GPIO[5] GE0_RXD[2] +29 DEV_CSn[2] SPI1_MOSI MSS_GPIO[6] GE0_RXD[1] +30 DEV_CSn[3] SPI1_CLK MSS_GPIO[7] GE0_RXD[0] +31 DEV_A[2] - MSS_GPIO[4] - +32 MII_COL MII_TXERR MSS_SPI_MISO TDM_DRX +33 MII_TXCLK SDIO_PWR1[0] MSS_SPI_CSn TDM_FSYNC +34 MII_RXERR SDIO_PWR1[1] MSS_SPI_MOSI TDM_DTX +35 SATA1_PRESENT_ACTIVEn TWSI1_SDA MSS_SPI_CLK TDM_PCLK +36 SYNCE2_CLK TWSI1_SCK PTP_CLK SYNCE1_CLK +37 UART2_RXD TWSI0_SCK PTP_PCLK_OUT TDM_INTn +38 UART2_TXD TWSI0_SDA PTP_PULSE TDM_RSTn +39 SDIO_WR_PROTECT - - AU_I2SBCLK PTP_CLK +40 SDIO_PWR1[1] SYNCE1_CLK MSS_TWSI_SDA AU_I2SDO_SPDIFO +41 SDIO_PWR1[0] SDIO_BUS_PWR MSS_TWSI_SCK AU_I2SLRCLK +42 SDIO_V18_EN SDIO_WR_PROTECT SYNCE2_CLK AU_I2SMCLK +43 SDIO_CARD_DETECT - SYNCE1_CLK AU_I2SEXTCLK +44 GE1_TXD[2] - - - +45 GE1_TXD[3] - - - +46 GE1_TXD[1] - - - +47 GE1_TXD[0] - - - +48 GE1_TXCTL_MII_TXEN - - - +49 GE1_TXCLKOUT MII_CRS - - +50 GE1_RXCLK MSS_TWSI_SDA - - +51 GE1_RXD[0] MSS_TWSI_SCK - - +52 GE1_RXD[1] SYNCE1_CLK - SYNCE2_CLK +53 GE1_RXD[2] - PTP_CLK - +54 GE1_RXD[3] SYNCE2_CLK PTP_PCLK_OUT SYNCE1_CLK +55 GE1_RXCTL_MII_RXDV - PTP_PULSE - +56 - - - TDM_DRX +57 - MSS_TWSI_SDA PTP_PCLK_OUT TDM_INTn +58 - MSS_TWSI_SCK PTP_CLK TDM_RSTn +59 MSS_GPIO[7] SYNCE2_CLK - TDM_FSYNC +60 MSS_GPIO[6] - PTP_PULSE TDM_DTX +61 MSS_GPIO[5] - PTP_CLK TDM_PCLK +62 MSS_GPIO[4] SYNCE1_CLK PTP_PCLK_OUT - + +------------------------------------------------------------------------------- +MPP# 0x5 0x6 0x7 +------------------------------------------------------------------------------- +0 - PTP_PULSE MSS_TWSI_SDA +1 - PTP_CLK MSS_TWSI_SCK +2 MSS_UART_RXD PTP_PCLK_OUT TWSI1_SCK +3 MSS_UART_TXD PCIe_RSTOUTn TWSI1_SDA +4 MSS_UART_RXD UART1_CTS PCIe0_CLKREQ +5 MSS_UART_TXD UART1_RTS PCIe1_CLKREQ +6 AU_I2SEXTCLK SATA1_PRESENT_ACTIVEn PCIe2_CLKREQ +7 SPI1_CSn[1] SATA0_PRESENT_ACTIVEn LED_DATA +8 SPI1_CSn[0] UART0_CTS LED_STB +9 SPI1_MOSI - PCIe_RSTOUTn +10 SPI1_MISO UART0_CTS SATA1_PRESENT_ACTIVEn +11 SPI1_CLK UART0_RTS LED_CLK +12 - - - +13 - - - +14 AU_I2SEXTCLK SPI0_MISO SATA0_PRESENT_ACTIVEn +15 - SPI0_MOSI - +16 - - - +17 - - - +18 - - - +19 - - - +20 - - - +21 - - - +22 - - - +23 AU_I2SMCLK - - +24 AU_I2SLRCLK - - +25 AU_I2SDO_SPDIFO - - +26 AU_I2SBCLK - - +27 SPI0_CSn[4] - - +28 SPI0_CSn[5] PCIe2_CLKREQ PTP_PULSE +29 SPI0_CSn[6] PCIe1_CLKREQ PTP_CLK +30 SPI0_CSn[7] PCIe0_CLKREQ PTP_PCLK_OUT +31 - PCIe_RSTOUTn - +32 AU_I2SEXTCLK AU_I2SDI GE_MDIO +33 AU_I2SMCLK SDIO_BUS_PWR - +34 AU_I2SLRCLK SDIO_WR_PROTECT GE_MDC +35 AU_I2SDO_SPDIFO SDIO_CARD_DETECT XG_MDIO +36 AU_I2SBCLK SATA0_PRESENT_ACTIVEn XG_MDC +37 MSS_TWSI_SCK SATA1_PRESENT_ACTIVEn GE_MDC +38 MSS_TWSI_SDA SATA0_PRESENT_ACTIVEn GE_MDIO +39 SPI0_CSn[1] - - +40 PTP_PCLK_OUT SPI0_CLK UART1_TXD +41 PTP_PULSE SPI0_MOSI UART1_RXD +42 MSS_UART_TXD SPI0_MISO UART1_CTS +43 MSS_UART_RXD SPI0_CSn[0] UART1_RTS +44 - - UART0_RTS +45 - - UART0_TXD +46 - - UART1_RTS +47 SPI1_CLK - UART1_TXD +48 SPI1_MOSI - - +49 SPI1_MISO - UART1_RXD +50 SPI1_CSn[0] UART2_TXD UART0_RXD +51 SPI1_CSn[1] UART2_RXD UART0_CTS +52 SPI1_CSn[2] - UART1_CTS +53 SPI1_CSn[3] - UART1_RXD +54 - - - +55 - - - +56 AU_I2SDO_SPDIFO SPI0_CLK UART1_RXD +57 AU_I2SBCLK SPI0_MOSI UART1_TXD +58 AU_I2SDI SPI0_MISO UART1_CTS +59 AU_I2SLRCLK SPI0_CSn[0] UART0_CTS +60 AU_I2SMCLK SPI0_CSn[1] UART0_RTS +61 AU_I2SEXTCLK SPI0_CSn[2] UART0_TXD +62 SATA1_PRESENT_ACTIVEn SPI0_CSn[3] UART0_RXD + +------------------------------------------------------------------------------- +MPP# 0x8 0x9 0xA +------------------------------------------------------------------------------- +0 UART0_RXD SATA0_PRESENT_ACTIVEn GE_MDIO +1 UART0_TXD SATA1_PRESENT_ACTIVEn GE_MDC +2 UART1_RXD SATA0_PRESENT_ACTIVEn XG_MDC +3 UART1_TXD SATA1_PRESENT_ACTIVEn XG_MDIO +4 UART3_RXD - GE_MDC +5 UART3_TXD - GE_MDIO +6 UART0_RXD PTP_PULSE - +7 UART0_TXD PTP_CLK - +8 UART2_RXD PTP_PCLK_OUT SYNCE1_CLK +9 - - SYNCE2_CLK +10 - - - +11 UART2_TXD SATA0_PRESENT_ACTIVEn - +12 - - - +13 MSS_SPI_MISO - - +14 MSS_SPI_CSn - - +15 MSS_SPI_MOSI - - +16 MSS_SPI_CLK - - +17 - - - +18 - - - +19 - - - +20 - - - +21 - - - +22 - - - +23 - - - +24 - - - +25 - - - +26 - - - +27 GE_MDIO SATA0_PRESENT_ACTIVEn UART0_RTS +28 GE_MDC SATA1_PRESENT_ACTIVEn UART0_CTS +29 MSS_TWSI_SDA SATA0_PRESENT_ACTIVEn UART0_RXD +30 MSS_TWSI_SCK SATA1_PRESENT_ACTIVEn UART0_TXD +31 GE_MDC - - +32 SDIO_V18_EN PCIe1_CLKREQ MSS_GPIO[0] +33 XG_MDIO PCIe2_CLKREQ MSS_GPIO[1] +34 - PCIe0_CLKREQ MSS_GPIO[2] +35 GE_MDIO PCIe_RSTOUTn MSS_GPIO[3] +36 GE_MDC PCIe2_CLKREQ MSS_GPIO[5] +37 XG_MDC PCIe1_CLKREQ MSS_GPIO[6] +38 XG_MDIO AU_I2SEXTCLK MSS_GPIO[7] +39 SATA1_PRESENT_ACTIVEn MSS_GPIO[0] +40 GE_MDIO SATA0_PRESENT_ACTIVEn MSS_GPIO[1] +41 GE_MDC SATA1_PRESENT_ACTIVEn MSS_GPIO[2] +42 XG_MDC SATA0_PRESENT_ACTIVEn MSS_GPIO[4] +43 XG_MDIO SATA1_PRESENT_ACTIVEn MSS_GPIO[5] +44 - - - +45 - PCIe_RSTOUTn - +46 - - - +47 GE_MDC CLKOUT - +48 XG_MDC - - +49 GE_MDIO PCIe0_CLKREQ SDIO_V18_EN +50 XG_MDIO - SDIO_PWR1[1] +51 - - SDIO_PWR1[0] +52 LED_CLK PCIe_RSTOUTn PCIe0_CLKREQ +53 LED_STB - - +54 LED_DATA - SDIO_HW_RST +55 - - SDIO_LED +56 - SATA1_PRESENT_ACTIVEn - +57 - SATA0_PRESENT_ACTIVEn - +58 LED_CLK - - +59 LED_STB UART1_TXD - +60 LED_DATA UART1_RXD - +61 UART2_TXD SATA1_PRESENT_ACTIVEn GE_MDIO +62 UART2_RXD SATA0_PRESENT_ACTIVEn GE_MDC + +------------------------------------------------------------------------------- +MPP# 0xB 0xD 0xE +------------------------------------------------------------------------------- +0 - - - +1 - - - +2 - - - +3 - - - +4 - - - +5 - - - +6 - - - +7 - - - +8 - - - +9 - - - +10 - - - +11 - CLKOUT_MPP_11 - +12 - - - +13 - - - +14 - - - +15 PTP_PULSE_CP2CP SAR_IN[5] - +16 - SAR_IN[3] - +17 - SAR_IN[6] - +18 PTP_CLK_CP2CP SAR_IN[11] - +19 WAKEUP_OUT_CP2CP SAR_IN[7] - +20 - SAR_IN[9] - +21 SEI_IN_CP2CP SAR_IN[8] - +22 WAKEUP_IN_CP2CP SAR_IN[10] - +23 LINK_RD_IN_CP2CP SAR_IN[4] - +24 - - - +25 - CLKOUT_MPP_25 - +26 - SAR_IN[0] - +27 REI_IN_CP2CP SAR_IN[1] - +28 LED_DATA SAR_IN[2] - +29 LED_STB AVS_FB_IN_CP2CP - +30 LED_CLK SAR_IN[13] - +31 - - - +32 - SAR_CP2CP_OUT[0] - +33 - SAR_CP2CP_OUT[1] - +34 - SAR_CP2CP_OUT[2] - +35 - SAR_CP2CP_OUT[3] - +36 - CLKIN - +37 LINK_RD_OUT_CP2CP SAR_CP2CP_OUT[4] - +38 PTP_PULSE_CP2CP SAR_CP2CP_OUT[5] - +39 - AVS_FB_OUT_CP2CP - +40 - - - +41 REI_OUT_CP2CP - - +42 - SAR_CP2CP_OUT[9] - +43 WAKEUP_OUT_CP2CP SAR_CP2CP_OUT[10] - +44 PTP_CLK_CP2CP SAR_CP2CP_OUT[11] - +45 - SAR_CP2CP_OUT[6] - +46 - SAR_CP2CP_OUT[13] - +47 - - - +48 WAKEUP_IN_CP2CP SAR_CP2CP_OUT[7] - +49 SEI_OUT_CP2CP SAR_CP2CP_OUT[8] - +50 - - - +51 - - - +52 - - - +53 SDIO_LED - - +54 SDIO_WR_PROTECT - - +55 SDIO_CARD_DETECT - - +56 - - SDIO0_CLK +57 - - SDIO0_CMD +58 - - SDIO0_D[0] +59 - - SDIO0_D[1] +60 - - SDIO0_D[2] +61 - - SDIO0_D[3] +62 - - - diff --git a/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt new file mode 100644 index 0000000..0973db8 --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt @@ -0,0 +1,113 @@ +The pinctrl driver enables Marvell Armada 8K SoCs to configure the multi-purpose +pins (mpp) to a specific function. +A Marvell SoC pin configuration node is a node of a group of pins which can +be used for a specific device or function. Each node requires one or more +mpp pins or group of pins and a mpp function common to all pins. + +Required properties for the pinctrl driver: +- compatible: "marvell,mvebu-pinctrl", + "marvell,armada-ap806-pinctrl", + "marvell,a70x0-pinctrl", + "marvell,a80x0-cp0-pinctrl", + "marvell,a80x0-cp1-pinctrl" +- bank-name: A string defining the pinc controller bank name +- reg: A pair of values defining the pin controller base address + and the address space +- pin-count: Numeric value defining the amount of multi purpose pins + included in this bank +- max-func: Numeric value defining the maximum function value for + pins in this bank +- pin-func: Array of pin function values for every pin in the bank. + When the function value for a specific pin equal 0xFF, + the pin configuration is skipped and a default function + value is used for this pin. + +The A8K is a hybrid SoC that contains several silicon dies interconnected in +a single package. Each such die may have a separate pin controller. + +Example: +/ { + ap806 { + config-space { + pinctl: pinctl@6F4000 { + compatible = "marvell,mvebu-pinctrl", + "marvell,armada-ap806-pinctrl"; + bank-name ="apn-806"; + reg = <0x6F4000 0x10>; + pin-count = <20>; + max-func = <3>; + /* MPP Bus: + SPI0 [0-3] + I2C0 [4-5] + UART0 [11,19] + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 3 3 3 3 3 3 0 0 0 0 + 0 3 0 0 0 0 0 0 0 3>; + }; + }; + }; + + cp110-master { + config-space { + cpm_pinctl: pinctl@44000 { + compatible = "marvell,mvebu-pinctrl", + "marvell,a70x0-pinctrl", + "marvell,a80x0-cp0-pinctrl"; + bank-name ="cp0-110"; + reg = <0x440000 0x20>; + pin-count = <63>; + max-func = <0xf>; + /* MPP Bus: + [0-31] = 0xff: Keep default CP0_shared_pins: + [11] CLKOUT_MPP_11 (out) + [23] LINK_RD_IN_CP2CP (in) + [25] CLKOUT_MPP_25 (out) + [29] AVS_FB_IN_CP2CP (in) + [32,34] SMI + [31] GPIO: push button/Wake + [35-36] GPIO + [37-38] I2C + [40-41] SATA[0/1]_PRESENT_ACTIVEn + [42-43] XSMI + [44-55] RGMII1 + [56-62] SD + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0 7 0 7 0 0 2 2 0 + 0 0 8 8 1 1 1 1 1 1 + 1 1 1 1 1 1 0xE 0xE 0xE 0xE + 0xE 0xE 0xE>; + }; + }; + }; + + cp110-slave { + config-space { + cps_pinctl: pinctl@44000 { + compatible = "marvell,mvebu-pinctrl", + "marvell,a80x0-cp1-pinctrl"; + bank-name ="cp1-110"; + reg = <0x440000 0x20>; + pin-count = <63>; + max-func = <0xf>; + /* MPP Bus: + [0-11] RGMII0 + [27,31] GE_MDIO/MDC + [32-62] = 0xff: Keep default CP1_shared_pins: + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 + 0x3 0x3 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8 0xff 0xff + 0xff 0x8 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff>; + }; + }; + }; +} diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 12be3cf..efcb4c0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -181,5 +181,6 @@ source "drivers/pinctrl/meson/Kconfig" source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/exynos/Kconfig" +source "drivers/pinctrl/mvebu/Kconfig" endmenu diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f28b5c1..512112a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_MESON) += meson/ +obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig new file mode 100644 index 0000000..cf9c299 --- /dev/null +++ b/drivers/pinctrl/mvebu/Kconfig @@ -0,0 +1,7 @@ +config PINCTRL_MVEBU + depends on ARCH_MVEBU + bool + default y + help + Support pin multiplexing and pin configuration control on + Marvell's Armada-8K SoC. diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile new file mode 100644 index 0000000..f4f7864 --- /dev/null +++ b/drivers/pinctrl/mvebu/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Marvell International Ltd. +# +# SPDX-License-Identifier: GPL-2.0 +# https://spdx.org/licenses + +obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c new file mode 100644 index 0000000..b077639 --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0 + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pinctrl-mvebu.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * mvebu_pinctrl_set_state: configure pin functions. + * @dev: the pinctrl device to be configured. + * @config: the state to be configured. + * @return: 0 in success + */ +int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + const void *blob = gd->fdt_blob; + int node = config->of_offset; + struct mvebu_pinctrl_priv *priv; + u32 pin_arr[MVEBU_MAX_PINS_PER_BANK]; + u32 function; + int i, pin_count; + + priv = dev_get_priv(dev); + + pin_count = fdtdec_get_int_array_count(blob, node, + "marvell,pins", + pin_arr, + MVEBU_MAX_PINS_PER_BANK); + if (pin_count <= 0) { + debug("Failed reading pins array for pinconfig %s (%d)\n", + config->name, pin_count); + return -EINVAL; + } + + function = fdtdec_get_int(blob, node, "marvell,function", 0xff); + + for (i = 0; i < pin_count; i++) { + int reg_offset; + int field_offset; + int pin = pin_arr[i]; + + if (function > priv->max_func) { + debug("Illegal function %d for pinconfig %s\n", + function, config->name); + return -EINVAL; + } + + /* Calculate register address and bit in register */ + reg_offset = priv->reg_direction * 4 * + (pin >> (PIN_REG_SHIFT)); + field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK); + + clrsetbits_le32(priv->base_reg + reg_offset, + PIN_FUNC_MASK << field_offset, + (function & PIN_FUNC_MASK) << field_offset); + } + + return 0; +} + +/* + * mvebu_pinctrl_set_state_all: configure the entire bank pin functions. + * @dev: the pinctrl device to be configured. + * @config: the state to be configured. + * @return: 0 in success + */ +static int mvebu_pinctrl_set_state_all(struct udevice *dev, + struct udevice *config) +{ + const void *blob = gd->fdt_blob; + int node = config->of_offset; + struct mvebu_pinctrl_priv *priv; + u32 func_arr[MVEBU_MAX_PINS_PER_BANK]; + int pin, err; + + priv = dev_get_priv(dev); + + err = fdtdec_get_int_array(blob, node, "pin-func", + func_arr, priv->pin_cnt); + if (err) { + debug("Failed reading pin functions for bank %s\n", + priv->bank_name); + return -EINVAL; + } + + for (pin = 0; pin < priv->pin_cnt; pin++) { + int reg_offset; + int field_offset; + u32 func = func_arr[pin]; + + /* Bypass pins with function 0xFF */ + if (func == 0xff) { + debug("Warning: pin %d value is not modified ", pin); + debug("(kept as default)\n"); + continue; + } else if (func > priv->max_func) { + debug("Illegal function %d for pin %d\n", func, pin); + return -EINVAL; + } + + /* Calculate register address and bit in register */ + reg_offset = priv->reg_direction * 4 * + (pin >> (PIN_REG_SHIFT)); + field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK); + + clrsetbits_le32(priv->base_reg + reg_offset, + PIN_FUNC_MASK << field_offset, + (func & PIN_FUNC_MASK) << field_offset); + } + + return 0; +} + +int mvebu_pinctl_probe(struct udevice *dev) +{ + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + struct mvebu_pinctrl_priv *priv; + + priv = dev_get_priv(dev); + if (!priv) { + debug("%s: Failed to get private\n", __func__); + return -EINVAL; + } + + priv->base_reg = dev_get_addr_ptr(dev); + if (priv->base_reg == (void *)FDT_ADDR_T_NONE) { + debug("%s: Failed to get base address\n", __func__); + return -EINVAL; + } + + priv->pin_cnt = fdtdec_get_int(blob, node, "pin-count", + MVEBU_MAX_PINS_PER_BANK); + priv->max_func = fdtdec_get_int(blob, node, "max-func", + MVEBU_MAX_FUNC); + priv->bank_name = fdt_getprop(blob, node, "bank-name", NULL); + + priv->reg_direction = 1; + if (fdtdec_get_bool(blob, node, "reverse-reg")) + priv->reg_direction = -1; + + return mvebu_pinctrl_set_state_all(dev, dev); +} + +static struct pinctrl_ops mvebu_pinctrl_ops = { + .set_state = mvebu_pinctrl_set_state +}; + +static const struct udevice_id mvebu_pinctrl_ids[] = { + { .compatible = "marvell,mvebu-pinctrl" }, + { .compatible = "marvell,armada-ap806-pinctrl" }, + { .compatible = "marvell,a70x0-pinctrl" }, + { .compatible = "marvell,a80x0-cp0-pinctrl" }, + { .compatible = "marvell,a80x0-cp1-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_mvebu) = { + .name = "mvebu_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = mvebu_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct mvebu_pinctrl_priv), + .ops = &mvebu_pinctrl_ops, + .probe = mvebu_pinctl_probe +}; diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h new file mode 100644 index 0000000..1a1d3ef --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0 + * https://spdx.org/licenses + */ + + #ifndef __PINCTRL_MVEBU_H_ + #define __PINCTRL_MVEBU_H_ + + #define MVEBU_MAX_PINCTL_BANKS 4 + #define MVEBU_MAX_PINS_PER_BANK 100 + #define MVEBU_MAX_FUNC 0xF + +/* + * struct mvebu_pin_bank_data: mvebu-pinctrl bank data + * @base_reg: controller base address for this bank + * @pin_cnt: number of pins included in this bank + * @max_func: maximum configurable function value for pins in this bank + * @reg_direction: + * @bank_name: the pin's bank name + */ +struct mvebu_pinctrl_priv { + void *base_reg; + uint pin_cnt; + uint max_func; + int reg_direction; + const char *bank_name; +}; + +#endif /* __PINCTRL_MVEBU_H_ */