aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnant Gole <anantgole@ti.com>2009-10-06 22:59:47 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-08 01:02:53 -0400
commit3758bf25db8caeec667e4e56e030da0ec3060529 (patch)
tree5eacde81468c8e201086083a19456ba28e67e3e0
parent0cdc03698f2586923ad3b9fca06643ff5675f221 (diff)
can: add TI CAN (HECC) driver
TI HECC (High End CAN Controller) module is found on many TI devices. It has 32 hardware mailboxes with full implementation of CAN protocol 2.0B with bus speeds up to 1Mbps. Specifications of the module are available on TI web <http://www.ti.com> Signed-off-by: Anant Gole <anantgole@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/can/Kconfig7
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/ti_hecc.c1006
-rw-r--r--include/linux/can/platform/ti_hecc.h40
4 files changed, 1054 insertions, 0 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index df32c109b7ac..26d77cc0ded7 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -95,6 +95,13 @@ config CAN_AT91
95 ---help--- 95 ---help---
96 This is a driver for the SoC CAN controller in Atmel's AT91SAM9263. 96 This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
97 97
98config CAN_TI_HECC
99 depends on CAN_DEV && ARCH_OMAP3
100 tristate "TI High End CAN Controller"
101 ---help---
102 Driver for TI HECC (High End CAN Controller) module found on many
103 TI devices. The device specifications are available from www.ti.com
104
98config CAN_DEBUG_DEVICES 105config CAN_DEBUG_DEVICES
99 bool "CAN devices debugging messages" 106 bool "CAN devices debugging messages"
100 depends on CAN 107 depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 0dea62721f2f..31f4ab5df28b 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -11,5 +11,6 @@ obj-y += usb/
11 11
12obj-$(CONFIG_CAN_SJA1000) += sja1000/ 12obj-$(CONFIG_CAN_SJA1000) += sja1000/
13obj-$(CONFIG_CAN_AT91) += at91_can.o 13obj-$(CONFIG_CAN_AT91) += at91_can.o
14obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
14 15
15ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG 16ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
new file mode 100644
index 000000000000..814e6c5c6386
--- /dev/null
+++ b/drivers/net/can/ti_hecc.c
@@ -0,0 +1,1006 @@
1/*
2 * TI HECC (CAN) device driver
3 *
4 * This driver supports TI's HECC (High End CAN Controller module) and the
5 * specs for the same is available at <http://www.ti.com>
6 *
7 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation version 2.
12 *
13 * This program is distributed as is WITHOUT ANY WARRANTY of any
14 * kind, whether express or implied; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20/*
21 * Your platform definitions should specify module ram offsets and interrupt
22 * number to use as follows:
23 *
24 * static struct ti_hecc_platform_data am3517_evm_hecc_pdata = {
25 * .scc_hecc_offset = 0,
26 * .scc_ram_offset = 0x3000,
27 * .hecc_ram_offset = 0x3000,
28 * .mbx_offset = 0x2000,
29 * .int_line = 0,
30 * .revision = 1,
31 * };
32 *
33 * Please see include/can/platform/ti_hecc.h for description of above fields
34 *
35 */
36
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/kernel.h>
40#include <linux/types.h>
41#include <linux/interrupt.h>
42#include <linux/errno.h>
43#include <linux/netdevice.h>
44#include <linux/skbuff.h>
45#include <linux/platform_device.h>
46#include <linux/clk.h>
47
48#include <linux/can.h>
49#include <linux/can/dev.h>
50#include <linux/can/error.h>
51#include <linux/can/platform/ti_hecc.h>
52
53#define DRV_NAME "ti_hecc"
54#define HECC_MODULE_VERSION "0.7"
55MODULE_VERSION(HECC_MODULE_VERSION);
56#define DRV_DESC "TI High End CAN Controller Driver " HECC_MODULE_VERSION
57
58/* TX / RX Mailbox Configuration */
59#define HECC_MAX_MAILBOXES 32 /* hardware mailboxes - do not change */
60#define MAX_TX_PRIO 0x3F /* hardware value - do not change */
61
62/*
63 * Important Note: TX mailbox configuration
64 * TX mailboxes should be restricted to the number of SKB buffers to avoid
65 * maintaining SKB buffers separately. TX mailboxes should be a power of 2
66 * for the mailbox logic to work. Top mailbox numbers are reserved for RX
67 * and lower mailboxes for TX.
68 *
69 * HECC_MAX_TX_MBOX HECC_MB_TX_SHIFT
70 * 4 (default) 2
71 * 8 3
72 * 16 4
73 */
74#define HECC_MB_TX_SHIFT 2 /* as per table above */
75#define HECC_MAX_TX_MBOX BIT(HECC_MB_TX_SHIFT)
76
77#if (HECC_MAX_TX_MBOX > CAN_ECHO_SKB_MAX)
78#error "HECC: MAX TX mailboxes should be equal or less than CAN_ECHO_SKB_MAX"
79#endif
80
81#define HECC_TX_PRIO_SHIFT (HECC_MB_TX_SHIFT)
82#define HECC_TX_PRIO_MASK (MAX_TX_PRIO << HECC_MB_TX_SHIFT)
83#define HECC_TX_MB_MASK (HECC_MAX_TX_MBOX - 1)
84#define HECC_TX_MASK ((HECC_MAX_TX_MBOX - 1) | HECC_TX_PRIO_MASK)
85#define HECC_TX_MBOX_MASK (~(BIT(HECC_MAX_TX_MBOX) - 1))
86#define HECC_DEF_NAPI_WEIGHT HECC_MAX_RX_MBOX
87
88/*
89 * Important Note: RX mailbox configuration
90 * RX mailboxes are further logically split into two - main and buffer
91 * mailboxes. The goal is to get all packets into main mailboxes as
92 * driven by mailbox number and receive priority (higher to lower) and
93 * buffer mailboxes are used to receive pkts while main mailboxes are being
94 * processed. This ensures in-order packet reception.
95 *
96 * Here are the recommended values for buffer mailbox. Note that RX mailboxes
97 * start after TX mailboxes:
98 *
99 * HECC_MAX_RX_MBOX HECC_RX_BUFFER_MBOX No of buffer mailboxes
100 * 28 12 8
101 * 16 20 4
102 */
103
104#define HECC_MAX_RX_MBOX (HECC_MAX_MAILBOXES - HECC_MAX_TX_MBOX)
105#define HECC_RX_BUFFER_MBOX 12 /* as per table above */
106#define HECC_RX_FIRST_MBOX (HECC_MAX_MAILBOXES - 1)
107#define HECC_RX_HIGH_MBOX_MASK (~(BIT(HECC_RX_BUFFER_MBOX) - 1))
108
109/* TI HECC module registers */
110#define HECC_CANME 0x0 /* Mailbox enable */
111#define HECC_CANMD 0x4 /* Mailbox direction */
112#define HECC_CANTRS 0x8 /* Transmit request set */
113#define HECC_CANTRR 0xC /* Transmit request */
114#define HECC_CANTA 0x10 /* Transmission acknowledge */
115#define HECC_CANAA 0x14 /* Abort acknowledge */
116#define HECC_CANRMP 0x18 /* Receive message pending */
117#define HECC_CANRML 0x1C /* Remote message lost */
118#define HECC_CANRFP 0x20 /* Remote frame pending */
119#define HECC_CANGAM 0x24 /* SECC only:Global acceptance mask */
120#define HECC_CANMC 0x28 /* Master control */
121#define HECC_CANBTC 0x2C /* Bit timing configuration */
122#define HECC_CANES 0x30 /* Error and status */
123#define HECC_CANTEC 0x34 /* Transmit error counter */
124#define HECC_CANREC 0x38 /* Receive error counter */
125#define HECC_CANGIF0 0x3C /* Global interrupt flag 0 */
126#define HECC_CANGIM 0x40 /* Global interrupt mask */
127#define HECC_CANGIF1 0x44 /* Global interrupt flag 1 */
128#define HECC_CANMIM 0x48 /* Mailbox interrupt mask */
129#define HECC_CANMIL 0x4C /* Mailbox interrupt level */
130#define HECC_CANOPC 0x50 /* Overwrite protection control */
131#define HECC_CANTIOC 0x54 /* Transmit I/O control */
132#define HECC_CANRIOC 0x58 /* Receive I/O control */
133#define HECC_CANLNT 0x5C /* HECC only: Local network time */
134#define HECC_CANTOC 0x60 /* HECC only: Time-out control */
135#define HECC_CANTOS 0x64 /* HECC only: Time-out status */
136#define HECC_CANTIOCE 0x68 /* SCC only:Enhanced TX I/O control */
137#define HECC_CANRIOCE 0x6C /* SCC only:Enhanced RX I/O control */
138
139/* Mailbox registers */
140#define HECC_CANMID 0x0
141#define HECC_CANMCF 0x4
142#define HECC_CANMDL 0x8
143#define HECC_CANMDH 0xC
144
145#define HECC_SET_REG 0xFFFFFFFF
146#define HECC_CANID_MASK 0x3FF /* 18 bits mask for extended id's */
147#define HECC_CCE_WAIT_COUNT 100 /* Wait for ~1 sec for CCE bit */
148
149#define HECC_CANMC_SCM BIT(13) /* SCC compat mode */
150#define HECC_CANMC_CCR BIT(12) /* Change config request */
151#define HECC_CANMC_PDR BIT(11) /* Local Power down - for sleep mode */
152#define HECC_CANMC_ABO BIT(7) /* Auto Bus On */
153#define HECC_CANMC_STM BIT(6) /* Self test mode - loopback */
154#define HECC_CANMC_SRES BIT(5) /* Software reset */
155
156#define HECC_CANTIOC_EN BIT(3) /* Enable CAN TX I/O pin */
157#define HECC_CANRIOC_EN BIT(3) /* Enable CAN RX I/O pin */
158
159#define HECC_CANMID_IDE BIT(31) /* Extended frame format */
160#define HECC_CANMID_AME BIT(30) /* Acceptance mask enable */
161#define HECC_CANMID_AAM BIT(29) /* Auto answer mode */
162
163#define HECC_CANES_FE BIT(24) /* form error */
164#define HECC_CANES_BE BIT(23) /* bit error */
165#define HECC_CANES_SA1 BIT(22) /* stuck at dominant error */
166#define HECC_CANES_CRCE BIT(21) /* CRC error */
167#define HECC_CANES_SE BIT(20) /* stuff bit error */
168#define HECC_CANES_ACKE BIT(19) /* ack error */
169#define HECC_CANES_BO BIT(18) /* Bus off status */
170#define HECC_CANES_EP BIT(17) /* Error passive status */
171#define HECC_CANES_EW BIT(16) /* Error warning status */
172#define HECC_CANES_SMA BIT(5) /* suspend mode ack */
173#define HECC_CANES_CCE BIT(4) /* Change config enabled */
174#define HECC_CANES_PDA BIT(3) /* Power down mode ack */
175
176#define HECC_CANBTC_SAM BIT(7) /* sample points */
177
178#define HECC_BUS_ERROR (HECC_CANES_FE | HECC_CANES_BE |\
179 HECC_CANES_CRCE | HECC_CANES_SE |\
180 HECC_CANES_ACKE)
181
182#define HECC_CANMCF_RTR BIT(4) /* Remote transmit request */
183
184#define HECC_CANGIF_MAIF BIT(17) /* Message alarm interrupt */
185#define HECC_CANGIF_TCOIF BIT(16) /* Timer counter overflow int */
186#define HECC_CANGIF_GMIF BIT(15) /* Global mailbox interrupt */
187#define HECC_CANGIF_AAIF BIT(14) /* Abort ack interrupt */
188#define HECC_CANGIF_WDIF BIT(13) /* Write denied interrupt */
189#define HECC_CANGIF_WUIF BIT(12) /* Wake up interrupt */
190#define HECC_CANGIF_RMLIF BIT(11) /* Receive message lost interrupt */
191#define HECC_CANGIF_BOIF BIT(10) /* Bus off interrupt */
192#define HECC_CANGIF_EPIF BIT(9) /* Error passive interrupt */
193#define HECC_CANGIF_WLIF BIT(8) /* Warning level interrupt */
194#define HECC_CANGIF_MBOX_MASK 0x1F /* Mailbox number mask */
195#define HECC_CANGIM_I1EN BIT(1) /* Int line 1 enable */
196#define HECC_CANGIM_I0EN BIT(0) /* Int line 0 enable */
197#define HECC_CANGIM_DEF_MASK 0x700 /* only busoff/warning/passive */
198#define HECC_CANGIM_SIL BIT(2) /* system interrupts to int line 1 */
199
200/* CAN Bittiming constants as per HECC specs */
201static struct can_bittiming_const ti_hecc_bittiming_const = {
202 .name = DRV_NAME,
203 .tseg1_min = 1,
204 .tseg1_max = 16,
205 .tseg2_min = 1,
206 .tseg2_max = 8,
207 .sjw_max = 4,
208 .brp_min = 1,
209 .brp_max = 256,
210 .brp_inc = 1,
211};
212
213struct ti_hecc_priv {
214 struct can_priv can; /* MUST be first member/field */
215 struct napi_struct napi;
216 struct net_device *ndev;
217 struct clk *clk;
218 void __iomem *base;
219 u32 scc_ram_offset;
220 u32 hecc_ram_offset;
221 u32 mbx_offset;
222 u32 int_line;
223 spinlock_t mbx_lock; /* CANME register needs protection */
224 u32 tx_head;
225 u32 tx_tail;
226 u32 rx_next;
227};
228
229static inline int get_tx_head_mb(struct ti_hecc_priv *priv)
230{
231 return priv->tx_head & HECC_TX_MB_MASK;
232}
233
234static inline int get_tx_tail_mb(struct ti_hecc_priv *priv)
235{
236 return priv->tx_tail & HECC_TX_MB_MASK;
237}
238
239static inline int get_tx_head_prio(struct ti_hecc_priv *priv)
240{
241 return (priv->tx_head >> HECC_TX_PRIO_SHIFT) & MAX_TX_PRIO;
242}
243
244static inline void hecc_write_lam(struct ti_hecc_priv *priv, u32 mbxno, u32 val)
245{
246 __raw_writel(val, priv->base + priv->hecc_ram_offset + mbxno * 4);
247}
248
249static inline void hecc_write_mbx(struct ti_hecc_priv *priv, u32 mbxno,
250 u32 reg, u32 val)
251{
252 __raw_writel(val, priv->base + priv->mbx_offset + mbxno * 0x10 +
253 reg);
254}
255
256static inline u32 hecc_read_mbx(struct ti_hecc_priv *priv, u32 mbxno, u32 reg)
257{
258 return __raw_readl(priv->base + priv->mbx_offset + mbxno * 0x10 +
259 reg);
260}
261
262static inline void hecc_write(struct ti_hecc_priv *priv, u32 reg, u32 val)
263{
264 __raw_writel(val, priv->base + reg);
265}
266
267static inline u32 hecc_read(struct ti_hecc_priv *priv, int reg)
268{
269 return __raw_readl(priv->base + reg);
270}
271
272static inline void hecc_set_bit(struct ti_hecc_priv *priv, int reg,
273 u32 bit_mask)
274{
275 hecc_write(priv, reg, hecc_read(priv, reg) | bit_mask);
276}
277
278static inline void hecc_clear_bit(struct ti_hecc_priv *priv, int reg,
279 u32 bit_mask)
280{
281 hecc_write(priv, reg, hecc_read(priv, reg) & ~bit_mask);
282}
283
284static inline u32 hecc_get_bit(struct ti_hecc_priv *priv, int reg, u32 bit_mask)
285{
286 return (hecc_read(priv, reg) & bit_mask) ? 1 : 0;
287}
288
289static int ti_hecc_get_state(const struct net_device *ndev,
290 enum can_state *state)
291{
292 struct ti_hecc_priv *priv = netdev_priv(ndev);
293
294 *state = priv->can.state;
295 return 0;
296}
297
298static int ti_hecc_set_btc(struct ti_hecc_priv *priv)
299{
300 struct can_bittiming *bit_timing = &priv->can.bittiming;
301 u32 can_btc;
302
303 can_btc = (bit_timing->phase_seg2 - 1) & 0x7;
304 can_btc |= ((bit_timing->phase_seg1 + bit_timing->prop_seg - 1)
305 & 0xF) << 3;
306 if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) {
307 if (bit_timing->brp > 4)
308 can_btc |= HECC_CANBTC_SAM;
309 else
310 dev_warn(priv->ndev->dev.parent, "WARN: Triple" \
311 "sampling not set due to h/w limitations");
312 }
313 can_btc |= ((bit_timing->sjw - 1) & 0x3) << 8;
314 can_btc |= ((bit_timing->brp - 1) & 0xFF) << 16;
315
316 /* ERM being set to 0 by default meaning resync at falling edge */
317
318 hecc_write(priv, HECC_CANBTC, can_btc);
319 dev_info(priv->ndev->dev.parent, "setting CANBTC=%#x\n", can_btc);
320
321 return 0;
322}
323
324static void ti_hecc_reset(struct net_device *ndev)
325{
326 u32 cnt;
327 struct ti_hecc_priv *priv = netdev_priv(ndev);
328
329 dev_dbg(ndev->dev.parent, "resetting hecc ...\n");
330 hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SRES);
331
332 /* Set change control request and wait till enabled */
333 hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
334
335 /*
336 * INFO: It has been observed that at times CCE bit may not be
337 * set and hw seems to be ok even if this bit is not set so
338 * timing out with a timing of 1ms to respect the specs
339 */
340 cnt = HECC_CCE_WAIT_COUNT;
341 while (!hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && cnt != 0) {
342 --cnt;
343 udelay(10);
344 }
345
346 /*
347 * Note: On HECC, BTC can be programmed only in initialization mode, so
348 * it is expected that the can bittiming parameters are set via ip
349 * utility before the device is opened
350 */
351 ti_hecc_set_btc(priv);
352
353 /* Clear CCR (and CANMC register) and wait for CCE = 0 enable */
354 hecc_write(priv, HECC_CANMC, 0);
355
356 /*
357 * INFO: CAN net stack handles bus off and hence disabling auto-bus-on
358 * hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_ABO);
359 */
360
361 /*
362 * INFO: It has been observed that at times CCE bit may not be
363 * set and hw seems to be ok even if this bit is not set so
364 */
365 cnt = HECC_CCE_WAIT_COUNT;
366 while (hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && cnt != 0) {
367 --cnt;
368 udelay(10);
369 }
370
371 /* Enable TX and RX I/O Control pins */
372 hecc_write(priv, HECC_CANTIOC, HECC_CANTIOC_EN);
373 hecc_write(priv, HECC_CANRIOC, HECC_CANRIOC_EN);
374
375 /* Clear registers for clean operation */
376 hecc_write(priv, HECC_CANTA, HECC_SET_REG);
377 hecc_write(priv, HECC_CANRMP, HECC_SET_REG);
378 hecc_write(priv, HECC_CANGIF0, HECC_SET_REG);
379 hecc_write(priv, HECC_CANGIF1, HECC_SET_REG);
380 hecc_write(priv, HECC_CANME, 0);
381 hecc_write(priv, HECC_CANMD, 0);
382
383 /* SCC compat mode NOT supported (and not needed too) */
384 hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SCM);
385}
386
387static void ti_hecc_start(struct net_device *ndev)
388{
389 struct ti_hecc_priv *priv = netdev_priv(ndev);
390 u32 cnt, mbxno, mbx_mask;
391
392 /* put HECC in initialization mode and set btc */
393 ti_hecc_reset(ndev);
394
395 priv->tx_head = priv->tx_tail = HECC_TX_MASK;
396 priv->rx_next = HECC_RX_FIRST_MBOX;
397
398 /* Enable local and global acceptance mask registers */
399 hecc_write(priv, HECC_CANGAM, HECC_SET_REG);
400
401 /* Prepare configured mailboxes to receive messages */
402 for (cnt = 0; cnt < HECC_MAX_RX_MBOX; cnt++) {
403 mbxno = HECC_MAX_MAILBOXES - 1 - cnt;
404 mbx_mask = BIT(mbxno);
405 hecc_clear_bit(priv, HECC_CANME, mbx_mask);
406 hecc_write_mbx(priv, mbxno, HECC_CANMID, HECC_CANMID_AME);
407 hecc_write_lam(priv, mbxno, HECC_SET_REG);
408 hecc_set_bit(priv, HECC_CANMD, mbx_mask);
409 hecc_set_bit(priv, HECC_CANME, mbx_mask);
410 hecc_set_bit(priv, HECC_CANMIM, mbx_mask);
411 }
412
413 /* Prevent message over-write & Enable interrupts */
414 hecc_write(priv, HECC_CANOPC, HECC_SET_REG);
415 if (priv->int_line) {
416 hecc_write(priv, HECC_CANMIL, HECC_SET_REG);
417 hecc_write(priv, HECC_CANGIM, HECC_CANGIM_DEF_MASK |
418 HECC_CANGIM_I1EN | HECC_CANGIM_SIL);
419 } else {
420 hecc_write(priv, HECC_CANMIL, 0);
421 hecc_write(priv, HECC_CANGIM,
422 HECC_CANGIM_DEF_MASK | HECC_CANGIM_I0EN);
423 }
424 priv->can.state = CAN_STATE_ERROR_ACTIVE;
425}
426
427static void ti_hecc_stop(struct net_device *ndev)
428{
429 struct ti_hecc_priv *priv = netdev_priv(ndev);
430
431 /* Disable interrupts and disable mailboxes */
432 hecc_write(priv, HECC_CANGIM, 0);
433 hecc_write(priv, HECC_CANMIM, 0);
434 hecc_write(priv, HECC_CANME, 0);
435 priv->can.state = CAN_STATE_STOPPED;
436}
437
438static int ti_hecc_do_set_mode(struct net_device *ndev, enum can_mode mode)
439{
440 int ret = 0;
441
442 switch (mode) {
443 case CAN_MODE_START:
444 ti_hecc_start(ndev);
445 netif_wake_queue(ndev);
446 break;
447 default:
448 ret = -EOPNOTSUPP;
449 break;
450 }
451
452 return ret;
453}
454
455/*
456 * ti_hecc_xmit: HECC Transmit
457 *
458 * The transmit mailboxes start from 0 to HECC_MAX_TX_MBOX. In HECC the
459 * priority of the mailbox for tranmission is dependent upon priority setting
460 * field in mailbox registers. The mailbox with highest value in priority field
461 * is transmitted first. Only when two mailboxes have the same value in
462 * priority field the highest numbered mailbox is transmitted first.
463 *
464 * To utilize the HECC priority feature as described above we start with the
465 * highest numbered mailbox with highest priority level and move on to the next
466 * mailbox with the same priority level and so on. Once we loop through all the
467 * transmit mailboxes we choose the next priority level (lower) and so on
468 * until we reach the lowest priority level on the lowest numbered mailbox
469 * when we stop transmission until all mailboxes are transmitted and then
470 * restart at highest numbered mailbox with highest priority.
471 *
472 * Two counters (head and tail) are used to track the next mailbox to transmit
473 * and to track the echo buffer for already transmitted mailbox. The queue
474 * is stopped when all the mailboxes are busy or when there is a priority
475 * value roll-over happens.
476 */
477static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
478{
479 struct ti_hecc_priv *priv = netdev_priv(ndev);
480 struct can_frame *cf = (struct can_frame *)skb->data;
481 u32 mbxno, mbx_mask, data;
482 unsigned long flags;
483
484 mbxno = get_tx_head_mb(priv);
485 mbx_mask = BIT(mbxno);
486 spin_lock_irqsave(&priv->mbx_lock, flags);
487 if (unlikely(hecc_read(priv, HECC_CANME) & mbx_mask)) {
488 spin_unlock_irqrestore(&priv->mbx_lock, flags);
489 netif_stop_queue(ndev);
490 dev_err(priv->ndev->dev.parent,
491 "BUG: TX mbx not ready tx_head=%08X, tx_tail=%08X\n",
492 priv->tx_head, priv->tx_tail);
493 return NETDEV_TX_BUSY;
494 }
495 spin_unlock_irqrestore(&priv->mbx_lock, flags);
496
497 /* Prepare mailbox for transmission */
498 data = min_t(u8, cf->can_dlc, 8);
499 if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
500 data |= HECC_CANMCF_RTR;
501 data |= get_tx_head_prio(priv) << 8;
502 hecc_write_mbx(priv, mbxno, HECC_CANMCF, data);
503
504 if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
505 data = (cf->can_id & CAN_EFF_MASK) | HECC_CANMID_IDE;
506 else /* Standard frame format */
507 data = (cf->can_id & CAN_SFF_MASK) << 18;
508 hecc_write_mbx(priv, mbxno, HECC_CANMID, data);
509 hecc_write_mbx(priv, mbxno, HECC_CANMDL,
510 be32_to_cpu(*(u32 *)(cf->data)));
511 if (cf->can_dlc > 4)
512 hecc_write_mbx(priv, mbxno, HECC_CANMDH,
513 be32_to_cpu(*(u32 *)(cf->data + 4)));
514 else
515 *(u32 *)(cf->data + 4) = 0;
516 can_put_echo_skb(skb, ndev, mbxno);
517
518 spin_lock_irqsave(&priv->mbx_lock, flags);
519 --priv->tx_head;
520 if ((hecc_read(priv, HECC_CANME) & BIT(get_tx_head_mb(priv))) ||
521 (priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK) {
522 netif_stop_queue(ndev);
523 }
524 hecc_set_bit(priv, HECC_CANME, mbx_mask);
525 spin_unlock_irqrestore(&priv->mbx_lock, flags);
526
527 hecc_clear_bit(priv, HECC_CANMD, mbx_mask);
528 hecc_set_bit(priv, HECC_CANMIM, mbx_mask);
529 hecc_write(priv, HECC_CANTRS, mbx_mask);
530
531 return NETDEV_TX_OK;
532}
533
534static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
535{
536 struct net_device_stats *stats = &priv->ndev->stats;
537 struct can_frame *cf;
538 struct sk_buff *skb;
539 u32 data, mbx_mask;
540 unsigned long flags;
541
542 skb = netdev_alloc_skb(priv->ndev, sizeof(struct can_frame));
543 if (!skb) {
544 if (printk_ratelimit())
545 dev_err(priv->ndev->dev.parent,
546 "ti_hecc_rx_pkt: netdev_alloc_skb() failed\n");
547 return -ENOMEM;
548 }
549 skb->protocol = __constant_htons(ETH_P_CAN);
550 skb->ip_summed = CHECKSUM_UNNECESSARY;
551
552 mbx_mask = BIT(mbxno);
553 cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
554 data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
555 if (data & HECC_CANMID_IDE)
556 cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
557 else
558 cf->can_id = (data >> 18) & CAN_SFF_MASK;
559 data = hecc_read_mbx(priv, mbxno, HECC_CANMCF);
560 if (data & HECC_CANMCF_RTR)
561 cf->can_id |= CAN_RTR_FLAG;
562 cf->can_dlc = data & 0xF;
563 data = hecc_read_mbx(priv, mbxno, HECC_CANMDL);
564 *(u32 *)(cf->data) = cpu_to_be32(data);
565 if (cf->can_dlc > 4) {
566 data = hecc_read_mbx(priv, mbxno, HECC_CANMDH);
567 *(u32 *)(cf->data + 4) = cpu_to_be32(data);
568 } else {
569 *(u32 *)(cf->data + 4) = 0;
570 }
571 spin_lock_irqsave(&priv->mbx_lock, flags);
572 hecc_clear_bit(priv, HECC_CANME, mbx_mask);
573 hecc_write(priv, HECC_CANRMP, mbx_mask);
574 /* enable mailbox only if it is part of rx buffer mailboxes */
575 if (priv->rx_next < HECC_RX_BUFFER_MBOX)
576 hecc_set_bit(priv, HECC_CANME, mbx_mask);
577 spin_unlock_irqrestore(&priv->mbx_lock, flags);
578
579 stats->rx_bytes += cf->can_dlc;
580 netif_receive_skb(skb);
581 stats->rx_packets++;
582
583 return 0;
584}
585
586/*
587 * ti_hecc_rx_poll - HECC receive pkts
588 *
589 * The receive mailboxes start from highest numbered mailbox till last xmit
590 * mailbox. On CAN frame reception the hardware places the data into highest
591 * numbered mailbox that matches the CAN ID filter. Since all receive mailboxes
592 * have same filtering (ALL CAN frames) packets will arrive in the highest
593 * available RX mailbox and we need to ensure in-order packet reception.
594 *
595 * To ensure the packets are received in the right order we logically divide
596 * the RX mailboxes into main and buffer mailboxes. Packets are received as per
597 * mailbox priotity (higher to lower) in the main bank and once it is full we
598 * disable further reception into main mailboxes. While the main mailboxes are
599 * processed in NAPI, further packets are received in buffer mailboxes.
600 *
601 * We maintain a RX next mailbox counter to process packets and once all main
602 * mailboxe packets are passed to the upper stack we enable all of them but
603 * continue to process packets received in buffer mailboxes. With each packet
604 * received from buffer mailbox we enable it immediately so as to handle the
605 * overflow from higher mailboxes.
606 */
607static int ti_hecc_rx_poll(struct napi_struct *napi, int quota)
608{
609 struct net_device *ndev = napi->dev;
610 struct ti_hecc_priv *priv = netdev_priv(ndev);
611 u32 num_pkts = 0;
612 u32 mbx_mask;
613 unsigned long pending_pkts, flags;
614
615 if (!netif_running(ndev))
616 return 0;
617
618 while ((pending_pkts = hecc_read(priv, HECC_CANRMP)) &&
619 num_pkts < quota) {
620 mbx_mask = BIT(priv->rx_next); /* next rx mailbox to process */
621 if (mbx_mask & pending_pkts) {
622 if (ti_hecc_rx_pkt(priv, priv->rx_next) < 0)
623 return num_pkts;
624 ++num_pkts;
625 } else if (priv->rx_next > HECC_RX_BUFFER_MBOX) {
626 break; /* pkt not received yet */
627 }
628 --priv->rx_next;
629 if (priv->rx_next == HECC_RX_BUFFER_MBOX) {
630 /* enable high bank mailboxes */
631 spin_lock_irqsave(&priv->mbx_lock, flags);
632 mbx_mask = hecc_read(priv, HECC_CANME);
633 mbx_mask |= HECC_RX_HIGH_MBOX_MASK;
634 hecc_write(priv, HECC_CANME, mbx_mask);
635 spin_unlock_irqrestore(&priv->mbx_lock, flags);
636 } else if (priv->rx_next == HECC_MAX_TX_MBOX - 1) {
637 priv->rx_next = HECC_RX_FIRST_MBOX;
638 break;
639 }
640 }
641
642 /* Enable packet interrupt if all pkts are handled */
643 if (hecc_read(priv, HECC_CANRMP) == 0) {
644 napi_complete(napi);
645 /* Re-enable RX mailbox interrupts */
646 mbx_mask = hecc_read(priv, HECC_CANMIM);
647 mbx_mask |= HECC_TX_MBOX_MASK;
648 hecc_write(priv, HECC_CANMIM, mbx_mask);
649 }
650
651 return num_pkts;
652}
653
654static int ti_hecc_error(struct net_device *ndev, int int_status,
655 int err_status)
656{
657 struct ti_hecc_priv *priv = netdev_priv(ndev);
658 struct net_device_stats *stats = &ndev->stats;
659 struct can_frame *cf;
660 struct sk_buff *skb;
661
662 /* propogate the error condition to the can stack */
663 skb = netdev_alloc_skb(ndev, sizeof(struct can_frame));
664 if (!skb) {
665 if (printk_ratelimit())
666 dev_err(priv->ndev->dev.parent,
667 "ti_hecc_error: netdev_alloc_skb() failed\n");
668 return -ENOMEM;
669 }
670 skb->protocol = __constant_htons(ETH_P_CAN);
671 skb->ip_summed = CHECKSUM_UNNECESSARY;
672 cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
673 memset(cf, 0, sizeof(struct can_frame));
674 cf->can_id = CAN_ERR_FLAG;
675 cf->can_dlc = CAN_ERR_DLC;
676
677 if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
678 if ((int_status & HECC_CANGIF_BOIF) == 0) {
679 priv->can.state = CAN_STATE_ERROR_WARNING;
680 ++priv->can.can_stats.error_warning;
681 cf->can_id |= CAN_ERR_CRTL;
682 if (hecc_read(priv, HECC_CANTEC) > 96)
683 cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
684 if (hecc_read(priv, HECC_CANREC) > 96)
685 cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
686 }
687 hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
688 dev_dbg(priv->ndev->dev.parent, "Error Warning interrupt\n");
689 hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
690 }
691
692 if (int_status & HECC_CANGIF_EPIF) { /* error passive int */
693 if ((int_status & HECC_CANGIF_BOIF) == 0) {
694 priv->can.state = CAN_STATE_ERROR_PASSIVE;
695 ++priv->can.can_stats.error_passive;
696 cf->can_id |= CAN_ERR_CRTL;
697 if (hecc_read(priv, HECC_CANTEC) > 127)
698 cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
699 if (hecc_read(priv, HECC_CANREC) > 127)
700 cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
701 }
702 hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP);
703 dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n");
704 hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
705 }
706
707 /*
708 * Need to check busoff condition in error status register too to
709 * ensure warning interrupts don't hog the system
710 */
711 if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) {
712 priv->can.state = CAN_STATE_BUS_OFF;
713 cf->can_id |= CAN_ERR_BUSOFF;
714 hecc_set_bit(priv, HECC_CANES, HECC_CANES_BO);
715 hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
716 /* Disable all interrupts in bus-off to avoid int hog */
717 hecc_write(priv, HECC_CANGIM, 0);
718 can_bus_off(ndev);
719 }
720
721 if (err_status & HECC_BUS_ERROR) {
722 ++priv->can.can_stats.bus_error;
723 cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
724 cf->data[2] |= CAN_ERR_PROT_UNSPEC;
725 if (err_status & HECC_CANES_FE) {
726 hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE);
727 cf->data[2] |= CAN_ERR_PROT_FORM;
728 }
729 if (err_status & HECC_CANES_BE) {
730 hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE);
731 cf->data[2] |= CAN_ERR_PROT_BIT;
732 }
733 if (err_status & HECC_CANES_SE) {
734 hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE);
735 cf->data[2] |= CAN_ERR_PROT_STUFF;
736 }
737 if (err_status & HECC_CANES_CRCE) {
738 hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE);
739 cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
740 CAN_ERR_PROT_LOC_CRC_DEL;
741 }
742 if (err_status & HECC_CANES_ACKE) {
743 hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE);
744 cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
745 CAN_ERR_PROT_LOC_ACK_DEL;
746 }
747 }
748
749 netif_receive_skb(skb);
750 stats->rx_packets++;
751 stats->rx_bytes += cf->can_dlc;
752 return 0;
753}
754
755static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
756{
757 struct net_device *ndev = (struct net_device *)dev_id;
758 struct ti_hecc_priv *priv = netdev_priv(ndev);
759 struct net_device_stats *stats = &ndev->stats;
760 u32 mbxno, mbx_mask, int_status, err_status;
761 unsigned long ack, flags;
762
763 int_status = hecc_read(priv,
764 (priv->int_line) ? HECC_CANGIF1 : HECC_CANGIF0);
765
766 if (!int_status)
767 return IRQ_NONE;
768
769 err_status = hecc_read(priv, HECC_CANES);
770 if (err_status & (HECC_BUS_ERROR | HECC_CANES_BO |
771 HECC_CANES_EP | HECC_CANES_EW))
772 ti_hecc_error(ndev, int_status, err_status);
773
774 if (int_status & HECC_CANGIF_GMIF) {
775 while (priv->tx_tail - priv->tx_head > 0) {
776 mbxno = get_tx_tail_mb(priv);
777 mbx_mask = BIT(mbxno);
778 if (!(mbx_mask & hecc_read(priv, HECC_CANTA)))
779 break;
780 hecc_clear_bit(priv, HECC_CANMIM, mbx_mask);
781 hecc_write(priv, HECC_CANTA, mbx_mask);
782 spin_lock_irqsave(&priv->mbx_lock, flags);
783 hecc_clear_bit(priv, HECC_CANME, mbx_mask);
784 spin_unlock_irqrestore(&priv->mbx_lock, flags);
785 stats->tx_bytes += hecc_read_mbx(priv, mbxno,
786 HECC_CANMCF) & 0xF;
787 stats->tx_packets++;
788 can_get_echo_skb(ndev, mbxno);
789 --priv->tx_tail;
790 }
791
792 /* restart queue if wrap-up or if queue stalled on last pkt */
793 if (((priv->tx_head == priv->tx_tail) &&
794 ((priv->tx_head & HECC_TX_MASK) != HECC_TX_MASK)) ||
795 (((priv->tx_tail & HECC_TX_MASK) == HECC_TX_MASK) &&
796 ((priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK)))
797 netif_wake_queue(ndev);
798
799 /* Disable RX mailbox interrupts and let NAPI reenable them */
800 if (hecc_read(priv, HECC_CANRMP)) {
801 ack = hecc_read(priv, HECC_CANMIM);
802 ack &= BIT(HECC_MAX_TX_MBOX) - 1;
803 hecc_write(priv, HECC_CANMIM, ack);
804 napi_schedule(&priv->napi);
805 }
806 }
807
808 /* clear all interrupt conditions - read back to avoid spurious ints */
809 if (priv->int_line) {
810 hecc_write(priv, HECC_CANGIF1, HECC_SET_REG);
811 int_status = hecc_read(priv, HECC_CANGIF1);
812 } else {
813 hecc_write(priv, HECC_CANGIF0, HECC_SET_REG);
814 int_status = hecc_read(priv, HECC_CANGIF0);
815 }
816
817 return IRQ_HANDLED;
818}
819
820static int ti_hecc_open(struct net_device *ndev)
821{
822 struct ti_hecc_priv *priv = netdev_priv(ndev);
823 int err;
824
825 err = request_irq(ndev->irq, ti_hecc_interrupt, IRQF_SHARED,
826 ndev->name, ndev);
827 if (err) {
828 dev_err(ndev->dev.parent, "error requesting interrupt\n");
829 return err;
830 }
831
832 /* Open common can device */
833 err = open_candev(ndev);
834 if (err) {
835 dev_err(ndev->dev.parent, "open_candev() failed %d\n", err);
836 free_irq(ndev->irq, ndev);
837 return err;
838 }
839
840 clk_enable(priv->clk);
841 ti_hecc_start(ndev);
842 napi_enable(&priv->napi);
843 netif_start_queue(ndev);
844
845 return 0;
846}
847
848static int ti_hecc_close(struct net_device *ndev)
849{
850 struct ti_hecc_priv *priv = netdev_priv(ndev);
851
852 netif_stop_queue(ndev);
853 napi_disable(&priv->napi);
854 ti_hecc_stop(ndev);
855 free_irq(ndev->irq, ndev);
856 clk_disable(priv->clk);
857 close_candev(ndev);
858
859 return 0;
860}
861
862static const struct net_device_ops ti_hecc_netdev_ops = {
863 .ndo_open = ti_hecc_open,
864 .ndo_stop = ti_hecc_close,
865 .ndo_start_xmit = ti_hecc_xmit,
866};
867
868static int ti_hecc_probe(struct platform_device *pdev)
869{
870 struct net_device *ndev = (struct net_device *)0;
871 struct ti_hecc_priv *priv;
872 struct ti_hecc_platform_data *pdata;
873 struct resource *mem, *irq;
874 void __iomem *addr;
875 int err = -ENODEV;
876
877 pdata = pdev->dev.platform_data;
878 if (!pdata) {
879 dev_err(&pdev->dev, "No platform data\n");
880 goto probe_exit;
881 }
882
883 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
884 if (!mem) {
885 dev_err(&pdev->dev, "No mem resources\n");
886 goto probe_exit;
887 }
888 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
889 if (!irq) {
890 dev_err(&pdev->dev, "No irq resource\n");
891 goto probe_exit;
892 }
893 if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
894 dev_err(&pdev->dev, "HECC region already claimed\n");
895 err = -EBUSY;
896 goto probe_exit;
897 }
898 addr = ioremap(mem->start, resource_size(mem));
899 if (!addr) {
900 dev_err(&pdev->dev, "ioremap failed\n");
901 err = -ENOMEM;
902 goto probe_exit_free_region;
903 }
904
905 ndev = alloc_candev(sizeof(struct ti_hecc_priv));
906 if (!ndev) {
907 dev_err(&pdev->dev, "alloc_candev failed\n");
908 err = -ENOMEM;
909 goto probe_exit_iounmap;
910 }
911
912 priv = netdev_priv(ndev);
913 priv->ndev = ndev;
914 priv->base = addr;
915 priv->scc_ram_offset = pdata->scc_ram_offset;
916 priv->hecc_ram_offset = pdata->hecc_ram_offset;
917 priv->mbx_offset = pdata->mbx_offset;
918 priv->int_line = pdata->int_line;
919
920 priv->can.bittiming_const = &ti_hecc_bittiming_const;
921 priv->can.do_set_mode = ti_hecc_do_set_mode;
922 priv->can.do_get_state = ti_hecc_get_state;
923
924 ndev->irq = irq->start;
925 ndev->flags |= IFF_ECHO;
926 platform_set_drvdata(pdev, ndev);
927 SET_NETDEV_DEV(ndev, &pdev->dev);
928 ndev->netdev_ops = &ti_hecc_netdev_ops;
929
930 priv->clk = clk_get(&pdev->dev, "hecc_ck");
931 if (IS_ERR(priv->clk)) {
932 dev_err(&pdev->dev, "No clock available\n");
933 err = PTR_ERR(priv->clk);
934 priv->clk = NULL;
935 goto probe_exit_candev;
936 }
937 priv->can.clock.freq = clk_get_rate(priv->clk);
938 netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
939 HECC_DEF_NAPI_WEIGHT);
940
941 err = register_candev(ndev);
942 if (err) {
943 dev_err(&pdev->dev, "register_candev() failed\n");
944 goto probe_exit_clk;
945 }
946 dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
947 priv->base, (u32) ndev->irq);
948
949 return 0;
950
951probe_exit_clk:
952 clk_put(priv->clk);
953probe_exit_candev:
954 free_candev(ndev);
955probe_exit_iounmap:
956 iounmap(addr);
957probe_exit_free_region:
958 release_mem_region(mem->start, resource_size(mem));
959probe_exit:
960 return err;
961}
962
963static int __devexit ti_hecc_remove(struct platform_device *pdev)
964{
965 struct resource *res;
966 struct net_device *ndev = platform_get_drvdata(pdev);
967 struct ti_hecc_priv *priv = netdev_priv(ndev);
968
969 clk_put(priv->clk);
970 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
971 iounmap(priv->base);
972 release_mem_region(res->start, resource_size(res));
973 unregister_candev(ndev);
974 free_candev(ndev);
975 platform_set_drvdata(pdev, NULL);
976
977 return 0;
978}
979
980/* TI HECC netdevice driver: platform driver structure */
981static struct platform_driver ti_hecc_driver = {
982 .driver = {
983 .name = DRV_NAME,
984 .owner = THIS_MODULE,
985 },
986 .probe = ti_hecc_probe,
987 .remove = __devexit_p(ti_hecc_remove),
988};
989
990static int __init ti_hecc_init_driver(void)
991{
992 printk(KERN_INFO DRV_DESC "\n");
993 return platform_driver_register(&ti_hecc_driver);
994}
995module_init(ti_hecc_init_driver);
996
997static void __exit ti_hecc_exit_driver(void)
998{
999 printk(KERN_INFO DRV_DESC " unloaded\n");
1000 platform_driver_unregister(&ti_hecc_driver);
1001}
1002module_exit(ti_hecc_exit_driver);
1003
1004MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
1005MODULE_LICENSE("GPL v2");
1006MODULE_DESCRIPTION(DRV_DESC);
diff --git a/include/linux/can/platform/ti_hecc.h b/include/linux/can/platform/ti_hecc.h
new file mode 100644
index 000000000000..4688c7bb1bd1
--- /dev/null
+++ b/include/linux/can/platform/ti_hecc.h
@@ -0,0 +1,40 @@
1/*
2 * TI HECC (High End CAN Controller) driver platform header
3 *
4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed as is WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17/**
18 * struct hecc_platform_data - HECC Platform Data
19 *
20 * @scc_hecc_offset: mostly 0 - should really never change
21 * @scc_ram_offset: SCC RAM offset
22 * @hecc_ram_offset: HECC RAM offset
23 * @mbx_offset: Mailbox RAM offset
24 * @int_line: Interrupt line to use - 0 or 1
25 * @version: version for future use
26 *
27 * Platform data structure to get all platform specific settings.
28 * this structure also accounts the fact that the IP may have different
29 * RAM and mailbox offsets for different SOC's
30 */
31struct ti_hecc_platform_data {
32 u32 scc_hecc_offset;
33 u32 scc_ram_offset;
34 u32 hecc_ram_offset;
35 u32 mbx_offset;
36 u32 int_line;
37 u32 version;
38};
39
40