linux/drivers/misc/c2port/c2port-duramar2150.c
<<
>>
Prefs
   1/*
   2 *  Silicon Labs C2 port Linux support for Eurotech Duramar 2150
   3 *
   4 *  Copyright (c) 2008 Rodolfo Giometti <giometti@linux.it>
   5 *  Copyright (c) 2008 Eurotech S.p.A. <info@eurotech.it>
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation
  10 */
  11
  12#include <linux/errno.h>
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/delay.h>
  17#include <linux/io.h>
  18#include <linux/ioport.h>
  19#include <linux/c2port.h>
  20
  21#define DATA_PORT       0x325
  22#define DIR_PORT        0x326
  23#define    C2D             (1 << 0)
  24#define    C2CK            (1 << 1)
  25
  26static DEFINE_MUTEX(update_lock);
  27
  28/*
  29 * C2 port operations
  30 */
  31
  32static void duramar2150_c2port_access(struct c2port_device *dev, int status)
  33{
  34        u8 v;
  35
  36        mutex_lock(&update_lock);
  37
  38        v = inb(DIR_PORT);
  39
  40        /* 0 = input, 1 = output */
  41        if (status)
  42                outb(v | (C2D | C2CK), DIR_PORT);
  43        else
  44                /* When access is "off" is important that both lines are set
  45                 * as inputs or hi-impedance */
  46                outb(v & ~(C2D | C2CK), DIR_PORT);
  47
  48        mutex_unlock(&update_lock);
  49}
  50
  51static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir)
  52{
  53        u8 v;
  54
  55        mutex_lock(&update_lock);
  56
  57        v = inb(DIR_PORT);
  58
  59        if (dir)
  60                outb(v & ~C2D, DIR_PORT);
  61        else
  62                outb(v | C2D, DIR_PORT);
  63
  64        mutex_unlock(&update_lock);
  65}
  66
  67static int duramar2150_c2port_c2d_get(struct c2port_device *dev)
  68{
  69        return inb(DATA_PORT) & C2D;
  70}
  71
  72static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status)
  73{
  74        u8 v;
  75
  76        mutex_lock(&update_lock);
  77
  78        v = inb(DATA_PORT);
  79
  80        if (status)
  81                outb(v | C2D, DATA_PORT);
  82        else
  83                outb(v & ~C2D, DATA_PORT);
  84
  85        mutex_unlock(&update_lock);
  86}
  87
  88static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status)
  89{
  90        u8 v;
  91
  92        mutex_lock(&update_lock);
  93
  94        v = inb(DATA_PORT);
  95
  96        if (status)
  97                outb(v | C2CK, DATA_PORT);
  98        else
  99                outb(v & ~C2CK, DATA_PORT);
 100
 101        mutex_unlock(&update_lock);
 102}
 103
 104static struct c2port_ops duramar2150_c2port_ops = {
 105        .block_size     = 512,  /* bytes */
 106        .blocks_num     = 30,   /* total flash size: 15360 bytes */
 107
 108        .access         = duramar2150_c2port_access,
 109        .c2d_dir        = duramar2150_c2port_c2d_dir,
 110        .c2d_get        = duramar2150_c2port_c2d_get,
 111        .c2d_set        = duramar2150_c2port_c2d_set,
 112        .c2ck_set       = duramar2150_c2port_c2ck_set,
 113};
 114
 115static struct c2port_device *duramar2150_c2port_dev;
 116
 117/*
 118 * Module stuff
 119 */
 120
 121static int __init duramar2150_c2port_init(void)
 122{
 123        struct resource *res;
 124        int ret = 0;
 125
 126        res = request_region(0x325, 2, "c2port");
 127        if (!res)
 128                return -EBUSY;
 129
 130        duramar2150_c2port_dev = c2port_device_register("uc",
 131                                        &duramar2150_c2port_ops, NULL);
 132        if (!duramar2150_c2port_dev) {
 133                ret = -ENODEV;
 134                goto free_region;
 135        }
 136
 137        return 0;
 138
 139free_region:
 140        release_region(0x325, 2);
 141        return ret;
 142}
 143
 144static void __exit duramar2150_c2port_exit(void)
 145{
 146        /* Setup the GPIOs as input by default (access = 0) */
 147        duramar2150_c2port_access(duramar2150_c2port_dev, 0);
 148
 149        c2port_device_unregister(duramar2150_c2port_dev);
 150
 151        release_region(0x325, 2);
 152}
 153
 154module_init(duramar2150_c2port_init);
 155module_exit(duramar2150_c2port_exit);
 156
 157MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 158MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150");
 159MODULE_LICENSE("GPL");
 160