]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/smartcan.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / smartcan.c
1 /**************************************************************************/
2 /* File: smartcan.c - i82527 based card with indexed access               */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
7 /* Copyright (C) other parties found in actual files                      */
8 /* Funded by OCERA and FRESCOR IST projects                               */
9 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
10 /*                                                                        */
11 /* LinCAN is free software; you can redistribute it and/or modify it      */
12 /* under terms of the GNU General Public License as published by the      */
13 /* Free Software Foundation; either version 2, or (at your option) any    */
14 /* later version.  LinCAN is distributed in the hope that it will be      */
15 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
16 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
17 /* General Public License for more details. You should have received a    */
18 /* copy of the GNU General Public License along with LinCAN; see file     */
19 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
20 /* Cambridge, MA 02139, USA.                                              */
21 /*                                                                        */
22 /* To allow use of LinCAN in the compact embedded systems firmware        */
23 /* and RT-executives (RTEMS for example), main authors agree with next    */
24 /* special exception:                                                     */
25 /*                                                                        */
26 /* Including LinCAN header files in a file, instantiating LinCAN generics */
27 /* or templates, or linking other files with LinCAN objects to produce    */
28 /* an application image/executable, does not by itself cause the          */
29 /* resulting application image/executable to be covered by                */
30 /* the GNU General Public License.                                        */
31 /* This exception does not however invalidate any other reasons           */
32 /* why the executable file might be covered by the GNU Public License.    */
33 /* Publication of enhanced or derived LinCAN files is required although.  */
34 /**************************************************************************/
35
36 #include "../include/can.h"
37 #include "../include/can_sysdep.h"
38 #include "../include/main.h"
39 #include "../include/smartcan.h"
40 #include "../include/i82527.h"
41
42 int smartcan_irq=-1;
43 unsigned long smartcan_base=0x0;
44
45 static CAN_DEFINE_SPINLOCK(smartcan_port_lock);
46
47 int smartcan_request_io(struct candevice_t *candev)
48 {
49         if (!can_request_io_region(candev->io_addr,0x04,DEVICE_NAME)) {
50                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
51                 return -ENODEV;
52         }else {
53                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x04 - 1);
54         }
55         return 0;
56 }
57
58 int smartcan_release_io(struct candevice_t *candev)
59 {
60         can_release_io_region(candev->io_addr,0x04);
61
62         return 0;
63 }
64
65 int smartcan_reset(struct candevice_t *candev)
66 {
67         int i=0;
68
69         DEBUGMSG("Resetting smartcan hardware ...\n");
70         can_outb(0x00,candev->res_addr);
71         while (i < 1000000) {
72                 i++;
73                 can_outb(0x01,candev->res_addr);
74         }
75         can_outb(0x00,candev->res_addr);
76
77         /* Check hardware reset status */
78         i=0;
79         can_outb(candev->io_addr+iCPU,candev->io_addr);
80         while ( (can_inb(candev->io_addr+1)&0x80) && (i<=15) ) {
81                 mdelay(20);
82                 i++;
83         }
84         if (i>=15) {
85                 CANMSG("Reset status timeout!\n");
86                 CANMSG("Please check your hardware.\n");
87                 return -ENODEV;
88         }
89         else
90                 DEBUGMSG("Chip0 reset status ok.\n");
91
92         return 0;
93 }
94
95 int smartcan_init_hw_data(struct candevice_t *candev)
96 {
97         candev->res_addr=candev->io_addr+0x02;
98         candev->nr_82527_chips=1;
99         candev->nr_sja1000_chips=0;
100         candev->nr_all_chips=1;
101
102         return 0;
103 }
104
105 int smartcan_init_chip_data(struct candevice_t *candev, int chipnr)
106 {
107         i82527_fill_chipspecops(candev->chip[chipnr]);
108         candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(candev->io_addr);
109         candev->chip[chipnr]->clock = 16000000;
110         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
111         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
112         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
113         candev->chip[chipnr]->sja_cdr_reg = 0;
114         candev->chip[chipnr]->sja_ocr_reg = 0;
115         smartcan_irq=candev->chip[chipnr]->chip_irq;
116         smartcan_base=candev->chip[chipnr]->chip_base_addr;
117
118         return 0;
119 }
120
121 int smartcan_init_obj_data(struct canchip_t *chip, int objnr)
122 {
123         chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
124
125         return 0;
126 }
127
128
129 void smartcan_write_register(unsigned data, can_ioptr_t address)
130 {
131         can_spin_irqflags_t flags;
132         can_spin_lock_irqsave(&smartcan_port_lock,flags);
133         can_outb(address-smartcan_base,smartcan_base);
134         can_outb(data,smartcan_base+1);
135         can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
136 }
137
138 unsigned smartcan_read_register(can_ioptr_t address)
139 {
140         unsigned ret;
141         can_spin_irqflags_t flags;
142         can_spin_lock_irqsave(&smartcan_port_lock,flags);
143         can_outb(address-smartcan_base,smartcan_base);
144         ret=can_inb(smartcan_base+1);
145         can_spin_unlock_irqrestore(&smartcan_port_lock,flags);
146         return ret;
147 }
148
149 int smartcan_program_irq(struct candevice_t *candev)
150 {
151         CANMSG("The 'smartcan' card doesn't have programmable interrupts\n");
152         return 0;
153 }
154
155 /* !!! Don't change this function !!! */
156 int smartcan_register(struct hwspecops_t *hwspecops)
157 {
158         hwspecops->request_io = smartcan_request_io;
159         hwspecops->release_io = smartcan_release_io;
160         hwspecops->reset = smartcan_reset;
161         hwspecops->init_hw_data = smartcan_init_hw_data;
162         hwspecops->init_chip_data = smartcan_init_chip_data;
163         hwspecops->init_obj_data = smartcan_init_obj_data;
164         hwspecops->write_register = smartcan_write_register;
165         hwspecops->read_register = smartcan_read_register;
166         hwspecops->program_irq = smartcan_program_irq;
167         return 0;
168 }