]>
Commit | Line | Data |
---|---|---|
03fd3cf5 KVD |
1 | /* |
2 | * Copyright (C) 2008-2010 | |
3 | * | |
4 | * - Kurt Van Dijck, EIA Electronics | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the version 2 of the GNU General Public License | |
8 | * as published by the Free Software Foundation | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
05780d98 | 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
03fd3cf5 KVD |
17 | */ |
18 | ||
19 | #include <linux/firmware.h> | |
20 | #include <linux/sched.h> | |
21 | #include <asm/div64.h> | |
b7f080cf | 22 | #include <asm/io.h> |
03fd3cf5 KVD |
23 | |
24 | #include "softing.h" | |
25 | ||
26 | /* | |
27 | * low level DPRAM command. | |
28 | * Make sure that card->dpram[DPRAM_FCT_HOST] is preset | |
29 | */ | |
30 | static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector, | |
31 | const char *msg) | |
32 | { | |
33 | int ret; | |
34 | unsigned long stamp; | |
35 | ||
36 | iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]); | |
37 | iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]); | |
38 | iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]); | |
39 | /* be sure to flush this to the card */ | |
40 | wmb(); | |
41 | stamp = jiffies + 1 * HZ; | |
42 | /* wait for card */ | |
43 | do { | |
44 | /* DPRAM_FCT_HOST is _not_ aligned */ | |
45 | ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) + | |
46 | (ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8); | |
47 | /* don't have any cached variables */ | |
48 | rmb(); | |
49 | if (ret == RES_OK) | |
50 | /* read return-value now */ | |
51 | return ioread16(&card->dpram[DPRAM_FCT_RESULT]); | |
52 | ||
53 | if ((ret != vector) || time_after(jiffies, stamp)) | |
54 | break; | |
55 | /* process context => relax */ | |
56 | usleep_range(500, 10000); | |
57 | } while (1); | |
58 | ||
59 | ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; | |
60 | dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret); | |
61 | return ret; | |
62 | } | |
63 | ||
64 | static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg) | |
65 | { | |
66 | int ret; | |
67 | ||
68 | ret = _softing_fct_cmd(card, cmd, 0, msg); | |
69 | if (ret > 0) { | |
70 | dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret); | |
71 | ret = -EIO; | |
72 | } | |
73 | return ret; | |
74 | } | |
75 | ||
76 | int softing_bootloader_command(struct softing *card, int16_t cmd, | |
77 | const char *msg) | |
78 | { | |
79 | int ret; | |
80 | unsigned long stamp; | |
81 | ||
82 | iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]); | |
83 | iowrite16(cmd, &card->dpram[DPRAM_COMMAND]); | |
84 | /* be sure to flush this to the card */ | |
85 | wmb(); | |
86 | stamp = jiffies + 3 * HZ; | |
87 | /* wait for card */ | |
88 | do { | |
89 | ret = ioread16(&card->dpram[DPRAM_RECEIPT]); | |
90 | /* don't have any cached variables */ | |
91 | rmb(); | |
92 | if (ret == RES_OK) | |
93 | return 0; | |
94 | if (time_after(jiffies, stamp)) | |
95 | break; | |
96 | /* process context => relax */ | |
97 | usleep_range(500, 10000); | |
98 | } while (!signal_pending(current)); | |
99 | ||
100 | ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; | |
101 | dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret); | |
102 | return ret; | |
103 | } | |
104 | ||
105 | static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr, | |
106 | uint16_t *plen, const uint8_t **pdat) | |
107 | { | |
108 | uint16_t checksum[2]; | |
109 | const uint8_t *mem; | |
110 | const uint8_t *end; | |
111 | ||
112 | /* | |
113 | * firmware records are a binary, unaligned stream composed of: | |
114 | * uint16_t type; | |
115 | * uint32_t addr; | |
116 | * uint16_t len; | |
117 | * uint8_t dat[len]; | |
118 | * uint16_t checksum; | |
119 | * all values in little endian. | |
120 | * We could define a struct for this, with __attribute__((packed)), | |
121 | * but would that solve the alignment in _all_ cases (cfr. the | |
122 | * struct itself may be an odd address)? | |
123 | * | |
124 | * I chose to use leXX_to_cpup() since this solves both | |
125 | * endianness & alignment. | |
126 | */ | |
127 | mem = *pmem; | |
128 | *ptype = le16_to_cpup((void *)&mem[0]); | |
129 | *paddr = le32_to_cpup((void *)&mem[2]); | |
130 | *plen = le16_to_cpup((void *)&mem[6]); | |
131 | *pdat = &mem[8]; | |
132 | /* verify checksum */ | |
133 | end = &mem[8 + *plen]; | |
134 | checksum[0] = le16_to_cpup((void *)end); | |
135 | for (checksum[1] = 0; mem < end; ++mem) | |
136 | checksum[1] += *mem; | |
137 | if (checksum[0] != checksum[1]) | |
138 | return -EINVAL; | |
139 | /* increment */ | |
140 | *pmem += 10 + *plen; | |
141 | return 0; | |
142 | } | |
143 | ||
144 | int softing_load_fw(const char *file, struct softing *card, | |
145 | __iomem uint8_t *dpram, unsigned int size, int offset) | |
146 | { | |
147 | const struct firmware *fw; | |
148 | int ret; | |
149 | const uint8_t *mem, *end, *dat; | |
150 | uint16_t type, len; | |
151 | uint32_t addr; | |
ef813c41 | 152 | uint8_t *buf = NULL, *new_buf; |
03fd3cf5 KVD |
153 | int buflen = 0; |
154 | int8_t type_end = 0; | |
155 | ||
156 | ret = request_firmware(&fw, file, &card->pdev->dev); | |
157 | if (ret < 0) | |
158 | return ret; | |
159 | dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes" | |
160 | ", offset %c0x%04x\n", | |
161 | card->pdat->name, file, (unsigned int)fw->size, | |
162 | (offset >= 0) ? '+' : '-', (unsigned int)abs(offset)); | |
163 | /* parse the firmware */ | |
164 | mem = fw->data; | |
165 | end = &mem[fw->size]; | |
166 | /* look for header record */ | |
167 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | |
168 | if (ret < 0) | |
169 | goto failed; | |
170 | if (type != 0xffff) | |
171 | goto failed; | |
172 | if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) { | |
173 | ret = -EINVAL; | |
174 | goto failed; | |
175 | } | |
176 | /* ok, we had a header */ | |
177 | while (mem < end) { | |
178 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | |
179 | if (ret < 0) | |
180 | goto failed; | |
181 | if (type == 3) { | |
182 | /* start address, not used here */ | |
183 | continue; | |
184 | } else if (type == 1) { | |
185 | /* eof */ | |
186 | type_end = 1; | |
187 | break; | |
188 | } else if (type != 0) { | |
189 | ret = -EINVAL; | |
190 | goto failed; | |
191 | } | |
192 | ||
193 | if ((addr + len + offset) > size) | |
194 | goto failed; | |
195 | memcpy_toio(&dpram[addr + offset], dat, len); | |
196 | /* be sure to flush caches from IO space */ | |
197 | mb(); | |
198 | if (len > buflen) { | |
199 | /* align buflen */ | |
200 | buflen = (len + (1024-1)) & ~(1024-1); | |
ef813c41 AK |
201 | new_buf = krealloc(buf, buflen, GFP_KERNEL); |
202 | if (!new_buf) { | |
03fd3cf5 KVD |
203 | ret = -ENOMEM; |
204 | goto failed; | |
205 | } | |
ef813c41 | 206 | buf = new_buf; |
03fd3cf5 KVD |
207 | } |
208 | /* verify record data */ | |
209 | memcpy_fromio(buf, &dpram[addr + offset], len); | |
210 | if (memcmp(buf, dat, len)) { | |
211 | /* is not ok */ | |
212 | dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); | |
213 | ret = -EIO; | |
214 | goto failed; | |
215 | } | |
216 | } | |
217 | if (!type_end) | |
218 | /* no end record seen */ | |
219 | goto failed; | |
220 | ret = 0; | |
221 | failed: | |
222 | kfree(buf); | |
223 | release_firmware(fw); | |
224 | if (ret < 0) | |
225 | dev_info(&card->pdev->dev, "firmware %s failed\n", file); | |
226 | return ret; | |
227 | } | |
228 | ||
229 | int softing_load_app_fw(const char *file, struct softing *card) | |
230 | { | |
231 | const struct firmware *fw; | |
232 | const uint8_t *mem, *end, *dat; | |
233 | int ret, j; | |
234 | uint16_t type, len; | |
235 | uint32_t addr, start_addr = 0; | |
236 | unsigned int sum, rx_sum; | |
237 | int8_t type_end = 0, type_entrypoint = 0; | |
238 | ||
239 | ret = request_firmware(&fw, file, &card->pdev->dev); | |
240 | if (ret) { | |
241 | dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n", | |
242 | file, ret); | |
243 | return ret; | |
244 | } | |
245 | dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", | |
246 | file, (unsigned long)fw->size); | |
247 | /* parse the firmware */ | |
248 | mem = fw->data; | |
249 | end = &mem[fw->size]; | |
250 | /* look for header record */ | |
251 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | |
252 | if (ret) | |
253 | goto failed; | |
254 | ret = -EINVAL; | |
255 | if (type != 0xffff) { | |
256 | dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n", | |
257 | type); | |
258 | goto failed; | |
259 | } | |
260 | if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) { | |
261 | dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n", | |
262 | len, dat); | |
263 | goto failed; | |
264 | } | |
265 | /* ok, we had a header */ | |
266 | while (mem < end) { | |
267 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | |
268 | if (ret) | |
269 | goto failed; | |
270 | ||
271 | if (type == 3) { | |
272 | /* start address */ | |
273 | start_addr = addr; | |
274 | type_entrypoint = 1; | |
275 | continue; | |
276 | } else if (type == 1) { | |
277 | /* eof */ | |
278 | type_end = 1; | |
279 | break; | |
280 | } else if (type != 0) { | |
281 | dev_alert(&card->pdev->dev, | |
282 | "unknown record type 0x%04x\n", type); | |
283 | ret = -EINVAL; | |
284 | goto failed; | |
285 | } | |
286 | ||
287 | /* regualar data */ | |
288 | for (sum = 0, j = 0; j < len; ++j) | |
289 | sum += dat[j]; | |
290 | /* work in 16bit (target) */ | |
291 | sum &= 0xffff; | |
292 | ||
293 | memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len); | |
294 | iowrite32(card->pdat->app.offs + card->pdat->app.addr, | |
295 | &card->dpram[DPRAM_COMMAND + 2]); | |
296 | iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]); | |
297 | iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]); | |
298 | iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]); | |
299 | ret = softing_bootloader_command(card, 1, "loading app."); | |
300 | if (ret < 0) | |
301 | goto failed; | |
302 | /* verify checksum */ | |
303 | rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]); | |
304 | if (rx_sum != sum) { | |
305 | dev_alert(&card->pdev->dev, "SRAM seems to be damaged" | |
306 | ", wanted 0x%04x, got 0x%04x\n", sum, rx_sum); | |
307 | ret = -EIO; | |
308 | goto failed; | |
309 | } | |
310 | } | |
311 | if (!type_end || !type_entrypoint) | |
312 | goto failed; | |
313 | /* start application in card */ | |
314 | iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]); | |
315 | iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]); | |
316 | ret = softing_bootloader_command(card, 3, "start app."); | |
317 | if (ret < 0) | |
318 | goto failed; | |
319 | ret = 0; | |
320 | failed: | |
321 | release_firmware(fw); | |
322 | if (ret < 0) | |
323 | dev_info(&card->pdev->dev, "firmware %s failed\n", file); | |
324 | return ret; | |
325 | } | |
326 | ||
327 | static int softing_reset_chip(struct softing *card) | |
328 | { | |
329 | int ret; | |
330 | ||
331 | do { | |
332 | /* reset chip */ | |
333 | iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]); | |
334 | iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]); | |
335 | iowrite8(1, &card->dpram[DPRAM_RESET]); | |
336 | iowrite8(0, &card->dpram[DPRAM_RESET+1]); | |
337 | ||
338 | ret = softing_fct_cmd(card, 0, "reset_can"); | |
339 | if (!ret) | |
340 | break; | |
341 | if (signal_pending(current)) | |
342 | /* don't wait any longer */ | |
343 | break; | |
344 | } while (1); | |
345 | card->tx.pending = 0; | |
346 | return ret; | |
347 | } | |
348 | ||
349 | int softing_chip_poweron(struct softing *card) | |
350 | { | |
351 | int ret; | |
352 | /* sync */ | |
353 | ret = _softing_fct_cmd(card, 99, 0x55, "sync-a"); | |
354 | if (ret < 0) | |
355 | goto failed; | |
356 | ||
357 | ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b"); | |
358 | if (ret < 0) | |
359 | goto failed; | |
360 | ||
361 | ret = softing_reset_chip(card); | |
362 | if (ret < 0) | |
363 | goto failed; | |
364 | /* get_serial */ | |
365 | ret = softing_fct_cmd(card, 43, "get_serial_number"); | |
366 | if (ret < 0) | |
367 | goto failed; | |
368 | card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]); | |
369 | /* get_version */ | |
370 | ret = softing_fct_cmd(card, 12, "get_version"); | |
371 | if (ret < 0) | |
372 | goto failed; | |
373 | card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]); | |
374 | card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]); | |
375 | card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]); | |
376 | card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]); | |
377 | card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]); | |
378 | return 0; | |
379 | failed: | |
380 | return ret; | |
381 | } | |
382 | ||
383 | static void softing_initialize_timestamp(struct softing *card) | |
384 | { | |
385 | uint64_t ovf; | |
386 | ||
387 | card->ts_ref = ktime_get(); | |
388 | ||
389 | /* 16MHz is the reference */ | |
390 | ovf = 0x100000000ULL * 16; | |
391 | do_div(ovf, card->pdat->freq ?: 16); | |
392 | ||
8b0e1953 | 393 | card->ts_overflow = ktime_add_us(0, ovf); |
03fd3cf5 KVD |
394 | } |
395 | ||
396 | ktime_t softing_raw2ktime(struct softing *card, u32 raw) | |
397 | { | |
398 | uint64_t rawl; | |
399 | ktime_t now, real_offset; | |
400 | ktime_t target; | |
401 | ktime_t tmp; | |
402 | ||
403 | now = ktime_get(); | |
404 | real_offset = ktime_sub(ktime_get_real(), now); | |
405 | ||
406 | /* find nsec from card */ | |
407 | rawl = raw * 16; | |
408 | do_div(rawl, card->pdat->freq ?: 16); | |
409 | target = ktime_add_us(card->ts_ref, rawl); | |
410 | /* test for overflows */ | |
411 | tmp = ktime_add(target, card->ts_overflow); | |
412 | while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) { | |
413 | card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow); | |
414 | target = tmp; | |
415 | tmp = ktime_add(target, card->ts_overflow); | |
416 | } | |
417 | return ktime_add(target, real_offset); | |
418 | } | |
419 | ||
420 | static inline int softing_error_reporting(struct net_device *netdev) | |
421 | { | |
422 | struct softing_priv *priv = netdev_priv(netdev); | |
423 | ||
424 | return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) | |
425 | ? 1 : 0; | |
426 | } | |
427 | ||
428 | int softing_startstop(struct net_device *dev, int up) | |
429 | { | |
430 | int ret; | |
431 | struct softing *card; | |
432 | struct softing_priv *priv; | |
433 | struct net_device *netdev; | |
434 | int bus_bitmask_start; | |
435 | int j, error_reporting; | |
436 | struct can_frame msg; | |
437 | const struct can_bittiming *bt; | |
438 | ||
439 | priv = netdev_priv(dev); | |
440 | card = priv->card; | |
441 | ||
442 | if (!card->fw.up) | |
443 | return -EIO; | |
444 | ||
445 | ret = mutex_lock_interruptible(&card->fw.lock); | |
446 | if (ret) | |
447 | return ret; | |
448 | ||
449 | bus_bitmask_start = 0; | |
450 | if (dev && up) | |
451 | /* prepare to start this bus as well */ | |
452 | bus_bitmask_start |= (1 << priv->index); | |
453 | /* bring netdevs down */ | |
454 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | |
455 | netdev = card->net[j]; | |
456 | if (!netdev) | |
457 | continue; | |
458 | priv = netdev_priv(netdev); | |
459 | ||
460 | if (dev != netdev) | |
461 | netif_stop_queue(netdev); | |
462 | ||
463 | if (netif_running(netdev)) { | |
464 | if (dev != netdev) | |
465 | bus_bitmask_start |= (1 << j); | |
466 | priv->tx.pending = 0; | |
467 | priv->tx.echo_put = 0; | |
468 | priv->tx.echo_get = 0; | |
469 | /* | |
470 | * this bus' may just have called open_candev() | |
471 | * which is rather stupid to call close_candev() | |
472 | * already | |
473 | * but we may come here from busoff recovery too | |
474 | * in which case the echo_skb _needs_ flushing too. | |
475 | * just be sure to call open_candev() again | |
476 | */ | |
477 | close_candev(netdev); | |
478 | } | |
479 | priv->can.state = CAN_STATE_STOPPED; | |
480 | } | |
481 | card->tx.pending = 0; | |
482 | ||
483 | softing_enable_irq(card, 0); | |
484 | ret = softing_reset_chip(card); | |
485 | if (ret) | |
486 | goto failed; | |
487 | if (!bus_bitmask_start) | |
488 | /* no busses to be brought up */ | |
489 | goto card_done; | |
490 | ||
491 | if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2) | |
492 | && (softing_error_reporting(card->net[0]) | |
493 | != softing_error_reporting(card->net[1]))) { | |
494 | dev_alert(&card->pdev->dev, | |
495 | "err_reporting flag differs for busses\n"); | |
496 | goto invalid; | |
497 | } | |
498 | error_reporting = 0; | |
499 | if (bus_bitmask_start & 1) { | |
500 | netdev = card->net[0]; | |
501 | priv = netdev_priv(netdev); | |
502 | error_reporting += softing_error_reporting(netdev); | |
503 | /* init chip 1 */ | |
504 | bt = &priv->can.bittiming; | |
505 | iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
506 | iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
507 | iowrite16(bt->phase_seg1 + bt->prop_seg, | |
508 | &card->dpram[DPRAM_FCT_PARAM + 6]); | |
509 | iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); | |
510 | iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, | |
511 | &card->dpram[DPRAM_FCT_PARAM + 10]); | |
512 | ret = softing_fct_cmd(card, 1, "initialize_chip[0]"); | |
513 | if (ret < 0) | |
514 | goto failed; | |
515 | /* set mode */ | |
516 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
517 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
518 | ret = softing_fct_cmd(card, 3, "set_mode[0]"); | |
519 | if (ret < 0) | |
520 | goto failed; | |
521 | /* set filter */ | |
522 | /* 11bit id & mask */ | |
523 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
524 | iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
525 | /* 29bit id.lo & mask.lo & id.hi & mask.hi */ | |
526 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); | |
527 | iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); | |
528 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); | |
529 | iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); | |
530 | ret = softing_fct_cmd(card, 7, "set_filter[0]"); | |
531 | if (ret < 0) | |
532 | goto failed; | |
533 | /* set output control */ | |
534 | iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
535 | ret = softing_fct_cmd(card, 5, "set_output[0]"); | |
536 | if (ret < 0) | |
537 | goto failed; | |
538 | } | |
539 | if (bus_bitmask_start & 2) { | |
540 | netdev = card->net[1]; | |
541 | priv = netdev_priv(netdev); | |
542 | error_reporting += softing_error_reporting(netdev); | |
543 | /* init chip2 */ | |
544 | bt = &priv->can.bittiming; | |
545 | iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
546 | iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
547 | iowrite16(bt->phase_seg1 + bt->prop_seg, | |
548 | &card->dpram[DPRAM_FCT_PARAM + 6]); | |
549 | iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); | |
550 | iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, | |
551 | &card->dpram[DPRAM_FCT_PARAM + 10]); | |
552 | ret = softing_fct_cmd(card, 2, "initialize_chip[1]"); | |
553 | if (ret < 0) | |
554 | goto failed; | |
555 | /* set mode2 */ | |
556 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
557 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
558 | ret = softing_fct_cmd(card, 4, "set_mode[1]"); | |
559 | if (ret < 0) | |
560 | goto failed; | |
561 | /* set filter2 */ | |
562 | /* 11bit id & mask */ | |
563 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
564 | iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
565 | /* 29bit id.lo & mask.lo & id.hi & mask.hi */ | |
566 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); | |
567 | iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); | |
568 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); | |
569 | iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); | |
570 | ret = softing_fct_cmd(card, 8, "set_filter[1]"); | |
571 | if (ret < 0) | |
572 | goto failed; | |
573 | /* set output control2 */ | |
574 | iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
575 | ret = softing_fct_cmd(card, 6, "set_output[1]"); | |
576 | if (ret < 0) | |
577 | goto failed; | |
578 | } | |
579 | /* enable_error_frame */ | |
580 | /* | |
581 | * Error reporting is switched off at the moment since | |
582 | * the receiving of them is not yet 100% verified | |
583 | * This should be enabled sooner or later | |
584 | * | |
585 | if (error_reporting) { | |
586 | ret = softing_fct_cmd(card, 51, "enable_error_frame"); | |
587 | if (ret < 0) | |
588 | goto failed; | |
589 | } | |
590 | */ | |
591 | /* initialize interface */ | |
592 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); | |
593 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); | |
594 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]); | |
595 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]); | |
596 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]); | |
597 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]); | |
598 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]); | |
599 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]); | |
600 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]); | |
601 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]); | |
602 | ret = softing_fct_cmd(card, 17, "initialize_interface"); | |
603 | if (ret < 0) | |
604 | goto failed; | |
605 | /* enable_fifo */ | |
606 | ret = softing_fct_cmd(card, 36, "enable_fifo"); | |
607 | if (ret < 0) | |
608 | goto failed; | |
609 | /* enable fifo tx ack */ | |
610 | ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]"); | |
611 | if (ret < 0) | |
612 | goto failed; | |
613 | /* enable fifo tx ack2 */ | |
614 | ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]"); | |
615 | if (ret < 0) | |
616 | goto failed; | |
617 | /* start_chip */ | |
618 | ret = softing_fct_cmd(card, 11, "start_chip"); | |
619 | if (ret < 0) | |
620 | goto failed; | |
621 | iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]); | |
622 | iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]); | |
623 | if (card->pdat->generation < 2) { | |
624 | iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); | |
625 | /* flush the DPRAM caches */ | |
626 | wmb(); | |
627 | } | |
628 | ||
629 | softing_initialize_timestamp(card); | |
630 | ||
631 | /* | |
632 | * do socketcan notifications/status changes | |
633 | * from here, no errors should occur, or the failed: part | |
634 | * must be reviewed | |
635 | */ | |
636 | memset(&msg, 0, sizeof(msg)); | |
637 | msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; | |
638 | msg.can_dlc = CAN_ERR_DLC; | |
639 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | |
640 | if (!(bus_bitmask_start & (1 << j))) | |
641 | continue; | |
642 | netdev = card->net[j]; | |
643 | if (!netdev) | |
644 | continue; | |
645 | priv = netdev_priv(netdev); | |
646 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
647 | open_candev(netdev); | |
648 | if (dev != netdev) { | |
649 | /* notify other busses on the restart */ | |
8b0e1953 | 650 | softing_netdev_rx(netdev, &msg, 0); |
03fd3cf5 KVD |
651 | ++priv->can.can_stats.restarts; |
652 | } | |
653 | netif_wake_queue(netdev); | |
654 | } | |
655 | ||
656 | /* enable interrupts */ | |
657 | ret = softing_enable_irq(card, 1); | |
658 | if (ret) | |
659 | goto failed; | |
660 | card_done: | |
661 | mutex_unlock(&card->fw.lock); | |
662 | return 0; | |
663 | invalid: | |
664 | ret = -EINVAL; | |
665 | failed: | |
666 | softing_enable_irq(card, 0); | |
667 | softing_reset_chip(card); | |
668 | mutex_unlock(&card->fw.lock); | |
669 | /* bring all other interfaces down */ | |
670 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | |
671 | netdev = card->net[j]; | |
672 | if (!netdev) | |
673 | continue; | |
674 | dev_close(netdev); | |
675 | } | |
676 | return ret; | |
677 | } | |
678 | ||
679 | int softing_default_output(struct net_device *netdev) | |
680 | { | |
681 | struct softing_priv *priv = netdev_priv(netdev); | |
682 | struct softing *card = priv->card; | |
683 | ||
684 | switch (priv->chip) { | |
685 | case 1000: | |
686 | return (card->pdat->generation < 2) ? 0xfb : 0xfa; | |
687 | case 5: | |
688 | return 0x60; | |
689 | default: | |
690 | return 0x40; | |
691 | } | |
692 | } |