Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Anant Gole and committed by
David S. Miller
3758bf25 0cdc0369

+1054
+7
drivers/net/can/Kconfig
··· 95 95 ---help--- 96 96 This is a driver for the SoC CAN controller in Atmel's AT91SAM9263. 97 97 98 + config 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 + 98 105 config CAN_DEBUG_DEVICES 99 106 bool "CAN devices debugging messages" 100 107 depends on CAN
+1
drivers/net/can/Makefile
··· 11 11 12 12 obj-$(CONFIG_CAN_SJA1000) += sja1000/ 13 13 obj-$(CONFIG_CAN_AT91) += at91_can.o 14 + obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o 14 15 15 16 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+1006
drivers/net/can/ti_hecc.c
··· 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" 55 + MODULE_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 */ 201 + static 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 + 213 + struct 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 + 229 + static inline int get_tx_head_mb(struct ti_hecc_priv *priv) 230 + { 231 + return priv->tx_head & HECC_TX_MB_MASK; 232 + } 233 + 234 + static inline int get_tx_tail_mb(struct ti_hecc_priv *priv) 235 + { 236 + return priv->tx_tail & HECC_TX_MB_MASK; 237 + } 238 + 239 + static 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 + 244 + static 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 + 249 + static 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 + 256 + static 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 + 262 + static inline void hecc_write(struct ti_hecc_priv *priv, u32 reg, u32 val) 263 + { 264 + __raw_writel(val, priv->base + reg); 265 + } 266 + 267 + static inline u32 hecc_read(struct ti_hecc_priv *priv, int reg) 268 + { 269 + return __raw_readl(priv->base + reg); 270 + } 271 + 272 + static 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 + 278 + static 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 + 284 + static 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 + 289 + static 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 + 298 + static 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 + 324 + static 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 + 387 + static 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 + 427 + static 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 + 438 + static 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 + */ 477 + static 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 + 534 + static 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 + */ 607 + static 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 + 654 + static 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 + 755 + static 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 + 820 + static 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 + 848 + static 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 + 862 + static 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 + 868 + static 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 + 951 + probe_exit_clk: 952 + clk_put(priv->clk); 953 + probe_exit_candev: 954 + free_candev(ndev); 955 + probe_exit_iounmap: 956 + iounmap(addr); 957 + probe_exit_free_region: 958 + release_mem_region(mem->start, resource_size(mem)); 959 + probe_exit: 960 + return err; 961 + } 962 + 963 + static 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 */ 981 + static 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 + 990 + static int __init ti_hecc_init_driver(void) 991 + { 992 + printk(KERN_INFO DRV_DESC "\n"); 993 + return platform_driver_register(&ti_hecc_driver); 994 + } 995 + module_init(ti_hecc_init_driver); 996 + 997 + static void __exit ti_hecc_exit_driver(void) 998 + { 999 + printk(KERN_INFO DRV_DESC " unloaded\n"); 1000 + platform_driver_unregister(&ti_hecc_driver); 1001 + } 1002 + module_exit(ti_hecc_exit_driver); 1003 + 1004 + MODULE_AUTHOR("Anant Gole <anantgole@ti.com>"); 1005 + MODULE_LICENSE("GPL v2"); 1006 + MODULE_DESCRIPTION(DRV_DESC);
+40
include/linux/can/platform/ti_hecc.h
··· 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 + */ 31 + struct 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 +