1/* 2 * Allocator for I/O pins. All pins are allocated to GPIO at bootup. 3 * Unassigned pins and GPIO pins can be allocated to a fixed interface 4 * or the I/O processor instead. 5 * 6 * Copyright (c) 2004-2007 Axis Communications AB. 7 */ 8 9#include <linux/init.h> 10#include <linux/errno.h> 11#include <linux/kernel.h> 12#include <linux/string.h> 13#include <linux/spinlock.h> 14#include <hwregs/reg_map.h> 15#include <hwregs/reg_rdwr.h> 16#include <pinmux.h> 17#include <hwregs/pinmux_defs.h> 18 19#undef DEBUG 20 21#define PORT_PINS 18 22#define PORTS 4 23 24static char pins[PORTS][PORT_PINS]; 25static DEFINE_SPINLOCK(pinmux_lock); 26 27static void crisv32_pinmux_set(int port); 28 29static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin, 30 enum pin_mode mode) 31{ 32 int i; 33 34 for (i = first_pin; i <= last_pin; i++) { 35 if ((pins[port][i] != pinmux_none) 36 && (pins[port][i] != pinmux_gpio) 37 && (pins[port][i] != mode)) { 38#ifdef DEBUG 39 panic("Pinmux alloc failed!\n"); 40#endif 41 return -EPERM; 42 } 43 } 44 45 for (i = first_pin; i <= last_pin; i++) 46 pins[port][i] = mode; 47 48 crisv32_pinmux_set(port); 49 50 return 0; 51} 52 53static int crisv32_pinmux_init(void) 54{ 55 static int initialized; 56 57 if (!initialized) { 58 reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa); 59 initialized = 1; 60 REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0); 61 pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 = 62 pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes; 63 REG_WR(pinmux, regi_pinmux, rw_pa, pa); 64 __crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio); 65 __crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio); 66 __crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio); 67 __crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio); 68 } 69 70 return 0; 71} 72 73int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, 74 enum pin_mode mode) 75{ 76 unsigned long flags; 77 int ret; 78 79 crisv32_pinmux_init(); 80 81 if (port > PORTS || port < 0) 82 return -EINVAL; 83 84 spin_lock_irqsave(&pinmux_lock, flags); 85 86 ret = __crisv32_pinmux_alloc(port, first_pin, last_pin, mode); 87 88 spin_unlock_irqrestore(&pinmux_lock, flags); 89 90 return ret; 91} 92 93int crisv32_pinmux_alloc_fixed(enum fixed_function function) 94{ 95 int ret = -EINVAL; 96 char saved[sizeof pins]; 97 unsigned long flags; 98 reg_pinmux_rw_hwprot hwprot; 99 100 spin_lock_irqsave(&pinmux_lock, flags); 101 102 /* Save internal data for recovery */ 103 memcpy(saved, pins, sizeof pins); 104 105 crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */ 106 107 hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); 108 109 switch (function) { 110 case pinmux_ser1: 111 ret = __crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed); 112 hwprot.ser1 = regk_pinmux_yes; 113 break; 114 case pinmux_ser2: 115 ret = __crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed); 116 hwprot.ser2 = regk_pinmux_yes; 117 break; 118 case pinmux_ser3: 119 ret = __crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed); 120 hwprot.ser3 = regk_pinmux_yes; 121 break; 122 case pinmux_sser0: 123 ret = __crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed); 124 ret |= __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); 125 hwprot.sser0 = regk_pinmux_yes; 126 break; 127 case pinmux_sser1: 128 ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); 129 hwprot.sser1 = regk_pinmux_yes; 130 break; 131 case pinmux_ata0: 132 ret = __crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed); 133 ret |= __crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed); 134 hwprot.ata0 = regk_pinmux_yes; 135 break; 136 case pinmux_ata1: 137 ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed); 138 ret |= __crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed); 139 hwprot.ata1 = regk_pinmux_yes; 140 break; 141 case pinmux_ata2: 142 ret = __crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed); 143 ret |= __crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed); 144 hwprot.ata2 = regk_pinmux_yes; 145 break; 146 case pinmux_ata3: 147 ret = __crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed); 148 ret |= __crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed); 149 hwprot.ata2 = regk_pinmux_yes; 150 break; 151 case pinmux_ata: 152 ret = __crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed); 153 ret |= __crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed); 154 hwprot.ata = regk_pinmux_yes; 155 break; 156 case pinmux_eth1: 157 ret = __crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed); 158 hwprot.eth1 = regk_pinmux_yes; 159 hwprot.eth1_mgm = regk_pinmux_yes; 160 break; 161 case pinmux_timer: 162 ret = __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed); 163 hwprot.timer = regk_pinmux_yes; 164 spin_unlock_irqrestore(&pinmux_lock, flags); 165 return ret; 166 } 167 168 if (!ret) 169 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot); 170 else 171 memcpy(pins, saved, sizeof pins); 172 173 spin_unlock_irqrestore(&pinmux_lock, flags); 174 175 return ret; 176} 177 178void crisv32_pinmux_set(int port) 179{ 180 int i; 181 int gpio_val = 0; 182 int iop_val = 0; 183 184 for (i = 0; i < PORT_PINS; i++) { 185 if (pins[port][i] == pinmux_gpio) 186 gpio_val |= (1 << i); 187 else if (pins[port][i] == pinmux_iop) 188 iop_val |= (1 << i); 189 } 190 191 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8 * port, 192 gpio_val); 193 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8 * port, 194 iop_val); 195 196#ifdef DEBUG 197 crisv32_pinmux_dump(); 198#endif 199} 200 201static int __crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) 202{ 203 int i; 204 205 for (i = first_pin; i <= last_pin; i++) 206 pins[port][i] = pinmux_none; 207 208 crisv32_pinmux_set(port); 209 return 0; 210} 211 212int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin) 213{ 214 unsigned long flags; 215 216 crisv32_pinmux_init(); 217 218 if (port > PORTS || port < 0) 219 return -EINVAL; 220 221 spin_lock_irqsave(&pinmux_lock, flags); 222 __crisv32_pinmux_dealloc(port, first_pin, last_pin); 223 spin_unlock_irqrestore(&pinmux_lock, flags); 224 225 return 0; 226} 227 228int crisv32_pinmux_dealloc_fixed(enum fixed_function function) 229{ 230 int ret = -EINVAL; 231 char saved[sizeof pins]; 232 unsigned long flags; 233 reg_pinmux_rw_hwprot hwprot; 234 235 spin_lock_irqsave(&pinmux_lock, flags); 236 237 /* Save internal data for recovery */ 238 memcpy(saved, pins, sizeof pins); 239 240 crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */ 241 242 hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); 243 244 switch (function) { 245 case pinmux_ser1: 246 ret = __crisv32_pinmux_dealloc(PORT_C, 4, 7); 247 hwprot.ser1 = regk_pinmux_no; 248 break; 249 case pinmux_ser2: 250 ret = __crisv32_pinmux_dealloc(PORT_C, 8, 11); 251 hwprot.ser2 = regk_pinmux_no; 252 break; 253 case pinmux_ser3: 254 ret = __crisv32_pinmux_dealloc(PORT_C, 12, 15); 255 hwprot.ser3 = regk_pinmux_no; 256 break; 257 case pinmux_sser0: 258 ret = __crisv32_pinmux_dealloc(PORT_C, 0, 3); 259 ret |= __crisv32_pinmux_dealloc(PORT_C, 16, 16); 260 hwprot.sser0 = regk_pinmux_no; 261 break; 262 case pinmux_sser1: 263 ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4); 264 hwprot.sser1 = regk_pinmux_no; 265 break; 266 case pinmux_ata0: 267 ret = __crisv32_pinmux_dealloc(PORT_D, 5, 7); 268 ret |= __crisv32_pinmux_dealloc(PORT_D, 15, 17); 269 hwprot.ata0 = regk_pinmux_no; 270 break; 271 case pinmux_ata1: 272 ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4); 273 ret |= __crisv32_pinmux_dealloc(PORT_E, 17, 17); 274 hwprot.ata1 = regk_pinmux_no; 275 break; 276 case pinmux_ata2: 277 ret = __crisv32_pinmux_dealloc(PORT_C, 11, 15); 278 ret |= __crisv32_pinmux_dealloc(PORT_E, 3, 3); 279 hwprot.ata2 = regk_pinmux_no; 280 break; 281 case pinmux_ata3: 282 ret = __crisv32_pinmux_dealloc(PORT_C, 8, 10); 283 ret |= __crisv32_pinmux_dealloc(PORT_C, 0, 2); 284 hwprot.ata2 = regk_pinmux_no; 285 break; 286 case pinmux_ata: 287 ret = __crisv32_pinmux_dealloc(PORT_B, 0, 15); 288 ret |= __crisv32_pinmux_dealloc(PORT_D, 8, 15); 289 hwprot.ata = regk_pinmux_no; 290 break; 291 case pinmux_eth1: 292 ret = __crisv32_pinmux_dealloc(PORT_E, 0, 17); 293 hwprot.eth1 = regk_pinmux_no; 294 hwprot.eth1_mgm = regk_pinmux_no; 295 break; 296 case pinmux_timer: 297 ret = __crisv32_pinmux_dealloc(PORT_C, 16, 16); 298 hwprot.timer = regk_pinmux_no; 299 spin_unlock_irqrestore(&pinmux_lock, flags); 300 return ret; 301 } 302 303 if (!ret) 304 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot); 305 else 306 memcpy(pins, saved, sizeof pins); 307 308 spin_unlock_irqrestore(&pinmux_lock, flags); 309 310 return ret; 311} 312 313#ifdef DEBUG 314static void crisv32_pinmux_dump(void) 315{ 316 int i, j; 317 318 crisv32_pinmux_init(); 319 320 for (i = 0; i < PORTS; i++) { 321 printk(KERN_DEBUG "Port %c\n", 'B' + i); 322 for (j = 0; j < PORT_PINS; j++) 323 printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]); 324 } 325} 326#endif 327__initcall(crisv32_pinmux_init); 328