diff options
Diffstat (limited to 'drivers/net/can/mscan/mscan.c')
| -rw-r--r-- | drivers/net/can/mscan/mscan.c | 125 | 
1 files changed, 81 insertions, 44 deletions
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 74cd880c7e0..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> @@ -34,7 +33,7 @@  #include "mscan.h" -static struct can_bittiming_const mscan_bittiming_const = { +static const struct can_bittiming_const mscan_bittiming_const = {  	.name = "mscan",  	.tseg1_min = 4,  	.tseg1_max = 16, @@ -62,7 +61,7 @@ static enum can_state state_map[] = {  static int mscan_set_mode(struct net_device *dev, u8 mode)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	int ret = 0;  	int i;  	u8 canctl1; @@ -95,9 +94,9 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)  			 * any, at once.  			 */  			if (i >= MSCAN_SET_MODE_RETRIES) -				dev_dbg(dev->dev.parent, -					"device failed to enter sleep mode. " -					"We proceed anyhow.\n"); +				netdev_dbg(dev, +					   "device failed to enter sleep mode. " +					   "We proceed anyhow.\n");  			else  				priv->can.state = CAN_STATE_SLEEPING;  		} @@ -138,7 +137,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)  static int mscan_start(struct net_device *dev)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	u8 canrflg;  	int err; @@ -178,7 +177,7 @@ static int mscan_restart(struct net_device *dev)  	struct mscan_priv *priv = netdev_priv(dev);  	if (priv->type == MSCAN_TYPE_MPC5121) { -		struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +		struct mscan_regs __iomem *regs = priv->reg_base;  		priv->can.state = CAN_STATE_ERROR_ACTIVE;  		WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD), @@ -199,7 +198,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)  {  	struct can_frame *frame = (struct can_frame *)skb->data;  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	int i, rtr, buf_id;  	u32 can_id; @@ -213,7 +212,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)  	switch (hweight8(i)) {  	case 0:  		netif_stop_queue(dev); -		dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n"); +		netdev_err(dev, "Tx Ring full when queue awake!\n");  		return NETDEV_TX_BUSY;  	case 1:  		/* @@ -246,7 +245,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)  		out_be16(®s->tx.idr3_2, can_id);  		can_id >>= 16; -		/* EFF_FLAGS are inbetween the IDs :( */ +		/* EFF_FLAGS are between the IDs :( */  		can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0)  			 | MSCAN_EFF_FLAGS;  	} else { @@ -261,11 +260,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)  		void __iomem *data = ®s->tx.dsr1_0;  		u16 *payload = (u16 *)frame->data; -		/* It is safe to write into dsr[dlc+1] */ -		for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { +		for (i = 0; i < frame->can_dlc / 2; i++) {  			out_be16(data, *payload++);  			data += 2 + _MSCAN_RESERVED_DSR_SIZE;  		} +		/* write remaining byte if necessary */ +		if (frame->can_dlc & 1) +			out_8(data, frame->data[frame->can_dlc - 1]);  	}  	out_8(®s->tx.dlr, frame->can_dlc); @@ -305,7 +306,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg)  static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	u32 can_id;  	int i; @@ -330,10 +331,13 @@ static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)  		void __iomem *data = ®s->rx.dsr1_0;  		u16 *payload = (u16 *)frame->data; -		for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { +		for (i = 0; i < frame->can_dlc / 2; i++) {  			*payload++ = in_be16(data);  			data += 2 + _MSCAN_RESERVED_DSR_SIZE;  		} +		/* read remaining byte if necessary */ +		if (frame->can_dlc & 1) +			frame->data[frame->can_dlc - 1] = in_8(data);  	}  	out_8(®s->canrflg, MSCAN_RXF); @@ -343,11 +347,11 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,  				u8 canrflg)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	struct net_device_stats *stats = &dev->stats;  	enum can_state old_state; -	dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg); +	netdev_dbg(dev, "error interrupt (canrflg=%#x)\n", canrflg);  	frame->can_id = CAN_ERR_FLAG;  	if (canrflg & MSCAN_OVRIF) { @@ -406,7 +410,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)  {  	struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);  	struct net_device *dev = napi->dev; -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	struct net_device_stats *stats = &dev->stats;  	int npackets = 0;  	int ret = 1; @@ -422,7 +426,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)  		skb = alloc_can_skb(dev, &frame);  		if (!skb) {  			if (printk_ratelimit()) -				dev_notice(dev->dev.parent, "packet dropped\n"); +				netdev_notice(dev, "packet dropped\n");  			stats->rx_dropped++;  			out_8(®s->canrflg, canrflg);  			continue; @@ -453,7 +457,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)  {  	struct net_device *dev = (struct net_device *)dev_id;  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	struct net_device_stats *stats = &dev->stats;  	u8 cantier, cantflg, canrflg;  	irqreturn_t ret = IRQ_NONE; @@ -512,12 +516,8 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)  static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)  { -	struct mscan_priv *priv = netdev_priv(dev);  	int ret = 0; -	if (!priv->open_time) -		return -EINVAL; -  	switch (mode) {  	case CAN_MODE_START:  		ret = mscan_restart(dev); @@ -537,7 +537,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)  static int mscan_do_set_bittiming(struct net_device *dev)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	struct can_bittiming *bt = &priv->can.bittiming;  	u8 btr0, btr1; @@ -546,8 +546,7 @@ static int mscan_do_set_bittiming(struct net_device *dev)  		BTR1_SET_TSEG2(bt->phase_seg2) |  		BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)); -	dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n", -		btr0, btr1); +	netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);  	out_8(®s->canbtr0, btr0);  	out_8(®s->canbtr1, btr1); @@ -555,28 +554,52 @@ static int mscan_do_set_bittiming(struct net_device *dev)  	return 0;  } +static int mscan_get_berr_counter(const struct net_device *dev, +				  struct can_berr_counter *bec) +{ +	struct mscan_priv *priv = netdev_priv(dev); +	struct mscan_regs __iomem *regs = priv->reg_base; + +	bec->txerr = in_8(®s->cantxerr); +	bec->rxerr = in_8(®s->canrxerr); + +	return 0; +} +  static int mscan_open(struct net_device *dev)  {  	int ret;  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base; + +	if (priv->clk_ipg) { +		ret = clk_prepare_enable(priv->clk_ipg); +		if (ret) +			goto exit_retcode; +	} +	if (priv->clk_can) { +		ret = clk_prepare_enable(priv->clk_can); +		if (ret) +			goto exit_dis_ipg_clock; +	}  	/* common open */  	ret = open_candev(dev);  	if (ret) -		return ret; +		goto exit_dis_can_clock;  	napi_enable(&priv->napi);  	ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);  	if (ret < 0) { -		dev_err(dev->dev.parent, "failed to attach interrupt\n"); +		netdev_err(dev, "failed to attach interrupt\n");  		goto exit_napi_disable;  	} -	priv->open_time = jiffies; - -	clrbits8(®s->canctl1, MSCAN_LISTEN); +	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) +		setbits8(®s->canctl1, MSCAN_LISTEN); +	else +		clrbits8(®s->canctl1, MSCAN_LISTEN);  	ret = mscan_start(dev);  	if (ret) @@ -587,18 +610,24 @@ static int mscan_open(struct net_device *dev)  	return 0;  exit_free_irq: -	priv->open_time = 0;  	free_irq(dev->irq, dev);  exit_napi_disable:  	napi_disable(&priv->napi);  	close_candev(dev); +exit_dis_can_clock: +	if (priv->clk_can) +		clk_disable_unprepare(priv->clk_can); +exit_dis_ipg_clock: +	if (priv->clk_ipg) +		clk_disable_unprepare(priv->clk_ipg); +exit_retcode:  	return ret;  }  static int mscan_close(struct net_device *dev)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	netif_stop_queue(dev);  	napi_disable(&priv->napi); @@ -608,21 +637,26 @@ static int mscan_close(struct net_device *dev)  	mscan_set_mode(dev, MSCAN_INIT_MODE);  	close_candev(dev);  	free_irq(dev->irq, dev); -	priv->open_time = 0; + +	if (priv->clk_can) +		clk_disable_unprepare(priv->clk_can); +	if (priv->clk_ipg) +		clk_disable_unprepare(priv->clk_ipg);  	return 0;  }  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)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	u8 ctl1;  	ctl1 = in_8(®s->canctl1); @@ -631,8 +665,10 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)  	else  		ctl1 &= ~MSCAN_CLKSRC; -	if (priv->type == MSCAN_TYPE_MPC5121) +	if (priv->type == MSCAN_TYPE_MPC5121) { +		priv->can.do_get_berr_counter = mscan_get_berr_counter;  		ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */ +	}  	ctl1 |= MSCAN_CANE;  	out_8(®s->canctl1, ctl1); @@ -659,7 +695,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)  void unregister_mscandev(struct net_device *dev)  {  	struct mscan_priv *priv = netdev_priv(dev); -	struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; +	struct mscan_regs __iomem *regs = priv->reg_base;  	mscan_set_mode(dev, MSCAN_INIT_MODE);  	clrbits8(®s->canctl1, MSCAN_CANE);  	unregister_candev(dev); @@ -685,7 +721,8 @@ struct net_device *alloc_mscandev(void)  	priv->can.bittiming_const = &mscan_bittiming_const;  	priv->can.do_set_bittiming = mscan_do_set_bittiming;  	priv->can.do_set_mode = mscan_do_set_mode; -	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; +	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | +		CAN_CTRLMODE_LISTENONLY;  	for (i = 0; i < TX_QUEUE_SIZE; i++) {  		priv->tx_queue[i].id = i;  | 
