linux/drivers/char/tb0219.c
<<
>>
Prefs
   1/*
   2 *  Driver for TANBAC TB0219 base board.
   3 *
   4 *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20#include <linux/platform_device.h>
  21#include <linux/fs.h>
  22#include <linux/init.h>
  23#include <linux/module.h>
  24
  25#include <asm/io.h>
  26#include <asm/reboot.h>
  27#include <asm/vr41xx/giu.h>
  28#include <asm/vr41xx/tb0219.h>
  29
  30MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
  31MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
  32MODULE_LICENSE("GPL");
  33
  34static int major;       /* default is dynamic major device number */
  35module_param(major, int, 0);
  36MODULE_PARM_DESC(major, "Major device number");
  37
  38static void (*old_machine_restart)(char *command);
  39static void __iomem *tb0219_base;
  40static DEFINE_SPINLOCK(tb0219_lock);
  41
  42#define tb0219_read(offset)             readw(tb0219_base + (offset))
  43#define tb0219_write(offset, value)     writew((value), tb0219_base + (offset))
  44
  45#define TB0219_START    0x0a000000UL
  46#define TB0219_SIZE     0x20UL
  47
  48#define TB0219_LED                      0x00
  49#define TB0219_GPIO_INPUT               0x02
  50#define TB0219_GPIO_OUTPUT              0x04
  51#define TB0219_DIP_SWITCH               0x06
  52#define TB0219_MISC                     0x08
  53#define TB0219_RESET                    0x0e
  54#define TB0219_PCI_SLOT1_IRQ_STATUS     0x10
  55#define TB0219_PCI_SLOT2_IRQ_STATUS     0x12
  56#define TB0219_PCI_SLOT3_IRQ_STATUS     0x14
  57
  58typedef enum {
  59        TYPE_LED,
  60        TYPE_GPIO_OUTPUT,
  61} tb0219_type_t;
  62
  63/*
  64 * Minor device number
  65 *       0 = 7 segment LED
  66 *
  67 *      16 = GPIO IN 0
  68 *      17 = GPIO IN 1
  69 *      18 = GPIO IN 2
  70 *      19 = GPIO IN 3
  71 *      20 = GPIO IN 4
  72 *      21 = GPIO IN 5
  73 *      22 = GPIO IN 6
  74 *      23 = GPIO IN 7
  75 *
  76 *      32 = GPIO OUT 0
  77 *      33 = GPIO OUT 1
  78 *      34 = GPIO OUT 2
  79 *      35 = GPIO OUT 3
  80 *      36 = GPIO OUT 4
  81 *      37 = GPIO OUT 5
  82 *      38 = GPIO OUT 6
  83 *      39 = GPIO OUT 7
  84 *
  85 *      48 = DIP switch 1
  86 *      49 = DIP switch 2
  87 *      50 = DIP switch 3
  88 *      51 = DIP switch 4
  89 *      52 = DIP switch 5
  90 *      53 = DIP switch 6
  91 *      54 = DIP switch 7
  92 *      55 = DIP switch 8
  93 */
  94
  95static inline char get_led(void)
  96{
  97        return (char)tb0219_read(TB0219_LED);
  98}
  99
 100static inline char get_gpio_input_pin(unsigned int pin)
 101{
 102        uint16_t values;
 103
 104        values = tb0219_read(TB0219_GPIO_INPUT);
 105        if (values & (1 << pin))
 106                return '1';
 107
 108        return '0';
 109}
 110
 111static inline char get_gpio_output_pin(unsigned int pin)
 112{
 113        uint16_t values;
 114
 115        values = tb0219_read(TB0219_GPIO_OUTPUT);
 116        if (values & (1 << pin))
 117                return '1';
 118
 119        return '0';
 120}
 121
 122static inline char get_dip_switch(unsigned int pin)
 123{
 124        uint16_t values;
 125
 126        values = tb0219_read(TB0219_DIP_SWITCH);
 127        if (values & (1 << pin))
 128                return '1';
 129
 130        return '0';
 131}
 132
 133static inline int set_led(char command)
 134{
 135        tb0219_write(TB0219_LED, command);
 136
 137        return 0;
 138}
 139
 140static inline int set_gpio_output_pin(unsigned int pin, char command)
 141{
 142        unsigned long flags;
 143        uint16_t value;
 144
 145        if (command != '0' && command != '1')
 146                return -EINVAL;
 147
 148        spin_lock_irqsave(&tb0219_lock, flags);
 149        value = tb0219_read(TB0219_GPIO_OUTPUT);
 150        if (command == '0')
 151                value &= ~(1 << pin);
 152        else
 153                value |= 1 << pin;
 154        tb0219_write(TB0219_GPIO_OUTPUT, value);
 155        spin_unlock_irqrestore(&tb0219_lock, flags);
 156
 157        return 0;
 158
 159}
 160
 161static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t len,
 162                                  loff_t *ppos)
 163{
 164        unsigned int minor;
 165        char value;
 166
 167        minor = iminor(file->f_path.dentry->d_inode);
 168        switch (minor) {
 169        case 0:
 170                value = get_led();
 171                break;
 172        case 16 ... 23:
 173                value = get_gpio_input_pin(minor - 16);
 174                break;
 175        case 32 ... 39:
 176                value = get_gpio_output_pin(minor - 32);
 177                break;
 178        case 48 ... 55:
 179                value = get_dip_switch(minor - 48);
 180                break;
 181        default:
 182                return -EBADF;
 183        }
 184
 185        if (len <= 0)
 186                return -EFAULT;
 187
 188        if (put_user(value, buf))
 189                return -EFAULT;
 190
 191        return 1;
 192}
 193
 194static ssize_t tanbac_tb0219_write(struct file *file, const char __user *dr 178        case 48 ... 55:
len,
 *ppos)
 1{
  971     1   return (char)minor;
 1}
spin_lockle" claa href="drivers/char/tb0219.c#L62" id="sref">spin_lockl#L6="drivers/char/t#L6" id="L165" class="line" name="L165"> 1 */value = len,
 200sta2ic cor;
file" class="srL19f">ss="sred="L158" class="line" name="L158"> 201{
<2 href="drivers/char/tb0229.c#L20har/tb0219.c#>command)
'0" id="L165" class="line" name="L165"> 20/a>#inclu     203
uint16_t iminor(file->f_path.dentry->d_inode);
 204   2    value">minor) {
 205   2    if ( 206   2            return '1'spin_lockl#L6="drivers/char/t#L6" idinor( 20/a>#incluhref="drivers/char/tb0212.c#L120ers/char/tb0219.c#L178" id="L178" class="line" name="L178"> 208   2    return  209}
<2 href="drivers/char/tb0229.c#L20" class="sref">value = (,
  21sta2href="drivers/char/tb0212.c#L121ers/char/tb0219.c#L181" id="L181" class="line" name="L181"> 211sta2ic  212{
<2 href="drivers/char/tb0229.c#L21de=EBADF" class="sref">EBADF;
 213   2     214
 215   2    valueforr) {
;
 216   2    if ('1'put_user('0" id=_t * 217   2            return '1'EBADF;
 218
 219   2    return value<">minor) {
 220}
<2 href="drivers/char/tb0229.c#L22ers/char/tb0219.c#L18219.cr( 221
;
file" class="srL19f">ss="sre/a> = ->'0" idd="L168" class="line" name="L168"> 222sta2ic  223{
<2 href="drivers/char/tb0229.c#L22" class="sref">value<219.cr(,
 224
;
file" class="srL19f">ss="sre/a> = );
'0" idd="L168" class="line" name="L168"> 225   2href="drivers/char/tb0212.c#L1225e=EFAULT" class="sreeeeeeeee1" id="L181" class="line" name="L181"> 226   2    '1' 2#incluude < 2#incluude <'1'put_user(file" class="srL19f">ss="s;d="L186" class="line" name="L186"> 2
value 230   2    return  231}
<2 href="drivers/char/tb0229.c#L23" id="L122" class="line" name="L122"> 232
 233sta2ic  234
 235   2    inlincor;
file *)
 *file, const char  236
  97237   2    return 0;
minor;
 238}
<2 href="drivers/char/tb0229.c#L23" id="L119" class="line" name="L119"> 239
value = iminor(file-> 240sta2ic minor) {
 241{
<2 href="drivers/char/tb0229.c#L24har/tb0219.c#>19.cd="L170" class="line" name="L170"> 242   2    unsigned long  243   2    uin219.c#L176" id="L176" class="line" name="L176"> 244
uin219.c#L179" id="L179" class="line" name="L179"> 245   2    if (->);
 246
 247
 248   2     249   2     250   2    if ( 251   2             252   2    else
 253   2            inlincor;
file *)
 *file, const char  254   2     255   2     256
 257
  58258
file *spin_lockle" clafopfef="+code=__usele" clafopf">imino="L135" class="line" name="L135"> 259   2 href="drivers/char/tb0229.c#L2ass="sref">TYPry-> 260
( 261   2ic ( 262   2                        2     2a href="+code=ry->( 263   2 href="drivers/char/tb0229.c#L263UT" class="sry->( 264   2    unsigned int ->( 265   2    char  266
 267   2    inlin id=>tb0219_read(>comma>, const char  268   2    switch ( 269   2    case 0:
value = r( 270   2             271   2            break;
 272   2    case 16 ... 23:
inlin id=>tb0219_read( id="L96" class="line" name="L96">  96273   2             274   2            break;
  94275   2    case 32 ... 39:
r();
);
 276   2            values = file" class="sr=r41xx_ref=_lo_leve>ref">r();
 277   2            break;
  58278   2    case 48 ... 55:
  94279   2            value = r();
);
 280   2            break;
r();
 281   2    default:
 282   2            return -  94283   2    }
uint16_t r();
);
 284   2href="drivers/char/tb0212.c#L128="sref">values = file" class="sr=r41xx_ref=_lo_leve>ref">r();
 285   2    if ( 286   2            return - 287
inlincor;
spin_lockle" claprobtruct file *, const char  288   2    if ( 289   2            return -;
file" class="srL19f">ss="="L168" class="line" name="L168"> 290
 291   2    return 1;
r();
)
);
 292}
<2 href="drivers/char/tb0229.c#L29de=EBADF" class="sref">EBADF;
 293   2href="drivers/char/tb0212.c#L124" id="L194" class="line" name="L194"> 294sta2ic tb0219_write((iminor(r();
 2178  2     case 48 ... 55:
put_user(((imin)
);
 2{
'1'spin_lockreleref_mem_regio/char/tb0219.c#LL1leref_mem_regio/ref">r();
 217
'1';
;
 298   2href="drivers/char/tb02129.c#L29save" class="="L184" class="line" name="L184"> 2 */ 300sta3ic file" class="srL19f">ss="sre/a> = r(tb0219_lock, im=="L168" class="line" name="L168"> 301{
<3 href="drivers/char/tb0239.c#L30har/tb0219.c#>put_user(file" class="srL19f">ss="s;d=o="L135" class="line" name="L135"> 30/a>#incl3    r((im=="L168" class="line" name="L168"> 303a>#incl3 ref="drivers/char/tb0213.c#L130" class="sref">value = (iminor( 304a>#incl3 c spin_lockreleref_mem_regio/char/tb0219.c#LL1leref_mem_regio/ref">r();
 305   3    if (file" class="srL19f">ss="="L168" class="line" name="L168"> 306   3            return '="L184" class="line" name="L184"> 30/a>#incl3href="drivers/char/tb0213.c#L138" id="L108" class="line" name="L108"> 308   3    return spin_lockold_machspaef=">irf="drivers/char/old_machspaef=">irf">iminor(irf="drivers/char/_machspaef=">irf">im="L168" class="line" name="L168"> 309   3 class="comment"> */value = irf="drivers/char/_machspaef=">irf">imf">tb0219_read( 3/0sta3href="drivers/char/tb0213.c#L131" id="L111" class="line" name="L111"> 311sta3ic =="L168" class="line" name="L168"> 312{
<3 href="drivers/char/tb0239.c#L31" id="L133" class="line" name="L133"> 313   3    put_user( 314
spin_lockmajivers/char/tb0219.ajiv8" iin
<file" class="srL19f">ss="="L168" class="line" name="L168"> 315   3    r(spin_lockmajivers/char/tb0219.ajiv8" i=="L168" class="line" name="L168"> 316   3    if ('="L184" class="line" name="L184"> 317   3            return  318
 319   3    return  320}
<3 href="drivers/char/tb0239.c#L32" id="L111" class="line" name="L111"> 321
ssizcor;
spin_lockle" claremomp;file *, const char  322sta3ic  323{
<3 href="drivers/char/tb0239.c#L32ss="sref">uint16_t imf">tb0219_readold_machspaef=">irf="drivers/char/old_machspaef=">irf">im="L158" class="line" name="L158"> 324
 325   3href="drivers/char/tb0213.c#L132vers/char/tb0tb0219_read+ounmapvers/char/tb021counmapref">r((im=="L168" class="line" name="L168"> 326   3    values = ((iminor( 3#incl3ude < 3#incl3ude <spin_lockreleref_mem_regio/char/tb0219.c#LL1leref_mem_regio/ref">r();
 3
 330   3    return  331}
<3 href="drivers/char/tb0239.c#L332" id="L132" class="line" name="L132"> 332
 333sta3ic inlinfile *, const char  334
 335   3    inlinfile *spin_lockle" cladevict_ds="liruct imino="L135" class="line" name="L135"> 336
valuery->tb0219_read( 337   3    return 0;
->tb0219_read__devexif_pvers/char/tb021__devexif_pref">r( 33/a>#incl3 href="drivers/char/tb0239.c#L338b0219_read" ry->imiass="sre">="L135" class="line" name="L135"> 33/a>
value-> 340sta3ic  341{
<3 href="drivers/char/tb0239.c#L34har/tb0219.c#},"L135" class="line" name="L135"> 342
 343   3     344
ssizcor;
spin_locklode=file" clainif="drivers/char/tode=file" clainifref"> id="L96" class="line" name="L96">  96345   3    if ( 346
;
file" class="srL19f">ss="="L168" class="line" name="L168"> 347
 348   3    spin_locktb0219.platform_devictruct ('platform_devict_alloeref">ra href="drivers/char/quot;aa hre/quot;151" id, -1=="L168" class="line" name="L168"> 349   3    value<>put!sref">spin_locktb0219.platform_devictruct   96350   3    if ( 351   3             352   3    else
 = file" class="srL19f">ss="sre/a> = r( 353   3            put_user(file" class="srL19f">ss="s;d=o="L135" class="line" name="L135"> 354   3    spin_lockplatform_devict_puf="drivers/char/platform_devict_pufref">r( 355   3    file" class="srL19f">ss="="L168" class="line" name="L168"> 356
'="L184" class="line" name="L184"> 357
  58358
spin_lockre9f">file" class="srL19f">ss="sre/a> = ref">tb0219_lock, im"="L168" class="line" name="L168"> 359   3 href="drivers/char/tb0239.c#L35"sref">value<>put_user(file" class="srL19f">ss="s;d="L168" class="line" name="L168"> 360
value = r( 361   3ic  362   3                        3     36 href="+code=span>;
<file" class="srL19f">ss="="L168" class="line" name="L168"> 363   3 href="drivers/char/tb0239.c#L36"sref="L184" class="line" name="L184"> 364   3    unsigned int  365   3    char inlin id=>tb0219_read__exif="drivers/char/__exif id="sref">spin_locklode=file" claexif="drivers/char/lode=file" claexifref"> id="L96" class="line" name="L96">  96366
  97367   3    minor = ref">tb0219_lock, im"="L168" class="line" name="L168"> 368   3    switch (spin_lockplatform_devict_unregisterruct r( 369   3    case 0:
 370   3             371   3            break;
spin_lockmoduleainif="drivers/char/moduleainifref">r( 372   3    case 16 ... 23:
spin_lockmoduleaexif="drivers/char/moduleaexifref">r( 373   3            


The original LXR software by th.cr(LXR tb02unify8" is(lxr@
lxr. (Redpill L