xref: /openbmc/linux/drivers/net/can/usb/f81604.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
188da1743SJi-Ze Hong // SPDX-License-Identifier: GPL-2.0
288da1743SJi-Ze Hong /* Fintek F81604 USB-to-2CAN controller driver.
388da1743SJi-Ze Hong  *
488da1743SJi-Ze Hong  * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
588da1743SJi-Ze Hong  */
688da1743SJi-Ze Hong #include <linux/bitfield.h>
788da1743SJi-Ze Hong #include <linux/netdevice.h>
888da1743SJi-Ze Hong #include <linux/units.h>
988da1743SJi-Ze Hong #include <linux/usb.h>
1088da1743SJi-Ze Hong 
1188da1743SJi-Ze Hong #include <linux/can.h>
1288da1743SJi-Ze Hong #include <linux/can/dev.h>
1388da1743SJi-Ze Hong #include <linux/can/error.h>
1488da1743SJi-Ze Hong #include <linux/can/platform/sja1000.h>
1588da1743SJi-Ze Hong 
1688da1743SJi-Ze Hong #include <asm-generic/unaligned.h>
1788da1743SJi-Ze Hong 
1888da1743SJi-Ze Hong /* vendor and product id */
1988da1743SJi-Ze Hong #define F81604_VENDOR_ID 0x2c42
2088da1743SJi-Ze Hong #define F81604_PRODUCT_ID 0x1709
2188da1743SJi-Ze Hong #define F81604_CAN_CLOCK (12 * MEGA)
2288da1743SJi-Ze Hong #define F81604_MAX_DEV 2
2388da1743SJi-Ze Hong #define F81604_SET_DEVICE_RETRY 10
2488da1743SJi-Ze Hong 
2588da1743SJi-Ze Hong #define F81604_USB_TIMEOUT 2000
2688da1743SJi-Ze Hong #define F81604_SET_GET_REGISTER 0xA0
2788da1743SJi-Ze Hong #define F81604_PORT_OFFSET 0x1000
2888da1743SJi-Ze Hong #define F81604_MAX_RX_URBS 4
2988da1743SJi-Ze Hong 
3088da1743SJi-Ze Hong #define F81604_CMD_DATA 0x00
3188da1743SJi-Ze Hong 
3288da1743SJi-Ze Hong #define F81604_DLC_LEN_MASK GENMASK(3, 0)
3388da1743SJi-Ze Hong #define F81604_DLC_EFF_BIT BIT(7)
3488da1743SJi-Ze Hong #define F81604_DLC_RTR_BIT BIT(6)
3588da1743SJi-Ze Hong 
3688da1743SJi-Ze Hong #define F81604_SFF_SHIFT 5
3788da1743SJi-Ze Hong #define F81604_EFF_SHIFT 3
3888da1743SJi-Ze Hong 
3988da1743SJi-Ze Hong #define F81604_BRP_MASK GENMASK(5, 0)
4088da1743SJi-Ze Hong #define F81604_SJW_MASK GENMASK(7, 6)
4188da1743SJi-Ze Hong 
4288da1743SJi-Ze Hong #define F81604_SEG1_MASK GENMASK(3, 0)
4388da1743SJi-Ze Hong #define F81604_SEG2_MASK GENMASK(6, 4)
4488da1743SJi-Ze Hong 
4588da1743SJi-Ze Hong #define F81604_CLEAR_ALC 0
4688da1743SJi-Ze Hong #define F81604_CLEAR_ECC 1
4788da1743SJi-Ze Hong #define F81604_CLEAR_OVERRUN 2
4888da1743SJi-Ze Hong 
4988da1743SJi-Ze Hong /* device setting */
5088da1743SJi-Ze Hong #define F81604_CTRL_MODE_REG 0x80
5188da1743SJi-Ze Hong #define F81604_TX_ONESHOT (0x03 << 3)
5288da1743SJi-Ze Hong #define F81604_TX_NORMAL (0x01 << 3)
5388da1743SJi-Ze Hong #define F81604_RX_AUTO_RELEASE_BUF BIT(1)
5488da1743SJi-Ze Hong #define F81604_INT_WHEN_CHANGE BIT(0)
5588da1743SJi-Ze Hong 
5688da1743SJi-Ze Hong #define F81604_TERMINATOR_REG 0x105
5788da1743SJi-Ze Hong #define F81604_CAN0_TERM BIT(2)
5888da1743SJi-Ze Hong #define F81604_CAN1_TERM BIT(3)
5988da1743SJi-Ze Hong 
6088da1743SJi-Ze Hong #define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
6188da1743SJi-Ze Hong #define F81604_TERMINATION_ENABLED 120
6288da1743SJi-Ze Hong 
6388da1743SJi-Ze Hong /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
6488da1743SJi-Ze Hong #define F81604_SJA1000_MOD 0x00
6588da1743SJi-Ze Hong #define F81604_SJA1000_CMR 0x01
6688da1743SJi-Ze Hong #define F81604_SJA1000_IR 0x03
6788da1743SJi-Ze Hong #define F81604_SJA1000_IER 0x04
6888da1743SJi-Ze Hong #define F81604_SJA1000_ALC 0x0B
6988da1743SJi-Ze Hong #define F81604_SJA1000_ECC 0x0C
7088da1743SJi-Ze Hong #define F81604_SJA1000_RXERR 0x0E
7188da1743SJi-Ze Hong #define F81604_SJA1000_TXERR 0x0F
7288da1743SJi-Ze Hong #define F81604_SJA1000_ACCC0 0x10
7388da1743SJi-Ze Hong #define F81604_SJA1000_ACCM0 0x14
7488da1743SJi-Ze Hong #define F81604_MAX_FILTER_CNT 4
7588da1743SJi-Ze Hong 
7688da1743SJi-Ze Hong /* Common registers - manual section 6.5 */
7788da1743SJi-Ze Hong #define F81604_SJA1000_BTR0 0x06
7888da1743SJi-Ze Hong #define F81604_SJA1000_BTR1 0x07
7988da1743SJi-Ze Hong #define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7)
8088da1743SJi-Ze Hong #define F81604_SJA1000_OCR 0x08
8188da1743SJi-Ze Hong #define F81604_SJA1000_CDR 0x1F
8288da1743SJi-Ze Hong 
8388da1743SJi-Ze Hong /* mode register */
8488da1743SJi-Ze Hong #define F81604_SJA1000_MOD_RM 0x01
8588da1743SJi-Ze Hong #define F81604_SJA1000_MOD_LOM 0x02
8688da1743SJi-Ze Hong #define F81604_SJA1000_MOD_STM 0x04
8788da1743SJi-Ze Hong 
8888da1743SJi-Ze Hong /* commands */
8988da1743SJi-Ze Hong #define F81604_SJA1000_CMD_CDO 0x08
9088da1743SJi-Ze Hong 
9188da1743SJi-Ze Hong /* interrupt sources */
9288da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_BEI 0x80
9388da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_ALI 0x40
9488da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_EPI 0x20
9588da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_DOI 0x08
9688da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_EI 0x04
9788da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_TI 0x02
9888da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_RI 0x01
9988da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_ALL 0xFF
10088da1743SJi-Ze Hong #define F81604_SJA1000_IRQ_OFF 0x00
10188da1743SJi-Ze Hong 
10288da1743SJi-Ze Hong /* status register content */
10388da1743SJi-Ze Hong #define F81604_SJA1000_SR_BS 0x80
10488da1743SJi-Ze Hong #define F81604_SJA1000_SR_ES 0x40
10588da1743SJi-Ze Hong #define F81604_SJA1000_SR_TCS 0x08
10688da1743SJi-Ze Hong 
10788da1743SJi-Ze Hong /* ECC register */
10888da1743SJi-Ze Hong #define F81604_SJA1000_ECC_SEG 0x1F
10988da1743SJi-Ze Hong #define F81604_SJA1000_ECC_DIR 0x20
11088da1743SJi-Ze Hong #define F81604_SJA1000_ECC_BIT 0x00
11188da1743SJi-Ze Hong #define F81604_SJA1000_ECC_FORM 0x40
11288da1743SJi-Ze Hong #define F81604_SJA1000_ECC_STUFF 0x80
11388da1743SJi-Ze Hong #define F81604_SJA1000_ECC_MASK 0xc0
11488da1743SJi-Ze Hong 
11588da1743SJi-Ze Hong /* ALC register */
11688da1743SJi-Ze Hong #define F81604_SJA1000_ALC_MASK 0x1f
11788da1743SJi-Ze Hong 
11888da1743SJi-Ze Hong /* table of devices that work with this driver */
11988da1743SJi-Ze Hong static const struct usb_device_id f81604_table[] = {
12088da1743SJi-Ze Hong 	{ USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) },
12188da1743SJi-Ze Hong 	{} /* Terminating entry */
12288da1743SJi-Ze Hong };
12388da1743SJi-Ze Hong 
12488da1743SJi-Ze Hong MODULE_DEVICE_TABLE(usb, f81604_table);
12588da1743SJi-Ze Hong 
12688da1743SJi-Ze Hong static const struct ethtool_ops f81604_ethtool_ops = {
12788da1743SJi-Ze Hong 	.get_ts_info = ethtool_op_get_ts_info,
12888da1743SJi-Ze Hong };
12988da1743SJi-Ze Hong 
13088da1743SJi-Ze Hong static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED,
13188da1743SJi-Ze Hong 					  F81604_TERMINATION_ENABLED };
13288da1743SJi-Ze Hong 
13388da1743SJi-Ze Hong struct f81604_priv {
13488da1743SJi-Ze Hong 	struct net_device *netdev[F81604_MAX_DEV];
13588da1743SJi-Ze Hong };
13688da1743SJi-Ze Hong 
13788da1743SJi-Ze Hong struct f81604_port_priv {
13888da1743SJi-Ze Hong 	struct can_priv can;
13988da1743SJi-Ze Hong 	struct net_device *netdev;
14088da1743SJi-Ze Hong 	struct sk_buff *echo_skb;
14188da1743SJi-Ze Hong 
14288da1743SJi-Ze Hong 	unsigned long clear_flags;
14388da1743SJi-Ze Hong 	struct work_struct clear_reg_work;
14488da1743SJi-Ze Hong 
14588da1743SJi-Ze Hong 	struct usb_device *dev;
14688da1743SJi-Ze Hong 	struct usb_interface *intf;
14788da1743SJi-Ze Hong 
14888da1743SJi-Ze Hong 	struct usb_anchor urbs_anchor;
14988da1743SJi-Ze Hong };
15088da1743SJi-Ze Hong 
15188da1743SJi-Ze Hong /* Interrupt endpoint data format:
15288da1743SJi-Ze Hong  *	Byte 0: Status register.
15388da1743SJi-Ze Hong  *	Byte 1: Interrupt register.
15488da1743SJi-Ze Hong  *	Byte 2: Interrupt enable register.
15588da1743SJi-Ze Hong  *	Byte 3: Arbitration lost capture(ALC) register.
15688da1743SJi-Ze Hong  *	Byte 4: Error code capture(ECC) register.
15788da1743SJi-Ze Hong  *	Byte 5: Error warning limit register.
15888da1743SJi-Ze Hong  *	Byte 6: RX error counter register.
15988da1743SJi-Ze Hong  *	Byte 7: TX error counter register.
16088da1743SJi-Ze Hong  *	Byte 8: Reserved.
16188da1743SJi-Ze Hong  */
16288da1743SJi-Ze Hong struct f81604_int_data {
16388da1743SJi-Ze Hong 	u8 sr;
16488da1743SJi-Ze Hong 	u8 isrc;
16588da1743SJi-Ze Hong 	u8 ier;
16688da1743SJi-Ze Hong 	u8 alc;
16788da1743SJi-Ze Hong 	u8 ecc;
16888da1743SJi-Ze Hong 	u8 ewlr;
16988da1743SJi-Ze Hong 	u8 rxerr;
17088da1743SJi-Ze Hong 	u8 txerr;
17188da1743SJi-Ze Hong 	u8 val;
17288da1743SJi-Ze Hong } __packed __aligned(4);
17388da1743SJi-Ze Hong 
17488da1743SJi-Ze Hong struct f81604_sff {
17588da1743SJi-Ze Hong 	__be16 id;
17688da1743SJi-Ze Hong 	u8 data[CAN_MAX_DLEN];
17788da1743SJi-Ze Hong } __packed __aligned(2);
17888da1743SJi-Ze Hong 
17988da1743SJi-Ze Hong struct f81604_eff {
18088da1743SJi-Ze Hong 	__be32 id;
18188da1743SJi-Ze Hong 	u8 data[CAN_MAX_DLEN];
18288da1743SJi-Ze Hong } __packed __aligned(2);
18388da1743SJi-Ze Hong 
18488da1743SJi-Ze Hong struct f81604_can_frame {
18588da1743SJi-Ze Hong 	u8 cmd;
18688da1743SJi-Ze Hong 
18788da1743SJi-Ze Hong 	/* According for F81604 DLC define:
18888da1743SJi-Ze Hong 	 *	bit 3~0: data length (0~8)
18988da1743SJi-Ze Hong 	 *	bit6: is RTR flag.
19088da1743SJi-Ze Hong 	 *	bit7: is EFF frame.
19188da1743SJi-Ze Hong 	 */
19288da1743SJi-Ze Hong 	u8 dlc;
19388da1743SJi-Ze Hong 
19488da1743SJi-Ze Hong 	union {
19588da1743SJi-Ze Hong 		struct f81604_sff sff;
19688da1743SJi-Ze Hong 		struct f81604_eff eff;
19788da1743SJi-Ze Hong 	};
19888da1743SJi-Ze Hong } __packed __aligned(2);
19988da1743SJi-Ze Hong 
20088da1743SJi-Ze Hong static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 };
20188da1743SJi-Ze Hong static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 };
20288da1743SJi-Ze Hong static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 };
20388da1743SJi-Ze Hong 
f81604_write(struct usb_device * dev,u16 reg,u8 data)20488da1743SJi-Ze Hong static int f81604_write(struct usb_device *dev, u16 reg, u8 data)
20588da1743SJi-Ze Hong {
20688da1743SJi-Ze Hong 	int ret;
20788da1743SJi-Ze Hong 
20888da1743SJi-Ze Hong 	ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER,
20988da1743SJi-Ze Hong 				   USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg,
21088da1743SJi-Ze Hong 				   &data, sizeof(data), F81604_USB_TIMEOUT,
21188da1743SJi-Ze Hong 				   GFP_KERNEL);
21288da1743SJi-Ze Hong 	if (ret)
21388da1743SJi-Ze Hong 		dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n",
21488da1743SJi-Ze Hong 			__func__, reg, data, ERR_PTR(ret));
21588da1743SJi-Ze Hong 
21688da1743SJi-Ze Hong 	return ret;
21788da1743SJi-Ze Hong }
21888da1743SJi-Ze Hong 
f81604_read(struct usb_device * dev,u16 reg,u8 * data)21988da1743SJi-Ze Hong static int f81604_read(struct usb_device *dev, u16 reg, u8 *data)
22088da1743SJi-Ze Hong {
22188da1743SJi-Ze Hong 	int ret;
22288da1743SJi-Ze Hong 
22388da1743SJi-Ze Hong 	ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER,
22488da1743SJi-Ze Hong 				   USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data,
22588da1743SJi-Ze Hong 				   sizeof(*data), F81604_USB_TIMEOUT,
22688da1743SJi-Ze Hong 				   GFP_KERNEL);
22788da1743SJi-Ze Hong 
22888da1743SJi-Ze Hong 	if (ret < 0)
22988da1743SJi-Ze Hong 		dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg,
23088da1743SJi-Ze Hong 			ERR_PTR(ret));
23188da1743SJi-Ze Hong 
23288da1743SJi-Ze Hong 	return ret;
23388da1743SJi-Ze Hong }
23488da1743SJi-Ze Hong 
f81604_update_bits(struct usb_device * dev,u16 reg,u8 mask,u8 data)23588da1743SJi-Ze Hong static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask,
23688da1743SJi-Ze Hong 			      u8 data)
23788da1743SJi-Ze Hong {
23888da1743SJi-Ze Hong 	int ret;
23988da1743SJi-Ze Hong 	u8 tmp;
24088da1743SJi-Ze Hong 
24188da1743SJi-Ze Hong 	ret = f81604_read(dev, reg, &tmp);
24288da1743SJi-Ze Hong 	if (ret)
24388da1743SJi-Ze Hong 		return ret;
24488da1743SJi-Ze Hong 
24588da1743SJi-Ze Hong 	tmp &= ~mask;
24688da1743SJi-Ze Hong 	tmp |= (mask & data);
24788da1743SJi-Ze Hong 
24888da1743SJi-Ze Hong 	return f81604_write(dev, reg, tmp);
24988da1743SJi-Ze Hong }
25088da1743SJi-Ze Hong 
f81604_sja1000_write(struct f81604_port_priv * priv,u16 reg,u8 data)25188da1743SJi-Ze Hong static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg,
25288da1743SJi-Ze Hong 				u8 data)
25388da1743SJi-Ze Hong {
25488da1743SJi-Ze Hong 	int port = priv->netdev->dev_port;
25588da1743SJi-Ze Hong 	int real_reg;
25688da1743SJi-Ze Hong 
25788da1743SJi-Ze Hong 	real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
25888da1743SJi-Ze Hong 	return f81604_write(priv->dev, real_reg, data);
25988da1743SJi-Ze Hong }
26088da1743SJi-Ze Hong 
f81604_sja1000_read(struct f81604_port_priv * priv,u16 reg,u8 * data)26188da1743SJi-Ze Hong static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg,
26288da1743SJi-Ze Hong 			       u8 *data)
26388da1743SJi-Ze Hong {
26488da1743SJi-Ze Hong 	int port = priv->netdev->dev_port;
26588da1743SJi-Ze Hong 	int real_reg;
26688da1743SJi-Ze Hong 
26788da1743SJi-Ze Hong 	real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
26888da1743SJi-Ze Hong 	return f81604_read(priv->dev, real_reg, data);
26988da1743SJi-Ze Hong }
27088da1743SJi-Ze Hong 
f81604_set_reset_mode(struct f81604_port_priv * priv)27188da1743SJi-Ze Hong static int f81604_set_reset_mode(struct f81604_port_priv *priv)
27288da1743SJi-Ze Hong {
27388da1743SJi-Ze Hong 	int ret, i;
27488da1743SJi-Ze Hong 	u8 tmp;
27588da1743SJi-Ze Hong 
27688da1743SJi-Ze Hong 	/* disable interrupts */
27788da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_IER,
27888da1743SJi-Ze Hong 				   F81604_SJA1000_IRQ_OFF);
27988da1743SJi-Ze Hong 	if (ret)
28088da1743SJi-Ze Hong 		return ret;
28188da1743SJi-Ze Hong 
28288da1743SJi-Ze Hong 	for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
28388da1743SJi-Ze Hong 		ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
28488da1743SJi-Ze Hong 		if (ret)
28588da1743SJi-Ze Hong 			return ret;
28688da1743SJi-Ze Hong 
28788da1743SJi-Ze Hong 		/* check reset bit */
28888da1743SJi-Ze Hong 		if (tmp & F81604_SJA1000_MOD_RM) {
28988da1743SJi-Ze Hong 			priv->can.state = CAN_STATE_STOPPED;
29088da1743SJi-Ze Hong 			return 0;
29188da1743SJi-Ze Hong 		}
29288da1743SJi-Ze Hong 
29388da1743SJi-Ze Hong 		/* reset chip */
29488da1743SJi-Ze Hong 		ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD,
29588da1743SJi-Ze Hong 					   F81604_SJA1000_MOD_RM);
29688da1743SJi-Ze Hong 		if (ret)
29788da1743SJi-Ze Hong 			return ret;
29888da1743SJi-Ze Hong 	}
29988da1743SJi-Ze Hong 
30088da1743SJi-Ze Hong 	return -EPERM;
30188da1743SJi-Ze Hong }
30288da1743SJi-Ze Hong 
f81604_set_normal_mode(struct f81604_port_priv * priv)30388da1743SJi-Ze Hong static int f81604_set_normal_mode(struct f81604_port_priv *priv)
30488da1743SJi-Ze Hong {
30588da1743SJi-Ze Hong 	u8 tmp, ier = 0;
30688da1743SJi-Ze Hong 	u8 mod_reg = 0;
30788da1743SJi-Ze Hong 	int ret, i;
30888da1743SJi-Ze Hong 
30988da1743SJi-Ze Hong 	for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
31088da1743SJi-Ze Hong 		ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
31188da1743SJi-Ze Hong 		if (ret)
31288da1743SJi-Ze Hong 			return ret;
31388da1743SJi-Ze Hong 
31488da1743SJi-Ze Hong 		/* check reset bit */
31588da1743SJi-Ze Hong 		if ((tmp & F81604_SJA1000_MOD_RM) == 0) {
31688da1743SJi-Ze Hong 			priv->can.state = CAN_STATE_ERROR_ACTIVE;
31788da1743SJi-Ze Hong 			/* enable interrupts, RI handled by bulk-in */
31888da1743SJi-Ze Hong 			ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI;
31988da1743SJi-Ze Hong 			if (!(priv->can.ctrlmode &
32088da1743SJi-Ze Hong 			      CAN_CTRLMODE_BERR_REPORTING))
32188da1743SJi-Ze Hong 				ier &= ~F81604_SJA1000_IRQ_BEI;
32288da1743SJi-Ze Hong 
32388da1743SJi-Ze Hong 			return f81604_sja1000_write(priv, F81604_SJA1000_IER,
32488da1743SJi-Ze Hong 						    ier);
32588da1743SJi-Ze Hong 		}
32688da1743SJi-Ze Hong 
32788da1743SJi-Ze Hong 		/* set chip to normal mode */
32888da1743SJi-Ze Hong 		if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
32988da1743SJi-Ze Hong 			mod_reg |= F81604_SJA1000_MOD_LOM;
33088da1743SJi-Ze Hong 		if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
33188da1743SJi-Ze Hong 			mod_reg |= F81604_SJA1000_MOD_STM;
33288da1743SJi-Ze Hong 
33388da1743SJi-Ze Hong 		ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg);
33488da1743SJi-Ze Hong 		if (ret)
33588da1743SJi-Ze Hong 			return ret;
33688da1743SJi-Ze Hong 	}
33788da1743SJi-Ze Hong 
33888da1743SJi-Ze Hong 	return -EPERM;
33988da1743SJi-Ze Hong }
34088da1743SJi-Ze Hong 
f81604_chipset_init(struct f81604_port_priv * priv)34188da1743SJi-Ze Hong static int f81604_chipset_init(struct f81604_port_priv *priv)
34288da1743SJi-Ze Hong {
34388da1743SJi-Ze Hong 	int i, ret;
34488da1743SJi-Ze Hong 
34588da1743SJi-Ze Hong 	/* set clock divider and output control register */
34688da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR,
34788da1743SJi-Ze Hong 				   CDR_CBP | CDR_PELICAN);
34888da1743SJi-Ze Hong 	if (ret)
34988da1743SJi-Ze Hong 		return ret;
35088da1743SJi-Ze Hong 
35188da1743SJi-Ze Hong 	/* set acceptance filter (accept all) */
35288da1743SJi-Ze Hong 	for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
35388da1743SJi-Ze Hong 		ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0);
35488da1743SJi-Ze Hong 		if (ret)
35588da1743SJi-Ze Hong 			return ret;
35688da1743SJi-Ze Hong 	}
35788da1743SJi-Ze Hong 
35888da1743SJi-Ze Hong 	for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
35988da1743SJi-Ze Hong 		ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i,
36088da1743SJi-Ze Hong 					   0xFF);
36188da1743SJi-Ze Hong 		if (ret)
36288da1743SJi-Ze Hong 			return ret;
36388da1743SJi-Ze Hong 	}
36488da1743SJi-Ze Hong 
36588da1743SJi-Ze Hong 	return f81604_sja1000_write(priv, F81604_SJA1000_OCR,
36688da1743SJi-Ze Hong 				    OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL |
36788da1743SJi-Ze Hong 					    OCR_MODE_NORMAL);
36888da1743SJi-Ze Hong }
36988da1743SJi-Ze Hong 
f81604_process_rx_packet(struct net_device * netdev,struct f81604_can_frame * frame)37088da1743SJi-Ze Hong static void f81604_process_rx_packet(struct net_device *netdev,
37188da1743SJi-Ze Hong 				     struct f81604_can_frame *frame)
37288da1743SJi-Ze Hong {
37388da1743SJi-Ze Hong 	struct net_device_stats *stats = &netdev->stats;
37488da1743SJi-Ze Hong 	struct can_frame *cf;
37588da1743SJi-Ze Hong 	struct sk_buff *skb;
37688da1743SJi-Ze Hong 
37788da1743SJi-Ze Hong 	if (frame->cmd != F81604_CMD_DATA)
37888da1743SJi-Ze Hong 		return;
37988da1743SJi-Ze Hong 
38088da1743SJi-Ze Hong 	skb = alloc_can_skb(netdev, &cf);
38188da1743SJi-Ze Hong 	if (!skb) {
38288da1743SJi-Ze Hong 		stats->rx_dropped++;
38388da1743SJi-Ze Hong 		return;
38488da1743SJi-Ze Hong 	}
38588da1743SJi-Ze Hong 
38688da1743SJi-Ze Hong 	cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK);
38788da1743SJi-Ze Hong 
38888da1743SJi-Ze Hong 	if (frame->dlc & F81604_DLC_EFF_BIT) {
38988da1743SJi-Ze Hong 		cf->can_id = get_unaligned_be32(&frame->eff.id) >>
39088da1743SJi-Ze Hong 			     F81604_EFF_SHIFT;
39188da1743SJi-Ze Hong 		cf->can_id |= CAN_EFF_FLAG;
39288da1743SJi-Ze Hong 
39388da1743SJi-Ze Hong 		if (!(frame->dlc & F81604_DLC_RTR_BIT))
39488da1743SJi-Ze Hong 			memcpy(cf->data, frame->eff.data, cf->len);
39588da1743SJi-Ze Hong 	} else {
39688da1743SJi-Ze Hong 		cf->can_id = get_unaligned_be16(&frame->sff.id) >>
39788da1743SJi-Ze Hong 			     F81604_SFF_SHIFT;
39888da1743SJi-Ze Hong 
39988da1743SJi-Ze Hong 		if (!(frame->dlc & F81604_DLC_RTR_BIT))
40088da1743SJi-Ze Hong 			memcpy(cf->data, frame->sff.data, cf->len);
40188da1743SJi-Ze Hong 	}
40288da1743SJi-Ze Hong 
40388da1743SJi-Ze Hong 	if (frame->dlc & F81604_DLC_RTR_BIT)
40488da1743SJi-Ze Hong 		cf->can_id |= CAN_RTR_FLAG;
40588da1743SJi-Ze Hong 	else
40688da1743SJi-Ze Hong 		stats->rx_bytes += cf->len;
40788da1743SJi-Ze Hong 
40888da1743SJi-Ze Hong 	stats->rx_packets++;
40988da1743SJi-Ze Hong 	netif_rx(skb);
41088da1743SJi-Ze Hong }
41188da1743SJi-Ze Hong 
f81604_read_bulk_callback(struct urb * urb)41288da1743SJi-Ze Hong static void f81604_read_bulk_callback(struct urb *urb)
41388da1743SJi-Ze Hong {
41488da1743SJi-Ze Hong 	struct f81604_can_frame *frame = urb->transfer_buffer;
41588da1743SJi-Ze Hong 	struct net_device *netdev = urb->context;
41688da1743SJi-Ze Hong 	int ret;
41788da1743SJi-Ze Hong 
41888da1743SJi-Ze Hong 	if (!netif_device_present(netdev))
41988da1743SJi-Ze Hong 		return;
42088da1743SJi-Ze Hong 
42188da1743SJi-Ze Hong 	if (urb->status)
42288da1743SJi-Ze Hong 		netdev_info(netdev, "%s: URB aborted %pe\n", __func__,
42388da1743SJi-Ze Hong 			    ERR_PTR(urb->status));
42488da1743SJi-Ze Hong 
42588da1743SJi-Ze Hong 	switch (urb->status) {
42688da1743SJi-Ze Hong 	case 0: /* success */
42788da1743SJi-Ze Hong 		break;
42888da1743SJi-Ze Hong 
42988da1743SJi-Ze Hong 	case -ENOENT:
43088da1743SJi-Ze Hong 	case -EPIPE:
43188da1743SJi-Ze Hong 	case -EPROTO:
43288da1743SJi-Ze Hong 	case -ESHUTDOWN:
43388da1743SJi-Ze Hong 		return;
43488da1743SJi-Ze Hong 
43588da1743SJi-Ze Hong 	default:
43688da1743SJi-Ze Hong 		goto resubmit_urb;
43788da1743SJi-Ze Hong 	}
43888da1743SJi-Ze Hong 
43988da1743SJi-Ze Hong 	if (urb->actual_length != sizeof(*frame)) {
44088da1743SJi-Ze Hong 		netdev_warn(netdev, "URB length %u not equal to %zu\n",
44188da1743SJi-Ze Hong 			    urb->actual_length, sizeof(*frame));
44288da1743SJi-Ze Hong 		goto resubmit_urb;
44388da1743SJi-Ze Hong 	}
44488da1743SJi-Ze Hong 
44588da1743SJi-Ze Hong 	f81604_process_rx_packet(netdev, frame);
44688da1743SJi-Ze Hong 
44788da1743SJi-Ze Hong resubmit_urb:
44888da1743SJi-Ze Hong 	ret = usb_submit_urb(urb, GFP_ATOMIC);
44988da1743SJi-Ze Hong 	if (ret == -ENODEV)
45088da1743SJi-Ze Hong 		netif_device_detach(netdev);
45188da1743SJi-Ze Hong 	else if (ret)
45288da1743SJi-Ze Hong 		netdev_err(netdev,
45388da1743SJi-Ze Hong 			   "%s: failed to resubmit read bulk urb: %pe\n",
45488da1743SJi-Ze Hong 			   __func__, ERR_PTR(ret));
45588da1743SJi-Ze Hong }
45688da1743SJi-Ze Hong 
f81604_handle_tx(struct f81604_port_priv * priv,struct f81604_int_data * data)45788da1743SJi-Ze Hong static void f81604_handle_tx(struct f81604_port_priv *priv,
45888da1743SJi-Ze Hong 			     struct f81604_int_data *data)
45988da1743SJi-Ze Hong {
46088da1743SJi-Ze Hong 	struct net_device *netdev = priv->netdev;
46188da1743SJi-Ze Hong 	struct net_device_stats *stats = &netdev->stats;
46288da1743SJi-Ze Hong 
46388da1743SJi-Ze Hong 	/* transmission buffer released */
46488da1743SJi-Ze Hong 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT &&
46588da1743SJi-Ze Hong 	    !(data->sr & F81604_SJA1000_SR_TCS)) {
46688da1743SJi-Ze Hong 		stats->tx_errors++;
46788da1743SJi-Ze Hong 		can_free_echo_skb(netdev, 0, NULL);
46888da1743SJi-Ze Hong 	} else {
46988da1743SJi-Ze Hong 		/* transmission complete */
47088da1743SJi-Ze Hong 		stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL);
47188da1743SJi-Ze Hong 		stats->tx_packets++;
47288da1743SJi-Ze Hong 	}
47388da1743SJi-Ze Hong 
47488da1743SJi-Ze Hong 	netif_wake_queue(netdev);
47588da1743SJi-Ze Hong }
47688da1743SJi-Ze Hong 
f81604_handle_can_bus_errors(struct f81604_port_priv * priv,struct f81604_int_data * data)47788da1743SJi-Ze Hong static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
47888da1743SJi-Ze Hong 					 struct f81604_int_data *data)
47988da1743SJi-Ze Hong {
48088da1743SJi-Ze Hong 	enum can_state can_state = priv->can.state;
48188da1743SJi-Ze Hong 	struct net_device *netdev = priv->netdev;
48288da1743SJi-Ze Hong 	struct net_device_stats *stats = &netdev->stats;
48388da1743SJi-Ze Hong 	struct can_frame *cf;
48488da1743SJi-Ze Hong 	struct sk_buff *skb;
48588da1743SJi-Ze Hong 
48688da1743SJi-Ze Hong 	/* Note: ALC/ECC will not auto clear by read here, must be cleared by
48788da1743SJi-Ze Hong 	 * read register (via clear_reg_work).
48888da1743SJi-Ze Hong 	 */
48988da1743SJi-Ze Hong 
49088da1743SJi-Ze Hong 	skb = alloc_can_err_skb(netdev, &cf);
49188da1743SJi-Ze Hong 	if (skb) {
49288da1743SJi-Ze Hong 		cf->can_id |= CAN_ERR_CNT;
49388da1743SJi-Ze Hong 		cf->data[6] = data->txerr;
49488da1743SJi-Ze Hong 		cf->data[7] = data->rxerr;
49588da1743SJi-Ze Hong 	}
49688da1743SJi-Ze Hong 
49788da1743SJi-Ze Hong 	if (data->isrc & F81604_SJA1000_IRQ_DOI) {
49888da1743SJi-Ze Hong 		/* data overrun interrupt */
49988da1743SJi-Ze Hong 		netdev_dbg(netdev, "data overrun interrupt\n");
50088da1743SJi-Ze Hong 
50188da1743SJi-Ze Hong 		if (skb) {
50288da1743SJi-Ze Hong 			cf->can_id |= CAN_ERR_CRTL;
50388da1743SJi-Ze Hong 			cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
50488da1743SJi-Ze Hong 		}
50588da1743SJi-Ze Hong 
50688da1743SJi-Ze Hong 		stats->rx_over_errors++;
50788da1743SJi-Ze Hong 		stats->rx_errors++;
50888da1743SJi-Ze Hong 
50988da1743SJi-Ze Hong 		set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags);
51088da1743SJi-Ze Hong 	}
51188da1743SJi-Ze Hong 
51288da1743SJi-Ze Hong 	if (data->isrc & F81604_SJA1000_IRQ_EI) {
51388da1743SJi-Ze Hong 		/* error warning interrupt */
51488da1743SJi-Ze Hong 		netdev_dbg(netdev, "error warning interrupt\n");
51588da1743SJi-Ze Hong 
51688da1743SJi-Ze Hong 		if (data->sr & F81604_SJA1000_SR_BS)
51788da1743SJi-Ze Hong 			can_state = CAN_STATE_BUS_OFF;
51888da1743SJi-Ze Hong 		else if (data->sr & F81604_SJA1000_SR_ES)
51988da1743SJi-Ze Hong 			can_state = CAN_STATE_ERROR_WARNING;
52088da1743SJi-Ze Hong 		else
52188da1743SJi-Ze Hong 			can_state = CAN_STATE_ERROR_ACTIVE;
52288da1743SJi-Ze Hong 	}
52388da1743SJi-Ze Hong 
52488da1743SJi-Ze Hong 	if (data->isrc & F81604_SJA1000_IRQ_BEI) {
52588da1743SJi-Ze Hong 		/* bus error interrupt */
52688da1743SJi-Ze Hong 		netdev_dbg(netdev, "bus error interrupt\n");
52788da1743SJi-Ze Hong 
52888da1743SJi-Ze Hong 		priv->can.can_stats.bus_error++;
52988da1743SJi-Ze Hong 
53088da1743SJi-Ze Hong 		if (skb) {
53188da1743SJi-Ze Hong 			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
53288da1743SJi-Ze Hong 
53388da1743SJi-Ze Hong 			/* set error type */
53488da1743SJi-Ze Hong 			switch (data->ecc & F81604_SJA1000_ECC_MASK) {
53588da1743SJi-Ze Hong 			case F81604_SJA1000_ECC_BIT:
53688da1743SJi-Ze Hong 				cf->data[2] |= CAN_ERR_PROT_BIT;
53788da1743SJi-Ze Hong 				break;
53888da1743SJi-Ze Hong 			case F81604_SJA1000_ECC_FORM:
53988da1743SJi-Ze Hong 				cf->data[2] |= CAN_ERR_PROT_FORM;
54088da1743SJi-Ze Hong 				break;
54188da1743SJi-Ze Hong 			case F81604_SJA1000_ECC_STUFF:
54288da1743SJi-Ze Hong 				cf->data[2] |= CAN_ERR_PROT_STUFF;
54388da1743SJi-Ze Hong 				break;
54488da1743SJi-Ze Hong 			default:
54588da1743SJi-Ze Hong 				break;
54688da1743SJi-Ze Hong 			}
54788da1743SJi-Ze Hong 
54888da1743SJi-Ze Hong 			/* set error location */
54988da1743SJi-Ze Hong 			cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
550*39df17a1SDario Binacchi 		}
55188da1743SJi-Ze Hong 
55288da1743SJi-Ze Hong 		/* Error occurred during transmission? */
553*39df17a1SDario Binacchi 		if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
554*39df17a1SDario Binacchi 			stats->tx_errors++;
555*39df17a1SDario Binacchi 			if (skb)
55688da1743SJi-Ze Hong 				cf->data[2] |= CAN_ERR_PROT_TX;
557*39df17a1SDario Binacchi 		} else {
558*39df17a1SDario Binacchi 			stats->rx_errors++;
55988da1743SJi-Ze Hong 		}
56088da1743SJi-Ze Hong 
56188da1743SJi-Ze Hong 		set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
56288da1743SJi-Ze Hong 	}
56388da1743SJi-Ze Hong 
56488da1743SJi-Ze Hong 	if (data->isrc & F81604_SJA1000_IRQ_EPI) {
56588da1743SJi-Ze Hong 		if (can_state == CAN_STATE_ERROR_PASSIVE)
56688da1743SJi-Ze Hong 			can_state = CAN_STATE_ERROR_WARNING;
56788da1743SJi-Ze Hong 		else
56888da1743SJi-Ze Hong 			can_state = CAN_STATE_ERROR_PASSIVE;
56988da1743SJi-Ze Hong 
57088da1743SJi-Ze Hong 		/* error passive interrupt */
57188da1743SJi-Ze Hong 		netdev_dbg(netdev, "error passive interrupt: %d\n", can_state);
57288da1743SJi-Ze Hong 	}
57388da1743SJi-Ze Hong 
57488da1743SJi-Ze Hong 	if (data->isrc & F81604_SJA1000_IRQ_ALI) {
57588da1743SJi-Ze Hong 		/* arbitration lost interrupt */
57688da1743SJi-Ze Hong 		netdev_dbg(netdev, "arbitration lost interrupt\n");
57788da1743SJi-Ze Hong 
57888da1743SJi-Ze Hong 		priv->can.can_stats.arbitration_lost++;
57988da1743SJi-Ze Hong 
58088da1743SJi-Ze Hong 		if (skb) {
58188da1743SJi-Ze Hong 			cf->can_id |= CAN_ERR_LOSTARB;
58288da1743SJi-Ze Hong 			cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK;
58388da1743SJi-Ze Hong 		}
58488da1743SJi-Ze Hong 
58588da1743SJi-Ze Hong 		set_bit(F81604_CLEAR_ALC, &priv->clear_flags);
58688da1743SJi-Ze Hong 	}
58788da1743SJi-Ze Hong 
58888da1743SJi-Ze Hong 	if (can_state != priv->can.state) {
58988da1743SJi-Ze Hong 		enum can_state tx_state, rx_state;
59088da1743SJi-Ze Hong 
59188da1743SJi-Ze Hong 		tx_state = data->txerr >= data->rxerr ? can_state : 0;
59288da1743SJi-Ze Hong 		rx_state = data->txerr <= data->rxerr ? can_state : 0;
59388da1743SJi-Ze Hong 
59488da1743SJi-Ze Hong 		can_change_state(netdev, cf, tx_state, rx_state);
59588da1743SJi-Ze Hong 
59688da1743SJi-Ze Hong 		if (can_state == CAN_STATE_BUS_OFF)
59788da1743SJi-Ze Hong 			can_bus_off(netdev);
59888da1743SJi-Ze Hong 	}
59988da1743SJi-Ze Hong 
60088da1743SJi-Ze Hong 	if (priv->clear_flags)
60188da1743SJi-Ze Hong 		schedule_work(&priv->clear_reg_work);
60288da1743SJi-Ze Hong 
60388da1743SJi-Ze Hong 	if (skb)
60488da1743SJi-Ze Hong 		netif_rx(skb);
60588da1743SJi-Ze Hong }
60688da1743SJi-Ze Hong 
f81604_read_int_callback(struct urb * urb)60788da1743SJi-Ze Hong static void f81604_read_int_callback(struct urb *urb)
60888da1743SJi-Ze Hong {
60988da1743SJi-Ze Hong 	struct f81604_int_data *data = urb->transfer_buffer;
61088da1743SJi-Ze Hong 	struct net_device *netdev = urb->context;
61188da1743SJi-Ze Hong 	struct f81604_port_priv *priv;
61288da1743SJi-Ze Hong 	int ret;
61388da1743SJi-Ze Hong 
61488da1743SJi-Ze Hong 	priv = netdev_priv(netdev);
61588da1743SJi-Ze Hong 
61688da1743SJi-Ze Hong 	if (!netif_device_present(netdev))
61788da1743SJi-Ze Hong 		return;
61888da1743SJi-Ze Hong 
61988da1743SJi-Ze Hong 	if (urb->status)
62088da1743SJi-Ze Hong 		netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
62188da1743SJi-Ze Hong 			    ERR_PTR(urb->status));
62288da1743SJi-Ze Hong 
62388da1743SJi-Ze Hong 	switch (urb->status) {
62488da1743SJi-Ze Hong 	case 0: /* success */
62588da1743SJi-Ze Hong 		break;
62688da1743SJi-Ze Hong 
62788da1743SJi-Ze Hong 	case -ENOENT:
62888da1743SJi-Ze Hong 	case -EPIPE:
62988da1743SJi-Ze Hong 	case -EPROTO:
63088da1743SJi-Ze Hong 	case -ESHUTDOWN:
63188da1743SJi-Ze Hong 		return;
63288da1743SJi-Ze Hong 
63388da1743SJi-Ze Hong 	default:
63488da1743SJi-Ze Hong 		goto resubmit_urb;
63588da1743SJi-Ze Hong 	}
63688da1743SJi-Ze Hong 
63788da1743SJi-Ze Hong 	/* handle Errors */
63888da1743SJi-Ze Hong 	if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI |
63988da1743SJi-Ze Hong 			  F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI |
64088da1743SJi-Ze Hong 			  F81604_SJA1000_IRQ_ALI))
64188da1743SJi-Ze Hong 		f81604_handle_can_bus_errors(priv, data);
64288da1743SJi-Ze Hong 
64388da1743SJi-Ze Hong 	/* handle TX */
64488da1743SJi-Ze Hong 	if (priv->can.state != CAN_STATE_BUS_OFF &&
64588da1743SJi-Ze Hong 	    (data->isrc & F81604_SJA1000_IRQ_TI))
64688da1743SJi-Ze Hong 		f81604_handle_tx(priv, data);
64788da1743SJi-Ze Hong 
64888da1743SJi-Ze Hong resubmit_urb:
64988da1743SJi-Ze Hong 	ret = usb_submit_urb(urb, GFP_ATOMIC);
65088da1743SJi-Ze Hong 	if (ret == -ENODEV)
65188da1743SJi-Ze Hong 		netif_device_detach(netdev);
65288da1743SJi-Ze Hong 	else if (ret)
65388da1743SJi-Ze Hong 		netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
65488da1743SJi-Ze Hong 			   __func__, ERR_PTR(ret));
65588da1743SJi-Ze Hong }
65688da1743SJi-Ze Hong 
f81604_unregister_urbs(struct f81604_port_priv * priv)65788da1743SJi-Ze Hong static void f81604_unregister_urbs(struct f81604_port_priv *priv)
65888da1743SJi-Ze Hong {
65988da1743SJi-Ze Hong 	usb_kill_anchored_urbs(&priv->urbs_anchor);
66088da1743SJi-Ze Hong }
66188da1743SJi-Ze Hong 
f81604_register_urbs(struct f81604_port_priv * priv)66288da1743SJi-Ze Hong static int f81604_register_urbs(struct f81604_port_priv *priv)
66388da1743SJi-Ze Hong {
66488da1743SJi-Ze Hong 	struct net_device *netdev = priv->netdev;
66588da1743SJi-Ze Hong 	struct f81604_int_data *int_data;
66688da1743SJi-Ze Hong 	int id = netdev->dev_port;
66788da1743SJi-Ze Hong 	struct urb *int_urb;
66888da1743SJi-Ze Hong 	int rx_urb_cnt;
66988da1743SJi-Ze Hong 	int ret;
67088da1743SJi-Ze Hong 
67188da1743SJi-Ze Hong 	for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) {
67288da1743SJi-Ze Hong 		struct f81604_can_frame *frame;
67388da1743SJi-Ze Hong 		struct urb *rx_urb;
67488da1743SJi-Ze Hong 
67588da1743SJi-Ze Hong 		rx_urb = usb_alloc_urb(0, GFP_KERNEL);
67688da1743SJi-Ze Hong 		if (!rx_urb) {
67788da1743SJi-Ze Hong 			ret = -ENOMEM;
67888da1743SJi-Ze Hong 			break;
67988da1743SJi-Ze Hong 		}
68088da1743SJi-Ze Hong 
68188da1743SJi-Ze Hong 		frame = kmalloc(sizeof(*frame), GFP_KERNEL);
68288da1743SJi-Ze Hong 		if (!frame) {
68388da1743SJi-Ze Hong 			usb_free_urb(rx_urb);
68488da1743SJi-Ze Hong 			ret = -ENOMEM;
68588da1743SJi-Ze Hong 			break;
68688da1743SJi-Ze Hong 		}
68788da1743SJi-Ze Hong 
68888da1743SJi-Ze Hong 		usb_fill_bulk_urb(rx_urb, priv->dev,
68988da1743SJi-Ze Hong 				  usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]),
69088da1743SJi-Ze Hong 				  frame, sizeof(*frame),
69188da1743SJi-Ze Hong 				  f81604_read_bulk_callback, netdev);
69288da1743SJi-Ze Hong 
69388da1743SJi-Ze Hong 		rx_urb->transfer_flags |= URB_FREE_BUFFER;
69488da1743SJi-Ze Hong 		usb_anchor_urb(rx_urb, &priv->urbs_anchor);
69588da1743SJi-Ze Hong 
69688da1743SJi-Ze Hong 		ret = usb_submit_urb(rx_urb, GFP_KERNEL);
69788da1743SJi-Ze Hong 		if (ret) {
69888da1743SJi-Ze Hong 			usb_unanchor_urb(rx_urb);
69988da1743SJi-Ze Hong 			usb_free_urb(rx_urb);
70088da1743SJi-Ze Hong 			break;
70188da1743SJi-Ze Hong 		}
70288da1743SJi-Ze Hong 
70388da1743SJi-Ze Hong 		/* Drop reference, USB core will take care of freeing it */
70488da1743SJi-Ze Hong 		usb_free_urb(rx_urb);
70588da1743SJi-Ze Hong 	}
70688da1743SJi-Ze Hong 
70788da1743SJi-Ze Hong 	if (rx_urb_cnt == 0) {
70888da1743SJi-Ze Hong 		netdev_warn(netdev, "%s: submit rx urb failed: %pe\n",
70988da1743SJi-Ze Hong 			    __func__, ERR_PTR(ret));
71088da1743SJi-Ze Hong 
71188da1743SJi-Ze Hong 		goto error;
71288da1743SJi-Ze Hong 	}
71388da1743SJi-Ze Hong 
71488da1743SJi-Ze Hong 	int_urb = usb_alloc_urb(0, GFP_KERNEL);
71588da1743SJi-Ze Hong 	if (!int_urb) {
71688da1743SJi-Ze Hong 		ret = -ENOMEM;
71788da1743SJi-Ze Hong 		goto error;
71888da1743SJi-Ze Hong 	}
71988da1743SJi-Ze Hong 
72088da1743SJi-Ze Hong 	int_data = kmalloc(sizeof(*int_data), GFP_KERNEL);
72188da1743SJi-Ze Hong 	if (!int_data) {
72288da1743SJi-Ze Hong 		usb_free_urb(int_urb);
72388da1743SJi-Ze Hong 		ret = -ENOMEM;
72488da1743SJi-Ze Hong 		goto error;
72588da1743SJi-Ze Hong 	}
72688da1743SJi-Ze Hong 
72788da1743SJi-Ze Hong 	usb_fill_int_urb(int_urb, priv->dev,
72888da1743SJi-Ze Hong 			 usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data,
72988da1743SJi-Ze Hong 			 sizeof(*int_data), f81604_read_int_callback, netdev,
73088da1743SJi-Ze Hong 			 1);
73188da1743SJi-Ze Hong 
73288da1743SJi-Ze Hong 	int_urb->transfer_flags |= URB_FREE_BUFFER;
73388da1743SJi-Ze Hong 	usb_anchor_urb(int_urb, &priv->urbs_anchor);
73488da1743SJi-Ze Hong 
73588da1743SJi-Ze Hong 	ret = usb_submit_urb(int_urb, GFP_KERNEL);
73688da1743SJi-Ze Hong 	if (ret) {
73788da1743SJi-Ze Hong 		usb_unanchor_urb(int_urb);
73888da1743SJi-Ze Hong 		usb_free_urb(int_urb);
73988da1743SJi-Ze Hong 
74088da1743SJi-Ze Hong 		netdev_warn(netdev, "%s: submit int urb failed: %pe\n",
74188da1743SJi-Ze Hong 			    __func__, ERR_PTR(ret));
74288da1743SJi-Ze Hong 		goto error;
74388da1743SJi-Ze Hong 	}
74488da1743SJi-Ze Hong 
74588da1743SJi-Ze Hong 	/* Drop reference, USB core will take care of freeing it */
74688da1743SJi-Ze Hong 	usb_free_urb(int_urb);
74788da1743SJi-Ze Hong 
74888da1743SJi-Ze Hong 	return 0;
74988da1743SJi-Ze Hong 
75088da1743SJi-Ze Hong error:
75188da1743SJi-Ze Hong 	f81604_unregister_urbs(priv);
75288da1743SJi-Ze Hong 	return ret;
75388da1743SJi-Ze Hong }
75488da1743SJi-Ze Hong 
f81604_start(struct net_device * netdev)75588da1743SJi-Ze Hong static int f81604_start(struct net_device *netdev)
75688da1743SJi-Ze Hong {
75788da1743SJi-Ze Hong 	struct f81604_port_priv *priv = netdev_priv(netdev);
75888da1743SJi-Ze Hong 	int ret;
75988da1743SJi-Ze Hong 	u8 mode;
76088da1743SJi-Ze Hong 	u8 tmp;
76188da1743SJi-Ze Hong 
76288da1743SJi-Ze Hong 	mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE;
76388da1743SJi-Ze Hong 
76488da1743SJi-Ze Hong 	/* Set TR/AT mode */
76588da1743SJi-Ze Hong 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
76688da1743SJi-Ze Hong 		mode |= F81604_TX_ONESHOT;
76788da1743SJi-Ze Hong 	else
76888da1743SJi-Ze Hong 		mode |= F81604_TX_NORMAL;
76988da1743SJi-Ze Hong 
77088da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode);
77188da1743SJi-Ze Hong 	if (ret)
77288da1743SJi-Ze Hong 		return ret;
77388da1743SJi-Ze Hong 
77488da1743SJi-Ze Hong 	/* set reset mode */
77588da1743SJi-Ze Hong 	ret = f81604_set_reset_mode(priv);
77688da1743SJi-Ze Hong 	if (ret)
77788da1743SJi-Ze Hong 		return ret;
77888da1743SJi-Ze Hong 
77988da1743SJi-Ze Hong 	ret = f81604_chipset_init(priv);
78088da1743SJi-Ze Hong 	if (ret)
78188da1743SJi-Ze Hong 		return ret;
78288da1743SJi-Ze Hong 
78388da1743SJi-Ze Hong 	/* Clear error counters and error code capture */
78488da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0);
78588da1743SJi-Ze Hong 	if (ret)
78688da1743SJi-Ze Hong 		return ret;
78788da1743SJi-Ze Hong 
78888da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0);
78988da1743SJi-Ze Hong 	if (ret)
79088da1743SJi-Ze Hong 		return ret;
79188da1743SJi-Ze Hong 
79288da1743SJi-Ze Hong 	/* Read clear for ECC/ALC/IR register */
79388da1743SJi-Ze Hong 	ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
79488da1743SJi-Ze Hong 	if (ret)
79588da1743SJi-Ze Hong 		return ret;
79688da1743SJi-Ze Hong 
79788da1743SJi-Ze Hong 	ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
79888da1743SJi-Ze Hong 	if (ret)
79988da1743SJi-Ze Hong 		return ret;
80088da1743SJi-Ze Hong 
80188da1743SJi-Ze Hong 	ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp);
80288da1743SJi-Ze Hong 	if (ret)
80388da1743SJi-Ze Hong 		return ret;
80488da1743SJi-Ze Hong 
80588da1743SJi-Ze Hong 	ret = f81604_register_urbs(priv);
80688da1743SJi-Ze Hong 	if (ret)
80788da1743SJi-Ze Hong 		return ret;
80888da1743SJi-Ze Hong 
80988da1743SJi-Ze Hong 	ret = f81604_set_normal_mode(priv);
81088da1743SJi-Ze Hong 	if (ret) {
81188da1743SJi-Ze Hong 		f81604_unregister_urbs(priv);
81288da1743SJi-Ze Hong 		return ret;
81388da1743SJi-Ze Hong 	}
81488da1743SJi-Ze Hong 
81588da1743SJi-Ze Hong 	return 0;
81688da1743SJi-Ze Hong }
81788da1743SJi-Ze Hong 
f81604_set_bittiming(struct net_device * dev)81888da1743SJi-Ze Hong static int f81604_set_bittiming(struct net_device *dev)
81988da1743SJi-Ze Hong {
82088da1743SJi-Ze Hong 	struct f81604_port_priv *priv = netdev_priv(dev);
82188da1743SJi-Ze Hong 	struct can_bittiming *bt = &priv->can.bittiming;
82288da1743SJi-Ze Hong 	u8 btr0, btr1;
82388da1743SJi-Ze Hong 	int ret;
82488da1743SJi-Ze Hong 
82588da1743SJi-Ze Hong 	btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) |
82688da1743SJi-Ze Hong 	       FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1);
82788da1743SJi-Ze Hong 
82888da1743SJi-Ze Hong 	btr1 = FIELD_PREP(F81604_SEG1_MASK,
82988da1743SJi-Ze Hong 			  bt->prop_seg + bt->phase_seg1 - 1) |
83088da1743SJi-Ze Hong 	       FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1);
83188da1743SJi-Ze Hong 
83288da1743SJi-Ze Hong 	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
83388da1743SJi-Ze Hong 		btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE;
83488da1743SJi-Ze Hong 
83588da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0);
83688da1743SJi-Ze Hong 	if (ret) {
83788da1743SJi-Ze Hong 		netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__,
83888da1743SJi-Ze Hong 			    ERR_PTR(ret));
83988da1743SJi-Ze Hong 		return ret;
84088da1743SJi-Ze Hong 	}
84188da1743SJi-Ze Hong 
84288da1743SJi-Ze Hong 	ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1);
84388da1743SJi-Ze Hong 	if (ret) {
84488da1743SJi-Ze Hong 		netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__,
84588da1743SJi-Ze Hong 			    ERR_PTR(ret));
84688da1743SJi-Ze Hong 		return ret;
84788da1743SJi-Ze Hong 	}
84888da1743SJi-Ze Hong 
84988da1743SJi-Ze Hong 	return 0;
85088da1743SJi-Ze Hong }
85188da1743SJi-Ze Hong 
f81604_set_mode(struct net_device * netdev,enum can_mode mode)85288da1743SJi-Ze Hong static int f81604_set_mode(struct net_device *netdev, enum can_mode mode)
85388da1743SJi-Ze Hong {
85488da1743SJi-Ze Hong 	int ret;
85588da1743SJi-Ze Hong 
85688da1743SJi-Ze Hong 	switch (mode) {
85788da1743SJi-Ze Hong 	case CAN_MODE_START:
85888da1743SJi-Ze Hong 		ret = f81604_start(netdev);
85988da1743SJi-Ze Hong 		if (!ret && netif_queue_stopped(netdev))
86088da1743SJi-Ze Hong 			netif_wake_queue(netdev);
86188da1743SJi-Ze Hong 		break;
86288da1743SJi-Ze Hong 
86388da1743SJi-Ze Hong 	default:
86488da1743SJi-Ze Hong 		ret = -EOPNOTSUPP;
86588da1743SJi-Ze Hong 	}
86688da1743SJi-Ze Hong 
86788da1743SJi-Ze Hong 	return ret;
86888da1743SJi-Ze Hong }
86988da1743SJi-Ze Hong 
f81604_write_bulk_callback(struct urb * urb)87088da1743SJi-Ze Hong static void f81604_write_bulk_callback(struct urb *urb)
87188da1743SJi-Ze Hong {
87288da1743SJi-Ze Hong 	struct net_device *netdev = urb->context;
87388da1743SJi-Ze Hong 
87488da1743SJi-Ze Hong 	if (!netif_device_present(netdev))
87588da1743SJi-Ze Hong 		return;
87688da1743SJi-Ze Hong 
87788da1743SJi-Ze Hong 	if (urb->status)
87888da1743SJi-Ze Hong 		netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
87988da1743SJi-Ze Hong 			    ERR_PTR(urb->status));
88088da1743SJi-Ze Hong }
88188da1743SJi-Ze Hong 
f81604_clear_reg_work(struct work_struct * work)88288da1743SJi-Ze Hong static void f81604_clear_reg_work(struct work_struct *work)
88388da1743SJi-Ze Hong {
88488da1743SJi-Ze Hong 	struct f81604_port_priv *priv;
88588da1743SJi-Ze Hong 	u8 tmp;
88688da1743SJi-Ze Hong 
88788da1743SJi-Ze Hong 	priv = container_of(work, struct f81604_port_priv, clear_reg_work);
88888da1743SJi-Ze Hong 
88988da1743SJi-Ze Hong 	/* dummy read for clear Arbitration lost capture(ALC) register. */
89088da1743SJi-Ze Hong 	if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags))
89188da1743SJi-Ze Hong 		f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
89288da1743SJi-Ze Hong 
89388da1743SJi-Ze Hong 	/* dummy read for clear Error code capture(ECC) register. */
89488da1743SJi-Ze Hong 	if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags))
89588da1743SJi-Ze Hong 		f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
89688da1743SJi-Ze Hong 
89788da1743SJi-Ze Hong 	/* dummy write for clear data overrun flag. */
89888da1743SJi-Ze Hong 	if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags))
89988da1743SJi-Ze Hong 		f81604_sja1000_write(priv, F81604_SJA1000_CMR,
90088da1743SJi-Ze Hong 				     F81604_SJA1000_CMD_CDO);
90188da1743SJi-Ze Hong }
90288da1743SJi-Ze Hong 
f81604_start_xmit(struct sk_buff * skb,struct net_device * netdev)90388da1743SJi-Ze Hong static netdev_tx_t f81604_start_xmit(struct sk_buff *skb,
90488da1743SJi-Ze Hong 				     struct net_device *netdev)
90588da1743SJi-Ze Hong {
90688da1743SJi-Ze Hong 	struct can_frame *cf = (struct can_frame *)skb->data;
90788da1743SJi-Ze Hong 	struct f81604_port_priv *priv = netdev_priv(netdev);
90888da1743SJi-Ze Hong 	struct net_device_stats *stats = &netdev->stats;
90988da1743SJi-Ze Hong 	struct f81604_can_frame *frame;
91088da1743SJi-Ze Hong 	struct urb *write_urb;
91188da1743SJi-Ze Hong 	int ret;
91288da1743SJi-Ze Hong 
91388da1743SJi-Ze Hong 	if (can_dev_dropped_skb(netdev, skb))
91488da1743SJi-Ze Hong 		return NETDEV_TX_OK;
91588da1743SJi-Ze Hong 
91688da1743SJi-Ze Hong 	netif_stop_queue(netdev);
91788da1743SJi-Ze Hong 
91888da1743SJi-Ze Hong 	write_urb = usb_alloc_urb(0, GFP_ATOMIC);
91988da1743SJi-Ze Hong 	if (!write_urb)
92088da1743SJi-Ze Hong 		goto nomem_urb;
92188da1743SJi-Ze Hong 
92288da1743SJi-Ze Hong 	frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
92388da1743SJi-Ze Hong 	if (!frame)
92488da1743SJi-Ze Hong 		goto nomem_buf;
92588da1743SJi-Ze Hong 
92688da1743SJi-Ze Hong 	usb_fill_bulk_urb(write_urb, priv->dev,
92788da1743SJi-Ze Hong 			  usb_sndbulkpipe(priv->dev,
92888da1743SJi-Ze Hong 					  bulk_out_addr[netdev->dev_port]),
92988da1743SJi-Ze Hong 			  frame, sizeof(*frame), f81604_write_bulk_callback,
93088da1743SJi-Ze Hong 			  priv->netdev);
93188da1743SJi-Ze Hong 
93288da1743SJi-Ze Hong 	write_urb->transfer_flags |= URB_FREE_BUFFER;
93388da1743SJi-Ze Hong 
93488da1743SJi-Ze Hong 	frame->cmd = F81604_CMD_DATA;
93588da1743SJi-Ze Hong 	frame->dlc = cf->len;
93688da1743SJi-Ze Hong 
93788da1743SJi-Ze Hong 	if (cf->can_id & CAN_RTR_FLAG)
93888da1743SJi-Ze Hong 		frame->dlc |= F81604_DLC_RTR_BIT;
93988da1743SJi-Ze Hong 
94088da1743SJi-Ze Hong 	if (cf->can_id & CAN_EFF_FLAG) {
94188da1743SJi-Ze Hong 		u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT;
94288da1743SJi-Ze Hong 
94388da1743SJi-Ze Hong 		put_unaligned_be32(id, &frame->eff.id);
94488da1743SJi-Ze Hong 
94588da1743SJi-Ze Hong 		frame->dlc |= F81604_DLC_EFF_BIT;
94688da1743SJi-Ze Hong 
94788da1743SJi-Ze Hong 		if (!(cf->can_id & CAN_RTR_FLAG))
94888da1743SJi-Ze Hong 			memcpy(&frame->eff.data, cf->data, cf->len);
94988da1743SJi-Ze Hong 	} else {
95088da1743SJi-Ze Hong 		u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT;
95188da1743SJi-Ze Hong 
95288da1743SJi-Ze Hong 		put_unaligned_be16(id, &frame->sff.id);
95388da1743SJi-Ze Hong 
95488da1743SJi-Ze Hong 		if (!(cf->can_id & CAN_RTR_FLAG))
95588da1743SJi-Ze Hong 			memcpy(&frame->sff.data, cf->data, cf->len);
95688da1743SJi-Ze Hong 	}
95788da1743SJi-Ze Hong 
95888da1743SJi-Ze Hong 	can_put_echo_skb(skb, netdev, 0, 0);
95988da1743SJi-Ze Hong 
96088da1743SJi-Ze Hong 	ret = usb_submit_urb(write_urb, GFP_ATOMIC);
96188da1743SJi-Ze Hong 	if (ret) {
96288da1743SJi-Ze Hong 		netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n",
96388da1743SJi-Ze Hong 			   __func__, ERR_PTR(ret));
96488da1743SJi-Ze Hong 
96588da1743SJi-Ze Hong 		can_free_echo_skb(netdev, 0, NULL);
96688da1743SJi-Ze Hong 		stats->tx_dropped++;
96788da1743SJi-Ze Hong 		stats->tx_errors++;
96888da1743SJi-Ze Hong 
96988da1743SJi-Ze Hong 		if (ret == -ENODEV)
97088da1743SJi-Ze Hong 			netif_device_detach(netdev);
97188da1743SJi-Ze Hong 		else
97288da1743SJi-Ze Hong 			netif_wake_queue(netdev);
97388da1743SJi-Ze Hong 	}
97488da1743SJi-Ze Hong 
97588da1743SJi-Ze Hong 	/* let usb core take care of this urb */
97688da1743SJi-Ze Hong 	usb_free_urb(write_urb);
97788da1743SJi-Ze Hong 
97888da1743SJi-Ze Hong 	return NETDEV_TX_OK;
97988da1743SJi-Ze Hong 
98088da1743SJi-Ze Hong nomem_buf:
98188da1743SJi-Ze Hong 	usb_free_urb(write_urb);
98288da1743SJi-Ze Hong 
98388da1743SJi-Ze Hong nomem_urb:
98488da1743SJi-Ze Hong 	dev_kfree_skb(skb);
98588da1743SJi-Ze Hong 	stats->tx_dropped++;
98688da1743SJi-Ze Hong 	stats->tx_errors++;
98788da1743SJi-Ze Hong 	netif_wake_queue(netdev);
98888da1743SJi-Ze Hong 
98988da1743SJi-Ze Hong 	return NETDEV_TX_OK;
99088da1743SJi-Ze Hong }
99188da1743SJi-Ze Hong 
f81604_get_berr_counter(const struct net_device * netdev,struct can_berr_counter * bec)99288da1743SJi-Ze Hong static int f81604_get_berr_counter(const struct net_device *netdev,
99388da1743SJi-Ze Hong 				   struct can_berr_counter *bec)
99488da1743SJi-Ze Hong {
99588da1743SJi-Ze Hong 	struct f81604_port_priv *priv = netdev_priv(netdev);
99688da1743SJi-Ze Hong 	u8 txerr, rxerr;
99788da1743SJi-Ze Hong 	int ret;
99888da1743SJi-Ze Hong 
99988da1743SJi-Ze Hong 	ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr);
100088da1743SJi-Ze Hong 	if (ret)
100188da1743SJi-Ze Hong 		return ret;
100288da1743SJi-Ze Hong 
100388da1743SJi-Ze Hong 	ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr);
100488da1743SJi-Ze Hong 	if (ret)
100588da1743SJi-Ze Hong 		return ret;
100688da1743SJi-Ze Hong 
100788da1743SJi-Ze Hong 	bec->txerr = txerr;
100888da1743SJi-Ze Hong 	bec->rxerr = rxerr;
100988da1743SJi-Ze Hong 
101088da1743SJi-Ze Hong 	return 0;
101188da1743SJi-Ze Hong }
101288da1743SJi-Ze Hong 
101388da1743SJi-Ze Hong /* Open USB device */
f81604_open(struct net_device * netdev)101488da1743SJi-Ze Hong static int f81604_open(struct net_device *netdev)
101588da1743SJi-Ze Hong {
101688da1743SJi-Ze Hong 	int ret;
101788da1743SJi-Ze Hong 
101888da1743SJi-Ze Hong 	ret = open_candev(netdev);
101988da1743SJi-Ze Hong 	if (ret)
102088da1743SJi-Ze Hong 		return ret;
102188da1743SJi-Ze Hong 
102288da1743SJi-Ze Hong 	ret = f81604_start(netdev);
102388da1743SJi-Ze Hong 	if (ret) {
102488da1743SJi-Ze Hong 		if (ret == -ENODEV)
102588da1743SJi-Ze Hong 			netif_device_detach(netdev);
102688da1743SJi-Ze Hong 
102788da1743SJi-Ze Hong 		close_candev(netdev);
102888da1743SJi-Ze Hong 		return ret;
102988da1743SJi-Ze Hong 	}
103088da1743SJi-Ze Hong 
103188da1743SJi-Ze Hong 	netif_start_queue(netdev);
103288da1743SJi-Ze Hong 	return 0;
103388da1743SJi-Ze Hong }
103488da1743SJi-Ze Hong 
103588da1743SJi-Ze Hong /* Close USB device */
f81604_close(struct net_device * netdev)103688da1743SJi-Ze Hong static int f81604_close(struct net_device *netdev)
103788da1743SJi-Ze Hong {
103888da1743SJi-Ze Hong 	struct f81604_port_priv *priv = netdev_priv(netdev);
103988da1743SJi-Ze Hong 
104088da1743SJi-Ze Hong 	f81604_set_reset_mode(priv);
104188da1743SJi-Ze Hong 
104288da1743SJi-Ze Hong 	netif_stop_queue(netdev);
104388da1743SJi-Ze Hong 	cancel_work_sync(&priv->clear_reg_work);
104488da1743SJi-Ze Hong 	close_candev(netdev);
104588da1743SJi-Ze Hong 
104688da1743SJi-Ze Hong 	f81604_unregister_urbs(priv);
104788da1743SJi-Ze Hong 
104888da1743SJi-Ze Hong 	return 0;
104988da1743SJi-Ze Hong }
105088da1743SJi-Ze Hong 
105188da1743SJi-Ze Hong static const struct net_device_ops f81604_netdev_ops = {
105288da1743SJi-Ze Hong 	.ndo_open = f81604_open,
105388da1743SJi-Ze Hong 	.ndo_stop = f81604_close,
105488da1743SJi-Ze Hong 	.ndo_start_xmit = f81604_start_xmit,
105588da1743SJi-Ze Hong 	.ndo_change_mtu = can_change_mtu,
105688da1743SJi-Ze Hong };
105788da1743SJi-Ze Hong 
105888da1743SJi-Ze Hong static const struct can_bittiming_const f81604_bittiming_const = {
105988da1743SJi-Ze Hong 	.name = KBUILD_MODNAME,
106088da1743SJi-Ze Hong 	.tseg1_min = 1,
106188da1743SJi-Ze Hong 	.tseg1_max = 16,
106288da1743SJi-Ze Hong 	.tseg2_min = 1,
106388da1743SJi-Ze Hong 	.tseg2_max = 8,
106488da1743SJi-Ze Hong 	.sjw_max = 4,
106588da1743SJi-Ze Hong 	.brp_min = 1,
106688da1743SJi-Ze Hong 	.brp_max = 64,
106788da1743SJi-Ze Hong 	.brp_inc = 1,
106888da1743SJi-Ze Hong };
106988da1743SJi-Ze Hong 
107088da1743SJi-Ze Hong /* Called by the usb core when driver is unloaded or device is removed */
f81604_disconnect(struct usb_interface * intf)107188da1743SJi-Ze Hong static void f81604_disconnect(struct usb_interface *intf)
107288da1743SJi-Ze Hong {
107388da1743SJi-Ze Hong 	struct f81604_priv *priv = usb_get_intfdata(intf);
107488da1743SJi-Ze Hong 	int i;
107588da1743SJi-Ze Hong 
107688da1743SJi-Ze Hong 	for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
107788da1743SJi-Ze Hong 		if (!priv->netdev[i])
107888da1743SJi-Ze Hong 			continue;
107988da1743SJi-Ze Hong 
108088da1743SJi-Ze Hong 		unregister_netdev(priv->netdev[i]);
108188da1743SJi-Ze Hong 		free_candev(priv->netdev[i]);
108288da1743SJi-Ze Hong 	}
108388da1743SJi-Ze Hong }
108488da1743SJi-Ze Hong 
__f81604_set_termination(struct usb_device * dev,int idx,u16 term)108588da1743SJi-Ze Hong static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term)
108688da1743SJi-Ze Hong {
108788da1743SJi-Ze Hong 	u8 mask, data = 0;
108888da1743SJi-Ze Hong 
108988da1743SJi-Ze Hong 	if (idx == 0)
109088da1743SJi-Ze Hong 		mask = F81604_CAN0_TERM;
109188da1743SJi-Ze Hong 	else
109288da1743SJi-Ze Hong 		mask = F81604_CAN1_TERM;
109388da1743SJi-Ze Hong 
109488da1743SJi-Ze Hong 	if (term)
109588da1743SJi-Ze Hong 		data = mask;
109688da1743SJi-Ze Hong 
109788da1743SJi-Ze Hong 	return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data);
109888da1743SJi-Ze Hong }
109988da1743SJi-Ze Hong 
f81604_set_termination(struct net_device * netdev,u16 term)110088da1743SJi-Ze Hong static int f81604_set_termination(struct net_device *netdev, u16 term)
110188da1743SJi-Ze Hong {
110288da1743SJi-Ze Hong 	struct f81604_port_priv *port_priv = netdev_priv(netdev);
110388da1743SJi-Ze Hong 
110488da1743SJi-Ze Hong 	ASSERT_RTNL();
110588da1743SJi-Ze Hong 
110688da1743SJi-Ze Hong 	return __f81604_set_termination(port_priv->dev, netdev->dev_port,
110788da1743SJi-Ze Hong 					term);
110888da1743SJi-Ze Hong }
110988da1743SJi-Ze Hong 
f81604_probe(struct usb_interface * intf,const struct usb_device_id * id)111088da1743SJi-Ze Hong static int f81604_probe(struct usb_interface *intf,
111188da1743SJi-Ze Hong 			const struct usb_device_id *id)
111288da1743SJi-Ze Hong {
111388da1743SJi-Ze Hong 	struct usb_device *dev = interface_to_usbdev(intf);
111488da1743SJi-Ze Hong 	struct net_device *netdev;
111588da1743SJi-Ze Hong 	struct f81604_priv *priv;
111688da1743SJi-Ze Hong 	int i, ret;
111788da1743SJi-Ze Hong 
111888da1743SJi-Ze Hong 	priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL);
111988da1743SJi-Ze Hong 	if (!priv)
112088da1743SJi-Ze Hong 		return -ENOMEM;
112188da1743SJi-Ze Hong 
112288da1743SJi-Ze Hong 	usb_set_intfdata(intf, priv);
112388da1743SJi-Ze Hong 
112488da1743SJi-Ze Hong 	for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
112588da1743SJi-Ze Hong 		ret = __f81604_set_termination(dev, i, 0);
112688da1743SJi-Ze Hong 		if (ret) {
112788da1743SJi-Ze Hong 			dev_err(&intf->dev,
112888da1743SJi-Ze Hong 				"Setting termination of CH#%d failed: %pe\n",
112988da1743SJi-Ze Hong 				i, ERR_PTR(ret));
113088da1743SJi-Ze Hong 			return ret;
113188da1743SJi-Ze Hong 		}
113288da1743SJi-Ze Hong 	}
113388da1743SJi-Ze Hong 
113488da1743SJi-Ze Hong 	for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
113588da1743SJi-Ze Hong 		struct f81604_port_priv *port_priv;
113688da1743SJi-Ze Hong 
113788da1743SJi-Ze Hong 		netdev = alloc_candev(sizeof(*port_priv), 1);
113888da1743SJi-Ze Hong 		if (!netdev) {
113988da1743SJi-Ze Hong 			dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i);
114088da1743SJi-Ze Hong 			ret = -ENOMEM;
114188da1743SJi-Ze Hong 
114288da1743SJi-Ze Hong 			goto failure_cleanup;
114388da1743SJi-Ze Hong 		}
114488da1743SJi-Ze Hong 
114588da1743SJi-Ze Hong 		port_priv = netdev_priv(netdev);
114688da1743SJi-Ze Hong 
114788da1743SJi-Ze Hong 		INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work);
114888da1743SJi-Ze Hong 		init_usb_anchor(&port_priv->urbs_anchor);
114988da1743SJi-Ze Hong 
115088da1743SJi-Ze Hong 		port_priv->intf = intf;
115188da1743SJi-Ze Hong 		port_priv->dev = dev;
115288da1743SJi-Ze Hong 		port_priv->netdev = netdev;
115388da1743SJi-Ze Hong 		port_priv->can.clock.freq = F81604_CAN_CLOCK;
115488da1743SJi-Ze Hong 
115588da1743SJi-Ze Hong 		port_priv->can.termination_const = f81604_termination;
115688da1743SJi-Ze Hong 		port_priv->can.termination_const_cnt =
115788da1743SJi-Ze Hong 			ARRAY_SIZE(f81604_termination);
115888da1743SJi-Ze Hong 		port_priv->can.bittiming_const = &f81604_bittiming_const;
115988da1743SJi-Ze Hong 		port_priv->can.do_set_bittiming = f81604_set_bittiming;
116088da1743SJi-Ze Hong 		port_priv->can.do_set_mode = f81604_set_mode;
116188da1743SJi-Ze Hong 		port_priv->can.do_set_termination = f81604_set_termination;
116288da1743SJi-Ze Hong 		port_priv->can.do_get_berr_counter = f81604_get_berr_counter;
116388da1743SJi-Ze Hong 		port_priv->can.ctrlmode_supported =
116488da1743SJi-Ze Hong 			CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
116588da1743SJi-Ze Hong 			CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING |
116688da1743SJi-Ze Hong 			CAN_CTRLMODE_PRESUME_ACK;
116788da1743SJi-Ze Hong 
116888da1743SJi-Ze Hong 		netdev->ethtool_ops = &f81604_ethtool_ops;
116988da1743SJi-Ze Hong 		netdev->netdev_ops = &f81604_netdev_ops;
117088da1743SJi-Ze Hong 		netdev->flags |= IFF_ECHO;
117188da1743SJi-Ze Hong 		netdev->dev_port = i;
117288da1743SJi-Ze Hong 
117388da1743SJi-Ze Hong 		SET_NETDEV_DEV(netdev, &intf->dev);
117488da1743SJi-Ze Hong 
117588da1743SJi-Ze Hong 		ret = register_candev(netdev);
117688da1743SJi-Ze Hong 		if (ret) {
117788da1743SJi-Ze Hong 			netdev_err(netdev, "register CAN device failed: %pe\n",
117888da1743SJi-Ze Hong 				   ERR_PTR(ret));
117988da1743SJi-Ze Hong 			free_candev(netdev);
118088da1743SJi-Ze Hong 
118188da1743SJi-Ze Hong 			goto failure_cleanup;
118288da1743SJi-Ze Hong 		}
118388da1743SJi-Ze Hong 
118488da1743SJi-Ze Hong 		priv->netdev[i] = netdev;
118588da1743SJi-Ze Hong 	}
118688da1743SJi-Ze Hong 
118788da1743SJi-Ze Hong 	return 0;
118888da1743SJi-Ze Hong 
118988da1743SJi-Ze Hong failure_cleanup:
119088da1743SJi-Ze Hong 	f81604_disconnect(intf);
119188da1743SJi-Ze Hong 	return ret;
119288da1743SJi-Ze Hong }
119388da1743SJi-Ze Hong 
119488da1743SJi-Ze Hong static struct usb_driver f81604_driver = {
119588da1743SJi-Ze Hong 	.name = KBUILD_MODNAME,
119688da1743SJi-Ze Hong 	.probe = f81604_probe,
119788da1743SJi-Ze Hong 	.disconnect = f81604_disconnect,
119888da1743SJi-Ze Hong 	.id_table = f81604_table,
119988da1743SJi-Ze Hong };
120088da1743SJi-Ze Hong 
120188da1743SJi-Ze Hong module_usb_driver(f81604_driver);
120288da1743SJi-Ze Hong 
120388da1743SJi-Ze Hong MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>");
120488da1743SJi-Ze Hong MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS");
120588da1743SJi-Ze Hong MODULE_LICENSE("GPL");
1206