OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [tb0219.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  Driver for TANBAC TB0219 base board.
3
 *
4
 *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
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
 
30
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
31
MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
32
MODULE_LICENSE("GPL");
33
 
34
static int major;       /* default is dynamic major device number */
35
module_param(major, int, 0);
36
MODULE_PARM_DESC(major, "Major device number");
37
 
38
static void (*old_machine_restart)(char *command);
39
static void __iomem *tb0219_base;
40
static spinlock_t 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
 
58
typedef 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
 
95
static inline char get_led(void)
96
{
97
        return (char)tb0219_read(TB0219_LED);
98
}
99
 
100
static 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
 
111
static 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
 
122
static 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
 
133
static inline int set_led(char command)
134
{
135
        tb0219_write(TB0219_LED, command);
136
 
137
        return 0;
138
}
139
 
140
static 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
 
161
static 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
 
194
static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
195
                                   size_t len, loff_t *ppos)
196
{
197
        unsigned int minor;
198
        tb0219_type_t type;
199
        size_t i;
200
        int retval = 0;
201
        char c;
202
 
203
        minor = iminor(file->f_path.dentry->d_inode);
204
        switch (minor) {
205
        case 0:
206
                type = TYPE_LED;
207
                break;
208
        case 32 ... 39:
209
                type = TYPE_GPIO_OUTPUT;
210
                break;
211
        default:
212
                return -EBADF;
213
        }
214
 
215
        for (i = 0; i < len; i++) {
216
                if (get_user(c, data + i))
217
                        return -EFAULT;
218
 
219
                switch (type) {
220
                case TYPE_LED:
221
                        retval = set_led(c);
222
                        break;
223
                case TYPE_GPIO_OUTPUT:
224
                        retval = set_gpio_output_pin(minor - 32, c);
225
                        break;
226
                }
227
 
228
                if (retval < 0)
229
                        break;
230
        }
231
 
232
        return i;
233
}
234
 
235
static int tanbac_tb0219_open(struct inode *inode, struct file *file)
236
{
237
        unsigned int minor;
238
 
239
        minor = iminor(inode);
240
        switch (minor) {
241
        case 0:
242
        case 16 ... 23:
243
        case 32 ... 39:
244
        case 48 ... 55:
245
                return nonseekable_open(inode, file);
246
        default:
247
                break;
248
        }
249
 
250
        return -EBADF;
251
}
252
 
253
static int tanbac_tb0219_release(struct inode *inode, struct file *file)
254
{
255
        return 0;
256
}
257
 
258
static const struct file_operations tb0219_fops = {
259
        .owner          = THIS_MODULE,
260
        .read           = tanbac_tb0219_read,
261
        .write          = tanbac_tb0219_write,
262
        .open           = tanbac_tb0219_open,
263
        .release        = tanbac_tb0219_release,
264
};
265
 
266
static void tb0219_restart(char *command)
267
{
268
        tb0219_write(TB0219_RESET, 0);
269
}
270
 
271
static void tb0219_pci_irq_init(void)
272
{
273
        /* PCI Slot 1 */
274
        vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
275
        vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN, IRQ_LEVEL_LOW);
276
 
277
        /* PCI Slot 2 */
278
        vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
279
        vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN, IRQ_LEVEL_LOW);
280
 
281
        /* PCI Slot 3 */
282
        vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
283
        vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
284
}
285
 
286
static int __devinit tb0219_probe(struct platform_device *dev)
287
{
288
        int retval;
289
 
290
        if (request_mem_region(TB0219_START, TB0219_SIZE, "TB0219") == NULL)
291
                return -EBUSY;
292
 
293
        tb0219_base = ioremap(TB0219_START, TB0219_SIZE);
294
        if (tb0219_base == NULL) {
295
                release_mem_region(TB0219_START, TB0219_SIZE);
296
                return -ENOMEM;
297
        }
298
 
299
        retval = register_chrdev(major, "TB0219", &tb0219_fops);
300
        if (retval < 0) {
301
                iounmap(tb0219_base);
302
                tb0219_base = NULL;
303
                release_mem_region(TB0219_START, TB0219_SIZE);
304
                return retval;
305
        }
306
 
307
        spin_lock_init(&tb0219_lock);
308
 
309
        old_machine_restart = _machine_restart;
310
        _machine_restart = tb0219_restart;
311
 
312
        tb0219_pci_irq_init();
313
 
314
        if (major == 0) {
315
                major = retval;
316
                printk(KERN_INFO "TB0219: major number %d\n", major);
317
        }
318
 
319
        return 0;
320
}
321
 
322
static int __devexit tb0219_remove(struct platform_device *dev)
323
{
324
        _machine_restart = old_machine_restart;
325
 
326
        iounmap(tb0219_base);
327
        tb0219_base = NULL;
328
 
329
        release_mem_region(TB0219_START, TB0219_SIZE);
330
 
331
        return 0;
332
}
333
 
334
static struct platform_device *tb0219_platform_device;
335
 
336
static struct platform_driver tb0219_device_driver = {
337
        .probe          = tb0219_probe,
338
        .remove         = __devexit_p(tb0219_remove),
339
        .driver         = {
340
                .name   = "TB0219",
341
                .owner  = THIS_MODULE,
342
        },
343
};
344
 
345
static int __init tanbac_tb0219_init(void)
346
{
347
        int retval;
348
 
349
        tb0219_platform_device = platform_device_alloc("TB0219", -1);
350
        if (!tb0219_platform_device)
351
                return -ENOMEM;
352
 
353
        retval = platform_device_add(tb0219_platform_device);
354
        if (retval < 0) {
355
                platform_device_put(tb0219_platform_device);
356
                return retval;
357
        }
358
 
359
        retval = platform_driver_register(&tb0219_device_driver);
360
        if (retval < 0)
361
                platform_device_unregister(tb0219_platform_device);
362
 
363
        return retval;
364
}
365
 
366
static void __exit tanbac_tb0219_exit(void)
367
{
368
        platform_driver_unregister(&tb0219_device_driver);
369
        platform_device_unregister(tb0219_platform_device);
370
}
371
 
372
module_init(tanbac_tb0219_init);
373
module_exit(tanbac_tb0219_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.