Instead of having board code poke directly into the MPP configuration registers, and separately calling orion5x_gpio_set_valid_pins() to indicate which MPP pins can be used as GPIO pins, introduce a helper function for configuring the roles of each of the MPP pins, and have that helper function handle gpio validity internally. Signed-off-by: Lennert Buytenhek Acked-by: Sylver Bruneau --- arch/arm/mach-orion5x/Makefile | 2 +- arch/arm/mach-orion5x/common.h | 2 +- arch/arm/mach-orion5x/db88f5281-setup.c | 42 +++++---- arch/arm/mach-orion5x/dns323-setup.c | 50 +++++------ arch/arm/mach-orion5x/gpio.c | 7 +- arch/arm/mach-orion5x/kurobox_pro-setup.c | 41 ++++---- arch/arm/mach-orion5x/mpp.c | 142 +++++++++++++++++++++++++++++ arch/arm/mach-orion5x/mpp.h | 63 +++++++++++++ arch/arm/mach-orion5x/rd88f5182-setup.c | 43 +++++---- arch/arm/mach-orion5x/ts209-setup.c | 43 +++++---- 10 files changed, 321 insertions(+), 114 deletions(-) create mode 100644 arch/arm/mach-orion5x/mpp.c create mode 100644 arch/arm/mach-orion5x/mpp.h --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o pci.o gpio.o irq.o +obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -48,7 +48,7 @@ * Valid GPIO pins according to MPP setup, used by machine-setup. * (/mach-orion/gpio.c). */ -void orion5x_gpio_set_valid_pins(u32 pins); +void orion5x_gpio_set_valid(unsigned pin, int valid); void gpio_display(void); /* debug */ struct machine_desc; --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -27,6 +27,7 @@ #include #include #include "common.h" +#include "mpp.h" /***************************************************************************** * DB-88F5281 on board devices @@ -305,26 +306,27 @@ */ orion5x_init(); - /* - * Setup Multiplexing Pins: - * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input) - * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2] - * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3] - * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1) - * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3) - * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator) - * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2) - * MPP14: NAND_REn[2] MPP15: NAND_WEn[2] - * MPP16: UART1_RX MPP17: UART1_TX - * MPP18: UART1_CTS MPP19: UART1_RTS - * MPP-DEV: DEV_D[16:31] - */ - orion5x_write(MPP_0_7_CTRL, 0x00222203); - orion5x_write(MPP_8_15_CTRL, 0x44000000); - orion5x_write(MPP_16_19_CTRL, 0); - orion5x_write(MPP_DEV_CTRL, 0); - - orion5x_gpio_set_valid_pins(0x00003fc3); + orion5x_mpp_conf(0, MPP_GPIO); /* USB Over Current */ + orion5x_mpp_conf(1, MPP_GPIO); /* USB Vbat input */ + orion5x_mpp_conf(2, MPP_PCI_ARB); /* PCI_REQn[2] */ + orion5x_mpp_conf(3, MPP_PCI_ARB); /* PCI_GNTn[2] */ + orion5x_mpp_conf(4, MPP_PCI_ARB); /* PCI_REQn[3] */ + orion5x_mpp_conf(5, MPP_PCI_ARB); /* PCI_GNTn[3] */ + orion5x_mpp_conf(6, MPP_GPIO); /* JP0, CON17.2 */ + orion5x_mpp_conf(7, MPP_GPIO); /* JP1, CON17.1 */ + orion5x_mpp_conf(8, MPP_GPIO); /* JP2, CON11.2 */ + orion5x_mpp_conf(9, MPP_GPIO); /* JP3, CON11.3 */ + orion5x_mpp_conf(10, MPP_GPIO); /* RTC int */ + orion5x_mpp_conf(11, MPP_GPIO); /* Baud Rate Generator */ + orion5x_mpp_conf(12, MPP_GPIO); /* PCI int 1 */ + orion5x_mpp_conf(13, MPP_GPIO); /* PCI int 2 */ + orion5x_mpp_conf(14, MPP_NAND); /* NAND_REn[2] */ + orion5x_mpp_conf(15, MPP_NAND); /* NAND_WEn[2] */ + orion5x_mpp_conf(16, MPP_UART); /* UART1_RX */ + orion5x_mpp_conf(17, MPP_UART); /* UART1_TX */ + orion5x_mpp_conf(18, MPP_UART); /* UART1_CTSn */ + orion5x_mpp_conf(19, MPP_UART); /* UART1_RTSn */ + orion5x_write(MPP_DEV_CTRL, 0); /* DEV_D[31:16] */ /* * Configure peripherals. --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -27,6 +27,7 @@ #include #include #include "common.h" +#include "mpp.h" #define DNS323_GPIO_LED_RIGHT_AMBER 1 #define DNS323_GPIO_LED_LEFT_AMBER 2 @@ -247,34 +248,27 @@ /* Setup basic Orion functions. Need to be called early. */ orion5x_init(); - /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */ - orion5x_write(MPP_0_7_CTRL, 0); - orion5x_write(MPP_8_15_CTRL, 0); - orion5x_write(MPP_16_19_CTRL, 0); - orion5x_write(MPP_DEV_CTRL, 0); - - /* Define used GPIO pins - - GPIO Map: - - | 0 | | PEX_RST_OUT (not controlled by GPIO) - | 1 | Out | right amber LED (= sata ch0 LED) (low-active) - | 2 | Out | left amber LED (= sata ch1 LED) (low-active) - | 3 | Out | //unknown// - | 4 | Out | power button LED (low-active, together with pin #5) - | 5 | Out | power button LED (low-active, together with pin #4) - | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active) - | 7 | In | M41T80 nIRQ/OUT/SQW signal - | 8 | Out | triggers power off (high-active) - | 9 | In | power button switch (low-active) - | 10 | In | reset button switch (low-active) - | 11 | Out | //unknown// - | 12 | Out | //unknown// - | 13 | Out | //unknown// - | 14 | Out | //unknown// - | 15 | Out | //unknown// - */ - orion5x_gpio_set_valid_pins(0x07f6); + orion5x_mpp_conf(0, MPP_PCIE_RST_OUTn); + orion5x_mpp_conf(1, MPP_GPIO); /* right amber LED (sata ch0) */ + orion5x_mpp_conf(2, MPP_GPIO); /* left amber LED (sata ch1) */ + orion5x_mpp_conf(3, MPP_UNUSED); + orion5x_mpp_conf(4, MPP_GPIO); /* power button LED */ + orion5x_mpp_conf(5, MPP_GPIO); /* power button LED */ + orion5x_mpp_conf(6, MPP_GPIO); /* GMT G751-2f overtemp */ + orion5x_mpp_conf(7, MPP_GPIO); /* M41T80 nIRQ/OUT/SQW */ + orion5x_mpp_conf(8, MPP_GPIO); /* triggers power off */ + orion5x_mpp_conf(9, MPP_GPIO); /* power button switch */ + orion5x_mpp_conf(10, MPP_GPIO); /* reset button switch */ + orion5x_mpp_conf(11, MPP_UNUSED); + orion5x_mpp_conf(12, MPP_UNUSED); + orion5x_mpp_conf(13, MPP_UNUSED); + orion5x_mpp_conf(14, MPP_UNUSED); + orion5x_mpp_conf(15, MPP_UNUSED); + orion5x_mpp_conf(16, MPP_UNUSED); + orion5x_mpp_conf(17, MPP_UNUSED); + orion5x_mpp_conf(18, MPP_UNUSED); + orion5x_mpp_conf(19, MPP_UNUSED); + orion5x_write(MPP_DEV_CTRL, 0); /* DEV_D[31:16] */ /* * Configure peripherals. --- a/arch/arm/mach-orion5x/gpio.c +++ b/arch/arm/mach-orion5x/gpio.c @@ -24,9 +24,12 @@ static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ -void __init orion5x_gpio_set_valid_pins(u32 pins) +void __init orion5x_gpio_set_valid(unsigned pin, int valid) { - gpio_valid[0] = pins; + if (valid) + __set_bit(pin, gpio_valid); + else + __clear_bit(pin, gpio_valid); } /* --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -25,6 +25,7 @@ #include #include #include "common.h" +#include "mpp.h" /***************************************************************************** * KUROBOX-PRO Info @@ -187,26 +188,26 @@ */ orion5x_init(); - /* - * Setup Multiplexing Pins -- - * MPP[0-1] Not used - * MPP[2] GPIO Micon - * MPP[3] GPIO RTC - * MPP[4-5] Not used - * MPP[6] Nand Flash REn - * MPP[7] Nand Flash WEn - * MPP[8-11] Not used - * MPP[12] SATA 0 presence Indication - * MPP[13] SATA 1 presence Indication - * MPP[14] SATA 0 active Indication - * MPP[15] SATA 1 active indication - * MPP[16-19] Not used - */ - orion5x_write(MPP_0_7_CTRL, 0x44220003); - orion5x_write(MPP_8_15_CTRL, 0x55550000); - orion5x_write(MPP_16_19_CTRL, 0x0); - - orion5x_gpio_set_valid_pins(0x0000000c); + orion5x_mpp_conf(0, MPP_UNUSED); + orion5x_mpp_conf(1, MPP_UNUSED); + orion5x_mpp_conf(2, MPP_GPIO); /* GPIO Micon */ + orion5x_mpp_conf(3, MPP_GPIO); /* GPIO Rtc */ + orion5x_mpp_conf(4, MPP_UNUSED); + orion5x_mpp_conf(5, MPP_UNUSED); + orion5x_mpp_conf(6, MPP_NAND); /* NAND Flash REn */ + orion5x_mpp_conf(7, MPP_NAND); /* NAND Flash WEn */ + orion5x_mpp_conf(8, MPP_UNUSED); + orion5x_mpp_conf(9, MPP_UNUSED); + orion5x_mpp_conf(10, MPP_UNUSED); + orion5x_mpp_conf(11, MPP_UNUSED); + orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */ + orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */ + orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */ + orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */ + orion5x_mpp_conf(16, MPP_UNUSED); + orion5x_mpp_conf(17, MPP_UNUSED); + orion5x_mpp_conf(18, MPP_UNUSED); + orion5x_mpp_conf(19, MPP_UNUSED); /* * Configure peripherals. --- /dev/null +++ b/arch/arm/mach-orion5x/mpp.c @@ -0,0 +1,142 @@ +/* + * arch/arm/mach-orion5x/mpp.c + * + * MPP functions for Marvell Orion 5x SoCs + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +static int is_5182(void) +{ + u32 dev; + u32 rev; + + orion5x_pcie_id(&dev, &rev); + + return !!(dev == MV88F5182_DEV_ID); +} + +static int is_5281(void) +{ + u32 dev; + u32 rev; + + orion5x_pcie_id(&dev, &rev); + + return !!(dev == MV88F5281_DEV_ID); +} + +static int __init determine_type_encoding(int mpp, enum orion5x_mpp_type type) +{ + switch (type) { + case MPP_UNUSED: + case MPP_GPIO: + if (mpp == 0) + return 3; + if (mpp >= 1 && mpp <= 15) + return 0; + if (mpp >= 16 && mpp <= 19) { + if (is_5182()) + return 5; + if (type == MPP_UNUSED) + return 0; + } + return -1; + + case MPP_PCIE_RST_OUTn: + if (mpp == 0) + return 0; + return -1; + + case MPP_PCI_ARB: + if (mpp >= 0 && mpp <= 7) + return 2; + return -1; + + case MPP_PCI_PMEn: + if (mpp == 2) + return 3; + return -1; + + case MPP_GIGE: + if (mpp >= 8 && mpp <= 15) + return 1; + return -1; + + case MPP_NAND: + if (is_5182() || is_5281()) { + if (mpp >= 4 && mpp <= 7) + return 4; + if (mpp >= 12 && mpp <= 17) + return 4; + } + return -1; + + + case MPP_SATA_LED: + if (is_5182()) { + if (mpp >= 4 && mpp <= 7) + return 5; + if (mpp >= 12 && mpp <= 15) + return 5; + } + return -1; + + case MPP_UART: + if (mpp >= 16 && mpp <= 19) + return 0; + return -1; + } + + printk(KERN_INFO "unknown MPP type %d\n", type); + + return -1; +} + +static void __init set_mpp_type(int mpp, int num_type) +{ + unsigned long reg; + u32 value; + + if (mpp >= 0 && mpp <= 7) + reg = MPP_0_7_CTRL; + else if (mpp >= 8 && mpp <= 15) + reg = MPP_8_15_CTRL; + else if (mpp >= 16 && mpp <= 19) + reg = MPP_16_19_CTRL; + else + return; + + mpp &= 7; + + value = readl(reg); + value &= ~(0xf << (mpp << 2)); + value |= (num_type & 0xf) << (mpp << 2); + writel(value, reg); +} + +void __init orion5x_mpp_conf(int mpp, enum orion5x_mpp_type type) +{ + int num_type; + + num_type = determine_type_encoding(mpp, type); + if (num_type < 0) { + printk(KERN_ERR "orion5x_mpp_conf: invalid MPP " + "combination (%d, %d)\n", mpp, type); + return; + } + + set_mpp_type(mpp, num_type); + + orion5x_gpio_set_valid(mpp, (type == MPP_GPIO) ? 1 : 0); +} --- /dev/null +++ b/arch/arm/mach-orion5x/mpp.h @@ -0,0 +1,63 @@ +#ifndef __ARCH_ORION5X_MPP_H +#define __ARCH_ORION5X_MPP_H + +enum orion5x_mpp_type { + /* + * This MPP is unused. + */ + MPP_UNUSED, + + /* + * This MPP pin is used as a generic GPIO pin. Valid for + * MPPs 0-15 and device bus data pins 16-31. On 5182, also + * valid for MPPs 16-19. + */ + MPP_GPIO, + + /* + * This MPP is used as PCIe_RST_OUTn pin. Valid for + * MPP 0 only. + */ + MPP_PCIE_RST_OUTn, + + /* + * This MPP is used as PCI arbiter pin (REQn/GNTn.) + * Valid for MPPs 0-7 only. + */ + MPP_PCI_ARB, + + /* + * This MPP is used as PCI_PMEn pin. Valid for MPP 2 only. + */ + MPP_PCI_PMEn, + + /* + * This MPP is used as GigE half-duplex (COL, CRS) or GMII + * (RXERR, CRS, TXERR, TXD[7:4], RXD[7:4]) pin. Valid for + * MPPs 8-19 only. + */ + MPP_GIGE, + + /* + * This MPP is used as NAND REn/WEn pin. Valid for MPPs + * 4-7 and 12-17 only, and only on the 5181l/5182/5281. + */ + MPP_NAND, + + /* + * This MPP is used as a SATA presence/activity LED. + * Valid for MPPs 4-7 and 12-15 only, and only on the 5182. + */ + MPP_SATA_LED, + + /* + * This MPP is used as UART1 RXD/TXD/CTSn/RTSn pin. + * Valid for MPPs 16-19 only. + */ + MPP_UART, +}; + +void orion5x_mpp_conf(int mpp, enum orion5x_mpp_type type); + + +#endif --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -26,6 +26,7 @@ #include #include #include "common.h" +#include "mpp.h" /***************************************************************************** * RD-88F5182 Info @@ -248,22 +249,28 @@ */ orion5x_init(); + orion5x_mpp_conf(0, MPP_GPIO); /* Debug Led */ + orion5x_mpp_conf(1, MPP_GPIO); /* Reset Switch */ + orion5x_mpp_conf(2, MPP_UNUSED); + orion5x_mpp_conf(3, MPP_GPIO); /* RTC Int */ + orion5x_mpp_conf(4, MPP_GPIO); + orion5x_mpp_conf(5, MPP_GPIO); + orion5x_mpp_conf(6, MPP_GPIO); /* PCI_intA */ + orion5x_mpp_conf(7, MPP_GPIO); /* PCI_intB */ + orion5x_mpp_conf(8, MPP_UNUSED); + orion5x_mpp_conf(9, MPP_UNUSED); + orion5x_mpp_conf(10, MPP_UNUSED); + orion5x_mpp_conf(11, MPP_UNUSED); + orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */ + orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */ + orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */ + orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */ + orion5x_mpp_conf(16, MPP_UNUSED); + orion5x_mpp_conf(17, MPP_UNUSED); + orion5x_mpp_conf(18, MPP_UNUSED); + orion5x_mpp_conf(19, MPP_UNUSED); + /* - * Setup Multiplexing Pins -- - * MPP[0] Debug Led (GPIO - Out) - * MPP[1] Debug Led (GPIO - Out) - * MPP[2] N/A - * MPP[3] RTC_Int (GPIO - In) - * MPP[4] GPIO - * MPP[5] GPIO - * MPP[6] PCI_intA (GPIO - In) - * MPP[7] PCI_intB (GPIO - In) - * MPP[8-11] N/A - * MPP[12] SATA 0 presence Indication - * MPP[13] SATA 1 presence Indication - * MPP[14] SATA 0 active Indication - * MPP[15] SATA 1 active indication - * MPP[16-19] Not used * MPP[20] PCI Clock to MV88F5182 * MPP[21] PCI Clock to mini PCI CON11 * MPP[22] USB 0 over current indication @@ -272,12 +279,6 @@ * MPP[25] USB 0 over current enable */ - orion5x_write(MPP_0_7_CTRL, 0x00000003); - orion5x_write(MPP_8_15_CTRL, 0x55550000); - orion5x_write(MPP_16_19_CTRL, 0x5555); - - orion5x_gpio_set_valid_pins(0x000000fb); - /* * Configure peripherals. */ --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -28,6 +28,7 @@ #include #include #include "common.h" +#include "mpp.h" #define QNAP_TS209_NOR_BOOT_BASE 0xf4000000 #define QNAP_TS209_NOR_BOOT_SIZE SZ_8M @@ -364,33 +365,33 @@ */ orion5x_init(); + orion5x_mpp_conf(0, MPP_UNUSED); + orion5x_mpp_conf(1, MPP_GPIO); /* USB copy button */ + orion5x_mpp_conf(2, MPP_GPIO); /* Load defaults button */ + orion5x_mpp_conf(3, MPP_GPIO); /* GPIO RTC */ + orion5x_mpp_conf(4, MPP_UNUSED); + orion5x_mpp_conf(5, MPP_UNUSED); + orion5x_mpp_conf(6, MPP_GPIO); /* PCI Int A */ + orion5x_mpp_conf(7, MPP_GPIO); /* PCI Int B */ + orion5x_mpp_conf(8, MPP_UNUSED); + orion5x_mpp_conf(9, MPP_UNUSED); + orion5x_mpp_conf(10, MPP_UNUSED); + orion5x_mpp_conf(11, MPP_UNUSED); + orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */ + orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */ + orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */ + orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */ + orion5x_mpp_conf(16, MPP_UART); /* UART1 RXD */ + orion5x_mpp_conf(17, MPP_UART); /* UART1 TXD */ + orion5x_mpp_conf(18, MPP_GPIO); /* SW_RST */ + orion5x_mpp_conf(19, MPP_UNUSED); + /* - * Setup Multiplexing Pins -- - * MPP[0] Reserved - * MPP[1] USB copy button (0 active) - * MPP[2] Load defaults button (0 active) - * MPP[3] GPIO RTC - * MPP[4-5] Reserved - * MPP[6] PCI Int A - * MPP[7] PCI Int B - * MPP[8-11] Reserved - * MPP[12] SATA 0 presence - * MPP[13] SATA 1 presence - * MPP[14] SATA 0 active - * MPP[15] SATA 1 active - * MPP[16] UART1 RXD - * MPP[17] UART1 TXD - * MPP[18] SW_RST (0 active) - * MPP[19] Reserved * MPP[20] PCI clock 0 * MPP[21] PCI clock 1 * MPP[22] USB 0 over current * MPP[23-25] Reserved */ - orion5x_write(MPP_0_7_CTRL, 0x3); - orion5x_write(MPP_8_15_CTRL, 0x55550000); - orion5x_write(MPP_16_19_CTRL, 0x5500); - orion5x_gpio_set_valid_pins(0x3cc0fff); /* * Configure peripherals.