2a88bebdfb10d076cc670c1418664cc2fa0d8175
[lincan.git] / lincan / src / pcan_pci.c
1 /* pcan_pci.c - support for PEAK System PCAN-PCI cards
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.3  17 Jun 2004
8  */
9
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/sja1000p.h"
14
15 #ifdef CAN_ENABLE_PCI_SUPPORT
16
17 /* This card is based on Infineon's PSB 4600 PITA bridge */
18
19 #define PITA_ICR         0x00        /* interrupt control register */
20 #define PITA_ICR_STAT    0x00        /*   - status/IRQ pending bits */
21 #define PITA_ICR_IEN     0x02        /*   - IRQ enable bits */
22 #define PITA_GPIOICR     0x18        /* general purpose IO interface control register */
23 #define PITA_MISC        0x1C        /* misc register */
24
25 #define PCAN_PCI_CONFIG_PORT_SIZE 0x1000  /* size of the config io-memory */
26 #define PCAN_PCI_PORT_SIZE        0x0400  /* size of a channel io-memory */
27
28 #define PCAN_PCI_VENDOR_ID      0x001C  /* PCAN-PCI and clones vednor id */
29 #define PCAN_PCI_PRODUCT_ID     0x0001  /* PCAN-PCI and clones device ID */
30
31 /* Standard value: Pushpull  (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1) */
32 #define PCAN_PCI_OCR_DEFAULT_STD 0xFA
33
34 #define PCAN_PCI_BYTES_PER_CIRCUIT 0x400
35 #define PCAN_PCI_BYTES_PER_REG     4
36
37 /* Conversion of the chip index to IRQ register mask */
38 static unsigned int pcan_pci_idx2mask[4]={
39         0x0002,
40         0x0001,
41         0x0040,
42         0x0080
43 };
44
45 void pcan_pci_disconnect_irq(struct candevice_t *candev)
46 {
47         u16 w;
48
49         /* disable interrupts sources */
50         w = can_readw(candev->aux_base_addr + PITA_ICR_IEN);
51         can_writew(w & ~0xC3, candev->aux_base_addr + PITA_ICR_IEN);
52 }
53
54 void pcan_pci_connect_irq(struct candevice_t *candev)
55 {
56         u16 w;
57         int i;
58
59         /* clear previous accumulated status */
60         can_writew(0xC3, candev->aux_base_addr + PITA_ICR_STAT);
61
62         /* enable interrupts sources */
63         w = can_readw(candev->aux_base_addr + PITA_ICR_IEN);
64         for(i = 0; i < candev->nr_all_chips; i++)
65                 w |= pcan_pci_idx2mask[i];
66         can_writew(w, candev->aux_base_addr + PITA_ICR_IEN);
67 }
68
69
70 int pcan_pci_request_io(struct candevice_t *candev)
71 {
72         unsigned long ctrl_addr;
73         unsigned long io_addr;
74         int i;
75
76     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
77         if(pci_request_region(candev->sysdevptr.pcidev, 0, "pcan_pci_ctrl") != 0){
78                 CANMSG("Request of pcan_pci_ctrl range failed\n");
79                 return -ENODEV;
80         }else if(pci_request_region(candev->sysdevptr.pcidev, 1, "pcan_pci_io") != 0){
81                 CANMSG("Request of pcan_pci_io range failed\n");
82                 goto error_io;
83         }
84     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
85         if(pci_request_regions(candev->sysdevptr.pcidev, "pcan_pci") != 0){
86                 CANMSG("Request of pcan_pci_bridge regions failed\n");
87                 return -ENODEV;
88         }
89     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
90
91         ctrl_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
92         if (!(candev->aux_base_addr = ioremap(ctrl_addr,
93               pci_resource_len(candev->sysdevptr.pcidev,0)))) {
94                 CANMSG("Unable to access I/O memory at: 0x%lx\n", ctrl_addr);
95                 goto error_ioremap_ctrl;
96         }
97
98         io_addr=pci_resource_start(candev->sysdevptr.pcidev,1);;
99         if (!(candev->dev_base_addr = ioremap(io_addr,
100               pci_resource_len(candev->sysdevptr.pcidev,1)))) {
101                 CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
102                 goto error_ioremap_io;
103         }
104
105         candev->io_addr=io_addr;
106         candev->res_addr=ctrl_addr;
107
108         /*
109          * this is redundant with chip initialization, but remap address
110          * can change when resources are temporarily released
111          */
112         for(i=0;i<candev->nr_all_chips;i++) {
113                 struct canchip_t *chip=candev->chip[i];
114                 if(!chip) continue;
115                 chip->chip_base_addr = candev->dev_base_addr +
116                         i * PCAN_PCI_BYTES_PER_CIRCUIT;
117                 if(!chip->msgobj[0]) continue;
118                 chip->msgobj[0]->obj_base_addr=chip->chip_base_addr;
119         }
120
121         pcan_pci_disconnect_irq(candev);
122
123         /* Configure PITA */
124         can_writew(0x0005, candev->aux_base_addr + PITA_GPIOICR + 2);   /* set GPIO control register */
125
126         can_writeb(0x00, candev->aux_base_addr + PITA_GPIOICR);         /* enable all channels */
127
128         can_writeb(0x05, candev->aux_base_addr + PITA_MISC + 3);        /* toggle reset */
129         mdelay(5);
130         writeb(0x04, candev->aux_base_addr + PITA_MISC + 3);            /* leave parport mux mode */
131         wmb();
132
133         return 0;
134
135     error_ioremap_io:
136         iounmap(candev->aux_base_addr);
137     error_ioremap_ctrl:
138     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
139         pci_release_region(candev->sysdevptr.pcidev, 1);
140     error_io:
141         pci_release_region(candev->sysdevptr.pcidev, 0);
142     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
143         pci_release_regions(candev->sysdevptr.pcidev);
144     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
145
146         return -ENODEV;
147 }
148
149 int pcan_pci_release_io(struct candevice_t *candev)
150 {
151         pcan_pci_disconnect_irq(candev);
152
153         iounmap(candev->dev_base_addr);
154         iounmap(candev->aux_base_addr);
155     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
156         pci_release_region(candev->sysdevptr.pcidev, 1);
157         pci_release_region(candev->sysdevptr.pcidev, 0);
158     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
159         pci_release_regions(candev->sysdevptr.pcidev);
160     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
161
162         return 0;
163 }
164
165 void pcan_pci_write_register(unsigned data, can_ioptr_t address)
166 {
167         address += ((can_ioptr2ulong(address)&(PCAN_PCI_BYTES_PER_CIRCUIT-1))
168                                              *(PCAN_PCI_BYTES_PER_REG-1));
169         can_writeb(data,address);
170 }
171
172 unsigned pcan_pci_read_register(can_ioptr_t address)
173 {
174         address += ((can_ioptr2ulong(address)&(PCAN_PCI_BYTES_PER_CIRCUIT-1))
175                                              *(PCAN_PCI_BYTES_PER_REG-1));
176         return can_readb(address);
177 }
178
179 int pcan_pci_irq_handler(int irq, struct canchip_t *chip)
180 {
181         struct candevice_t *candev=chip->hostdevice;
182         int ret;
183         unsigned int icr_stat;
184         unsigned int chip_mask = pcan_pci_idx2mask[chip->chip_idx];
185
186         icr_stat = can_readw(candev->aux_base_addr + PITA_ICR_STAT);
187
188         if(!(icr_stat & chip_mask)) return CANCHIP_IRQ_NONE;
189
190         ret = sja1000p_irq_handler(irq, chip);
191
192         can_writew(chip_mask, candev->aux_base_addr + PITA_ICR_STAT);
193
194         return ret;
195 }
196
197 int pcan_pci_reset(struct candevice_t *candev)
198 {
199         int i=0,chip_nr;
200         struct canchip_t *chip;
201         unsigned cdr;
202
203         DEBUGMSG("Resetting pcan_pci hardware ...\n");
204
205         pcan_pci_disconnect_irq(candev);
206
207         for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
208                 if(!candev->chip[chip_nr]) continue;
209                 chip=candev->chip[chip_nr];
210
211                 pcan_pci_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
212                 udelay(1000);
213
214                 cdr=pcan_pci_read_register(chip->chip_base_addr+SJACDR);
215                 pcan_pci_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
216
217                 pcan_pci_write_register(0, chip->chip_base_addr+SJAIER);
218
219                 i=20;
220                 pcan_pci_write_register(0, chip->chip_base_addr+SJAMOD);
221                 while (pcan_pci_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
222                         if(!i--) return -ENODEV;
223                         udelay(1000);
224                         pcan_pci_write_register(0, chip->chip_base_addr+SJAMOD);
225                 }
226
227                 cdr=pcan_pci_read_register(chip->chip_base_addr+SJACDR);
228                 pcan_pci_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
229
230                 pcan_pci_write_register(0, chip->chip_base_addr+SJAIER);
231
232                 pcan_pci_read_register(chip->chip_base_addr+SJAIR);
233         }
234
235
236         pcan_pci_connect_irq(candev);
237
238         return 0;
239 }
240
241 int pcan_pci_init_hw_data(struct candevice_t *candev)
242 {
243         struct pci_dev *pcidev = NULL;
244         int i;
245         int nr_chips;
246         u16 subsysid;
247
248         do {
249                 pcidev = pci_find_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID, pcidev);
250                 if(pcidev == NULL) return -ENODEV;
251         } while(can_check_dev_taken(pcidev));
252
253         if (pci_enable_device (pcidev)){
254                 printk(KERN_CRIT "Enable PCAN_PCI failed\n");
255                 return -EIO;
256         }
257         candev->sysdevptr.pcidev=pcidev;
258
259         if(pci_read_config_word(pcidev, 0x2E, &subsysid))
260                 goto error_ret;
261
262         if(pci_write_config_word(pcidev, 0x04, 2))
263                 goto error_ret;
264
265         if(pci_write_config_word(pcidev, 0x44, 0))
266                 goto error_ret;
267
268         wmb();
269
270         for(i=0;i<2;i++){
271                 if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
272                         printk(KERN_CRIT "PCAN_PCI region %d is not memory\n",i);
273                         goto error_ret;
274                 }
275         }
276
277         candev->res_addr=pci_resource_start(pcidev,0);  /* Control registers */
278         candev->io_addr=pci_resource_start(pcidev,1);   /* SJA1000 chips are mapped here */
279         candev->dev_base_addr=pci_resource_start(pcidev,1);
280
281         /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
282
283         if(subsysid >= 12)
284                 nr_chips = 4;
285         else if(subsysid >= 10)
286                 nr_chips = 3;
287         else if(subsysid >= 4)
288                 nr_chips = 2;
289         else
290                 nr_chips = 1;
291
292         candev->nr_82527_chips=0;
293         candev->nr_sja1000_chips=nr_chips;
294         candev->nr_all_chips=nr_chips;
295
296         printk(KERN_INFO "Found PCAN_PCI device with %d chip(s)\n", nr_chips);
297
298         return 0;
299
300 error_ret:
301
302         printk(KERN_CRIT "Setup of PCAN_PCI failed\n");
303         pci_disable_device (pcidev);
304         return -EIO;
305 }
306
307 int pcan_pci_init_chip_data(struct candevice_t *candev, int chipnr)
308 {
309
310         if(candev->sysdevptr.pcidev==NULL)
311                 return -ENODEV;
312
313         /* special version of the IRQ handler is required for PCAN_PCI board */
314         candev->chip[chipnr]->chipspecops->irq_handler=pcan_pci_irq_handler;
315
316         candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
317
318         sja1000p_fill_chipspecops(candev->chip[chipnr]);
319         candev->chip[chipnr]->chip_base_addr=
320                         can_ioport2ioptr(candev->io_addr+chipnr*PCAN_PCI_BYTES_PER_CIRCUIT);
321         candev->chip[chipnr]->flags = 0;
322         candev->chip[chipnr]->int_cpu_reg = 0;
323         candev->chip[chipnr]->int_clk_reg = 0;
324         candev->chip[chipnr]->int_bus_reg = 0;
325         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
326         candev->chip[chipnr]->sja_ocr_reg = PCAN_PCI_OCR_DEFAULT_STD;
327         candev->chip[chipnr]->clock = 16000000;
328         candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
329
330         return 0;
331 }
332
333 int pcan_pci_init_obj_data(struct canchip_t *chip, int objnr)
334 {
335         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
336         return 0;
337 }
338
339 int pcan_pci_program_irq(struct candevice_t *candev)
340 {
341
342         return 0;
343 }
344
345 int pcan_pci_register(struct hwspecops_t *hwspecops)
346 {
347         hwspecops->request_io = pcan_pci_request_io;
348         hwspecops->release_io = pcan_pci_release_io;
349         hwspecops->reset = pcan_pci_reset;
350         hwspecops->init_hw_data = pcan_pci_init_hw_data;
351         hwspecops->init_chip_data = pcan_pci_init_chip_data;
352         hwspecops->init_obj_data = pcan_pci_init_obj_data;
353         hwspecops->write_register = pcan_pci_write_register;
354         hwspecops->read_register = pcan_pci_read_register;
355         hwspecops->program_irq = pcan_pci_program_irq;
356         return 0;
357 }
358
359
360 #endif /*CAN_ENABLE_PCI_SUPPORT*/