linux/drivers/staging/meilhaus/me4600_dio.c
<<
>>
Prefs
   1/**
   2 * @file me4600_dio.c
   3 *
   4 * @brief ME-4000 digital input/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_dio.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                         struct file *filep, int flags)
  60{
  61        me4600_dio_subdevice_t *instance;
  62        uint32_t mode;
  63
  64        PDEBUG("executed.\n");
  65
  66        instance = (me4600_dio_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 input mode */
  76        spin_lock(&instance->subdevice_lock);
  77        spin_lock(instance->ctrl_reg_lock);
  78        mode = inl(instance->ctrl_reg);
  79        mode &=
  80            ~((ME4600_DIO_CTRL_BIT_MODE_0 | ME4600_DIO_CTRL_BIT_MODE_1) <<
  81              (instance->dio_idx * 2));
  82        outl(mode, instance->ctrl_reg);
  83        PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  84                   instance->ctrl_reg - instance->reg_base, mode);
  85        spin_unlock(instance->ctrl_reg_lock);
  86
  87        outl(0, instance->port_reg);
  88        PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  89                   instance->port_reg - instance->reg_base, 0);
  90        spin_unlock(&instance->subdevice_lock);
  91
  92        ME_SUBDEVICE_EXIT;
  93
  94        return ME_ERRNO_SUCCESS;
  95}
  96
  97static int me4600_dio_io_single_config(me_subdevice_t * subdevice,
  98                                       struct file *filep,
  99                                       int channel,
 100                                       int single_config,
 101                                       int ref,
 102                                       int trig_chan,
 103                                       int trig_type, int trig_edge, int flags)
 104{
 105        me4600_dio_subdevice_t *instance;
 106        int err = ME_ERRNO_SUCCESS;
 107        uint32_t mode;
 108        uint32_t size =
 109            flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
 110                     | ME_IO_SINGLE_CONFIG_DIO_WORD |
 111                     ME_IO_SINGLE_CONFIG_DIO_DWORD);
 112        uint32_t mask;
 113
 114        PDEBUG("executed.\n");
 115
 116        instance = (me4600_dio_subdevice_t *) subdevice;
 117
 118        ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
 119        spin_lock(instance->ctrl_reg_lock);
 120        mode = inl(instance->ctrl_reg);
 121        switch (size) {
 122        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 123        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 124                if (channel == 0) {
 125                        if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
 126                                mode &=
 127                                    ~((ME4600_DIO_CTRL_BIT_MODE_0 |
 128                                       ME4600_DIO_CTRL_BIT_MODE_1) <<
 129                                      (instance->dio_idx * 2));
 130                        } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 131                                mode &=
 132                                    ~((ME4600_DIO_CTRL_BIT_MODE_0 |
 133                                       ME4600_DIO_CTRL_BIT_MODE_1) <<
 134                                      (instance->dio_idx * 2));
 135                                mode |=
 136                                    ME4600_DIO_CTRL_BIT_MODE_0 << (instance->
 137                                                                   dio_idx * 2);
 138                        } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) {
 139                                mask =
 140                                    (ME4600_DIO_CTRL_BIT_MODE_0 |
 141                                     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
 142                                                                     dio_idx *
 143                                                                     2);
 144                                mask |=
 145                                    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 146                                    ME4600_DIO_CTRL_BIT_FUNCTION_1;
 147                                mask |=
 148                                    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 149                                    instance->dio_idx;
 150                                mode &= ~mask;
 151
 152                                if (ref == ME_REF_DIO_FIFO_LOW) {
 153                                        mode |=
 154                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 155                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 156                                            (instance->dio_idx * 2);
 157                                        mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
 158                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 159                                        mode |=
 160                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 161                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 162                                            (instance->dio_idx * 2);
 163                                        mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
 164                                        mode |=
 165                                            ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 166                                            instance->dio_idx;
 167                                } else {
 168                                        PERROR
 169                                            ("Invalid port reference specified.\n");
 170                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 171                                }
 172                        } else if (single_config ==
 173                                   ME_SINGLE_CONFIG_DIO_DEMUX32) {
 174                                mask =
 175                                    (ME4600_DIO_CTRL_BIT_MODE_0 |
 176                                     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
 177                                                                     dio_idx *
 178                                                                     2);
 179                                mask |=
 180                                    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 181                                    ME4600_DIO_CTRL_BIT_FUNCTION_1;
 182                                mask |=
 183                                    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 184                                    instance->dio_idx;
 185                                mode &= ~mask;
 186
 187                                if (ref == ME_REF_DIO_FIFO_LOW) {
 188                                        mode |=
 189                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 190                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 191                                            (instance->dio_idx * 2);
 192                                        mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
 193                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 194                                        mode |=
 195                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 196                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 197                                            (instance->dio_idx * 2);
 198                                        mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
 199                                        mode |=
 200                                            ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 201                                            instance->dio_idx;
 202                                } else {
 203                                        PERROR
 204                                            ("Invalid port reference specified.\n");
 205                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 206                                }
 207                        } else if (single_config ==
 208                                   ME_SINGLE_CONFIG_DIO_BIT_PATTERN) {
 209                                mask =
 210                                    (ME4600_DIO_CTRL_BIT_MODE_0 |
 211                                     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
 212                                                                     dio_idx *
 213                                                                     2);
 214                                mask |=
 215                                    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
 216                                    ME4600_DIO_CTRL_BIT_FUNCTION_1;
 217                                mask |=
 218                                    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 219                                    instance->dio_idx;
 220                                mode &= ~mask;
 221
 222                                if (ref == ME_REF_DIO_FIFO_LOW) {
 223                                        mode |=
 224                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 225                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 226                                            (instance->dio_idx * 2);
 227                                } else if (ref == ME_REF_DIO_FIFO_HIGH) {
 228                                        mode |=
 229                                            (ME4600_DIO_CTRL_BIT_MODE_0 |
 230                                             ME4600_DIO_CTRL_BIT_MODE_1) <<
 231                                            (instance->dio_idx * 2);
 232                                        mode |=
 233                                            ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
 234                                            instance->dio_idx;
 235                                } else {
 236                                        PERROR
 237                                            ("Invalid port reference specified.\n");
 238                                        err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 239                                }
 240                        } else {
 241                                PERROR
 242                                    ("Invalid port configuration specified.\n");
 243                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 244                        }
 245                } else {
 246                        PERROR("Invalid channel number.\n");
 247                        err = ME_ERRNO_INVALID_CHANNEL;
 248                }
 249
 250                break;
 251
 252        default:
 253                PERROR("Invalid flags.\n");
 254                err = ME_ERRNO_INVALID_FLAGS;
 255        }
 256
 257        if (!err) {
 258                outl(mode, instance->ctrl_reg);
 259                PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
 260                           instance->reg_base,
 261                           instance->ctrl_reg - instance->reg_base, mode);
 262        }
 263        spin_unlock(instance->ctrl_reg_lock);
 264        spin_unlock(&instance->subdevice_lock);
 265
 266        ME_SUBDEVICE_EXIT;
 267
 268        return err;
 269}
 270
 271static int me4600_dio_io_single_read(me_subdevice_t * subdevice,
 272                                     struct file *filep,
 273                                     int channel,
 274                                     int *value, int time_out, int flags)
 275{
 276        me4600_dio_subdevice_t *instance;
 277        int err = ME_ERRNO_SUCCESS;
 278        uint32_t mode;
 279
 280        PDEBUG("executed.\n");
 281
 282        instance = (me4600_dio_subdevice_t *) subdevice;
 283
 284        ME_SUBDEVICE_ENTER;
 285
 286        spin_lock(&instance->subdevice_lock);
 287        spin_lock(instance->ctrl_reg_lock);
 288        switch (flags) {
 289        case ME_IO_SINGLE_TYPE_DIO_BIT:
 290                if ((channel >= 0) && (channel < 8)) {
 291                        mode =
 292                            inl(instance->
 293                                ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
 294                                              ME4600_DIO_CTRL_BIT_MODE_1) <<
 295                                             (instance->dio_idx * 2));
 296                        if ((mode ==
 297                             (ME4600_DIO_CTRL_BIT_MODE_0 <<
 298                              (instance->dio_idx * 2))) || !mode) {
 299                                *value =
 300                                    inl(instance->port_reg) & (0x1 << channel);
 301                        } else {
 302                                PERROR("Port not in output or input mode.\n");
 303                                err = ME_ERRNO_PREVIOUS_CONFIG;
 304                        }
 305                } else {
 306                        PERROR("Invalid bit number specified.\n");
 307                        err = ME_ERRNO_INVALID_CHANNEL;
 308                }
 309                break;
 310
 311        case ME_IO_SINGLE_NO_FLAGS:
 312        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 313                if (channel == 0) {
 314                        mode =
 315                            inl(instance->
 316                                ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
 317                                              ME4600_DIO_CTRL_BIT_MODE_1) <<
 318                                             (instance->dio_idx * 2));
 319                        if ((mode ==
 320                             (ME4600_DIO_CTRL_BIT_MODE_0 <<
 321                              (instance->dio_idx * 2))) || !mode) {
 322                                *value = inl(instance->port_reg) & 0xFF;
 323                        } else {
 324                                PERROR("Port not in output or input mode.\n");
 325                                err = ME_ERRNO_PREVIOUS_CONFIG;
 326                        }
 327                } else {
 328                        PERROR("Invalid byte number specified.\n");
 329                        err = ME_ERRNO_INVALID_CHANNEL;
 330                }
 331                break;
 332
 333        default:
 334                PERROR("Invalid flags specified.\n");
 335                err = ME_ERRNO_INVALID_FLAGS;
 336        }
 337        spin_unlock(instance->ctrl_reg_lock);
 338        spin_unlock(&instance->subdevice_lock);
 339
 340        ME_SUBDEVICE_EXIT;
 341
 342        return err;
 343}
 344
 345static int me4600_dio_io_single_write(me_subdevice_t * subdevice,
 346                                      struct file *filep,
 347                                      int channel,
 348                                      int value, int time_out, int flags)
 349{
 350        me4600_dio_subdevice_t *instance;
 351        int err = ME_ERRNO_SUCCESS;
 352        uint32_t mode;
 353        uint32_t byte;
 354
 355        PDEBUG("executed.\n");
 356
 357        instance = (me4600_dio_subdevice_t *) subdevice;
 358
 359        ME_SUBDEVICE_ENTER;
 360
 361        spin_lock(&instance->subdevice_lock);
 362        spin_lock(instance->ctrl_reg_lock);
 363        switch (flags) {
 364        case ME_IO_SINGLE_TYPE_DIO_BIT:
 365                if ((channel >= 0) && (channel < 8)) {
 366                        mode =
 367                            inl(instance->
 368                                ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
 369                                              ME4600_DIO_CTRL_BIT_MODE_1) <<
 370                                             (instance->dio_idx * 2));
 371
 372                        if (mode ==
 373                            (ME4600_DIO_CTRL_BIT_MODE_0 <<
 374                             (instance->dio_idx * 2))) {
 375                                byte = inl(instance->port_reg) & 0xFF;
 376
 377                                if (value)
 378                                        byte |= 0x1 << channel;
 379                                else
 380                                        byte &= ~(0x1 << channel);
 381
 382                                outl(byte, instance->port_reg);
 383                        } else {
 384                                PERROR("Port not in output or input mode.\n");
 385                                err = ME_ERRNO_PREVIOUS_CONFIG;
 386                        }
 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                        mode =
 397                            inl(instance->
 398                                ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
 399                                              ME4600_DIO_CTRL_BIT_MODE_1) <<
 400                                             (instance->dio_idx * 2));
 401
 402                        if (mode ==
 403                            (ME4600_DIO_CTRL_BIT_MODE_0 <<
 404                             (instance->dio_idx * 2))) {
 405                                outl(value, instance->port_reg);
 406                        } else {
 407                                PERROR("Port not in output or input mode.\n");
 408                                err = ME_ERRNO_PREVIOUS_CONFIG;
 409                        }
 410                } else {
 411                        PERROR("Invalid byte number specified.\n");
 412                        err = ME_ERRNO_INVALID_CHANNEL;
 413                }
 414                break;
 415
 416        default:
 417                PERROR("Invalid flags specified.\n");
 418                err = ME_ERRNO_INVALID_FLAGS;
 419        }
 420        spin_unlock(instance->ctrl_reg_lock);
 421        spin_unlock(&instance->subdevice_lock);
 422
 423        ME_SUBDEVICE_EXIT;
 424
 425        return err;
 426}
 427
 428static int me4600_dio_query_number_channels(me_subdevice_t * subdevice,
 429                                            int *number)
 430{
 431        PDEBUG("executed.\n");
 432        *number = 8;
 433        return ME_ERRNO_SUCCESS;
 434}
 435
 436static int me4600_dio_query_subdevice_type(me_subdevice_t * subdevice,
 437                                           int *type, int *subtype)
 438{
 439        PDEBUG("executed.\n");
 440        *type = ME_TYPE_DIO;
 441        *subtype = ME_SUBTYPE_SINGLE;
 442        return ME_ERRNO_SUCCESS;
 443}
 444
 445static int me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice,
 446                                           int *caps)
 447{
 448        PDEBUG("executed.\n");
 449        *caps = ME_CAPS_DIO_DIR_BYTE;
 450        return ME_ERRNO_SUCCESS;
 451}
 452
 453me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base,
 454                                               unsigned int dio_idx,
 455                                               spinlock_t * ctrl_reg_lock)
 456{
 457        me4600_dio_subdevice_t *subdevice;
 458        int err;
 459
 460        PDEBUG("executed.\n");
 461
 462        /* Allocate memory for subdevice instance */
 463        subdevice = kmalloc(sizeof(me4600_dio_subdevice_t), GFP_KERNEL);
 464
 465        if (!subdevice) {
 466                PERROR("Cannot get memory for subdevice instance.\n");
 467                return NULL;
 468        }
 469
 470        memset(subdevice, 0, sizeof(me4600_dio_subdevice_t));
 471
 472        /* Initialize subdevice base class */
 473        err = me_subdevice_init(&subdevice->base);
 474
 475        if (err) {
 476                PERROR("Cannot initialize subdevice base class instance.\n");
 477                kfree(subdevice);
 478                return NULL;
 479        }
 480        // Initialize spin locks.
 481        spin_lock_init(&subdevice->subdevice_lock);
 482        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 483
 484        /* Save digital i/o index */
 485        subdevice->dio_idx = dio_idx;
 486
 487        /* Save the subdevice index */
 488        subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
 489        subdevice->port_reg = reg_base + ME4600_DIO_PORT_REG + (dio_idx * 4);
 490#ifdef MEDEBUG_DEBUG_REG
 491        subdevice->reg_base = reg_base;
 492#endif
 493
 494        /* Overload base class methods. */
 495        subdevice->base.me_subdevice_io_reset_subdevice =
 496            me4600_dio_io_reset_subdevice;
 497        subdevice->base.me_subdevice_io_single_config =
 498            me4600_dio_io_single_config;
 499        subdevice->base.me_subdevice_io_single_read = me4600_dio_io_single_read;
 500        subdevice->base.me_subdevice_io_single_write =
 501            me4600_dio_io_single_write;
 502        subdevice->base.me_subdevice_query_number_channels =
 503            me4600_dio_query_number_channels;
 504        subdevice->base.me_subdevice_query_subdevice_type =
 505            me4600_dio_query_subdevice_type;
 506        subdevice->base.me_subdevice_query_subdevice_caps =
 507            me4600_dio_query_subdevice_caps;
 508
 509        return subdevice;
 510}
 511
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.