162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * CAN bus driver for Bosch C_CAN controller 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2010 ST Microelectronics 562306a36Sopenharmony_ci * Bhupesh Sharma <bhupesh.sharma@st.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Borrowed heavily from the C_CAN driver originally written by: 862306a36Sopenharmony_ci * Copyright (C) 2007 962306a36Sopenharmony_ci * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de> 1062306a36Sopenharmony_ci * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch> 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B. 1362306a36Sopenharmony_ci * Bosch C_CAN user manual can be obtained from: 1462306a36Sopenharmony_ci * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/ 1562306a36Sopenharmony_ci * users_manual_c_can.pdf 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 1862306a36Sopenharmony_ci * License version 2. This program is licensed "as is" without any 1962306a36Sopenharmony_ci * warranty of any kind, whether express or implied. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#ifndef C_CAN_H 2362306a36Sopenharmony_ci#define C_CAN_H 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum reg { 2662306a36Sopenharmony_ci C_CAN_CTRL_REG = 0, 2762306a36Sopenharmony_ci C_CAN_CTRL_EX_REG, 2862306a36Sopenharmony_ci C_CAN_STS_REG, 2962306a36Sopenharmony_ci C_CAN_ERR_CNT_REG, 3062306a36Sopenharmony_ci C_CAN_BTR_REG, 3162306a36Sopenharmony_ci C_CAN_INT_REG, 3262306a36Sopenharmony_ci C_CAN_TEST_REG, 3362306a36Sopenharmony_ci C_CAN_BRPEXT_REG, 3462306a36Sopenharmony_ci C_CAN_IF1_COMREQ_REG, 3562306a36Sopenharmony_ci C_CAN_IF1_COMMSK_REG, 3662306a36Sopenharmony_ci C_CAN_IF1_MASK1_REG, 3762306a36Sopenharmony_ci C_CAN_IF1_MASK2_REG, 3862306a36Sopenharmony_ci C_CAN_IF1_ARB1_REG, 3962306a36Sopenharmony_ci C_CAN_IF1_ARB2_REG, 4062306a36Sopenharmony_ci C_CAN_IF1_MSGCTRL_REG, 4162306a36Sopenharmony_ci C_CAN_IF1_DATA1_REG, 4262306a36Sopenharmony_ci C_CAN_IF1_DATA2_REG, 4362306a36Sopenharmony_ci C_CAN_IF1_DATA3_REG, 4462306a36Sopenharmony_ci C_CAN_IF1_DATA4_REG, 4562306a36Sopenharmony_ci C_CAN_IF2_COMREQ_REG, 4662306a36Sopenharmony_ci C_CAN_IF2_COMMSK_REG, 4762306a36Sopenharmony_ci C_CAN_IF2_MASK1_REG, 4862306a36Sopenharmony_ci C_CAN_IF2_MASK2_REG, 4962306a36Sopenharmony_ci C_CAN_IF2_ARB1_REG, 5062306a36Sopenharmony_ci C_CAN_IF2_ARB2_REG, 5162306a36Sopenharmony_ci C_CAN_IF2_MSGCTRL_REG, 5262306a36Sopenharmony_ci C_CAN_IF2_DATA1_REG, 5362306a36Sopenharmony_ci C_CAN_IF2_DATA2_REG, 5462306a36Sopenharmony_ci C_CAN_IF2_DATA3_REG, 5562306a36Sopenharmony_ci C_CAN_IF2_DATA4_REG, 5662306a36Sopenharmony_ci C_CAN_TXRQST1_REG, 5762306a36Sopenharmony_ci C_CAN_TXRQST2_REG, 5862306a36Sopenharmony_ci C_CAN_NEWDAT1_REG, 5962306a36Sopenharmony_ci C_CAN_NEWDAT2_REG, 6062306a36Sopenharmony_ci C_CAN_INTPND1_REG, 6162306a36Sopenharmony_ci C_CAN_INTPND2_REG, 6262306a36Sopenharmony_ci C_CAN_INTPND3_REG, 6362306a36Sopenharmony_ci C_CAN_MSGVAL1_REG, 6462306a36Sopenharmony_ci C_CAN_MSGVAL2_REG, 6562306a36Sopenharmony_ci C_CAN_FUNCTION_REG, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic const u16 __maybe_unused reg_map_c_can[] = { 6962306a36Sopenharmony_ci [C_CAN_CTRL_REG] = 0x00, 7062306a36Sopenharmony_ci [C_CAN_STS_REG] = 0x02, 7162306a36Sopenharmony_ci [C_CAN_ERR_CNT_REG] = 0x04, 7262306a36Sopenharmony_ci [C_CAN_BTR_REG] = 0x06, 7362306a36Sopenharmony_ci [C_CAN_INT_REG] = 0x08, 7462306a36Sopenharmony_ci [C_CAN_TEST_REG] = 0x0A, 7562306a36Sopenharmony_ci [C_CAN_BRPEXT_REG] = 0x0C, 7662306a36Sopenharmony_ci [C_CAN_IF1_COMREQ_REG] = 0x10, 7762306a36Sopenharmony_ci [C_CAN_IF1_COMMSK_REG] = 0x12, 7862306a36Sopenharmony_ci [C_CAN_IF1_MASK1_REG] = 0x14, 7962306a36Sopenharmony_ci [C_CAN_IF1_MASK2_REG] = 0x16, 8062306a36Sopenharmony_ci [C_CAN_IF1_ARB1_REG] = 0x18, 8162306a36Sopenharmony_ci [C_CAN_IF1_ARB2_REG] = 0x1A, 8262306a36Sopenharmony_ci [C_CAN_IF1_MSGCTRL_REG] = 0x1C, 8362306a36Sopenharmony_ci [C_CAN_IF1_DATA1_REG] = 0x1E, 8462306a36Sopenharmony_ci [C_CAN_IF1_DATA2_REG] = 0x20, 8562306a36Sopenharmony_ci [C_CAN_IF1_DATA3_REG] = 0x22, 8662306a36Sopenharmony_ci [C_CAN_IF1_DATA4_REG] = 0x24, 8762306a36Sopenharmony_ci [C_CAN_IF2_COMREQ_REG] = 0x40, 8862306a36Sopenharmony_ci [C_CAN_IF2_COMMSK_REG] = 0x42, 8962306a36Sopenharmony_ci [C_CAN_IF2_MASK1_REG] = 0x44, 9062306a36Sopenharmony_ci [C_CAN_IF2_MASK2_REG] = 0x46, 9162306a36Sopenharmony_ci [C_CAN_IF2_ARB1_REG] = 0x48, 9262306a36Sopenharmony_ci [C_CAN_IF2_ARB2_REG] = 0x4A, 9362306a36Sopenharmony_ci [C_CAN_IF2_MSGCTRL_REG] = 0x4C, 9462306a36Sopenharmony_ci [C_CAN_IF2_DATA1_REG] = 0x4E, 9562306a36Sopenharmony_ci [C_CAN_IF2_DATA2_REG] = 0x50, 9662306a36Sopenharmony_ci [C_CAN_IF2_DATA3_REG] = 0x52, 9762306a36Sopenharmony_ci [C_CAN_IF2_DATA4_REG] = 0x54, 9862306a36Sopenharmony_ci [C_CAN_TXRQST1_REG] = 0x80, 9962306a36Sopenharmony_ci [C_CAN_TXRQST2_REG] = 0x82, 10062306a36Sopenharmony_ci [C_CAN_NEWDAT1_REG] = 0x90, 10162306a36Sopenharmony_ci [C_CAN_NEWDAT2_REG] = 0x92, 10262306a36Sopenharmony_ci [C_CAN_INTPND1_REG] = 0xA0, 10362306a36Sopenharmony_ci [C_CAN_INTPND2_REG] = 0xA2, 10462306a36Sopenharmony_ci [C_CAN_MSGVAL1_REG] = 0xB0, 10562306a36Sopenharmony_ci [C_CAN_MSGVAL2_REG] = 0xB2, 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic const u16 __maybe_unused reg_map_d_can[] = { 10962306a36Sopenharmony_ci [C_CAN_CTRL_REG] = 0x00, 11062306a36Sopenharmony_ci [C_CAN_CTRL_EX_REG] = 0x02, 11162306a36Sopenharmony_ci [C_CAN_STS_REG] = 0x04, 11262306a36Sopenharmony_ci [C_CAN_ERR_CNT_REG] = 0x08, 11362306a36Sopenharmony_ci [C_CAN_BTR_REG] = 0x0C, 11462306a36Sopenharmony_ci [C_CAN_BRPEXT_REG] = 0x0E, 11562306a36Sopenharmony_ci [C_CAN_INT_REG] = 0x10, 11662306a36Sopenharmony_ci [C_CAN_TEST_REG] = 0x14, 11762306a36Sopenharmony_ci [C_CAN_FUNCTION_REG] = 0x18, 11862306a36Sopenharmony_ci [C_CAN_TXRQST1_REG] = 0x88, 11962306a36Sopenharmony_ci [C_CAN_TXRQST2_REG] = 0x8A, 12062306a36Sopenharmony_ci [C_CAN_NEWDAT1_REG] = 0x9C, 12162306a36Sopenharmony_ci [C_CAN_NEWDAT2_REG] = 0x9E, 12262306a36Sopenharmony_ci [C_CAN_INTPND1_REG] = 0xB0, 12362306a36Sopenharmony_ci [C_CAN_INTPND2_REG] = 0xB2, 12462306a36Sopenharmony_ci [C_CAN_INTPND3_REG] = 0xB4, 12562306a36Sopenharmony_ci [C_CAN_MSGVAL1_REG] = 0xC4, 12662306a36Sopenharmony_ci [C_CAN_MSGVAL2_REG] = 0xC6, 12762306a36Sopenharmony_ci [C_CAN_IF1_COMREQ_REG] = 0x100, 12862306a36Sopenharmony_ci [C_CAN_IF1_COMMSK_REG] = 0x102, 12962306a36Sopenharmony_ci [C_CAN_IF1_MASK1_REG] = 0x104, 13062306a36Sopenharmony_ci [C_CAN_IF1_MASK2_REG] = 0x106, 13162306a36Sopenharmony_ci [C_CAN_IF1_ARB1_REG] = 0x108, 13262306a36Sopenharmony_ci [C_CAN_IF1_ARB2_REG] = 0x10A, 13362306a36Sopenharmony_ci [C_CAN_IF1_MSGCTRL_REG] = 0x10C, 13462306a36Sopenharmony_ci [C_CAN_IF1_DATA1_REG] = 0x110, 13562306a36Sopenharmony_ci [C_CAN_IF1_DATA2_REG] = 0x112, 13662306a36Sopenharmony_ci [C_CAN_IF1_DATA3_REG] = 0x114, 13762306a36Sopenharmony_ci [C_CAN_IF1_DATA4_REG] = 0x116, 13862306a36Sopenharmony_ci [C_CAN_IF2_COMREQ_REG] = 0x120, 13962306a36Sopenharmony_ci [C_CAN_IF2_COMMSK_REG] = 0x122, 14062306a36Sopenharmony_ci [C_CAN_IF2_MASK1_REG] = 0x124, 14162306a36Sopenharmony_ci [C_CAN_IF2_MASK2_REG] = 0x126, 14262306a36Sopenharmony_ci [C_CAN_IF2_ARB1_REG] = 0x128, 14362306a36Sopenharmony_ci [C_CAN_IF2_ARB2_REG] = 0x12A, 14462306a36Sopenharmony_ci [C_CAN_IF2_MSGCTRL_REG] = 0x12C, 14562306a36Sopenharmony_ci [C_CAN_IF2_DATA1_REG] = 0x130, 14662306a36Sopenharmony_ci [C_CAN_IF2_DATA2_REG] = 0x132, 14762306a36Sopenharmony_ci [C_CAN_IF2_DATA3_REG] = 0x134, 14862306a36Sopenharmony_ci [C_CAN_IF2_DATA4_REG] = 0x136, 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cienum c_can_dev_id { 15262306a36Sopenharmony_ci BOSCH_C_CAN, 15362306a36Sopenharmony_ci BOSCH_D_CAN, 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistruct raminit_bits { 15762306a36Sopenharmony_ci u8 start; 15862306a36Sopenharmony_ci u8 done; 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistruct c_can_driver_data { 16262306a36Sopenharmony_ci enum c_can_dev_id id; 16362306a36Sopenharmony_ci unsigned int msg_obj_num; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* RAMINIT register description. Optional. */ 16662306a36Sopenharmony_ci const struct raminit_bits *raminit_bits; /* Array of START/DONE bit positions */ 16762306a36Sopenharmony_ci u8 raminit_num; /* Number of CAN instances on the SoC */ 16862306a36Sopenharmony_ci bool raminit_pulse; /* If set, sets and clears START bit (pulse) */ 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/* Out of band RAMINIT register access via syscon regmap */ 17262306a36Sopenharmony_cistruct c_can_raminit { 17362306a36Sopenharmony_ci struct regmap *syscon; /* for raminit ctrl. reg. access */ 17462306a36Sopenharmony_ci unsigned int reg; /* register index within syscon */ 17562306a36Sopenharmony_ci struct raminit_bits bits; 17662306a36Sopenharmony_ci bool needs_pulse; 17762306a36Sopenharmony_ci}; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* c_can tx ring structure */ 18062306a36Sopenharmony_cistruct c_can_tx_ring { 18162306a36Sopenharmony_ci unsigned int head; 18262306a36Sopenharmony_ci unsigned int tail; 18362306a36Sopenharmony_ci unsigned int obj_num; 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* c_can private data structure */ 18762306a36Sopenharmony_cistruct c_can_priv { 18862306a36Sopenharmony_ci struct can_priv can; /* must be the first member */ 18962306a36Sopenharmony_ci struct napi_struct napi; 19062306a36Sopenharmony_ci struct net_device *dev; 19162306a36Sopenharmony_ci struct device *device; 19262306a36Sopenharmony_ci unsigned int msg_obj_num; 19362306a36Sopenharmony_ci unsigned int msg_obj_rx_num; 19462306a36Sopenharmony_ci unsigned int msg_obj_tx_num; 19562306a36Sopenharmony_ci unsigned int msg_obj_rx_first; 19662306a36Sopenharmony_ci unsigned int msg_obj_rx_last; 19762306a36Sopenharmony_ci unsigned int msg_obj_tx_first; 19862306a36Sopenharmony_ci unsigned int msg_obj_tx_last; 19962306a36Sopenharmony_ci u32 msg_obj_rx_mask; 20062306a36Sopenharmony_ci atomic_t sie_pending; 20162306a36Sopenharmony_ci unsigned long tx_dir; 20262306a36Sopenharmony_ci int last_status; 20362306a36Sopenharmony_ci struct c_can_tx_ring tx; 20462306a36Sopenharmony_ci u16 (*read_reg)(const struct c_can_priv *priv, enum reg index); 20562306a36Sopenharmony_ci void (*write_reg)(const struct c_can_priv *priv, enum reg index, u16 val); 20662306a36Sopenharmony_ci u32 (*read_reg32)(const struct c_can_priv *priv, enum reg index); 20762306a36Sopenharmony_ci void (*write_reg32)(const struct c_can_priv *priv, enum reg index, u32 val); 20862306a36Sopenharmony_ci void __iomem *base; 20962306a36Sopenharmony_ci const u16 *regs; 21062306a36Sopenharmony_ci enum c_can_dev_id type; 21162306a36Sopenharmony_ci struct c_can_raminit raminit_sys; /* RAMINIT via syscon regmap */ 21262306a36Sopenharmony_ci void (*raminit)(const struct c_can_priv *priv, bool enable); 21362306a36Sopenharmony_ci u32 comm_rcv_high; 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistruct net_device *alloc_c_can_dev(int msg_obj_num); 21762306a36Sopenharmony_civoid free_c_can_dev(struct net_device *dev); 21862306a36Sopenharmony_ciint register_c_can_dev(struct net_device *dev); 21962306a36Sopenharmony_civoid unregister_c_can_dev(struct net_device *dev); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#ifdef CONFIG_PM 22262306a36Sopenharmony_ciint c_can_power_up(struct net_device *dev); 22362306a36Sopenharmony_ciint c_can_power_down(struct net_device *dev); 22462306a36Sopenharmony_ci#endif 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ciextern const struct ethtool_ops c_can_ethtool_ops; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic inline u8 c_can_get_tx_head(const struct c_can_tx_ring *ring) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci return ring->head & (ring->obj_num - 1); 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic inline u8 c_can_get_tx_tail(const struct c_can_tx_ring *ring) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci return ring->tail & (ring->obj_num - 1); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic inline u8 c_can_get_tx_free(const struct c_can_priv *priv, 23962306a36Sopenharmony_ci const struct c_can_tx_ring *ring) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci u8 head = c_can_get_tx_head(ring); 24262306a36Sopenharmony_ci u8 tail = c_can_get_tx_tail(ring); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (priv->type == BOSCH_D_CAN) 24562306a36Sopenharmony_ci return ring->obj_num - (ring->head - ring->tail); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* This is not a FIFO. C/D_CAN sends out the buffers 24862306a36Sopenharmony_ci * prioritized. The lowest buffer number wins. 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_ci if (head < tail) 25162306a36Sopenharmony_ci return 0; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return ring->obj_num - head; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci#endif /* C_CAN_H */ 257