1*19cfd5c0SLennert Buytenhek /* 2*19cfd5c0SLennert Buytenhek * arch/arm/mach-orion5x/mpp.c 3*19cfd5c0SLennert Buytenhek * 4*19cfd5c0SLennert Buytenhek * MPP functions for Marvell Orion 5x SoCs 5*19cfd5c0SLennert Buytenhek * 6*19cfd5c0SLennert Buytenhek * This file is licensed under the terms of the GNU General Public 7*19cfd5c0SLennert Buytenhek * License version 2. This program is licensed "as is" without any 8*19cfd5c0SLennert Buytenhek * warranty of any kind, whether express or implied. 9*19cfd5c0SLennert Buytenhek */ 10*19cfd5c0SLennert Buytenhek 11*19cfd5c0SLennert Buytenhek #include <linux/kernel.h> 12*19cfd5c0SLennert Buytenhek #include <linux/init.h> 13*19cfd5c0SLennert Buytenhek #include <linux/mbus.h> 14*19cfd5c0SLennert Buytenhek #include <asm/hardware.h> 15*19cfd5c0SLennert Buytenhek #include <asm/io.h> 16*19cfd5c0SLennert Buytenhek #include "common.h" 17*19cfd5c0SLennert Buytenhek #include "mpp.h" 18*19cfd5c0SLennert Buytenhek 19*19cfd5c0SLennert Buytenhek static int is_5181l(void) 20*19cfd5c0SLennert Buytenhek { 21*19cfd5c0SLennert Buytenhek u32 dev; 22*19cfd5c0SLennert Buytenhek u32 rev; 23*19cfd5c0SLennert Buytenhek 24*19cfd5c0SLennert Buytenhek orion5x_pcie_id(&dev, &rev); 25*19cfd5c0SLennert Buytenhek 26*19cfd5c0SLennert Buytenhek return !!(dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0); 27*19cfd5c0SLennert Buytenhek } 28*19cfd5c0SLennert Buytenhek 29*19cfd5c0SLennert Buytenhek static int is_5182(void) 30*19cfd5c0SLennert Buytenhek { 31*19cfd5c0SLennert Buytenhek u32 dev; 32*19cfd5c0SLennert Buytenhek u32 rev; 33*19cfd5c0SLennert Buytenhek 34*19cfd5c0SLennert Buytenhek orion5x_pcie_id(&dev, &rev); 35*19cfd5c0SLennert Buytenhek 36*19cfd5c0SLennert Buytenhek return !!(dev == MV88F5182_DEV_ID); 37*19cfd5c0SLennert Buytenhek } 38*19cfd5c0SLennert Buytenhek 39*19cfd5c0SLennert Buytenhek static int is_5281(void) 40*19cfd5c0SLennert Buytenhek { 41*19cfd5c0SLennert Buytenhek u32 dev; 42*19cfd5c0SLennert Buytenhek u32 rev; 43*19cfd5c0SLennert Buytenhek 44*19cfd5c0SLennert Buytenhek orion5x_pcie_id(&dev, &rev); 45*19cfd5c0SLennert Buytenhek 46*19cfd5c0SLennert Buytenhek return !!(dev == MV88F5281_DEV_ID); 47*19cfd5c0SLennert Buytenhek } 48*19cfd5c0SLennert Buytenhek 49*19cfd5c0SLennert Buytenhek static int __init determine_type_encoding(int mpp, enum orion5x_mpp_type type) 50*19cfd5c0SLennert Buytenhek { 51*19cfd5c0SLennert Buytenhek switch (type) { 52*19cfd5c0SLennert Buytenhek case MPP_UNUSED: 53*19cfd5c0SLennert Buytenhek case MPP_GPIO: 54*19cfd5c0SLennert Buytenhek if (mpp == 0) 55*19cfd5c0SLennert Buytenhek return 3; 56*19cfd5c0SLennert Buytenhek if (mpp >= 1 && mpp <= 15) 57*19cfd5c0SLennert Buytenhek return 0; 58*19cfd5c0SLennert Buytenhek if (mpp >= 16 && mpp <= 19) { 59*19cfd5c0SLennert Buytenhek if (is_5182()) 60*19cfd5c0SLennert Buytenhek return 5; 61*19cfd5c0SLennert Buytenhek if (type == MPP_UNUSED) 62*19cfd5c0SLennert Buytenhek return 0; 63*19cfd5c0SLennert Buytenhek } 64*19cfd5c0SLennert Buytenhek return -1; 65*19cfd5c0SLennert Buytenhek 66*19cfd5c0SLennert Buytenhek case MPP_PCIE_RST_OUTn: 67*19cfd5c0SLennert Buytenhek if (mpp == 0) 68*19cfd5c0SLennert Buytenhek return 0; 69*19cfd5c0SLennert Buytenhek return -1; 70*19cfd5c0SLennert Buytenhek 71*19cfd5c0SLennert Buytenhek case MPP_PCI_ARB: 72*19cfd5c0SLennert Buytenhek if (mpp >= 0 && mpp <= 7) 73*19cfd5c0SLennert Buytenhek return 2; 74*19cfd5c0SLennert Buytenhek return -1; 75*19cfd5c0SLennert Buytenhek 76*19cfd5c0SLennert Buytenhek case MPP_PCI_PMEn: 77*19cfd5c0SLennert Buytenhek if (mpp == 2) 78*19cfd5c0SLennert Buytenhek return 3; 79*19cfd5c0SLennert Buytenhek return -1; 80*19cfd5c0SLennert Buytenhek 81*19cfd5c0SLennert Buytenhek case MPP_GIGE: 82*19cfd5c0SLennert Buytenhek if (mpp >= 8 && mpp <= 19) 83*19cfd5c0SLennert Buytenhek return 1; 84*19cfd5c0SLennert Buytenhek return -1; 85*19cfd5c0SLennert Buytenhek 86*19cfd5c0SLennert Buytenhek case MPP_NAND: 87*19cfd5c0SLennert Buytenhek if (is_5182() || is_5281()) { 88*19cfd5c0SLennert Buytenhek if (mpp >= 4 && mpp <= 7) 89*19cfd5c0SLennert Buytenhek return 4; 90*19cfd5c0SLennert Buytenhek if (mpp >= 12 && mpp <= 17) 91*19cfd5c0SLennert Buytenhek return 4; 92*19cfd5c0SLennert Buytenhek } 93*19cfd5c0SLennert Buytenhek return -1; 94*19cfd5c0SLennert Buytenhek 95*19cfd5c0SLennert Buytenhek case MPP_PCI_CLK: 96*19cfd5c0SLennert Buytenhek if (is_5181l() && mpp >= 6 && mpp <= 7) 97*19cfd5c0SLennert Buytenhek return 5; 98*19cfd5c0SLennert Buytenhek return -1; 99*19cfd5c0SLennert Buytenhek 100*19cfd5c0SLennert Buytenhek case MPP_SATA_LED: 101*19cfd5c0SLennert Buytenhek if (is_5182()) { 102*19cfd5c0SLennert Buytenhek if (mpp >= 4 && mpp <= 7) 103*19cfd5c0SLennert Buytenhek return 5; 104*19cfd5c0SLennert Buytenhek if (mpp >= 12 && mpp <= 15) 105*19cfd5c0SLennert Buytenhek return 5; 106*19cfd5c0SLennert Buytenhek } 107*19cfd5c0SLennert Buytenhek return -1; 108*19cfd5c0SLennert Buytenhek 109*19cfd5c0SLennert Buytenhek case MPP_UART: 110*19cfd5c0SLennert Buytenhek if (mpp >= 16 && mpp <= 19) 111*19cfd5c0SLennert Buytenhek return 0; 112*19cfd5c0SLennert Buytenhek return -1; 113*19cfd5c0SLennert Buytenhek } 114*19cfd5c0SLennert Buytenhek 115*19cfd5c0SLennert Buytenhek printk(KERN_INFO "unknown MPP type %d\n", type); 116*19cfd5c0SLennert Buytenhek 117*19cfd5c0SLennert Buytenhek return -1; 118*19cfd5c0SLennert Buytenhek } 119*19cfd5c0SLennert Buytenhek 120*19cfd5c0SLennert Buytenhek void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode) 121*19cfd5c0SLennert Buytenhek { 122*19cfd5c0SLennert Buytenhek u32 mpp_0_7_ctrl = readl(MPP_0_7_CTRL); 123*19cfd5c0SLennert Buytenhek u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL); 124*19cfd5c0SLennert Buytenhek u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL); 125*19cfd5c0SLennert Buytenhek 126*19cfd5c0SLennert Buytenhek while (mode->mpp >= 0) { 127*19cfd5c0SLennert Buytenhek u32 *reg; 128*19cfd5c0SLennert Buytenhek int num_type; 129*19cfd5c0SLennert Buytenhek int shift; 130*19cfd5c0SLennert Buytenhek 131*19cfd5c0SLennert Buytenhek if (mode->mpp >= 0 && mode->mpp <= 7) 132*19cfd5c0SLennert Buytenhek reg = &mpp_0_7_ctrl; 133*19cfd5c0SLennert Buytenhek else if (mode->mpp >= 8 && mode->mpp <= 15) 134*19cfd5c0SLennert Buytenhek reg = &mpp_8_15_ctrl; 135*19cfd5c0SLennert Buytenhek else if (mode->mpp >= 16 && mode->mpp <= 19) 136*19cfd5c0SLennert Buytenhek reg = &mpp_16_19_ctrl; 137*19cfd5c0SLennert Buytenhek else { 138*19cfd5c0SLennert Buytenhek printk(KERN_ERR "orion5x_mpp_conf: invalid MPP " 139*19cfd5c0SLennert Buytenhek "(%d)\n", mode->mpp); 140*19cfd5c0SLennert Buytenhek continue; 141*19cfd5c0SLennert Buytenhek } 142*19cfd5c0SLennert Buytenhek 143*19cfd5c0SLennert Buytenhek num_type = determine_type_encoding(mode->mpp, mode->type); 144*19cfd5c0SLennert Buytenhek if (num_type < 0) { 145*19cfd5c0SLennert Buytenhek printk(KERN_ERR "orion5x_mpp_conf: invalid MPP " 146*19cfd5c0SLennert Buytenhek "combination (%d, %d)\n", mode->mpp, 147*19cfd5c0SLennert Buytenhek mode->type); 148*19cfd5c0SLennert Buytenhek continue; 149*19cfd5c0SLennert Buytenhek } 150*19cfd5c0SLennert Buytenhek 151*19cfd5c0SLennert Buytenhek shift = (mode->mpp & 7) << 2; 152*19cfd5c0SLennert Buytenhek *reg &= ~(0xf << shift); 153*19cfd5c0SLennert Buytenhek *reg |= (num_type & 0xf) << shift; 154*19cfd5c0SLennert Buytenhek 155*19cfd5c0SLennert Buytenhek orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO)); 156*19cfd5c0SLennert Buytenhek 157*19cfd5c0SLennert Buytenhek mode++; 158*19cfd5c0SLennert Buytenhek } 159*19cfd5c0SLennert Buytenhek 160*19cfd5c0SLennert Buytenhek writel(mpp_0_7_ctrl, MPP_0_7_CTRL); 161*19cfd5c0SLennert Buytenhek writel(mpp_8_15_ctrl, MPP_8_15_CTRL); 162*19cfd5c0SLennert Buytenhek writel(mpp_16_19_ctrl, MPP_16_19_CTRL); 163*19cfd5c0SLennert Buytenhek } 164