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 <kostap@marvell.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Nadav Haklai <nadavh@marvell.com>
Cc: Neta Zur Hershkovits <neta@marvell.com>
Cc: Omri Itach <omrii@marvell.com>
Cc: Igal Liberman <igall@marvell.com>
Cc: Haim Boot <hayim@marvell.com>
Cc: Hanna Hawa <hannah@marvell.com>
Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
Konstantin Porotchkin 2016-12-08 12:22:29 +02:00 committed by Stefan Roese
parent fa61ef6b49
commit 656e6cc86b
10 changed files with 651 additions and 0 deletions

View file

@ -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_ */

View file

@ -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 -

View file

@ -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 - - -

View file

@ -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>;
};
};
};
}

View file

@ -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

View file

@ -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/

View file

@ -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.

View file

@ -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

View file

@ -0,0 +1,179 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#include <common.h>
#include <config.h>
#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <dm/pinctrl.h>
#include <dm/root.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/arch-armada8k/soc-info.h>
#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
};

View file

@ -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_ */