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