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