]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/smartcan.c
CAN driver infrastructure redesign to LinCAN-0.2 version
[lincan.git] / lincan / src / smartcan.c
1 /* smartcan.c
2  * Linux CAN-bus device driver.
3  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4  * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
5  * email:pisa@cmp.felk.cvut.cz
6  * This software is released under the GPL-License.
7  * Version lincan-0.2  9 Jul 2003
8  */ 
9
10 #include <linux/autoconf.h>
11
12 #include <linux/ioport.h>
13 #include <linux/delay.h>
14 #include <linux/sched.h>
15 #include <asm/errno.h>
16 #include <asm/io.h>
17 #include <asm/irq.h>
18
19 #include "../include/main.h"
20 #include "../include/smartcan.h"
21 #include "../include/i82527.h"
22
23 int smartcan_irq=-1;
24 unsigned long smartcan_base=0x0;
25
26 int smartcan_request_io(struct candevice_t *candev)
27 {
28         if (!can_request_io_region(candev->io_addr,0x04,DEVICE_NAME)) {
29                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
30                 return -ENODEV;
31         }else {
32                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x04 - 1);
33         }
34         return 0;
35 }
36
37 int smartcan_release_io(struct candevice_t *candev)
38 {
39         can_release_io_region(candev->io_addr,0x04);
40
41         return 0;
42 }
43
44 int smartcan_reset(struct candevice_t *candev)
45 {
46         int i=0;
47
48         DEBUGMSG("Resetting smartcan hardware ...\n");
49         outb(0x00,candev->res_addr);
50         while (i < 1000000) {
51                 i++;
52                 outb(0x01,candev->res_addr);
53         }
54         outb(0x00,candev->res_addr); 
55
56         /* Check hardware reset status */
57         i=0;
58         outb(candev->io_addr+iCPU,candev->io_addr);
59         while ( (inb(candev->io_addr+1)&0x80) && (i<=15) ) {
60                 udelay(20000);
61                 i++;
62         }
63         if (i>=15) {
64                 CANMSG("Reset status timeout!\n");
65                 CANMSG("Please check your hardware.\n");
66                 return -ENODEV;
67         }
68         else
69                 DEBUGMSG("Chip0 reset status ok.\n");
70
71         return 0;
72
73
74 int smartcan_init_hw_data(struct candevice_t *candev)
75 {
76         candev->res_addr=candev->io_addr+0x02;
77         candev->nr_82527_chips=1;
78         candev->nr_sja1000_chips=0;
79         candev->nr_all_chips=1;
80         
81         return 0;
82 }
83
84 int smartcan_init_chip_data(struct candevice_t *candev, int chipnr)
85 {
86         candev->chip[chipnr]->chip_type="i82527";
87         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
88         candev->chip[chipnr]->clock = 16000000;
89         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
90         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
91         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
92         candev->chip[chipnr]->sja_cdr_reg = 0;
93         candev->chip[chipnr]->sja_ocr_reg = 0;
94         smartcan_irq=candev->chip[chipnr]->chip_irq;
95         smartcan_base=candev->chip[chipnr]->chip_base_addr;
96
97         return 0;
98 }
99
100 int smartcan_init_obj_data(struct chip_t *chip, int objnr)
101 {
102         chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
103         chip->msgobj[objnr]->flags=0;
104
105         return 0;
106 }
107
108
109 void smartcan_write_register(unsigned char data, unsigned long address)
110 {
111         disable_irq(smartcan_irq);
112         outb(address-smartcan_base,smartcan_base);
113         outb(data,smartcan_base+1);
114         enable_irq(smartcan_irq);
115 }
116
117 unsigned smartcan_read_register(unsigned long address)
118 {
119         unsigned ret;
120         disable_irq(smartcan_irq);
121         outb(address-smartcan_base,smartcan_base);
122         ret=inb(smartcan_base+1);
123         enable_irq(smartcan_irq);
124         return ret;
125 }
126
127 int smartcan_program_irq(struct candevice_t *candev)
128 {
129         CANMSG("The 'smartcan' card doesn't have programmable interrupts\n");
130         return 0;
131 }
132
133 /* !!! Don't change this function !!! */
134 int smartcan_register(struct hwspecops_t *hwspecops)
135 {
136         hwspecops->request_io = smartcan_request_io;
137         hwspecops->release_io = smartcan_release_io;
138         hwspecops->reset = smartcan_reset;
139         hwspecops->init_hw_data = smartcan_init_hw_data;
140         hwspecops->init_chip_data = smartcan_init_chip_data;
141         hwspecops->init_obj_data = smartcan_init_obj_data;
142         hwspecops->write_register = smartcan_write_register;
143         hwspecops->read_register = smartcan_read_register;
144         hwspecops->program_irq = smartcan_program_irq;
145         return 0;
146 }