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