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