linux/arch/cris/arch-v10/kernel/io_interface_mux.c
<<
>>
Prefs
   1/* IO interface mux allocator for ETRAX100LX.
   2 * Copyright 2004, Axis Communications AB
   3 * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
   4 */
   5
   6
   7/* C.f. ETRAX100LX Designer's Reference 20.9 */
   8
   9#include <linux/kernel.h>
  10#include <linux/slab.h>
  11#include <linux/errno.h>
  12#include <linux/module.h>
  13#include <linux/init.h>
  14
  15#include <asm/arch/svinto.h>
  16#include <asm/io.h>
  17#include <asm/arch/io_interface_mux.h>
  18
  19
  20#define DBG(s)
  21
  22/* Macro to access ETRAX 100 registers */
  23#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
  24                                          IO_STATE_(reg##_, field##_, _##val)
  25
  26enum io_if_group {
  27        group_a = (1<<0),
  28        group_b = (1<<1),
  29        group_c = (1<<2),
  30        group_d = (1<<3),
  31        group_e = (1<<4),
  32        group_f = (1<<5)
  33};
  34
  35struct watcher
  36{
  37        void (*notify)(const unsigned int gpio_in_available,
  38                       const unsigned int gpio_out_available,
  39                       const unsigned char pa_available,
  40                       const unsigned char pb_available);
  41        struct watcher *next;
  42};
  43
  44
  45struct if_group
  46{
  47        enum io_if_group        group;
  48        unsigned char           used;
  49        enum cris_io_interface  owner;
  50};
  51
  52
  53struct interface
  54{
  55        enum cris_io_interface   ioif;
  56        unsigned char            groups;
  57        unsigned char            used;
  58        char                    *owner;
  59        unsigned int             gpio_g_in;
  60        unsigned int             gpio_g_out;
  61        unsigned char            gpio_b;
  62};
  63
  64static struct if_group if_groups[6] = {
  65        {
  66                .group = group_a,
  67                .used = 0,
  68        },
  69        {
  70                .group = group_b,
  71                .used = 0,
  72        },
  73        {
  74                .group = group_c,
  75                .used = 0,
  76        },
  77        {
  78                .group = group_d,
  79                .used = 0,
  80        },
  81        {
  82                .group = group_e,
  83                .used = 0,
  84        },
  85        {
  86                .group = group_f,
  87                .used = 0,
  88        }
  89};
  90
  91/* The order in the array must match the order of enum
  92 * cris_io_interface in io_interface_mux.h */
  93static struct interface interfaces[] = {
  94        /* Begin Non-multiplexed interfaces */
  95        {
  96                .ioif = if_eth,
  97                .groups = 0,
  98                .gpio_g_in = 0,
  99                .gpio_g_out = 0,
 100                .gpio_b = 0
 101        },
 102        {
 103                .ioif = if_serial_0,
 104                .groups = 0,
 105                .gpio_g_in = 0,
 106                .gpio_g_out = 0,
 107                .gpio_b = 0
 108        },
 109        /* End Non-multiplexed interfaces */
 110        {
 111                .ioif = if_serial_1,
 112                .groups = group_e,
 113                .gpio_g_in =  0x00000000,
 114                .gpio_g_out = 0x00000000,
 115                .gpio_b = 0x00
 116        },
 117        {
 118                .ioif = if_serial_2,
 119                .groups = group_b,
 120                .gpio_g_in =  0x000000c0,
 121                .gpio_g_out = 0x000000c0,
 122                .gpio_b = 0x00
 123        },
 124        {
 125                .ioif = if_serial_3,
 126                .groups = group_c,
 127                .gpio_g_in =  0xc0000000,
 128                .gpio_g_out = 0xc0000000,
 129                .gpio_b = 0x00
 130        },
 131        {
 132                .ioif = if_sync_serial_1,
 133                .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
 134                                               can be used simultaneously */
 135                .gpio_g_in =  0x00000000,
 136                .gpio_g_out = 0x00000000,
 137                .gpio_b = 0x10
 138        },
 139        {
 140                .ioif = if_sync_serial_3,
 141                .groups = group_c | group_f,
 142                .gpio_g_in =  0xc0000000,
 143                .gpio_g_out = 0xc0000000,
 144                .gpio_b = 0x80
 145        },
 146        {
 147                .ioif = if_shared_ram,
 148                .groups = group_a,
 149                .gpio_g_in =  0x0000ff3e,
 150                .gpio_g_out = 0x0000ff38,
 151                .gpio_b = 0x00
 152        },
 153        {
 154                .ioif = if_shared_ram_w,
 155                .groups = group_a | group_d,
 156                .gpio_g_in =  0x00ffff3e,
 157                .gpio_g_out = 0x00ffff38,
 158                .gpio_b = 0x00
 159        },
 160        {
 161                .ioif = if_par_0,
 162                .groups = group_a,
 163                .gpio_g_in =  0x0000ff3e,
 164                .gpio_g_out = 0x0000ff3e,
 165                .gpio_b = 0x00
 166        },
 167        {
 168                .ioif = if_par_1,
 169                .groups = group_d,
 170                .gpio_g_in =  0x3eff0000,
 171                .gpio_g_out = 0x3eff0000,
 172                .gpio_b = 0x00
 173        },
 174        {
 175                .ioif = if_par_w,
 176                .groups = group_a | group_d,
 177                .gpio_g_in =  0x00ffff3e,
 178                .gpio_g_out = 0x00ffff3e,
 179                .gpio_b = 0x00
 180        },
 181        {
 182                .ioif = if_scsi8_0,
 183                .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
 184                                                          can be used simultaneously */
 185                .gpio_g_in =  0x0000ffff,
 186                .gpio_g_out = 0x0000ffff,
 187                .gpio_b = 0x10
 188        },
 189        {
 190                .ioif = if_scsi8_1,
 191                .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
 192                                                          can be used simultaneously */
 193                .gpio_g_in =  0xffff0000,
 194                .gpio_g_out = 0xffff0000,
 195                .gpio_b = 0x80
 196        },
 197        {
 198                .ioif = if_scsi_w,
 199                .groups = group_a | group_b | group_d | group_f,
 200                .gpio_g_in =  0x01ffffff,
 201                .gpio_g_out = 0x07ffffff,
 202                .gpio_b = 0x80
 203        },
 204        {
 205                .ioif = if_ata,
 206                .groups = group_a | group_b | group_c | group_d,
 207                .gpio_g_in =  0xf9ffffff,
 208                .gpio_g_out = 0xffffffff,
 209                .gpio_b = 0x80
 210        },
 211        {
 212                .ioif = if_csp,
 213                .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
 214                .gpio_g_in =  0x00000000,
 215                .gpio_g_out = 0x00000000,
 216                .gpio_b = 0xfc
 217        },
 218        {
 219                .ioif = if_i2c,
 220                .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
 221                .gpio_g_in =  0x00000000,
 222                .gpio_g_out = 0x00000000,
 223                .gpio_b = 0x03
 224        },
 225        {
 226                .ioif = if_usb_1,
 227                .groups = group_e | group_f,
 228                .gpio_g_in =  0x00000000,
 229                .gpio_g_out = 0x00000000,
 230                .gpio_b = 0x2c
 231        },
 232        {
 233                .ioif = if_usb_2,
 234                .groups = group_d,
 235                .gpio_g_in =  0x0e000000,
 236                .gpio_g_out = 0x3c000000,
 237                .gpio_b = 0x00
 238        },
 239        /* GPIO pins */
 240        {
 241                .ioif = if_gpio_grp_a,
 242                .groups = group_a,
 243                .gpio_g_in =  0x0000ff3f,
 244                .gpio_g_out = 0x0000ff3f,
 245                .gpio_b = 0x00
 246        },
 247        {
 248                .ioif = if_gpio_grp_b,
 249                .groups = group_b,
 250                .gpio_g_in =  0x000000c0,
 251                .gpio_g_out = 0x000000c0,
 252                .gpio_b = 0x00
 253        },
 254        {
 255                .ioif = if_gpio_grp_c,
 256                .groups = group_c,
 257                .gpio_g_in =  0xc0000000,
 258                .gpio_g_out = 0xc0000000,
 259                .gpio_b = 0x00
 260        },
 261        {
 262                .ioif = if_gpio_grp_d,
 263                .groups = group_d,
 264                .gpio_g_in =  0x3fff0000,
 265                .gpio_g_out = 0x3fff0000,
 266                .gpio_b = 0x00
 267        },
 268        {
 269                .ioif = if_gpio_grp_e,
 270                .groups = group_e,
 271                .gpio_g_in =  0x00000000,
 272                .gpio_g_out = 0x00000000,
 273                .gpio_b = 0x00
 274        },
 275        {
 276                .ioif = if_gpio_grp_f,
 277                .groups = group_f,
 278                .gpio_g_in =  0x00000000,
 279                .gpio_g_out = 0x00000000,
 280                .gpio_b = 0xff
 281        }
 282        /* Array end */
 283};
 284
 285static struct watcher *watchers = NULL;
 286
 287static unsigned int gpio_in_pins =  0xffffffff;
 288static unsigned int gpio_out_pins = 0xffffffff;
 289static unsigned char gpio_pb_pins = 0xff;
 290static unsigned char gpio_pa_pins = 0xff;
 291
 292static enum cris_io_interface gpio_pa_owners[8];
 293static enum cris_io_interface gpio_pb_owners[8];
 294static enum cris_io_interface gpio_pg_owners[32];
 295
 296static int cris_io_interface_init(void);
 297
 298static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group)
 299{
 300        return (groups & ~group->group);
 301}
 302
 303
 304static struct if_group *get_group(const unsigned char groups)
 305{
 306        int i;
 307        for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
 308                if (groups & if_groups[i].group) {
 309                        return &if_groups[i];
 310                }
 311        }
 312        return NULL;
 313}
 314
 315
 316static void notify_watchers(void)
 317{
 318        struct watcher *w = watchers;
 319
 320        DBG(printk("io_interface_mux: notifying watchers\n"));
 321
 322        while (NULL != w) {
 323                w->notify((const unsigned int)gpio_in_pins,
 324                          (const unsigned int)gpio_out_pins,
 325                          (const unsigned char)gpio_pa_pins,
 326                          (const unsigned char)gpio_pb_pins);
 327                w = w->next;
 328        }
 329}
 330
 331
 332int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id)
 333{
 334        int set_gen_config = 0;
 335        int set_gen_config_ii = 0;
 336        unsigned long int gens;
 337        unsigned long int gens_ii;
 338        struct if_group *grp;
 339        unsigned char group_set;
 340        unsigned long flags;
 341
 342        (void)cris_io_interface_init();
 343
 344        DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
 345
 346        if ((ioif >= if_max_interfaces) || (ioif < 0)) {
 347                printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
 348                       ioif,
 349                       device_id);
 350                return -EINVAL;
 351        }
 352
 353        local_irq_save(flags);
 354
 355        if (interfaces[ioif].used) {
 356                local_irq_restore(flags);
 357                printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
 358                       device_id,
 359                       interfaces[ioif].owner);
 360                return -EBUSY;
 361        }
 362
 363        /* Check that all required groups are free before allocating, */
 364        group_set = interfaces[ioif].groups;
 365        while (NULL != (grp = get_group(group_set))) {
 366                if (grp->used) {
 367                        if (grp->group == group_f) {
 368                                if ((if_sync_serial_1 ==  ioif) ||
 369                                    (if_sync_serial_3 ==  ioif)) {
 370                                        if ((grp->owner != if_sync_serial_1) &&
 371                                            (grp->owner != if_sync_serial_3)) {
 372                                                local_irq_restore(flags);
 373                                                return -EBUSY;
 374                                        }
 375                                } else if ((if_scsi8_0 == ioif) ||
 376                                           (if_scsi8_1 == ioif)) {
 377                                        if ((grp->owner != if_scsi8_0) &&
 378                                            (grp->owner != if_scsi8_1)) {
 379                                                local_irq_restore(flags);
 380                                                return -EBUSY;
 381                                        }
 382                                }
 383                        } else {
 384                                local_irq_restore(flags);
 385                                return -EBUSY;
 386                        }
 387                }
 388                group_set = clear_group_from_set(group_set, grp);
 389        }
 390
 391        /* Are the required GPIO pins available too? */
 392        if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
 393            ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
 394            ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
 395                printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
 396                       ioif);
 397                return -EBUSY;
 398        }
 399
 400        /* All needed I/O pins and pin groups are free, allocate. */
 401        group_set = interfaces[ioif].groups;
 402        while (NULL != (grp = get_group(group_set))) {
 403                grp->used = 1;
 404                grp->owner = ioif;
 405                group_set = clear_group_from_set(group_set, grp);
 406        }
 407
 408        gens = genconfig_shadow;
 409        gens_ii = gen_config_ii_shadow;
 410
 411        set_gen_config = 1;
 412        switch (ioif)
 413        {
 414        /* Begin Non-multiplexed interfaces */
 415        case if_eth:
 416                /* fall through */
 417        case if_serial_0:
 418                set_gen_config = 0;
 419                break;
 420        /* End Non-multiplexed interfaces */
 421        case if_serial_1:
 422                set_gen_config_ii = 1;
 423                SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);
 424                break;
 425        case if_serial_2:
 426                SETS(gens, R_GEN_CONFIG, ser2, select);
 427                break;
 428        case if_serial_3:
 429                SETS(gens, R_GEN_CONFIG, ser3, select);
 430                set_gen_config_ii = 1;
 431                SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);
 432                break;
 433        case if_sync_serial_1:
 434                set_gen_config_ii = 1;
 435                SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);
 436                break;
 437        case if_sync_serial_3:
 438                SETS(gens, R_GEN_CONFIG, ser3, select);
 439                set_gen_config_ii = 1;
 440                SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);
 441                break;
 442        case if_shared_ram:
 443                SETS(gens, R_GEN_CONFIG, mio, select);
 444                break;
 445        case if_shared_ram_w:
 446                SETS(gens, R_GEN_CONFIG, mio_w, select);
 447                break;
 448        case if_par_0:
 449                SETS(gens, R_GEN_CONFIG, par0, select);
 450                break;
 451        case if_par_1:
 452                SETS(gens, R_GEN_CONFIG, par1, select);
 453                break;
 454        case if_par_w:
 455                SETS(gens, R_GEN_CONFIG, par0, select);
 456                SETS(gens, R_GEN_CONFIG, par_w, select);
 457                break;
 458        case if_scsi8_0:
 459                SETS(gens, R_GEN_CONFIG, scsi0, select);
 460                break;
 461        case if_scsi8_1:
 462                SETS(gens, R_GEN_CONFIG, scsi1, select);
 463                break;
 464        case if_scsi_w:
 465                SETS(gens, R_GEN_CONFIG, scsi0, select);
 466                SETS(gens, R_GEN_CONFIG, scsi0w, select);
 467                break;
 468        case if_ata:
 469                SETS(gens, R_GEN_CONFIG, ata, select);
 470                break;
 471        case if_csp:
 472                /* fall through */
 473        case if_i2c:
 474                set_gen_config = 0;
 475                break;
 476        case if_usb_1:
 477                SETS(gens, R_GEN_CONFIG, usb1, select);
 478                break;
 479        case if_usb_2:
 480                SETS(gens, R_GEN_CONFIG, usb2, select);
 481                break;
 482        case if_gpio_grp_a:
 483                /* GPIO groups are only accounted, don't do configuration changes. */
 484                /* fall through */
 485        case if_gpio_grp_b:
 486                /* fall through */
 487        case if_gpio_grp_c:
 488                /* fall through */
 489        case if_gpio_grp_d:
 490                /* fall through */
 491        case if_gpio_grp_e:
 492                /* fall through */
 493        case if_gpio_grp_f:
 494                set_gen_config = 0;
 495                break;
 496        default:
 497                panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
 498                      ioif,
 499                      device_id);
 500        }
 501
 502        interfaces[ioif].used = 1;
 503        interfaces[ioif].owner = (char*)device_id;
 504
 505        if (set_gen_config) {
 506                volatile int i;
 507                genconfig_shadow = gens;
 508                *R_GEN_CONFIG = genconfig_shadow;
 509                /* Wait 12 cycles before doing any DMA command */
 510                for(i = 6; i > 0; i--)
 511                        nop();
 512        }
 513        if (set_gen_config_ii) {
 514                gen_config_ii_shadow = gens_ii;
 515                *R_GEN_CONFIG_II = gen_config_ii_shadow;
 516        }
 517
 518        DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 519                   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
 520        DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 521                   interfaces[ioif].gpio_g_in,
 522                   interfaces[ioif].gpio_g_out,
 523                   interfaces[ioif].gpio_b));
 524
 525        gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
 526        gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
 527        gpio_pb_pins &= ~interfaces[ioif].gpio_b;
 528
 529        DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 530                   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
 531
 532        local_irq_restore(flags);
 533
 534        notify_watchers();
 535
 536        return 0;
 537}
 538
 539
 540void cris_free_io_interface(enum cris_io_interface ioif)
 541{
 542        struct if_group *grp;
 543        unsigned char group_set;
 544        unsigned long flags;
 545
 546        (void)cris_io_interface_init();
 547
 548        if ((ioif >= if_max_interfaces) || (ioif < 0)) {
 549                printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n",
 550                       ioif);
 551                return;
 552        }
 553        local_irq_save(flags);
 554        if (!interfaces[ioif].used) {
 555                printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n",
 556                       ioif);
 557                local_irq_restore(flags);
 558                return;
 559        }
 560        group_set = interfaces[ioif].groups;
 561        while (NULL != (grp = get_group(group_set))) {
 562                if (grp->group == group_f) {
 563                        switch (ioif)
 564                        {
 565                        case if_sync_serial_1:
 566                                if ((grp->owner == if_sync_serial_1) &&
 567                                    interfaces[if_sync_serial_3].used) {
 568                                        grp->owner = if_sync_serial_3;
 569                                } else
 570                                        grp->used = 0;
 571                                break;
 572                        case if_sync_serial_3:
 573                                if ((grp->owner == if_sync_serial_3) &&
 574                                    interfaces[if_sync_serial_1].used) {
 575                                        grp->owner = if_sync_serial_1;
 576                                } else
 577                                        grp->used = 0;
 578                                break;
 579                        case if_scsi8_0:
 580                                if ((grp->owner == if_scsi8_0) &&
 581                                    interfaces[if_scsi8_1].used) {
 582                                        grp->owner = if_scsi8_1;
 583                                } else
 584                                        grp->used = 0;
 585                                break;
 586                        case if_scsi8_1:
 587                                if ((grp->owner == if_scsi8_1) &&
 588                                    interfaces[if_scsi8_0].used) {
 589                                        grp->owner = if_scsi8_0;
 590                                } else
 591                                        grp->used = 0;
 592                                break;
 593                        default:
 594                                grp->used = 0;
 595                        }
 596                } else {
 597                        grp->used = 0;
 598                }
 599                group_set = clear_group_from_set(group_set, grp);
 600        }
 601        interfaces[ioif].used = 0;
 602        interfaces[ioif].owner = NULL;
 603
 604        DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 605                   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
 606        DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 607                   interfaces[ioif].gpio_g_in,
 608                   interfaces[ioif].gpio_g_out,
 609                   interfaces[ioif].gpio_b));
 610
 611        gpio_in_pins |= interfaces[ioif].gpio_g_in;
 612        gpio_out_pins |= interfaces[ioif].gpio_g_out;
 613        gpio_pb_pins |= interfaces[ioif].gpio_b;
 614
 615        DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
 616                   gpio_in_pins, gpio_out_pins, gpio_pb_pins));
 617
 618        local_irq_restore(flags);
 619
 620        notify_watchers();
 621}
 622
 623/* Create a bitmask from bit 0 (inclusive) to bit stop_bit
 624   (non-inclusive).  stop_bit == 0 returns 0x0 */
 625static inline unsigned int create_mask(const unsigned stop_bit)
 626{
 627        /* Avoid overflow */
 628        if (stop_bit >= 32) {
 629                return 0xffffffff;
 630        }
 631        return (1<<stop_bit)-1;
 632}
 633
 634
 635/* port can be 'a', 'b' or 'g' */
 636int cris_io_interface_allocate_pins(const enum cris_io_interface ioif,
 637                                    const char port,
 638                                    const unsigned start_bit,
 639                                    const unsigned stop_bit)
 640{
 641        unsigned int i;
 642        unsigned int mask = 0;
 643        unsigned int tmp_mask;
 644        unsigned long int flags;
 645        enum cris_io_interface *owners;
 646
 647        (void)cris_io_interface_init();
 648
 649        DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n",
 650                   ioif, port, start_bit, stop_bit));
 651
 652        if (!((start_bit <= stop_bit) &&
 653              ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
 654               ((port == 'g') && (stop_bit < 32))))) {
 655                return -EINVAL;
 656        }
 657
 658        mask = create_mask(stop_bit + 1);
 659        tmp_mask = create_mask(start_bit);
 660        mask &= ~tmp_mask;
 661
 662        DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n",
 663                   port, start_bit, stop_bit, mask));
 664
 665        local_irq_save(flags);
 666
 667        switch (port) {
 668        case 'a':
 669                if ((gpio_pa_pins & mask) != mask) {
 670                        local_irq_restore(flags);
 671                        return -EBUSY;
 672                }
 673                owners = gpio_pa_owners;
 674                gpio_pa_pins &= ~mask;
 675                break;
 676        case 'b':
 677                if ((gpio_pb_pins & mask) != mask) {
 678                        local_irq_restore(flags);
 679                        return -EBUSY;
 680                }
 681                owners = gpio_pb_owners;
 682                gpio_pb_pins &= ~mask;
 683                break;
 684        case 'g':
 685                if (((gpio_in_pins & mask) != mask) ||
 686                    ((gpio_out_pins & mask) != mask)) {
 687                        local_irq_restore(flags);
 688                        return -EBUSY;
 689                }
 690                owners = gpio_pg_owners;
 691                gpio_in_pins &= ~mask;
 692                gpio_out_pins &= ~mask;
 693                break;
 694        default:
 695                local_irq_restore(flags);
 696                return -EINVAL;
 697        }
 698
 699        for (i = start_bit; i <= stop_bit; i++) {
 700                owners[i] = ioif;
 701        }
 702        local_irq_restore(flags);
 703
 704        notify_watchers();
 705        return 0;
 706}
 707
 708
 709/* port can be 'a', 'b' or 'g' */
 710int cris_io_interface_free_pins(const enum cris_io_interface ioif,
 711                                const char port,
 712                                const unsigned start_bit,
 713                                const unsigned stop_bit)
 714{
 715        unsigned int i;
 716        unsigned int mask = 0;
 717        unsigned int tmp_mask;
 718        unsigned long int flags;
 719        enum cris_io_interface *owners;
 720
 721        (void)cris_io_interface_init();
 722
 723        if (!((start_bit <= stop_bit) &&
 724              ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) ||
 725               ((port == 'g') && (stop_bit < 32))))) {
 726                return -EINVAL;
 727        }
 728
 729        mask = create_mask(stop_bit + 1);
 730        tmp_mask = create_mask(start_bit);
 731        mask &= ~tmp_mask;
 732
 733        DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n",
 734                   port, start_bit, stop_bit, mask));
 735
 736        local_irq_save(flags);
 737
 738        switch (port) {
 739        case 'a':
 740                if ((~gpio_pa_pins & mask) != mask) {
 741                        local_irq_restore(flags);
 742                        printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
 743                }
 744                owners = gpio_pa_owners;
 745                break;
 746        case 'b':
 747                if ((~gpio_pb_pins & mask) != mask) {
 748                        local_irq_restore(flags);
 749                        printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
 750                }
 751                owners = gpio_pb_owners;
 752                break;
 753        case 'g':
 754                if (((~gpio_in_pins & mask) != mask) ||
 755                    ((~gpio_out_pins & mask) != mask)) {
 756                        local_irq_restore(flags);
 757                        printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins");
 758                }
 759                owners = gpio_pg_owners;
 760                break;
 761        default:
 762                owners = NULL; /* Cannot happen. Shut up, gcc! */
 763        }
 764
 765        for (i = start_bit; i <= stop_bit; i++) {
 766                if (owners[i] != ioif) {
 767                        printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins");
 768                }
 769        }
 770
 771        /* All was ok, change data. */
 772        switch (port) {
 773        case 'a':
 774                gpio_pa_pins |= mask;
 775                break;
 776        case 'b':
 777                gpio_pb_pins |= mask;
 778                break;
 779        case 'g':
 780                gpio_in_pins |= mask;
 781                gpio_out_pins |= mask;
 782                break;
 783        }
 784
 785        for (i = start_bit; i <= stop_bit; i++) {
 786                owners[i] = if_unclaimed;
 787        }
 788        local_irq_restore(flags);
 789        notify_watchers();
 790
 791        return 0;
 792}
 793
 794
 795int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available,
 796                                                      const unsigned int gpio_out_available,
 797                                                      const unsigned char pa_available,
 798                                                      const unsigned char pb_available))
 799{
 800        struct watcher *w;
 801
 802        (void)cris_io_interface_init();
 803
 804        if (NULL == notify) {
 805                return -EINVAL;
 806        }
 807        w = kmalloc(sizeof(*w), GFP_KERNEL);
 808        if (!w) {
 809                return -ENOMEM;
 810        }
 811        w->notify = notify;
 812        w->next = watchers;
 813        watchers = w;
 814
 815        w->notify((const unsigned int)gpio_in_pins,
 816                  (const unsigned int)gpio_out_pins,
 817                  (const unsigned char)gpio_pa_pins,
 818                  (const unsigned char)gpio_pb_pins);
 819
 820        return 0;
 821}
 822
 823void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available,
 824                                                     const unsigned int gpio_out_available,
 825                                                     const unsigned char pa_available,
 826                                                     const unsigned char pb_available))
 827{
 828        struct watcher *w = watchers, *prev = NULL;
 829
 830        (void)cris_io_interface_init();
 831
 832        while ((NULL != w) && (w->notify != notify)){
 833                prev = w;
 834                w = w->next;
 835        }
 836        if (NULL != w) {
 837                if (NULL != prev) {
 838                        prev->next = w->next;
 839                } else {
 840                        watchers = w->next;
 841                }
 842                kfree(w);
 843                return;
 844        }
 845        printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify);
 846}
 847
 848
 849static int cris_io_interface_init(void)
 850{
 851        static int first = 1;
 852        int i;
 853
 854        if (!first) {
 855                return 0;
 856        }
 857        first = 0;
 858
 859        for (i = 0; i<8; i++) {
 860                gpio_pa_owners[i] = if_unclaimed;
 861                gpio_pb_owners[i] = if_unclaimed;
 862                gpio_pg_owners[i] = if_unclaimed;
 863        }
 864        for (; i<32; i++) {
 865                gpio_pg_owners[i] = if_unclaimed;
 866        }
 867        return 0;
 868}
 869
 870
 871module_init(cris_io_interface_init);
 872
 873
 874EXPORT_SYMBOL(cris_request_io_interface);
 875EXPORT_SYMBOL(cris_free_io_interface);
 876EXPORT_SYMBOL(cris_io_interface_allocate_pins);
 877EXPORT_SYMBOL(cris_io_interface_free_pins);
 878EXPORT_SYMBOL(cris_io_interface_register_watcher);
 879EXPORT_SYMBOL(cris_io_interface_delete_watcher);
 880
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.