From 0100defd2803f6c3df6bfd400a10af0cf9b8536a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 30 Jan 2009 22:44:20 -0500 Subject: [ARM] Kirkwood: MPP initialization code This allows for board support code to set up their MPP config if the bootloader didn't do it all or did it wrong. This also allows to register usable GPIOs. Signed-off-by: Nicolas Pitre --- arch/arm/mach-kirkwood/mpp.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 arch/arm/mach-kirkwood/mpp.c (limited to 'arch/arm/mach-kirkwood/mpp.c') diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c new file mode 100644 index 00000000000..63c44934391 --- /dev/null +++ b/arch/arm/mach-kirkwood/mpp.c @@ -0,0 +1,97 @@ +/* + * arch/arm/mach-kirkwood/mpp.c + * + * MPP functions for Marvell Kirkwood 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 +#include "common.h" +#include "mpp.h" + +static unsigned int __init kirkwood_variant(void) +{ + u32 dev, rev; + + kirkwood_pcie_id(&dev, &rev); + + if (dev == MV88F6281_DEV_ID && rev >= MV88F6281_REV_A0) + return MPP_F6281_MASK; + if (dev == MV88F6192_DEV_ID && rev >= MV88F6192_REV_A0) + return MPP_F6192_MASK; + if (dev == MV88F6180_DEV_ID) + return MPP_F6180_MASK; + + printk(KERN_ERR "MPP setup: unknown kirkwood variant " + "(dev %#x rev %#x)\n", dev, rev); + return 0; +} + +#define MPP_CTRL(i) (DEV_BUS_VIRT_BASE + (i) * 4) +#define MPP_NR_REGS (1 + MPP_MAX/8) + +void __init kirkwood_mpp_conf(unsigned int *mpp_list) +{ + u32 mpp_ctrl[MPP_NR_REGS]; + unsigned int variant_mask; + int i; + + variant_mask = kirkwood_variant(); + if (!variant_mask) + return; + + printk(KERN_DEBUG "initial MPP regs:"); + for (i = 0; i < MPP_NR_REGS; i++) { + mpp_ctrl[i] = readl(MPP_CTRL(i)); + printk(" %08x", mpp_ctrl[i]); + } + printk("\n"); + + while (*mpp_list) { + unsigned int num = MPP_NUM(*mpp_list); + unsigned int sel = MPP_SEL(*mpp_list); + int shift, gpio_mode; + + if (num > MPP_MAX) { + printk(KERN_ERR "kirkwood_mpp_conf: invalid MPP " + "number (%u)\n", num); + continue; + } + if (!(*mpp_list & variant_mask)) { + printk(KERN_WARNING + "kirkwood_mpp_conf: requested MPP%u config " + "unavailable on this hardware\n", num); + continue; + } + + shift = (num & 7) << 2; + mpp_ctrl[num / 8] &= ~(0xf << shift); + mpp_ctrl[num / 8] |= sel << shift; + + gpio_mode = 0; + if (*mpp_list & MPP_INPUT_MASK) + gpio_mode |= GPIO_INPUT_OK; + if (*mpp_list & MPP_OUTPUT_MASK) + gpio_mode |= GPIO_OUTPUT_OK; + if (sel != 0) + gpio_mode = 0; + orion_gpio_set_valid(num, gpio_mode); + + mpp_list++; + } + + printk(KERN_DEBUG " final MPP regs:"); + for (i = 0; i < MPP_NR_REGS; i++) { + writel(mpp_ctrl[i], MPP_CTRL(i)); + printk(" %08x", mpp_ctrl[i]); + } + printk("\n"); +} -- cgit v1.2.3-70-g09d2