Structured comments updated.
[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 "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/smartcan.h"
14 #include "../include/i82527.h"
15
16 int smartcan_irq=-1;
17 unsigned long smartcan_base=0x0;
18
19 static can_spinlock_t smartcan_port_lock=SPIN_LOCK_UNLOCKED;
20
21 int smartcan_request_io(struct candevice_t *candev)
22 {
23         if (!can_request_io_region(candev->io_addr,0x04,DEVICE_NAME)) {
24                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
25                 return -ENODEV;
26         }else {
27                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x04 - 1);
28         }
29         return 0;
30 }
31
32 int smartcan_release_io(struct candevice_t *candev)
33 {
34         can_release_io_region(candev->io_addr,0x04);
35
36         return 0;
37 }
38
39 int smartcan_reset(struct candevice_t *candev)
40 {
41         int i=0;
42
43         DEBUGMSG("Resetting smartcan hardware ...\n");
44         outb(0x00,candev->res_addr);
45         while (i < 1000000) {
46                 i++;
47                 outb(0x01,candev->res_addr);
48         }
49         outb(0x00,candev->res_addr); 
50
51         /* Check hardware reset status */
52         i=0;
53         outb(candev->io_addr+iCPU,candev->io_addr);
54         while ( (inb(candev->io_addr+1)&0x80) && (i<=15) ) {
55                 udelay(20000);
56                 i++;
57         }
58         if (i>=15) {
59                 CANMSG("Reset status timeout!\n");
60                 CANMSG("Please check your hardware.\n");
61                 return -ENODEV;
62         }
63         else
64                 DEBUGMSG("Chip0 reset status ok.\n");
65
66         return 0;
67
68
69 int smartcan_init_hw_data(struct candevice_t *candev)
70 {
71         candev->res_addr=candev->io_addr+0x02;
72         candev->nr_82527_chips=1;
73         candev->nr_sja1000_chips=0;
74         candev->nr_all_chips=1;
75         
76         return 0;
77 }
78
79 int smartcan_init_chip_data(struct candevice_t *candev, int chipnr)
80 {
81         candev->chip[chipnr]->chip_type="i82527";
82         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
83         candev->chip[chipnr]->clock = 16000000;
84         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
85         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
86         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
87         candev->chip[chipnr]->sja_cdr_reg = 0;
88         candev->chip[chipnr]->sja_ocr_reg = 0;
89         smartcan_irq=candev->chip[chipnr]->chip_irq;
90         smartcan_base=candev->chip[chipnr]->chip_base_addr;
91
92         return 0;
93 }
94
95 int smartcan_init_obj_data(struct chip_t *chip, int objnr)
96 {
97         chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
98
99         return 0;
100 }
101
102
103 void smartcan_write_register(unsigned char data, unsigned long address)
104 {
105         can_spin_irqflags_t flags;
106         can_spin_lock_irqsave(&smartcan_port_lock,flags);
107         outb(address-smartcan_base,smartcan_base);
108         outb(data,smartcan_base+1);
109         can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
110 }
111
112 unsigned smartcan_read_register(unsigned long address)
113 {
114         unsigned ret;
115         can_spin_irqflags_t flags;
116         can_spin_lock_irqsave(&smartcan_port_lock,flags);
117         outb(address-smartcan_base,smartcan_base);
118         ret=inb(smartcan_base+1);
119         can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
120         return ret;
121 }
122
123 int smartcan_program_irq(struct candevice_t *candev)
124 {
125         CANMSG("The 'smartcan' card doesn't have programmable interrupts\n");
126         return 0;
127 }
128
129 /* !!! Don't change this function !!! */
130 int smartcan_register(struct hwspecops_t *hwspecops)
131 {
132         hwspecops->request_io = smartcan_request_io;
133         hwspecops->release_io = smartcan_release_io;
134         hwspecops->reset = smartcan_reset;
135         hwspecops->init_hw_data = smartcan_init_hw_data;
136         hwspecops->init_chip_data = smartcan_init_chip_data;
137         hwspecops->init_obj_data = smartcan_init_obj_data;
138         hwspecops->write_register = smartcan_write_register;
139         hwspecops->read_register = smartcan_read_register;
140         hwspecops->program_irq = smartcan_program_irq;
141         return 0;
142 }