linux/drivers/staging/meilhaus/me8200_do.c
<<
>>
Prefs
   1/**
   2 * @file me8200_do.c
   3 *
   4 * @brief ME-8200 digital output subdevice instance.
   5 * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
   6 * @author Guenter Gebhardt
   7 * @author Krzysztof Gantzke    (k.gantzke@meilhaus.de)
   8 */
   9
  10/*
  11 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
  12 *
  13 * This file is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#ifndef __KERNEL__
  29#  define __KERNEL__
  30#endif
  31
  32/*
  33 * Includes
  34 */
  35#include <linux/module.h>
  36
  37#include <linux/slab.h>
  38#include <linux/spinlock.h>
  39#include <linux/interrupt.h>
  40#include <asm/io.h>
  41#include <linux/types.h>
  42#include <linux/version.h>
  43
  44#include "medefines.h"
  45#include "meinternal.h"
  46#include "meerror.h"
  47
  48#include "meids.h"
  49#include "medebug.h"
  50#include "me8200_reg.h"
  51#include "me8200_do_reg.h"
  52#include "me8200_do.h"
  53
  54/*
  55 * Defines
  56 */
  57
  58/*
  59 * Functions
  60 */
  61
  62static int me8200_do_io_irq_start(me_subdevice_t * subdevice,
  63                                  struct file *filep,
  64                                  int channel,
  65                                  int irq_source,
  66                                  int irq_edge, int irq_arg, int flags)
  67{
  68        me8200_do_subdevice_t *instance;
  69        int err = ME_ERRNO_SUCCESS;
  70        uint8_t tmp;
  71        unsigned long status;
  72
  73        if (flags & ~ME_IO_IRQ_START_DIO_BYTE) {
  74                PERROR("Invalid flag specified.\n");
  75                return ME_ERRNO_INVALID_FLAGS;
  76        }
  77
  78        if (channel != 0) {
  79                PERROR("Invalid channel specified.\n");
  80                return ME_ERRNO_INVALID_CHANNEL;
  81        }
  82
  83        if (irq_source != ME_IRQ_SOURCE_DIO_OVER_TEMP) {
  84                PERROR("Invalid interrupt source specified.\n");
  85                return ME_ERRNO_INVALID_IRQ_SOURCE;
  86        }
  87
  88        PDEBUG("executed.\n");
  89
  90        instance = (me8200_do_subdevice_t *) subdevice;
  91
  92        ME_SUBDEVICE_ENTER;
  93
  94        spin_lock_irqsave(&instance->subdevice_lock, status);
  95        spin_lock(instance->irq_mode_lock);
  96        tmp = inb(instance->irq_ctrl_reg);
  97        tmp |=
  98            ME8200_IRQ_MODE_BIT_ENABLE_POWER << (ME8200_IRQ_MODE_POWER_SHIFT *
  99                                                 instance->do_idx);
 100        outb(tmp, instance->irq_ctrl_reg);
 101        PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 102                   instance->irq_ctrl_reg - instance->reg_base, tmp);
 103        spin_unlock(instance->irq_mode_lock);
 104        instance->rised = 0;
 105        spin_unlock_irqrestore(&instance->subdevice_lock, status);
 106
 107        ME_SUBDEVICE_EXIT;
 108
 109        return err;
 110}
 111
 112static int me8200_do_io_irq_wait(me_subdevice_t * subdevice,
 113                                 struct file *filep,
 114                                 int channel,
 115                                 int *irq_count,
 116                                 int *value, int time_out, int flags)
 117{
 118        me8200_do_subdevice_t *instance;
 119        int err = ME_ERRNO_SUCCESS;
 120        long t = 0;
 121        unsigned long cpu_flags;
 122
 123        PDEBUG("executed.\n");
 124
 125        instance = (me8200_do_subdevice_t *) subdevice;
 126
 127        if (flags) {
 128                PERROR("Invalid flag specified.\n");
 129                return ME_ERRNO_INVALID_FLAGS;
 130        }
 131
 132        if (time_out < 0) {
 133                PERROR("Invalid time_out specified.\n");
 134                return ME_ERRNO_INVALID_TIMEOUT;
 135        }
 136
 137        if (time_out) {
 138                t = (time_out * HZ) / 1000;
 139
 140                if (t == 0)
 141                        t = 1;
 142        }
 143
 144        ME_SUBDEVICE_ENTER;
 145
 146        if (instance->rised <= 0) {
 147                instance->rised = 0;
 148
 149                if (time_out) {
 150                        t = wait_event_interruptible_timeout(instance->
 151                                                             wait_queue,
 152                                                             (instance->rised !=
 153                                                              0), t);
 154
 155                        if (t == 0) {
 156                                PERROR
 157                                    ("Wait on external interrupt timed out.\n");
 158                                err = ME_ERRNO_TIMEOUT;
 159                        }
 160                } else {
 161                        wait_event_interruptible(instance->wait_queue,
 162                                                 (instance->rised != 0));
 163                }
 164
 165                if (instance->rised < 0) {
 166                        PERROR("Wait on interrupt aborted by user.\n");
 167                        err = ME_ERRNO_CANCELLED;
 168                }
 169        }
 170
 171        if (signal_pending(current)) {
 172                PERROR("Wait on external interrupt aborted by signal.\n");
 173                err = ME_ERRNO_SIGNAL;
 174        }
 175
 176        spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
 177        instance->rised = 0;
 178        *irq_count = instance->count;
 179        *value = 0;
 180        spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
 181
 182        ME_SUBDEVICE_EXIT;
 183
 184        return err;
 185}
 186
 187static int me8200_do_io_irq_stop(me_subdevice_t * subdevice,
 188                                 struct file *filep, int channel, int flags)
 189{
 190        me8200_do_subdevice_t *instance;
 191        uint8_t tmp;
 192        unsigned long cpu_flags;
 193
 194        PDEBUG("executed.\n");
 195
 196        instance = (me8200_do_subdevice_t *) subdevice;
 197
 198        if (flags) {
 199                PERROR("Invalid flag specified.\n");
 200                return ME_ERRNO_INVALID_FLAGS;
 201        }
 202
 203        ME_SUBDEVICE_ENTER;
 204
 205        spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
 206        spin_lock(instance->irq_mode_lock);
 207        tmp = inb(instance->irq_ctrl_reg);
 208        tmp &=
 209            ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER <<
 210              (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx));
 211        outb(tmp, instance->irq_ctrl_reg);
 212        PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 213                   instance->irq_ctrl_reg - instance->reg_base, tmp);
 214        spin_unlock(instance->irq_mode_lock);
 215        instance->rised = -1;
 216        spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
 217        wake_up_interruptible_all(&instance->wait_queue);
 218
 219        ME_SUBDEVICE_EXIT;
 220
 221        return ME_ERRNO_SUCCESS;
 222}
 223
 224static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice,
 225                                        struct file *filep, int flags)
 226{
 227        me8200_do_subdevice_t *instance;
 228        unsigned long cpu_flags;
 229        uint8_t tmp;
 230
 231        PDEBUG("executed.\n");
 232
 233        instance = (me8200_do_subdevice_t *) subdevice;
 234
 235        if (flags) {
 236                PERROR("Invalid flag specified.\n");
 237                return ME_ERRNO_INVALID_FLAGS;
 238        }
 239
 240        ME_SUBDEVICE_ENTER;
 241
 242        spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
 243        outb(0x00, instance->port_reg);
 244        PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 245                   instance->port_reg - instance->reg_base, 0x00);
 246        spin_lock(instance->irq_mode_lock);
 247        tmp = inb(instance->irq_ctrl_reg);
 248        tmp &=
 249            ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER <<
 250              (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx));
 251        outb(tmp, instance->irq_ctrl_reg);
 252        PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 253                   instance->irq_ctrl_reg - instance->reg_base, tmp);
 254        spin_unlock(instance->irq_mode_lock);
 255        instance->rised = -1;
 256        instance->count = 0;
 257        spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
 258        wake_up_interruptible_all(&instance->wait_queue);
 259
 260        ME_SUBDEVICE_EXIT;
 261
 262        return ME_ERRNO_SUCCESS;
 263}
 264
 265static int me8200_do_io_single_config(me_subdevice_t * subdevice,
 266                                      struct file *filep,
 267                                      int channel,
 268                                      int single_config,
 269                                      int ref,
 270                                      int trig_chan,
 271                                      int trig_type, int trig_edge, int flags)
 272{
 273        me8200_do_subdevice_t *instance;
 274        int err = ME_ERRNO_SUCCESS;
 275        unsigned long status;
 276
 277        PDEBUG("executed.\n");
 278
 279        instance = (me8200_do_subdevice_t *) subdevice;
 280
 281        ME_SUBDEVICE_ENTER;
 282
 283        spin_lock_irqsave(&instance->subdevice_lock, status);
 284        switch (flags) {
 285        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 286        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 287                if (channel == 0) {
 288                        if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 289                        } else {
 290                                PERROR("Invalid byte direction specified.\n");
 291                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 292                        }
 293                } else {
 294                        PERROR("Invalid byte specified.\n");
 295                        err = ME_ERRNO_INVALID_CHANNEL;
 296                }
 297                break;
 298
 299        default:
 300                PERROR("Invalid flags specified.\n");
 301                err = ME_ERRNO_INVALID_FLAGS;
 302        }
 303        spin_unlock_irqrestore(&instance->subdevice_lock, status);
 304
 305        ME_SUBDEVICE_EXIT;
 306
 307        return err;
 308}
 309
 310static int me8200_do_io_single_read(me_subdevice_t * subdevice,
 311                                    struct file *filep,
 312                                    int channel,
 313                                    int *value, int time_out, int flags)
 314{
 315        me8200_do_subdevice_t *instance;
 316        int err = ME_ERRNO_SUCCESS;
 317        unsigned long status;
 318
 319        PDEBUG("executed.\n");
 320
 321        instance = (me8200_do_subdevice_t *) subdevice;
 322
 323        ME_SUBDEVICE_ENTER;
 324
 325        spin_lock_irqsave(&instance->subdevice_lock, status);
 326        switch (flags) {
 327        case ME_IO_SINGLE_TYPE_DIO_BIT:
 328                if ((channel >= 0) && (channel < 8)) {
 329                        *value = inb(instance->port_reg) & (0x1 << channel);
 330                } else {
 331                        PERROR("Invalid bit number specified.\n");
 332                        err = ME_ERRNO_INVALID_CHANNEL;
 333                }
 334                break;
 335
 336        case ME_IO_SINGLE_NO_FLAGS:
 337        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 338                if (channel == 0) {
 339                        *value = inb(instance->port_reg);
 340                } else {
 341                        PERROR("Invalid byte number specified.\n");
 342                        err = ME_ERRNO_INVALID_CHANNEL;
 343                }
 344                break;
 345
 346        default:
 347                PERROR("Invalid flags specified.\n");
 348                err = ME_ERRNO_INVALID_FLAGS;
 349        }
 350        spin_unlock_irqrestore(&instance->subdevice_lock, status);
 351
 352        ME_SUBDEVICE_EXIT;
 353
 354        return err;
 355}
 356
 357static int me8200_do_io_single_write(me_subdevice_t * subdevice,
 358                                     struct file *filep,
 359                                     int channel,
 360                                     int value, int time_out, int flags)
 361{
 362        me8200_do_subdevice_t *instance;
 363        int err = ME_ERRNO_SUCCESS;
 364        uint8_t state;
 365        unsigned long status;
 366
 367        PDEBUG("executed.\n");
 368
 369        instance = (me8200_do_subdevice_t *) subdevice;
 370
 371        ME_SUBDEVICE_ENTER;
 372
 373        spin_lock_irqsave(&instance->subdevice_lock, status);
 374        switch (flags) {
 375        case ME_IO_SINGLE_TYPE_DIO_BIT:
 376                if ((channel >= 0) && (channel < 8)) {
 377                        state = inb(instance->port_reg);
 378                        state =
 379                            value ? (state | (0x1 << channel)) : (state &
 380                                                                  ~(0x1 <<
 381                                                                    channel));
 382                        outb(state, instance->port_reg);
 383                        PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
 384                                   instance->reg_base,
 385                                   instance->port_reg - instance->reg_base,
 386                                   state);
 387                } else {
 388                        PERROR("Invalid bit number specified.\n");
 389                        err = ME_ERRNO_INVALID_CHANNEL;
 390                }
 391                break;
 392
 393        case ME_IO_SINGLE_NO_FLAGS:
 394        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 395                if (channel == 0) {
 396                        outb(value, instance->port_reg);
 397                        PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
 398                                   instance->reg_base,
 399                                   instance->port_reg - instance->reg_base,
 400                                   value);
 401                } else {
 402                        PERROR("Invalid byte number specified.\n");
 403                        err = ME_ERRNO_INVALID_CHANNEL;
 404                }
 405                break;
 406
 407        default:
 408                PERROR("Invalid flags specified.\n");
 409                err = ME_ERRNO_INVALID_FLAGS;
 410        }
 411        spin_unlock_irqrestore(&instance->subdevice_lock, status);
 412
 413        ME_SUBDEVICE_EXIT;
 414
 415        return err;
 416}
 417
 418static int me8200_do_query_number_channels(me_subdevice_t * subdevice,
 419                                           int *number)
 420{
 421        PDEBUG("executed.\n");
 422        *number = 8;
 423        return ME_ERRNO_SUCCESS;
 424}
 425
 426static int me8200_do_query_subdevice_type(me_subdevice_t * subdevice,
 427                                          int *type, int *subtype)
 428{
 429        PDEBUG("executed.\n");
 430        *type = ME_TYPE_DO;
 431        *subtype = ME_SUBTYPE_SINGLE;
 432        return ME_ERRNO_SUCCESS;
 433}
 434
 435static int me8200_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 436{
 437        PDEBUG("executed.\n");
 438        *caps = ME_CAPS_DIO_OVER_TEMP_IRQ;
 439        return ME_ERRNO_SUCCESS;
 440}
 441
 442static void me8200_do_destructor(struct me_subdevice *subdevice)
 443{
 444        me8200_do_subdevice_t *instance;
 445
 446        PDEBUG("executed.\n");
 447
 448        instance = (me8200_do_subdevice_t *) subdevice;
 449
 450        free_irq(instance->irq, (void *)instance);
 451        me_subdevice_deinit(&instance->base);
 452        kfree(instance);
 453}
 454
 455#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
 456static irqreturn_t me8200_do_isr(int irq, void *dev_id)
 457#else
 458static irqreturn_t me8200_do_isr(int irq, void *dev_id, struct pt_regs *regs)
 459#endif
 460{
 461        me8200_do_subdevice_t *instance;
 462        uint16_t ctrl;
 463        uint8_t irq_status;
 464
 465        instance = (me8200_do_subdevice_t *) dev_id;
 466
 467        if (irq != instance->irq) {
 468                PERROR("Incorrect interrupt num: %d.\n", irq);
 469                return IRQ_NONE;
 470        }
 471
 472        irq_status = inb(instance->irq_status_reg);
 473        if (!
 474            (irq_status &
 475             (ME8200_DO_IRQ_STATUS_BIT_ACTIVE << instance->do_idx))) {
 476                PINFO
 477                    ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
 478                     jiffies, __func__, instance->do_idx, irq_status);
 479                return IRQ_NONE;
 480        }
 481
 482        PDEBUG("executed.\n");
 483
 484        spin_lock(&instance->subdevice_lock);
 485        instance->rised = 1;
 486        instance->count++;
 487
 488        spin_lock(instance->irq_mode_lock);
 489        ctrl = inw(instance->irq_ctrl_reg);
 490        ctrl |= ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx;
 491        outw(ctrl, instance->irq_ctrl_reg);
 492        PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 493                   instance->irq_ctrl_reg - instance->reg_base, ctrl);
 494        ctrl &= ~(ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx);
 495        outw(ctrl, instance->irq_ctrl_reg);
 496        PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
 497                   instance->irq_ctrl_reg - instance->reg_base, ctrl);
 498        spin_unlock(instance->irq_mode_lock);
 499        spin_unlock(&instance->subdevice_lock);
 500        wake_up_interruptible_all(&instance->wait_queue);
 501
 502        return IRQ_HANDLED;
 503}
 504
 505me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base,
 506                                             unsigned int do_idx,
 507                                             int irq,
 508                                             spinlock_t * irq_mode_lock)
 509{
 510        me8200_do_subdevice_t *subdevice;
 511        int err;
 512
 513        PDEBUG("executed.\n");
 514
 515        /* Allocate memory for subdevice instance */
 516        subdevice = kmalloc(sizeof(me8200_do_subdevice_t), GFP_KERNEL);
 517
 518        if (!subdevice) {
 519                PERROR("Cannot get memory for subdevice instance.\n");
 520                return NULL;
 521        }
 522
 523        memset(subdevice, 0, sizeof(me8200_do_subdevice_t));
 524
 525        /* Initialize subdevice base class */
 526        err = me_subdevice_init(&subdevice->base);
 527
 528        if (err) {
 529                PERROR("Cannot initialize subdevice base class instance.\n");
 530                kfree(subdevice);
 531                return NULL;
 532        }
 533        // Initialize spin locks.
 534        spin_lock_init(&subdevice->subdevice_lock);
 535
 536        subdevice->irq_mode_lock = irq_mode_lock;
 537
 538        /* Save the index of the digital output */
 539        subdevice->do_idx = do_idx;
 540        subdevice->irq = irq;
 541
 542        /* Initialize the registers */
 543        if (do_idx == 0) {
 544                subdevice->port_reg = reg_base + ME8200_DO_PORT_0_REG;
 545        } else if (do_idx == 1) {
 546                subdevice->port_reg = reg_base + ME8200_DO_PORT_1_REG;
 547        } else {
 548                PERROR("Wrong subdevice idx=%d.\n", do_idx);
 549                kfree(subdevice);
 550                return NULL;
 551        }
 552        subdevice->irq_ctrl_reg = reg_base + ME8200_IRQ_MODE_REG;
 553        subdevice->irq_status_reg = reg_base + ME8200_DO_IRQ_STATUS_REG;
 554#ifdef MEDEBUG_DEBUG_REG
 555        subdevice->reg_base = reg_base;
 556#endif
 557
 558        /* Initialize the wait queue */
 559        init_waitqueue_head(&subdevice->wait_queue);
 560
 561        /* Request the interrupt line */
 562        err = request_irq(irq, me8200_do_isr,
 563#ifdef IRQF_DISABLED
 564                          IRQF_DISABLED | IRQF_SHARED,
 565#else
 566                          SA_INTERRUPT | SA_SHIRQ,
 567#endif
 568                          ME8200_NAME, (void *)subdevice);
 569
 570        if (err) {
 571                PERROR("Cannot get interrupt line.\n");
 572                kfree(subdevice);
 573                return NULL;
 574        }
 575        PINFO("Registered irq=%d.\n", irq);
 576
 577        /* Overload base class methods. */
 578        subdevice->base.me_subdevice_io_irq_start = me8200_do_io_irq_start;
 579        subdevice->base.me_subdevice_io_irq_wait = me8200_do_io_irq_wait;
 580        subdevice->base.me_subdevice_io_irq_stop = me8200_do_io_irq_stop;
 581        subdevice->base.me_subdevice_io_reset_subdevice =
 582            me8200_do_io_reset_subdevice;
 583        subdevice->base.me_subdevice_io_single_config =
 584            me8200_do_io_single_config;
 585        subdevice->base.me_subdevice_io_single_read = me8200_do_io_single_read;
 586        subdevice->base.me_subdevice_io_single_write =
 587            me8200_do_io_single_write;
 588        subdevice->base.me_subdevice_query_number_channels =
 589            me8200_do_query_number_channels;
 590        subdevice->base.me_subdevice_query_subdevice_type =
 591            me8200_do_query_subdevice_type;
 592        subdevice->base.me_subdevice_query_subdevice_caps =
 593            me8200_do_query_subdevice_caps;
 594        subdevice->base.me_subdevice_destructor = me8200_do_destructor;
 595
 596        subdevice->rised = 0;
 597        subdevice->count = 0;
 598
 599        return subdevice;
 600}
 601
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.