linux/drivers/staging/meilhaus/me4600_do.c
<<
>>
Prefs
   1/**
   2 * @file me4600_do.c
   3 *
   4 * @brief ME-4000 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 <asm/io.h>
  40#include <linux/types.h>
  41
  42#include "medefines.h"
  43#include "meinternal.h"
  44#include "meerror.h"
  45
  46#include "medebug.h"
  47#include "me4600_dio_reg.h"
  48#include "me4600_do.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me4600_do_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                        struct file *filep, int flags)
  60{
  61        me4600_do_subdevice_t *instance;
  62        uint32_t mode;
  63
  64        PDEBUG("executed.\n");
  65
  66        instance = (me4600_do_subdevice_t *) subdevice;
  67
  68        if (flags) {
  69                PERROR("Invalid flag specified.\n");
  70                return ME_ERRNO_INVALID_FLAGS;
  71        }
  72
  73        ME_SUBDEVICE_ENTER;
  74
  75        /* Set port to output mode */
  76        spin_lock(&instance->subdevice_lock);
  77        spin_lock(instance->ctrl_reg_lock);
  78        mode = inl(instance->ctrl_reg);
  79        mode &= ~ME4600_DIO_CTRL_BIT_MODE_1;    //0xFFFD
  80        mode |= ME4600_DIO_CTRL_BIT_MODE_0;     //0x1
  81        outl(mode, instance->ctrl_reg);
  82        PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  83                   instance->ctrl_reg - instance->reg_base, mode);
  84        spin_unlock(instance->ctrl_reg_lock);
  85
  86        outl(0, instance->port_reg);
  87        PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  88                   instance->port_reg - instance->reg_base, 0);
  89        spin_unlock(&instance->subdevice_lock);
  90
  91        ME_SUBDEVICE_EXIT;
  92
  93        return ME_ERRNO_SUCCESS;
  94}
  95
  96static int me4600_do_io_single_config(me_subdevice_t * subdevice,
  97                                      struct file *filep,
  98                                      int channel,
  99                                      int single_config,
 100                                      int ref,
 101                                      int trig_chan,
 102                                      int trig_type, int trig_edge, int flags)
 103{
 104        me4600_do_subdevice_t *instance;
 105        int err = ME_ERRNO_SUCCESS;
 106        uint32_t mode;
 107        int size =
 108            flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
 109                     | ME_IO_SINGLE_CONFIG_DIO_WORD |
 110                     ME_IO_SINGLE_CONFIG_DIO_DWORD);
 111
 112        PDEBUG("executed.\n");
 113
 114        instance = (me4600_do_subdevice_t *) subdevice;
 115
 116        ME_SUBDEVICE_ENTER;
 117
 118        spin_lock(&instance->subdevice_lock);
 119        spin_lock(instance->ctrl_reg_lock);
 120        mode = inl(instance->ctrl_reg);
 121
 122        switch (size) {
 123        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 124        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 125                if (channel == 0) {
 126                        if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 127                                mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 |
 128                                          ME4600_DIO_CTRL_BIT_MODE_1);
 129                                mode |= (ME4600_DIO_CTRL_BIT_MODE_0);
 130                        } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) {
 131                                mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 |
 132                                          ME4600_DIO_CTRL_BIT_MODE_1 |
 133                                          ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 134                                          ME4600_DIO_CTRL_BIT_FUNCTION_1 |
 135                                          ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 136
 137                                if (ref == ME_REF_DIO_FIFO_LOW) {
 138                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 139                                                 ME4600_DIO_CTRL_BIT_MODE_1 |
 140                                                 ME4600_DIO_CTRL_BIT_FUNCTION_1);
 141                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 142                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 143                                                 ME4600_DIO_CTRL_BIT_MODE_1 |
 144                                                 ME4600_DIO_CTRL_BIT_FUNCTION_1
 145                                                 |
 146                                                 ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 147                                } else {
 148                                        PERROR
 149                                            ("Invalid port reference specified.\n");
 150                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 151                                }
 152                        } else if (single_config ==
 153                                   ME_SINGLE_CONFIG_DIO_DEMUX32) {
 154                                mode &=
 155                                    ~(ME4600_DIO_CTRL_BIT_MODE_0 |
 156                                      ME4600_DIO_CTRL_BIT_MODE_1 |
 157                                      ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 158                                      ME4600_DIO_CTRL_BIT_FUNCTION_1 |
 159                                      ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 160
 161                                if (ref == ME_REF_DIO_FIFO_LOW) {
 162                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 163                                                 ME4600_DIO_CTRL_BIT_MODE_1 |
 164                                                 ME4600_DIO_CTRL_BIT_FUNCTION_0);
 165                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 166                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 167                                                 ME4600_DIO_CTRL_BIT_MODE_1 |
 168                                                 ME4600_DIO_CTRL_BIT_FUNCTION_0
 169                                                 |
 170                                                 ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 171                                } else {
 172                                        PERROR
 173                                            ("Invalid port reference specified.\n");
 174                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 175                                }
 176                        } else if (single_config ==
 177                                   ME_SINGLE_CONFIG_DIO_BIT_PATTERN) {
 178                                mode &=
 179                                    ~(ME4600_DIO_CTRL_BIT_MODE_0 |
 180                                      ME4600_DIO_CTRL_BIT_MODE_1 |
 181                                      ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 182                                      ME4600_DIO_CTRL_BIT_FUNCTION_1 |
 183                                      ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 184
 185                                if (ref == ME_REF_DIO_FIFO_LOW) {
 186                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 187                                                 ME4600_DIO_CTRL_BIT_MODE_1);
 188                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 189                                        mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
 190                                                 ME4600_DIO_CTRL_BIT_MODE_1 |
 191                                                 ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
 192                                } else {
 193                                        PERROR
 194                                            ("Invalid port reference specified.\n");
 195                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 196                                }
 197                        } else {
 198                                PERROR("Invalid port direction specified.\n");
 199                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 200                        }
 201                } else {
 202                        PERROR("Invalid channel number.\n");
 203                        err = ME_ERRNO_INVALID_CHANNEL;
 204                }
 205
 206                break;
 207
 208        default:
 209                PERROR("Invalid flags specified.\n");
 210                err = ME_ERRNO_INVALID_FLAGS;
 211        }
 212
 213        if (!err) {
 214                outl(mode, instance->ctrl_reg);
 215                PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
 216                           instance->reg_base,
 217                           instance->ctrl_reg - instance->reg_base, mode);
 218        }
 219        spin_unlock(instance->ctrl_reg_lock);
 220        spin_unlock(&instance->subdevice_lock);
 221
 222        ME_SUBDEVICE_EXIT;
 223
 224        return err;
 225}
 226
 227static int me4600_do_io_single_read(me_subdevice_t * subdevice,
 228                                    struct file *filep,
 229                                    int channel,
 230                                    int *value, int time_out, int flags)
 231{
 232        me4600_do_subdevice_t *instance;
 233        int err = ME_ERRNO_SUCCESS;
 234        uint32_t mode;
 235
 236        PDEBUG("executed.\n");
 237
 238        instance = (me4600_do_subdevice_t *) subdevice;
 239
 240        ME_SUBDEVICE_ENTER;
 241
 242        spin_lock(&instance->subdevice_lock);
 243        spin_lock(instance->ctrl_reg_lock);
 244        mode =
 245            inl(instance->
 246                ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 |
 247                             ME4600_DIO_CTRL_BIT_MODE_1);
 248
 249        if (mode == ME4600_DIO_CTRL_BIT_MODE_0) {
 250                switch (flags) {
 251                case ME_IO_SINGLE_TYPE_DIO_BIT:
 252                        if ((channel >= 0) && (channel < 8)) {
 253                                *value =
 254                                    inl(instance->port_reg) & (0x1 << channel);
 255                        } else {
 256                                PERROR("Invalid bit number specified.\n");
 257                                err = ME_ERRNO_INVALID_CHANNEL;
 258                        }
 259                        break;
 260
 261                case ME_IO_SINGLE_NO_FLAGS:
 262                case ME_IO_SINGLE_TYPE_DIO_BYTE:
 263                        if (channel == 0) {
 264                                *value = inl(instance->port_reg) & 0xFF;
 265                        } else {
 266                                PERROR("Invalid byte number specified.\n");
 267                                err = ME_ERRNO_INVALID_CHANNEL;
 268                        }
 269                        break;
 270
 271                default:
 272                        PERROR("Invalid flags specified.\n");
 273                        err = ME_ERRNO_INVALID_FLAGS;
 274                }
 275        } else {
 276                PERROR("Port not in output mode.\n");
 277                err = ME_ERRNO_PREVIOUS_CONFIG;
 278        }
 279        spin_unlock(instance->ctrl_reg_lock);
 280        spin_unlock(&instance->subdevice_lock);
 281
 282        ME_SUBDEVICE_EXIT;
 283
 284        return err;
 285}
 286
 287static int me4600_do_io_single_write(me_subdevice_t * subdevice,
 288                                     struct file *filep,
 289                                     int channel,
 290                                     int value, int time_out, int flags)
 291{
 292        me4600_do_subdevice_t *instance;
 293        int err = ME_ERRNO_SUCCESS;
 294        uint32_t byte;
 295        uint32_t mode;
 296
 297        PDEBUG("executed.\n");
 298
 299        instance = (me4600_do_subdevice_t *) subdevice;
 300
 301        ME_SUBDEVICE_ENTER;
 302
 303        spin_lock(&instance->subdevice_lock);
 304        spin_lock(instance->ctrl_reg_lock);
 305        mode =
 306            inl(instance->
 307                ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 |
 308                             ME4600_DIO_CTRL_BIT_MODE_1);
 309
 310        if (mode == ME4600_DIO_CTRL_BIT_MODE_0) {
 311                switch (flags) {
 312
 313                case ME_IO_SINGLE_TYPE_DIO_BIT:
 314                        if ((channel >= 0) && (channel < 8)) {
 315                                byte = inl(instance->port_reg) & 0xFF;
 316
 317                                if (value)
 318                                        byte |= 0x1 << channel;
 319                                else
 320                                        byte &= ~(0x1 << channel);
 321
 322                                outl(byte, instance->port_reg);
 323                        } else {
 324                                PERROR("Invalid bit number specified.\n");
 325                                err = ME_ERRNO_INVALID_CHANNEL;
 326                        }
 327                        break;
 328
 329                case ME_IO_SINGLE_NO_FLAGS:
 330                case ME_IO_SINGLE_TYPE_DIO_BYTE:
 331                        if (channel == 0) {
 332                                outl(value, instance->port_reg);
 333                        } else {
 334                                PERROR("Invalid byte number specified.\n");
 335                                err = ME_ERRNO_INVALID_CHANNEL;
 336                        }
 337                        break;
 338
 339                default:
 340                        PERROR("Invalid flags specified.\n");
 341                        err = ME_ERRNO_INVALID_FLAGS;
 342                }
 343        } else {
 344                PERROR("Port not in output mode.\n");
 345                err = ME_ERRNO_PREVIOUS_CONFIG;
 346        }
 347        spin_unlock(instance->ctrl_reg_lock);
 348        spin_unlock(&instance->subdevice_lock);
 349
 350        ME_SUBDEVICE_EXIT;
 351
 352        return err;
 353}
 354
 355static int me4600_do_query_number_channels(me_subdevice_t * subdevice,
 356                                           int *number)
 357{
 358        PDEBUG("executed.\n");
 359        *number = 8;
 360        return ME_ERRNO_SUCCESS;
 361}
 362
 363static int me4600_do_query_subdevice_type(me_subdevice_t * subdevice,
 364                                          int *type, int *subtype)
 365{
 366        PDEBUG("executed.\n");
 367        *type = ME_TYPE_DO;
 368        *subtype = ME_SUBTYPE_SINGLE;
 369        return ME_ERRNO_SUCCESS;
 370}
 371
 372static int me4600_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 373{
 374        PDEBUG("executed.\n");
 375        *caps = 0;
 376        return ME_ERRNO_SUCCESS;
 377}
 378
 379me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base,
 380                                             spinlock_t * ctrl_reg_lock)
 381{
 382        me4600_do_subdevice_t *subdevice;
 383        int err;
 384
 385        PDEBUG("executed.\n");
 386
 387        /* Allocate memory for subdevice instance */
 388        subdevice = kmalloc(sizeof(me4600_do_subdevice_t), GFP_KERNEL);
 389
 390        if (!subdevice) {
 391                PERROR("Cannot get memory for subdevice instance.\n");
 392                return NULL;
 393        }
 394
 395        memset(subdevice, 0, sizeof(me4600_do_subdevice_t));
 396
 397        /* Initialize subdevice base class */
 398        err = me_subdevice_init(&subdevice->base);
 399
 400        if (err) {
 401                PERROR("Cannot initialize subdevice base class instance.\n");
 402                kfree(subdevice);
 403                return NULL;
 404        }
 405        // Initialize spin locks.
 406        spin_lock_init(&subdevice->subdevice_lock);
 407
 408        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 409
 410        /* Save the subdevice index */
 411        subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
 412        subdevice->port_reg = reg_base + ME4600_DIO_PORT_0_REG;
 413#ifdef MEDEBUG_DEBUG_REG
 414        subdevice->reg_base = reg_base;
 415#endif
 416
 417        /* Overload base class methods. */
 418        subdevice->base.me_subdevice_io_reset_subdevice =
 419            me4600_do_io_reset_subdevice;
 420        subdevice->base.me_subdevice_io_single_config =
 421            me4600_do_io_single_config;
 422        subdevice->base.me_subdevice_io_single_read = me4600_do_io_single_read;
 423        subdevice->base.me_subdevice_io_single_write =
 424            me4600_do_io_single_write;
 425        subdevice->base.me_subdevice_query_number_channels =
 426            me4600_do_query_number_channels;
 427        subdevice->base.me_subdevice_query_subdevice_type =
 428            me4600_do_query_subdevice_type;
 429        subdevice->base.me_subdevice_query_subdevice_caps =
 430            me4600_do_query_subdevice_caps;
 431
 432        return subdevice;
 433}
 434
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.