diff options
Diffstat (limited to 'drivers/net/can')
53 files changed, 4915 insertions, 1470 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 3c069472eb8..41688229c57 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -65,24 +65,18 @@ config CAN_LEDS  config CAN_AT91  	tristate "Atmel AT91 onchip CAN controller" -	depends on ARM +	depends on ARCH_AT91 || COMPILE_TEST  	---help---  	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263  	  and AT91SAM9X5 processors.  config CAN_TI_HECC -	depends on ARCH_OMAP3 +	depends on ARM  	tristate "TI High End CAN Controller"  	---help---  	  Driver for TI HECC (High End CAN Controller) module found on many  	  TI devices. The device specifications are available from www.ti.com -config CAN_MCP251X -	tristate "Microchip MCP251x SPI CAN controllers" -	depends on SPI && HAS_DMA -	---help--- -	  Driver for the Microchip MCP251x SPI CAN controllers. -  config CAN_BFIN  	depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x  	tristate "Analog Devices Blackfin on-chip CAN" @@ -110,7 +104,7 @@ config CAN_FLEXCAN  config PCH_CAN  	tristate "Intel EG20T PCH CAN controller" -	depends on PCI +	depends on PCI && (X86_32 || COMPILE_TEST)  	---help---  	  This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which  	  is an IOH for x86 embedded processor (Intel Atom E6xx series). @@ -125,6 +119,24 @@ config CAN_GRCAN  	  endian syntheses of the cores would need some modifications on  	  the hardware level to work. +config CAN_RCAR +	tristate "Renesas R-Car CAN controller" +	depends on ARM +	---help--- +	  Say Y here if you want to use CAN controller found on Renesas R-Car +	  SoCs. + +	  To compile this driver as a module, choose M here: the module will +	  be called rcar_can. + +config CAN_XILINXCAN +	tristate "Xilinx CAN" +	depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST +	depends on COMMON_CLK && HAS_IOMEM +	---help--- +	  Xilinx CAN driver. This driver supports both soft AXI CAN IP and +	  Zynq CANPS IP. +  source "drivers/net/can/mscan/Kconfig"  source "drivers/net/can/sja1000/Kconfig" @@ -133,6 +145,8 @@ source "drivers/net/can/c_can/Kconfig"  source "drivers/net/can/cc770/Kconfig" +source "drivers/net/can/spi/Kconfig" +  source "drivers/net/can/usb/Kconfig"  source "drivers/net/can/softing/Kconfig" diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index c7440392adb..1697f22353a 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -10,6 +10,7 @@ can-dev-y			:= dev.o  can-dev-$(CONFIG_CAN_LEDS)	+= led.o +obj-y				+= spi/  obj-y				+= usb/  obj-y				+= softing/ @@ -19,11 +20,12 @@ obj-$(CONFIG_CAN_C_CAN)		+= c_can/  obj-$(CONFIG_CAN_CC770)		+= cc770/  obj-$(CONFIG_CAN_AT91)		+= at91_can.o  obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o -obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o  obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o  obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o  obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o  obj-$(CONFIG_PCH_CAN)		+= pch_can.o  obj-$(CONFIG_CAN_GRCAN)		+= grcan.o +obj-$(CONFIG_CAN_RCAR)		+= rcar_can.o +obj-$(CONFIG_CAN_XILINXCAN)	+= xilinx_can.o  ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 3b1ff614870..f07fa89b5fd 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -22,7 +22,6 @@  #include <linux/clk.h>  #include <linux/errno.h>  #include <linux/if_arp.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/module.h> @@ -421,7 +420,11 @@ static void at91_chip_start(struct net_device *dev)  	at91_transceiver_switch(priv, 1);  	/* enable chip */ -	at91_write(priv, AT91_MR, AT91_MR_CANEN); +	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) +		reg_mr = AT91_MR_CANEN | AT91_MR_ABM; +	else +		reg_mr = AT91_MR_CANEN; +	at91_write(priv, AT91_MR, reg_mr);  	priv->can.state = CAN_STATE_ERROR_ACTIVE; @@ -1191,6 +1194,7 @@ static const struct net_device_ops at91_netdev_ops = {  	.ndo_open	= at91_open,  	.ndo_stop	= at91_close,  	.ndo_start_xmit	= at91_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static ssize_t at91_sysfs_show_mb0_id(struct device *dev, @@ -1342,12 +1346,13 @@ static int at91_can_probe(struct platform_device *pdev)  	priv->can.bittiming_const = &at91_bittiming_const;  	priv->can.do_set_mode = at91_set_mode;  	priv->can.do_get_berr_counter = at91_get_berr_counter; -	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; +	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | +		CAN_CTRLMODE_LISTENONLY;  	priv->dev = dev;  	priv->reg_base = addr;  	priv->devtype_data = *devtype_data;  	priv->clk = clk; -	priv->pdata = pdev->dev.platform_data; +	priv->pdata = dev_get_platdata(&pdev->dev);  	priv->mb0_id = 0x7ff;  	netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv)); @@ -1405,10 +1410,10 @@ static int at91_can_remove(struct platform_device *pdev)  static const struct platform_device_id at91_can_id_table[] = {  	{ -		.name = "at91_can", +		.name = "at91sam9x5_can",  		.driver_data = (kernel_ulong_t)&at91_at91sam9x5_data,  	}, { -		.name = "at91sam9x5_can", +		.name = "at91_can",  		.driver_data = (kernel_ulong_t)&at91_at91sam9263_data,  	}, {  		/* sentinel */ diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index a2700d25ff0..543ecceb33e 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -9,7 +9,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/bitops.h>  #include <linux/interrupt.h> @@ -529,6 +528,7 @@ static const struct net_device_ops bfin_can_netdev_ops = {  	.ndo_open               = bfin_can_open,  	.ndo_stop               = bfin_can_close,  	.ndo_start_xmit         = bfin_can_start_xmit, +	.ndo_change_mtu         = can_change_mtu,  };  static int bfin_can_probe(struct platform_device *pdev) @@ -539,7 +539,7 @@ static int bfin_can_probe(struct platform_device *pdev)  	struct resource *res_mem, *rx_irq, *tx_irq, *err_irq;  	unsigned short *pdata; -	pdata = pdev->dev.platform_data; +	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata) {  		dev_err(&pdev->dev, "No platform data provided!\n");  		err = -EINVAL; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index a668cd491cb..8e78bb48f5a 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -60,6 +60,8 @@  #define CONTROL_IE		BIT(1)  #define CONTROL_INIT		BIT(0) +#define CONTROL_IRQMSK		(CONTROL_EIE | CONTROL_IE | CONTROL_SIE) +  /* test register */  #define TEST_RX			BIT(7)  #define TEST_TX1		BIT(6) @@ -108,21 +110,38 @@  #define IF_COMM_CONTROL		BIT(4)  #define IF_COMM_CLR_INT_PND	BIT(3)  #define IF_COMM_TXRQST		BIT(2) +#define IF_COMM_CLR_NEWDAT	IF_COMM_TXRQST  #define IF_COMM_DATAA		BIT(1)  #define IF_COMM_DATAB		BIT(0) -#define IF_COMM_ALL		(IF_COMM_MASK | IF_COMM_ARB | \ -				IF_COMM_CONTROL | IF_COMM_TXRQST | \ -				IF_COMM_DATAA | IF_COMM_DATAB) + +/* TX buffer setup */ +#define IF_COMM_TX		(IF_COMM_ARB | IF_COMM_CONTROL | \ +				 IF_COMM_TXRQST |		 \ +				 IF_COMM_DATAA | IF_COMM_DATAB) + +/* For the low buffers we clear the interrupt bit, but keep newdat */ +#define IF_COMM_RCV_LOW		(IF_COMM_MASK | IF_COMM_ARB | \ +				 IF_COMM_CONTROL | IF_COMM_CLR_INT_PND | \ +				 IF_COMM_DATAA | IF_COMM_DATAB) + +/* For the high buffers we clear the interrupt bit and newdat */ +#define IF_COMM_RCV_HIGH	(IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT) + + +/* Receive setup of message objects */ +#define IF_COMM_RCV_SETUP	(IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL) + +/* Invalidation of message objects */ +#define IF_COMM_INVAL		(IF_COMM_ARB | IF_COMM_CONTROL)  /* IFx arbitration */ -#define IF_ARB_MSGVAL		BIT(15) -#define IF_ARB_MSGXTD		BIT(14) -#define IF_ARB_TRANSMIT		BIT(13) +#define IF_ARB_MSGVAL		BIT(31) +#define IF_ARB_MSGXTD		BIT(30) +#define IF_ARB_TRANSMIT		BIT(29)  /* IFx message control */  #define IF_MCONT_NEWDAT		BIT(15)  #define IF_MCONT_MSGLST		BIT(14) -#define IF_MCONT_CLR_MSGLST	(0 << 14)  #define IF_MCONT_INTPND		BIT(13)  #define IF_MCONT_UMASK		BIT(12)  #define IF_MCONT_TXIE		BIT(11) @@ -132,39 +151,16 @@  #define IF_MCONT_EOB		BIT(7)  #define IF_MCONT_DLC_MASK	0xf -/* - * IFx register masks: - * allow easy operation on 16-bit registers when the - * argument is 32-bit instead - */ -#define IFX_WRITE_LOW_16BIT(x)	((x) & 0xFFFF) -#define IFX_WRITE_HIGH_16BIT(x)	(((x) & 0xFFFF0000) >> 16) - -/* message object split */ -#define C_CAN_NO_OF_OBJECTS	32 -#define C_CAN_MSG_OBJ_RX_NUM	16 -#define C_CAN_MSG_OBJ_TX_NUM	16 - -#define C_CAN_MSG_OBJ_RX_FIRST	1 -#define C_CAN_MSG_OBJ_RX_LAST	(C_CAN_MSG_OBJ_RX_FIRST + \ -				C_CAN_MSG_OBJ_RX_NUM - 1) - -#define C_CAN_MSG_OBJ_TX_FIRST	(C_CAN_MSG_OBJ_RX_LAST + 1) -#define C_CAN_MSG_OBJ_TX_LAST	(C_CAN_MSG_OBJ_TX_FIRST + \ -				C_CAN_MSG_OBJ_TX_NUM - 1) - -#define C_CAN_MSG_OBJ_RX_SPLIT	9 -#define C_CAN_MSG_RX_LOW_LAST	(C_CAN_MSG_OBJ_RX_SPLIT - 1) - -#define C_CAN_NEXT_MSG_OBJ_MASK	(C_CAN_MSG_OBJ_TX_NUM - 1) -#define RECEIVE_OBJECT_BITS	0x0000ffff +#define IF_MCONT_RCV		(IF_MCONT_RXIE | IF_MCONT_UMASK) +#define IF_MCONT_RCV_EOB	(IF_MCONT_RCV | IF_MCONT_EOB) -/* status interrupt */ -#define STATUS_INTERRUPT	0x8000 +#define IF_MCONT_TX		(IF_MCONT_TXIE | IF_MCONT_EOB) -/* global interrupt masks */ -#define ENABLE_ALL_INTERRUPTS	1 -#define DISABLE_ALL_INTERRUPTS	0 +/* + * Use IF1 for RX and IF2 for TX + */ +#define IF_RX			0 +#define IF_TX			1  /* minimum timeout for checking BUSY status */  #define MIN_TIMEOUT_VALUE	6 @@ -185,6 +181,7 @@ enum c_can_lec_type {  	LEC_BIT0_ERROR,  	LEC_CRC_ERROR,  	LEC_UNUSED, +	LEC_MASK = LEC_UNUSED,  };  /* @@ -240,210 +237,149 @@ static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)  		priv->raminit(priv, enable);  } -static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) -{ -	return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + -			C_CAN_MSG_OBJ_TX_FIRST; -} - -static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv) +static void c_can_irq_control(struct c_can_priv *priv, bool enable)  { -	return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) + -			C_CAN_MSG_OBJ_TX_FIRST; -} - -static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index) -{ -	u32 val = priv->read_reg(priv, index); -	val |= ((u32) priv->read_reg(priv, index + 1)) << 16; -	return val; -} - -static void c_can_enable_all_interrupts(struct c_can_priv *priv, -						int enable) -{ -	unsigned int cntrl_save = priv->read_reg(priv, -						C_CAN_CTRL_REG); +	u32 ctrl = priv->read_reg(priv,	C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;  	if (enable) -		cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE); -	else -		cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE); +		ctrl |= CONTROL_IRQMSK; -	priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save); +	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);  } -static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface) +static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj)  { -	int count = MIN_TIMEOUT_VALUE; +	struct c_can_priv *priv = netdev_priv(dev); +	int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); -	while (count && priv->read_reg(priv, -				C_CAN_IFACE(COMREQ_REG, iface)) & -				IF_COMR_BUSY) { -		count--; +	priv->write_reg32(priv, reg, (cmd << 16) | obj); + +	for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { +		if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) +			return;  		udelay(1);  	} +	netdev_err(dev, "Updating object timed out\n"); -	if (!count) -		return 1; +} -	return 0; +static inline void c_can_object_get(struct net_device *dev, int iface, +				    u32 obj, u32 cmd) +{ +	c_can_obj_update(dev, iface, cmd, obj);  } -static inline void c_can_object_get(struct net_device *dev, -					int iface, int objno, int mask) +static inline void c_can_object_put(struct net_device *dev, int iface, +				    u32 obj, u32 cmd)  { -	struct c_can_priv *priv = netdev_priv(dev); +	c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); +} -	/* -	 * As per specs, after writting the message object number in the -	 * IF command request register the transfer b/w interface -	 * register and message RAM must be complete in 6 CAN-CLK -	 * period. -	 */ -	priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), -			IFX_WRITE_LOW_16BIT(mask)); -	priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), -			IFX_WRITE_LOW_16BIT(objno)); +/* + * Note: According to documentation clearing TXIE while MSGVAL is set + * is not allowed, but works nicely on C/DCAN. And that lowers the I/O + * load significantly. + */ +static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) +{ +	struct c_can_priv *priv = netdev_priv(dev); -	if (c_can_msg_obj_is_busy(priv, iface)) -		netdev_err(dev, "timed out in object get\n"); +	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); +	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);  } -static inline void c_can_object_put(struct net_device *dev, -					int iface, int objno, int mask) +static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)  {  	struct c_can_priv *priv = netdev_priv(dev); -	/* -	 * As per specs, after writting the message object number in the -	 * IF command request register the transfer b/w interface -	 * register and message RAM must be complete in 6 CAN-CLK -	 * period. -	 */ -	priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), -			(IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask))); -	priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), -			IFX_WRITE_LOW_16BIT(objno)); - -	if (c_can_msg_obj_is_busy(priv, iface)) -		netdev_err(dev, "timed out in object put\n"); +	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); +	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); +	c_can_inval_tx_object(dev, iface, obj);  } -static void c_can_write_msg_object(struct net_device *dev, -			int iface, struct can_frame *frame, int objno) +static void c_can_setup_tx_object(struct net_device *dev, int iface, +				  struct can_frame *frame, int idx)  { -	int i; -	u16 flags = 0; -	unsigned int id;  	struct c_can_priv *priv = netdev_priv(dev); - -	if (!(frame->can_id & CAN_RTR_FLAG)) -		flags |= IF_ARB_TRANSMIT; +	u16 ctrl = IF_MCONT_TX | frame->can_dlc; +	bool rtr = frame->can_id & CAN_RTR_FLAG; +	u32 arb = IF_ARB_MSGVAL; +	int i;  	if (frame->can_id & CAN_EFF_FLAG) { -		id = frame->can_id & CAN_EFF_MASK; -		flags |= IF_ARB_MSGXTD; -	} else -		id = ((frame->can_id & CAN_SFF_MASK) << 18); +		arb |= frame->can_id & CAN_EFF_MASK; +		arb |= IF_ARB_MSGXTD; +	} else { +		arb |= (frame->can_id & CAN_SFF_MASK) << 18; +	} -	flags |= IF_ARB_MSGVAL; +	if (!rtr) +		arb |= IF_ARB_TRANSMIT; -	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), -				IFX_WRITE_LOW_16BIT(id)); -	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags | -				IFX_WRITE_HIGH_16BIT(id)); +	/* +	 * If we change the DIR bit, we need to invalidate the buffer +	 * first, i.e. clear the MSGVAL flag in the arbiter. +	 */ +	if (rtr != (bool)test_bit(idx, &priv->tx_dir)) { +		u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST; -	for (i = 0; i < frame->can_dlc; i += 2) { -		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, -				frame->data[i] | (frame->data[i + 1] << 8)); +		c_can_inval_msg_object(dev, iface, obj); +		change_bit(idx, &priv->tx_dir);  	} -	/* enable interrupt for this message object */ -	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), -			IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB | -			frame->can_dlc); -	c_can_object_put(dev, iface, objno, IF_COMM_ALL); -} +	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb); -static inline void c_can_mark_rx_msg_obj(struct net_device *dev, -						int iface, int ctrl_mask, -						int obj) -{ -	struct c_can_priv *priv = netdev_priv(dev); - -	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), -			ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND)); -	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL); +	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); +	for (i = 0; i < frame->can_dlc; i += 2) { +		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, +				frame->data[i] | (frame->data[i + 1] << 8)); +	}  }  static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, -						int iface, -						int ctrl_mask) +						       int iface)  {  	int i; -	struct c_can_priv *priv = netdev_priv(dev); -	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) { -		priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), -				ctrl_mask & ~(IF_MCONT_MSGLST | -					IF_MCONT_INTPND | IF_MCONT_NEWDAT)); -		c_can_object_put(dev, iface, i, IF_COMM_CONTROL); -	} +	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) +		c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);  } -static inline void c_can_activate_rx_msg_obj(struct net_device *dev, -						int iface, int ctrl_mask, -						int obj) +static int c_can_handle_lost_msg_obj(struct net_device *dev, +				     int iface, int objno, u32 ctrl)  { -	struct c_can_priv *priv = netdev_priv(dev); - -	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), -			ctrl_mask & ~(IF_MCONT_MSGLST | -				IF_MCONT_INTPND | IF_MCONT_NEWDAT)); -	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL); -} - -static void c_can_handle_lost_msg_obj(struct net_device *dev, -					int iface, int objno) -{ -	struct c_can_priv *priv = netdev_priv(dev);  	struct net_device_stats *stats = &dev->stats; -	struct sk_buff *skb; +	struct c_can_priv *priv = netdev_priv(dev);  	struct can_frame *frame; +	struct sk_buff *skb; -	netdev_err(dev, "msg lost in buffer %d\n", objno); - -	c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); - -	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), -			IF_MCONT_CLR_MSGLST); +	ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); +	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); +	c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); -	c_can_object_put(dev, 0, objno, IF_COMM_CONTROL); +	stats->rx_errors++; +	stats->rx_over_errors++;  	/* create an error msg */  	skb = alloc_can_err_skb(dev, &frame);  	if (unlikely(!skb)) -		return; +		return 0;  	frame->can_id |= CAN_ERR_CRTL;  	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; -	stats->rx_errors++; -	stats->rx_over_errors++;  	netif_receive_skb(skb); +	return 1;  } -static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) +static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)  { -	u16 flags, data; -	int i; -	unsigned int val; -	struct c_can_priv *priv = netdev_priv(dev);  	struct net_device_stats *stats = &dev->stats; -	struct sk_buff *skb; +	struct c_can_priv *priv = netdev_priv(dev);  	struct can_frame *frame; +	struct sk_buff *skb; +	u32 arb, data;  	skb = alloc_can_skb(dev, &frame);  	if (!skb) { @@ -453,119 +389,98 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)  	frame->can_dlc = get_can_dlc(ctrl & 0x0F); -	flags =	priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)); -	val = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)) | -		(flags << 16); +	arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface)); -	if (flags & IF_ARB_MSGXTD) -		frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG; +	if (arb & IF_ARB_MSGXTD) +		frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;  	else -		frame->can_id = (val >> 18) & CAN_SFF_MASK; +		frame->can_id = (arb >> 18) & CAN_SFF_MASK; -	if (flags & IF_ARB_TRANSMIT) +	if (arb & IF_ARB_TRANSMIT) {  		frame->can_id |= CAN_RTR_FLAG; -	else { -		for (i = 0; i < frame->can_dlc; i += 2) { -			data = priv->read_reg(priv, -				C_CAN_IFACE(DATA1_REG, iface) + i / 2); +	} else { +		int i, dreg = C_CAN_IFACE(DATA1_REG, iface); + +		for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { +			data = priv->read_reg(priv, dreg);  			frame->data[i] = data;  			frame->data[i + 1] = data >> 8;  		}  	} -	netif_receive_skb(skb); -  	stats->rx_packets++;  	stats->rx_bytes += frame->can_dlc; -	can_led_event(dev, CAN_LED_EVENT_RX); - +	netif_receive_skb(skb);  	return 0;  }  static void c_can_setup_receive_object(struct net_device *dev, int iface, -					int objno, unsigned int mask, -					unsigned int id, unsigned int mcont) +				       u32 obj, u32 mask, u32 id, u32 mcont)  {  	struct c_can_priv *priv = netdev_priv(dev); -	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), -			IFX_WRITE_LOW_16BIT(mask)); - -	/* According to C_CAN documentation, the reserved bit -	 * in IFx_MASK2 register is fixed 1 -	 */ -	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), -			IFX_WRITE_HIGH_16BIT(mask) | BIT(13)); +	mask |= BIT(29); +	priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask); -	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), -			IFX_WRITE_LOW_16BIT(id)); -	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), -			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id))); +	id |= IF_ARB_MSGVAL; +	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id);  	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont); -	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); - -	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, -			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno) -{ -	struct c_can_priv *priv = netdev_priv(dev); - -	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); -	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); -	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); - -	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL); - -	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, -			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno) -{ -	int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); - -	/* -	 * as transmission request register's bit n-1 corresponds to -	 * message object n, we need to handle the same properly. -	 */ -	if (val & (1 << (objno - 1))) -		return 1; - -	return 0; +	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);  }  static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, -					struct net_device *dev) +				    struct net_device *dev)  { -	u32 msg_obj_no; -	struct c_can_priv *priv = netdev_priv(dev);  	struct can_frame *frame = (struct can_frame *)skb->data; +	struct c_can_priv *priv = netdev_priv(dev); +	u32 idx, obj;  	if (can_dropped_invalid_skb(dev, skb))  		return NETDEV_TX_OK; - -	msg_obj_no = get_tx_next_msg_obj(priv); - -	/* prepare message object for transmission */ -	c_can_write_msg_object(dev, 0, frame, msg_obj_no); -	can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); -  	/* -	 * we have to stop the queue in case of a wrap around or -	 * if the next TX message object is still in use +	 * This is not a FIFO. C/D_CAN sends out the buffers +	 * prioritized. The lowest buffer number wins.  	 */ -	priv->tx_next++; -	if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) || -			(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0) +	idx = fls(atomic_read(&priv->tx_active)); +	obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + +	/* If this is the last buffer, stop the xmit queue */ +	if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)  		netif_stop_queue(dev); +	/* +	 * Store the message in the interface so we can call +	 * can_put_echo_skb(). We must do this before we enable +	 * transmit as we might race against do_tx(). +	 */ +	c_can_setup_tx_object(dev, IF_TX, frame, idx); +	priv->dlc[idx] = frame->can_dlc; +	can_put_echo_skb(skb, dev, idx); + +	/* Update the active bits */ +	atomic_add((1 << idx), &priv->tx_active); +	/* Start transmission */ +	c_can_object_put(dev, IF_TX, obj, IF_COMM_TX);  	return NETDEV_TX_OK;  } +static int c_can_wait_for_ctrl_init(struct net_device *dev, +				    struct c_can_priv *priv, u32 init) +{ +	int retry = 0; + +	while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) { +		udelay(10); +		if (retry++ > 1000) { +			netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n"); +			return -EIO; +		} +	} +	return 0; +} +  static int c_can_set_bittiming(struct net_device *dev)  {  	unsigned int reg_btr, reg_brpe, ctrl_save; @@ -573,6 +488,7 @@ static int c_can_set_bittiming(struct net_device *dev)  	u32 ten_bit_brp;  	struct c_can_priv *priv = netdev_priv(dev);  	const struct can_bittiming *bt = &priv->can.bittiming; +	int res;  	/* c_can provides a 6-bit brp and 4-bit brpe fields */  	ten_bit_brp = bt->brp - 1; @@ -590,13 +506,17 @@ static int c_can_set_bittiming(struct net_device *dev)  		"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);  	ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG); -	priv->write_reg(priv, C_CAN_CTRL_REG, -			ctrl_save | CONTROL_CCE | CONTROL_INIT); +	ctrl_save &= ~CONTROL_INIT; +	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT); +	res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT); +	if (res) +		return res; +  	priv->write_reg(priv, C_CAN_BTR_REG, reg_btr);  	priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe);  	priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save); -	return 0; +	return c_can_wait_for_ctrl_init(dev, priv, 0);  }  /* @@ -614,15 +534,14 @@ static void c_can_configure_msg_objects(struct net_device *dev)  	/* first invalidate all message objects */  	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) -		c_can_inval_msg_object(dev, 0, i); +		c_can_inval_msg_object(dev, IF_RX, i);  	/* setup receive message objects */  	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) -		c_can_setup_receive_object(dev, 0, i, 0, 0, -			(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB); +		c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); -	c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0, -			IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK); +	c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0, +				   IF_MCONT_RCV_EOB);  }  /* @@ -631,35 +550,27 @@ static void c_can_configure_msg_objects(struct net_device *dev)   * - set operating mode   * - configure message objects   */ -static void c_can_chip_config(struct net_device *dev) +static int c_can_chip_config(struct net_device *dev)  {  	struct c_can_priv *priv = netdev_priv(dev);  	/* enable automatic retransmission */ -	priv->write_reg(priv, C_CAN_CTRL_REG, -			CONTROL_ENABLE_AR); +	priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);  	if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&  	    (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {  		/* loopback + silent mode : useful for hot self-test */ -		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | -				CONTROL_SIE | CONTROL_IE | CONTROL_TEST); -		priv->write_reg(priv, C_CAN_TEST_REG, -				TEST_LBACK | TEST_SILENT); +		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); +		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);  	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {  		/* loopback mode : useful for self-test function */ -		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | -				CONTROL_SIE | CONTROL_IE | CONTROL_TEST); +		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);  		priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);  	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {  		/* silent mode : bus-monitoring mode */ -		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | -				CONTROL_SIE | CONTROL_IE | CONTROL_TEST); +		priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);  		priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT); -	} else -		/* normal mode*/ -		priv->write_reg(priv, C_CAN_CTRL_REG, -				CONTROL_EIE | CONTROL_SIE | CONTROL_IE); +	}  	/* configure message objects */  	c_can_configure_msg_objects(dev); @@ -667,43 +578,54 @@ static void c_can_chip_config(struct net_device *dev)  	/* set a `lec` value so that we can check for updates later */  	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); +	/* Clear all internal status */ +	atomic_set(&priv->tx_active, 0); +	priv->rxmasked = 0; +	priv->tx_dir = 0; +  	/* set bittiming params */ -	c_can_set_bittiming(dev); +	return c_can_set_bittiming(dev);  } -static void c_can_start(struct net_device *dev) +static int c_can_start(struct net_device *dev)  {  	struct c_can_priv *priv = netdev_priv(dev); +	int err;  	/* basic c_can configuration */ -	c_can_chip_config(dev); +	err = c_can_chip_config(dev); +	if (err) +		return err; -	priv->can.state = CAN_STATE_ERROR_ACTIVE; +	/* Setup the command for new messages */ +	priv->comm_rcv_high = priv->type != BOSCH_D_CAN ? +		IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; -	/* reset tx helper pointers */ -	priv->tx_next = priv->tx_echo = 0; +	priv->can.state = CAN_STATE_ERROR_ACTIVE; -	/* enable status change, error and module interrupts */ -	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); +	return 0;  }  static void c_can_stop(struct net_device *dev)  {  	struct c_can_priv *priv = netdev_priv(dev); -	/* disable all interrupts */ -	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); - -	/* set the state as STOPPED */ +	c_can_irq_control(priv, false);  	priv->can.state = CAN_STATE_STOPPED;  }  static int c_can_set_mode(struct net_device *dev, enum can_mode mode)  { +	struct c_can_priv *priv = netdev_priv(dev); +	int err; +  	switch (mode) {  	case CAN_MODE_START: -		c_can_start(dev); +		err = c_can_start(dev); +		if (err) +			return err;  		netif_wake_queue(dev); +		c_can_irq_control(priv, true);  		break;  	default:  		return -EOPNOTSUPP; @@ -712,63 +634,153 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)  	return 0;  } -static int c_can_get_berr_counter(const struct net_device *dev, -					struct can_berr_counter *bec) +static int __c_can_get_berr_counter(const struct net_device *dev, +				    struct can_berr_counter *bec)  {  	unsigned int reg_err_counter;  	struct c_can_priv *priv = netdev_priv(dev); -	c_can_pm_runtime_get_sync(priv); -  	reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);  	bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>  				ERR_CNT_REC_SHIFT;  	bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; +	return 0; +} + +static int c_can_get_berr_counter(const struct net_device *dev, +				  struct can_berr_counter *bec) +{ +	struct c_can_priv *priv = netdev_priv(dev); +	int err; + +	c_can_pm_runtime_get_sync(priv); +	err = __c_can_get_berr_counter(dev, bec);  	c_can_pm_runtime_put_sync(priv); -	return 0; +	return err;  } -/* - * theory of operation: - * - * priv->tx_echo holds the number of the oldest can_frame put for - * transmission into the hardware, but not yet ACKed by the CAN tx - * complete IRQ. - * - * We iterate from priv->tx_echo to priv->tx_next and check if the - * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted packet, stop looking for more. - */  static void c_can_do_tx(struct net_device *dev)  { -	u32 val; -	u32 msg_obj_no;  	struct c_can_priv *priv = netdev_priv(dev);  	struct net_device_stats *stats = &dev->stats; +	u32 idx, obj, pkts = 0, bytes = 0, pend, clr; + +	clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); + +	while ((idx = ffs(pend))) { +		idx--; +		pend &= ~(1 << idx); +		obj = idx + C_CAN_MSG_OBJ_TX_FIRST; +		c_can_inval_tx_object(dev, IF_RX, obj); +		can_get_echo_skb(dev, idx); +		bytes += priv->dlc[idx]; +		pkts++; +	} -	for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { -		msg_obj_no = get_tx_echo_msg_obj(priv); -		val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); -		if (!(val & (1 << (msg_obj_no - 1)))) { -			can_get_echo_skb(dev, -					msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); -			stats->tx_bytes += priv->read_reg(priv, -					C_CAN_IFACE(MSGCTRL_REG, 0)) -					& IF_MCONT_DLC_MASK; -			stats->tx_packets++; -			can_led_event(dev, CAN_LED_EVENT_TX); -			c_can_inval_msg_object(dev, 0, msg_obj_no); -		} else { -			break; +	/* Clear the bits in the tx_active mask */ +	atomic_sub(clr, &priv->tx_active); + +	if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) +		netif_wake_queue(dev); + +	if (pkts) { +		stats->tx_bytes += bytes; +		stats->tx_packets += pkts; +		can_led_event(dev, CAN_LED_EVENT_TX); +	} +} + +/* + * If we have a gap in the pending bits, that means we either + * raced with the hardware or failed to readout all upper + * objects in the last run due to quota limit. + */ +static u32 c_can_adjust_pending(u32 pend) +{ +	u32 weight, lasts; + +	if (pend == RECEIVE_OBJECT_BITS) +		return pend; + +	/* +	 * If the last set bit is larger than the number of pending +	 * bits we have a gap. +	 */ +	weight = hweight32(pend); +	lasts = fls(pend); + +	/* If the bits are linear, nothing to do */ +	if (lasts == weight) +		return pend; + +	/* +	 * Find the first set bit after the gap. We walk backwards +	 * from the last set bit. +	 */ +	for (lasts--; pend & (1 << (lasts - 1)); lasts--); + +	return pend & ~((1 << lasts) - 1); +} + +static inline void c_can_rx_object_get(struct net_device *dev, +				       struct c_can_priv *priv, u32 obj) +{ +		c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high); +} + +static inline void c_can_rx_finalize(struct net_device *dev, +				     struct c_can_priv *priv, u32 obj) +{ +	if (priv->type != BOSCH_D_CAN) +		c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT); +} + +static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, +			      u32 pend, int quota) +{ +	u32 pkts = 0, ctrl, obj; + +	while ((obj = ffs(pend)) && quota > 0) { +		pend &= ~BIT(obj - 1); + +		c_can_rx_object_get(dev, priv, obj); +		ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); + +		if (ctrl & IF_MCONT_MSGLST) { +			int n = c_can_handle_lost_msg_obj(dev, IF_RX, obj, ctrl); + +			pkts += n; +			quota -= n; +			continue;  		} + +		/* +		 * This really should not happen, but this covers some +		 * odd HW behaviour. Do not remove that unless you +		 * want to brick your machine. +		 */ +		if (!(ctrl & IF_MCONT_NEWDAT)) +			continue; + +		/* read the data from the message object */ +		c_can_read_msg_object(dev, IF_RX, ctrl); + +		c_can_rx_finalize(dev, priv, obj); + +		pkts++; +		quota--;  	} -	/* restart queue if wrap-up or if queue stalled on last pkt */ -	if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) || -			((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) -		netif_wake_queue(dev); +	return pkts; +} + +static inline u32 c_can_get_pending(struct c_can_priv *priv) +{ +	u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); + +	return pend;  }  /* @@ -780,80 +792,47 @@ static void c_can_do_tx(struct net_device *dev)   * has arrived. To work-around this issue, we keep two groups of message   * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.   * - * To ensure in-order frame reception we use the following - * approach while re-activating a message object to receive further - * frames: - * - if the current message object number is lower than - *   C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing - *   the INTPND bit. - * - if the current message object number is equal to - *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower - *   receive message objects. - * - if the current message object number is greater than - *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of - *   only this message object. + * We clear the newdat bit right away. + * + * This can result in packet reordering when the readout is slow.   */  static int c_can_do_rx_poll(struct net_device *dev, int quota)  { -	u32 num_rx_pkts = 0; -	unsigned int msg_obj, msg_ctrl_save;  	struct c_can_priv *priv = netdev_priv(dev); -	u32 val = c_can_read_reg32(priv, C_CAN_INTPND1_REG); +	u32 pkts = 0, pend = 0, toread, n; -	for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST; -			msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0; -			val = c_can_read_reg32(priv, C_CAN_INTPND1_REG), -			msg_obj++) { -		/* -		 * as interrupt pending register's bit n-1 corresponds to -		 * message object n, we need to handle the same properly. -		 */ -		if (val & (1 << (msg_obj - 1))) { -			c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL & -					~IF_COMM_TXRQST); -			msg_ctrl_save = priv->read_reg(priv, -					C_CAN_IFACE(MSGCTRL_REG, 0)); - -			if (msg_ctrl_save & IF_MCONT_EOB) -				return num_rx_pkts; - -			if (msg_ctrl_save & IF_MCONT_MSGLST) { -				c_can_handle_lost_msg_obj(dev, 0, msg_obj); -				num_rx_pkts++; -				quota--; -				continue; -			} - -			if (!(msg_ctrl_save & IF_MCONT_NEWDAT)) -				continue; - -			/* read the data from the message object */ -			c_can_read_msg_object(dev, 0, msg_ctrl_save); - -			if (msg_obj < C_CAN_MSG_RX_LOW_LAST) -				c_can_mark_rx_msg_obj(dev, 0, -						msg_ctrl_save, msg_obj); -			else if (msg_obj > C_CAN_MSG_RX_LOW_LAST) -				/* activate this msg obj */ -				c_can_activate_rx_msg_obj(dev, 0, -						msg_ctrl_save, msg_obj); -			else if (msg_obj == C_CAN_MSG_RX_LOW_LAST) -				/* activate all lower message objects */ -				c_can_activate_all_lower_rx_msg_obj(dev, -						0, msg_ctrl_save); - -			num_rx_pkts++; -			quota--; +	/* +	 * It is faster to read only one 16bit register. This is only possible +	 * for a maximum number of 16 objects. +	 */ +	BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, +			"Implementation does not support more message objects than 16"); + +	while (quota > 0) { +		if (!pend) { +			pend = c_can_get_pending(priv); +			if (!pend) +				break; +			/* +			 * If the pending field has a gap, handle the +			 * bits above the gap first. +			 */ +			toread = c_can_adjust_pending(pend); +		} else { +			toread = pend;  		} +		/* Remove the bits from pend */ +		pend &= ~toread; +		/* Read the objects */ +		n = c_can_read_objects(dev, priv, toread, quota); +		pkts += n; +		quota -= n;  	} -	return num_rx_pkts; -} +	if (pkts) +		can_led_event(dev, CAN_LED_EVENT_RX); -static inline int c_can_has_and_handle_berr(struct c_can_priv *priv) -{ -	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && -		(priv->current_status & LEC_UNUSED); +	return pkts;  }  static int c_can_handle_state_change(struct net_device *dev, @@ -867,12 +846,32 @@ static int c_can_handle_state_change(struct net_device *dev,  	struct sk_buff *skb;  	struct can_berr_counter bec; +	switch (error_type) { +	case C_CAN_ERROR_WARNING: +		/* error warning state */ +		priv->can.can_stats.error_warning++; +		priv->can.state = CAN_STATE_ERROR_WARNING; +		break; +	case C_CAN_ERROR_PASSIVE: +		/* error passive state */ +		priv->can.can_stats.error_passive++; +		priv->can.state = CAN_STATE_ERROR_PASSIVE; +		break; +	case C_CAN_BUS_OFF: +		/* bus-off state */ +		priv->can.state = CAN_STATE_BUS_OFF; +		can_bus_off(dev); +		break; +	default: +		break; +	} +  	/* propagate the error condition to the CAN stack */  	skb = alloc_can_err_skb(dev, &cf);  	if (unlikely(!skb))  		return 0; -	c_can_get_berr_counter(dev, &bec); +	__c_can_get_berr_counter(dev, &bec);  	reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);  	rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>  				ERR_CNT_RP_SHIFT; @@ -880,8 +879,6 @@ static int c_can_handle_state_change(struct net_device *dev,  	switch (error_type) {  	case C_CAN_ERROR_WARNING:  		/* error warning state */ -		priv->can.can_stats.error_warning++; -		priv->can.state = CAN_STATE_ERROR_WARNING;  		cf->can_id |= CAN_ERR_CRTL;  		cf->data[1] = (bec.txerr > bec.rxerr) ?  			CAN_ERR_CRTL_TX_WARNING : @@ -892,8 +889,6 @@ static int c_can_handle_state_change(struct net_device *dev,  		break;  	case C_CAN_ERROR_PASSIVE:  		/* error passive state */ -		priv->can.can_stats.error_passive++; -		priv->can.state = CAN_STATE_ERROR_PASSIVE;  		cf->can_id |= CAN_ERR_CRTL;  		if (rx_err_passive)  			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; @@ -905,22 +900,16 @@ static int c_can_handle_state_change(struct net_device *dev,  		break;  	case C_CAN_BUS_OFF:  		/* bus-off state */ -		priv->can.state = CAN_STATE_BUS_OFF;  		cf->can_id |= CAN_ERR_BUSOFF; -		/* -		 * disable all interrupts in bus-off mode to ensure that -		 * the CPU is not hogged down -		 */ -		c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);  		can_bus_off(dev);  		break;  	default:  		break;  	} -	netif_receive_skb(skb);  	stats->rx_packets++;  	stats->rx_bytes += cf->can_dlc; +	netif_receive_skb(skb);  	return 1;  } @@ -941,6 +930,13 @@ static int c_can_handle_bus_err(struct net_device *dev,  	if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)  		return 0; +	if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) +		return 0; + +	/* common for all type of bus errors */ +	priv->can.can_stats.bus_error++; +	stats->rx_errors++; +  	/* propagate the error condition to the CAN stack */  	skb = alloc_can_err_skb(dev, &cf);  	if (unlikely(!skb)) @@ -950,10 +946,6 @@ static int c_can_handle_bus_err(struct net_device *dev,  	 * check for 'last error code' which tells us the  	 * type of the last error to occur on the CAN bus  	 */ - -	/* common for all type of bus errors */ -	priv->can.can_stats.bus_error++; -	stats->rx_errors++;  	cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;  	cf->data[2] |= CAN_ERR_PROT_UNSPEC; @@ -988,95 +980,64 @@ static int c_can_handle_bus_err(struct net_device *dev,  		break;  	} -	/* set a `lec` value so that we can check for updates later */ -	priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); - -	netif_receive_skb(skb);  	stats->rx_packets++;  	stats->rx_bytes += cf->can_dlc; - +	netif_receive_skb(skb);  	return 1;  }  static int c_can_poll(struct napi_struct *napi, int quota)  { -	u16 irqstatus; -	int lec_type = 0; -	int work_done = 0;  	struct net_device *dev = napi->dev;  	struct c_can_priv *priv = netdev_priv(dev); +	u16 curr, last = priv->last_status; +	int work_done = 0; -	irqstatus = priv->irqstatus; -	if (!irqstatus) -		goto end; +	priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); +	/* Ack status on C_CAN. D_CAN is self clearing */ +	if (priv->type != BOSCH_D_CAN) +		priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); -	/* status events have the highest priority */ -	if (irqstatus == STATUS_INTERRUPT) { -		priv->current_status = priv->read_reg(priv, -					C_CAN_STS_REG); - -		/* handle Tx/Rx events */ -		if (priv->current_status & STATUS_TXOK) -			priv->write_reg(priv, C_CAN_STS_REG, -					priv->current_status & ~STATUS_TXOK); - -		if (priv->current_status & STATUS_RXOK) -			priv->write_reg(priv, C_CAN_STS_REG, -					priv->current_status & ~STATUS_RXOK); - -		/* handle state changes */ -		if ((priv->current_status & STATUS_EWARN) && -				(!(priv->last_status & STATUS_EWARN))) { -			netdev_dbg(dev, "entered error warning state\n"); -			work_done += c_can_handle_state_change(dev, -						C_CAN_ERROR_WARNING); -		} -		if ((priv->current_status & STATUS_EPASS) && -				(!(priv->last_status & STATUS_EPASS))) { -			netdev_dbg(dev, "entered error passive state\n"); -			work_done += c_can_handle_state_change(dev, -						C_CAN_ERROR_PASSIVE); -		} -		if ((priv->current_status & STATUS_BOFF) && -				(!(priv->last_status & STATUS_BOFF))) { -			netdev_dbg(dev, "entered bus off state\n"); -			work_done += c_can_handle_state_change(dev, -						C_CAN_BUS_OFF); -		} +	/* handle state changes */ +	if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { +		netdev_dbg(dev, "entered error warning state\n"); +		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); +	} -		/* handle bus recovery events */ -		if ((!(priv->current_status & STATUS_BOFF)) && -				(priv->last_status & STATUS_BOFF)) { -			netdev_dbg(dev, "left bus off state\n"); -			priv->can.state = CAN_STATE_ERROR_ACTIVE; -		} -		if ((!(priv->current_status & STATUS_EPASS)) && -				(priv->last_status & STATUS_EPASS)) { -			netdev_dbg(dev, "left error passive state\n"); -			priv->can.state = CAN_STATE_ERROR_ACTIVE; -		} +	if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { +		netdev_dbg(dev, "entered error passive state\n"); +		work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); +	} -		priv->last_status = priv->current_status; - -		/* handle lec errors on the bus */ -		lec_type = c_can_has_and_handle_berr(priv); -		if (lec_type) -			work_done += c_can_handle_bus_err(dev, lec_type); -	} else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) && -			(irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) { -		/* handle events corresponding to receive message objects */ -		work_done += c_can_do_rx_poll(dev, (quota - work_done)); -	} else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) && -			(irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) { -		/* handle events corresponding to transmit message objects */ -		c_can_do_tx(dev); +	if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { +		netdev_dbg(dev, "entered bus off state\n"); +		work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); +		goto end; +	} + +	/* handle bus recovery events */ +	if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { +		netdev_dbg(dev, "left bus off state\n"); +		priv->can.state = CAN_STATE_ERROR_ACTIVE;  	} +	if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { +		netdev_dbg(dev, "left error passive state\n"); +		priv->can.state = CAN_STATE_ERROR_ACTIVE; +	} + +	/* handle lec errors on the bus */ +	work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); + +	/* Handle Tx/Rx events. We do this unconditionally */ +	work_done += c_can_do_rx_poll(dev, (quota - work_done)); +	c_can_do_tx(dev);  end:  	if (work_done < quota) {  		napi_complete(napi); -		/* enable all IRQs */ -		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); +		/* enable all IRQs if we are not in bus off state */ +		if (priv->can.state != CAN_STATE_BUS_OFF) +			c_can_irq_control(priv, true);  	}  	return work_done; @@ -1087,12 +1048,11 @@ static irqreturn_t c_can_isr(int irq, void *dev_id)  	struct net_device *dev = (struct net_device *)dev_id;  	struct c_can_priv *priv = netdev_priv(dev); -	priv->irqstatus = priv->read_reg(priv, C_CAN_INT_REG); -	if (!priv->irqstatus) +	if (!priv->read_reg(priv, C_CAN_INT_REG))  		return IRQ_NONE;  	/* disable all interrupts and schedule the NAPI */ -	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); +	c_can_irq_control(priv, false);  	napi_schedule(&priv->napi);  	return IRQ_HANDLED; @@ -1121,17 +1081,22 @@ static int c_can_open(struct net_device *dev)  		goto exit_irq_fail;  	} -	napi_enable(&priv->napi); +	/* start the c_can controller */ +	err = c_can_start(dev); +	if (err) +		goto exit_start_fail;  	can_led_event(dev, CAN_LED_EVENT_OPEN); -	/* start the c_can controller */ -	c_can_start(dev); - +	napi_enable(&priv->napi); +	/* enable status change, error and module interrupts */ +	c_can_irq_control(priv, true);  	netif_start_queue(dev);  	return 0; +exit_start_fail: +	free_irq(dev->irq, dev);  exit_irq_fail:  	close_candev(dev);  exit_open_fail: @@ -1222,6 +1187,7 @@ int c_can_power_up(struct net_device *dev)  	u32 val;  	unsigned long time_out;  	struct c_can_priv *priv = netdev_priv(dev); +	int ret;  	if (!(dev->flags & IFF_UP))  		return 0; @@ -1248,15 +1214,20 @@ int c_can_power_up(struct net_device *dev)  	if (time_after(jiffies, time_out))  		return -ETIMEDOUT; -	c_can_start(dev); +	ret = c_can_start(dev); +	if (!ret) +		c_can_irq_control(priv, true); -	return 0; +	return ret;  }  EXPORT_SYMBOL_GPL(c_can_power_up);  #endif  void free_c_can_dev(struct net_device *dev)  { +	struct c_can_priv *priv = netdev_priv(dev); + +	netif_napi_del(&priv->napi);  	free_candev(dev);  }  EXPORT_SYMBOL_GPL(free_c_can_dev); @@ -1265,6 +1236,7 @@ static const struct net_device_ops c_can_netdev_ops = {  	.ndo_open = c_can_open,  	.ndo_stop = c_can_close,  	.ndo_start_xmit = c_can_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  int register_c_can_dev(struct net_device *dev) diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index d2e1c21b143..99ad1aa576b 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -22,6 +22,23 @@  #ifndef C_CAN_H  #define C_CAN_H +/* message object split */ +#define C_CAN_NO_OF_OBJECTS	32 +#define C_CAN_MSG_OBJ_RX_NUM	16 +#define C_CAN_MSG_OBJ_TX_NUM	16 + +#define C_CAN_MSG_OBJ_RX_FIRST	1 +#define C_CAN_MSG_OBJ_RX_LAST	(C_CAN_MSG_OBJ_RX_FIRST + \ +				C_CAN_MSG_OBJ_RX_NUM - 1) + +#define C_CAN_MSG_OBJ_TX_FIRST	(C_CAN_MSG_OBJ_RX_LAST + 1) +#define C_CAN_MSG_OBJ_TX_LAST	(C_CAN_MSG_OBJ_TX_FIRST + \ +				C_CAN_MSG_OBJ_TX_NUM - 1) + +#define C_CAN_MSG_OBJ_RX_SPLIT	9 +#define C_CAN_MSG_RX_LOW_LAST	(C_CAN_MSG_OBJ_RX_SPLIT - 1) +#define RECEIVE_OBJECT_BITS	0x0000ffff +  enum reg {  	C_CAN_CTRL_REG = 0,  	C_CAN_CTRL_EX_REG, @@ -61,6 +78,7 @@ enum reg {  	C_CAN_INTPND2_REG,  	C_CAN_MSGVAL1_REG,  	C_CAN_MSGVAL2_REG, +	C_CAN_FUNCTION_REG,  };  static const u16 reg_map_c_can[] = { @@ -112,6 +130,7 @@ static const u16 reg_map_d_can[] = {  	[C_CAN_BRPEXT_REG]	= 0x0E,  	[C_CAN_INT_REG]		= 0x10,  	[C_CAN_TEST_REG]	= 0x14, +	[C_CAN_FUNCTION_REG]	= 0x18,  	[C_CAN_TXRQST1_REG]	= 0x88,  	[C_CAN_TXRQST2_REG]	= 0x8A,  	[C_CAN_NEWDAT1_REG]	= 0x9C, @@ -156,22 +175,23 @@ struct c_can_priv {  	struct napi_struct napi;  	struct net_device *dev;  	struct device *device; -	int tx_object; -	int current_status; +	atomic_t tx_active; +	unsigned long tx_dir;  	int last_status; -	u16 (*read_reg) (struct c_can_priv *priv, enum reg index); -	void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val); +	u16 (*read_reg) (const struct c_can_priv *priv, enum reg index); +	void (*write_reg) (const struct c_can_priv *priv, enum reg index, u16 val); +	u32 (*read_reg32) (const struct c_can_priv *priv, enum reg index); +	void (*write_reg32) (const struct c_can_priv *priv, enum reg index, u32 val);  	void __iomem *base;  	const u16 *regs; -	unsigned long irq_flags; /* for request_irq() */ -	unsigned int tx_next; -	unsigned int tx_echo;  	void *priv;		/* for board-specific data */ -	u16 irqstatus;  	enum c_can_dev_id type;  	u32 __iomem *raminit_ctrlreg; -	unsigned int instance; +	int instance;  	void (*raminit) (const struct c_can_priv *priv, bool enable); +	u32 comm_rcv_high; +	u32 rxmasked; +	u32 dlc[C_CAN_MSG_OBJ_TX_NUM];  };  struct net_device *alloc_c_can_dev(void); diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index b374be7891a..5d11e0e4225 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -19,9 +19,13 @@  #include "c_can.h" +#define PCI_DEVICE_ID_PCH_CAN	0x8818 +#define PCH_PCI_SOFT_RESET	0x01fc +  enum c_can_pci_reg_align {  	C_CAN_REG_ALIGN_16,  	C_CAN_REG_ALIGN_32, +	C_CAN_REG_32,  };  struct c_can_pci_data { @@ -31,6 +35,10 @@ struct c_can_pci_data {  	enum c_can_pci_reg_align reg_align;  	/* Set the frequency */  	unsigned int freq; +	/* PCI bar number */ +	int bar; +	/* Callback for reset */ +	void (*init)(const struct c_can_priv *priv, bool enable);  };  /* @@ -39,30 +47,70 @@ struct c_can_pci_data {   * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.   * Handle the same by providing a common read/write interface.   */ -static u16 c_can_pci_read_reg_aligned_to_16bit(struct c_can_priv *priv, +static u16 c_can_pci_read_reg_aligned_to_16bit(const struct c_can_priv *priv,  						enum reg index)  {  	return readw(priv->base + priv->regs[index]);  } -static void c_can_pci_write_reg_aligned_to_16bit(struct c_can_priv *priv, +static void c_can_pci_write_reg_aligned_to_16bit(const struct c_can_priv *priv,  						enum reg index, u16 val)  {  	writew(val, priv->base + priv->regs[index]);  } -static u16 c_can_pci_read_reg_aligned_to_32bit(struct c_can_priv *priv, +static u16 c_can_pci_read_reg_aligned_to_32bit(const struct c_can_priv *priv,  						enum reg index)  {  	return readw(priv->base + 2 * priv->regs[index]);  } -static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv, +static void c_can_pci_write_reg_aligned_to_32bit(const struct c_can_priv *priv,  						enum reg index, u16 val)  {  	writew(val, priv->base + 2 * priv->regs[index]);  } +static u16 c_can_pci_read_reg_32bit(const struct c_can_priv *priv, +				    enum reg index) +{ +	return (u16)ioread32(priv->base + 2 * priv->regs[index]); +} + +static void c_can_pci_write_reg_32bit(const struct c_can_priv *priv, +				      enum reg index, u16 val) +{ +	iowrite32((u32)val, priv->base + 2 * priv->regs[index]); +} + +static u32 c_can_pci_read_reg32(const struct c_can_priv *priv, enum reg index) +{ +	u32 val; + +	val = priv->read_reg(priv, index); +	val |= ((u32) priv->read_reg(priv, index + 1)) << 16; + +	return val; +} + +static void c_can_pci_write_reg32(const struct c_can_priv *priv, enum reg index, +		u32 val) +{ +	priv->write_reg(priv, index + 1, val >> 16); +	priv->write_reg(priv, index, val); +} + +static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable) +{ +	if (enable) { +		u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET; + +		/* write to sw reset register */ +		iowrite32(1, addr); +		iowrite32(0, addr); +	} +} +  static int c_can_pci_probe(struct pci_dev *pdev,  			   const struct pci_device_id *ent)  { @@ -84,10 +132,14 @@ static int c_can_pci_probe(struct pci_dev *pdev,  		goto out_disable_device;  	} -	pci_set_master(pdev); -	pci_enable_msi(pdev); +	ret = pci_enable_msi(pdev); +	if (!ret) { +		dev_info(&pdev->dev, "MSI enabled\n"); +		pci_set_master(pdev); +	} -	addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); +	addr = pci_iomap(pdev, c_can_pci_data->bar, +			 pci_resource_len(pdev, c_can_pci_data->bar));  	if (!addr) {  		dev_err(&pdev->dev,  			"device has no PCI memory resources, " @@ -132,6 +184,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,  		goto out_free_c_can;  	} +	priv->type = c_can_pci_data->type; +  	/* Configure access to registers */  	switch (c_can_pci_data->reg_align) {  	case C_CAN_REG_ALIGN_32: @@ -142,10 +196,18 @@ static int c_can_pci_probe(struct pci_dev *pdev,  		priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;  		priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;  		break; +	case C_CAN_REG_32: +		priv->read_reg = c_can_pci_read_reg_32bit; +		priv->write_reg = c_can_pci_write_reg_32bit; +		break;  	default:  		ret = -EINVAL;  		goto out_free_c_can;  	} +	priv->read_reg32 = c_can_pci_read_reg32; +	priv->write_reg32 = c_can_pci_write_reg32; + +	priv->raminit = c_can_pci_data->init;  	ret = register_c_can_dev(dev);  	if (ret) { @@ -160,7 +222,6 @@ static int c_can_pci_probe(struct pci_dev *pdev,  	return 0;  out_free_c_can: -	pci_set_drvdata(pdev, NULL);  	free_c_can_dev(dev);  out_iounmap:  	pci_iounmap(pdev, addr); @@ -181,7 +242,6 @@ static void c_can_pci_remove(struct pci_dev *pdev)  	unregister_c_can_dev(dev); -	pci_set_drvdata(pdev, NULL);  	free_c_can_dev(dev);  	pci_iounmap(pdev, priv->base); @@ -195,6 +255,15 @@ static struct c_can_pci_data c_can_sta2x11= {  	.type = BOSCH_C_CAN,  	.reg_align = C_CAN_REG_ALIGN_32,  	.freq = 52000000, /* 52 Mhz */ +	.bar = 0, +}; + +static struct c_can_pci_data c_can_pch = { +	.type = BOSCH_C_CAN, +	.reg_align = C_CAN_REG_32, +	.freq = 50000000, /* 50 MHz */ +	.init = c_can_pci_reset_pch, +	.bar = 1,  };  #define C_CAN_ID(_vend, _dev, _driverdata) {		\ @@ -204,6 +273,8 @@ static struct c_can_pci_data c_can_sta2x11= {  static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {  	C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,  		 c_can_sta2x11), +	C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN, +		 c_can_pch),  	{},  };  static struct pci_driver c_can_pci_driver = { diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 294ced3cc22..12430be6448 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -37,48 +37,126 @@  #include "c_can.h" -#define CAN_RAMINIT_START_MASK(i)	(1 << (i)) - +#define CAN_RAMINIT_START_MASK(i)	(0x001 << (i)) +#define CAN_RAMINIT_DONE_MASK(i)	(0x100 << (i)) +#define CAN_RAMINIT_ALL_MASK(i)		(0x101 << (i)) +#define DCAN_RAM_INIT_BIT		(1 << 3) +static DEFINE_SPINLOCK(raminit_lock);  /*   * 16-bit c_can registers can be arranged differently in the memory   * architecture of different implementations. For example: 16-bit   * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.   * Handle the same by providing a common read/write interface.   */ -static u16 c_can_plat_read_reg_aligned_to_16bit(struct c_can_priv *priv, +static u16 c_can_plat_read_reg_aligned_to_16bit(const struct c_can_priv *priv,  						enum reg index)  {  	return readw(priv->base + priv->regs[index]);  } -static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv *priv, +static void c_can_plat_write_reg_aligned_to_16bit(const struct c_can_priv *priv,  						enum reg index, u16 val)  {  	writew(val, priv->base + priv->regs[index]);  } -static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv *priv, +static u16 c_can_plat_read_reg_aligned_to_32bit(const struct c_can_priv *priv,  						enum reg index)  {  	return readw(priv->base + 2 * priv->regs[index]);  } -static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, +static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv,  						enum reg index, u16 val)  {  	writew(val, priv->base + 2 * priv->regs[index]);  } -static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) +static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask, +				  u32 val) +{ +	/* We look only at the bits of our instance. */ +	val &= mask; +	while ((readl(priv->raminit_ctrlreg) & mask) != val) +		udelay(1); +} + +static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) +{ +	u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); +	u32 ctrl; + +	spin_lock(&raminit_lock); + +	ctrl = readl(priv->raminit_ctrlreg); +	/* We clear the done and start bit first. The start bit is +	 * looking at the 0 -> transition, but is not self clearing; +	 * And we clear the init done bit as well. +	 */ +	ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance); +	ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); +	writel(ctrl, priv->raminit_ctrlreg); +	ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); +	c_can_hw_raminit_wait_ti(priv, ctrl, mask); + +	if (enable) { +		/* Set start bit and wait for the done bit. */ +		ctrl |= CAN_RAMINIT_START_MASK(priv->instance); +		writel(ctrl, priv->raminit_ctrlreg); +		ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); +		c_can_hw_raminit_wait_ti(priv, ctrl, mask); +	} +	spin_unlock(&raminit_lock); +} + +static u32 c_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index)  {  	u32 val; -	val = readl(priv->raminit_ctrlreg); -	if (enable) -		val |= CAN_RAMINIT_START_MASK(priv->instance); -	else -		val &= ~CAN_RAMINIT_START_MASK(priv->instance); -	writel(val, priv->raminit_ctrlreg); +	val = priv->read_reg(priv, index); +	val |= ((u32) priv->read_reg(priv, index + 1)) << 16; + +	return val; +} + +static void c_can_plat_write_reg32(const struct c_can_priv *priv, enum reg index, +		u32 val) +{ +	priv->write_reg(priv, index + 1, val >> 16); +	priv->write_reg(priv, index, val); +} + +static u32 d_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index) +{ +	return readl(priv->base + priv->regs[index]); +} + +static void d_can_plat_write_reg32(const struct c_can_priv *priv, enum reg index, +		u32 val) +{ +	writel(val, priv->base + priv->regs[index]); +} + +static void c_can_hw_raminit_wait(const struct c_can_priv *priv, u32 mask) +{ +	while (priv->read_reg32(priv, C_CAN_FUNCTION_REG) & mask) +		udelay(1); +} + +static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) +{ +	u32 ctrl; + +	ctrl = priv->read_reg32(priv, C_CAN_FUNCTION_REG); +	ctrl &= ~DCAN_RAM_INIT_BIT; +	priv->write_reg32(priv, C_CAN_FUNCTION_REG, ctrl); +	c_can_hw_raminit_wait(priv, ctrl); + +	if (enable) { +		ctrl |= DCAN_RAM_INIT_BIT; +		priv->write_reg32(priv, C_CAN_FUNCTION_REG, ctrl); +		c_can_hw_raminit_wait(priv, ctrl); +	}  }  static struct platform_device_id c_can_id_table[] = { @@ -174,11 +252,15 @@ static int c_can_plat_probe(struct platform_device *pdev)  		case IORESOURCE_MEM_32BIT:  			priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;  			priv->write_reg = c_can_plat_write_reg_aligned_to_32bit; +			priv->read_reg32 = c_can_plat_read_reg32; +			priv->write_reg32 = c_can_plat_write_reg32;  			break;  		case IORESOURCE_MEM_16BIT:  		default:  			priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;  			priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; +			priv->read_reg32 = c_can_plat_read_reg32; +			priv->write_reg32 = c_can_plat_write_reg32;  			break;  		}  		break; @@ -187,6 +269,8 @@ static int c_can_plat_probe(struct platform_device *pdev)  		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;  		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;  		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; +		priv->read_reg32 = d_can_plat_read_reg32; +		priv->write_reg32 = d_can_plat_write_reg32;  		if (pdev->dev.of_node)  			priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); @@ -194,11 +278,21 @@ static int c_can_plat_probe(struct platform_device *pdev)  			priv->instance = pdev->id;  		res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -		priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); -		if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0) +		/* Not all D_CAN modules have a separate register for the D_CAN +		 * RAM initialization. Use default RAM init bit in D_CAN module +		 * if not specified in DT. +		 */ +		if (!res) { +			priv->raminit = c_can_hw_raminit; +			break; +		} + +		priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start, +						     resource_size(res)); +		if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)  			dev_info(&pdev->dev, "control memory is not used for raminit\n");  		else -			priv->raminit = c_can_hw_raminit; +			priv->raminit = c_can_hw_raminit_ti;  		break;  	default:  		ret = -EINVAL; @@ -322,7 +416,7 @@ static struct platform_driver c_can_plat_driver = {  	.driver = {  		.name = KBUILD_MODNAME,  		.owner = THIS_MODULE, -		.of_match_table = of_match_ptr(c_can_of_table), +		.of_match_table = c_can_of_table,  	},  	.probe = c_can_plat_probe,  	.remove = c_can_plat_remove, diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index 0f12abf6591..d8379278d64 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -823,6 +823,7 @@ static const struct net_device_ops cc770_netdev_ops = {  	.ndo_open = cc770_open,  	.ndo_stop = cc770_close,  	.ndo_start_xmit = cc770_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  int register_cc770dev(struct net_device *dev) diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 034bdd816a6..ad76734b3ec 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -152,7 +152,7 @@ static int cc770_get_platform_data(struct platform_device *pdev,  				   struct cc770_priv *priv)  { -	struct cc770_platform_data *pdata = pdev->dev.platform_data; +	struct cc770_platform_data *pdata = dev_get_platdata(&pdev->dev);  	priv->can.clock.freq = pdata->osc_freq;  	if (priv->cpu_interface & CPUIF_DSC) @@ -203,7 +203,7 @@ static int cc770_platform_probe(struct platform_device *pdev)  	if (pdev->dev.of_node)  		err = cc770_get_of_node_data(pdev, priv); -	else if (pdev->dev.platform_data) +	else if (dev_get_platdata(&pdev->dev))  		err = cc770_get_platform_data(pdev, priv);  	else  		err = -ENODEV; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index f9cba4123c6..e318e87e2bf 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -13,8 +13,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/module.h> @@ -100,10 +99,10 @@ static int can_update_spt(const struct can_bittiming_const *btc,  	return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);  } -static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt) +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, +			      const struct can_bittiming_const *btc)  {  	struct can_priv *priv = netdev_priv(dev); -	const struct can_bittiming_const *btc = priv->bittiming_const;  	long rate, best_rate = 0;  	long best_error = 1000000000, error = 0;  	int best_tseg = 0, best_brp = 0, brp = 0; @@ -111,9 +110,6 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)  	int spt_error = 1000, spt = 0, sampl_pt;  	u64 v64; -	if (!priv->bittiming_const) -		return -ENOTSUPP; -  	/* Use CIA recommended sample points */  	if (bt->sample_point) {  		sampl_pt = bt->sample_point; @@ -205,7 +201,8 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)  	return 0;  }  #else /* !CONFIG_CAN_CALC_BITTIMING */ -static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt) +static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, +			      const struct can_bittiming_const *btc)  {  	netdev_err(dev, "bit-timing calculation not available\n");  	return -EINVAL; @@ -218,16 +215,13 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)   * prescaler value brp. You can find more information in the header   * file linux/can/netlink.h.   */ -static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt) +static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, +			       const struct can_bittiming_const *btc)  {  	struct can_priv *priv = netdev_priv(dev); -	const struct can_bittiming_const *btc = priv->bittiming_const;  	int tseg1, alltseg;  	u64 brp64; -	if (!priv->bittiming_const) -		return -ENOTSUPP; -  	tseg1 = bt->prop_seg + bt->phase_seg1;  	if (!bt->sjw)  		bt->sjw = 1; @@ -255,26 +249,29 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt)  	return 0;  } -static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt) +static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, +			     const struct can_bittiming_const *btc)  { -	struct can_priv *priv = netdev_priv(dev);  	int err;  	/* Check if the CAN device has bit-timing parameters */ -	if (priv->bittiming_const) { +	if (!btc) +		return -EOPNOTSUPP; -		/* Non-expert mode? Check if the bitrate has been pre-defined */ -		if (!bt->tq) -			/* Determine bit-timing parameters */ -			err = can_calc_bittiming(dev, bt); -		else -			/* Check bit-timing params and calculate proper brp */ -			err = can_fixup_bittiming(dev, bt); -		if (err) -			return err; -	} +	/* +	 * Depending on the given can_bittiming parameter structure the CAN +	 * timing parameters are calculated based on the provided bitrate OR +	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are +	 * provided directly which are then checked and fixed up. +	 */ +	if (!bt->tq && bt->bitrate) +		err = can_calc_bittiming(dev, bt, btc); +	else if (bt->tq && !bt->bitrate) +		err = can_fixup_bittiming(dev, bt, btc); +	else +		err = -EINVAL; -	return 0; +	return err;  }  /* @@ -318,28 +315,20 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,  	BUG_ON(idx >= priv->echo_skb_max);  	/* check flag whether this packet has to be looped back */ -	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { +	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK || +	    (skb->protocol != htons(ETH_P_CAN) && +	     skb->protocol != htons(ETH_P_CANFD))) {  		kfree_skb(skb);  		return;  	}  	if (!priv->echo_skb[idx]) { -		struct sock *srcsk = skb->sk; - -		if (atomic_read(&skb->users) != 1) { -			struct sk_buff *old_skb = skb; - -			skb = skb_clone(old_skb, GFP_ATOMIC); -			kfree_skb(old_skb); -			if (!skb) -				return; -		} else -			skb_orphan(skb); -		skb->sk = srcsk; +		skb = can_create_echo_skb(skb); +		if (!skb) +			return;  		/* make settings for echo to reduce code in irq context */ -		skb->protocol = htons(ETH_P_CAN);  		skb->pkt_type = PACKET_BROADCAST;  		skb->ip_summed = CHECKSUM_UNNECESSARY;  		skb->dev = dev; @@ -522,6 +511,30 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)  }  EXPORT_SYMBOL_GPL(alloc_can_skb); +struct sk_buff *alloc_canfd_skb(struct net_device *dev, +				struct canfd_frame **cfd) +{ +	struct sk_buff *skb; + +	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + +			       sizeof(struct canfd_frame)); +	if (unlikely(!skb)) +		return NULL; + +	skb->protocol = htons(ETH_P_CANFD); +	skb->pkt_type = PACKET_BROADCAST; +	skb->ip_summed = CHECKSUM_UNNECESSARY; + +	can_skb_reserve(skb); +	can_skb_prv(skb)->ifindex = dev->ifindex; + +	*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame)); +	memset(*cfd, 0, sizeof(struct canfd_frame)); + +	return skb; +} +EXPORT_SYMBOL_GPL(alloc_canfd_skb); +  struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)  {  	struct sk_buff *skb; @@ -582,6 +595,39 @@ void free_candev(struct net_device *dev)  EXPORT_SYMBOL_GPL(free_candev);  /* + * changing MTU and control mode for CAN/CANFD devices + */ +int can_change_mtu(struct net_device *dev, int new_mtu) +{ +	struct can_priv *priv = netdev_priv(dev); + +	/* Do not allow changing the MTU while running */ +	if (dev->flags & IFF_UP) +		return -EBUSY; + +	/* allow change of MTU according to the CANFD ability of the device */ +	switch (new_mtu) { +	case CAN_MTU: +		priv->ctrlmode &= ~CAN_CTRLMODE_FD; +		break; + +	case CANFD_MTU: +		if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD)) +			return -EINVAL; + +		priv->ctrlmode |= CAN_CTRLMODE_FD; +		break; + +	default: +		return -EINVAL; +	} + +	dev->mtu = new_mtu; +	return 0; +} +EXPORT_SYMBOL_GPL(can_change_mtu); + +/*   * Common open function when the device gets opened.   *   * This function should be called in the open function of the device @@ -591,11 +637,19 @@ int open_candev(struct net_device *dev)  {  	struct can_priv *priv = netdev_priv(dev); -	if (!priv->bittiming.tq && !priv->bittiming.bitrate) { +	if (!priv->bittiming.bitrate) {  		netdev_err(dev, "bit-timing not yet defined\n");  		return -EINVAL;  	} +	/* For CAN FD the data bitrate has to be >= the arbitration bitrate */ +	if ((priv->ctrlmode & CAN_CTRLMODE_FD) && +	    (!priv->data_bittiming.bitrate || +	     (priv->data_bittiming.bitrate < priv->bittiming.bitrate))) { +		netdev_err(dev, "incorrect/missing data bit-timing\n"); +		return -EINVAL; +	} +  	/* Switch carrier on if device was stopped while in bus-off state */  	if (!netif_carrier_ok(dev))  		netif_carrier_on(dev); @@ -634,6 +688,10 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {  				= { .len = sizeof(struct can_bittiming_const) },  	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },  	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) }, +	[IFLA_CAN_DATA_BITTIMING] +				= { .len = sizeof(struct can_bittiming) }, +	[IFLA_CAN_DATA_BITTIMING_CONST] +				= { .len = sizeof(struct can_bittiming_const) },  };  static int can_changelink(struct net_device *dev, @@ -645,19 +703,6 @@ static int can_changelink(struct net_device *dev,  	/* We need synchronization with dev->stop() */  	ASSERT_RTNL(); -	if (data[IFLA_CAN_CTRLMODE]) { -		struct can_ctrlmode *cm; - -		/* Do not allow changing controller mode while running */ -		if (dev->flags & IFF_UP) -			return -EBUSY; -		cm = nla_data(data[IFLA_CAN_CTRLMODE]); -		if (cm->flags & ~priv->ctrlmode_supported) -			return -EOPNOTSUPP; -		priv->ctrlmode &= ~cm->mask; -		priv->ctrlmode |= cm->flags; -	} -  	if (data[IFLA_CAN_BITTIMING]) {  		struct can_bittiming bt; @@ -665,9 +710,7 @@ static int can_changelink(struct net_device *dev,  		if (dev->flags & IFF_UP)  			return -EBUSY;  		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); -		if ((!bt.bitrate && !bt.tq) || (bt.bitrate && bt.tq)) -			return -EINVAL; -		err = can_get_bittiming(dev, &bt); +		err = can_get_bittiming(dev, &bt, priv->bittiming_const);  		if (err)  			return err;  		memcpy(&priv->bittiming, &bt, sizeof(bt)); @@ -680,6 +723,25 @@ static int can_changelink(struct net_device *dev,  		}  	} +	if (data[IFLA_CAN_CTRLMODE]) { +		struct can_ctrlmode *cm; + +		/* Do not allow changing controller mode while running */ +		if (dev->flags & IFF_UP) +			return -EBUSY; +		cm = nla_data(data[IFLA_CAN_CTRLMODE]); +		if (cm->flags & ~priv->ctrlmode_supported) +			return -EOPNOTSUPP; +		priv->ctrlmode &= ~cm->mask; +		priv->ctrlmode |= cm->flags; + +		/* CAN_CTRLMODE_FD can only be set when driver supports FD */ +		if (priv->ctrlmode & CAN_CTRLMODE_FD) +			dev->mtu = CANFD_MTU; +		else +			dev->mtu = CAN_MTU; +	} +  	if (data[IFLA_CAN_RESTART_MS]) {  		/* Do not allow changing restart delay while running */  		if (dev->flags & IFF_UP) @@ -696,23 +758,49 @@ static int can_changelink(struct net_device *dev,  			return err;  	} +	if (data[IFLA_CAN_DATA_BITTIMING]) { +		struct can_bittiming dbt; + +		/* Do not allow changing bittiming while running */ +		if (dev->flags & IFF_UP) +			return -EBUSY; +		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), +		       sizeof(dbt)); +		err = can_get_bittiming(dev, &dbt, priv->data_bittiming_const); +		if (err) +			return err; +		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); + +		if (priv->do_set_data_bittiming) { +			/* Finally, set the bit-timing registers */ +			err = priv->do_set_data_bittiming(dev); +			if (err) +				return err; +		} +	} +  	return 0;  }  static size_t can_get_size(const struct net_device *dev)  {  	struct can_priv *priv = netdev_priv(dev); -	size_t size; - -	size = nla_total_size(sizeof(u32));   /* IFLA_CAN_STATE */ -	size += sizeof(struct can_ctrlmode);  /* IFLA_CAN_CTRLMODE */ -	size += nla_total_size(sizeof(u32));  /* IFLA_CAN_RESTART_MS */ -	size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ -	size += sizeof(struct can_clock);     /* IFLA_CAN_CLOCK */ -	if (priv->do_get_berr_counter)        /* IFLA_CAN_BERR_COUNTER */ -		size += sizeof(struct can_berr_counter); -	if (priv->bittiming_const)	      /* IFLA_CAN_BITTIMING_CONST */ -		size += sizeof(struct can_bittiming_const); +	size_t size = 0; + +	if (priv->bittiming.bitrate)				/* IFLA_CAN_BITTIMING */ +		size += nla_total_size(sizeof(struct can_bittiming)); +	if (priv->bittiming_const)				/* IFLA_CAN_BITTIMING_CONST */ +		size += nla_total_size(sizeof(struct can_bittiming_const)); +	size += nla_total_size(sizeof(struct can_clock));	/* IFLA_CAN_CLOCK */ +	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */ +	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */ +	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */ +	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */ +		size += nla_total_size(sizeof(struct can_berr_counter)); +	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */ +		size += nla_total_size(sizeof(struct can_bittiming)); +	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */ +		size += nla_total_size(sizeof(struct can_bittiming_const));  	return size;  } @@ -726,23 +814,35 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)  	if (priv->do_get_state)  		priv->do_get_state(dev, &state); -	if (nla_put_u32(skb, IFLA_CAN_STATE, state) || + +	if ((priv->bittiming.bitrate && +	     nla_put(skb, IFLA_CAN_BITTIMING, +		     sizeof(priv->bittiming), &priv->bittiming)) || + +	    (priv->bittiming_const && +	     nla_put(skb, IFLA_CAN_BITTIMING_CONST, +		     sizeof(*priv->bittiming_const), priv->bittiming_const)) || + +	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) || +	    nla_put_u32(skb, IFLA_CAN_STATE, state) ||  	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||  	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) || -	    nla_put(skb, IFLA_CAN_BITTIMING, -		    sizeof(priv->bittiming), &priv->bittiming) || -	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) || +  	    (priv->do_get_berr_counter &&  	     !priv->do_get_berr_counter(dev, &bec) &&  	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) || -	    (priv->bittiming_const && -	     nla_put(skb, IFLA_CAN_BITTIMING_CONST, -		     sizeof(*priv->bittiming_const), priv->bittiming_const))) -		goto nla_put_failure; -	return 0; -nla_put_failure: -	return -EMSGSIZE; +	    (priv->data_bittiming.bitrate && +	     nla_put(skb, IFLA_CAN_DATA_BITTIMING, +		     sizeof(priv->data_bittiming), &priv->data_bittiming)) || + +	    (priv->data_bittiming_const && +	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST, +		     sizeof(*priv->data_bittiming_const), +		     priv->data_bittiming_const))) +		return -EMSGSIZE; + +	return 0;  }  static size_t can_get_xstats_size(const struct net_device *dev) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 71c677e651d..f425ec2c783 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -62,7 +62,7 @@  #define FLEXCAN_MCR_BCC			BIT(16)  #define FLEXCAN_MCR_LPRIO_EN		BIT(13)  #define FLEXCAN_MCR_AEN			BIT(12) -#define FLEXCAN_MCR_MAXMB(x)		((x) & 0xf) +#define FLEXCAN_MCR_MAXMB(x)		((x) & 0x1f)  #define FLEXCAN_MCR_IDAM_A		(0 << 8)  #define FLEXCAN_MCR_IDAM_B		(1 << 8)  #define FLEXCAN_MCR_IDAM_C		(2 << 8) @@ -144,6 +144,8 @@  #define FLEXCAN_MB_CODE_MASK		(0xf0ffffff) +#define FLEXCAN_TIMEOUT_US             (50) +  /*   * FLEXCAN hardware feature flags   * @@ -235,9 +237,12 @@ static const struct can_bittiming_const flexcan_bittiming_const = {  };  /* - * Abstract off the read/write for arm versus ppc. + * Abstract off the read/write for arm versus ppc. This + * assumes that PPC uses big-endian registers and everything + * else uses little-endian registers, independent of CPU + * endianess.   */ -#if defined(__BIG_ENDIAN) +#if defined(CONFIG_PPC)  static inline u32 flexcan_read(void __iomem *addr)  {  	return in_be32(addr); @@ -259,6 +264,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)  }  #endif +static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) +{ +	if (!priv->reg_xceiver) +		return 0; + +	return regulator_enable(priv->reg_xceiver); +} + +static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv) +{ +	if (!priv->reg_xceiver) +		return 0; + +	return regulator_disable(priv->reg_xceiver); +} +  static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,  					      u32 reg_esr)  { @@ -266,26 +287,95 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,  		(reg_esr & FLEXCAN_ESR_ERR_BUS);  } -static inline void flexcan_chip_enable(struct flexcan_priv *priv) +static int flexcan_chip_enable(struct flexcan_priv *priv)  {  	struct flexcan_regs __iomem *regs = priv->base; +	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;  	u32 reg;  	reg = flexcan_read(®s->mcr);  	reg &= ~FLEXCAN_MCR_MDIS;  	flexcan_write(reg, ®s->mcr); -	udelay(10); +	while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) +		usleep_range(10, 20); + +	if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) +		return -ETIMEDOUT; + +	return 0;  } -static inline void flexcan_chip_disable(struct flexcan_priv *priv) +static int flexcan_chip_disable(struct flexcan_priv *priv)  {  	struct flexcan_regs __iomem *regs = priv->base; +	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;  	u32 reg;  	reg = flexcan_read(®s->mcr);  	reg |= FLEXCAN_MCR_MDIS;  	flexcan_write(reg, ®s->mcr); + +	while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) +		usleep_range(10, 20); + +	if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) +		return -ETIMEDOUT; + +	return 0; +} + +static int flexcan_chip_freeze(struct flexcan_priv *priv) +{ +	struct flexcan_regs __iomem *regs = priv->base; +	unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; +	u32 reg; + +	reg = flexcan_read(®s->mcr); +	reg |= FLEXCAN_MCR_HALT; +	flexcan_write(reg, ®s->mcr); + +	while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) +		usleep_range(100, 200); + +	if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) +		return -ETIMEDOUT; + +	return 0; +} + +static int flexcan_chip_unfreeze(struct flexcan_priv *priv) +{ +	struct flexcan_regs __iomem *regs = priv->base; +	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; +	u32 reg; + +	reg = flexcan_read(®s->mcr); +	reg &= ~FLEXCAN_MCR_HALT; +	flexcan_write(reg, ®s->mcr); + +	while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) +		usleep_range(10, 20); + +	if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) +		return -ETIMEDOUT; + +	return 0; +} + +static int flexcan_chip_softreset(struct flexcan_priv *priv) +{ +	struct flexcan_regs __iomem *regs = priv->base; +	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; + +	flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); +	while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) +		usleep_range(10, 20); + +	if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) +		return -ETIMEDOUT; + +	return 0;  }  static int flexcan_get_berr_counter(const struct net_device *dev, @@ -702,24 +792,18 @@ static int flexcan_chip_start(struct net_device *dev)  {  	struct flexcan_priv *priv = netdev_priv(dev);  	struct flexcan_regs __iomem *regs = priv->base; -	unsigned int i;  	int err;  	u32 reg_mcr, reg_ctrl;  	/* enable module */ -	flexcan_chip_enable(priv); +	err = flexcan_chip_enable(priv); +	if (err) +		return err;  	/* soft reset */ -	flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); -	udelay(10); - -	reg_mcr = flexcan_read(®s->mcr); -	if (reg_mcr & FLEXCAN_MCR_SOFTRST) { -		netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n", -			   reg_mcr); -		err = -ENODEV; -		goto out; -	} +	err = flexcan_chip_softreset(priv); +	if (err) +		goto out_chip_disable;  	flexcan_set_bittiming(dev); @@ -736,9 +820,11 @@ static int flexcan_chip_start(struct net_device *dev)  	 *  	 */  	reg_mcr = flexcan_read(®s->mcr); +	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);  	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |  		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | -		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS; +		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | +		FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);  	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);  	flexcan_write(reg_mcr, ®s->mcr); @@ -772,16 +858,9 @@ static int flexcan_chip_start(struct net_device *dev)  	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);  	flexcan_write(reg_ctrl, ®s->ctrl); -	for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) { -		flexcan_write(0, ®s->cantxfg[i].can_ctrl); -		flexcan_write(0, ®s->cantxfg[i].can_id); -		flexcan_write(0, ®s->cantxfg[i].data[0]); -		flexcan_write(0, ®s->cantxfg[i].data[1]); - -		/* put MB into rx queue */ -		flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), -			®s->cantxfg[i].can_ctrl); -	} +	/* Abort any pending TX, mark Mailbox as INACTIVE */ +	flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), +		      ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);  	/* acceptance mask/acceptance code (accept everything) */  	flexcan_write(0x0, ®s->rxgmask); @@ -791,16 +870,14 @@ static int flexcan_chip_start(struct net_device *dev)  	if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)  		flexcan_write(0x0, ®s->rxfgmask); -	if (priv->reg_xceiver)	{ -		err = regulator_enable(priv->reg_xceiver); -		if (err) -			goto out; -	} +	err = flexcan_transceiver_enable(priv); +	if (err) +		goto out_chip_disable;  	/* synchronize with the can bus */ -	reg_mcr = flexcan_read(®s->mcr); -	reg_mcr &= ~FLEXCAN_MCR_HALT; -	flexcan_write(reg_mcr, ®s->mcr); +	err = flexcan_chip_unfreeze(priv); +	if (err) +		goto out_transceiver_disable;  	priv->can.state = CAN_STATE_ERROR_ACTIVE; @@ -813,7 +890,9 @@ static int flexcan_chip_start(struct net_device *dev)  	return 0; - out: + out_transceiver_disable: +	flexcan_transceiver_disable(priv); + out_chip_disable:  	flexcan_chip_disable(priv);  	return err;  } @@ -828,18 +907,17 @@ static void flexcan_chip_stop(struct net_device *dev)  {  	struct flexcan_priv *priv = netdev_priv(dev);  	struct flexcan_regs __iomem *regs = priv->base; -	u32 reg; + +	/* freeze + disable module */ +	flexcan_chip_freeze(priv); +	flexcan_chip_disable(priv);  	/* Disable all interrupts */  	flexcan_write(0, ®s->imask1); +	flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, +		      ®s->ctrl); -	/* Disable + halt module */ -	reg = flexcan_read(®s->mcr); -	reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; -	flexcan_write(reg, ®s->mcr); - -	if (priv->reg_xceiver) -		regulator_disable(priv->reg_xceiver); +	flexcan_transceiver_disable(priv);  	priv->can.state = CAN_STATE_STOPPED;  	return; @@ -869,7 +947,7 @@ static int flexcan_open(struct net_device *dev)  	/* start chip and queuing */  	err = flexcan_chip_start(dev);  	if (err) -		goto out_close; +		goto out_free_irq;  	can_led_event(dev, CAN_LED_EVENT_OPEN); @@ -878,6 +956,8 @@ static int flexcan_open(struct net_device *dev)  	return 0; + out_free_irq: +	free_irq(dev->irq, dev);   out_close:  	close_candev(dev);   out_disable_per: @@ -931,6 +1011,7 @@ static const struct net_device_ops flexcan_netdev_ops = {  	.ndo_open	= flexcan_open,  	.ndo_stop	= flexcan_close,  	.ndo_start_xmit	= flexcan_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static int register_flexcandev(struct net_device *dev) @@ -948,12 +1029,16 @@ static int register_flexcandev(struct net_device *dev)  		goto out_disable_ipg;  	/* select "bus clock", chip must be disabled */ -	flexcan_chip_disable(priv); +	err = flexcan_chip_disable(priv); +	if (err) +		goto out_disable_per;  	reg = flexcan_read(®s->ctrl);  	reg |= FLEXCAN_CTRL_CLK_SRC;  	flexcan_write(reg, ®s->ctrl); -	flexcan_chip_enable(priv); +	err = flexcan_chip_enable(priv); +	if (err) +		goto out_chip_disable;  	/* set freeze, halt and activate FIFO, restrict register access */  	reg = flexcan_read(®s->mcr); @@ -970,14 +1055,15 @@ static int register_flexcandev(struct net_device *dev)  	if (!(reg & FLEXCAN_MCR_FEN)) {  		netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");  		err = -ENODEV; -		goto out_disable_per; +		goto out_chip_disable;  	}  	err = register_candev(dev); - out_disable_per:  	/* disable core and turn off clocks */ + out_chip_disable:  	flexcan_chip_disable(priv); + out_disable_per:  	clk_disable_unprepare(priv->clk_per);   out_disable_ipg:  	clk_disable_unprepare(priv->clk_ipg); @@ -991,9 +1077,9 @@ static void unregister_flexcandev(struct net_device *dev)  }  static const struct of_device_id flexcan_of_match[] = { -	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, -	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },  	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, +	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, +	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },  	{ /* sentinel */ },  };  MODULE_DEVICE_TABLE(of, flexcan_of_match); @@ -1026,13 +1112,13 @@ static int flexcan_probe(struct platform_device *pdev)  			dev_err(&pdev->dev, "no ipg clock defined\n");  			return PTR_ERR(clk_ipg);  		} -		clock_freq = clk_get_rate(clk_ipg);  		clk_per = devm_clk_get(&pdev->dev, "per");  		if (IS_ERR(clk_per)) {  			dev_err(&pdev->dev, "no per clock defined\n");  			return PTR_ERR(clk_per);  		} +		clock_freq = clk_get_rate(clk_per);  	}  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1047,9 +1133,9 @@ static int flexcan_probe(struct platform_device *pdev)  	of_id = of_match_device(flexcan_of_match, &pdev->dev);  	if (of_id) {  		devtype_data = of_id->data; -	} else if (pdev->id_entry->driver_data) { +	} else if (platform_get_device_id(pdev)->driver_data) {  		devtype_data = (struct flexcan_devtype_data *) -			pdev->id_entry->driver_data; +			platform_get_device_id(pdev)->driver_data;  	} else {  		return -ENODEV;  	} @@ -1074,7 +1160,7 @@ static int flexcan_probe(struct platform_device *pdev)  	priv->dev = dev;  	priv->clk_ipg = clk_ipg;  	priv->clk_per = clk_per; -	priv->pdata = pdev->dev.platform_data; +	priv->pdata = dev_get_platdata(&pdev->dev);  	priv->devtype_data = devtype_data;  	priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); @@ -1107,21 +1193,24 @@ static int flexcan_probe(struct platform_device *pdev)  static int flexcan_remove(struct platform_device *pdev)  {  	struct net_device *dev = platform_get_drvdata(pdev); +	struct flexcan_priv *priv = netdev_priv(dev);  	unregister_flexcandev(dev); - +	netif_napi_del(&priv->napi);  	free_candev(dev);  	return 0;  } -#ifdef CONFIG_PM_SLEEP -static int flexcan_suspend(struct device *device) +static int __maybe_unused flexcan_suspend(struct device *device)  {  	struct net_device *dev = dev_get_drvdata(device);  	struct flexcan_priv *priv = netdev_priv(dev); +	int err; -	flexcan_chip_disable(priv); +	err = flexcan_chip_disable(priv); +	if (err) +		return err;  	if (netif_running(dev)) {  		netif_stop_queue(dev); @@ -1132,7 +1221,7 @@ static int flexcan_suspend(struct device *device)  	return 0;  } -static int flexcan_resume(struct device *device) +static int __maybe_unused flexcan_resume(struct device *device)  {  	struct net_device *dev = dev_get_drvdata(device);  	struct flexcan_priv *priv = netdev_priv(dev); @@ -1142,11 +1231,8 @@ static int flexcan_resume(struct device *device)  		netif_device_attach(dev);  		netif_start_queue(dev);  	} -	flexcan_chip_enable(priv); - -	return 0; +	return flexcan_chip_enable(priv);  } -#endif /* CONFIG_PM_SLEEP */  static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume); diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 6aa737a2439..3fd9fd942c6 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -34,10 +34,7 @@  #include <linux/io.h>  #include <linux/can/dev.h>  #include <linux/spinlock.h> -  #include <linux/of_platform.h> -#include <asm/prom.h> -  #include <linux/of_irq.h>  #include <linux/dma-mapping.h> @@ -1581,6 +1578,7 @@ static const struct net_device_ops grcan_netdev_ops = {  	.ndo_open	= grcan_open,  	.ndo_stop	= grcan_close,  	.ndo_start_xmit	= grcan_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static int grcan_setup_netdev(struct platform_device *ofdev, diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 36bd6fa1c7f..2382c04dc78 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -11,7 +11,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/platform_device.h> @@ -19,6 +18,7 @@  #include <linux/netdevice.h>  #include <linux/can.h>  #include <linux/can/dev.h> +#include <linux/can/skb.h>  #include <linux/can/error.h>  #include <linux/mfd/janz.h> @@ -198,9 +198,6 @@ struct ican3_dev {  	struct net_device *ndev;  	struct napi_struct napi; -	/* Device for printing */ -	struct device *dev; -  	/* module number */  	unsigned int num; @@ -295,7 +292,7 @@ static int ican3_old_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)  	xord = locl ^ peer;  	if ((xord & MSYNC_RB_MASK) == 0x00) { -		dev_dbg(mod->dev, "no mbox for reading\n"); +		netdev_dbg(mod->ndev, "no mbox for reading\n");  		return -ENOMEM;  	} @@ -340,7 +337,7 @@ static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)  	xord = locl ^ peer;  	if ((xord & MSYNC_WB_MASK) == MSYNC_WB_MASK) { -		dev_err(mod->dev, "no mbox for writing\n"); +		netdev_err(mod->ndev, "no mbox for writing\n");  		return -ENOMEM;  	} @@ -542,7 +539,7 @@ static int ican3_new_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)  	memcpy_fromio(&desc, desc_addr, sizeof(desc));  	if (!(desc.control & DESC_VALID)) { -		dev_dbg(mod->dev, "%s: no free buffers\n", __func__); +		netdev_dbg(mod->ndev, "%s: no free buffers\n", __func__);  		return -ENOMEM;  	} @@ -573,7 +570,7 @@ static int ican3_new_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)  	memcpy_fromio(&desc, desc_addr, sizeof(desc));  	if (!(desc.control & DESC_VALID)) { -		dev_dbg(mod->dev, "%s: no buffers to recv\n", __func__); +		netdev_dbg(mod->ndev, "%s: no buffers to recv\n", __func__);  		return -ENOMEM;  	} @@ -883,7 +880,7 @@ static void can_frame_to_ican3(struct ican3_dev *mod,   */  static void ican3_handle_idvers(struct ican3_dev *mod, struct ican3_msg *msg)  { -	dev_dbg(mod->dev, "IDVERS response: %s\n", msg->data); +	netdev_dbg(mod->ndev, "IDVERS response: %s\n", msg->data);  }  static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg) @@ -899,7 +896,7 @@ static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg)  	 * error frame for userspace  	 */  	if (msg->spec == MSG_MSGLOST) { -		dev_err(mod->dev, "lost %d control messages\n", msg->data[0]); +		netdev_err(mod->ndev, "lost %d control messages\n", msg->data[0]);  		return;  	} @@ -939,13 +936,13 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)  	/* we can only handle the SJA1000 part */  	if (msg->data[1] != CEVTIND_CHIP_SJA1000) { -		dev_err(mod->dev, "unable to handle errors on non-SJA1000\n"); +		netdev_err(mod->ndev, "unable to handle errors on non-SJA1000\n");  		return -ENODEV;  	}  	/* check the message length for sanity */  	if (le16_to_cpu(msg->len) < 6) { -		dev_err(mod->dev, "error message too short\n"); +		netdev_err(mod->ndev, "error message too short\n");  		return -EINVAL;  	} @@ -967,7 +964,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)  	 */  	if (isrc == CEVTIND_BEI) {  		int ret; -		dev_dbg(mod->dev, "bus error interrupt\n"); +		netdev_dbg(mod->ndev, "bus error interrupt\n");  		/* TX error */  		if (!(ecc & ECC_DIR)) { @@ -983,7 +980,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)  		 */  		ret = ican3_set_buserror(mod, 1);  		if (ret) { -			dev_err(mod->dev, "unable to re-enable bus-error\n"); +			netdev_err(mod->ndev, "unable to re-enable bus-error\n");  			return ret;  		} @@ -998,7 +995,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)  	/* data overrun interrupt */  	if (isrc == CEVTIND_DOI || isrc == CEVTIND_LOST) { -		dev_dbg(mod->dev, "data overrun interrupt\n"); +		netdev_dbg(mod->ndev, "data overrun interrupt\n");  		cf->can_id |= CAN_ERR_CRTL;  		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;  		stats->rx_over_errors++; @@ -1007,7 +1004,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)  	/* error warning + passive interrupt */  	if (isrc == CEVTIND_EI) { -		dev_dbg(mod->dev, "error warning + passive interrupt\n"); +		netdev_dbg(mod->ndev, "error warning + passive interrupt\n");  		if (status & SR_BS) {  			state = CAN_STATE_BUS_OFF;  			cf->can_id |= CAN_ERR_BUSOFF; @@ -1088,7 +1085,7 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)  		complete(&mod->termination_comp);  		break;  	default: -		dev_err(mod->dev, "received an unknown inquiry response\n"); +		netdev_err(mod->ndev, "received an unknown inquiry response\n");  		break;  	}  } @@ -1096,7 +1093,7 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)  static void ican3_handle_unknown_message(struct ican3_dev *mod,  					struct ican3_msg *msg)  { -	dev_warn(mod->dev, "received unknown message: spec 0x%.2x length %d\n", +	netdev_warn(mod->ndev, "received unknown message: spec 0x%.2x length %d\n",  			   msg->spec, le16_to_cpu(msg->len));  } @@ -1105,7 +1102,7 @@ static void ican3_handle_unknown_message(struct ican3_dev *mod,   */  static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)  { -	dev_dbg(mod->dev, "%s: modno %d spec 0x%.2x len %d bytes\n", __func__, +	netdev_dbg(mod->ndev, "%s: modno %d spec 0x%.2x len %d bytes\n", __func__,  			   mod->num, msg->spec, le16_to_cpu(msg->len));  	switch (msg->spec) { @@ -1134,20 +1131,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)   */  static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)  { -	struct sock *srcsk = skb->sk; - -	if (atomic_read(&skb->users) != 1) { -		struct sk_buff *old_skb = skb; - -		skb = skb_clone(old_skb, GFP_ATOMIC); -		kfree_skb(old_skb); -		if (!skb) -			return; -	} else { -		skb_orphan(skb); -	} - -	skb->sk = srcsk; +	skb = can_create_echo_skb(skb); +	if (!skb) +		return;  	/* save this skb for tx interrupt echo handling */  	skb_queue_tail(&mod->echoq, skb); @@ -1323,7 +1309,7 @@ static int ican3_napi(struct napi_struct *napi, int budget)  	/* process all communication messages */  	while (true) { -		struct ican3_msg msg; +		struct ican3_msg uninitialized_var(msg);  		ret = ican3_recv_msg(mod, &msg);  		if (ret)  			break; @@ -1417,7 +1403,7 @@ static int ican3_reset_module(struct ican3_dev *mod)  		msleep(10);  	} while (time_before(jiffies, start + HZ / 4)); -	dev_err(mod->dev, "failed to reset CAN module\n"); +	netdev_err(mod->ndev, "failed to reset CAN module\n");  	return -ETIMEDOUT;  } @@ -1436,7 +1422,7 @@ static int ican3_startup_module(struct ican3_dev *mod)  	ret = ican3_reset_module(mod);  	if (ret) { -		dev_err(mod->dev, "unable to reset module\n"); +		netdev_err(mod->ndev, "unable to reset module\n");  		return ret;  	} @@ -1445,41 +1431,41 @@ static int ican3_startup_module(struct ican3_dev *mod)  	ret = ican3_msg_connect(mod);  	if (ret) { -		dev_err(mod->dev, "unable to connect to module\n"); +		netdev_err(mod->ndev, "unable to connect to module\n");  		return ret;  	}  	ican3_init_new_host_interface(mod);  	ret = ican3_msg_newhostif(mod);  	if (ret) { -		dev_err(mod->dev, "unable to switch to new-style interface\n"); +		netdev_err(mod->ndev, "unable to switch to new-style interface\n");  		return ret;  	}  	/* default to "termination on" */  	ret = ican3_set_termination(mod, true);  	if (ret) { -		dev_err(mod->dev, "unable to enable termination\n"); +		netdev_err(mod->ndev, "unable to enable termination\n");  		return ret;  	}  	/* default to "bus errors enabled" */  	ret = ican3_set_buserror(mod, 1);  	if (ret) { -		dev_err(mod->dev, "unable to set bus-error\n"); +		netdev_err(mod->ndev, "unable to set bus-error\n");  		return ret;  	}  	ican3_init_fast_host_interface(mod);  	ret = ican3_msg_fasthostif(mod);  	if (ret) { -		dev_err(mod->dev, "unable to switch to fast host interface\n"); +		netdev_err(mod->ndev, "unable to switch to fast host interface\n");  		return ret;  	}  	ret = ican3_set_id_filter(mod, true);  	if (ret) { -		dev_err(mod->dev, "unable to set acceptance filter\n"); +		netdev_err(mod->ndev, "unable to set acceptance filter\n");  		return ret;  	} @@ -1498,14 +1484,14 @@ static int ican3_open(struct net_device *ndev)  	/* open the CAN layer */  	ret = open_candev(ndev);  	if (ret) { -		dev_err(mod->dev, "unable to start CAN layer\n"); +		netdev_err(mod->ndev, "unable to start CAN layer\n");  		return ret;  	}  	/* bring the bus online */  	ret = ican3_set_bus_state(mod, true);  	if (ret) { -		dev_err(mod->dev, "unable to set bus-on\n"); +		netdev_err(mod->ndev, "unable to set bus-on\n");  		close_candev(ndev);  		return ret;  	} @@ -1529,7 +1515,7 @@ static int ican3_stop(struct net_device *ndev)  	/* bring the bus offline, stop receiving packets */  	ret = ican3_set_bus_state(mod, false);  	if (ret) { -		dev_err(mod->dev, "unable to set bus-off\n"); +		netdev_err(mod->ndev, "unable to set bus-off\n");  		return ret;  	} @@ -1556,7 +1542,7 @@ static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)  	/* check that we can actually transmit */  	if (!ican3_txok(mod)) { -		dev_err(mod->dev, "BUG: no free descriptors\n"); +		netdev_err(mod->ndev, "BUG: no free descriptors\n");  		spin_unlock_irqrestore(&mod->lock, flags);  		return NETDEV_TX_BUSY;  	} @@ -1608,6 +1594,7 @@ static const struct net_device_ops ican3_netdev_ops = {  	.ndo_open	= ican3_open,  	.ndo_stop	= ican3_stop,  	.ndo_start_xmit	= ican3_xmit, +	.ndo_change_mtu = can_change_mtu,  };  /* @@ -1668,7 +1655,7 @@ static int ican3_set_mode(struct net_device *ndev, enum can_mode mode)  	/* bring the bus online */  	ret = ican3_set_bus_state(mod, true);  	if (ret) { -		dev_err(mod->dev, "unable to set bus-on\n"); +		netdev_err(ndev, "unable to set bus-on\n");  		return ret;  	} @@ -1693,7 +1680,7 @@ static int ican3_get_berr_counter(const struct net_device *ndev,  	ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);  	if (ret == 0) { -		dev_info(mod->dev, "%s timed out\n", __func__); +		netdev_info(mod->ndev, "%s timed out\n", __func__);  		return -ETIMEDOUT;  	} @@ -1719,7 +1706,7 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,  	ret = wait_for_completion_timeout(&mod->termination_comp, HZ);  	if (ret == 0) { -		dev_info(mod->dev, "%s timed out\n", __func__); +		netdev_info(mod->ndev, "%s timed out\n", __func__);  		return -ETIMEDOUT;  	} @@ -1769,7 +1756,7 @@ static int ican3_probe(struct platform_device *pdev)  	struct device *dev;  	int ret; -	pdata = pdev->dev.platform_data; +	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata)  		return -ENXIO; @@ -1789,7 +1776,6 @@ static int ican3_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, ndev);  	mod = netdev_priv(ndev);  	mod->ndev = ndev; -	mod->dev = &pdev->dev;  	mod->num = pdata->modno;  	netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);  	skb_queue_head_init(&mod->echoq); diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c index a3d99a8fd2d..ab7f1b01be4 100644 --- a/drivers/net/can/led.c +++ b/drivers/net/can/led.c @@ -97,6 +97,9 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg,  	if (!priv)  		return NOTIFY_DONE; +	if (!priv->tx_led_trig || !priv->rx_led_trig) +		return NOTIFY_DONE; +  	if (msg == NETDEV_CHANGENAME) {  		snprintf(name, sizeof(name), "%s-tx", netdev->name);  		led_trigger_rename_static(name, priv->tx_led_trig); diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig index f19be5269e7..81c71171949 100644 --- a/drivers/net/can/mscan/Kconfig +++ b/drivers/net/can/mscan/Kconfig @@ -1,5 +1,5 @@  config CAN_MSCAN -	depends on PPC || M68K +	depends on PPC  	tristate "Support for Freescale MSCAN based chips"  	---help---  	  The Motorola Scalable Controller Area Network (MSCAN) definition diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index e59b3a392af..44725296f72 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -16,8 +16,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -109,135 +108,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,  #endif /* CONFIG_PPC_MPC52xx */  #ifdef CONFIG_PPC_MPC512x -struct mpc512x_clockctl { -	u32 spmr;		/* System PLL Mode Reg */ -	u32 sccr[2];		/* System Clk Ctrl Reg 1 & 2 */ -	u32 scfr1;		/* System Clk Freq Reg 1 */ -	u32 scfr2;		/* System Clk Freq Reg 2 */ -	u32 reserved; -	u32 bcr;		/* Bread Crumb Reg */ -	u32 pccr[12];		/* PSC Clk Ctrl Reg 0-11 */ -	u32 spccr;		/* SPDIF Clk Ctrl Reg */ -	u32 cccr;		/* CFM Clk Ctrl Reg */ -	u32 dccr;		/* DIU Clk Cnfg Reg */ -	u32 mccr[4];		/* MSCAN Clk Ctrl Reg 1-3 */ -}; - -static struct of_device_id mpc512x_clock_ids[] = { -	{ .compatible = "fsl,mpc5121-clock", }, -	{} -}; -  static u32 mpc512x_can_get_clock(struct platform_device *ofdev, -				 const char *clock_name, int *mscan_clksrc) +				 const char *clock_source, int *mscan_clksrc)  { -	struct mpc512x_clockctl __iomem *clockctl; -	struct device_node *np_clock; -	struct clk *sys_clk, *ref_clk; -	int plen, clockidx, clocksrc = -1; -	u32 sys_freq, val, clockdiv = 1, freq = 0; -	const u32 *pval; - -	np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); -	if (!np_clock) { -		dev_err(&ofdev->dev, "couldn't find clock node\n"); -		return 0; -	} -	clockctl = of_iomap(np_clock, 0); -	if (!clockctl) { -		dev_err(&ofdev->dev, "couldn't map clock registers\n"); -		goto exit_put; -	} +	struct device_node *np; +	u32 clockdiv; +	enum { +		CLK_FROM_AUTO, +		CLK_FROM_IPS, +		CLK_FROM_SYS, +		CLK_FROM_REF, +	} clk_from; +	struct clk *clk_in, *clk_can; +	unsigned long freq_calc; +	struct mscan_priv *priv; +	struct clk *clk_ipg; -	/* Determine the MSCAN device index from the peripheral's -	 * physical address. Register address offsets against the -	 * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380 +	/* the caller passed in the clock source spec that was read from +	 * the device tree, get the optional clock divider as well  	 */ -	pval = of_get_property(ofdev->dev.of_node, "reg", &plen); -	BUG_ON(!pval || plen < sizeof(*pval)); -	clockidx = (*pval & 0x80) ? 1 : 0; -	if (*pval & 0x2000) -		clockidx += 2; +	np = ofdev->dev.of_node; +	clockdiv = 1; +	of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv); +	dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n", +		clock_source ? clock_source : "<NULL>", clockdiv); + +	/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to +	 * get set, and the 'ips' clock is the input to the MSCAN +	 * component +	 * +	 * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC] +	 * bit needs to get cleared, an optional clock-divider may have +	 * been specified (the default value is 1), the appropriate +	 * MSCAN related MCLK is the input to the MSCAN component +	 * +	 * in the absence of a clock-source spec, first an optimal clock +	 * gets determined based on the 'sys' clock, if that fails the +	 * 'ref' clock is used +	 */ +	clk_from = CLK_FROM_AUTO; +	if (clock_source) { +		/* interpret the device tree's spec for the clock source */ +		if (!strcmp(clock_source, "ip")) +			clk_from = CLK_FROM_IPS; +		else if (!strcmp(clock_source, "sys")) +			clk_from = CLK_FROM_SYS; +		else if (!strcmp(clock_source, "ref")) +			clk_from = CLK_FROM_REF; +		else +			goto err_invalid; +		dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from); +	} +	if (clk_from == CLK_FROM_AUTO) { +		/* no spec so far, try the 'sys' clock; round to the +		 * next MHz and see if we can get a multiple of 16MHz +		 */ +		dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n"); +		clk_in = devm_clk_get(&ofdev->dev, "sys"); +		if (IS_ERR(clk_in)) +			goto err_notavail; +		freq_calc = clk_get_rate(clk_in); +		freq_calc +=  499999; +		freq_calc /= 1000000; +		freq_calc *= 1000000; +		if ((freq_calc % 16000000) == 0) { +			clk_from = CLK_FROM_SYS; +			clockdiv = freq_calc / 16000000; +			dev_dbg(&ofdev->dev, +				"clk fit, sys[%lu] div[%d] freq[%lu]\n", +				freq_calc, clockdiv, freq_calc / clockdiv); +		} +	} +	if (clk_from == CLK_FROM_AUTO) { +		/* no spec so far, use the 'ref' clock */ +		dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n"); +		clk_in = devm_clk_get(&ofdev->dev, "ref"); +		if (IS_ERR(clk_in)) +			goto err_notavail; +		clk_from = CLK_FROM_REF; +		freq_calc = clk_get_rate(clk_in); +		dev_dbg(&ofdev->dev, +			"clk fit, ref[%lu] (no div) freq[%lu]\n", +			freq_calc, freq_calc); +	} -	/* -	 * Clock source and divider selection: 3 different clock sources -	 * can be selected: "ip", "ref" or "sys". For the latter two, a -	 * clock divider can be defined as well. If the clock source is -	 * not specified by the device tree, we first try to find an -	 * optimal CAN source clock based on the system clock. If that -	 * is not posslible, the reference clock will be used. +	/* select IPS or MCLK as the MSCAN input (returned to the caller), +	 * setup the MCLK mux source and rate if applicable, apply the +	 * optionally specified or derived above divider, and determine +	 * the actual resulting clock rate to return to the caller  	 */ -	if (clock_name && !strcmp(clock_name, "ip")) { +	switch (clk_from) { +	case CLK_FROM_IPS: +		clk_can = devm_clk_get(&ofdev->dev, "ips"); +		if (IS_ERR(clk_can)) +			goto err_notavail; +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); +		priv->clk_can = clk_can; +		freq_calc = clk_get_rate(clk_can);  		*mscan_clksrc = MSCAN_CLKSRC_IPS; -		freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node); -	} else { +		dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n", +			*mscan_clksrc, freq_calc); +		break; +	case CLK_FROM_SYS: +	case CLK_FROM_REF: +		clk_can = devm_clk_get(&ofdev->dev, "mclk"); +		if (IS_ERR(clk_can)) +			goto err_notavail; +		priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); +		priv->clk_can = clk_can; +		if (clk_from == CLK_FROM_SYS) +			clk_in = devm_clk_get(&ofdev->dev, "sys"); +		if (clk_from == CLK_FROM_REF) +			clk_in = devm_clk_get(&ofdev->dev, "ref"); +		if (IS_ERR(clk_in)) +			goto err_notavail; +		clk_set_parent(clk_can, clk_in); +		freq_calc = clk_get_rate(clk_in); +		freq_calc /= clockdiv; +		clk_set_rate(clk_can, freq_calc); +		freq_calc = clk_get_rate(clk_can);  		*mscan_clksrc = MSCAN_CLKSRC_BUS; - -		pval = of_get_property(ofdev->dev.of_node, -				       "fsl,mscan-clock-divider", &plen); -		if (pval && plen == sizeof(*pval)) -			clockdiv = *pval; -		if (!clockdiv) -			clockdiv = 1; - -		if (!clock_name || !strcmp(clock_name, "sys")) { -			sys_clk = devm_clk_get(&ofdev->dev, "sys_clk"); -			if (IS_ERR(sys_clk)) { -				dev_err(&ofdev->dev, "couldn't get sys_clk\n"); -				goto exit_unmap; -			} -			/* Get and round up/down sys clock rate */ -			sys_freq = 1000000 * -				((clk_get_rate(sys_clk) + 499999) / 1000000); - -			if (!clock_name) { -				/* A multiple of 16 MHz would be optimal */ -				if ((sys_freq % 16000000) == 0) { -					clocksrc = 0; -					clockdiv = sys_freq / 16000000; -					freq = sys_freq / clockdiv; -				} -			} else { -				clocksrc = 0; -				freq = sys_freq / clockdiv; -			} -		} - -		if (clocksrc < 0) { -			ref_clk = devm_clk_get(&ofdev->dev, "ref_clk"); -			if (IS_ERR(ref_clk)) { -				dev_err(&ofdev->dev, "couldn't get ref_clk\n"); -				goto exit_unmap; -			} -			clocksrc = 1; -			freq = clk_get_rate(ref_clk) / clockdiv; -		} +		dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n", +			*mscan_clksrc, freq_calc); +		break; +	default: +		goto err_invalid;  	} -	/* Disable clock */ -	out_be32(&clockctl->mccr[clockidx], 0x0); -	if (clocksrc >= 0) { -		/* Set source and divider */ -		val = (clocksrc << 14) | ((clockdiv - 1) << 17); -		out_be32(&clockctl->mccr[clockidx], val); -		/* Enable clock */ -		out_be32(&clockctl->mccr[clockidx], val | 0x10000); -	} +	/* the above clk_can item is used for the bitrate, access to +	 * the peripheral's register set needs the clk_ipg item +	 */ +	clk_ipg = devm_clk_get(&ofdev->dev, "ipg"); +	if (IS_ERR(clk_ipg)) +		goto err_notavail_ipg; +	if (clk_prepare_enable(clk_ipg)) +		goto err_notavail_ipg; +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); +	priv->clk_ipg = clk_ipg; + +	/* return the determined clock source rate */ +	return freq_calc; + +err_invalid: +	dev_err(&ofdev->dev, "invalid clock source specification\n"); +	/* clock source rate could not get determined */ +	return 0; -	/* Enable MSCAN clock domain */ -	val = in_be32(&clockctl->sccr[1]); -	if (!(val & (1 << 25))) -		out_be32(&clockctl->sccr[1], val | (1 << 25)); +err_notavail: +	dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n"); +	/* clock source rate could not get determined */ +	return 0; -	dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", -		*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : -		clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); +err_notavail_ipg: +	dev_err(&ofdev->dev, "cannot acquire or setup register clock\n"); +	/* clock source rate could not get determined */ +	return 0; +} -exit_unmap: -	iounmap(clockctl); -exit_put: -	of_node_put(np_clock); -	return freq; +static void mpc512x_can_put_clock(struct platform_device *ofdev) +{ +	struct mscan_priv *priv; + +	priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); +	if (priv->clk_ipg) +		clk_disable_unprepare(priv->clk_ipg);  }  #else /* !CONFIG_PPC_MPC512x */  static u32 mpc512x_can_get_clock(struct platform_device *ofdev, @@ -245,6 +279,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,  {  	return 0;  } +#define mpc512x_can_put_clock NULL  #endif /* CONFIG_PPC_MPC512x */  static const struct of_device_id mpc5xxx_can_table[]; @@ -386,11 +421,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)  static const struct mpc5xxx_can_data mpc5200_can_data = {  	.type = MSCAN_TYPE_MPC5200,  	.get_clock = mpc52xx_can_get_clock, +	/* .put_clock not applicable */  };  static const struct mpc5xxx_can_data mpc5121_can_data = {  	.type = MSCAN_TYPE_MPC5121,  	.get_clock = mpc512x_can_get_clock, +	.put_clock = mpc512x_can_put_clock,  };  static const struct of_device_id mpc5xxx_can_table[] = { diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index a955ec8c4b9..e0c9be5e2ab 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -16,8 +16,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -648,9 +647,10 @@ static int mscan_close(struct net_device *dev)  }  static const struct net_device_ops mscan_netdev_ops = { -       .ndo_open               = mscan_open, -       .ndo_stop               = mscan_close, -       .ndo_start_xmit         = mscan_start_xmit, +	.ndo_open	= mscan_open, +	.ndo_stop	= mscan_close, +	.ndo_start_xmit	= mscan_start_xmit, +	.ndo_change_mtu	= can_change_mtu,  };  int register_mscandev(struct net_device *dev, int mscan_clksrc) diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index 9c24d60a23b..ad8e08f9c49 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h @@ -14,8 +14,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifndef __MSCAN_H__ @@ -297,8 +296,8 @@ struct mscan_priv {  	struct napi_struct napi;  }; -extern struct net_device *alloc_mscandev(void); -extern int register_mscandev(struct net_device *dev, int mscan_clksrc); -extern void unregister_mscandev(struct net_device *dev); +struct net_device *alloc_mscandev(void); +int register_mscandev(struct net_device *dev, int mscan_clksrc); +void unregister_mscandev(struct net_device *dev);  #endif /* __MSCAN_H__ */ diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 5c314a96197..6472562efed 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -12,8 +12,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/interrupt.h> @@ -22,7 +21,6 @@  #include <linux/module.h>  #include <linux/sched.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/types.h>  #include <linux/errno.h> @@ -952,6 +950,7 @@ static const struct net_device_ops pch_can_netdev_ops = {  	.ndo_open		= pch_can_open,  	.ndo_stop		= pch_close,  	.ndo_start_xmit		= pch_xmit, +	.ndo_change_mtu		= can_change_mtu,  };  static void pch_can_remove(struct pci_dev *pdev) @@ -964,7 +963,6 @@ static void pch_can_remove(struct pci_dev *pdev)  		pci_disable_msi(priv->dev);  	pci_release_regions(pdev);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  	pch_can_reset(priv);  	pci_iounmap(pdev, priv->regs);  	free_candev(priv->ndev); diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c new file mode 100644 index 00000000000..5268d216ecf --- /dev/null +++ b/drivers/net/can/rcar_can.c @@ -0,0 +1,876 @@ +/* Renesas R-Car CAN device driver + * + * Copyright (C) 2013 Cogent Embedded, Inc. <source@cogentembedded.com> + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/netdevice.h> +#include <linux/platform_device.h> +#include <linux/can/led.h> +#include <linux/can/dev.h> +#include <linux/clk.h> +#include <linux/can/platform/rcar_can.h> + +#define RCAR_CAN_DRV_NAME	"rcar_can" + +/* Mailbox configuration: + * mailbox 60 - 63 - Rx FIFO mailboxes + * mailbox 56 - 59 - Tx FIFO mailboxes + * non-FIFO mailboxes are not used + */ +#define RCAR_CAN_N_MBX		64 /* Number of mailboxes in non-FIFO mode */ +#define RCAR_CAN_RX_FIFO_MBX	60 /* Mailbox - window to Rx FIFO */ +#define RCAR_CAN_TX_FIFO_MBX	56 /* Mailbox - window to Tx FIFO */ +#define RCAR_CAN_FIFO_DEPTH	4 + +/* Mailbox registers structure */ +struct rcar_can_mbox_regs { +	u32 id;		/* IDE and RTR bits, SID and EID */ +	u8 stub;	/* Not used */ +	u8 dlc;		/* Data Length Code - bits [0..3] */ +	u8 data[8];	/* Data Bytes */ +	u8 tsh;		/* Time Stamp Higher Byte */ +	u8 tsl;		/* Time Stamp Lower Byte */ +}; + +struct rcar_can_regs { +	struct rcar_can_mbox_regs mb[RCAR_CAN_N_MBX]; /* Mailbox registers */ +	u32 mkr_2_9[8];	/* Mask Registers 2-9 */ +	u32 fidcr[2];	/* FIFO Received ID Compare Register */ +	u32 mkivlr1;	/* Mask Invalid Register 1 */ +	u32 mier1;	/* Mailbox Interrupt Enable Register 1 */ +	u32 mkr_0_1[2];	/* Mask Registers 0-1 */ +	u32 mkivlr0;    /* Mask Invalid Register 0*/ +	u32 mier0;      /* Mailbox Interrupt Enable Register 0 */ +	u8 pad_440[0x3c0]; +	u8 mctl[64];	/* Message Control Registers */ +	u16 ctlr;	/* Control Register */ +	u16 str;	/* Status register */ +	u8 bcr[3];	/* Bit Configuration Register */ +	u8 clkr;	/* Clock Select Register */ +	u8 rfcr;	/* Receive FIFO Control Register */ +	u8 rfpcr;	/* Receive FIFO Pointer Control Register */ +	u8 tfcr;	/* Transmit FIFO Control Register */ +	u8 tfpcr;       /* Transmit FIFO Pointer Control Register */ +	u8 eier;	/* Error Interrupt Enable Register */ +	u8 eifr;	/* Error Interrupt Factor Judge Register */ +	u8 recr;	/* Receive Error Count Register */ +	u8 tecr;        /* Transmit Error Count Register */ +	u8 ecsr;	/* Error Code Store Register */ +	u8 cssr;	/* Channel Search Support Register */ +	u8 mssr;	/* Mailbox Search Status Register */ +	u8 msmr;	/* Mailbox Search Mode Register */ +	u16 tsr;	/* Time Stamp Register */ +	u8 afsr;	/* Acceptance Filter Support Register */ +	u8 pad_857; +	u8 tcr;		/* Test Control Register */ +	u8 pad_859[7]; +	u8 ier;		/* Interrupt Enable Register */ +	u8 isr;		/* Interrupt Status Register */ +	u8 pad_862; +	u8 mbsmr;	/* Mailbox Search Mask Register */ +}; + +struct rcar_can_priv { +	struct can_priv can;	/* Must be the first member! */ +	struct net_device *ndev; +	struct napi_struct napi; +	struct rcar_can_regs __iomem *regs; +	struct clk *clk; +	u8 tx_dlc[RCAR_CAN_FIFO_DEPTH]; +	u32 tx_head; +	u32 tx_tail; +	u8 clock_select; +	u8 ier; +}; + +static const struct can_bittiming_const rcar_can_bittiming_const = { +	.name = RCAR_CAN_DRV_NAME, +	.tseg1_min = 4, +	.tseg1_max = 16, +	.tseg2_min = 2, +	.tseg2_max = 8, +	.sjw_max = 4, +	.brp_min = 1, +	.brp_max = 1024, +	.brp_inc = 1, +}; + +/* Control Register bits */ +#define RCAR_CAN_CTLR_BOM	(3 << 11) /* Bus-Off Recovery Mode Bits */ +#define RCAR_CAN_CTLR_BOM_ENT	(1 << 11) /* Entry to halt mode */ +					/* at bus-off entry */ +#define RCAR_CAN_CTLR_SLPM	(1 << 10) +#define RCAR_CAN_CTLR_CANM	(3 << 8) /* Operating Mode Select Bit */ +#define RCAR_CAN_CTLR_CANM_HALT	(1 << 9) +#define RCAR_CAN_CTLR_CANM_RESET (1 << 8) +#define RCAR_CAN_CTLR_CANM_FORCE_RESET (3 << 8) +#define RCAR_CAN_CTLR_MLM	(1 << 3) /* Message Lost Mode Select */ +#define RCAR_CAN_CTLR_IDFM	(3 << 1) /* ID Format Mode Select Bits */ +#define RCAR_CAN_CTLR_IDFM_MIXED (1 << 2) /* Mixed ID mode */ +#define RCAR_CAN_CTLR_MBM	(1 << 0) /* Mailbox Mode select */ + +/* Status Register bits */ +#define RCAR_CAN_STR_RSTST	(1 << 8) /* Reset Status Bit */ + +/* FIFO Received ID Compare Registers 0 and 1 bits */ +#define RCAR_CAN_FIDCR_IDE	(1 << 31) /* ID Extension Bit */ +#define RCAR_CAN_FIDCR_RTR	(1 << 30) /* Remote Transmission Request Bit */ + +/* Receive FIFO Control Register bits */ +#define RCAR_CAN_RFCR_RFEST	(1 << 7) /* Receive FIFO Empty Status Flag */ +#define RCAR_CAN_RFCR_RFE	(1 << 0) /* Receive FIFO Enable */ + +/* Transmit FIFO Control Register bits */ +#define RCAR_CAN_TFCR_TFUST	(7 << 1) /* Transmit FIFO Unsent Message */ +					/* Number Status Bits */ +#define RCAR_CAN_TFCR_TFUST_SHIFT 1	/* Offset of Transmit FIFO Unsent */ +					/* Message Number Status Bits */ +#define RCAR_CAN_TFCR_TFE	(1 << 0) /* Transmit FIFO Enable */ + +#define RCAR_CAN_N_RX_MKREGS1	2	/* Number of mask registers */ +					/* for Rx mailboxes 0-31 */ +#define RCAR_CAN_N_RX_MKREGS2	8 + +/* Bit Configuration Register settings */ +#define RCAR_CAN_BCR_TSEG1(x)	(((x) & 0x0f) << 20) +#define RCAR_CAN_BCR_BPR(x)	(((x) & 0x3ff) << 8) +#define RCAR_CAN_BCR_SJW(x)	(((x) & 0x3) << 4) +#define RCAR_CAN_BCR_TSEG2(x)	((x) & 0x07) + +/* Mailbox and Mask Registers bits */ +#define RCAR_CAN_IDE		(1 << 31) +#define RCAR_CAN_RTR		(1 << 30) +#define RCAR_CAN_SID_SHIFT	18 + +/* Mailbox Interrupt Enable Register 1 bits */ +#define RCAR_CAN_MIER1_RXFIE	(1 << 28) /* Receive  FIFO Interrupt Enable */ +#define RCAR_CAN_MIER1_TXFIE	(1 << 24) /* Transmit FIFO Interrupt Enable */ + +/* Interrupt Enable Register bits */ +#define RCAR_CAN_IER_ERSIE	(1 << 5) /* Error (ERS) Interrupt Enable Bit */ +#define RCAR_CAN_IER_RXFIE	(1 << 4) /* Reception FIFO Interrupt */ +					/* Enable Bit */ +#define RCAR_CAN_IER_TXFIE	(1 << 3) /* Transmission FIFO Interrupt */ +					/* Enable Bit */ +/* Interrupt Status Register bits */ +#define RCAR_CAN_ISR_ERSF	(1 << 5) /* Error (ERS) Interrupt Status Bit */ +#define RCAR_CAN_ISR_RXFF	(1 << 4) /* Reception FIFO Interrupt */ +					/* Status Bit */ +#define RCAR_CAN_ISR_TXFF	(1 << 3) /* Transmission FIFO Interrupt */ +					/* Status Bit */ + +/* Error Interrupt Enable Register bits */ +#define RCAR_CAN_EIER_BLIE	(1 << 7) /* Bus Lock Interrupt Enable */ +#define RCAR_CAN_EIER_OLIE	(1 << 6) /* Overload Frame Transmit */ +					/* Interrupt Enable */ +#define RCAR_CAN_EIER_ORIE	(1 << 5) /* Receive Overrun  Interrupt Enable */ +#define RCAR_CAN_EIER_BORIE	(1 << 4) /* Bus-Off Recovery Interrupt Enable */ +#define RCAR_CAN_EIER_BOEIE	(1 << 3) /* Bus-Off Entry Interrupt Enable */ +#define RCAR_CAN_EIER_EPIE	(1 << 2) /* Error Passive Interrupt Enable */ +#define RCAR_CAN_EIER_EWIE	(1 << 1) /* Error Warning Interrupt Enable */ +#define RCAR_CAN_EIER_BEIE	(1 << 0) /* Bus Error Interrupt Enable */ + +/* Error Interrupt Factor Judge Register bits */ +#define RCAR_CAN_EIFR_BLIF	(1 << 7) /* Bus Lock Detect Flag */ +#define RCAR_CAN_EIFR_OLIF	(1 << 6) /* Overload Frame Transmission */ +					 /* Detect Flag */ +#define RCAR_CAN_EIFR_ORIF	(1 << 5) /* Receive Overrun Detect Flag */ +#define RCAR_CAN_EIFR_BORIF	(1 << 4) /* Bus-Off Recovery Detect Flag */ +#define RCAR_CAN_EIFR_BOEIF	(1 << 3) /* Bus-Off Entry Detect Flag */ +#define RCAR_CAN_EIFR_EPIF	(1 << 2) /* Error Passive Detect Flag */ +#define RCAR_CAN_EIFR_EWIF	(1 << 1) /* Error Warning Detect Flag */ +#define RCAR_CAN_EIFR_BEIF	(1 << 0) /* Bus Error Detect Flag */ + +/* Error Code Store Register bits */ +#define RCAR_CAN_ECSR_EDPM	(1 << 7) /* Error Display Mode Select Bit */ +#define RCAR_CAN_ECSR_ADEF	(1 << 6) /* ACK Delimiter Error Flag */ +#define RCAR_CAN_ECSR_BE0F	(1 << 5) /* Bit Error (dominant) Flag */ +#define RCAR_CAN_ECSR_BE1F	(1 << 4) /* Bit Error (recessive) Flag */ +#define RCAR_CAN_ECSR_CEF	(1 << 3) /* CRC Error Flag */ +#define RCAR_CAN_ECSR_AEF	(1 << 2) /* ACK Error Flag */ +#define RCAR_CAN_ECSR_FEF	(1 << 1) /* Form Error Flag */ +#define RCAR_CAN_ECSR_SEF	(1 << 0) /* Stuff Error Flag */ + +#define RCAR_CAN_NAPI_WEIGHT	4 +#define MAX_STR_READS		0x100 + +static void tx_failure_cleanup(struct net_device *ndev) +{ +	int i; + +	for (i = 0; i < RCAR_CAN_FIFO_DEPTH; i++) +		can_free_echo_skb(ndev, i); +} + +static void rcar_can_error(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; +	struct can_frame *cf; +	struct sk_buff *skb; +	u8 eifr, txerr = 0, rxerr = 0; + +	/* Propagate the error condition to the CAN stack */ +	skb = alloc_can_err_skb(ndev, &cf); + +	eifr = readb(&priv->regs->eifr); +	if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) { +		txerr = readb(&priv->regs->tecr); +		rxerr = readb(&priv->regs->recr); +		if (skb) { +			cf->can_id |= CAN_ERR_CRTL; +			cf->data[6] = txerr; +			cf->data[7] = rxerr; +		} +	} +	if (eifr & RCAR_CAN_EIFR_BEIF) { +		int rx_errors = 0, tx_errors = 0; +		u8 ecsr; + +		netdev_dbg(priv->ndev, "Bus error interrupt:\n"); +		if (skb) { +			cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; +			cf->data[2] = CAN_ERR_PROT_UNSPEC; +		} +		ecsr = readb(&priv->regs->ecsr); +		if (ecsr & RCAR_CAN_ECSR_ADEF) { +			netdev_dbg(priv->ndev, "ACK Delimiter Error\n"); +			tx_errors++; +			writeb(~RCAR_CAN_ECSR_ADEF, &priv->regs->ecsr); +			if (skb) +				cf->data[3] |= CAN_ERR_PROT_LOC_ACK_DEL; +		} +		if (ecsr & RCAR_CAN_ECSR_BE0F) { +			netdev_dbg(priv->ndev, "Bit Error (dominant)\n"); +			tx_errors++; +			writeb(~RCAR_CAN_ECSR_BE0F, &priv->regs->ecsr); +			if (skb) +				cf->data[2] |= CAN_ERR_PROT_BIT0; +		} +		if (ecsr & RCAR_CAN_ECSR_BE1F) { +			netdev_dbg(priv->ndev, "Bit Error (recessive)\n"); +			tx_errors++; +			writeb(~RCAR_CAN_ECSR_BE1F, &priv->regs->ecsr); +			if (skb) +				cf->data[2] |= CAN_ERR_PROT_BIT1; +		} +		if (ecsr & RCAR_CAN_ECSR_CEF) { +			netdev_dbg(priv->ndev, "CRC Error\n"); +			rx_errors++; +			writeb(~RCAR_CAN_ECSR_CEF, &priv->regs->ecsr); +			if (skb) +				cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; +		} +		if (ecsr & RCAR_CAN_ECSR_AEF) { +			netdev_dbg(priv->ndev, "ACK Error\n"); +			tx_errors++; +			writeb(~RCAR_CAN_ECSR_AEF, &priv->regs->ecsr); +			if (skb) { +				cf->can_id |= CAN_ERR_ACK; +				cf->data[3] |= CAN_ERR_PROT_LOC_ACK; +			} +		} +		if (ecsr & RCAR_CAN_ECSR_FEF) { +			netdev_dbg(priv->ndev, "Form Error\n"); +			rx_errors++; +			writeb(~RCAR_CAN_ECSR_FEF, &priv->regs->ecsr); +			if (skb) +				cf->data[2] |= CAN_ERR_PROT_FORM; +		} +		if (ecsr & RCAR_CAN_ECSR_SEF) { +			netdev_dbg(priv->ndev, "Stuff Error\n"); +			rx_errors++; +			writeb(~RCAR_CAN_ECSR_SEF, &priv->regs->ecsr); +			if (skb) +				cf->data[2] |= CAN_ERR_PROT_STUFF; +		} + +		priv->can.can_stats.bus_error++; +		ndev->stats.rx_errors += rx_errors; +		ndev->stats.tx_errors += tx_errors; +		writeb(~RCAR_CAN_EIFR_BEIF, &priv->regs->eifr); +	} +	if (eifr & RCAR_CAN_EIFR_EWIF) { +		netdev_dbg(priv->ndev, "Error warning interrupt\n"); +		priv->can.state = CAN_STATE_ERROR_WARNING; +		priv->can.can_stats.error_warning++; +		/* Clear interrupt condition */ +		writeb(~RCAR_CAN_EIFR_EWIF, &priv->regs->eifr); +		if (skb) +			cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING : +					      CAN_ERR_CRTL_RX_WARNING; +	} +	if (eifr & RCAR_CAN_EIFR_EPIF) { +		netdev_dbg(priv->ndev, "Error passive interrupt\n"); +		priv->can.state = CAN_STATE_ERROR_PASSIVE; +		priv->can.can_stats.error_passive++; +		/* Clear interrupt condition */ +		writeb(~RCAR_CAN_EIFR_EPIF, &priv->regs->eifr); +		if (skb) +			cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE : +					      CAN_ERR_CRTL_RX_PASSIVE; +	} +	if (eifr & RCAR_CAN_EIFR_BOEIF) { +		netdev_dbg(priv->ndev, "Bus-off entry interrupt\n"); +		tx_failure_cleanup(ndev); +		priv->ier = RCAR_CAN_IER_ERSIE; +		writeb(priv->ier, &priv->regs->ier); +		priv->can.state = CAN_STATE_BUS_OFF; +		/* Clear interrupt condition */ +		writeb(~RCAR_CAN_EIFR_BOEIF, &priv->regs->eifr); +		can_bus_off(ndev); +		if (skb) +			cf->can_id |= CAN_ERR_BUSOFF; +	} +	if (eifr & RCAR_CAN_EIFR_ORIF) { +		netdev_dbg(priv->ndev, "Receive overrun error interrupt\n"); +		ndev->stats.rx_over_errors++; +		ndev->stats.rx_errors++; +		writeb(~RCAR_CAN_EIFR_ORIF, &priv->regs->eifr); +		if (skb) { +			cf->can_id |= CAN_ERR_CRTL; +			cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; +		} +	} +	if (eifr & RCAR_CAN_EIFR_OLIF) { +		netdev_dbg(priv->ndev, +			   "Overload Frame Transmission error interrupt\n"); +		ndev->stats.rx_over_errors++; +		ndev->stats.rx_errors++; +		writeb(~RCAR_CAN_EIFR_OLIF, &priv->regs->eifr); +		if (skb) { +			cf->can_id |= CAN_ERR_PROT; +			cf->data[2] |= CAN_ERR_PROT_OVERLOAD; +		} +	} + +	if (skb) { +		stats->rx_packets++; +		stats->rx_bytes += cf->can_dlc; +		netif_rx(skb); +	} +} + +static void rcar_can_tx_done(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; +	u8 isr; + +	while (1) { +		u8 unsent = readb(&priv->regs->tfcr); + +		unsent = (unsent & RCAR_CAN_TFCR_TFUST) >> +			  RCAR_CAN_TFCR_TFUST_SHIFT; +		if (priv->tx_head - priv->tx_tail <= unsent) +			break; +		stats->tx_packets++; +		stats->tx_bytes += priv->tx_dlc[priv->tx_tail % +						RCAR_CAN_FIFO_DEPTH]; +		priv->tx_dlc[priv->tx_tail % RCAR_CAN_FIFO_DEPTH] = 0; +		can_get_echo_skb(ndev, priv->tx_tail % RCAR_CAN_FIFO_DEPTH); +		priv->tx_tail++; +		netif_wake_queue(ndev); +	} +	/* Clear interrupt */ +	isr = readb(&priv->regs->isr); +	writeb(isr & ~RCAR_CAN_ISR_TXFF, &priv->regs->isr); +	can_led_event(ndev, CAN_LED_EVENT_TX); +} + +static irqreturn_t rcar_can_interrupt(int irq, void *dev_id) +{ +	struct net_device *ndev = dev_id; +	struct rcar_can_priv *priv = netdev_priv(ndev); +	u8 isr; + +	isr = readb(&priv->regs->isr); +	if (!(isr & priv->ier)) +		return IRQ_NONE; + +	if (isr & RCAR_CAN_ISR_ERSF) +		rcar_can_error(ndev); + +	if (isr & RCAR_CAN_ISR_TXFF) +		rcar_can_tx_done(ndev); + +	if (isr & RCAR_CAN_ISR_RXFF) { +		if (napi_schedule_prep(&priv->napi)) { +			/* Disable Rx FIFO interrupts */ +			priv->ier &= ~RCAR_CAN_IER_RXFIE; +			writeb(priv->ier, &priv->regs->ier); +			__napi_schedule(&priv->napi); +		} +	} + +	return IRQ_HANDLED; +} + +static void rcar_can_set_bittiming(struct net_device *dev) +{ +	struct rcar_can_priv *priv = netdev_priv(dev); +	struct can_bittiming *bt = &priv->can.bittiming; +	u32 bcr; + +	bcr = RCAR_CAN_BCR_TSEG1(bt->phase_seg1 + bt->prop_seg - 1) | +	      RCAR_CAN_BCR_BPR(bt->brp - 1) | RCAR_CAN_BCR_SJW(bt->sjw - 1) | +	      RCAR_CAN_BCR_TSEG2(bt->phase_seg2 - 1); +	/* Don't overwrite CLKR with 32-bit BCR access; CLKR has 8-bit access. +	 * All the registers are big-endian but they get byte-swapped on 32-bit +	 * read/write (but not on 8-bit, contrary to the manuals)... +	 */ +	writel((bcr << 8) | priv->clock_select, &priv->regs->bcr); +} + +static void rcar_can_start(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	u16 ctlr; +	int i; + +	/* Set controller to known mode: +	 * - FIFO mailbox mode +	 * - accept all messages +	 * - overrun mode +	 * CAN is in sleep mode after MCU hardware or software reset. +	 */ +	ctlr = readw(&priv->regs->ctlr); +	ctlr &= ~RCAR_CAN_CTLR_SLPM; +	writew(ctlr, &priv->regs->ctlr); +	/* Go to reset mode */ +	ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET; +	writew(ctlr, &priv->regs->ctlr); +	for (i = 0; i < MAX_STR_READS; i++) { +		if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST) +			break; +	} +	rcar_can_set_bittiming(ndev); +	ctlr |= RCAR_CAN_CTLR_IDFM_MIXED; /* Select mixed ID mode */ +	ctlr |= RCAR_CAN_CTLR_BOM_ENT;	/* Entry to halt mode automatically */ +					/* at bus-off */ +	ctlr |= RCAR_CAN_CTLR_MBM;	/* Select FIFO mailbox mode */ +	ctlr |= RCAR_CAN_CTLR_MLM;	/* Overrun mode */ +	writew(ctlr, &priv->regs->ctlr); + +	/* Accept all SID and EID */ +	writel(0, &priv->regs->mkr_2_9[6]); +	writel(0, &priv->regs->mkr_2_9[7]); +	/* In FIFO mailbox mode, write "0" to bits 24 to 31 */ +	writel(0, &priv->regs->mkivlr1); +	/* Accept all frames */ +	writel(0, &priv->regs->fidcr[0]); +	writel(RCAR_CAN_FIDCR_IDE | RCAR_CAN_FIDCR_RTR, &priv->regs->fidcr[1]); +	/* Enable and configure FIFO mailbox interrupts */ +	writel(RCAR_CAN_MIER1_RXFIE | RCAR_CAN_MIER1_TXFIE, &priv->regs->mier1); + +	priv->ier = RCAR_CAN_IER_ERSIE | RCAR_CAN_IER_RXFIE | +		    RCAR_CAN_IER_TXFIE; +	writeb(priv->ier, &priv->regs->ier); + +	/* Accumulate error codes */ +	writeb(RCAR_CAN_ECSR_EDPM, &priv->regs->ecsr); +	/* Enable error interrupts */ +	writeb(RCAR_CAN_EIER_EWIE | RCAR_CAN_EIER_EPIE | RCAR_CAN_EIER_BOEIE | +	       (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING ? +	       RCAR_CAN_EIER_BEIE : 0) | RCAR_CAN_EIER_ORIE | +	       RCAR_CAN_EIER_OLIE, &priv->regs->eier); +	priv->can.state = CAN_STATE_ERROR_ACTIVE; + +	/* Go to operation mode */ +	writew(ctlr & ~RCAR_CAN_CTLR_CANM, &priv->regs->ctlr); +	for (i = 0; i < MAX_STR_READS; i++) { +		if (!(readw(&priv->regs->str) & RCAR_CAN_STR_RSTST)) +			break; +	} +	/* Enable Rx and Tx FIFO */ +	writeb(RCAR_CAN_RFCR_RFE, &priv->regs->rfcr); +	writeb(RCAR_CAN_TFCR_TFE, &priv->regs->tfcr); +} + +static int rcar_can_open(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	int err; + +	err = clk_prepare_enable(priv->clk); +	if (err) { +		netdev_err(ndev, "clk_prepare_enable() failed, error %d\n", +			   err); +		goto out; +	} +	err = open_candev(ndev); +	if (err) { +		netdev_err(ndev, "open_candev() failed, error %d\n", err); +		goto out_clock; +	} +	napi_enable(&priv->napi); +	err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev); +	if (err) { +		netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq); +		goto out_close; +	} +	can_led_event(ndev, CAN_LED_EVENT_OPEN); +	rcar_can_start(ndev); +	netif_start_queue(ndev); +	return 0; +out_close: +	napi_disable(&priv->napi); +	close_candev(ndev); +out_clock: +	clk_disable_unprepare(priv->clk); +out: +	return err; +} + +static void rcar_can_stop(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	u16 ctlr; +	int i; + +	/* Go to (force) reset mode */ +	ctlr = readw(&priv->regs->ctlr); +	ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET; +	writew(ctlr, &priv->regs->ctlr); +	for (i = 0; i < MAX_STR_READS; i++) { +		if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST) +			break; +	} +	writel(0, &priv->regs->mier0); +	writel(0, &priv->regs->mier1); +	writeb(0, &priv->regs->ier); +	writeb(0, &priv->regs->eier); +	/* Go to sleep mode */ +	ctlr |= RCAR_CAN_CTLR_SLPM; +	writew(ctlr, &priv->regs->ctlr); +	priv->can.state = CAN_STATE_STOPPED; +} + +static int rcar_can_close(struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); + +	netif_stop_queue(ndev); +	rcar_can_stop(ndev); +	free_irq(ndev->irq, ndev); +	napi_disable(&priv->napi); +	clk_disable_unprepare(priv->clk); +	close_candev(ndev); +	can_led_event(ndev, CAN_LED_EVENT_STOP); +	return 0; +} + +static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb, +				       struct net_device *ndev) +{ +	struct rcar_can_priv *priv = netdev_priv(ndev); +	struct can_frame *cf = (struct can_frame *)skb->data; +	u32 data, i; + +	if (can_dropped_invalid_skb(ndev, skb)) +		return NETDEV_TX_OK; + +	if (cf->can_id & CAN_EFF_FLAG)	/* Extended frame format */ +		data = (cf->can_id & CAN_EFF_MASK) | RCAR_CAN_IDE; +	else				/* Standard frame format */ +		data = (cf->can_id & CAN_SFF_MASK) << RCAR_CAN_SID_SHIFT; + +	if (cf->can_id & CAN_RTR_FLAG) { /* Remote transmission request */ +		data |= RCAR_CAN_RTR; +	} else { +		for (i = 0; i < cf->can_dlc; i++) +			writeb(cf->data[i], +			       &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].data[i]); +	} + +	writel(data, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].id); + +	writeb(cf->can_dlc, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].dlc); + +	priv->tx_dlc[priv->tx_head % RCAR_CAN_FIFO_DEPTH] = cf->can_dlc; +	can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH); +	priv->tx_head++; +	/* Start Tx: write 0xff to the TFPCR register to increment +	 * the CPU-side pointer for the transmit FIFO to the next +	 * mailbox location +	 */ +	writeb(0xff, &priv->regs->tfpcr); +	/* Stop the queue if we've filled all FIFO entries */ +	if (priv->tx_head - priv->tx_tail >= RCAR_CAN_FIFO_DEPTH) +		netif_stop_queue(ndev); + +	return NETDEV_TX_OK; +} + +static const struct net_device_ops rcar_can_netdev_ops = { +	.ndo_open = rcar_can_open, +	.ndo_stop = rcar_can_close, +	.ndo_start_xmit = rcar_can_start_xmit, +}; + +static void rcar_can_rx_pkt(struct rcar_can_priv *priv) +{ +	struct net_device_stats *stats = &priv->ndev->stats; +	struct can_frame *cf; +	struct sk_buff *skb; +	u32 data; +	u8 dlc; + +	skb = alloc_can_skb(priv->ndev, &cf); +	if (!skb) { +		stats->rx_dropped++; +		return; +	} + +	data = readl(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].id); +	if (data & RCAR_CAN_IDE) +		cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG; +	else +		cf->can_id = (data >> RCAR_CAN_SID_SHIFT) & CAN_SFF_MASK; + +	dlc = readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].dlc); +	cf->can_dlc = get_can_dlc(dlc); +	if (data & RCAR_CAN_RTR) { +		cf->can_id |= CAN_RTR_FLAG; +	} else { +		for (dlc = 0; dlc < cf->can_dlc; dlc++) +			cf->data[dlc] = +			readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].data[dlc]); +	} + +	can_led_event(priv->ndev, CAN_LED_EVENT_RX); + +	stats->rx_bytes += cf->can_dlc; +	stats->rx_packets++; +	netif_receive_skb(skb); +} + +static int rcar_can_rx_poll(struct napi_struct *napi, int quota) +{ +	struct rcar_can_priv *priv = container_of(napi, +						  struct rcar_can_priv, napi); +	int num_pkts; + +	for (num_pkts = 0; num_pkts < quota; num_pkts++) { +		u8 rfcr, isr; + +		isr = readb(&priv->regs->isr); +		/* Clear interrupt bit */ +		if (isr & RCAR_CAN_ISR_RXFF) +			writeb(isr & ~RCAR_CAN_ISR_RXFF, &priv->regs->isr); +		rfcr = readb(&priv->regs->rfcr); +		if (rfcr & RCAR_CAN_RFCR_RFEST) +			break; +		rcar_can_rx_pkt(priv); +		/* Write 0xff to the RFPCR register to increment +		 * the CPU-side pointer for the receive FIFO +		 * to the next mailbox location +		 */ +		writeb(0xff, &priv->regs->rfpcr); +	} +	/* All packets processed */ +	if (num_pkts < quota) { +		napi_complete(napi); +		priv->ier |= RCAR_CAN_IER_RXFIE; +		writeb(priv->ier, &priv->regs->ier); +	} +	return num_pkts; +} + +static int rcar_can_do_set_mode(struct net_device *ndev, enum can_mode mode) +{ +	switch (mode) { +	case CAN_MODE_START: +		rcar_can_start(ndev); +		netif_wake_queue(ndev); +		return 0; +	default: +		return -EOPNOTSUPP; +	} +} + +static int rcar_can_get_berr_counter(const struct net_device *dev, +				     struct can_berr_counter *bec) +{ +	struct rcar_can_priv *priv = netdev_priv(dev); +	int err; + +	err = clk_prepare_enable(priv->clk); +	if (err) +		return err; +	bec->txerr = readb(&priv->regs->tecr); +	bec->rxerr = readb(&priv->regs->recr); +	clk_disable_unprepare(priv->clk); +	return 0; +} + +static int rcar_can_probe(struct platform_device *pdev) +{ +	struct rcar_can_platform_data *pdata; +	struct rcar_can_priv *priv; +	struct net_device *ndev; +	struct resource *mem; +	void __iomem *addr; +	int err = -ENODEV; +	int irq; + +	pdata = dev_get_platdata(&pdev->dev); +	if (!pdata) { +		dev_err(&pdev->dev, "No platform data provided!\n"); +		goto fail; +	} + +	irq = platform_get_irq(pdev, 0); +	if (!irq) { +		dev_err(&pdev->dev, "No IRQ resource\n"); +		goto fail; +	} + +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	addr = devm_ioremap_resource(&pdev->dev, mem); +	if (IS_ERR(addr)) { +		err = PTR_ERR(addr); +		goto fail; +	} + +	ndev = alloc_candev(sizeof(struct rcar_can_priv), RCAR_CAN_FIFO_DEPTH); +	if (!ndev) { +		dev_err(&pdev->dev, "alloc_candev() failed\n"); +		err = -ENOMEM; +		goto fail; +	} + +	priv = netdev_priv(ndev); + +	priv->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(priv->clk)) { +		err = PTR_ERR(priv->clk); +		dev_err(&pdev->dev, "cannot get clock: %d\n", err); +		goto fail_clk; +	} + +	ndev->netdev_ops = &rcar_can_netdev_ops; +	ndev->irq = irq; +	ndev->flags |= IFF_ECHO; +	priv->ndev = ndev; +	priv->regs = addr; +	priv->clock_select = pdata->clock_select; +	priv->can.clock.freq = clk_get_rate(priv->clk); +	priv->can.bittiming_const = &rcar_can_bittiming_const; +	priv->can.do_set_mode = rcar_can_do_set_mode; +	priv->can.do_get_berr_counter = rcar_can_get_berr_counter; +	priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; +	platform_set_drvdata(pdev, ndev); +	SET_NETDEV_DEV(ndev, &pdev->dev); + +	netif_napi_add(ndev, &priv->napi, rcar_can_rx_poll, +		       RCAR_CAN_NAPI_WEIGHT); +	err = register_candev(ndev); +	if (err) { +		dev_err(&pdev->dev, "register_candev() failed, error %d\n", +			err); +		goto fail_candev; +	} + +	devm_can_led_init(ndev); + +	dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n", +		 priv->regs, ndev->irq); + +	return 0; +fail_candev: +	netif_napi_del(&priv->napi); +fail_clk: +	free_candev(ndev); +fail: +	return err; +} + +static int rcar_can_remove(struct platform_device *pdev) +{ +	struct net_device *ndev = platform_get_drvdata(pdev); +	struct rcar_can_priv *priv = netdev_priv(ndev); + +	unregister_candev(ndev); +	netif_napi_del(&priv->napi); +	free_candev(ndev); +	return 0; +} + +static int __maybe_unused rcar_can_suspend(struct device *dev) +{ +	struct net_device *ndev = dev_get_drvdata(dev); +	struct rcar_can_priv *priv = netdev_priv(ndev); +	u16 ctlr; + +	if (netif_running(ndev)) { +		netif_stop_queue(ndev); +		netif_device_detach(ndev); +	} +	ctlr = readw(&priv->regs->ctlr); +	ctlr |= RCAR_CAN_CTLR_CANM_HALT; +	writew(ctlr, &priv->regs->ctlr); +	ctlr |= RCAR_CAN_CTLR_SLPM; +	writew(ctlr, &priv->regs->ctlr); +	priv->can.state = CAN_STATE_SLEEPING; + +	clk_disable(priv->clk); +	return 0; +} + +static int __maybe_unused rcar_can_resume(struct device *dev) +{ +	struct net_device *ndev = dev_get_drvdata(dev); +	struct rcar_can_priv *priv = netdev_priv(ndev); +	u16 ctlr; +	int err; + +	err = clk_enable(priv->clk); +	if (err) { +		netdev_err(ndev, "clk_enable() failed, error %d\n", err); +		return err; +	} + +	ctlr = readw(&priv->regs->ctlr); +	ctlr &= ~RCAR_CAN_CTLR_SLPM; +	writew(ctlr, &priv->regs->ctlr); +	ctlr &= ~RCAR_CAN_CTLR_CANM; +	writew(ctlr, &priv->regs->ctlr); +	priv->can.state = CAN_STATE_ERROR_ACTIVE; + +	if (netif_running(ndev)) { +		netif_device_attach(ndev); +		netif_start_queue(ndev); +	} +	return 0; +} + +static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume); + +static struct platform_driver rcar_can_driver = { +	.driver = { +		.name = RCAR_CAN_DRV_NAME, +		.owner = THIS_MODULE, +		.pm = &rcar_can_pm_ops, +	}, +	.probe = rcar_can_probe, +	.remove = rcar_can_remove, +}; + +module_platform_driver(rcar_can_driver); + +MODULE_AUTHOR("Cogent Embedded, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CAN driver for Renesas R-Car SoC"); +MODULE_ALIAS("platform:" RCAR_CAN_DRV_NAME); diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index ff2ba86cd4a..1e65cb6c259 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -17,16 +17,9 @@ config CAN_SJA1000_PLATFORM  	  the "platform bus" (Linux abstraction for directly to the  	  processor attached devices).  Which can be found on various  	  boards from Phytec (http://www.phytec.de) like the PCM027, -	  PCM038. - -config CAN_SJA1000_OF_PLATFORM -	tristate "Generic OF Platform Bus based SJA1000 driver" -	depends on OF -	---help--- -	  This driver adds support for the SJA1000 chips connected to -	  the OpenFirmware "platform bus" found on embedded systems with -	  OpenFirmware bindings, e.g. if you have a PowerPC based system -	  you may want to enable this option. +	  PCM038. It also provides the OpenFirmware "platform bus" found +	  on embedded systems with OpenFirmware bindings, e.g. if you +	  have a PowerPC based system you may want to enable this option.  config CAN_EMS_PCMCIA  	tristate "EMS CPC-CARD Card" @@ -46,7 +39,7 @@ config CAN_EMS_PCI  config CAN_PEAK_PCMCIA  	tristate "PEAK PCAN-PC Card"  	depends on PCMCIA -	depends on HAS_IOPORT +	depends on HAS_IOPORT_MAP  	---help---  	  This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)  	  from PEAK-System (http://www.peak-system.com). To compile this diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index b3d05cbfec3..531d5fcc97e 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -5,7 +5,6 @@  obj-$(CONFIG_CAN_SJA1000) += sja1000.o  obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o  obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o -obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o  obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o  obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o  obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 3752342a678..fd13dbf07d9 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -13,8 +13,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -207,7 +206,6 @@ static void ems_pci_del_card(struct pci_dev *pdev)  	kfree(card);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  }  static void ems_pci_card_reset(struct ems_pci_card *card) @@ -325,6 +323,7 @@ static int ems_pci_add_card(struct pci_dev *pdev,  			priv->cdr = EMS_PCI_CDR;  			SET_NETDEV_DEV(dev, &pdev->dev); +			dev->dev_id = i;  			if (card->version == 1)  				/* reset int flag of pita */ diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c index 9e535f2ef52..381de998d2f 100644 --- a/drivers/net/can/sja1000/ems_pcmcia.c +++ b/drivers/net/can/sja1000/ems_pcmcia.c @@ -211,6 +211,7 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)  		priv = netdev_priv(dev);  		priv->priv = card;  		SET_NETDEV_DEV(dev, &pdev->dev); +		dev->dev_id = i;  		priv->irq_flags = IRQF_SHARED;  		dev->irq = pdev->irq; diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 217585b97cd..23b8e1324e2 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -26,8 +26,7 @@   * General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -271,6 +270,7 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,  		 priv->reg_base, board->conf_addr, dev->irq);  	SET_NETDEV_DEV(dev, &pdev->dev); +	dev->dev_id = channel;  	/* Register SJA1000 device */  	err = register_sja1000dev(dev); @@ -387,7 +387,6 @@ static void kvaser_pci_remove_one(struct pci_dev *pdev)  	pci_release_regions(pdev);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  }  static struct pci_driver kvaser_pci_driver = { diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 6b6f0ad7509..564933ae218 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -551,7 +551,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	struct sja1000_priv *priv;  	struct peak_pci_chan *chan; -	struct net_device *dev; +	struct net_device *dev, *prev_dev;  	void __iomem *cfg_base, *reg_base;  	u16 sub_sys_id, icr;  	int i, err, channels; @@ -642,6 +642,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		icr |= chan->icr_mask;  		SET_NETDEV_DEV(dev, &pdev->dev); +		dev->dev_id = i;  		/* Create chain of SJA1000 devices */  		chan->prev_dev = pci_get_drvdata(pdev); @@ -687,11 +688,13 @@ failure_remove_channels:  	writew(0x0, cfg_base + PITA_ICR + 2);  	chan = NULL; -	for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) { -		unregister_sja1000dev(dev); -		free_sja1000dev(dev); +	for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {  		priv = netdev_priv(dev);  		chan = priv->priv; +		prev_dev = chan->prev_dev; + +		unregister_sja1000dev(dev); +		free_sja1000dev(dev);  	}  	/* free any PCIeC resources too */ @@ -725,10 +728,12 @@ static void peak_pci_remove(struct pci_dev *pdev)  	/* Loop over all registered devices */  	while (1) { +		struct net_device *prev_dev = chan->prev_dev; +  		dev_info(&pdev->dev, "removing device %s\n", dev->name);  		unregister_sja1000dev(dev);  		free_sja1000dev(dev); -		dev = chan->prev_dev; +		dev = prev_dev;  		if (!dev) {  			/* do that only for first channel */ @@ -744,8 +749,6 @@ static void peak_pci_remove(struct pci_dev *pdev)  	pci_iounmap(pdev, cfg_base);  	pci_release_regions(pdev);  	pci_disable_device(pdev); - -	pci_set_drvdata(pdev, NULL);  }  static struct pci_driver peak_pci_driver = { diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c index f7ad754dd2a..dd56133cc46 100644 --- a/drivers/net/can/sja1000/peak_pcmcia.c +++ b/drivers/net/can/sja1000/peak_pcmcia.c @@ -550,6 +550,7 @@ static int pcan_add_channels(struct pcan_pccard *card)  		priv = netdev_priv(netdev);  		priv->priv = card;  		SET_NETDEV_DEV(netdev, &pdev->dev); +		netdev->dev_id = i;  		priv->irq_flags = IRQF_SHARED;  		netdev->irq = pdev->irq; diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index c52c1e96bf9..ec39b7cb228 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -16,8 +16,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -45,7 +44,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "  			"esd CAN-PCI/PMC/266, "  			"esd CAN-PCIe/2000, "  			"Connect Tech Inc. CANpro/104-Plus Opto (CRG001), " -			"IXXAT PC-I 04/PCI") +			"IXXAT PC-I 04/PCI, " +			"ELCUS CAN-200-PCI")  MODULE_LICENSE("GPL v2");  #define PLX_PCI_MAX_CHAN 2 @@ -123,6 +123,11 @@ struct plx_pci_card {  #define ESD_PCI_SUB_SYS_ID_PCIE2000	0x0200  #define ESD_PCI_SUB_SYS_ID_PCI104200	0x0501 +#define CAN200PCI_DEVICE_ID		0x9030 +#define CAN200PCI_VENDOR_ID		0x10b5 +#define CAN200PCI_SUB_DEVICE_ID		0x0301 +#define CAN200PCI_SUB_VENDOR_ID		0xe1c5 +  #define IXXAT_PCI_VENDOR_ID		0x10b5  #define IXXAT_PCI_DEVICE_ID		0x9050  #define IXXAT_PCI_SUB_SYS_ID		0x2540 @@ -234,6 +239,14 @@ static struct plx_pci_card_info plx_pci_card_info_cti = {  	/* based on PLX9030 */  }; +static struct plx_pci_card_info plx_pci_card_info_elcus = { +	"Eclus CAN-200-PCI", 2, +	PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, +	{1, 0x00, 0x00}, { {2, 0x00, 0x80}, {3, 0x00, 0x80} }, +	&plx_pci_reset_common +	/* based on PLX9030 */ +}; +  static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {  	{  		/* Adlink PCI-7841/cPCI-7841 */ @@ -319,6 +332,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {  		0, 0,  		(kernel_ulong_t)&plx_pci_card_info_cti  	}, +	{ +		/* Elcus CAN-200-PCI */ +		CAN200PCI_VENDOR_ID, CAN200PCI_DEVICE_ID, +		CAN200PCI_SUB_VENDOR_ID, CAN200PCI_SUB_DEVICE_ID, +		0, 0, +		(kernel_ulong_t)&plx_pci_card_info_elcus +	},  	{ 0,}  };  MODULE_DEVICE_TABLE(pci, plx_pci_tbl); @@ -477,7 +497,6 @@ static void plx_pci_del_card(struct pci_dev *pdev)  	kfree(card);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  }  /* @@ -568,6 +587,7 @@ static int plx_pci_add_card(struct pci_dev *pdev,  			priv->cdr = ci->cdr;  			SET_NETDEV_DEV(dev, &pdev->dev); +			dev->dev_id = i;  			/* Register SJA1000 device */  			err = register_sja1000dev(dev); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 7164a999f50..f31499a32d7 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -106,8 +106,7 @@ static int sja1000_probe_chip(struct net_device *dev)  	struct sja1000_priv *priv = netdev_priv(dev);  	if (priv->reg_base && sja1000_is_absent(priv)) { -		printk(KERN_INFO "%s: probing @0x%lX failed\n", -		       DRV_NAME, dev->base_addr); +		netdev_err(dev, "probing failed\n");  		return 0;  	}  	return -1; @@ -494,20 +493,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)  	uint8_t isrc, status;  	int n = 0; -	/* Shared interrupts and IRQ off? */ -	if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) -		return IRQ_NONE; -  	if (priv->pre_irq)  		priv->pre_irq(priv); +	/* Shared interrupts and IRQ off? */ +	if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) +		goto out; +  	while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&  	       (n < SJA1000_MAX_IRQ)) { -		n++; +  		status = priv->read_reg(priv, SJA1000_SR);  		/* check for absent controller due to hw unplug */  		if (status == 0xFF && sja1000_is_absent(priv)) -			return IRQ_NONE; +			goto out;  		if (isrc & IRQ_WUI)  			netdev_warn(dev, "wakeup interrupt\n"); @@ -535,7 +534,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)  				status = priv->read_reg(priv, SJA1000_SR);  				/* check for absent controller */  				if (status == 0xFF && sja1000_is_absent(priv)) -					return IRQ_NONE; +					goto out;  			}  		}  		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { @@ -543,8 +542,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)  			if (sja1000_err(dev, isrc, status))  				break;  		} +		n++;  	} - +out:  	if (priv->post_irq)  		priv->post_irq(priv); @@ -642,9 +642,10 @@ void free_sja1000dev(struct net_device *dev)  EXPORT_SYMBOL_GPL(free_sja1000dev);  static const struct net_device_ops sja1000_netdev_ops = { -       .ndo_open               = sja1000_open, -       .ndo_stop               = sja1000_close, -       .ndo_start_xmit         = sja1000_start_xmit, +	.ndo_open	= sja1000_open, +	.ndo_stop	= sja1000_close, +	.ndo_start_xmit	= sja1000_start_xmit, +	.ndo_change_mtu	= can_change_mtu,  };  int register_sja1000dev(struct net_device *dev) diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 06a282397ff..014695d7e6a 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -11,8 +11,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -47,6 +46,7 @@ static int clk[MAXDEV];  static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};  static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};  static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; +static spinlock_t indirect_lock[MAXDEV];  /* lock for indirect access mode */  module_param_array(port, ulong, NULL, S_IRUGO);  MODULE_PARM_DESC(port, "I/O port number"); @@ -102,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,  static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,  					     int reg)  { -	unsigned long base = (unsigned long)priv->reg_base; +	unsigned long flags, base = (unsigned long)priv->reg_base; +	u8 readval; +	spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);  	outb(reg, base); -	return inb(base + 1); +	readval = inb(base + 1); +	spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags); + +	return readval;  }  static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,  						int reg, u8 val)  { -	unsigned long base = (unsigned long)priv->reg_base; +	unsigned long flags, base = (unsigned long)priv->reg_base; +	spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);  	outb(reg, base);  	outb(val, base + 1); +	spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);  }  static int sja1000_isa_probe(struct platform_device *pdev) @@ -170,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)  		if (iosize == SJA1000_IOSIZE_INDIRECT) {  			priv->read_reg = sja1000_isa_port_read_reg_indirect;  			priv->write_reg = sja1000_isa_port_write_reg_indirect; +			spin_lock_init(&indirect_lock[idx]);  		} else {  			priv->read_reg = sja1000_isa_port_read_reg;  			priv->write_reg = sja1000_isa_port_write_reg; @@ -199,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, dev);  	SET_NETDEV_DEV(dev, &pdev->dev); +	dev->dev_id = idx;  	err = register_sja1000dev(dev);  	if (err) { diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c deleted file mode 100644 index 31ad3391116..00000000000 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Driver for SJA1000 CAN controllers on the OpenFirmware platform bus - * - * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* This is a generic driver for SJA1000 chips on the OpenFirmware platform - * bus found on embedded PowerPC systems. You need a SJA1000 CAN node - * definition in your flattened device tree source (DTS) file similar to: - * - *   can@3,100 { - *           compatible = "nxp,sja1000"; - *           reg = <3 0x100 0x80>; - *           interrupts = <2 0>; - *           interrupt-parent = <&mpic>; - *           nxp,external-clock-frequency = <16000000>; - *   }; - * - * See "Documentation/devicetree/bindings/net/can/sja1000.txt" for further - * information. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/netdevice.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/can/dev.h> - -#include <linux/of_platform.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <asm/prom.h> - -#include "sja1000.h" - -#define DRV_NAME "sja1000_of_platform" - -MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); -MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the OF platform bus"); -MODULE_LICENSE("GPL v2"); - -#define SJA1000_OFP_CAN_CLOCK  (16000000 / 2) - -#define SJA1000_OFP_OCR        OCR_TX0_PULLDOWN -#define SJA1000_OFP_CDR        (CDR_CBP | CDR_CLK_OFF) - -static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg) -{ -	return ioread8(priv->reg_base + reg); -} - -static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, -				  int reg, u8 val) -{ -	iowrite8(val, priv->reg_base + reg); -} - -static int sja1000_ofp_remove(struct platform_device *ofdev) -{ -	struct net_device *dev = platform_get_drvdata(ofdev); -	struct sja1000_priv *priv = netdev_priv(dev); -	struct device_node *np = ofdev->dev.of_node; -	struct resource res; - -	unregister_sja1000dev(dev); -	free_sja1000dev(dev); -	iounmap(priv->reg_base); -	irq_dispose_mapping(dev->irq); - -	of_address_to_resource(np, 0, &res); -	release_mem_region(res.start, resource_size(&res)); - -	return 0; -} - -static int sja1000_ofp_probe(struct platform_device *ofdev) -{ -	struct device_node *np = ofdev->dev.of_node; -	struct net_device *dev; -	struct sja1000_priv *priv; -	struct resource res; -	u32 prop; -	int err, irq, res_size; -	void __iomem *base; - -	err = of_address_to_resource(np, 0, &res); -	if (err) { -		dev_err(&ofdev->dev, "invalid address\n"); -		return err; -	} - -	res_size = resource_size(&res); - -	if (!request_mem_region(res.start, res_size, DRV_NAME)) { -		dev_err(&ofdev->dev, "couldn't request %pR\n", &res); -		return -EBUSY; -	} - -	base = ioremap_nocache(res.start, res_size); -	if (!base) { -		dev_err(&ofdev->dev, "couldn't ioremap %pR\n", &res); -		err = -ENOMEM; -		goto exit_release_mem; -	} - -	irq = irq_of_parse_and_map(np, 0); -	if (irq == 0) { -		dev_err(&ofdev->dev, "no irq found\n"); -		err = -ENODEV; -		goto exit_unmap_mem; -	} - -	dev = alloc_sja1000dev(0); -	if (!dev) { -		err = -ENOMEM; -		goto exit_dispose_irq; -	} - -	priv = netdev_priv(dev); - -	priv->read_reg = sja1000_ofp_read_reg; -	priv->write_reg = sja1000_ofp_write_reg; - -	err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop); -	if (!err) -		priv->can.clock.freq = prop / 2; -	else -		priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */ - -	err = of_property_read_u32(np, "nxp,tx-output-mode", &prop); -	if (!err) -		priv->ocr |= prop & OCR_MODE_MASK; -	else -		priv->ocr |= OCR_MODE_NORMAL; /* default */ - -	err = of_property_read_u32(np, "nxp,tx-output-config", &prop); -	if (!err) -		priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK; -	else -		priv->ocr |= OCR_TX0_PULLDOWN; /* default */ - -	err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop); -	if (!err && prop) { -		u32 divider = priv->can.clock.freq * 2 / prop; - -		if (divider > 1) -			priv->cdr |= divider / 2 - 1; -		else -			priv->cdr |= CDR_CLKOUT_MASK; -	} else { -		priv->cdr |= CDR_CLK_OFF; /* default */ -	} - -	if (!of_property_read_bool(np, "nxp,no-comparator-bypass")) -		priv->cdr |= CDR_CBP; /* default */ - -	priv->irq_flags = IRQF_SHARED; -	priv->reg_base = base; - -	dev->irq = irq; - -	dev_info(&ofdev->dev, -		 "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n", -		 priv->reg_base, dev->irq, priv->can.clock.freq, -		 priv->ocr, priv->cdr); - -	platform_set_drvdata(ofdev, dev); -	SET_NETDEV_DEV(dev, &ofdev->dev); - -	err = register_sja1000dev(dev); -	if (err) { -		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", -			DRV_NAME, err); -		goto exit_free_sja1000; -	} - -	return 0; - -exit_free_sja1000: -	free_sja1000dev(dev); -exit_dispose_irq: -	irq_dispose_mapping(irq); -exit_unmap_mem: -	iounmap(base); -exit_release_mem: -	release_mem_region(res.start, res_size); - -	return err; -} - -static struct of_device_id sja1000_ofp_table[] = { -	{.compatible = "nxp,sja1000"}, -	{}, -}; -MODULE_DEVICE_TABLE(of, sja1000_ofp_table); - -static struct platform_driver sja1000_ofp_driver = { -	.driver = { -		.owner = THIS_MODULE, -		.name = DRV_NAME, -		.of_match_table = sja1000_ofp_table, -	}, -	.probe = sja1000_ofp_probe, -	.remove = sja1000_ofp_remove, -}; - -module_platform_driver(sja1000_ofp_driver); diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 8e259c54103..95a844a7ee7 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -12,8 +12,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/kernel.h> @@ -27,12 +26,16 @@  #include <linux/can/dev.h>  #include <linux/can/platform/sja1000.h>  #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_irq.h>  #include "sja1000.h"  #define DRV_NAME "sja1000_platform" +#define SP_CAN_CLOCK  (16000000 / 2)  MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");  MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");  MODULE_ALIAS("platform:" DRV_NAME);  MODULE_LICENSE("GPL v2"); @@ -67,59 +70,16 @@ static void sp_write_reg32(const struct sja1000_priv *priv, int reg, u8 val)  	iowrite8(val, priv->reg_base + reg * 4);  } -static int sp_probe(struct platform_device *pdev) +static void sp_populate(struct sja1000_priv *priv, +			struct sja1000_platform_data *pdata, +			unsigned long resource_mem_flags)  { -	int err; -	void __iomem *addr; -	struct net_device *dev; -	struct sja1000_priv *priv; -	struct resource *res_mem, *res_irq; -	struct sja1000_platform_data *pdata; - -	pdata = pdev->dev.platform_data; -	if (!pdata) { -		dev_err(&pdev->dev, "No platform data provided!\n"); -		err = -ENODEV; -		goto exit; -	} - -	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res_mem || !res_irq) { -		err = -ENODEV; -		goto exit; -	} - -	if (!request_mem_region(res_mem->start, resource_size(res_mem), -				DRV_NAME)) { -		err = -EBUSY; -		goto exit; -	} - -	addr = ioremap_nocache(res_mem->start, resource_size(res_mem)); -	if (!addr) { -		err = -ENOMEM; -		goto exit_release; -	} - -	dev = alloc_sja1000dev(0); -	if (!dev) { -		err = -ENOMEM; -		goto exit_iounmap; -	} -	priv = netdev_priv(dev); - -	dev->irq = res_irq->start; -	priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; -	if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE) -		priv->irq_flags |= IRQF_SHARED; -	priv->reg_base = addr;  	/* The CAN clock frequency is half the oscillator clock frequency */  	priv->can.clock.freq = pdata->osc_freq / 2;  	priv->ocr = pdata->ocr;  	priv->cdr = pdata->cdr; -	switch (res_mem->flags & IORESOURCE_MEM_TYPE_MASK) { +	switch (resource_mem_flags & IORESOURCE_MEM_TYPE_MASK) {  	case IORESOURCE_MEM_32BIT:  		priv->read_reg = sp_read_reg32;  		priv->write_reg = sp_write_reg32; @@ -134,6 +94,124 @@ static int sp_probe(struct platform_device *pdev)  		priv->write_reg = sp_write_reg8;  		break;  	} +} + +static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of) +{ +	int err; +	u32 prop; + +	err = of_property_read_u32(of, "reg-io-width", &prop); +	if (err) +		prop = 1; /* 8 bit is default */ + +	switch (prop) { +	case 4: +		priv->read_reg = sp_read_reg32; +		priv->write_reg = sp_write_reg32; +		break; +	case 2: +		priv->read_reg = sp_read_reg16; +		priv->write_reg = sp_write_reg16; +		break; +	case 1:	/* fallthrough */ +	default: +		priv->read_reg = sp_read_reg8; +		priv->write_reg = sp_write_reg8; +	} + +	err = of_property_read_u32(of, "nxp,external-clock-frequency", &prop); +	if (!err) +		priv->can.clock.freq = prop / 2; +	else +		priv->can.clock.freq = SP_CAN_CLOCK; /* default */ + +	err = of_property_read_u32(of, "nxp,tx-output-mode", &prop); +	if (!err) +		priv->ocr |= prop & OCR_MODE_MASK; +	else +		priv->ocr |= OCR_MODE_NORMAL; /* default */ + +	err = of_property_read_u32(of, "nxp,tx-output-config", &prop); +	if (!err) +		priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK; +	else +		priv->ocr |= OCR_TX0_PULLDOWN; /* default */ + +	err = of_property_read_u32(of, "nxp,clock-out-frequency", &prop); +	if (!err && prop) { +		u32 divider = priv->can.clock.freq * 2 / prop; + +		if (divider > 1) +			priv->cdr |= divider / 2 - 1; +		else +			priv->cdr |= CDR_CLKOUT_MASK; +	} else { +		priv->cdr |= CDR_CLK_OFF; /* default */ +	} + +	if (!of_property_read_bool(of, "nxp,no-comparator-bypass")) +		priv->cdr |= CDR_CBP; /* default */ +} + +static int sp_probe(struct platform_device *pdev) +{ +	int err, irq = 0; +	void __iomem *addr; +	struct net_device *dev; +	struct sja1000_priv *priv; +	struct resource *res_mem, *res_irq = NULL; +	struct sja1000_platform_data *pdata; +	struct device_node *of = pdev->dev.of_node; + +	pdata = dev_get_platdata(&pdev->dev); +	if (!pdata && !of) { +		dev_err(&pdev->dev, "No platform data provided!\n"); +		return -ENODEV; +	} + +	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res_mem) +		return -ENODEV; + +	if (!devm_request_mem_region(&pdev->dev, res_mem->start, +				     resource_size(res_mem), DRV_NAME)) +		return -EBUSY; + +	addr = devm_ioremap_nocache(&pdev->dev, res_mem->start, +				    resource_size(res_mem)); +	if (!addr) +		return -ENOMEM; + +	if (of) +		irq = irq_of_parse_and_map(of, 0); +	else +		res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + +	if (!irq && !res_irq) +		return -ENODEV; + +	dev = alloc_sja1000dev(0); +	if (!dev) +		return -ENOMEM; +	priv = netdev_priv(dev); + +	if (res_irq) { +		irq = res_irq->start; +		priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK; +		if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE) +			priv->irq_flags |= IRQF_SHARED; +	} else { +		priv->irq_flags = IRQF_SHARED; +	} + +	dev->irq = irq; +	priv->reg_base = addr; + +	if (of) +		sp_populate_of(priv, of); +	else +		sp_populate(priv, pdata, res_mem->flags);  	platform_set_drvdata(pdev, dev);  	SET_NETDEV_DEV(dev, &pdev->dev); @@ -151,39 +229,32 @@ static int sp_probe(struct platform_device *pdev)   exit_free:  	free_sja1000dev(dev); - exit_iounmap: -	iounmap(addr); - exit_release: -	release_mem_region(res_mem->start, resource_size(res_mem)); - exit:  	return err;  }  static int sp_remove(struct platform_device *pdev)  {  	struct net_device *dev = platform_get_drvdata(pdev); -	struct sja1000_priv *priv = netdev_priv(dev); -	struct resource *res;  	unregister_sja1000dev(dev); - -	if (priv->reg_base) -		iounmap(priv->reg_base); - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	release_mem_region(res->start, resource_size(res)); -  	free_sja1000dev(dev);  	return 0;  } +static struct of_device_id sp_of_table[] = { +	{.compatible = "nxp,sja1000"}, +	{}, +}; +MODULE_DEVICE_TABLE(of, sp_of_table); +  static struct platform_driver sp_driver = {  	.probe = sp_probe,  	.remove = sp_remove,  	.driver = {  		.name = DRV_NAME,  		.owner = THIS_MODULE, +		.of_match_table = sp_of_table,  	},  }; diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 874188ba06f..ea4d4f1a641 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -18,9 +18,7 @@   * General Public License for more details.   *   * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307. You can also get it - * at http://www.gnu.org/licenses/gpl.html + * with this program; if not, see http://www.gnu.org/licenses/gpl.html   *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -54,6 +52,7 @@  #include <linux/delay.h>  #include <linux/init.h>  #include <linux/kernel.h> +#include <linux/workqueue.h>  #include <linux/can.h>  #include <linux/can/skb.h> @@ -76,6 +75,10 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");  /* maximum rx buffer len: extended CAN frame with timestamp */  #define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1) +#define SLC_CMD_LEN 1 +#define SLC_SFF_ID_LEN 3 +#define SLC_EFF_ID_LEN 8 +  struct slcan {  	int			magic; @@ -83,6 +86,7 @@ struct slcan {  	struct tty_struct	*tty;		/* ptr to TTY structure	     */  	struct net_device	*dev;		/* easy for intr handling    */  	spinlock_t		lock; +	struct work_struct	tx_work;	/* Flushes transmit buffer   */  	/* These are pointers to the malloc()ed frame buffers. */  	unsigned char		rbuff[SLC_MTU];	/* receiver buffer	     */ @@ -142,47 +146,63 @@ static void slc_bump(struct slcan *sl)  {  	struct sk_buff *skb;  	struct can_frame cf; -	int i, dlc_pos, tmp; -	unsigned long ultmp; -	char cmd = sl->rbuff[0]; - -	if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R')) +	int i, tmp; +	u32 tmpid; +	char *cmd = sl->rbuff; + +	cf.can_id = 0; + +	switch (*cmd) { +	case 'r': +		cf.can_id = CAN_RTR_FLAG; +		/* fallthrough */ +	case 't': +		/* store dlc ASCII value and terminate SFF CAN ID string */ +		cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN]; +		sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN] = 0; +		/* point to payload data behind the dlc */ +		cmd += SLC_CMD_LEN + SLC_SFF_ID_LEN + 1; +		break; +	case 'R': +		cf.can_id = CAN_RTR_FLAG; +		/* fallthrough */ +	case 'T': +		cf.can_id |= CAN_EFF_FLAG; +		/* store dlc ASCII value and terminate EFF CAN ID string */ +		cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN]; +		sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN] = 0; +		/* point to payload data behind the dlc */ +		cmd += SLC_CMD_LEN + SLC_EFF_ID_LEN + 1; +		break; +	default:  		return; +	} -	if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */ -		dlc_pos = 4; /* dlc position tiiid */ -	else -		dlc_pos = 9; /* dlc position Tiiiiiiiid */ - -	if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9'))) +	if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid))  		return; -	cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */ - -	sl->rbuff[dlc_pos] = 0; /* terminate can_id string */ +	cf.can_id |= tmpid; -	if (kstrtoul(sl->rbuff+1, 16, &ultmp)) +	/* get can_dlc from sanitized ASCII value */ +	if (cf.can_dlc >= '0' && cf.can_dlc < '9') +		cf.can_dlc -= '0'; +	else  		return; -	cf.can_id = ultmp; - -	if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */ -		cf.can_id |= CAN_EFF_FLAG; - -	if ((cmd | 0x20) == 'r') /* RTR frame */ -		cf.can_id |= CAN_RTR_FLAG; -  	*(u64 *) (&cf.data) = 0; /* clear payload */ -	for (i = 0, dlc_pos++; i < cf.can_dlc; i++) { -		tmp = hex_to_bin(sl->rbuff[dlc_pos++]); -		if (tmp < 0) -			return; -		cf.data[i] = (tmp << 4); -		tmp = hex_to_bin(sl->rbuff[dlc_pos++]); -		if (tmp < 0) -			return; -		cf.data[i] |= tmp; +	/* RTR frames may have a dlc > 0 but they never have any data bytes */ +	if (!(cf.can_id & CAN_RTR_FLAG)) { +		for (i = 0; i < cf.can_dlc; i++) { +			tmp = hex_to_bin(*cmd++); +			if (tmp < 0) +				return; +			cf.data[i] = (tmp << 4); +			tmp = hex_to_bin(*cmd++); +			if (tmp < 0) +				return; +			cf.data[i] |= tmp; +		}  	}  	skb = dev_alloc_skb(sizeof(struct can_frame) + @@ -209,7 +229,6 @@ static void slc_bump(struct slcan *sl)  /* parse tty input stream */  static void slcan_unesc(struct slcan *sl, unsigned char s)  { -  	if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */  		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&  		    (sl->rcount > 4))  { @@ -236,27 +255,46 @@ static void slcan_unesc(struct slcan *sl, unsigned char s)  /* Encapsulate one can_frame and stuff into a TTY queue. */  static void slc_encaps(struct slcan *sl, struct can_frame *cf)  { -	int actual, idx, i; -	char cmd; +	int actual, i; +	unsigned char *pos; +	unsigned char *endpos; +	canid_t id = cf->can_id; + +	pos = sl->xbuff;  	if (cf->can_id & CAN_RTR_FLAG) -		cmd = 'R'; /* becomes 'r' in standard frame format */ +		*pos = 'R'; /* becomes 'r' in standard frame format (SFF) */  	else -		cmd = 'T'; /* becomes 't' in standard frame format */ +		*pos = 'T'; /* becomes 't' in standard frame format (SSF) */ -	if (cf->can_id & CAN_EFF_FLAG) -		sprintf(sl->xbuff, "%c%08X%d", cmd, -			cf->can_id & CAN_EFF_MASK, cf->can_dlc); -	else -		sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20, -			cf->can_id & CAN_SFF_MASK, cf->can_dlc); +	/* determine number of chars for the CAN-identifier */ +	if (cf->can_id & CAN_EFF_FLAG) { +		id &= CAN_EFF_MASK; +		endpos = pos + SLC_EFF_ID_LEN; +	} else { +		*pos |= 0x20; /* convert R/T to lower case for SFF */ +		id &= CAN_SFF_MASK; +		endpos = pos + SLC_SFF_ID_LEN; +	} -	idx = strlen(sl->xbuff); +	/* build 3 (SFF) or 8 (EFF) digit CAN identifier */ +	pos++; +	while (endpos >= pos) { +		*endpos-- = hex_asc_upper[id & 0xf]; +		id >>= 4; +	} + +	pos += (cf->can_id & CAN_EFF_FLAG) ? SLC_EFF_ID_LEN : SLC_SFF_ID_LEN; -	for (i = 0; i < cf->can_dlc; i++) -		sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]); +	*pos++ = cf->can_dlc + '0'; -	strcat(sl->xbuff, "\r"); /* add terminating character */ +	/* RTR frames may have a dlc > 0 but they never have any data bytes */ +	if (!(cf->can_id & CAN_RTR_FLAG)) { +		for (i = 0; i < cf->can_dlc; i++) +			pos = hex_byte_pack_upper(pos, cf->data[i]); +	} + +	*pos++ = '\r';  	/* Order of next two lines is *very* important.  	 * When we are sending a little amount of data, @@ -267,37 +305,50 @@ static void slc_encaps(struct slcan *sl, struct can_frame *cf)  	 *       14 Oct 1994  Dmitry Gorodchanin.  	 */  	set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); -	actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff)); -	sl->xleft = strlen(sl->xbuff) - actual; +	actual = sl->tty->ops->write(sl->tty, sl->xbuff, pos - sl->xbuff); +	sl->xleft = (pos - sl->xbuff) - actual;  	sl->xhead = sl->xbuff + actual;  	sl->dev->stats.tx_bytes += cf->can_dlc;  } -/* - * Called by the driver when there's room for more data.  If we have - * more packets to send, we send them here. - */ -static void slcan_write_wakeup(struct tty_struct *tty) +/* Write out any remaining transmit buffer. Scheduled when tty is writable */ +static void slcan_transmit(struct work_struct *work)  { +	struct slcan *sl = container_of(work, struct slcan, tx_work);  	int actual; -	struct slcan *sl = (struct slcan *) tty->disc_data; +	spin_lock_bh(&sl->lock);  	/* First make sure we're connected. */ -	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) +	if (!sl->tty || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) { +		spin_unlock_bh(&sl->lock);  		return; +	}  	if (sl->xleft <= 0)  {  		/* Now serial buffer is almost free & we can start  		 * transmission of another packet */  		sl->dev->stats.tx_packets++; -		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); +		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags); +		spin_unlock_bh(&sl->lock);  		netif_wake_queue(sl->dev);  		return;  	} -	actual = tty->ops->write(tty, sl->xhead, sl->xleft); +	actual = sl->tty->ops->write(sl->tty, sl->xhead, sl->xleft);  	sl->xleft -= actual;  	sl->xhead += actual; +	spin_unlock_bh(&sl->lock); +} + +/* + * Called by the driver when there's room for more data. + * Schedule the transmit. + */ +static void slcan_write_wakeup(struct tty_struct *tty) +{ +	struct slcan *sl = tty->disc_data; + +	schedule_work(&sl->tx_work);  }  /* Send a can_frame to a TTY queue. */ @@ -372,10 +423,16 @@ static void slc_free_netdev(struct net_device *dev)  	slcan_devs[i] = NULL;  } +static int slcan_change_mtu(struct net_device *dev, int new_mtu) +{ +	return -EINVAL; +} +  static const struct net_device_ops slc_netdev_ops = {  	.ndo_open               = slc_open,  	.ndo_stop               = slc_close,  	.ndo_start_xmit         = slc_xmit, +	.ndo_change_mtu         = slcan_change_mtu,  };  static void slc_setup(struct net_device *dev) @@ -483,6 +540,7 @@ static struct slcan *slc_alloc(dev_t line)  	sl->magic = SLCAN_MAGIC;  	sl->dev	= dev;  	spin_lock_init(&sl->lock); +	INIT_WORK(&sl->tx_work, slcan_transmit);  	slcan_devs[i] = dev;  	return sl; @@ -581,8 +639,12 @@ static void slcan_close(struct tty_struct *tty)  	if (!sl || sl->magic != SLCAN_MAGIC || sl->tty != tty)  		return; +	spin_lock_bh(&sl->lock);  	tty->disc_data = NULL;  	sl->tty = NULL; +	spin_unlock_bh(&sl->lock); + +	flush_work(&sl->tx_work);  	/* Flush network side */  	unregister_netdev(sl->dev); diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h index afd7d85b691..35f062282db 100644 --- a/drivers/net/can/softing/softing.h +++ b/drivers/net/can/softing/softing.h @@ -71,34 +71,34 @@ struct softing {  	} id;  }; -extern int softing_default_output(struct net_device *netdev); +int softing_default_output(struct net_device *netdev); -extern ktime_t softing_raw2ktime(struct softing *card, u32 raw); +ktime_t softing_raw2ktime(struct softing *card, u32 raw); -extern int softing_chip_poweron(struct softing *card); +int softing_chip_poweron(struct softing *card); -extern int softing_bootloader_command(struct softing *card, int16_t cmd, -		const char *msg); +int softing_bootloader_command(struct softing *card, int16_t cmd, +			       const char *msg);  /* Load firmware after reset */ -extern int softing_load_fw(const char *file, struct softing *card, -			__iomem uint8_t *virt, unsigned int size, int offset); +int softing_load_fw(const char *file, struct softing *card, +		    __iomem uint8_t *virt, unsigned int size, int offset);  /* Load final application firmware after bootloader */ -extern int softing_load_app_fw(const char *file, struct softing *card); +int softing_load_app_fw(const char *file, struct softing *card);  /*   * enable or disable irq   * only called with fw.lock locked   */ -extern int softing_enable_irq(struct softing *card, int enable); +int softing_enable_irq(struct softing *card, int enable);  /* start/stop 1 bus on card */ -extern int softing_startstop(struct net_device *netdev, int up); +int softing_startstop(struct net_device *netdev, int up);  /* netif_rx() */ -extern int softing_netdev_rx(struct net_device *netdev, -		const struct can_frame *msg, ktime_t ktime); +int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg, +		      ktime_t ktime);  /* SOFTING DPRAM mappings */  #define DPRAM_RX		0x0000 diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c index 498605f833d..cdc0c7433a4 100644 --- a/drivers/net/can/softing/softing_cs.c +++ b/drivers/net/can/softing/softing_cs.c @@ -13,8 +13,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/module.h> diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c index b595d3422b9..52fe50725d7 100644 --- a/drivers/net/can/softing/softing_fw.c +++ b/drivers/net/can/softing/softing_fw.c @@ -13,8 +13,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/firmware.h> diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 65eef1eea2e..bacd236ce30 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -13,12 +13,10 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/interrupt.h>  #include <asm/io.h> @@ -558,15 +556,6 @@ failed:  /*   * netdev sysfs   */ -static ssize_t show_channel(struct device *dev, struct device_attribute *attr, -		char *buf) -{ -	struct net_device *ndev = to_net_dev(dev); -	struct softing_priv *priv = netdev2softing(ndev); - -	return sprintf(buf, "%i\n", priv->index); -} -  static ssize_t show_chip(struct device *dev, struct device_attribute *attr,  		char *buf)  { @@ -611,12 +600,10 @@ static ssize_t store_output(struct device *dev, struct device_attribute *attr,  	return count;  } -static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);  static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL);  static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output);  static const struct attribute *const netdev_sysfs_attrs[] = { -	&dev_attr_channel.attr,  	&dev_attr_chip.attr,  	&dev_attr_output.attr,  	NULL, @@ -630,6 +617,7 @@ static const struct net_device_ops softing_netdev_ops = {  	.ndo_open = softing_netdev_open,  	.ndo_stop = softing_netdev_stop,  	.ndo_start_xmit	= softing_netdev_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static const struct can_bittiming_const softing_btr_const = { @@ -680,17 +668,20 @@ static int softing_netdev_register(struct net_device *netdev)  {  	int ret; -	netdev->sysfs_groups[0] = &netdev_sysfs_group;  	ret = register_candev(netdev);  	if (ret) {  		dev_alert(&netdev->dev, "register failed\n");  		return ret;  	} +	if (sysfs_create_group(&netdev->dev.kobj, &netdev_sysfs_group) < 0) +		netdev_alert(netdev, "sysfs group failed\n"); +  	return 0;  }  static void softing_netdev_cleanup(struct net_device *netdev)  { +	sysfs_remove_group(&netdev->dev.kobj, &netdev_sysfs_group);  	unregister_candev(netdev);  	free_candev(netdev);  } @@ -722,8 +713,6 @@ DEV_ATTR_RO(firmware_version, id.fw_version);  DEV_ATTR_RO_STR(hardware, pdat->name);  DEV_ATTR_RO(hardware_version, id.hw_version);  DEV_ATTR_RO(license, id.license); -DEV_ATTR_RO(frequency, id.freq); -DEV_ATTR_RO(txpending, tx.pending);  static struct attribute *softing_pdev_attrs[] = {  	&dev_attr_serial.attr, @@ -732,8 +721,6 @@ static struct attribute *softing_pdev_attrs[] = {  	&dev_attr_hardware.attr,  	&dev_attr_hardware_version.attr,  	&dev_attr_license.attr, -	&dev_attr_frequency.attr, -	&dev_attr_txpending.attr,  	NULL,  }; @@ -768,7 +755,7 @@ static int softing_pdev_remove(struct platform_device *pdev)  static int softing_pdev_probe(struct platform_device *pdev)  { -	const struct softing_platform_data *pdat = pdev->dev.platform_data; +	const struct softing_platform_data *pdat = dev_get_platdata(&pdev->dev);  	struct softing *card;  	struct net_device *netdev;  	struct softing_priv *priv; @@ -834,6 +821,7 @@ static int softing_pdev_probe(struct platform_device *pdev)  			ret = -ENOMEM;  			goto netdev_failed;  		} +		netdev->dev_id = j;  		priv = netdev_priv(card->net[j]);  		priv->index = j;  		ret = softing_netdev_register(netdev); diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig new file mode 100644 index 00000000000..148cae5871a --- /dev/null +++ b/drivers/net/can/spi/Kconfig @@ -0,0 +1,10 @@ +menu "CAN SPI interfaces" +	depends on SPI + +config CAN_MCP251X +	tristate "Microchip MCP251x SPI CAN controllers" +	depends on HAS_DMA +	---help--- +	  Driver for the Microchip MCP251x SPI CAN controllers. + +endmenu diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile new file mode 100644 index 00000000000..90bcacffbc6 --- /dev/null +++ b/drivers/net/can/spi/Makefile @@ -0,0 +1,8 @@ +# +#  Makefile for the Linux Controller Area Network SPI drivers. +# + + +obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/spi/mcp251x.c index fe7dd696957..5df239e6881 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -28,8 +28,7 @@   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * along with this program; if not, see <http://www.gnu.org/licenses/>.   *   *   * @@ -59,6 +58,7 @@  #include <linux/can/dev.h>  #include <linux/can/led.h>  #include <linux/can/platform/mcp251x.h> +#include <linux/clk.h>  #include <linux/completion.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -69,6 +69,8 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/netdevice.h> +#include <linux/of.h> +#include <linux/of_device.h>  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/spi/spi.h> @@ -212,6 +214,8 @@  #define TX_ECHO_SKB_MAX	1 +#define MCP251X_OST_DELAY_MS	(5) +  #define DEVICE_NAME "mcp251x"  static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ @@ -264,6 +268,7 @@ struct mcp251x_priv {  	int restart_tx;  	struct regulator *power;  	struct regulator *transceiver; +	struct clk *clk;  };  #define MCP251X_IS(_model) \ @@ -598,10 +603,10 @@ static int mcp251x_do_set_bittiming(struct net_device *net)  			  (bt->prop_seg - 1));  	mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,  			   (bt->phase_seg2 - 1)); -	dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", -		 mcp251x_read_reg(spi, CNF1), -		 mcp251x_read_reg(spi, CNF2), -		 mcp251x_read_reg(spi, CNF3)); +	dev_dbg(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", +		mcp251x_read_reg(spi, CNF1), +		mcp251x_read_reg(spi, CNF2), +		mcp251x_read_reg(spi, CNF3));  	return 0;  } @@ -621,55 +626,50 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,  static int mcp251x_hw_reset(struct spi_device *spi)  {  	struct mcp251x_priv *priv = spi_get_drvdata(spi); +	u8 reg;  	int ret; -	unsigned long timeout; + +	/* Wait for oscillator startup timer after power up */ +	mdelay(MCP251X_OST_DELAY_MS);  	priv->spi_tx_buf[0] = INSTRUCTION_RESET; -	ret = spi_write(spi, priv->spi_tx_buf, 1); -	if (ret) { -		dev_err(&spi->dev, "reset failed: ret = %d\n", ret); -		return -EIO; -	} +	ret = mcp251x_spi_trans(spi, 1); +	if (ret) +		return ret; + +	/* Wait for oscillator startup timer after reset */ +	mdelay(MCP251X_OST_DELAY_MS); +	 +	reg = mcp251x_read_reg(spi, CANSTAT); +	if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) +		return -ENODEV; -	/* Wait for reset to finish */ -	timeout = jiffies + HZ; -	mdelay(10); -	while ((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) -	       != CANCTRL_REQOP_CONF) { -		schedule(); -		if (time_after(jiffies, timeout)) { -			dev_err(&spi->dev, "MCP251x didn't" -				" enter in conf mode after reset\n"); -			return -EBUSY; -		} -	}  	return 0;  }  static int mcp251x_hw_probe(struct spi_device *spi)  { -	int st1, st2; +	u8 ctrl; +	int ret; -	mcp251x_hw_reset(spi); +	ret = mcp251x_hw_reset(spi); +	if (ret) +		return ret; -	/* -	 * Please note that these are "magic values" based on after -	 * reset defaults taken from data sheet which allows us to see -	 * if we really have a chip on the bus (we avoid common all -	 * zeroes or all ones situations) -	 */ -	st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE; -	st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17; +	ctrl = mcp251x_read_reg(spi, CANCTRL); -	dev_dbg(&spi->dev, "CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2); +	dev_dbg(&spi->dev, "CANCTRL 0x%02x\n", ctrl); -	/* Check for power up default values */ -	return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; +	/* Check for power up default value */ +	if ((ctrl & 0x17) != 0x07) +		return -ENODEV; + +	return 0;  }  static int mcp251x_power_enable(struct regulator *reg, int enable)  { -	if (IS_ERR(reg)) +	if (IS_ERR_OR_NULL(reg))  		return 0;  	if (enable) @@ -773,7 +773,6 @@ static void mcp251x_restart_work_handler(struct work_struct *ws)  	mutex_lock(&priv->mcp_lock);  	if (priv->after_suspend) { -		mdelay(10);  		mcp251x_hw_reset(spi);  		mcp251x_setup(net, priv, spi);  		if (priv->after_suspend & AFTER_SUSPEND_RESTART) { @@ -952,7 +951,7 @@ static int mcp251x_open(struct net_device *net)  	priv->tx_len = 0;  	ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, -				   flags, DEVICE_NAME, priv); +				   flags | IRQF_ONESHOT, DEVICE_NAME, priv);  	if (ret) {  		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);  		mcp251x_power_enable(priv->transceiver, 0); @@ -993,24 +992,68 @@ static const struct net_device_ops mcp251x_netdev_ops = {  	.ndo_open = mcp251x_open,  	.ndo_stop = mcp251x_stop,  	.ndo_start_xmit = mcp251x_hard_start_xmit, +	.ndo_change_mtu = can_change_mtu,  }; +static const struct of_device_id mcp251x_of_match[] = { +	{ +		.compatible	= "microchip,mcp2510", +		.data		= (void *)CAN_MCP251X_MCP2510, +	}, +	{ +		.compatible	= "microchip,mcp2515", +		.data		= (void *)CAN_MCP251X_MCP2515, +	}, +	{ } +}; +MODULE_DEVICE_TABLE(of, mcp251x_of_match); + +static const struct spi_device_id mcp251x_id_table[] = { +	{ +		.name		= "mcp2510", +		.driver_data	= (kernel_ulong_t)CAN_MCP251X_MCP2510, +	}, +	{ +		.name		= "mcp2515", +		.driver_data	= (kernel_ulong_t)CAN_MCP251X_MCP2515, +	}, +	{ } +}; +MODULE_DEVICE_TABLE(spi, mcp251x_id_table); +  static int mcp251x_can_probe(struct spi_device *spi)  { +	const struct of_device_id *of_id = of_match_device(mcp251x_of_match, +							   &spi->dev); +	struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);  	struct net_device *net;  	struct mcp251x_priv *priv; -	struct mcp251x_platform_data *pdata = spi->dev.platform_data; -	int ret = -ENODEV; +	struct clk *clk; +	int freq, ret; + +	clk = devm_clk_get(&spi->dev, NULL); +	if (IS_ERR(clk)) { +		if (pdata) +			freq = pdata->oscillator_frequency; +		else +			return PTR_ERR(clk); +	} else { +		freq = clk_get_rate(clk); +	} -	if (!pdata) -		/* Platform data is required for osc freq */ -		goto error_out; +	/* Sanity check */ +	if (freq < 1000000 || freq > 25000000) +		return -ERANGE;  	/* Allocate can/net device */  	net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); -	if (!net) { -		ret = -ENOMEM; -		goto error_alloc; +	if (!net) +		return -ENOMEM; + +	if (!IS_ERR(clk)) { +		ret = clk_prepare_enable(clk); +		if (ret) +			goto out_free;  	}  	net->netdev_ops = &mcp251x_netdev_ops; @@ -1019,25 +1062,39 @@ static int mcp251x_can_probe(struct spi_device *spi)  	priv = netdev_priv(net);  	priv->can.bittiming_const = &mcp251x_bittiming_const;  	priv->can.do_set_mode = mcp251x_do_set_mode; -	priv->can.clock.freq = pdata->oscillator_frequency / 2; +	priv->can.clock.freq = freq / 2;  	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |  		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; -	priv->model = spi_get_device_id(spi)->driver_data; +	if (of_id) +		priv->model = (enum mcp251x_model)of_id->data; +	else +		priv->model = spi_get_device_id(spi)->driver_data;  	priv->net = net; +	priv->clk = clk; + +	spi_set_drvdata(spi, priv); + +	/* Configure the SPI bus */ +	spi->bits_per_word = 8; +	if (mcp251x_is_2510(spi)) +		spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; +	else +		spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; +	ret = spi_setup(spi); +	if (ret) +		goto out_clk;  	priv->power = devm_regulator_get(&spi->dev, "vdd");  	priv->transceiver = devm_regulator_get(&spi->dev, "xceiver");  	if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||  	    (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {  		ret = -EPROBE_DEFER; -		goto error_power; +		goto out_clk;  	}  	ret = mcp251x_power_enable(priv->power, 1);  	if (ret) -		goto error_power; - -	spi_set_drvdata(spi, priv); +		goto out_clk;  	priv->spi = spi;  	mutex_init(&priv->mcp_lock); @@ -1067,34 +1124,27 @@ static int mcp251x_can_probe(struct spi_device *spi)  	/* Allocate non-DMA buffers */  	if (!mcp251x_enable_dma) { -		priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); +		priv->spi_tx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, +						GFP_KERNEL);  		if (!priv->spi_tx_buf) {  			ret = -ENOMEM; -			goto error_tx_buf; +			goto error_probe;  		} -		priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); +		priv->spi_rx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, +						GFP_KERNEL);  		if (!priv->spi_rx_buf) {  			ret = -ENOMEM; -			goto error_rx_buf; +			goto error_probe;  		}  	}  	SET_NETDEV_DEV(net, &spi->dev); -	/* Configure the SPI bus */ -	spi->mode = spi->mode ? : SPI_MODE_0; -	if (mcp251x_is_2510(spi)) -		spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; -	else -		spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; -	spi->bits_per_word = 8; -	spi_setup(spi); -  	/* Here is OK to not lock the MCP, no one knows about it yet */ -	if (!mcp251x_hw_probe(spi)) { -		ret = -ENODEV; +	ret = mcp251x_hw_probe(spi); +	if (ret)  		goto error_probe; -	} +  	mcp251x_hw_sleep(spi);  	ret = register_candev(net); @@ -1103,26 +1153,21 @@ static int mcp251x_can_probe(struct spi_device *spi)  	devm_can_led_init(net); -	dev_info(&spi->dev, "probed\n"); - -	return ret; +	return 0;  error_probe: -	if (!mcp251x_enable_dma) -		kfree(priv->spi_rx_buf); -error_rx_buf: -	if (!mcp251x_enable_dma) -		kfree(priv->spi_tx_buf); -error_tx_buf:  	if (mcp251x_enable_dma)  		dma_free_coherent(&spi->dev, PAGE_SIZE,  				  priv->spi_tx_buf, priv->spi_tx_dma);  	mcp251x_power_enable(priv->power, 0); -error_power: + +out_clk: +	if (!IS_ERR(clk)) +		clk_disable_unprepare(clk); + +out_free:  	free_candev(net); -error_alloc: -	dev_err(&spi->dev, "probe failed\n"); -error_out: +  	return ret;  } @@ -1136,21 +1181,19 @@ static int mcp251x_can_remove(struct spi_device *spi)  	if (mcp251x_enable_dma) {  		dma_free_coherent(&spi->dev, PAGE_SIZE,  				  priv->spi_tx_buf, priv->spi_tx_dma); -	} else { -		kfree(priv->spi_tx_buf); -		kfree(priv->spi_rx_buf);  	}  	mcp251x_power_enable(priv->power, 0); +	if (!IS_ERR(priv->clk)) +		clk_disable_unprepare(priv->clk); +  	free_candev(net);  	return 0;  } -#ifdef CONFIG_PM_SLEEP - -static int mcp251x_can_suspend(struct device *dev) +static int __maybe_unused mcp251x_can_suspend(struct device *dev)  {  	struct spi_device *spi = to_spi_device(dev);  	struct mcp251x_priv *priv = spi_get_drvdata(spi); @@ -1172,7 +1215,7 @@ static int mcp251x_can_suspend(struct device *dev)  		priv->after_suspend = AFTER_SUSPEND_DOWN;  	} -	if (!IS_ERR(priv->power)) { +	if (!IS_ERR_OR_NULL(priv->power)) {  		regulator_disable(priv->power);  		priv->after_suspend |= AFTER_SUSPEND_POWER;  	} @@ -1180,7 +1223,7 @@ static int mcp251x_can_suspend(struct device *dev)  	return 0;  } -static int mcp251x_can_resume(struct device *dev) +static int __maybe_unused mcp251x_can_resume(struct device *dev)  {  	struct spi_device *spi = to_spi_device(dev);  	struct mcp251x_priv *priv = spi_get_drvdata(spi); @@ -1200,26 +1243,17 @@ static int mcp251x_can_resume(struct device *dev)  	enable_irq(spi->irq);  	return 0;  } -#endif  static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,  	mcp251x_can_resume); -static const struct spi_device_id mcp251x_id_table[] = { -	{ "mcp2510",	CAN_MCP251X_MCP2510 }, -	{ "mcp2515",	CAN_MCP251X_MCP2515 }, -	{ }, -}; - -MODULE_DEVICE_TABLE(spi, mcp251x_id_table); -  static struct spi_driver mcp251x_can_driver = {  	.driver = {  		.name = DEVICE_NAME,  		.owner = THIS_MODULE, +		.of_match_table = mcp251x_of_match,  		.pm = &mcp251x_can_pm_ops,  	}, -  	.id_table = mcp251x_id_table,  	.probe = mcp251x_can_probe,  	.remove = mcp251x_can_remove, diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 3a349a22d5b..258b9c4856e 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -37,7 +37,6 @@   */  #include <linux/module.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/types.h>  #include <linux/interrupt.h> @@ -286,15 +285,6 @@ static inline u32 hecc_get_bit(struct ti_hecc_priv *priv, int reg, u32 bit_mask)  	return (hecc_read(priv, reg) & bit_mask) ? 1 : 0;  } -static int ti_hecc_get_state(const struct net_device *ndev, -	enum can_state *state) -{ -	struct ti_hecc_priv *priv = netdev_priv(ndev); - -	*state = priv->can.state; -	return 0; -} -  static int ti_hecc_set_btc(struct ti_hecc_priv *priv)  {  	struct can_bittiming *bit_timing = &priv->can.bittiming; @@ -527,10 +517,10 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)  		data = (cf->can_id & CAN_SFF_MASK) << 18;  	hecc_write_mbx(priv, mbxno, HECC_CANMID, data);  	hecc_write_mbx(priv, mbxno, HECC_CANMDL, -		be32_to_cpu(*(u32 *)(cf->data))); +		be32_to_cpu(*(__be32 *)(cf->data)));  	if (cf->can_dlc > 4)  		hecc_write_mbx(priv, mbxno, HECC_CANMDH, -			be32_to_cpu(*(u32 *)(cf->data + 4))); +			be32_to_cpu(*(__be32 *)(cf->data + 4)));  	else  		*(u32 *)(cf->data + 4) = 0;  	can_put_echo_skb(skb, ndev, mbxno); @@ -578,12 +568,10 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)  		cf->can_id |= CAN_RTR_FLAG;  	cf->can_dlc = get_can_dlc(data & 0xF);  	data = hecc_read_mbx(priv, mbxno, HECC_CANMDL); -	*(u32 *)(cf->data) = cpu_to_be32(data); +	*(__be32 *)(cf->data) = cpu_to_be32(data);  	if (cf->can_dlc > 4) {  		data = hecc_read_mbx(priv, mbxno, HECC_CANMDH); -		*(u32 *)(cf->data + 4) = cpu_to_be32(data); -	} else { -		*(u32 *)(cf->data + 4) = 0; +		*(__be32 *)(cf->data + 4) = cpu_to_be32(data);  	}  	spin_lock_irqsave(&priv->mbx_lock, flags);  	hecc_clear_bit(priv, HECC_CANME, mbx_mask); @@ -883,6 +871,7 @@ static const struct net_device_ops ti_hecc_netdev_ops = {  	.ndo_open		= ti_hecc_open,  	.ndo_stop		= ti_hecc_close,  	.ndo_start_xmit		= ti_hecc_xmit, +	.ndo_change_mtu		= can_change_mtu,  };  static int ti_hecc_probe(struct platform_device *pdev) @@ -894,7 +883,7 @@ static int ti_hecc_probe(struct platform_device *pdev)  	void __iomem *addr;  	int err = -ENODEV; -	pdata = pdev->dev.platform_data; +	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata) {  		dev_err(&pdev->dev, "No platform data\n");  		goto probe_exit; @@ -940,7 +929,6 @@ static int ti_hecc_probe(struct platform_device *pdev)  	priv->can.bittiming_const = &ti_hecc_bittiming_const;  	priv->can.do_set_mode = ti_hecc_do_set_mode; -	priv->can.do_get_state = ti_hecc_get_state;  	priv->can.do_get_berr_counter = ti_hecc_get_berr_counter;  	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index fc96a3d83eb..a77db919363 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -13,13 +13,21 @@ config CAN_ESD_USB2            This driver supports the CAN-USB/2 interface            from esd electronic system design gmbh (http://www.esd.eu). +config CAN_GS_USB +	tristate "Geschwister Schneider UG interfaces" +	---help--- +	  This driver supports the Geschwister Schneider USB/CAN devices. +	  If unsure choose N, +	  choose Y for built in support, +	  M to compile as module (module will be named: gs_usb). +  config CAN_KVASER_USB  	tristate "Kvaser CAN/USB interface"  	---help---  	  This driver adds support for Kvaser CAN/USB devices like Kvaser  	  Leaf Light. -	  The driver gives support for the following devices: +	  The driver provides support for the following devices:  	    - Kvaser Leaf Light  	    - Kvaser Leaf Professional HS  	    - Kvaser Leaf SemiPro HS @@ -36,6 +44,8 @@ config CAN_KVASER_USB  	    - Kvaser Leaf Light "China"  	    - Kvaser BlackBird SemiPro  	    - Kvaser USBcan R +	    - Kvaser Leaf Light v2 +	    - Kvaser Mini PCI Express HS  	  If unsure, say N. diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index becef460a91..7b9a393b1ac 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -4,6 +4,7 @@  obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o  obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o +obj-$(CONFIG_CAN_GS_USB) += gs_usb.o  obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o  obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/  obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 5f9a7ad9b96..00f2534dde7 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -16,7 +16,6 @@   * with this program; if not, write to the Free Software Foundation, Inc.,   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   */ -#include <linux/init.h>  #include <linux/signal.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -625,6 +624,7 @@ static int ems_usb_start(struct ems_usb *dev)  			usb_unanchor_urb(urb);  			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,  					  urb->transfer_dma); +			usb_free_urb(urb);  			break;  		} @@ -798,8 +798,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne  	 * allowed (MAX_TX_URBS).  	 */  	if (!context) { -		usb_unanchor_urb(urb);  		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); +		usb_free_urb(urb);  		netdev_warn(netdev, "couldn't find free context\n"); @@ -883,6 +883,7 @@ static const struct net_device_ops ems_usb_netdev_ops = {  	.ndo_open = ems_usb_open,  	.ndo_stop = ems_usb_close,  	.ndo_start_xmit = ems_usb_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static const struct can_bittiming_const ems_usb_bittiming_const = { diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index ac6177d3bef..b7c9e8b1146 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -16,7 +16,6 @@   * with this program; if not, write to the Free Software Foundation, Inc.,   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   */ -#include <linux/init.h>  #include <linux/signal.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -889,6 +888,7 @@ static const struct net_device_ops esd_usb2_netdev_ops = {  	.ndo_open = esd_usb2_open,  	.ndo_stop = esd_usb2_close,  	.ndo_start_xmit = esd_usb2_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static const struct can_bittiming_const esd_usb2_bittiming_const = { @@ -1025,6 +1025,7 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)  	netdev->netdev_ops = &esd_usb2_netdev_ops;  	SET_NETDEV_DEV(netdev, &intf->dev); +	netdev->dev_id = index;  	err = register_candev(netdev);  	if (err) { diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c new file mode 100644 index 00000000000..04b0f84612f --- /dev/null +++ b/drivers/net/can/usb/gs_usb.c @@ -0,0 +1,971 @@ +/* CAN driver for Geschwister Schneider USB/CAN devices. + * + * Copyright (C) 2013 Geschwister Schneider Technologie-, + * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt). + * + * Many thanks to all socketcan devs! + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/init.h> +#include <linux/signal.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/usb.h> + +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> + +/* Device specific constants */ +#define USB_GSUSB_1_VENDOR_ID      0x1d50 +#define USB_GSUSB_1_PRODUCT_ID     0x606f + +#define GSUSB_ENDPOINT_IN          1 +#define GSUSB_ENDPOINT_OUT         2 + +/* Device specific constants */ +enum gs_usb_breq { +	GS_USB_BREQ_HOST_FORMAT = 0, +	GS_USB_BREQ_BITTIMING, +	GS_USB_BREQ_MODE, +	GS_USB_BREQ_BERR, +	GS_USB_BREQ_BT_CONST, +	GS_USB_BREQ_DEVICE_CONFIG +}; + +enum gs_can_mode { +	/* reset a channel. turns it off */ +	GS_CAN_MODE_RESET = 0, +	/* starts a channel */ +	GS_CAN_MODE_START +}; + +enum gs_can_state { +	GS_CAN_STATE_ERROR_ACTIVE = 0, +	GS_CAN_STATE_ERROR_WARNING, +	GS_CAN_STATE_ERROR_PASSIVE, +	GS_CAN_STATE_BUS_OFF, +	GS_CAN_STATE_STOPPED, +	GS_CAN_STATE_SLEEPING +}; + +/* data types passed between host and device */ +struct gs_host_config { +	u32 byte_order; +} __packed; +/* All data exchanged between host and device is exchanged in host byte order, + * thanks to the struct gs_host_config byte_order member, which is sent first + * to indicate the desired byte order. + */ + +struct gs_device_config { +	u8 reserved1; +	u8 reserved2; +	u8 reserved3; +	u8 icount; +	u32 sw_version; +	u32 hw_version; +} __packed; + +#define GS_CAN_MODE_NORMAL               0 +#define GS_CAN_MODE_LISTEN_ONLY          (1<<0) +#define GS_CAN_MODE_LOOP_BACK            (1<<1) +#define GS_CAN_MODE_TRIPLE_SAMPLE        (1<<2) +#define GS_CAN_MODE_ONE_SHOT             (1<<3) + +struct gs_device_mode { +	u32 mode; +	u32 flags; +} __packed; + +struct gs_device_state { +	u32 state; +	u32 rxerr; +	u32 txerr; +} __packed; + +struct gs_device_bittiming { +	u32 prop_seg; +	u32 phase_seg1; +	u32 phase_seg2; +	u32 sjw; +	u32 brp; +} __packed; + +#define GS_CAN_FEATURE_LISTEN_ONLY      (1<<0) +#define GS_CAN_FEATURE_LOOP_BACK        (1<<1) +#define GS_CAN_FEATURE_TRIPLE_SAMPLE    (1<<2) +#define GS_CAN_FEATURE_ONE_SHOT         (1<<3) + +struct gs_device_bt_const { +	u32 feature; +	u32 fclk_can; +	u32 tseg1_min; +	u32 tseg1_max; +	u32 tseg2_min; +	u32 tseg2_max; +	u32 sjw_max; +	u32 brp_min; +	u32 brp_max; +	u32 brp_inc; +} __packed; + +#define GS_CAN_FLAG_OVERFLOW 1 + +struct gs_host_frame { +	u32 echo_id; +	u32 can_id; + +	u8 can_dlc; +	u8 channel; +	u8 flags; +	u8 reserved; + +	u8 data[8]; +} __packed; +/* The GS USB devices make use of the same flags and masks as in + * linux/can.h and linux/can/error.h, and no additional mapping is necessary. + */ + +/* Only send a max of GS_MAX_TX_URBS frames per channel at a time. */ +#define GS_MAX_TX_URBS 10 +/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */ +#define GS_MAX_RX_URBS 30 +/* Maximum number of interfaces the driver supports per device. + * Current hardware only supports 2 interfaces. The future may vary. + */ +#define GS_MAX_INTF 2 + +struct gs_tx_context { +	struct gs_can *dev; +	unsigned int echo_id; +}; + +struct gs_can { +	struct can_priv can; /* must be the first member */ + +	struct gs_usb *parent; + +	struct net_device *netdev; +	struct usb_device *udev; +	struct usb_interface *iface; + +	struct can_bittiming_const bt_const; +	unsigned int channel;	/* channel number */ + +	/* This lock prevents a race condition between xmit and recieve. */ +	spinlock_t tx_ctx_lock; +	struct gs_tx_context tx_context[GS_MAX_TX_URBS]; + +	struct usb_anchor tx_submitted; +	atomic_t active_tx_urbs; +}; + +/* usb interface struct */ +struct gs_usb { +	struct gs_can *canch[GS_MAX_INTF]; +	struct usb_anchor rx_submitted; +	atomic_t active_channels; +	struct usb_device *udev; +}; + +/* 'allocate' a tx context. + * returns a valid tx context or NULL if there is no space. + */ +static struct gs_tx_context *gs_alloc_tx_context(struct gs_can *dev) +{ +	int i = 0; +	unsigned long flags; + +	spin_lock_irqsave(&dev->tx_ctx_lock, flags); + +	for (; i < GS_MAX_TX_URBS; i++) { +		if (dev->tx_context[i].echo_id == GS_MAX_TX_URBS) { +			dev->tx_context[i].echo_id = i; +			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags); +			return &dev->tx_context[i]; +		} +	} + +	spin_unlock_irqrestore(&dev->tx_ctx_lock, flags); +	return NULL; +} + +/* releases a tx context + */ +static void gs_free_tx_context(struct gs_tx_context *txc) +{ +	txc->echo_id = GS_MAX_TX_URBS; +} + +/* Get a tx context by id. + */ +static struct gs_tx_context *gs_get_tx_context(struct gs_can *dev, unsigned int id) +{ +	unsigned long flags; + +	if (id < GS_MAX_TX_URBS) { +		spin_lock_irqsave(&dev->tx_ctx_lock, flags); +		if (dev->tx_context[id].echo_id == id) { +			spin_unlock_irqrestore(&dev->tx_ctx_lock, flags); +			return &dev->tx_context[id]; +		} +		spin_unlock_irqrestore(&dev->tx_ctx_lock, flags); +	} +	return NULL; +} + +static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev) +{ +	struct gs_device_mode *dm; +	struct usb_interface *intf = gsdev->iface; +	int rc; + +	dm = kzalloc(sizeof(*dm), GFP_KERNEL); +	if (!dm) +		return -ENOMEM; + +	dm->mode = GS_CAN_MODE_RESET; + +	rc = usb_control_msg(interface_to_usbdev(intf), +			     usb_sndctrlpipe(interface_to_usbdev(intf), 0), +			     GS_USB_BREQ_MODE, +			     USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     gsdev->channel, +			     0, +			     dm, +			     sizeof(*dm), +			     1000); + +	return rc; +} + +static void gs_update_state(struct gs_can *dev, struct can_frame *cf) +{ +	struct can_device_stats *can_stats = &dev->can.can_stats; + +	if (cf->can_id & CAN_ERR_RESTARTED) { +		dev->can.state = CAN_STATE_ERROR_ACTIVE; +		can_stats->restarts++; +	} else if (cf->can_id & CAN_ERR_BUSOFF) { +		dev->can.state = CAN_STATE_BUS_OFF; +		can_stats->bus_off++; +	} else if (cf->can_id & CAN_ERR_CRTL) { +		if ((cf->data[1] & CAN_ERR_CRTL_TX_WARNING) || +		    (cf->data[1] & CAN_ERR_CRTL_RX_WARNING)) { +			dev->can.state = CAN_STATE_ERROR_WARNING; +			can_stats->error_warning++; +		} else if ((cf->data[1] & CAN_ERR_CRTL_TX_PASSIVE) || +			   (cf->data[1] & CAN_ERR_CRTL_RX_PASSIVE)) { +			dev->can.state = CAN_STATE_ERROR_PASSIVE; +			can_stats->error_passive++; +		} else { +			dev->can.state = CAN_STATE_ERROR_ACTIVE; +		} +	} +} + +static void gs_usb_recieve_bulk_callback(struct urb *urb) +{ +	struct gs_usb *usbcan = urb->context; +	struct gs_can *dev; +	struct net_device *netdev; +	int rc; +	struct net_device_stats *stats; +	struct gs_host_frame *hf = urb->transfer_buffer; +	struct gs_tx_context *txc; +	struct can_frame *cf; +	struct sk_buff *skb; + +	BUG_ON(!usbcan); + +	switch (urb->status) { +	case 0: /* success */ +		break; +	case -ENOENT: +	case -ESHUTDOWN: +		return; +	default: +		/* do not resubmit aborted urbs. eg: when device goes down */ +		return; +	} + +	/* device reports out of range channel id */ +	if (hf->channel >= GS_MAX_INTF) +		goto resubmit_urb; + +	dev = usbcan->canch[hf->channel]; + +	netdev = dev->netdev; +	stats = &netdev->stats; + +	if (!netif_device_present(netdev)) +		return; + +	if (hf->echo_id == -1) { /* normal rx */ +		skb = alloc_can_skb(dev->netdev, &cf); +		if (!skb) +			return; + +		cf->can_id = hf->can_id; + +		cf->can_dlc = get_can_dlc(hf->can_dlc); +		memcpy(cf->data, hf->data, 8); + +		/* ERROR frames tell us information about the controller */ +		if (hf->can_id & CAN_ERR_FLAG) +			gs_update_state(dev, cf); + +		netdev->stats.rx_packets++; +		netdev->stats.rx_bytes += hf->can_dlc; + +		netif_rx(skb); +	} else { /* echo_id == hf->echo_id */ +		if (hf->echo_id >= GS_MAX_TX_URBS) { +			netdev_err(netdev, +				   "Unexpected out of range echo id %d\n", +				   hf->echo_id); +			goto resubmit_urb; +		} + +		netdev->stats.tx_packets++; +		netdev->stats.tx_bytes += hf->can_dlc; + +		txc = gs_get_tx_context(dev, hf->echo_id); + +		/* bad devices send bad echo_ids. */ +		if (!txc) { +			netdev_err(netdev, +				   "Unexpected unused echo id %d\n", +				   hf->echo_id); +			goto resubmit_urb; +		} + +		can_get_echo_skb(netdev, hf->echo_id); + +		gs_free_tx_context(txc); + +		netif_wake_queue(netdev); +	} + +	if (hf->flags & GS_CAN_FLAG_OVERFLOW) { +		skb = alloc_can_err_skb(netdev, &cf); +		if (!skb) +			goto resubmit_urb; + +		cf->can_id |= CAN_ERR_CRTL; +		cf->can_dlc = CAN_ERR_DLC; +		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; +		stats->rx_over_errors++; +		stats->rx_errors++; +		netif_rx(skb); +	} + + resubmit_urb: +	usb_fill_bulk_urb(urb, +			  usbcan->udev, +			  usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), +			  hf, +			  sizeof(struct gs_host_frame), +			  gs_usb_recieve_bulk_callback, +			  usbcan +			  ); + +	rc = usb_submit_urb(urb, GFP_ATOMIC); + +	/* USB failure take down all interfaces */ +	if (rc == -ENODEV) { +		for (rc = 0; rc < GS_MAX_INTF; rc++) { +			if (usbcan->canch[rc]) +				netif_device_detach(usbcan->canch[rc]->netdev); +		} +	} +} + +static int gs_usb_set_bittiming(struct net_device *netdev) +{ +	struct gs_can *dev = netdev_priv(netdev); +	struct can_bittiming *bt = &dev->can.bittiming; +	struct usb_interface *intf = dev->iface; +	int rc; +	struct gs_device_bittiming *dbt; + +	dbt = kmalloc(sizeof(*dbt), GFP_KERNEL); +	if (!dbt) +		return -ENOMEM; + +	dbt->prop_seg = bt->prop_seg; +	dbt->phase_seg1 = bt->phase_seg1; +	dbt->phase_seg2 = bt->phase_seg2; +	dbt->sjw = bt->sjw; +	dbt->brp = bt->brp; + +	/* request bit timings */ +	rc = usb_control_msg(interface_to_usbdev(intf), +			     usb_sndctrlpipe(interface_to_usbdev(intf), 0), +			     GS_USB_BREQ_BITTIMING, +			     USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     dev->channel, +			     0, +			     dbt, +			     sizeof(*dbt), +			     1000); + +	kfree(dbt); + +	if (rc < 0) +		dev_err(netdev->dev.parent, "Couldn't set bittimings (err=%d)", +			rc); + +	return rc; +} + +static void gs_usb_xmit_callback(struct urb *urb) +{ +	struct gs_tx_context *txc = urb->context; +	struct gs_can *dev = txc->dev; +	struct net_device *netdev = dev->netdev; + +	if (urb->status) +		netdev_info(netdev, "usb xmit fail %d\n", txc->echo_id); + +	usb_free_coherent(urb->dev, +			  urb->transfer_buffer_length, +			  urb->transfer_buffer, +			  urb->transfer_dma); + +	atomic_dec(&dev->active_tx_urbs); + +	if (!netif_device_present(netdev)) +		return; + +	if (netif_queue_stopped(netdev)) +		netif_wake_queue(netdev); +} + +static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ +	struct gs_can *dev = netdev_priv(netdev); +	struct net_device_stats *stats = &dev->netdev->stats; +	struct urb *urb; +	struct gs_host_frame *hf; +	struct can_frame *cf; +	int rc; +	unsigned int idx; +	struct gs_tx_context *txc; + +	if (can_dropped_invalid_skb(netdev, skb)) +		return NETDEV_TX_OK; + +	/* find an empty context to keep track of transmission */ +	txc = gs_alloc_tx_context(dev); +	if (!txc) +		return NETDEV_TX_BUSY; + +	/* create a URB, and a buffer for it */ +	urb = usb_alloc_urb(0, GFP_ATOMIC); +	if (!urb) { +		netdev_err(netdev, "No memory left for URB\n"); +		goto nomem_urb; +	} + +	hf = usb_alloc_coherent(dev->udev, sizeof(*hf), GFP_ATOMIC, +				&urb->transfer_dma); +	if (!hf) { +		netdev_err(netdev, "No memory left for USB buffer\n"); +		goto nomem_hf; +	} + +	idx = txc->echo_id; + +	if (idx >= GS_MAX_TX_URBS) { +		netdev_err(netdev, "Invalid tx context %d\n", idx); +		goto badidx; +	} + +	hf->echo_id = idx; +	hf->channel = dev->channel; + +	cf = (struct can_frame *)skb->data; + +	hf->can_id = cf->can_id; +	hf->can_dlc = cf->can_dlc; +	memcpy(hf->data, cf->data, cf->can_dlc); + +	usb_fill_bulk_urb(urb, dev->udev, +			  usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT), +			  hf, +			  sizeof(*hf), +			  gs_usb_xmit_callback, +			  txc); + +	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +	usb_anchor_urb(urb, &dev->tx_submitted); + +	can_put_echo_skb(skb, netdev, idx); + +	atomic_inc(&dev->active_tx_urbs); + +	rc = usb_submit_urb(urb, GFP_ATOMIC); +	if (unlikely(rc)) {			/* usb send failed */ +		atomic_dec(&dev->active_tx_urbs); + +		can_free_echo_skb(netdev, idx); +		gs_free_tx_context(txc); + +		usb_unanchor_urb(urb); +		usb_free_coherent(dev->udev, +				  sizeof(*hf), +				  hf, +				  urb->transfer_dma); + + +		if (rc == -ENODEV) { +			netif_device_detach(netdev); +		} else { +			netdev_err(netdev, "usb_submit failed (err=%d)\n", rc); +			stats->tx_dropped++; +		} +	} else { +		/* Slow down tx path */ +		if (atomic_read(&dev->active_tx_urbs) >= GS_MAX_TX_URBS) +			netif_stop_queue(netdev); +	} + +	/* let usb core take care of this urb */ +	usb_free_urb(urb); + +	return NETDEV_TX_OK; + + badidx: +	usb_free_coherent(dev->udev, +			  sizeof(*hf), +			  hf, +			  urb->transfer_dma); + nomem_hf: +	usb_free_urb(urb); + + nomem_urb: +	gs_free_tx_context(txc); +	dev_kfree_skb(skb); +	stats->tx_dropped++; +	return NETDEV_TX_OK; +} + +static int gs_can_open(struct net_device *netdev) +{ +	struct gs_can *dev = netdev_priv(netdev); +	struct gs_usb *parent = dev->parent; +	int rc, i; +	struct gs_device_mode *dm; +	u32 ctrlmode; + +	rc = open_candev(netdev); +	if (rc) +		return rc; + +	if (atomic_add_return(1, &parent->active_channels) == 1) { +		for (i = 0; i < GS_MAX_RX_URBS; i++) { +			struct urb *urb; +			u8 *buf; + +			/* alloc rx urb */ +			urb = usb_alloc_urb(0, GFP_KERNEL); +			if (!urb) { +				netdev_err(netdev, +					   "No memory left for URB\n"); +				return -ENOMEM; +			} + +			/* alloc rx buffer */ +			buf = usb_alloc_coherent(dev->udev, +						 sizeof(struct gs_host_frame), +						 GFP_KERNEL, +						 &urb->transfer_dma); +			if (!buf) { +				netdev_err(netdev, +					   "No memory left for USB buffer\n"); +				usb_free_urb(urb); +				return -ENOMEM; +			} + +			/* fill, anchor, and submit rx urb */ +			usb_fill_bulk_urb(urb, +					  dev->udev, +					  usb_rcvbulkpipe(dev->udev, +							  GSUSB_ENDPOINT_IN), +					  buf, +					  sizeof(struct gs_host_frame), +					  gs_usb_recieve_bulk_callback, +					  parent); +			urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + +			usb_anchor_urb(urb, &parent->rx_submitted); + +			rc = usb_submit_urb(urb, GFP_KERNEL); +			if (rc) { +				if (rc == -ENODEV) +					netif_device_detach(dev->netdev); + +				netdev_err(netdev, +					   "usb_submit failed (err=%d)\n", +					   rc); + +				usb_unanchor_urb(urb); +				break; +			} + +			/* Drop reference, +			 * USB core will take care of freeing it +			 */ +			usb_free_urb(urb); +		} +	} + +	dm = kmalloc(sizeof(*dm), GFP_KERNEL); +	if (!dm) +		return -ENOMEM; + +	/* flags */ +	ctrlmode = dev->can.ctrlmode; +	dm->flags = 0; + +	if (ctrlmode & CAN_CTRLMODE_LOOPBACK) +		dm->flags |= GS_CAN_MODE_LOOP_BACK; +	else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) +		dm->flags |= GS_CAN_MODE_LISTEN_ONLY; + +	/* Controller is not allowed to retry TX +	 * this mode is unavailable on atmels uc3c hardware +	 */ +	if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) +		dm->flags |= GS_CAN_MODE_ONE_SHOT; + +	if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) +		dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE; + +	/* finally start device */ +	dm->mode = GS_CAN_MODE_START; +	rc = usb_control_msg(interface_to_usbdev(dev->iface), +			     usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), +			     GS_USB_BREQ_MODE, +			     USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     dev->channel, +			     0, +			     dm, +			     sizeof(*dm), +			     1000); + +	if (rc < 0) { +		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc); +		kfree(dm); +		return rc; +	} + +	kfree(dm); + +	dev->can.state = CAN_STATE_ERROR_ACTIVE; + +	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) +		netif_start_queue(netdev); + +	return 0; +} + +static int gs_can_close(struct net_device *netdev) +{ +	int rc; +	struct gs_can *dev = netdev_priv(netdev); +	struct gs_usb *parent = dev->parent; + +	netif_stop_queue(netdev); + +	/* Stop polling */ +	if (atomic_dec_and_test(&parent->active_channels)) +		usb_kill_anchored_urbs(&parent->rx_submitted); + +	/* Stop sending URBs */ +	usb_kill_anchored_urbs(&dev->tx_submitted); +	atomic_set(&dev->active_tx_urbs, 0); + +	/* reset the device */ +	rc = gs_cmd_reset(parent, dev); +	if (rc < 0) +		netdev_warn(netdev, "Couldn't shutdown device (err=%d)", rc); + +	/* reset tx contexts */ +	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) { +		dev->tx_context[rc].dev = dev; +		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; +	} + +	/* close the netdev */ +	close_candev(netdev); + +	return 0; +} + +static const struct net_device_ops gs_usb_netdev_ops = { +	.ndo_open = gs_can_open, +	.ndo_stop = gs_can_close, +	.ndo_start_xmit = gs_can_start_xmit, +}; + +static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface *intf) +{ +	struct gs_can *dev; +	struct net_device *netdev; +	int rc; +	struct gs_device_bt_const *bt_const; + +	bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); +	if (!bt_const) +		return ERR_PTR(-ENOMEM); + +	/* fetch bit timing constants */ +	rc = usb_control_msg(interface_to_usbdev(intf), +			     usb_rcvctrlpipe(interface_to_usbdev(intf), 0), +			     GS_USB_BREQ_BT_CONST, +			     USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     channel, +			     0, +			     bt_const, +			     sizeof(*bt_const), +			     1000); + +	if (rc < 0) { +		dev_err(&intf->dev, +			"Couldn't get bit timing const for channel (err=%d)\n", +			rc); +		kfree(bt_const); +		return ERR_PTR(rc); +	} + +	/* create netdev */ +	netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS); +	if (!netdev) { +		dev_err(&intf->dev, "Couldn't allocate candev\n"); +		kfree(bt_const); +		return ERR_PTR(-ENOMEM); +	} + +	dev = netdev_priv(netdev); + +	netdev->netdev_ops = &gs_usb_netdev_ops; + +	netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */ + +	/* dev settup */ +	strcpy(dev->bt_const.name, "gs_usb"); +	dev->bt_const.tseg1_min = bt_const->tseg1_min; +	dev->bt_const.tseg1_max = bt_const->tseg1_max; +	dev->bt_const.tseg2_min = bt_const->tseg2_min; +	dev->bt_const.tseg2_max = bt_const->tseg2_max; +	dev->bt_const.sjw_max = bt_const->sjw_max; +	dev->bt_const.brp_min = bt_const->brp_min; +	dev->bt_const.brp_max = bt_const->brp_max; +	dev->bt_const.brp_inc = bt_const->brp_inc; + +	dev->udev = interface_to_usbdev(intf); +	dev->iface = intf; +	dev->netdev = netdev; +	dev->channel = channel; + +	init_usb_anchor(&dev->tx_submitted); +	atomic_set(&dev->active_tx_urbs, 0); +	spin_lock_init(&dev->tx_ctx_lock); +	for (rc = 0; rc < GS_MAX_TX_URBS; rc++) { +		dev->tx_context[rc].dev = dev; +		dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; +	} + +	/* can settup */ +	dev->can.state = CAN_STATE_STOPPED; +	dev->can.clock.freq = bt_const->fclk_can; +	dev->can.bittiming_const = &dev->bt_const; +	dev->can.do_set_bittiming = gs_usb_set_bittiming; + +	dev->can.ctrlmode_supported = 0; + +	if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) +		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; + +	if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) +		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK; + +	if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) +		dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + +	if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) +		dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; + +	kfree(bt_const); + +	SET_NETDEV_DEV(netdev, &intf->dev); + +	rc = register_candev(dev->netdev); +	if (rc) { +		free_candev(dev->netdev); +		dev_err(&intf->dev, "Couldn't register candev (err=%d)\n", rc); +		return ERR_PTR(rc); +	} + +	return dev; +} + +static void gs_destroy_candev(struct gs_can *dev) +{ +	unregister_candev(dev->netdev); +	free_candev(dev->netdev); +	usb_kill_anchored_urbs(&dev->tx_submitted); +	kfree(dev); +} + +static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ +	struct gs_usb *dev; +	int rc = -ENOMEM; +	unsigned int icount, i; +	struct gs_host_config *hconf; +	struct gs_device_config *dconf; + +	hconf = kmalloc(sizeof(*hconf), GFP_KERNEL); +	if (!hconf) +		return -ENOMEM; + +	hconf->byte_order = 0x0000beef; + +	/* send host config */ +	rc = usb_control_msg(interface_to_usbdev(intf), +			     usb_sndctrlpipe(interface_to_usbdev(intf), 0), +			     GS_USB_BREQ_HOST_FORMAT, +			     USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     1, +			     intf->altsetting[0].desc.bInterfaceNumber, +			     hconf, +			     sizeof(*hconf), +			     1000); + +	kfree(hconf); + +	if (rc < 0) { +		dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", +			rc); +		return rc; +	} + +	dconf = kmalloc(sizeof(*dconf), GFP_KERNEL); +	if (!dconf) +		return -ENOMEM; + +	/* read device config */ +	rc = usb_control_msg(interface_to_usbdev(intf), +			     usb_rcvctrlpipe(interface_to_usbdev(intf), 0), +			     GS_USB_BREQ_DEVICE_CONFIG, +			     USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +			     1, +			     intf->altsetting[0].desc.bInterfaceNumber, +			     dconf, +			     sizeof(*dconf), +			     1000); +	if (rc < 0) { +		dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n", +			rc); + +		kfree(dconf); + +		return rc; +	} + +	icount = dconf->icount+1; + +	kfree(dconf); + +	dev_info(&intf->dev, "Configuring for %d interfaces\n", icount); + +	if (icount > GS_MAX_INTF) { +		dev_err(&intf->dev, +			"Driver cannot handle more that %d CAN interfaces\n", +			GS_MAX_INTF); +		return -EINVAL; +	} + +	dev = kzalloc(sizeof(*dev), GFP_KERNEL); +	init_usb_anchor(&dev->rx_submitted); + +	atomic_set(&dev->active_channels, 0); + +	usb_set_intfdata(intf, dev); +	dev->udev = interface_to_usbdev(intf); + +	for (i = 0; i < icount; i++) { +		dev->canch[i] = gs_make_candev(i, intf); +		if (IS_ERR_OR_NULL(dev->canch[i])) { +			/* on failure destroy previously created candevs */ +			icount = i; +			for (i = 0; i < icount; i++) { +				gs_destroy_candev(dev->canch[i]); +				dev->canch[i] = NULL; +			} +			kfree(dev); +			return rc; +		} +		dev->canch[i]->parent = dev; +	} + +	return 0; +} + +static void gs_usb_disconnect(struct usb_interface *intf) +{ +	unsigned i; +	struct gs_usb *dev = usb_get_intfdata(intf); +	usb_set_intfdata(intf, NULL); + +	if (!dev) { +		dev_err(&intf->dev, "Disconnect (nodata)\n"); +		return; +	} + +	for (i = 0; i < GS_MAX_INTF; i++) { +		struct gs_can *can = dev->canch[i]; + +		if (!can) +			continue; + +		gs_destroy_candev(can); +	} + +	usb_kill_anchored_urbs(&dev->rx_submitted); +} + +static const struct usb_device_id gs_usb_table[] = { +	{USB_DEVICE(USB_GSUSB_1_VENDOR_ID, USB_GSUSB_1_PRODUCT_ID)}, +	{} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, gs_usb_table); + +static struct usb_driver gs_usb_driver = { +	.name       = "gs_usb", +	.probe      = gs_usb_probe, +	.disconnect = gs_usb_disconnect, +	.id_table   = gs_usb_table, +}; + +module_usb_driver(gs_usb_driver); + +MODULE_AUTHOR("Maximilian Schneider <mws@schneidersoft.net>"); +MODULE_DESCRIPTION( +"Socket CAN device driver for Geschwister Schneider Technologie-, " +"Entwicklungs- und Vertriebs UG. USB2.0 to CAN interfaces."); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 3b954658824..541fb7a0562 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -12,7 +12,6 @@   * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>   */ -#include <linux/init.h>  #include <linux/completion.h>  #include <linux/module.h>  #include <linux/netdevice.h> @@ -54,6 +53,8 @@  #define USB_OEM_MERCURY_PRODUCT_ID	34  #define USB_OEM_LEAF_PRODUCT_ID		35  #define USB_CAN_R_PRODUCT_ID		39 +#define USB_LEAF_LITE_V2_PRODUCT_ID	288 +#define USB_MINI_PCIE_HS_PRODUCT_ID	289  /* USB devices features */  #define KVASER_HAS_SILENT_MODE		BIT(0) @@ -357,6 +358,8 @@ static const struct usb_device_id kvaser_usb_table[] = {  		.driver_info = KVASER_HAS_TXRX_ERRORS },  	{ USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),  		.driver_info = KVASER_HAS_TXRX_ERRORS }, +	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) }, +	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) },  	{ }  };  MODULE_DEVICE_TABLE(usb, kvaser_usb_table); @@ -380,38 +383,43 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,  	void *buf;  	int actual_len;  	int err; -	int pos = 0; +	int pos; +	unsigned long to = jiffies + msecs_to_jiffies(USB_RECV_TIMEOUT);  	buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);  	if (!buf)  		return -ENOMEM; -	err = usb_bulk_msg(dev->udev, -			   usb_rcvbulkpipe(dev->udev, -					   dev->bulk_in->bEndpointAddress), -			   buf, RX_BUFFER_SIZE, &actual_len, -			   USB_RECV_TIMEOUT); -	if (err < 0) -		goto end; +	do { +		err = usb_bulk_msg(dev->udev, +				   usb_rcvbulkpipe(dev->udev, +					dev->bulk_in->bEndpointAddress), +				   buf, RX_BUFFER_SIZE, &actual_len, +				   USB_RECV_TIMEOUT); +		if (err < 0) +			goto end; -	while (pos <= actual_len - MSG_HEADER_LEN) { -		tmp = buf + pos; +		pos = 0; +		while (pos <= actual_len - MSG_HEADER_LEN) { +			tmp = buf + pos; -		if (!tmp->len) -			break; +			if (!tmp->len) +				break; -		if (pos + tmp->len > actual_len) { -			dev_err(dev->udev->dev.parent, "Format error\n"); -			break; -		} +			if (pos + tmp->len > actual_len) { +				dev_err(dev->udev->dev.parent, +					"Format error\n"); +				break; +			} -		if (tmp->id == id) { -			memcpy(msg, tmp, tmp->len); -			goto end; -		} +			if (tmp->id == id) { +				memcpy(msg, tmp, tmp->len); +				goto end; +			} -		pos += tmp->len; -	} +			pos += tmp->len; +		} +	} while (time_before(jiffies, to));  	err = -EINVAL; @@ -474,6 +482,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev)  		return err;  	dev->nchannels = msg.u.cardinfo.nchannels; +	if (dev->nchannels > MAX_NET_DEVICES) +		return -EINVAL;  	return 0;  } @@ -1387,6 +1397,7 @@ static const struct net_device_ops kvaser_usb_netdev_ops = {  	.ndo_open = kvaser_usb_open,  	.ndo_stop = kvaser_usb_close,  	.ndo_start_xmit = kvaser_usb_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static const struct can_bittiming_const kvaser_usb_bittiming_const = { @@ -1528,6 +1539,7 @@ static int kvaser_usb_init_one(struct usb_interface *intf,  	netdev->netdev_ops = &kvaser_usb_netdev_ops;  	SET_NETDEV_DEV(netdev, &intf->dev); +	netdev->dev_id = channel;  	dev->nets[channel] = priv; @@ -1544,9 +1556,9 @@ static int kvaser_usb_init_one(struct usb_interface *intf,  	return 0;  } -static void kvaser_usb_get_endpoints(const struct usb_interface *intf, -				     struct usb_endpoint_descriptor **in, -				     struct usb_endpoint_descriptor **out) +static int kvaser_usb_get_endpoints(const struct usb_interface *intf, +				    struct usb_endpoint_descriptor **in, +				    struct usb_endpoint_descriptor **out)  {  	const struct usb_host_interface *iface_desc;  	struct usb_endpoint_descriptor *endpoint; @@ -1557,12 +1569,18 @@ static void kvaser_usb_get_endpoints(const struct usb_interface *intf,  	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {  		endpoint = &iface_desc->endpoint[i].desc; -		if (usb_endpoint_is_bulk_in(endpoint)) +		if (!*in && usb_endpoint_is_bulk_in(endpoint))  			*in = endpoint; -		if (usb_endpoint_is_bulk_out(endpoint)) +		if (!*out && usb_endpoint_is_bulk_out(endpoint))  			*out = endpoint; + +		/* use first bulk endpoint for in and out */ +		if (*in && *out) +			return 0;  	} + +	return -ENODEV;  }  static int kvaser_usb_probe(struct usb_interface *intf, @@ -1576,8 +1594,8 @@ static int kvaser_usb_probe(struct usb_interface *intf,  	if (!dev)  		return -ENOMEM; -	kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out); -	if (!dev->bulk_in || !dev->bulk_out) { +	err = kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out); +	if (err) {  		dev_err(&intf->dev, "Cannot get usb endpoint(s)");  		return err;  	} diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index a0f647f92bf..644e6ab8a48 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -463,7 +463,7 @@ static int peak_usb_start(struct peak_usb_device *dev)  	if (i < PCAN_USB_MAX_TX_URBS) {  		if (i == 0) {  			netdev_err(netdev, "couldn't setup any tx URB\n"); -			return err; +			goto err_tx;  		}  		netdev_warn(netdev, "tx performance may be slow\n"); @@ -472,7 +472,7 @@ static int peak_usb_start(struct peak_usb_device *dev)  	if (dev->adapter->dev_start) {  		err = dev->adapter->dev_start(dev);  		if (err) -			goto failed; +			goto err_adapter;  	}  	dev->state |= PCAN_USB_STATE_STARTED; @@ -481,19 +481,26 @@ static int peak_usb_start(struct peak_usb_device *dev)  	if (dev->adapter->dev_set_bus) {  		err = dev->adapter->dev_set_bus(dev, 1);  		if (err) -			goto failed; +			goto err_adapter;  	}  	dev->can.state = CAN_STATE_ERROR_ACTIVE;  	return 0; -failed: +err_adapter:  	if (err == -ENODEV)  		netif_device_detach(dev->netdev);  	netdev_warn(netdev, "couldn't submit control: %d\n", err); +	for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) { +		usb_free_urb(dev->tx_contexts[i].urb); +		dev->tx_contexts[i].urb = NULL; +	} +err_tx: +	usb_kill_anchored_urbs(&dev->rx_submitted); +  	return err;  } @@ -695,6 +702,7 @@ static const struct net_device_ops peak_usb_netdev_ops = {  	.ndo_open = peak_usb_ndo_open,  	.ndo_stop = peak_usb_ndo_stop,  	.ndo_start_xmit = peak_usb_ndo_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  /* @@ -762,6 +770,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,  	usb_set_intfdata(intf, dev);  	SET_NETDEV_DEV(netdev, &intf->dev); +	netdev->dev_id = ctrl_idx;  	err = register_candev(netdev);  	if (err) { diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 8ee9d1556e6..263dd921edc 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)  	/* set LED in default state (end of init phase) */  	pcan_usb_pro_set_led(dev, 0, 1); +	kfree(bi); +	kfree(fi); +  	return 0;   err_out: diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index 8becd3d838b..ef674ecb82f 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -23,7 +23,6 @@   * who were very cooperative and answered my questions.   */ -#include <linux/init.h>  #include <linux/signal.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -698,8 +697,8 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,  	return NETDEV_TX_OK;  nofreecontext: -	usb_unanchor_urb(urb);  	usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); +	usb_free_urb(urb);  	netdev_warn(netdev, "couldn't find free context"); @@ -888,6 +887,7 @@ static const struct net_device_ops usb_8dev_netdev_ops = {  	.ndo_open = usb_8dev_open,  	.ndo_stop = usb_8dev_close,  	.ndo_start_xmit = usb_8dev_start_xmit, +	.ndo_change_mtu = can_change_mtu,  };  static const struct can_bittiming_const usb_8dev_bittiming_const = { diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0a2a5ee79a1..4e94057ef5c 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -46,6 +46,7 @@  #include <linux/if_ether.h>  #include <linux/can.h>  #include <linux/can/dev.h> +#include <linux/can/skb.h>  #include <linux/slab.h>  #include <net/rtnetlink.h> @@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)  			stats->rx_packets++;  			stats->rx_bytes += cfd->len;  		} -		kfree_skb(skb); +		consume_skb(skb);  		return NETDEV_TX_OK;  	}  	/* perform standard echo handling for CAN network interfaces */  	if (loop) { -		struct sock *srcsk = skb->sk; -		skb = skb_share_check(skb, GFP_ATOMIC); +		skb = can_create_echo_skb(skb);  		if (!skb)  			return NETDEV_TX_OK;  		/* receive with packet counting */ -		skb->sk = srcsk;  		vcan_rx(skb, dev);  	} else {  		/* no looped packets => no counting */ -		kfree_skb(skb); +		consume_skb(skb);  	}  	return NETDEV_TX_OK;  } diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c new file mode 100644 index 00000000000..5e8b5609c06 --- /dev/null +++ b/drivers/net/can/xilinx_can.c @@ -0,0 +1,1208 @@ +/* Xilinx CAN device driver + * + * Copyright (C) 2012 - 2014 Xilinx, Inc. + * Copyright (C) 2009 PetaLogix. All rights reserved. + * + * Description: + * This driver is developed for Axi CAN IP and for Zynq CANPS Controller. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/skbuff.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> +#include <linux/can/led.h> + +#define DRIVER_NAME	"xilinx_can" + +/* CAN registers set */ +enum xcan_reg { +	XCAN_SRR_OFFSET		= 0x00, /* Software reset */ +	XCAN_MSR_OFFSET		= 0x04, /* Mode select */ +	XCAN_BRPR_OFFSET	= 0x08, /* Baud rate prescaler */ +	XCAN_BTR_OFFSET		= 0x0C, /* Bit timing */ +	XCAN_ECR_OFFSET		= 0x10, /* Error counter */ +	XCAN_ESR_OFFSET		= 0x14, /* Error status */ +	XCAN_SR_OFFSET		= 0x18, /* Status */ +	XCAN_ISR_OFFSET		= 0x1C, /* Interrupt status */ +	XCAN_IER_OFFSET		= 0x20, /* Interrupt enable */ +	XCAN_ICR_OFFSET		= 0x24, /* Interrupt clear */ +	XCAN_TXFIFO_ID_OFFSET	= 0x30,/* TX FIFO ID */ +	XCAN_TXFIFO_DLC_OFFSET	= 0x34, /* TX FIFO DLC */ +	XCAN_TXFIFO_DW1_OFFSET	= 0x38, /* TX FIFO Data Word 1 */ +	XCAN_TXFIFO_DW2_OFFSET	= 0x3C, /* TX FIFO Data Word 2 */ +	XCAN_RXFIFO_ID_OFFSET	= 0x50, /* RX FIFO ID */ +	XCAN_RXFIFO_DLC_OFFSET	= 0x54, /* RX FIFO DLC */ +	XCAN_RXFIFO_DW1_OFFSET	= 0x58, /* RX FIFO Data Word 1 */ +	XCAN_RXFIFO_DW2_OFFSET	= 0x5C, /* RX FIFO Data Word 2 */ +}; + +/* CAN register bit masks - XCAN_<REG>_<BIT>_MASK */ +#define XCAN_SRR_CEN_MASK		0x00000002 /* CAN enable */ +#define XCAN_SRR_RESET_MASK		0x00000001 /* Soft Reset the CAN core */ +#define XCAN_MSR_LBACK_MASK		0x00000002 /* Loop back mode select */ +#define XCAN_MSR_SLEEP_MASK		0x00000001 /* Sleep mode select */ +#define XCAN_BRPR_BRP_MASK		0x000000FF /* Baud rate prescaler */ +#define XCAN_BTR_SJW_MASK		0x00000180 /* Synchronous jump width */ +#define XCAN_BTR_TS2_MASK		0x00000070 /* Time segment 2 */ +#define XCAN_BTR_TS1_MASK		0x0000000F /* Time segment 1 */ +#define XCAN_ECR_REC_MASK		0x0000FF00 /* Receive error counter */ +#define XCAN_ECR_TEC_MASK		0x000000FF /* Transmit error counter */ +#define XCAN_ESR_ACKER_MASK		0x00000010 /* ACK error */ +#define XCAN_ESR_BERR_MASK		0x00000008 /* Bit error */ +#define XCAN_ESR_STER_MASK		0x00000004 /* Stuff error */ +#define XCAN_ESR_FMER_MASK		0x00000002 /* Form error */ +#define XCAN_ESR_CRCER_MASK		0x00000001 /* CRC error */ +#define XCAN_SR_TXFLL_MASK		0x00000400 /* TX FIFO is full */ +#define XCAN_SR_ESTAT_MASK		0x00000180 /* Error status */ +#define XCAN_SR_ERRWRN_MASK		0x00000040 /* Error warning */ +#define XCAN_SR_NORMAL_MASK		0x00000008 /* Normal mode */ +#define XCAN_SR_LBACK_MASK		0x00000002 /* Loop back mode */ +#define XCAN_SR_CONFIG_MASK		0x00000001 /* Configuration mode */ +#define XCAN_IXR_TXFEMP_MASK		0x00004000 /* TX FIFO Empty */ +#define XCAN_IXR_WKUP_MASK		0x00000800 /* Wake up interrupt */ +#define XCAN_IXR_SLP_MASK		0x00000400 /* Sleep interrupt */ +#define XCAN_IXR_BSOFF_MASK		0x00000200 /* Bus off interrupt */ +#define XCAN_IXR_ERROR_MASK		0x00000100 /* Error interrupt */ +#define XCAN_IXR_RXNEMP_MASK		0x00000080 /* RX FIFO NotEmpty intr */ +#define XCAN_IXR_RXOFLW_MASK		0x00000040 /* RX FIFO Overflow intr */ +#define XCAN_IXR_RXOK_MASK		0x00000010 /* Message received intr */ +#define XCAN_IXR_TXFLL_MASK		0x00000004 /* Tx FIFO Full intr */ +#define XCAN_IXR_TXOK_MASK		0x00000002 /* TX successful intr */ +#define XCAN_IXR_ARBLST_MASK		0x00000001 /* Arbitration lost intr */ +#define XCAN_IDR_ID1_MASK		0xFFE00000 /* Standard msg identifier */ +#define XCAN_IDR_SRR_MASK		0x00100000 /* Substitute remote TXreq */ +#define XCAN_IDR_IDE_MASK		0x00080000 /* Identifier extension */ +#define XCAN_IDR_ID2_MASK		0x0007FFFE /* Extended message ident */ +#define XCAN_IDR_RTR_MASK		0x00000001 /* Remote TX request */ +#define XCAN_DLCR_DLC_MASK		0xF0000000 /* Data length code */ + +#define XCAN_INTR_ALL		(XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\ +				 XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \ +				 XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \ +				 XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK) + +/* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */ +#define XCAN_BTR_SJW_SHIFT		7  /* Synchronous jump width */ +#define XCAN_BTR_TS2_SHIFT		4  /* Time segment 2 */ +#define XCAN_IDR_ID1_SHIFT		21 /* Standard Messg Identifier */ +#define XCAN_IDR_ID2_SHIFT		1  /* Extended Message Identifier */ +#define XCAN_DLCR_DLC_SHIFT		28 /* Data length code */ +#define XCAN_ESR_REC_SHIFT		8  /* Rx Error Count */ + +/* CAN frame length constants */ +#define XCAN_FRAME_MAX_DATA_LEN		8 +#define XCAN_TIMEOUT			(1 * HZ) + +/** + * struct xcan_priv - This definition define CAN driver instance + * @can:			CAN private data structure. + * @tx_head:			Tx CAN packets ready to send on the queue + * @tx_tail:			Tx CAN packets successfully sended on the queue + * @tx_max:			Maximum number packets the driver can send + * @napi:			NAPI structure + * @read_reg:			For reading data from CAN registers + * @write_reg:			For writing data to CAN registers + * @dev:			Network device data structure + * @reg_base:			Ioremapped address to registers + * @irq_flags:			For request_irq() + * @bus_clk:			Pointer to struct clk + * @can_clk:			Pointer to struct clk + */ +struct xcan_priv { +	struct can_priv can; +	unsigned int tx_head; +	unsigned int tx_tail; +	unsigned int tx_max; +	struct napi_struct napi; +	u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); +	void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, +			u32 val); +	struct net_device *dev; +	void __iomem *reg_base; +	unsigned long irq_flags; +	struct clk *bus_clk; +	struct clk *can_clk; +}; + +/* CAN Bittiming constants as per Xilinx CAN specs */ +static const struct can_bittiming_const xcan_bittiming_const = { +	.name = DRIVER_NAME, +	.tseg1_min = 1, +	.tseg1_max = 16, +	.tseg2_min = 1, +	.tseg2_max = 8, +	.sjw_max = 4, +	.brp_min = 1, +	.brp_max = 256, +	.brp_inc = 1, +}; + +/** + * xcan_write_reg_le - Write a value to the device register little endian + * @priv:	Driver private data structure + * @reg:	Register offset + * @val:	Value to write at the Register offset + * + * Write data to the paricular CAN register + */ +static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, +			u32 val) +{ +	iowrite32(val, priv->reg_base + reg); +} + +/** + * xcan_read_reg_le - Read a value from the device register little endian + * @priv:	Driver private data structure + * @reg:	Register offset + * + * Read data from the particular CAN register + * Return: value read from the CAN register + */ +static u32 xcan_read_reg_le(const struct xcan_priv *priv, enum xcan_reg reg) +{ +	return ioread32(priv->reg_base + reg); +} + +/** + * xcan_write_reg_be - Write a value to the device register big endian + * @priv:	Driver private data structure + * @reg:	Register offset + * @val:	Value to write at the Register offset + * + * Write data to the paricular CAN register + */ +static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, +			u32 val) +{ +	iowrite32be(val, priv->reg_base + reg); +} + +/** + * xcan_read_reg_be - Read a value from the device register big endian + * @priv:	Driver private data structure + * @reg:	Register offset + * + * Read data from the particular CAN register + * Return: value read from the CAN register + */ +static u32 xcan_read_reg_be(const struct xcan_priv *priv, enum xcan_reg reg) +{ +	return ioread32be(priv->reg_base + reg); +} + +/** + * set_reset_mode - Resets the CAN device mode + * @ndev:	Pointer to net_device structure + * + * This is the driver reset mode routine.The driver + * enters into configuration mode. + * + * Return: 0 on success and failure value on error + */ +static int set_reset_mode(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	unsigned long timeout; + +	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); + +	timeout = jiffies + XCAN_TIMEOUT; +	while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & XCAN_SR_CONFIG_MASK)) { +		if (time_after(jiffies, timeout)) { +			netdev_warn(ndev, "timed out for config mode\n"); +			return -ETIMEDOUT; +		} +		usleep_range(500, 10000); +	} + +	return 0; +} + +/** + * xcan_set_bittiming - CAN set bit timing routine + * @ndev:	Pointer to net_device structure + * + * This is the driver set bittiming  routine. + * Return: 0 on success and failure value on error + */ +static int xcan_set_bittiming(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	struct can_bittiming *bt = &priv->can.bittiming; +	u32 btr0, btr1; +	u32 is_config_mode; + +	/* Check whether Xilinx CAN is in configuration mode. +	 * It cannot set bit timing if Xilinx CAN is not in configuration mode. +	 */ +	is_config_mode = priv->read_reg(priv, XCAN_SR_OFFSET) & +				XCAN_SR_CONFIG_MASK; +	if (!is_config_mode) { +		netdev_alert(ndev, +		     "BUG! Cannot set bittiming - CAN is not in config mode\n"); +		return -EPERM; +	} + +	/* Setting Baud Rate prescalar value in BRPR Register */ +	btr0 = (bt->brp - 1); + +	/* Setting Time Segment 1 in BTR Register */ +	btr1 = (bt->prop_seg + bt->phase_seg1 - 1); + +	/* Setting Time Segment 2 in BTR Register */ +	btr1 |= (bt->phase_seg2 - 1) << XCAN_BTR_TS2_SHIFT; + +	/* Setting Synchronous jump width in BTR Register */ +	btr1 |= (bt->sjw - 1) << XCAN_BTR_SJW_SHIFT; + +	priv->write_reg(priv, XCAN_BRPR_OFFSET, btr0); +	priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); + +	netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", +			priv->read_reg(priv, XCAN_BRPR_OFFSET), +			priv->read_reg(priv, XCAN_BTR_OFFSET)); + +	return 0; +} + +/** + * xcan_chip_start - This the drivers start routine + * @ndev:	Pointer to net_device structure + * + * This is the drivers start routine. + * Based on the State of the CAN device it puts + * the CAN device into a proper mode. + * + * Return: 0 on success and failure value on error + */ +static int xcan_chip_start(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	u32 err, reg_msr, reg_sr_mask; +	unsigned long timeout; + +	/* Check if it is in reset mode */ +	err = set_reset_mode(ndev); +	if (err < 0) +		return err; + +	err = xcan_set_bittiming(ndev); +	if (err < 0) +		return err; + +	/* Enable interrupts */ +	priv->write_reg(priv, XCAN_IER_OFFSET, XCAN_INTR_ALL); + +	/* Check whether it is loopback mode or normal mode  */ +	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { +		reg_msr = XCAN_MSR_LBACK_MASK; +		reg_sr_mask = XCAN_SR_LBACK_MASK; +	} else { +		reg_msr = 0x0; +		reg_sr_mask = XCAN_SR_NORMAL_MASK; +	} + +	priv->write_reg(priv, XCAN_MSR_OFFSET, reg_msr); +	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); + +	timeout = jiffies + XCAN_TIMEOUT; +	while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { +		if (time_after(jiffies, timeout)) { +			netdev_warn(ndev, +				"timed out for correct mode\n"); +			return -ETIMEDOUT; +		} +	} +	netdev_dbg(ndev, "status:#x%08x\n", +			priv->read_reg(priv, XCAN_SR_OFFSET)); + +	priv->can.state = CAN_STATE_ERROR_ACTIVE; +	return 0; +} + +/** + * xcan_do_set_mode - This sets the mode of the driver + * @ndev:	Pointer to net_device structure + * @mode:	Tells the mode of the driver + * + * This check the drivers state and calls the + * the corresponding modes to set. + * + * Return: 0 on success and failure value on error + */ +static int xcan_do_set_mode(struct net_device *ndev, enum can_mode mode) +{ +	int ret; + +	switch (mode) { +	case CAN_MODE_START: +		ret = xcan_chip_start(ndev); +		if (ret < 0) { +			netdev_err(ndev, "xcan_chip_start failed!\n"); +			return ret; +		} +		netif_wake_queue(ndev); +		break; +	default: +		ret = -EOPNOTSUPP; +		break; +	} + +	return ret; +} + +/** + * xcan_start_xmit - Starts the transmission + * @skb:	sk_buff pointer that contains data to be Txed + * @ndev:	Pointer to net_device structure + * + * This function is invoked from upper layers to initiate transmission. This + * function uses the next available free txbuff and populates their fields to + * start the transmission. + * + * Return: 0 on success and failure value on error + */ +static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; +	struct can_frame *cf = (struct can_frame *)skb->data; +	u32 id, dlc, data[2] = {0, 0}; + +	if (can_dropped_invalid_skb(ndev, skb)) +		return NETDEV_TX_OK; + +	/* Check if the TX buffer is full */ +	if (unlikely(priv->read_reg(priv, XCAN_SR_OFFSET) & +			XCAN_SR_TXFLL_MASK)) { +		netif_stop_queue(ndev); +		netdev_err(ndev, "BUG!, TX FIFO full when queue awake!\n"); +		return NETDEV_TX_BUSY; +	} + +	/* Watch carefully on the bit sequence */ +	if (cf->can_id & CAN_EFF_FLAG) { +		/* Extended CAN ID format */ +		id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) & +			XCAN_IDR_ID2_MASK; +		id |= (((cf->can_id & CAN_EFF_MASK) >> +			(CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << +			XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK; + +		/* The substibute remote TX request bit should be "1" +		 * for extended frames as in the Xilinx CAN datasheet +		 */ +		id |= XCAN_IDR_IDE_MASK | XCAN_IDR_SRR_MASK; + +		if (cf->can_id & CAN_RTR_FLAG) +			/* Extended frames remote TX request */ +			id |= XCAN_IDR_RTR_MASK; +	} else { +		/* Standard CAN ID format */ +		id = ((cf->can_id & CAN_SFF_MASK) << XCAN_IDR_ID1_SHIFT) & +			XCAN_IDR_ID1_MASK; + +		if (cf->can_id & CAN_RTR_FLAG) +			/* Standard frames remote TX request */ +			id |= XCAN_IDR_SRR_MASK; +	} + +	dlc = cf->can_dlc << XCAN_DLCR_DLC_SHIFT; + +	if (cf->can_dlc > 0) +		data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); +	if (cf->can_dlc > 4) +		data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); + +	can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max); +	priv->tx_head++; + +	/* Write the Frame to Xilinx CAN TX FIFO */ +	priv->write_reg(priv, XCAN_TXFIFO_ID_OFFSET, id); +	/* If the CAN frame is RTR frame this write triggers tranmission */ +	priv->write_reg(priv, XCAN_TXFIFO_DLC_OFFSET, dlc); +	if (!(cf->can_id & CAN_RTR_FLAG)) { +		priv->write_reg(priv, XCAN_TXFIFO_DW1_OFFSET, data[0]); +		/* If the CAN frame is Standard/Extended frame this +		 * write triggers tranmission +		 */ +		priv->write_reg(priv, XCAN_TXFIFO_DW2_OFFSET, data[1]); +		stats->tx_bytes += cf->can_dlc; +	} + +	/* Check if the TX buffer is full */ +	if ((priv->tx_head - priv->tx_tail) == priv->tx_max) +		netif_stop_queue(ndev); + +	return NETDEV_TX_OK; +} + +/** + * xcan_rx -  Is called from CAN isr to complete the received + *		frame  processing + * @ndev:	Pointer to net_device structure + * + * This function is invoked from the CAN isr(poll) to process the Rx frames. It + * does minimal processing and invokes "netif_receive_skb" to complete further + * processing. + * Return: 1 on success and 0 on failure. + */ +static int xcan_rx(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; +	struct can_frame *cf; +	struct sk_buff *skb; +	u32 id_xcan, dlc, data[2] = {0, 0}; + +	skb = alloc_can_skb(ndev, &cf); +	if (unlikely(!skb)) { +		stats->rx_dropped++; +		return 0; +	} + +	/* Read a frame from Xilinx zynq CANPS */ +	id_xcan = priv->read_reg(priv, XCAN_RXFIFO_ID_OFFSET); +	dlc = priv->read_reg(priv, XCAN_RXFIFO_DLC_OFFSET) >> +				XCAN_DLCR_DLC_SHIFT; + +	/* Change Xilinx CAN data length format to socketCAN data format */ +	cf->can_dlc = get_can_dlc(dlc); + +	/* Change Xilinx CAN ID format to socketCAN ID format */ +	if (id_xcan & XCAN_IDR_IDE_MASK) { +		/* The received frame is an Extended format frame */ +		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; +		cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> +				XCAN_IDR_ID2_SHIFT; +		cf->can_id |= CAN_EFF_FLAG; +		if (id_xcan & XCAN_IDR_RTR_MASK) +			cf->can_id |= CAN_RTR_FLAG; +	} else { +		/* The received frame is a standard format frame */ +		cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> +				XCAN_IDR_ID1_SHIFT; +		if (id_xcan & XCAN_IDR_SRR_MASK) +			cf->can_id |= CAN_RTR_FLAG; +	} + +	if (!(id_xcan & XCAN_IDR_SRR_MASK)) { +		data[0] = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET); +		data[1] = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET); + +		/* Change Xilinx CAN data format to socketCAN data format */ +		if (cf->can_dlc > 0) +			*(__be32 *)(cf->data) = cpu_to_be32(data[0]); +		if (cf->can_dlc > 4) +			*(__be32 *)(cf->data + 4) = cpu_to_be32(data[1]); +	} + +	stats->rx_bytes += cf->can_dlc; +	stats->rx_packets++; +	netif_receive_skb(skb); + +	return 1; +} + +/** + * xcan_err_interrupt - error frame Isr + * @ndev:	net_device pointer + * @isr:	interrupt status register value + * + * This is the CAN error interrupt and it will + * check the the type of error and forward the error + * frame to upper layers. + */ +static void xcan_err_interrupt(struct net_device *ndev, u32 isr) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; +	struct can_frame *cf; +	struct sk_buff *skb; +	u32 err_status, status, txerr = 0, rxerr = 0; + +	skb = alloc_can_err_skb(ndev, &cf); + +	err_status = priv->read_reg(priv, XCAN_ESR_OFFSET); +	priv->write_reg(priv, XCAN_ESR_OFFSET, err_status); +	txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; +	rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & +			XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); +	status = priv->read_reg(priv, XCAN_SR_OFFSET); + +	if (isr & XCAN_IXR_BSOFF_MASK) { +		priv->can.state = CAN_STATE_BUS_OFF; +		priv->can.can_stats.bus_off++; +		/* Leave device in Config Mode in bus-off state */ +		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); +		can_bus_off(ndev); +		if (skb) +			cf->can_id |= CAN_ERR_BUSOFF; +	} else if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) { +		priv->can.state = CAN_STATE_ERROR_PASSIVE; +		priv->can.can_stats.error_passive++; +		if (skb) { +			cf->can_id |= CAN_ERR_CRTL; +			cf->data[1] = (rxerr > 127) ? +					CAN_ERR_CRTL_RX_PASSIVE : +					CAN_ERR_CRTL_TX_PASSIVE; +			cf->data[6] = txerr; +			cf->data[7] = rxerr; +		} +	} else if (status & XCAN_SR_ERRWRN_MASK) { +		priv->can.state = CAN_STATE_ERROR_WARNING; +		priv->can.can_stats.error_warning++; +		if (skb) { +			cf->can_id |= CAN_ERR_CRTL; +			cf->data[1] |= (txerr > rxerr) ? +					CAN_ERR_CRTL_TX_WARNING : +					CAN_ERR_CRTL_RX_WARNING; +			cf->data[6] = txerr; +			cf->data[7] = rxerr; +		} +	} + +	/* Check for Arbitration lost interrupt */ +	if (isr & XCAN_IXR_ARBLST_MASK) { +		priv->can.can_stats.arbitration_lost++; +		if (skb) { +			cf->can_id |= CAN_ERR_LOSTARB; +			cf->data[0] = CAN_ERR_LOSTARB_UNSPEC; +		} +	} + +	/* Check for RX FIFO Overflow interrupt */ +	if (isr & XCAN_IXR_RXOFLW_MASK) { +		stats->rx_over_errors++; +		stats->rx_errors++; +		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); +		if (skb) { +			cf->can_id |= CAN_ERR_CRTL; +			cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; +		} +	} + +	/* Check for error interrupt */ +	if (isr & XCAN_IXR_ERROR_MASK) { +		if (skb) { +			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; +			cf->data[2] |= CAN_ERR_PROT_UNSPEC; +		} + +		/* Check for Ack error interrupt */ +		if (err_status & XCAN_ESR_ACKER_MASK) { +			stats->tx_errors++; +			if (skb) { +				cf->can_id |= CAN_ERR_ACK; +				cf->data[3] |= CAN_ERR_PROT_LOC_ACK; +			} +		} + +		/* Check for Bit error interrupt */ +		if (err_status & XCAN_ESR_BERR_MASK) { +			stats->tx_errors++; +			if (skb) { +				cf->can_id |= CAN_ERR_PROT; +				cf->data[2] = CAN_ERR_PROT_BIT; +			} +		} + +		/* Check for Stuff error interrupt */ +		if (err_status & XCAN_ESR_STER_MASK) { +			stats->rx_errors++; +			if (skb) { +				cf->can_id |= CAN_ERR_PROT; +				cf->data[2] = CAN_ERR_PROT_STUFF; +			} +		} + +		/* Check for Form error interrupt */ +		if (err_status & XCAN_ESR_FMER_MASK) { +			stats->rx_errors++; +			if (skb) { +				cf->can_id |= CAN_ERR_PROT; +				cf->data[2] = CAN_ERR_PROT_FORM; +			} +		} + +		/* Check for CRC error interrupt */ +		if (err_status & XCAN_ESR_CRCER_MASK) { +			stats->rx_errors++; +			if (skb) { +				cf->can_id |= CAN_ERR_PROT; +				cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ | +						CAN_ERR_PROT_LOC_CRC_DEL; +			} +		} +			priv->can.can_stats.bus_error++; +	} + +	if (skb) { +		stats->rx_packets++; +		stats->rx_bytes += cf->can_dlc; +		netif_rx(skb); +	} + +	netdev_dbg(ndev, "%s: error status register:0x%x\n", +			__func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); +} + +/** + * xcan_state_interrupt - It will check the state of the CAN device + * @ndev:	net_device pointer + * @isr:	interrupt status register value + * + * This will checks the state of the CAN device + * and puts the device into appropriate state. + */ +static void xcan_state_interrupt(struct net_device *ndev, u32 isr) +{ +	struct xcan_priv *priv = netdev_priv(ndev); + +	/* Check for Sleep interrupt if set put CAN device in sleep state */ +	if (isr & XCAN_IXR_SLP_MASK) +		priv->can.state = CAN_STATE_SLEEPING; + +	/* Check for Wake up interrupt if set put CAN device in Active state */ +	if (isr & XCAN_IXR_WKUP_MASK) +		priv->can.state = CAN_STATE_ERROR_ACTIVE; +} + +/** + * xcan_rx_poll - Poll routine for rx packets (NAPI) + * @napi:	napi structure pointer + * @quota:	Max number of rx packets to be processed. + * + * This is the poll routine for rx part. + * It will process the packets maximux quota value. + * + * Return: number of packets received + */ +static int xcan_rx_poll(struct napi_struct *napi, int quota) +{ +	struct net_device *ndev = napi->dev; +	struct xcan_priv *priv = netdev_priv(ndev); +	u32 isr, ier; +	int work_done = 0; + +	isr = priv->read_reg(priv, XCAN_ISR_OFFSET); +	while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) { +		if (isr & XCAN_IXR_RXOK_MASK) { +			priv->write_reg(priv, XCAN_ICR_OFFSET, +				XCAN_IXR_RXOK_MASK); +			work_done += xcan_rx(ndev); +		} else { +			priv->write_reg(priv, XCAN_ICR_OFFSET, +				XCAN_IXR_RXNEMP_MASK); +			break; +		} +		priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK); +		isr = priv->read_reg(priv, XCAN_ISR_OFFSET); +	} + +	if (work_done) +		can_led_event(ndev, CAN_LED_EVENT_RX); + +	if (work_done < quota) { +		napi_complete(napi); +		ier = priv->read_reg(priv, XCAN_IER_OFFSET); +		ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK); +		priv->write_reg(priv, XCAN_IER_OFFSET, ier); +	} +	return work_done; +} + +/** + * xcan_tx_interrupt - Tx Done Isr + * @ndev:	net_device pointer + * @isr:	Interrupt status register value + */ +static void xcan_tx_interrupt(struct net_device *ndev, u32 isr) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	struct net_device_stats *stats = &ndev->stats; + +	while ((priv->tx_head - priv->tx_tail > 0) && +			(isr & XCAN_IXR_TXOK_MASK)) { +		priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); +		can_get_echo_skb(ndev, priv->tx_tail % +					priv->tx_max); +		priv->tx_tail++; +		stats->tx_packets++; +		isr = priv->read_reg(priv, XCAN_ISR_OFFSET); +	} +	can_led_event(ndev, CAN_LED_EVENT_TX); +	netif_wake_queue(ndev); +} + +/** + * xcan_interrupt - CAN Isr + * @irq:	irq number + * @dev_id:	device id poniter + * + * This is the xilinx CAN Isr. It checks for the type of interrupt + * and invokes the corresponding ISR. + * + * Return: + * IRQ_NONE - If CAN device is in sleep mode, IRQ_HANDLED otherwise + */ +static irqreturn_t xcan_interrupt(int irq, void *dev_id) +{ +	struct net_device *ndev = (struct net_device *)dev_id; +	struct xcan_priv *priv = netdev_priv(ndev); +	u32 isr, ier; + +	/* Get the interrupt status from Xilinx CAN */ +	isr = priv->read_reg(priv, XCAN_ISR_OFFSET); +	if (!isr) +		return IRQ_NONE; + +	/* Check for the type of interrupt and Processing it */ +	if (isr & (XCAN_IXR_SLP_MASK | XCAN_IXR_WKUP_MASK)) { +		priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_SLP_MASK | +				XCAN_IXR_WKUP_MASK)); +		xcan_state_interrupt(ndev, isr); +	} + +	/* Check for Tx interrupt and Processing it */ +	if (isr & XCAN_IXR_TXOK_MASK) +		xcan_tx_interrupt(ndev, isr); + +	/* Check for the type of error interrupt and Processing it */ +	if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK | +			XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) { +		priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK | +				XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK | +				XCAN_IXR_ARBLST_MASK)); +		xcan_err_interrupt(ndev, isr); +	} + +	/* Check for the type of receive interrupt and Processing it */ +	if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) { +		ier = priv->read_reg(priv, XCAN_IER_OFFSET); +		ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK); +		priv->write_reg(priv, XCAN_IER_OFFSET, ier); +		napi_schedule(&priv->napi); +	} +	return IRQ_HANDLED; +} + +/** + * xcan_chip_stop - Driver stop routine + * @ndev:	Pointer to net_device structure + * + * This is the drivers stop routine. It will disable the + * interrupts and put the device into configuration mode. + */ +static void xcan_chip_stop(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	u32 ier; + +	/* Disable interrupts and leave the can in configuration mode */ +	ier = priv->read_reg(priv, XCAN_IER_OFFSET); +	ier &= ~XCAN_INTR_ALL; +	priv->write_reg(priv, XCAN_IER_OFFSET, ier); +	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); +	priv->can.state = CAN_STATE_STOPPED; +} + +/** + * xcan_open - Driver open routine + * @ndev:	Pointer to net_device structure + * + * This is the driver open routine. + * Return: 0 on success and failure value on error + */ +static int xcan_open(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	int ret; + +	ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, +			ndev->name, ndev); +	if (ret < 0) { +		netdev_err(ndev, "irq allocation for CAN failed\n"); +		goto err; +	} + +	ret = clk_prepare_enable(priv->can_clk); +	if (ret) { +		netdev_err(ndev, "unable to enable device clock\n"); +		goto err_irq; +	} + +	ret = clk_prepare_enable(priv->bus_clk); +	if (ret) { +		netdev_err(ndev, "unable to enable bus clock\n"); +		goto err_can_clk; +	} + +	/* Set chip into reset mode */ +	ret = set_reset_mode(ndev); +	if (ret < 0) { +		netdev_err(ndev, "mode resetting failed!\n"); +		goto err_bus_clk; +	} + +	/* Common open */ +	ret = open_candev(ndev); +	if (ret) +		goto err_bus_clk; + +	ret = xcan_chip_start(ndev); +	if (ret < 0) { +		netdev_err(ndev, "xcan_chip_start failed!\n"); +		goto err_candev; +	} + +	can_led_event(ndev, CAN_LED_EVENT_OPEN); +	napi_enable(&priv->napi); +	netif_start_queue(ndev); + +	return 0; + +err_candev: +	close_candev(ndev); +err_bus_clk: +	clk_disable_unprepare(priv->bus_clk); +err_can_clk: +	clk_disable_unprepare(priv->can_clk); +err_irq: +	free_irq(ndev->irq, ndev); +err: +	return ret; +} + +/** + * xcan_close - Driver close routine + * @ndev:	Pointer to net_device structure + * + * Return: 0 always + */ +static int xcan_close(struct net_device *ndev) +{ +	struct xcan_priv *priv = netdev_priv(ndev); + +	netif_stop_queue(ndev); +	napi_disable(&priv->napi); +	xcan_chip_stop(ndev); +	clk_disable_unprepare(priv->bus_clk); +	clk_disable_unprepare(priv->can_clk); +	free_irq(ndev->irq, ndev); +	close_candev(ndev); + +	can_led_event(ndev, CAN_LED_EVENT_STOP); + +	return 0; +} + +/** + * xcan_get_berr_counter - error counter routine + * @ndev:	Pointer to net_device structure + * @bec:	Pointer to can_berr_counter structure + * + * This is the driver error counter routine. + * Return: 0 on success and failure value on error + */ +static int xcan_get_berr_counter(const struct net_device *ndev, +					struct can_berr_counter *bec) +{ +	struct xcan_priv *priv = netdev_priv(ndev); +	int ret; + +	ret = clk_prepare_enable(priv->can_clk); +	if (ret) +		goto err; + +	ret = clk_prepare_enable(priv->bus_clk); +	if (ret) +		goto err_clk; + +	bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; +	bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & +			XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); + +	clk_disable_unprepare(priv->bus_clk); +	clk_disable_unprepare(priv->can_clk); + +	return 0; + +err_clk: +	clk_disable_unprepare(priv->can_clk); +err: +	return ret; +} + + +static const struct net_device_ops xcan_netdev_ops = { +	.ndo_open	= xcan_open, +	.ndo_stop	= xcan_close, +	.ndo_start_xmit	= xcan_start_xmit, +}; + +/** + * xcan_suspend - Suspend method for the driver + * @dev:	Address of the platform_device structure + * + * Put the driver into low power mode. + * Return: 0 always + */ +static int __maybe_unused xcan_suspend(struct device *dev) +{ +	struct platform_device *pdev = dev_get_drvdata(dev); +	struct net_device *ndev = platform_get_drvdata(pdev); +	struct xcan_priv *priv = netdev_priv(ndev); + +	if (netif_running(ndev)) { +		netif_stop_queue(ndev); +		netif_device_detach(ndev); +	} + +	priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); +	priv->can.state = CAN_STATE_SLEEPING; + +	clk_disable(priv->bus_clk); +	clk_disable(priv->can_clk); + +	return 0; +} + +/** + * xcan_resume - Resume from suspend + * @dev:	Address of the platformdevice structure + * + * Resume operation after suspend. + * Return: 0 on success and failure value on error + */ +static int __maybe_unused xcan_resume(struct device *dev) +{ +	struct platform_device *pdev = dev_get_drvdata(dev); +	struct net_device *ndev = platform_get_drvdata(pdev); +	struct xcan_priv *priv = netdev_priv(ndev); +	int ret; + +	ret = clk_enable(priv->bus_clk); +	if (ret) { +		dev_err(dev, "Cannot enable clock.\n"); +		return ret; +	} +	ret = clk_enable(priv->can_clk); +	if (ret) { +		dev_err(dev, "Cannot enable clock.\n"); +		clk_disable_unprepare(priv->bus_clk); +		return ret; +	} + +	priv->write_reg(priv, XCAN_MSR_OFFSET, 0); +	priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); +	priv->can.state = CAN_STATE_ERROR_ACTIVE; + +	if (netif_running(ndev)) { +		netif_device_attach(ndev); +		netif_start_queue(ndev); +	} + +	return 0; +} + +static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); + +/** + * xcan_probe - Platform registration call + * @pdev:	Handle to the platform device structure + * + * This function does all the memory allocation and registration for the CAN + * device. + * + * Return: 0 on success and failure value on error + */ +static int xcan_probe(struct platform_device *pdev) +{ +	struct resource *res; /* IO mem resources */ +	struct net_device *ndev; +	struct xcan_priv *priv; +	void __iomem *addr; +	int ret, rx_max, tx_max; + +	/* Get the virtual base address for the device */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	addr = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(addr)) { +		ret = PTR_ERR(addr); +		goto err; +	} + +	ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max); +	if (ret < 0) +		goto err; + +	ret = of_property_read_u32(pdev->dev.of_node, "rx-fifo-depth", &rx_max); +	if (ret < 0) +		goto err; + +	/* Create a CAN device instance */ +	ndev = alloc_candev(sizeof(struct xcan_priv), tx_max); +	if (!ndev) +		return -ENOMEM; + +	priv = netdev_priv(ndev); +	priv->dev = ndev; +	priv->can.bittiming_const = &xcan_bittiming_const; +	priv->can.do_set_mode = xcan_do_set_mode; +	priv->can.do_get_berr_counter = xcan_get_berr_counter; +	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | +					CAN_CTRLMODE_BERR_REPORTING; +	priv->reg_base = addr; +	priv->tx_max = tx_max; + +	/* Get IRQ for the device */ +	ndev->irq = platform_get_irq(pdev, 0); +	ndev->flags |= IFF_ECHO;	/* We support local echo */ + +	platform_set_drvdata(pdev, ndev); +	SET_NETDEV_DEV(ndev, &pdev->dev); +	ndev->netdev_ops = &xcan_netdev_ops; + +	/* Getting the CAN can_clk info */ +	priv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); +	if (IS_ERR(priv->can_clk)) { +		dev_err(&pdev->dev, "Device clock not found.\n"); +		ret = PTR_ERR(priv->can_clk); +		goto err_free; +	} +	/* Check for type of CAN device */ +	if (of_device_is_compatible(pdev->dev.of_node, +				    "xlnx,zynq-can-1.0")) { +		priv->bus_clk = devm_clk_get(&pdev->dev, "pclk"); +		if (IS_ERR(priv->bus_clk)) { +			dev_err(&pdev->dev, "bus clock not found\n"); +			ret = PTR_ERR(priv->bus_clk); +			goto err_free; +		} +	} else { +		priv->bus_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); +		if (IS_ERR(priv->bus_clk)) { +			dev_err(&pdev->dev, "bus clock not found\n"); +			ret = PTR_ERR(priv->bus_clk); +			goto err_free; +		} +	} + +	ret = clk_prepare_enable(priv->can_clk); +	if (ret) { +		dev_err(&pdev->dev, "unable to enable device clock\n"); +		goto err_free; +	} + +	ret = clk_prepare_enable(priv->bus_clk); +	if (ret) { +		dev_err(&pdev->dev, "unable to enable bus clock\n"); +		goto err_unprepare_disable_dev; +	} + +	priv->write_reg = xcan_write_reg_le; +	priv->read_reg = xcan_read_reg_le; + +	if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { +		priv->write_reg = xcan_write_reg_be; +		priv->read_reg = xcan_read_reg_be; +	} + +	priv->can.clock.freq = clk_get_rate(priv->can_clk); + +	netif_napi_add(ndev, &priv->napi, xcan_rx_poll, rx_max); + +	ret = register_candev(ndev); +	if (ret) { +		dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); +		goto err_unprepare_disable_busclk; +	} + +	devm_can_led_init(ndev); +	clk_disable_unprepare(priv->bus_clk); +	clk_disable_unprepare(priv->can_clk); +	netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", +			priv->reg_base, ndev->irq, priv->can.clock.freq, +			priv->tx_max); + +	return 0; + +err_unprepare_disable_busclk: +	clk_disable_unprepare(priv->bus_clk); +err_unprepare_disable_dev: +	clk_disable_unprepare(priv->can_clk); +err_free: +	free_candev(ndev); +err: +	return ret; +} + +/** + * xcan_remove - Unregister the device after releasing the resources + * @pdev:	Handle to the platform device structure + * + * This function frees all the resources allocated to the device. + * Return: 0 always + */ +static int xcan_remove(struct platform_device *pdev) +{ +	struct net_device *ndev = platform_get_drvdata(pdev); +	struct xcan_priv *priv = netdev_priv(ndev); + +	if (set_reset_mode(ndev) < 0) +		netdev_err(ndev, "mode resetting failed!\n"); + +	unregister_candev(ndev); +	netif_napi_del(&priv->napi); +	free_candev(ndev); + +	return 0; +} + +/* Match table for OF platform binding */ +static struct of_device_id xcan_of_match[] = { +	{ .compatible = "xlnx,zynq-can-1.0", }, +	{ .compatible = "xlnx,axi-can-1.00.a", }, +	{ /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, xcan_of_match); + +static struct platform_driver xcan_driver = { +	.probe = xcan_probe, +	.remove	= xcan_remove, +	.driver	= { +		.owner = THIS_MODULE, +		.name = DRIVER_NAME, +		.pm = &xcan_dev_pm_ops, +		.of_match_table	= xcan_of_match, +	}, +}; + +module_platform_driver(xcan_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Xilinx Inc"); +MODULE_DESCRIPTION("Xilinx CAN interface");  | 
