]>
Commit | Line | Data |
---|---|---|
3878fb6f WG |
1 | /* |
2 | * Copyright (C) 2008 Per Dalen <per.dalen@cnw.se> | |
3 | * | |
4 | * Parts of this software are based on (derived) the following: | |
5 | * | |
6 | * - Kvaser linux driver, version 4.72 BETA | |
7 | * Copyright (C) 2002-2007 KVASER AB | |
8 | * | |
9 | * - Lincan driver, version 0.3.3, OCERA project | |
10 | * Copyright (C) 2004 Pavel Pisa | |
11 | * Copyright (C) 2001 Arnaud Westenberg | |
12 | * | |
13 | * - Socketcan SJA1000 drivers | |
14 | * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com> | |
15 | * Copyright (c) 2002-2007 Volkswagen Group Electronic Research | |
16 | * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, | |
17 | * 38106 Braunschweig, GERMANY | |
18 | * | |
19 | * This program is free software; you can redistribute it and/or modify | |
20 | * it under the terms of the version 2 of the GNU General Public License | |
21 | * as published by the Free Software Foundation | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, but | |
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 | * General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program; if not, write to the Free Software Foundation, | |
30 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
31 | */ | |
32 | ||
33 | #include <linux/kernel.h> | |
34 | #include <linux/module.h> | |
35 | #include <linux/interrupt.h> | |
36 | #include <linux/netdevice.h> | |
37 | #include <linux/delay.h> | |
38 | #include <linux/pci.h> | |
3878fb6f WG |
39 | #include <linux/can/dev.h> |
40 | #include <linux/io.h> | |
41 | ||
42 | #include "sja1000.h" | |
43 | ||
44 | #define DRV_NAME "kvaser_pci" | |
45 | ||
46 | MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>"); | |
47 | MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards"); | |
48 | MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card"); | |
49 | MODULE_LICENSE("GPL v2"); | |
50 | ||
51 | #define MAX_NO_OF_CHANNELS 4 /* max no of channels on a single card */ | |
52 | ||
53 | struct kvaser_pci { | |
54 | int channel; | |
55 | struct pci_dev *pci_dev; | |
56 | struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1]; | |
57 | void __iomem *conf_addr; | |
58 | void __iomem *res_addr; | |
59 | int no_channels; | |
60 | u8 xilinx_ver; | |
61 | }; | |
62 | ||
63 | #define KVASER_PCI_CAN_CLOCK (16000000 / 2) | |
64 | ||
65 | /* | |
66 | * The board configuration is probably following: | |
67 | * RX1 is connected to ground. | |
68 | * TX1 is not connected. | |
69 | * CLKO is not connected. | |
70 | * Setting the OCR register to 0xDA is a good idea. | |
71 | * This means normal output mode , push-pull and the correct polarity. | |
72 | */ | |
73 | #define KVASER_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) | |
74 | ||
75 | /* | |
76 | * In the CDR register, you should set CBP to 1. | |
77 | * You will probably also want to set the clock divider value to 0 | |
78 | * (meaning divide-by-2), the Pelican bit, and the clock-off bit | |
79 | * (you will have no need for CLKOUT anyway). | |
80 | */ | |
81 | #define KVASER_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) | |
82 | ||
83 | /* | |
84 | * These register values are valid for revision 14 of the Xilinx logic. | |
85 | */ | |
86 | #define XILINX_VERINT 7 /* Lower nibble simulate interrupts, | |
87 | high nibble version number. */ | |
88 | ||
89 | #define XILINX_PRESUMED_VERSION 14 | |
90 | ||
91 | /* | |
92 | * Important S5920 registers | |
93 | */ | |
94 | #define S5920_INTCSR 0x38 | |
95 | #define S5920_PTCR 0x60 | |
96 | #define INTCSR_ADDON_INTENABLE_M 0x2000 | |
97 | ||
98 | ||
99 | #define KVASER_PCI_PORT_BYTES 0x20 | |
100 | ||
101 | #define PCI_CONFIG_PORT_SIZE 0x80 /* size of the config io-memory */ | |
102 | #define PCI_PORT_SIZE 0x80 /* size of a channel io-memory */ | |
103 | #define PCI_PORT_XILINX_SIZE 0x08 /* size of a xilinx io-memory */ | |
104 | ||
105 | #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */ | |
106 | #define KVASER_PCI_DEVICE_ID1 0x8406 | |
107 | ||
108 | #define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ | |
109 | #define KVASER_PCI_DEVICE_ID2 0x0008 | |
110 | ||
a3aa1884 | 111 | static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = { |
3878fb6f WG |
112 | {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, |
113 | {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, | |
114 | { 0,} | |
115 | }; | |
116 | ||
117 | MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl); | |
118 | ||
255a9154 | 119 | static u8 kvaser_pci_read_reg(const struct sja1000_priv *priv, int port) |
3878fb6f | 120 | { |
255a9154 | 121 | return ioread8(priv->reg_base + port); |
3878fb6f WG |
122 | } |
123 | ||
255a9154 WG |
124 | static void kvaser_pci_write_reg(const struct sja1000_priv *priv, |
125 | int port, u8 val) | |
3878fb6f | 126 | { |
255a9154 | 127 | iowrite8(val, priv->reg_base + port); |
3878fb6f WG |
128 | } |
129 | ||
130 | static void kvaser_pci_disable_irq(struct net_device *dev) | |
131 | { | |
132 | struct sja1000_priv *priv = netdev_priv(dev); | |
133 | struct kvaser_pci *board = priv->priv; | |
134 | u32 intcsr; | |
135 | ||
136 | /* Disable interrupts from card */ | |
137 | intcsr = ioread32(board->conf_addr + S5920_INTCSR); | |
138 | intcsr &= ~INTCSR_ADDON_INTENABLE_M; | |
139 | iowrite32(intcsr, board->conf_addr + S5920_INTCSR); | |
140 | } | |
141 | ||
142 | static void kvaser_pci_enable_irq(struct net_device *dev) | |
143 | { | |
144 | struct sja1000_priv *priv = netdev_priv(dev); | |
145 | struct kvaser_pci *board = priv->priv; | |
146 | u32 tmp_en_io; | |
147 | ||
148 | /* Enable interrupts from card */ | |
149 | tmp_en_io = ioread32(board->conf_addr + S5920_INTCSR); | |
150 | tmp_en_io |= INTCSR_ADDON_INTENABLE_M; | |
151 | iowrite32(tmp_en_io, board->conf_addr + S5920_INTCSR); | |
152 | } | |
153 | ||
154 | static int number_of_sja1000_chip(void __iomem *base_addr) | |
155 | { | |
156 | u8 status; | |
157 | int i; | |
158 | ||
159 | for (i = 0; i < MAX_NO_OF_CHANNELS; i++) { | |
160 | /* reset chip */ | |
161 | iowrite8(MOD_RM, base_addr + | |
162 | (i * KVASER_PCI_PORT_BYTES) + REG_MOD); | |
163 | status = ioread8(base_addr + | |
164 | (i * KVASER_PCI_PORT_BYTES) + REG_MOD); | |
165 | /* check reset bit */ | |
166 | if (!(status & MOD_RM)) | |
167 | break; | |
168 | } | |
169 | ||
170 | return i; | |
171 | } | |
172 | ||
173 | static void kvaser_pci_del_chan(struct net_device *dev) | |
174 | { | |
175 | struct sja1000_priv *priv; | |
176 | struct kvaser_pci *board; | |
177 | int i; | |
178 | ||
179 | if (!dev) | |
180 | return; | |
181 | priv = netdev_priv(dev); | |
182 | board = priv->priv; | |
183 | if (!board) | |
184 | return; | |
185 | ||
186 | dev_info(&board->pci_dev->dev, "Removing device %s\n", | |
187 | dev->name); | |
188 | ||
189 | /* Disable PCI interrupts */ | |
190 | kvaser_pci_disable_irq(dev); | |
191 | ||
192 | for (i = 0; i < board->no_channels - 1; i++) { | |
193 | if (board->slave_dev[i]) { | |
194 | dev_info(&board->pci_dev->dev, "Removing device %s\n", | |
195 | board->slave_dev[i]->name); | |
196 | unregister_sja1000dev(board->slave_dev[i]); | |
197 | free_sja1000dev(board->slave_dev[i]); | |
198 | } | |
199 | } | |
200 | unregister_sja1000dev(dev); | |
201 | ||
255a9154 | 202 | pci_iounmap(board->pci_dev, priv->reg_base); |
3878fb6f WG |
203 | pci_iounmap(board->pci_dev, board->conf_addr); |
204 | pci_iounmap(board->pci_dev, board->res_addr); | |
205 | ||
206 | free_sja1000dev(dev); | |
207 | } | |
208 | ||
209 | static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel, | |
210 | struct net_device **master_dev, | |
211 | void __iomem *conf_addr, | |
212 | void __iomem *res_addr, | |
255a9154 | 213 | void __iomem *base_addr) |
3878fb6f WG |
214 | { |
215 | struct net_device *dev; | |
216 | struct sja1000_priv *priv; | |
217 | struct kvaser_pci *board; | |
218 | int err, init_step; | |
219 | ||
220 | dev = alloc_sja1000dev(sizeof(struct kvaser_pci)); | |
221 | if (dev == NULL) | |
222 | return -ENOMEM; | |
223 | ||
224 | priv = netdev_priv(dev); | |
225 | board = priv->priv; | |
226 | ||
227 | board->pci_dev = pdev; | |
228 | board->channel = channel; | |
229 | ||
230 | /* S5920 */ | |
231 | board->conf_addr = conf_addr; | |
232 | ||
233 | /* XILINX board wide address */ | |
234 | board->res_addr = res_addr; | |
235 | ||
236 | if (channel == 0) { | |
237 | board->xilinx_ver = | |
238 | ioread8(board->res_addr + XILINX_VERINT) >> 4; | |
239 | init_step = 2; | |
240 | ||
241 | /* Assert PTADR# - we're in passive mode so the other bits are | |
242 | not important */ | |
243 | iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR); | |
244 | ||
245 | /* Enable interrupts from card */ | |
246 | kvaser_pci_enable_irq(dev); | |
247 | } else { | |
248 | struct sja1000_priv *master_priv = netdev_priv(*master_dev); | |
249 | struct kvaser_pci *master_board = master_priv->priv; | |
250 | master_board->slave_dev[channel - 1] = dev; | |
251 | master_board->no_channels = channel + 1; | |
252 | board->xilinx_ver = master_board->xilinx_ver; | |
253 | } | |
254 | ||
255a9154 | 255 | priv->reg_base = base_addr + channel * KVASER_PCI_PORT_BYTES; |
3878fb6f WG |
256 | |
257 | priv->read_reg = kvaser_pci_read_reg; | |
258 | priv->write_reg = kvaser_pci_write_reg; | |
259 | ||
260 | priv->can.clock.freq = KVASER_PCI_CAN_CLOCK; | |
261 | ||
262 | priv->ocr = KVASER_PCI_OCR; | |
263 | priv->cdr = KVASER_PCI_CDR; | |
264 | ||
265 | priv->irq_flags = IRQF_SHARED; | |
266 | dev->irq = pdev->irq; | |
267 | ||
268 | init_step = 4; | |
269 | ||
255a9154 WG |
270 | dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n", |
271 | priv->reg_base, board->conf_addr, dev->irq); | |
3878fb6f WG |
272 | |
273 | SET_NETDEV_DEV(dev, &pdev->dev); | |
274 | ||
275 | /* Register SJA1000 device */ | |
276 | err = register_sja1000dev(dev); | |
277 | if (err) { | |
278 | dev_err(&pdev->dev, "Registering device failed (err=%d)\n", | |
279 | err); | |
280 | goto failure; | |
281 | } | |
282 | ||
283 | if (channel == 0) | |
284 | *master_dev = dev; | |
285 | ||
286 | return 0; | |
287 | ||
288 | failure: | |
289 | kvaser_pci_del_chan(dev); | |
290 | return err; | |
291 | } | |
292 | ||
293 | static int __devinit kvaser_pci_init_one(struct pci_dev *pdev, | |
294 | const struct pci_device_id *ent) | |
295 | { | |
296 | int err; | |
297 | struct net_device *master_dev = NULL; | |
298 | struct sja1000_priv *priv; | |
299 | struct kvaser_pci *board; | |
300 | int no_channels; | |
301 | void __iomem *base_addr = NULL; | |
302 | void __iomem *conf_addr = NULL; | |
303 | void __iomem *res_addr = NULL; | |
304 | int i; | |
305 | ||
306 | dev_info(&pdev->dev, "initializing device %04x:%04x\n", | |
307 | pdev->vendor, pdev->device); | |
308 | ||
309 | err = pci_enable_device(pdev); | |
310 | if (err) | |
311 | goto failure; | |
312 | ||
313 | err = pci_request_regions(pdev, DRV_NAME); | |
314 | if (err) | |
315 | goto failure_release_pci; | |
316 | ||
317 | /* S5920 */ | |
318 | conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE); | |
319 | if (conf_addr == NULL) { | |
320 | err = -ENODEV; | |
321 | goto failure_release_regions; | |
322 | } | |
323 | ||
324 | /* XILINX board wide address */ | |
325 | res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE); | |
326 | if (res_addr == NULL) { | |
327 | err = -ENOMEM; | |
328 | goto failure_iounmap; | |
329 | } | |
330 | ||
331 | base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE); | |
332 | if (base_addr == NULL) { | |
333 | err = -ENOMEM; | |
334 | goto failure_iounmap; | |
335 | } | |
336 | ||
337 | no_channels = number_of_sja1000_chip(base_addr); | |
338 | if (no_channels == 0) { | |
339 | err = -ENOMEM; | |
340 | goto failure_iounmap; | |
341 | } | |
342 | ||
343 | for (i = 0; i < no_channels; i++) { | |
344 | err = kvaser_pci_add_chan(pdev, i, &master_dev, | |
345 | conf_addr, res_addr, | |
255a9154 | 346 | base_addr); |
3878fb6f WG |
347 | if (err) |
348 | goto failure_cleanup; | |
349 | } | |
350 | ||
351 | priv = netdev_priv(master_dev); | |
352 | board = priv->priv; | |
353 | ||
354 | dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n", | |
355 | board->xilinx_ver, board->no_channels); | |
356 | ||
357 | pci_set_drvdata(pdev, master_dev); | |
358 | return 0; | |
359 | ||
360 | failure_cleanup: | |
361 | kvaser_pci_del_chan(master_dev); | |
362 | ||
363 | failure_iounmap: | |
364 | if (conf_addr != NULL) | |
365 | pci_iounmap(pdev, conf_addr); | |
366 | if (res_addr != NULL) | |
367 | pci_iounmap(pdev, res_addr); | |
368 | if (base_addr != NULL) | |
369 | pci_iounmap(pdev, base_addr); | |
370 | ||
371 | failure_release_regions: | |
372 | pci_release_regions(pdev); | |
373 | ||
374 | failure_release_pci: | |
375 | pci_disable_device(pdev); | |
376 | ||
377 | failure: | |
378 | return err; | |
379 | ||
380 | } | |
381 | ||
382 | static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev) | |
383 | { | |
384 | struct net_device *dev = pci_get_drvdata(pdev); | |
385 | ||
386 | kvaser_pci_del_chan(dev); | |
387 | ||
388 | pci_release_regions(pdev); | |
389 | pci_disable_device(pdev); | |
390 | pci_set_drvdata(pdev, NULL); | |
391 | } | |
392 | ||
393 | static struct pci_driver kvaser_pci_driver = { | |
394 | .name = DRV_NAME, | |
395 | .id_table = kvaser_pci_tbl, | |
396 | .probe = kvaser_pci_init_one, | |
397 | .remove = __devexit_p(kvaser_pci_remove_one), | |
398 | }; | |
399 | ||
400 | static int __init kvaser_pci_init(void) | |
401 | { | |
402 | return pci_register_driver(&kvaser_pci_driver); | |
403 | } | |
404 | ||
405 | static void __exit kvaser_pci_exit(void) | |
406 | { | |
407 | pci_unregister_driver(&kvaser_pci_driver); | |
408 | } | |
409 | ||
410 | module_init(kvaser_pci_init); | |
411 | module_exit(kvaser_pci_exit); |