1aaa7cb26SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 22a367c3aSWolfgang Grandegger /* 32a367c3aSWolfgang Grandegger * Core driver for the CC770 and AN82527 CAN controllers 42a367c3aSWolfgang Grandegger * 52a367c3aSWolfgang Grandegger * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com> 62a367c3aSWolfgang Grandegger */ 72a367c3aSWolfgang Grandegger 82a367c3aSWolfgang Grandegger #ifndef CC770_DEV_H 92a367c3aSWolfgang Grandegger #define CC770_DEV_H 102a367c3aSWolfgang Grandegger 112a367c3aSWolfgang Grandegger #include <linux/can/dev.h> 122a367c3aSWolfgang Grandegger 132a367c3aSWolfgang Grandegger struct cc770_msgobj { 142a367c3aSWolfgang Grandegger u8 ctrl0; 152a367c3aSWolfgang Grandegger u8 ctrl1; 162a367c3aSWolfgang Grandegger u8 id[4]; 172a367c3aSWolfgang Grandegger u8 config; 182a367c3aSWolfgang Grandegger u8 data[8]; 192a367c3aSWolfgang Grandegger u8 dontuse; /* padding */ 202a367c3aSWolfgang Grandegger } __packed; 212a367c3aSWolfgang Grandegger 222a367c3aSWolfgang Grandegger struct cc770_regs { 232a367c3aSWolfgang Grandegger union { 242a367c3aSWolfgang Grandegger struct cc770_msgobj msgobj[16]; /* Message object 1..15 */ 252a367c3aSWolfgang Grandegger struct { 262a367c3aSWolfgang Grandegger u8 control; /* Control Register */ 272a367c3aSWolfgang Grandegger u8 status; /* Status Register */ 282a367c3aSWolfgang Grandegger u8 cpu_interface; /* CPU Interface Register */ 292a367c3aSWolfgang Grandegger u8 dontuse1; 302a367c3aSWolfgang Grandegger u8 high_speed_read[2]; /* High Speed Read */ 312a367c3aSWolfgang Grandegger u8 global_mask_std[2]; /* Standard Global Mask */ 322a367c3aSWolfgang Grandegger u8 global_mask_ext[4]; /* Extended Global Mask */ 332a367c3aSWolfgang Grandegger u8 msg15_mask[4]; /* Message 15 Mask */ 342a367c3aSWolfgang Grandegger u8 dontuse2[15]; 352a367c3aSWolfgang Grandegger u8 clkout; /* Clock Out Register */ 362a367c3aSWolfgang Grandegger u8 dontuse3[15]; 372a367c3aSWolfgang Grandegger u8 bus_config; /* Bus Configuration Register */ 382a367c3aSWolfgang Grandegger u8 dontuse4[15]; 392a367c3aSWolfgang Grandegger u8 bit_timing_0; /* Bit Timing Register byte 0 */ 402a367c3aSWolfgang Grandegger u8 dontuse5[15]; 412a367c3aSWolfgang Grandegger u8 bit_timing_1; /* Bit Timing Register byte 1 */ 422a367c3aSWolfgang Grandegger u8 dontuse6[15]; 432a367c3aSWolfgang Grandegger u8 interrupt; /* Interrupt Register */ 442a367c3aSWolfgang Grandegger u8 dontuse7[15]; 452a367c3aSWolfgang Grandegger u8 rx_error_counter; /* Receive Error Counter */ 462a367c3aSWolfgang Grandegger u8 dontuse8[15]; 472a367c3aSWolfgang Grandegger u8 tx_error_counter; /* Transmit Error Counter */ 482a367c3aSWolfgang Grandegger u8 dontuse9[31]; 492a367c3aSWolfgang Grandegger u8 p1_conf; 502a367c3aSWolfgang Grandegger u8 dontuse10[15]; 512a367c3aSWolfgang Grandegger u8 p2_conf; 522a367c3aSWolfgang Grandegger u8 dontuse11[15]; 532a367c3aSWolfgang Grandegger u8 p1_in; 542a367c3aSWolfgang Grandegger u8 dontuse12[15]; 552a367c3aSWolfgang Grandegger u8 p2_in; 562a367c3aSWolfgang Grandegger u8 dontuse13[15]; 572a367c3aSWolfgang Grandegger u8 p1_out; 582a367c3aSWolfgang Grandegger u8 dontuse14[15]; 592a367c3aSWolfgang Grandegger u8 p2_out; 602a367c3aSWolfgang Grandegger u8 dontuse15[15]; 612a367c3aSWolfgang Grandegger u8 serial_reset_addr; 622a367c3aSWolfgang Grandegger }; 632a367c3aSWolfgang Grandegger }; 642a367c3aSWolfgang Grandegger } __packed; 652a367c3aSWolfgang Grandegger 662a367c3aSWolfgang Grandegger /* Control Register (0x00) */ 672a367c3aSWolfgang Grandegger #define CTRL_INI 0x01 /* Initialization */ 682a367c3aSWolfgang Grandegger #define CTRL_IE 0x02 /* Interrupt Enable */ 692a367c3aSWolfgang Grandegger #define CTRL_SIE 0x04 /* Status Interrupt Enable */ 702a367c3aSWolfgang Grandegger #define CTRL_EIE 0x08 /* Error Interrupt Enable */ 712a367c3aSWolfgang Grandegger #define CTRL_EAF 0x20 /* Enable additional functions */ 722a367c3aSWolfgang Grandegger #define CTRL_CCE 0x40 /* Change Configuration Enable */ 732a367c3aSWolfgang Grandegger 742a367c3aSWolfgang Grandegger /* Status Register (0x01) */ 752a367c3aSWolfgang Grandegger #define STAT_LEC_STUFF 0x01 /* Stuff error */ 762a367c3aSWolfgang Grandegger #define STAT_LEC_FORM 0x02 /* Form error */ 772a367c3aSWolfgang Grandegger #define STAT_LEC_ACK 0x03 /* Acknowledgement error */ 782a367c3aSWolfgang Grandegger #define STAT_LEC_BIT1 0x04 /* Bit1 error */ 792a367c3aSWolfgang Grandegger #define STAT_LEC_BIT0 0x05 /* Bit0 error */ 802a367c3aSWolfgang Grandegger #define STAT_LEC_CRC 0x06 /* CRC error */ 812a367c3aSWolfgang Grandegger #define STAT_LEC_MASK 0x07 /* Last Error Code mask */ 822a367c3aSWolfgang Grandegger #define STAT_TXOK 0x08 /* Transmit Message Successfully */ 832a367c3aSWolfgang Grandegger #define STAT_RXOK 0x10 /* Receive Message Successfully */ 842a367c3aSWolfgang Grandegger #define STAT_WAKE 0x20 /* Wake Up Status */ 852a367c3aSWolfgang Grandegger #define STAT_WARN 0x40 /* Warning Status */ 862a367c3aSWolfgang Grandegger #define STAT_BOFF 0x80 /* Bus Off Status */ 872a367c3aSWolfgang Grandegger 882a367c3aSWolfgang Grandegger /* 892a367c3aSWolfgang Grandegger * CPU Interface Register (0x02) 902a367c3aSWolfgang Grandegger * Clock Out Register (0x1f) 912a367c3aSWolfgang Grandegger * Bus Configuration Register (0x2f) 922a367c3aSWolfgang Grandegger * 932a367c3aSWolfgang Grandegger * see include/linux/can/platform/cc770.h 942a367c3aSWolfgang Grandegger */ 952a367c3aSWolfgang Grandegger 962a367c3aSWolfgang Grandegger /* Message Control Register 0 (Base Address + 0x0) */ 972a367c3aSWolfgang Grandegger #define INTPND_RES 0x01 /* No Interrupt pending */ 982a367c3aSWolfgang Grandegger #define INTPND_SET 0x02 /* Interrupt pending */ 992a367c3aSWolfgang Grandegger #define INTPND_UNC 0x03 1002a367c3aSWolfgang Grandegger #define RXIE_RES 0x04 /* Receive Interrupt Disable */ 1012a367c3aSWolfgang Grandegger #define RXIE_SET 0x08 /* Receive Interrupt Enable */ 1022a367c3aSWolfgang Grandegger #define RXIE_UNC 0x0c 1032a367c3aSWolfgang Grandegger #define TXIE_RES 0x10 /* Transmit Interrupt Disable */ 1042a367c3aSWolfgang Grandegger #define TXIE_SET 0x20 /* Transmit Interrupt Enable */ 1052a367c3aSWolfgang Grandegger #define TXIE_UNC 0x30 1062a367c3aSWolfgang Grandegger #define MSGVAL_RES 0x40 /* Message Invalid */ 1072a367c3aSWolfgang Grandegger #define MSGVAL_SET 0x80 /* Message Valid */ 1082a367c3aSWolfgang Grandegger #define MSGVAL_UNC 0xc0 1092a367c3aSWolfgang Grandegger 1102a367c3aSWolfgang Grandegger /* Message Control Register 1 (Base Address + 0x01) */ 1112a367c3aSWolfgang Grandegger #define NEWDAT_RES 0x01 /* No New Data */ 1122a367c3aSWolfgang Grandegger #define NEWDAT_SET 0x02 /* New Data */ 1132a367c3aSWolfgang Grandegger #define NEWDAT_UNC 0x03 1142a367c3aSWolfgang Grandegger #define MSGLST_RES 0x04 /* No Message Lost */ 1152a367c3aSWolfgang Grandegger #define MSGLST_SET 0x08 /* Message Lost */ 1162a367c3aSWolfgang Grandegger #define MSGLST_UNC 0x0c 1172a367c3aSWolfgang Grandegger #define CPUUPD_RES 0x04 /* No CPU Updating */ 1182a367c3aSWolfgang Grandegger #define CPUUPD_SET 0x08 /* CPU Updating */ 1192a367c3aSWolfgang Grandegger #define CPUUPD_UNC 0x0c 1202a367c3aSWolfgang Grandegger #define TXRQST_RES 0x10 /* No Transmission Request */ 1212a367c3aSWolfgang Grandegger #define TXRQST_SET 0x20 /* Transmission Request */ 1222a367c3aSWolfgang Grandegger #define TXRQST_UNC 0x30 1232a367c3aSWolfgang Grandegger #define RMTPND_RES 0x40 /* No Remote Request Pending */ 1242a367c3aSWolfgang Grandegger #define RMTPND_SET 0x80 /* Remote Request Pending */ 1252a367c3aSWolfgang Grandegger #define RMTPND_UNC 0xc0 1262a367c3aSWolfgang Grandegger 1272a367c3aSWolfgang Grandegger /* Message Configuration Register (Base Address + 0x06) */ 1282a367c3aSWolfgang Grandegger #define MSGCFG_XTD 0x04 /* Extended Identifier */ 1292a367c3aSWolfgang Grandegger #define MSGCFG_DIR 0x08 /* Direction is Transmit */ 1302a367c3aSWolfgang Grandegger 1312a367c3aSWolfgang Grandegger #define MSGOBJ_FIRST 1 1322a367c3aSWolfgang Grandegger #define MSGOBJ_LAST 15 1332a367c3aSWolfgang Grandegger 1342a367c3aSWolfgang Grandegger #define CC770_IO_SIZE 0x100 1352a367c3aSWolfgang Grandegger #define CC770_MAX_IRQ 20 /* max. number of interrupts handled in ISR */ 1362a367c3aSWolfgang Grandegger #define CC770_MAX_MSG 4 /* max. number of messages handled in ISR */ 1372a367c3aSWolfgang Grandegger 1382a367c3aSWolfgang Grandegger #define CC770_ECHO_SKB_MAX 1 1392a367c3aSWolfgang Grandegger 1402a367c3aSWolfgang Grandegger #define cc770_read_reg(priv, member) \ 1412a367c3aSWolfgang Grandegger priv->read_reg(priv, offsetof(struct cc770_regs, member)) 1422a367c3aSWolfgang Grandegger 1432a367c3aSWolfgang Grandegger #define cc770_write_reg(priv, member, value) \ 1442a367c3aSWolfgang Grandegger priv->write_reg(priv, offsetof(struct cc770_regs, member), value) 1452a367c3aSWolfgang Grandegger 1462a367c3aSWolfgang Grandegger /* 1472a367c3aSWolfgang Grandegger * Message objects and flags used by this driver 1482a367c3aSWolfgang Grandegger */ 1492a367c3aSWolfgang Grandegger #define CC770_OBJ_FLAG_RX 0x01 1502a367c3aSWolfgang Grandegger #define CC770_OBJ_FLAG_RTR 0x02 1512a367c3aSWolfgang Grandegger #define CC770_OBJ_FLAG_EFF 0x04 1522a367c3aSWolfgang Grandegger 1532a367c3aSWolfgang Grandegger enum { 1542a367c3aSWolfgang Grandegger CC770_OBJ_RX0 = 0, /* for receiving normal messages */ 1552a367c3aSWolfgang Grandegger CC770_OBJ_RX1, /* for receiving normal messages */ 1562a367c3aSWolfgang Grandegger CC770_OBJ_RX_RTR0, /* for receiving remote transmission requests */ 1572a367c3aSWolfgang Grandegger CC770_OBJ_RX_RTR1, /* for receiving remote transmission requests */ 1582a367c3aSWolfgang Grandegger CC770_OBJ_TX, /* for sending messages */ 1592a367c3aSWolfgang Grandegger CC770_OBJ_MAX 1602a367c3aSWolfgang Grandegger }; 1612a367c3aSWolfgang Grandegger 1622a367c3aSWolfgang Grandegger #define obj2msgobj(o) (MSGOBJ_LAST - (o)) /* message object 11..15 */ 1632a367c3aSWolfgang Grandegger 1642a367c3aSWolfgang Grandegger /* 1652a367c3aSWolfgang Grandegger * CC770 private data structure 1662a367c3aSWolfgang Grandegger */ 1672a367c3aSWolfgang Grandegger struct cc770_priv { 1682a367c3aSWolfgang Grandegger struct can_priv can; /* must be the first member */ 1692a367c3aSWolfgang Grandegger struct sk_buff *echo_skb; 1702a367c3aSWolfgang Grandegger 1712a367c3aSWolfgang Grandegger /* the lower-layer is responsible for appropriate locking */ 1722a367c3aSWolfgang Grandegger u8 (*read_reg)(const struct cc770_priv *priv, int reg); 1732a367c3aSWolfgang Grandegger void (*write_reg)(const struct cc770_priv *priv, int reg, u8 val); 1742a367c3aSWolfgang Grandegger void (*pre_irq)(const struct cc770_priv *priv); 1752a367c3aSWolfgang Grandegger void (*post_irq)(const struct cc770_priv *priv); 1762a367c3aSWolfgang Grandegger 1772a367c3aSWolfgang Grandegger void *priv; /* for board-specific data */ 1782a367c3aSWolfgang Grandegger struct net_device *dev; 1792a367c3aSWolfgang Grandegger 1802a367c3aSWolfgang Grandegger void __iomem *reg_base; /* ioremap'ed address to registers */ 1812a367c3aSWolfgang Grandegger unsigned long irq_flags; /* for request_irq() */ 1822a367c3aSWolfgang Grandegger 1832a367c3aSWolfgang Grandegger unsigned char obj_flags[CC770_OBJ_MAX]; 1842a367c3aSWolfgang Grandegger u8 control_normal_mode; /* Control register for normal mode */ 1852a367c3aSWolfgang Grandegger u8 cpu_interface; /* CPU interface register */ 1862a367c3aSWolfgang Grandegger u8 clkout; /* Clock out register */ 187*88bfb9a7SMarc Kleine-Budde u8 bus_config; /* Bus configuration register */ 18874620123SAndri Yngvason 18974620123SAndri Yngvason struct sk_buff *tx_skb; 1902a367c3aSWolfgang Grandegger }; 1912a367c3aSWolfgang Grandegger 1922a367c3aSWolfgang Grandegger struct net_device *alloc_cc770dev(int sizeof_priv); 1932a367c3aSWolfgang Grandegger void free_cc770dev(struct net_device *dev); 1942a367c3aSWolfgang Grandegger int register_cc770dev(struct net_device *dev); 1952a367c3aSWolfgang Grandegger void unregister_cc770dev(struct net_device *dev); 1962a367c3aSWolfgang Grandegger 1972a367c3aSWolfgang Grandegger #endif /* CC770_DEV_H */ 198