1 /* esdpci266.c - support for ESD PCI/PMC 266 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
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/sja1000p.h"
15 #ifdef CAN_ENABLE_PCI_SUPPORT
17 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
18 #define ioread32 can_readl
19 #define iowrite32 can_writel
20 #define ioread8 can_readb
21 #define iowrite8 can_writeb
26 #define PLX_9056_VENDOR_ID 0x10B5
27 #define PLX_9056_DEVICE_ID 0x9056
28 #define ESDPCI266_PCI_VENDOR_ID 0x12FE
29 #define ESDPCI266_PCI_PRODUCT_ID 0x000E
31 /* PCI to local bus bridge PLX9050 */
32 #define ESDPCI266_BYTES_PER_CIRCUIT 0x100
34 void esdpci266_enable_irq(struct candevice_t *candev)
37 can_ioptr_t addr = candev->aux_base_addr + 0x68;
38 intcsr = ioread32(addr);
40 iowrite32(intcsr, addr);
43 void esdpci266_disable_irq(struct candevice_t *candev)
46 can_ioptr_t addr = candev->aux_base_addr + 0x68;
47 intcsr = ioread32(addr);
49 iowrite32(intcsr, addr);
52 int esdpci266_request_io(struct candevice_t *candev)
54 unsigned long addr, size;
55 can_ioptr_t remap_addr;
56 struct pci_dev *dev = candev->sysdevptr.pcidev;
58 /* request memory region for SJA chips window */
59 if (pci_request_region(dev, 2, "ESD PCI/PMC 266 - MEM") != 0) {
60 printk("lincan: request of memory range failed\n");
64 /* determine address and size of memory window #2 */
65 addr = pci_resource_start(dev, 2);
66 size = pci_resource_len(dev, 2);
68 /* remap to kernel address space */
69 remap_addr = ioremap(addr, size);
72 printk("lincan: Unable to access I/O memory at: 0x%lx\n", addr);
73 pci_release_region(dev, 2);
77 /* remap base device address */
78 can_base_addr_fixup(candev, remap_addr);
80 /* request memory region for PLX registers */
81 if (pci_request_region(dev, 0, "ESD PCI/PMC 266 - PLX9056") != 0) {
82 printk("lincan: request of memory range failed\n");
83 iounmap(candev->dev_base_addr);
84 pci_release_region(dev, 2);
88 /* determine address and size of memory window #2 */
89 addr = pci_resource_start(dev, 0);
90 size = pci_resource_len(dev, 0);
92 /* remap to kernel address space */
93 remap_addr = ioremap(addr, size);
96 printk("lincan: Unable to access I/O memory at: 0x%lx\n", addr);
97 pci_release_region(dev, 0);
98 iounmap(candev->dev_base_addr);
99 pci_release_region(dev, 2);
103 /* save address of PLX regs */
104 candev->aux_base_addr = remap_addr;
107 esdpci266_enable_irq(candev);
112 int esdpci266_release_io(struct candevice_t *candev)
114 esdpci266_disable_irq(candev);
115 iounmap(candev->aux_base_addr);
116 pci_release_region(candev->sysdevptr.pcidev, 0);
117 iounmap(candev->dev_base_addr);
118 pci_release_region(candev->sysdevptr.pcidev, 2);
122 void esdpci266_write_register(unsigned data, can_ioptr_t address)
124 iowrite8(data, address);
128 unsigned esdpci266_read_register(can_ioptr_t address)
130 return ioread8(address);
133 int esdpci266_reset(struct candevice_t *candev)
136 struct canchip_t *chip;
139 printk("lincan: resetting ESD PCI/PMC 266 hardware ...\n");
141 for (chip_nr = 0; chip_nr < candev->nr_all_chips; chip_nr++) {
142 if (!candev->chip[chip_nr])
145 printk("lincan: resetting SJA1000 chip nr. %d\n", chip_nr);
147 chip = candev->chip[chip_nr];
149 esdpci266_write_register(sjaMOD_RM,
150 chip->chip_base_addr + SJAMOD);
153 cdr = esdpci266_read_register(chip->chip_base_addr + SJACDR);
154 esdpci266_write_register(cdr | sjaCDR_PELICAN,
155 chip->chip_base_addr + SJACDR);
156 esdpci266_write_register(0, chip->chip_base_addr + SJAIER);
159 esdpci266_write_register(0, chip->chip_base_addr + SJAMOD);
160 while (esdpci266_read_register(chip->chip_base_addr + SJAMOD) &
165 esdpci266_write_register(0,
166 chip->chip_base_addr + SJAMOD);
169 cdr = esdpci266_read_register(chip->chip_base_addr + SJACDR);
170 esdpci266_write_register(cdr | sjaCDR_PELICAN,
171 chip->chip_base_addr + SJACDR);
172 esdpci266_write_register(0, chip->chip_base_addr + SJAIER);
173 esdpci266_read_register(chip->chip_base_addr + SJAIR);
179 int esdpci266_init_hw_data(struct candevice_t *candev)
181 struct pci_dev *pcidev = NULL;
183 printk("lincan: search for ESD PCI/PMC 266 board ...\n");
187 pci_find_device(PLX_9056_VENDOR_ID, PLX_9056_DEVICE_ID,
191 if (pcidev->subsystem_vendor != ESDPCI266_PCI_VENDOR_ID
192 || pcidev->subsystem_device != ESDPCI266_PCI_PRODUCT_ID) {
194 ("PLX9056 found, subvendor/subdevice mismatch (%04d:%04d)\n",
195 pcidev->subsystem_vendor,
196 pcidev->subsystem_device);
199 } while (can_check_dev_taken(pcidev));
201 if (pci_enable_device(pcidev)) {
202 printk("lincan: pci_enable_device() failed\n");
206 candev->sysdevptr.pcidev = pcidev;
208 candev->io_addr = pci_resource_start(pcidev, 2);
209 candev->dev_base_addr = 0;
210 candev->res_addr = 0;
211 candev->nr_82527_chips = 0;
212 candev->nr_sja1000_chips = 2;
213 candev->nr_all_chips = 2;
215 printk("lincan: ESD PCI/PMC 266 board found (%lx)\n", candev->io_addr);
220 int esdpci266_init_chip_data(struct candevice_t *candev, int chipnr)
222 if (candev->sysdevptr.pcidev == NULL)
225 candev->chip[chipnr]->chip_irq = candev->sysdevptr.pcidev->irq;
226 sja1000p_fill_chipspecops(candev->chip[chipnr]);
227 candev->chip[chipnr]->chip_base_addr =
228 candev->dev_base_addr + chipnr * ESDPCI266_BYTES_PER_CIRCUIT;
229 candev->chip[chipnr]->clock = 16000000;
230 candev->chip[chipnr]->int_clk_reg = 0;
231 candev->chip[chipnr]->int_bus_reg = 0;
232 candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
233 candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
234 candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
238 int esdpci266_init_obj_data(struct canchip_t *chip, int objnr)
240 chip->msgobj[objnr]->obj_base_addr = chip->chip_base_addr;
244 int esdpci266_program_irq(struct candevice_t *candev)
249 int esdpci266_register(struct hwspecops_t *hwspecops)
251 hwspecops->request_io = esdpci266_request_io;
252 hwspecops->release_io = esdpci266_release_io;
253 hwspecops->reset = esdpci266_reset;
254 hwspecops->init_hw_data = esdpci266_init_hw_data;
255 hwspecops->init_chip_data = esdpci266_init_chip_data;
256 hwspecops->init_obj_data = esdpci266_init_obj_data;
257 hwspecops->write_register = esdpci266_write_register;
258 hwspecops->read_register = esdpci266_read_register;
259 hwspecops->program_irq = esdpci266_program_irq;
263 #endif /* CAN_ENABLE_PCI_SUPPORT */