linux/drivers/staging/meilhaus/me8254.c
<<
>>
Prefs
   1/**
   2 * @file me8254.c
   3 *
   4 * @brief 8254 subdevice instance.
   5 * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
   6 * @author Guenter Gebhardt
   7 */
   8
   9/*
  10 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
  11 *
  12 * This file is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25 */
  26
  27#ifndef __KERNEL__
  28#  define __KERNEL__
  29#endif
  30
  31/*
  32 * Includes
  33 */
  34#include <linux/module.h>
  35
  36#include <linux/slab.h>
  37#include <linux/spinlock.h>
  38#include <asm/io.h>
  39#include <linux/types.h>
  40
  41#include "medefines.h"
  42#include "meinternal.h"
  43#include "meerror.h"
  44
  45#include "medebug.h"
  46#include "me8254_reg.h"
  47#include "me8254.h"
  48
  49/*
  50 * Defines
  51 */
  52#define ME8254_NUMBER_CHANNELS 1        /**< One channel per counter. */
  53#define ME8254_CTR_WIDTH 16                     /**< One counter has 16 bits. */
  54
  55/*
  56 * Functions
  57 */
  58
  59static int me8254_io_reset_subdevice(struct me_subdevice *subdevice,
  60                                     struct file *filep, int flags)
  61{
  62        me8254_subdevice_t *instance;
  63        uint8_t clk_src;
  64        int err = ME_ERRNO_SUCCESS;
  65
  66        PDEBUG("executed.\n");
  67
  68        instance = (me8254_subdevice_t *) subdevice;
  69
  70        if (flags) {
  71                PERROR("Invalid flag specified.\n");
  72                return ME_ERRNO_INVALID_FLAGS;
  73        }
  74
  75        ME_SUBDEVICE_ENTER;
  76
  77        spin_lock(&instance->subdevice_lock);
  78        spin_lock(instance->ctrl_reg_lock);
  79        if (instance->ctr_idx == 0)
  80                outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
  81                     ME8254_CTRL_BIN, instance->ctrl_reg);
  82        else if (instance->ctr_idx == 1)
  83                outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
  84                     ME8254_CTRL_BIN, instance->ctrl_reg);
  85        else
  86                outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
  87                     ME8254_CTRL_BIN, instance->ctrl_reg);
  88        spin_unlock(instance->ctrl_reg_lock);
  89
  90        outb(0x00, instance->val_reg);
  91        outb(0x00, instance->val_reg);
  92
  93        spin_lock(instance->clk_src_reg_lock);
  94        clk_src = inb(instance->clk_src_reg);
  95
  96        switch (instance->device_id) {
  97        case PCI_DEVICE_ID_MEILHAUS_ME1400:
  98        case PCI_DEVICE_ID_MEILHAUS_ME140A:
  99        case PCI_DEVICE_ID_MEILHAUS_ME140B:
 100        case PCI_DEVICE_ID_MEILHAUS_ME14E0:
 101        case PCI_DEVICE_ID_MEILHAUS_ME14EA:
 102        case PCI_DEVICE_ID_MEILHAUS_ME14EB:
 103                if (instance->me8254_idx == 0) {
 104                        if (instance->ctr_idx == 0)
 105                                clk_src &=
 106                                    ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ |
 107                                      ME1400AB_8254_A_0_CLK_SRC_QUARZ);
 108                        else if (instance->ctr_idx == 1)
 109                                clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV);
 110                        else
 111                                clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV);
 112                } else {
 113                        if (instance->ctr_idx == 0)
 114                                clk_src &=
 115                                    ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ |
 116                                      ME1400AB_8254_B_0_CLK_SRC_QUARZ);
 117                        else if (instance->ctr_idx == 1)
 118                                clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV);
 119                        else
 120                                clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV);
 121                }
 122                break;
 123
 124        case PCI_DEVICE_ID_MEILHAUS_ME140C:
 125        case PCI_DEVICE_ID_MEILHAUS_ME140D:
 126                switch (instance->me8254_idx) {
 127                case 0:
 128                case 2:
 129                case 4:
 130                case 6:
 131                case 8:
 132                        if (instance->ctr_idx == 0)
 133                                clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
 134                        else if (instance->ctr_idx == 1)
 135                                clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
 136                        else
 137                                clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
 138                        break;
 139
 140                default:
 141                        if (instance->ctr_idx == 0)
 142                                clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
 143                        else if (instance->ctr_idx == 1)
 144                                clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
 145                        else
 146                                clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
 147                        break;
 148                }
 149                break;
 150
 151        case PCI_DEVICE_ID_MEILHAUS_ME4610:
 152        case PCI_DEVICE_ID_MEILHAUS_ME4660:
 153        case PCI_DEVICE_ID_MEILHAUS_ME4660I:
 154        case PCI_DEVICE_ID_MEILHAUS_ME4660S:
 155        case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
 156        case PCI_DEVICE_ID_MEILHAUS_ME4670:
 157        case PCI_DEVICE_ID_MEILHAUS_ME4670I:
 158        case PCI_DEVICE_ID_MEILHAUS_ME4670S:
 159        case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
 160        case PCI_DEVICE_ID_MEILHAUS_ME4680:
 161        case PCI_DEVICE_ID_MEILHAUS_ME4680I:
 162        case PCI_DEVICE_ID_MEILHAUS_ME4680S:
 163        case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
 164        case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
 165        case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
 166
 167                /* No clock source register available */
 168                break;
 169
 170        default:
 171                PERROR("Invalid device type.\n");
 172                err = ME_ERRNO_INTERNAL;
 173        }
 174
 175        if (!err)
 176                outb(clk_src, instance->clk_src_reg);
 177
 178        spin_unlock(instance->clk_src_reg_lock);
 179        spin_unlock(&instance->subdevice_lock);
 180
 181        ME_SUBDEVICE_EXIT;
 182
 183        return err;
 184}
 185
 186static int me1400_ab_ref_config(me8254_subdevice_t * instance, int ref)
 187{
 188        uint8_t clk_src;
 189
 190        spin_lock(instance->clk_src_reg_lock);
 191        clk_src = inb(instance->clk_src_reg);
 192
 193        switch (ref) {
 194        case ME_REF_CTR_EXTERNAL:
 195                if (instance->me8254_idx == 0) {
 196                        if (instance->ctr_idx == 0)
 197                                clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_QUARZ);
 198                        else if (instance->ctr_idx == 1)
 199                                clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV);
 200                        else
 201                                clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV);
 202                } else {
 203                        if (instance->ctr_idx == 0)
 204                                clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_QUARZ);
 205                        else if (instance->ctr_idx == 1)
 206                                clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV);
 207                        else
 208                                clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV);
 209                }
 210
 211                break;
 212
 213        case ME_REF_CTR_PREVIOUS:
 214                if (instance->me8254_idx == 0) {
 215                        if (instance->ctr_idx == 0) {
 216                                PERROR("Invalid reference.\n");
 217                                spin_unlock(instance->clk_src_reg_lock);
 218                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 219                        } else if (instance->ctr_idx == 1)
 220                                clk_src |= (ME1400AB_8254_A_1_CLK_SRC_PREV);
 221                        else
 222                                clk_src |= (ME1400AB_8254_A_2_CLK_SRC_PREV);
 223                } else {
 224                        if (instance->ctr_idx == 0) {
 225                                PERROR("Invalid reference.\n");
 226                                spin_unlock(instance->clk_src_reg_lock);
 227                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 228                        } else if (instance->ctr_idx == 1)
 229                                clk_src |= (ME1400AB_8254_B_1_CLK_SRC_PREV);
 230                        else
 231                                clk_src |= (ME1400AB_8254_B_2_CLK_SRC_PREV);
 232                }
 233
 234                break;
 235
 236        case ME_REF_CTR_INTERNAL_1MHZ:
 237                if (instance->me8254_idx == 0) {
 238                        if (instance->ctr_idx == 0) {
 239                                clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
 240                                clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ);
 241                        } else {
 242                                PERROR("Invalid reference.\n");
 243                                spin_unlock(instance->clk_src_reg_lock);
 244                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 245                        }
 246                } else {
 247                        if (instance->ctr_idx == 0) {
 248                                clk_src |= (ME1400AB_8254_B_0_CLK_SRC_QUARZ);
 249                                clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ);
 250                        } else {
 251                                PERROR("Invalid reference.\n");
 252                                spin_unlock(instance->clk_src_reg_lock);
 253                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 254                        }
 255                }
 256
 257                break;
 258
 259        case ME_REF_CTR_INTERNAL_10MHZ:
 260                if (instance->me8254_idx == 0) {
 261                        if (instance->ctr_idx == 0) {
 262                                clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
 263                                clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ);
 264                        } else {
 265                                PERROR("Invalid reference.\n");
 266                                spin_unlock(instance->clk_src_reg_lock);
 267                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 268                        }
 269                } else {
 270                        if (instance->ctr_idx == 0) {
 271                                clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
 272                                clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ);
 273                        } else {
 274                                PERROR("Invalid reference.\n");
 275                                spin_unlock(instance->clk_src_reg_lock);
 276                                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 277                        }
 278                }
 279
 280                break;
 281
 282        default:
 283                PERROR("Invalid reference.\n");
 284                spin_unlock(instance->clk_src_reg_lock);
 285                return ME_ERRNO_INVALID_REF;
 286        }
 287
 288        outb(clk_src, instance->clk_src_reg);
 289        spin_unlock(instance->clk_src_reg_lock);
 290
 291        return ME_ERRNO_SUCCESS;
 292}
 293
 294static int me1400_cd_ref_config(me8254_subdevice_t * instance, int ref)
 295{
 296        uint8_t clk_src;
 297
 298        spin_lock(instance->clk_src_reg_lock);
 299        clk_src = inb(instance->clk_src_reg);
 300
 301        switch (ref) {
 302        case ME_REF_CTR_EXTERNAL:
 303                switch (instance->me8254_idx) {
 304                case 0:
 305                case 2:
 306                case 4:
 307                case 6:
 308                case 8:
 309                        if (instance->ctr_idx == 0)
 310                                clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
 311                        else if (instance->ctr_idx == 1)
 312                                clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
 313                        else
 314                                clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
 315                        break;
 316
 317                default:
 318                        if (instance->ctr_idx == 0)
 319                                clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
 320                        else if (instance->ctr_idx == 1)
 321                                clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
 322                        else
 323                                clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
 324                        break;
 325                }
 326                break;
 327
 328        case ME_REF_CTR_PREVIOUS:
 329                switch (instance->me8254_idx) {
 330                case 0:
 331                case 2:
 332                case 4:
 333                case 6:
 334                case 8:
 335                        if (instance->ctr_idx == 0) {
 336                                clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
 337                                clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_PREV);
 338                        } else if (instance->ctr_idx == 1) {
 339                                clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
 340                                clk_src |= (ME1400CD_8254_ACE_1_CLK_SRC_PREV);
 341                        } else {
 342                                clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
 343                                clk_src |= (ME1400CD_8254_ACE_2_CLK_SRC_PREV);
 344                        }
 345                        break;
 346
 347                default:
 348                        if (instance->ctr_idx == 0) {
 349                                clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
 350                                clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_PREV);
 351                        } else if (instance->ctr_idx == 1) {
 352                                clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
 353                                clk_src |= (ME1400CD_8254_BD_1_CLK_SRC_PREV);
 354                        } else {
 355                                clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
 356                                clk_src |= (ME1400CD_8254_BD_2_CLK_SRC_PREV);
 357                        }
 358                        break;
 359                }
 360
 361                break;
 362
 363        case ME_REF_CTR_INTERNAL_1MHZ:
 364                switch (instance->me8254_idx) {
 365                case 0:
 366                case 2:
 367                case 4:
 368                case 6:
 369                case 8:
 370                        if (instance->ctr_idx == 0) {
 371                                clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
 372                                clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_1MHZ);
 373                        } else {
 374                                PERROR("Invalid reference.\n");
 375                                spin_unlock(instance->clk_src_reg_lock);
 376                                return ME_ERRNO_INVALID_REF;
 377                        }
 378
 379                        break;
 380
 381                default:
 382                        if (instance->ctr_idx == 0) {
 383                                clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
 384                                clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_1MHZ);
 385                        } else {
 386                                PERROR("Invalid reference.\n");
 387                                spin_unlock(instance->clk_src_reg_lock);
 388                                return ME_ERRNO_INVALID_REF;
 389                        }
 390                        break;
 391                }
 392
 393                break;
 394
 395        case ME_REF_CTR_INTERNAL_10MHZ:
 396                switch (instance->me8254_idx) {
 397                case 0:
 398                case 2:
 399                case 4:
 400                case 6:
 401                case 8:
 402                        if (instance->ctr_idx == 0) {
 403                                clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
 404                                clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_10MHZ);
 405                        } else {
 406                                PERROR("Invalid reference.\n");
 407                                spin_unlock(instance->clk_src_reg_lock);
 408                                return ME_ERRNO_INVALID_REF;
 409                        }
 410                        break;
 411
 412                default:
 413                        if (instance->ctr_idx == 0) {
 414                                clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
 415                                clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_10MHZ);
 416                        } else {
 417                                PERROR("Invalid reference.\n");
 418                                spin_unlock(instance->clk_src_reg_lock);
 419                                return ME_ERRNO_INVALID_REF;
 420                        }
 421
 422                        break;
 423                }
 424
 425                break;
 426
 427        default:
 428                PERROR("Invalid reference.\n");
 429                spin_unlock(instance->clk_src_reg_lock);
 430                return ME_ERRNO_INVALID_REF;
 431        }
 432
 433        outb(clk_src, instance->clk_src_reg);
 434        spin_unlock(instance->clk_src_reg_lock);
 435
 436        return ME_ERRNO_SUCCESS;
 437}
 438
 439static int me4600_ref_config(me8254_subdevice_t * instance, int ref)
 440{
 441        switch (ref) {
 442
 443        case ME_REF_CTR_EXTERNAL:
 444                // Nothing to do
 445                break;
 446
 447        default:
 448                PERROR("Invalid reference.\n");
 449//                      spin_unlock(instance->clk_src_reg_lock);
 450                return ME_ERRNO_INVALID_REF;
 451        }
 452
 453        return ME_ERRNO_SUCCESS;
 454}
 455
 456static int me8100_ref_config(me8254_subdevice_t * instance, int ref)
 457{
 458        switch (ref) {
 459
 460        case ME_REF_CTR_EXTERNAL:
 461                // Nothing to do
 462                break;
 463
 464        default:
 465                PERROR("Invalid reference.\n");
 466//                      spin_unlock(instance->clk_src_reg_lock);
 467                return ME_ERRNO_INVALID_REF;
 468        }
 469
 470        return ME_ERRNO_SUCCESS;
 471}
 472
 473static int me8254_io_single_config(struct me_subdevice *subdevice,
 474                                   struct file *filep,
 475                                   int channel,
 476                                   int single_config,
 477                                   int ref,
 478                                   int trig_chan,
 479                                   int trig_type, int trig_edge, int flags)
 480{
 481        me8254_subdevice_t *instance;
 482        int err;
 483
 484        PDEBUG("executed.\n");
 485
 486        if (channel) {
 487                PERROR("Invalid channel.\n");
 488                return ME_ERRNO_INVALID_CHANNEL;
 489        }
 490
 491        instance = (me8254_subdevice_t *) subdevice;
 492
 493        if (flags) {
 494                PERROR("Invalid flag specified.\n");
 495                return ME_ERRNO_INVALID_FLAGS;
 496        }
 497
 498        ME_SUBDEVICE_ENTER;
 499
 500        spin_lock(&instance->subdevice_lock);
 501        // Configure the counter modes
 502        if (instance->ctr_idx == 0) {
 503                if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
 504                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
 505                             ME8254_CTRL_BIN, instance->ctrl_reg);
 506                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
 507                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
 508                             ME8254_CTRL_BIN, instance->ctrl_reg);
 509                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
 510                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
 511                             ME8254_CTRL_BIN, instance->ctrl_reg);
 512                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
 513                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
 514                             ME8254_CTRL_BIN, instance->ctrl_reg);
 515                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
 516                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
 517                             ME8254_CTRL_BIN, instance->ctrl_reg);
 518                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
 519                        outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
 520                             ME8254_CTRL_BIN, instance->ctrl_reg);
 521                } else {
 522                        PERROR("Invalid single configuration.\n");
 523                        spin_unlock(&instance->subdevice_lock);
 524                        return ME_ERRNO_INVALID_SINGLE_CONFIG;
 525                }
 526        } else if (instance->ctr_idx == 1) {
 527                if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
 528                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
 529                             ME8254_CTRL_BIN, instance->ctrl_reg);
 530                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
 531                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
 532                             ME8254_CTRL_BIN, instance->ctrl_reg);
 533                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
 534                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
 535                             ME8254_CTRL_BIN, instance->ctrl_reg);
 536                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
 537                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
 538                             ME8254_CTRL_BIN, instance->ctrl_reg);
 539                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
 540                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
 541                             ME8254_CTRL_BIN, instance->ctrl_reg);
 542                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
 543                        outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
 544                             ME8254_CTRL_BIN, instance->ctrl_reg);
 545                } else {
 546                        PERROR("Invalid single configuration.\n");
 547                        spin_unlock(&instance->subdevice_lock);
 548                        return ME_ERRNO_INVALID_SINGLE_CONFIG;
 549                }
 550        } else {
 551                if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
 552                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
 553                             ME8254_CTRL_BIN, instance->ctrl_reg);
 554                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
 555                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
 556                             ME8254_CTRL_BIN, instance->ctrl_reg);
 557                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
 558                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
 559                             ME8254_CTRL_BIN, instance->ctrl_reg);
 560                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
 561                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
 562                             ME8254_CTRL_BIN, instance->ctrl_reg);
 563                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
 564                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
 565                             ME8254_CTRL_BIN, instance->ctrl_reg);
 566                } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
 567                        outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
 568                             ME8254_CTRL_BIN, instance->ctrl_reg);
 569                } else {
 570                        PERROR("Invalid single configuration.\n");
 571                        spin_unlock(&instance->subdevice_lock);
 572                        return ME_ERRNO_INVALID_SINGLE_CONFIG;
 573                }
 574        }
 575
 576        switch (instance->device_id) {
 577        case PCI_DEVICE_ID_MEILHAUS_ME1400:
 578        case PCI_DEVICE_ID_MEILHAUS_ME14E0:
 579        case PCI_DEVICE_ID_MEILHAUS_ME140A:
 580        case PCI_DEVICE_ID_MEILHAUS_ME14EA:
 581        case PCI_DEVICE_ID_MEILHAUS_ME140B:
 582        case PCI_DEVICE_ID_MEILHAUS_ME14EB:
 583                err = me1400_ab_ref_config(instance, ref);
 584
 585                if (err) {
 586                        spin_unlock(&instance->subdevice_lock);
 587                        return err;
 588                }
 589
 590                break;
 591
 592        case PCI_DEVICE_ID_MEILHAUS_ME140C:
 593        case PCI_DEVICE_ID_MEILHAUS_ME140D:
 594                err = me1400_cd_ref_config(instance, ref);
 595
 596                if (err) {
 597                        spin_unlock(&instance->subdevice_lock);
 598                        return err;
 599                }
 600
 601                break;
 602
 603        case PCI_DEVICE_ID_MEILHAUS_ME4610:
 604        case PCI_DEVICE_ID_MEILHAUS_ME4660:
 605        case PCI_DEVICE_ID_MEILHAUS_ME4660I:
 606        case PCI_DEVICE_ID_MEILHAUS_ME4660S:
 607        case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
 608        case PCI_DEVICE_ID_MEILHAUS_ME4670:
 609        case PCI_DEVICE_ID_MEILHAUS_ME4670I:
 610        case PCI_DEVICE_ID_MEILHAUS_ME4670S:
 611        case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
 612        case PCI_DEVICE_ID_MEILHAUS_ME4680:
 613        case PCI_DEVICE_ID_MEILHAUS_ME4680I:
 614        case PCI_DEVICE_ID_MEILHAUS_ME4680S:
 615        case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
 616                err = me4600_ref_config(instance, ref);
 617
 618                if (err) {
 619                        spin_unlock(&instance->subdevice_lock);
 620                        return err;
 621                }
 622
 623                break;
 624
 625        case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
 626        case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
 627                err = me8100_ref_config(instance, ref);
 628
 629                if (err) {
 630                        spin_unlock(&instance->subdevice_lock);
 631                        return err;
 632                }
 633
 634                break;
 635
 636        default:
 637                PERROR("Invalid device type.\n");
 638
 639                spin_unlock(&instance->subdevice_lock);
 640//                              spin_unlock(instance->clk_src_reg_lock);
 641                return ME_ERRNO_INVALID_SINGLE_CONFIG;
 642        }
 643        spin_unlock(&instance->subdevice_lock);
 644
 645        ME_SUBDEVICE_EXIT;
 646
 647        return ME_ERRNO_SUCCESS;
 648}
 649
 650static int me8254_io_single_read(struct me_subdevice *subdevice,
 651                                 struct file *filep,
 652                                 int channel,
 653                                 int *value, int time_out, int flags)
 654{
 655        me8254_subdevice_t *instance;
 656        uint16_t lo_byte;
 657        uint16_t hi_byte;
 658
 659        PDEBUG("executed.\n");
 660
 661        if (channel) {
 662                PERROR("Invalid channel.\n");
 663                return ME_ERRNO_INVALID_CHANNEL;
 664        }
 665
 666        instance = (me8254_subdevice_t *) subdevice;
 667
 668        if (flags) {
 669                PERROR("Invalid flag specified.\n");
 670                return ME_ERRNO_INVALID_FLAGS;
 671        }
 672
 673        ME_SUBDEVICE_ENTER;
 674
 675        spin_lock(&instance->subdevice_lock);
 676        spin_lock(instance->ctrl_reg_lock);
 677        if (instance->ctr_idx == 0)
 678                outb(ME8254_CTRL_SC0 | ME8254_CTRL_TLO, instance->ctrl_reg);
 679        else if (instance->ctr_idx == 1)
 680                outb(ME8254_CTRL_SC1 | ME8254_CTRL_TLO, instance->ctrl_reg);
 681        else
 682                outb(ME8254_CTRL_SC2 | ME8254_CTRL_TLO, instance->ctrl_reg);
 683
 684        lo_byte = inb(instance->val_reg);
 685        hi_byte = inb(instance->val_reg);
 686        spin_unlock(instance->ctrl_reg_lock);
 687
 688        *value = lo_byte | (hi_byte << 8);
 689        spin_unlock(&instance->subdevice_lock);
 690
 691        ME_SUBDEVICE_EXIT;
 692
 693        return ME_ERRNO_SUCCESS;
 694}
 695
 696static int me8254_io_single_write(struct me_subdevice *subdevice,
 697                                  struct file *filep,
 698                                  int channel,
 699                                  int value, int time_out, int flags)
 700{
 701        me8254_subdevice_t *instance;
 702
 703        PDEBUG("executed.\n");
 704
 705        if (channel) {
 706                PERROR("Invalid channel.\n");
 707                return ME_ERRNO_INVALID_CHANNEL;
 708        }
 709
 710        instance = (me8254_subdevice_t *) subdevice;
 711
 712        if (flags) {
 713                PERROR("Invalid flag specified.\n");
 714                return ME_ERRNO_INVALID_FLAGS;
 715        }
 716
 717        ME_SUBDEVICE_ENTER;
 718
 719        spin_lock(&instance->subdevice_lock);
 720        outb(value, instance->val_reg);
 721        outb((value >> 8), instance->val_reg);
 722        spin_unlock(&instance->subdevice_lock);
 723
 724        ME_SUBDEVICE_EXIT;
 725
 726        return ME_ERRNO_SUCCESS;
 727}
 728
 729static int me8254_query_number_channels(struct me_subdevice *subdevice,
 730                                        int *number)
 731{
 732        PDEBUG("executed.\n");
 733        *number = ME8254_NUMBER_CHANNELS;
 734        return ME_ERRNO_SUCCESS;
 735}
 736
 737static int me8254_query_subdevice_type(struct me_subdevice *subdevice,
 738                                       int *type, int *subtype)
 739{
 740        PDEBUG("executed.\n");
 741        *type = ME_TYPE_CTR;
 742        *subtype = ME_SUBTYPE_CTR_8254;
 743        return ME_ERRNO_SUCCESS;
 744}
 745
 746static int me8254_query_subdevice_caps(struct me_subdevice *subdevice,
 747                                       int *caps)
 748{
 749        me8254_subdevice_t *instance;
 750        PDEBUG("executed.\n");
 751        instance = (me8254_subdevice_t *) subdevice;
 752        *caps = instance->caps;
 753        return ME_ERRNO_SUCCESS;
 754}
 755
 756static int me8254_query_subdevice_caps_args(struct me_subdevice *subdevice,
 757                                            int cap, int *args, int count)
 758{
 759        PDEBUG("executed.\n");
 760
 761        if (count != 1) {
 762                PERROR("Invalid capability argument count.\n");
 763                return ME_ERRNO_INVALID_CAP_ARG_COUNT;
 764        }
 765
 766        if (cap == ME_CAP_CTR_WIDTH) {
 767                args[0] = ME8254_CTR_WIDTH;
 768        } else {
 769                PERROR("Invalid capability.\n");
 770                return ME_ERRNO_INVALID_CAP;
 771        }
 772
 773        return ME_ERRNO_SUCCESS;
 774}
 775
 776static uint32_t me1400AB_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
 777                                     unsigned int ctr_idx)
 778{
 779        switch (me8254_idx) {
 780
 781        case 0:
 782                return (reg_base + ME1400AB_8254_A_0_VAL_REG + ctr_idx);
 783
 784        default:
 785                return (reg_base + ME1400AB_8254_B_0_VAL_REG + ctr_idx);
 786        }
 787
 788        return 0;
 789}
 790
 791static uint32_t me1400AB_get_ctrl_reg(uint32_t reg_base,
 792                                      unsigned int me8254_idx,
 793                                      unsigned int ctr_idx)
 794{
 795        switch (me8254_idx) {
 796        case 0:
 797                return (reg_base + ME1400AB_8254_A_CTRL_REG);
 798
 799        default:
 800                return (reg_base + ME1400AB_8254_B_CTRL_REG);
 801        }
 802
 803        return 0;
 804}
 805
 806static uint32_t me1400AB_get_clk_src_reg(uint32_t reg_base,
 807                                         unsigned int me8254_idx,
 808                                         unsigned int ctr_idx)
 809{
 810        switch (me8254_idx) {
 811        case 0:
 812                return (reg_base + ME1400AB_CLK_SRC_REG);
 813
 814        default:
 815                return (reg_base + ME1400AB_CLK_SRC_REG);
 816        }
 817
 818        return 0;
 819}
 820
 821static uint32_t me1400CD_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
 822                                     unsigned int ctr_idx)
 823{
 824        switch (me8254_idx) {
 825        case 0:
 826                return (reg_base + ME1400C_8254_A_0_VAL_REG + ctr_idx);
 827
 828        case 1:
 829                return (reg_base + ME1400C_8254_B_0_VAL_REG + ctr_idx);
 830
 831        case 2:
 832                return (reg_base + ME1400C_8254_C_0_VAL_REG + ctr_idx);
 833
 834        case 3:
 835                return (reg_base + ME1400C_8254_D_0_VAL_REG + ctr_idx);
 836
 837        case 4:
 838                return (reg_base + ME1400C_8254_E_0_VAL_REG + ctr_idx);
 839
 840        case 5:
 841                return (reg_base + ME1400D_8254_A_0_VAL_REG + ctr_idx);
 842
 843        case 6:
 844                return (reg_base + ME1400D_8254_B_0_VAL_REG + ctr_idx);
 845
 846        case 7:
 847                return (reg_base + ME1400D_8254_C_0_VAL_REG + ctr_idx);
 848
 849        case 8:
 850                return (reg_base + ME1400D_8254_D_0_VAL_REG + ctr_idx);
 851
 852        default:
 853                return (reg_base + ME1400D_8254_E_0_VAL_REG + ctr_idx);
 854        }
 855
 856        return 0;
 857}
 858
 859static uint32_t me1400CD_get_ctrl_reg(uint32_t reg_base,
 860                                      unsigned int me8254_idx,
 861                                      unsigned int ctr_idx)
 862{
 863        switch (me8254_idx) {
 864        case 0:
 865                return (reg_base + ME1400C_8254_A_CTRL_REG);
 866
 867        case 1:
 868                return (reg_base + ME1400C_8254_B_CTRL_REG);
 869
 870        case 2:
 871                return (reg_base + ME1400C_8254_C_CTRL_REG);
 872
 873        case 3:
 874                return (reg_base + ME1400C_8254_D_CTRL_REG);
 875
 876        case 4:
 877                return (reg_base + ME1400C_8254_E_CTRL_REG);
 878
 879        case 5:
 880                return (reg_base + ME1400D_8254_A_CTRL_REG);
 881
 882        case 6:
 883                return (reg_base + ME1400D_8254_B_CTRL_REG);
 884
 885        case 7:
 886                return (reg_base + ME1400D_8254_C_CTRL_REG);
 887
 888        case 8:
 889                return (reg_base + ME1400D_8254_D_CTRL_REG);
 890
 891        default:
 892                return (reg_base + ME1400D_8254_E_CTRL_REG);
 893        }
 894
 895        return 0;
 896}
 897
 898static uint32_t me1400CD_get_clk_src_reg(uint32_t reg_base,
 899                                         unsigned int me8254_idx,
 900                                         unsigned int ctr_idx)
 901{
 902        switch (me8254_idx) {
 903        case 0:
 904                return (reg_base + ME1400C_CLK_SRC_0_REG);
 905
 906        case 1:
 907                return (reg_base + ME1400C_CLK_SRC_0_REG);
 908
 909        case 2:
 910                return (reg_base + ME1400C_CLK_SRC_1_REG);
 911
 912        case 3:
 913                return (reg_base + ME1400C_CLK_SRC_1_REG);
 914
 915        case 4:
 916                return (reg_base + ME1400C_CLK_SRC_2_REG);
 917
 918        case 5:
 919                return (reg_base + ME1400D_CLK_SRC_0_REG);
 920
 921        case 6:
 922                return (reg_base + ME1400D_CLK_SRC_0_REG);
 923
 924        case 7:
 925                return (reg_base + ME1400D_CLK_SRC_1_REG);
 926
 927        case 8:
 928                return (reg_base + ME1400D_CLK_SRC_1_REG);
 929
 930        default:
 931                return (reg_base + ME1400D_CLK_SRC_2_REG);
 932        }
 933
 934        return 0;
 935}
 936
 937static uint32_t me4600_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
 938                                   unsigned int ctr_idx)
 939{
 940        return (reg_base + ME4600_8254_0_VAL_REG + ctr_idx);
 941}
 942
 943static uint32_t me4600_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx,
 944                                    unsigned int ctr_idx)
 945{
 946        return (reg_base + ME4600_8254_CTRL_REG);
 947}
 948
 949static uint32_t me8100_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
 950                                   unsigned int ctr_idx)
 951{
 952        return (reg_base + ME8100_COUNTER_REG_0 + ctr_idx * 2);
 953}
 954
 955static uint32_t me8100_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx,
 956                                    unsigned int ctr_idx)
 957{
 958        return (reg_base + ME8100_COUNTER_CTRL_REG);
 959}
 960
 961me8254_subdevice_t *me8254_constructor(uint32_t device_id,
 962                                       uint32_t reg_base,
 963                                       unsigned int me8254_idx,
 964                                       unsigned int ctr_idx,
 965                                       spinlock_t * ctrl_reg_lock,
 966                                       spinlock_t * clk_src_reg_lock)
 967{
 968        me8254_subdevice_t *subdevice;
 969        int err;
 970
 971        PDEBUG("executed.\n");
 972
 973        // Allocate memory for subdevice instance
 974        subdevice = kmalloc(sizeof(me8254_subdevice_t), GFP_KERNEL);
 975
 976        if (!subdevice) {
 977                PERROR("Cannot get memory for 8254 instance.\n");
 978                return NULL;
 979        }
 980
 981        memset(subdevice, 0, sizeof(me8254_subdevice_t));
 982
 983        // Check if counter index is out of range
 984
 985        if (ctr_idx > 2) {
 986                PERROR("Counter index is out of range.\n");
 987                kfree(subdevice);
 988                return NULL;
 989        }
 990        // Initialize subdevice base class
 991        err = me_subdevice_init(&subdevice->base);
 992
 993        if (err) {
 994                PERROR("Cannot initialize subdevice base class instance.\n");
 995                kfree(subdevice);
 996                return NULL;
 997        }
 998        // Initialize spin locks.
 999        spin_lock_init(&subdevice->subdevice_lock);
1000        subdevice->ctrl_reg_lock = ctrl_reg_lock;
1001        subdevice->clk_src_reg_lock = clk_src_reg_lock;
1002
1003        // Save type of Meilhaus device
1004        subdevice->device_id = device_id;
1005
1006        // Save the indices
1007        subdevice->me8254_idx = me8254_idx;
1008        subdevice->ctr_idx = ctr_idx;
1009
1010        // Do device specific initialization
1011        switch (device_id) {
1012
1013        case PCI_DEVICE_ID_MEILHAUS_ME140A:
1014        case PCI_DEVICE_ID_MEILHAUS_ME14EA:
1015                // Check if 8254 index is out of range
1016                if (me8254_idx > 0) {
1017                        PERROR("8254 index is out of range.\n");
1018                        me_subdevice_deinit(&subdevice->base);
1019                        kfree(subdevice);
1020                        return NULL;
1021                }
1022
1023        case PCI_DEVICE_ID_MEILHAUS_ME140B:     // Fall through
1024        case PCI_DEVICE_ID_MEILHAUS_ME14EB:
1025                // Check if 8254 index is out of range
1026                if (me8254_idx > 1) {
1027                        PERROR("8254 index is out of range.\n");
1028                        me_subdevice_deinit(&subdevice->base);
1029                        kfree(subdevice);
1030                        return NULL;
1031                }
1032                // Initialize the counters capabilities
1033                if (ctr_idx == 0)
1034                        subdevice->caps =
1035                            ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
1036                            ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
1037                            ME_CAPS_CTR_CLK_EXTERNAL;
1038                else
1039                        subdevice->caps =
1040                            ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;
1041
1042                // Get the counters registers
1043                subdevice->val_reg =
1044                    me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx);
1045                subdevice->ctrl_reg =
1046                    me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
1047                subdevice->clk_src_reg =
1048                    me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
1049                break;
1050
1051        case PCI_DEVICE_ID_MEILHAUS_ME140C:
1052                // Check if 8254 index is out of range
1053                if (me8254_idx > 4) {
1054                        PERROR("8254 index is out of range.\n");
1055                        me_subdevice_deinit(&subdevice->base);
1056                        kfree(subdevice);
1057                        return NULL;
1058                }
1059
1060        case PCI_DEVICE_ID_MEILHAUS_ME140D:
1061                // Check if 8254 index is out of range
1062                if (me8254_idx > 9) {
1063                        PERROR("8254 index is out of range.\n");
1064                        me_subdevice_deinit(&subdevice->base);
1065                        kfree(subdevice);
1066                        return NULL;
1067                }
1068                // Initialize the counters capabilities
1069                if (ctr_idx == 0) {
1070                        if (me8254_idx == 0)
1071                                subdevice->caps =
1072                                    ME_CAPS_CTR_CLK_PREVIOUS |
1073                                    ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
1074                                    ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
1075                                    ME_CAPS_CTR_CLK_EXTERNAL;
1076                        else
1077                                subdevice->caps =
1078                                    ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
1079                                    ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
1080                                    ME_CAPS_CTR_CLK_EXTERNAL;
1081                } else
1082                        subdevice->caps =
1083                            ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;
1084
1085                // Get the counters registers
1086                subdevice->val_reg =
1087                    me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx);
1088                subdevice->ctrl_reg =
1089                    me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
1090                subdevice->clk_src_reg =
1091                    me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
1092                break;
1093
1094        case PCI_DEVICE_ID_MEILHAUS_ME4610:
1095        case PCI_DEVICE_ID_MEILHAUS_ME4660:
1096        case PCI_DEVICE_ID_MEILHAUS_ME4660I:
1097        case PCI_DEVICE_ID_MEILHAUS_ME4660S:
1098        case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
1099        case PCI_DEVICE_ID_MEILHAUS_ME4670:
1100        case PCI_DEVICE_ID_MEILHAUS_ME4670I:
1101        case PCI_DEVICE_ID_MEILHAUS_ME4670S:
1102        case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
1103        case PCI_DEVICE_ID_MEILHAUS_ME4680:
1104        case PCI_DEVICE_ID_MEILHAUS_ME4680I:
1105        case PCI_DEVICE_ID_MEILHAUS_ME4680S:
1106        case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
1107                // Check if 8254 index is out of range
1108                if (me8254_idx > 0) {
1109                        PERROR("8254 index is out of range.\n");
1110                        me_subdevice_deinit(&subdevice->base);
1111                        kfree(subdevice);
1112                        return NULL;
1113                }
1114                // Initialize the counters capabilities
1115                subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;
1116
1117                // Get the counters registers
1118                subdevice->val_reg =
1119                    me4600_get_val_reg(reg_base, me8254_idx, ctr_idx);
1120                subdevice->ctrl_reg =
1121                    me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
1122                subdevice->clk_src_reg = 0;     // Not used
1123                break;
1124
1125        case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
1126        case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
1127                // Check if 8254 index is out of range
1128                if (me8254_idx > 0) {
1129                        PERROR("8254 index is out of range.\n");
1130                        me_subdevice_deinit(&subdevice->base);
1131                        kfree(subdevice);
1132                        return NULL;
1133                }
1134                // Initialize the counters capabilities
1135                subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;
1136
1137                // Get the counters registers
1138                subdevice->val_reg =
1139                    me8100_get_val_reg(reg_base, me8254_idx, ctr_idx);
1140                subdevice->ctrl_reg =
1141                    me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
1142                subdevice->clk_src_reg = 0;     // Not used
1143                break;
1144
1145        case PCI_DEVICE_ID_MEILHAUS_ME4650:
1146        case PCI_DEVICE_ID_MEILHAUS_ME1400:
1147        case PCI_DEVICE_ID_MEILHAUS_ME14E0:
1148                PERROR("No 8254 subdevices available for subdevice device.\n");
1149                me_subdevice_deinit(&subdevice->base);
1150                kfree(subdevice);
1151                return NULL;
1152
1153        default:
1154                PERROR("Unknown device type.\n");
1155                me_subdevice_deinit(&subdevice->base);
1156                kfree(subdevice);
1157                return NULL;
1158        }
1159
1160        // Overload subdevice base class methods.
1161        subdevice->base.me_subdevice_io_reset_subdevice =
1162            me8254_io_reset_subdevice;
1163        subdevice->base.me_subdevice_io_single_config = me8254_io_single_config;
1164        subdevice->base.me_subdevice_io_single_read = me8254_io_single_read;
1165        subdevice->base.me_subdevice_io_single_write = me8254_io_single_write;
1166        subdevice->base.me_subdevice_query_number_channels =
1167            me8254_query_number_channels;
1168        subdevice->base.me_subdevice_query_subdevice_type =
1169            me8254_query_subdevice_type;
1170        subdevice->base.me_subdevice_query_subdevice_caps =
1171            me8254_query_subdevice_caps;
1172        subdevice->base.me_subdevice_query_subdevice_caps_args =
1173            me8254_query_subdevice_caps_args;
1174
1175        return subdevice;
1176}
1177
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.