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