Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Core driver for the CC770 and AN82527 CAN controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/can.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/can/dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/can/error.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/can/platform/cc770.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include "cc770.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) MODULE_DESCRIPTION(KBUILD_MODNAME "CAN netdevice driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * The CC770 is a CAN controller from Bosch, which is 100% compatible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * with the AN82527 from Intel, but with "bugs" being fixed and some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * additional functionality, mainly:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * 1. RX and TX error counters are readable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * 2. Support of silent (listen-only) mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * 3. Message object 15 can receive all types of frames, also RTR and EFF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * Details are available from Bosch's "CC770_Product_Info_2007-01.pdf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * which explains in detail the compatibility between the CC770 and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * 82527. This driver use the additional functionality 3. on real CC770
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * devices. Unfortunately, the CC770 does still not store the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * identifier of received remote transmission request frames and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * therefore it's set to 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * The message objects 1..14 can be used for TX and RX while the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * objects 15 is optimized for RX. It has a shadow register for reliable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * data reception under heavy bus load. Therefore it makes sense to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * this message object for the needed use case. The frame type (EFF/SFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * for the message object 15 can be defined via kernel module parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * "msgobj15_eff". If not equal 0, it will receive 29-bit EFF frames,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * otherwise 11 bit SFF messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static int msgobj15_eff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) module_param(msgobj15_eff, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) MODULE_PARM_DESC(msgobj15_eff, "Extended 29-bit frames for message object 15 "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		 "(default: 11-bit standard frames)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) static int i82527_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) module_param(i82527_compat, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) MODULE_PARM_DESC(i82527_compat, "Strict Intel 82527 compatibility mode "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		 "without using additional functions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * This driver uses the last 5 message objects 11..15. The definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * and structure below allows to configure and assign them to the real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * message object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static unsigned char cc770_obj_flags[CC770_OBJ_MAX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	[CC770_OBJ_RX0] = CC770_OBJ_FLAG_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	[CC770_OBJ_RX1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_EFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	[CC770_OBJ_RX_RTR0] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	[CC770_OBJ_RX_RTR1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			      CC770_OBJ_FLAG_EFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	[CC770_OBJ_TX] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static const struct can_bittiming_const cc770_bittiming_const = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	.tseg1_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	.tseg1_max = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	.tseg2_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	.tseg2_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	.sjw_max = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	.brp_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	.brp_max = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	.brp_inc = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) static inline int intid2obj(unsigned int intid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (intid == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		return MSGOBJ_LAST + 2 - intid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void enable_all_objs(const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	u8 msgcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	unsigned char obj_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	unsigned int o, mo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	for (o = 0; o < ARRAY_SIZE(priv->obj_flags); o++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		obj_flags = priv->obj_flags[o];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		mo = obj2msgobj(o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		if (obj_flags & CC770_OBJ_FLAG_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			 * We don't need extra objects for RTR and EFF if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			 * the additional CC770 functions are enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			if (priv->control_normal_mode & CTRL_EAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 				if (o > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				netdev_dbg(dev, "Message object %d for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 					   "RX data, RTR, SFF and EFF\n", mo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 				netdev_dbg(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 					   "Message object %d for RX %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 					   mo, obj_flags & CC770_OBJ_FLAG_RTR ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 					   "RTR" : "data",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 					   obj_flags & CC770_OBJ_FLAG_EFF ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 					   "EFF" : "SFF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			if (obj_flags & CC770_OBJ_FLAG_EFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 				msgcfg = MSGCFG_XTD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 				msgcfg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			if (obj_flags & CC770_OBJ_FLAG_RTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 				msgcfg |= MSGCFG_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			cc770_write_reg(priv, msgobj[mo].config, msgcfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 					MSGVAL_SET | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 					RXIE_SET | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			if (obj_flags & CC770_OBJ_FLAG_RTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 				cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 						NEWDAT_RES | CPUUPD_SET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 						TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 						NEWDAT_RES | MSGLST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 						TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			netdev_dbg(dev, "Message object %d for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 				   "TX data, RTR, SFF and EFF\n", mo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 					RMTPND_RES | TXRQST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 					CPUUPD_RES | NEWDAT_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 					MSGVAL_RES | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 					RXIE_RES | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void disable_all_objs(const struct cc770_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	int o, mo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	for (o = 0; o <  ARRAY_SIZE(priv->obj_flags); o++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		mo = obj2msgobj(o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		if (priv->obj_flags[o] & CC770_OBJ_FLAG_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			if (o > 0 && priv->control_normal_mode & CTRL_EAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 					NEWDAT_RES | MSGLST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 					TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 					MSGVAL_RES | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 					RXIE_RES | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			/* Clear message object for send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 					RMTPND_RES | TXRQST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 					CPUUPD_RES | NEWDAT_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 					MSGVAL_RES | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 					RXIE_RES | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void set_reset_mode(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	/* Enable configuration and puts chip in bus-off, disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	cc770_write_reg(priv, control, CTRL_CCE | CTRL_INI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	priv->can.state = CAN_STATE_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	/* Clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	cc770_read_reg(priv, interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	/* Clear status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	cc770_write_reg(priv, status, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	/* Disable all used message objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	disable_all_objs(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static void set_normal_mode(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	/* Clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	cc770_read_reg(priv, interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	/* Clear status register and pre-set last error code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	cc770_write_reg(priv, status, STAT_LEC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	/* Enable all used message objects*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	enable_all_objs(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	 * Clear bus-off, interrupts only for errors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	 * not for status change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	cc770_write_reg(priv, control, priv->control_normal_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void chipset_init(struct cc770_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	int mo, id, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	/* Enable configuration and put chip in bus-off, disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	cc770_write_reg(priv, control, (CTRL_CCE | CTRL_INI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	/* Set CLKOUT divider and slew rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	cc770_write_reg(priv, clkout, priv->clkout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	/* Configure CPU interface / CLKOUT enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* Set bus configuration  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	cc770_write_reg(priv, bus_config, priv->bus_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	/* Clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	cc770_read_reg(priv, interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	/* Clear status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	cc770_write_reg(priv, status, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	/* Clear and invalidate message objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	for (mo = MSGOBJ_FIRST; mo <= MSGOBJ_LAST; mo++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				INTPND_UNC | RXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 				TXIE_RES | MSGVAL_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 				INTPND_RES | RXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 				TXIE_RES | MSGVAL_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 				NEWDAT_RES | MSGLST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 				TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		for (data = 0; data < 8; data++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			cc770_write_reg(priv, msgobj[mo].data[data], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		for (id = 0; id < 4; id++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			cc770_write_reg(priv, msgobj[mo].id[id], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		cc770_write_reg(priv, msgobj[mo].config, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	/* Set all global ID masks to "don't care" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	cc770_write_reg(priv, global_mask_std[0], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	cc770_write_reg(priv, global_mask_std[1], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	cc770_write_reg(priv, global_mask_ext[0], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	cc770_write_reg(priv, global_mask_ext[1], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	cc770_write_reg(priv, global_mask_ext[2], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	cc770_write_reg(priv, global_mask_ext[3], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int cc770_probe_chip(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	/* Enable configuration, put chip in bus-off, disable ints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	cc770_write_reg(priv, control, CTRL_CCE | CTRL_EAF | CTRL_INI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	/* Configure cpu interface / CLKOUT disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	 * Check if hardware reset is still inactive or maybe there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	 * is no chip in this address space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	if (cc770_read_reg(priv, cpu_interface) & CPUIF_RST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		netdev_info(dev, "probing @0x%p failed (reset)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			    priv->reg_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	/* Write and read back test pattern (some arbitrary values) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	cc770_write_reg(priv, msgobj[1].data[1], 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	cc770_write_reg(priv, msgobj[2].data[3], 0x52);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	cc770_write_reg(priv, msgobj[10].data[6], 0xc3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	if ((cc770_read_reg(priv, msgobj[1].data[1]) != 0x25) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	    (cc770_read_reg(priv, msgobj[2].data[3]) != 0x52) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	    (cc770_read_reg(priv, msgobj[10].data[6]) != 0xc3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		netdev_info(dev, "probing @0x%p failed (pattern)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			    priv->reg_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	/* Check if this chip is a CC770 supporting additional functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (cc770_read_reg(priv, control) & CTRL_EAF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		priv->control_normal_mode |= CTRL_EAF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static void cc770_start(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	/* leave reset mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (priv->can.state != CAN_STATE_STOPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		set_reset_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	/* leave reset mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	set_normal_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int cc770_set_mode(struct net_device *dev, enum can_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	case CAN_MODE_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		cc770_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int cc770_set_bittiming(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	struct can_bittiming *bt = &priv->can.bittiming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	u8 btr0, btr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		(((bt->phase_seg2 - 1) & 0x7) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		btr1 |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	cc770_write_reg(priv, bit_timing_0, btr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	cc770_write_reg(priv, bit_timing_1, btr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int cc770_get_berr_counter(const struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 				  struct can_berr_counter *bec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	bec->txerr = cc770_read_reg(priv, tx_error_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	bec->rxerr = cc770_read_reg(priv, rx_error_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void cc770_tx(struct net_device *dev, int mo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	struct can_frame *cf = (struct can_frame *)priv->tx_skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	u8 dlc, rtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	dlc = cf->can_dlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	id = cf->can_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	rtr = cf->can_id & CAN_RTR_FLAG ? 0 : MSGCFG_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	if (id & CAN_EFF_FLAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		id &= CAN_EFF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		cc770_write_reg(priv, msgobj[mo].config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 				(dlc << 4) | rtr | MSGCFG_XTD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		cc770_write_reg(priv, msgobj[mo].id[3], id << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		cc770_write_reg(priv, msgobj[mo].id[2], id >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		cc770_write_reg(priv, msgobj[mo].id[1], id >> 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		cc770_write_reg(priv, msgobj[mo].id[0], id >> 21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		id &= CAN_SFF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		cc770_write_reg(priv, msgobj[mo].config, (dlc << 4) | rtr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		cc770_write_reg(priv, msgobj[mo].id[0], id >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		cc770_write_reg(priv, msgobj[mo].id[1], id << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	for (i = 0; i < dlc; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			RMTPND_UNC | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			MSGVAL_SET | TXIE_SET | RXIE_SET | INTPND_UNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	unsigned int mo = obj2msgobj(CC770_OBJ_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	if (can_dropped_invalid_skb(dev, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	if ((cc770_read_reg(priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			    msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		netdev_err(dev, "TX register is still occupied!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		return NETDEV_TX_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	priv->tx_skb = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	cc770_tx(dev, mo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	struct can_frame *cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	u8 config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	skb = alloc_can_skb(dev, &cf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	config = cc770_read_reg(priv, msgobj[mo].config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	if (ctrl1 & RMTPND_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		 * Unfortunately, the chip does not store the real message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		 * identifier of the received remote transmission request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		 * frame. Therefore we set it to 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		cf->can_id = CAN_RTR_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		if (config & MSGCFG_XTD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 			cf->can_id |= CAN_EFF_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		cf->can_dlc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		if (config & MSGCFG_XTD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			id = cc770_read_reg(priv, msgobj[mo].id[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 			id |= cc770_read_reg(priv, msgobj[mo].id[2]) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 			id |= cc770_read_reg(priv, msgobj[mo].id[1]) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 			id >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			id |= CAN_EFF_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 			id = cc770_read_reg(priv, msgobj[mo].id[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 			id >>= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		cf->can_id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		cf->can_dlc = get_can_dlc((config & 0xf0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		for (i = 0; i < cf->can_dlc; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 			cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	stats->rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	stats->rx_bytes += cf->can_dlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static int cc770_err(struct net_device *dev, u8 status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	struct can_frame *cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	u8 lec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	netdev_dbg(dev, "status interrupt (%#x)\n", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	skb = alloc_can_err_skb(dev, &cf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	/* Use extended functions of the CC770 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if (priv->control_normal_mode & CTRL_EAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		cf->data[6] = cc770_read_reg(priv, tx_error_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		cf->data[7] = cc770_read_reg(priv, rx_error_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	if (status & STAT_BOFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		/* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		cc770_write_reg(priv, control, CTRL_INI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		cf->can_id |= CAN_ERR_BUSOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		priv->can.state = CAN_STATE_BUS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		priv->can.can_stats.bus_off++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		can_bus_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	} else if (status & STAT_WARN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		cf->can_id |= CAN_ERR_CRTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		/* Only the CC770 does show error passive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		if (cf->data[7] > 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 			cf->data[1] = CAN_ERR_CRTL_RX_PASSIVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 				CAN_ERR_CRTL_TX_PASSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			priv->can.state = CAN_STATE_ERROR_PASSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			priv->can.can_stats.error_passive++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			cf->data[1] = CAN_ERR_CRTL_RX_WARNING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 				CAN_ERR_CRTL_TX_WARNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			priv->can.state = CAN_STATE_ERROR_WARNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			priv->can.can_stats.error_warning++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		/* Back to error active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		cf->can_id |= CAN_ERR_PROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		cf->data[2] = CAN_ERR_PROT_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		priv->can.state = CAN_STATE_ERROR_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	lec = status & STAT_LEC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	if (lec < 7 && lec > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		if (lec == STAT_LEC_ACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 			cf->can_id |= CAN_ERR_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 			cf->can_id |= CAN_ERR_PROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 			switch (lec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 			case STAT_LEC_STUFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 				cf->data[2] |= CAN_ERR_PROT_STUFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			case STAT_LEC_FORM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 				cf->data[2] |= CAN_ERR_PROT_FORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			case STAT_LEC_BIT1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 				cf->data[2] |= CAN_ERR_PROT_BIT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 			case STAT_LEC_BIT0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 				cf->data[2] |= CAN_ERR_PROT_BIT0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			case STAT_LEC_CRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 				cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	stats->rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	stats->rx_bytes += cf->can_dlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int cc770_status_interrupt(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	status = cc770_read_reg(priv, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	/* Reset the status register including RXOK and TXOK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	cc770_write_reg(priv, status, STAT_LEC_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	if (status & (STAT_WARN | STAT_BOFF) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	    (status & STAT_LEC_MASK) != STAT_LEC_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		cc770_err(dev, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		return status & STAT_BOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static void cc770_rx_interrupt(struct net_device *dev, unsigned int o)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	unsigned int mo = obj2msgobj(o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	u8 ctrl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	int n = CC770_MAX_MSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	while (n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		if (!(ctrl1 & NEWDAT_SET))  {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 			/* Check for RTR if additional functions are enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			if (priv->control_normal_mode & CTRL_EAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 				if (!(cc770_read_reg(priv, msgobj[mo].ctrl0) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 				      INTPND_SET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		if (ctrl1 & MSGLST_SET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 			stats->rx_over_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 			stats->rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		if (mo < MSGOBJ_LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 			cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 					NEWDAT_RES | MSGLST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 					TXRQST_UNC | RMTPND_UNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		cc770_rx(dev, mo, ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 				MSGVAL_SET | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 				RXIE_SET | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 				NEWDAT_RES | MSGLST_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 				TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static void cc770_rtr_interrupt(struct net_device *dev, unsigned int o)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	unsigned int mo = obj2msgobj(o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	u8 ctrl0, ctrl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	int n = CC770_MAX_MSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	while (n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		ctrl0 = cc770_read_reg(priv, msgobj[mo].ctrl0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		if (!(ctrl0 & INTPND_SET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		cc770_rx(dev, mo, ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 				MSGVAL_SET | TXIE_RES |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 				RXIE_SET | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 				NEWDAT_RES | CPUUPD_SET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 				TXRQST_RES | RMTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	unsigned int mo = obj2msgobj(o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	struct can_frame *cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	u8 ctrl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	cc770_write_reg(priv, msgobj[mo].ctrl0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 			MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	cc770_write_reg(priv, msgobj[mo].ctrl1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 			RMTPND_RES | TXRQST_RES | MSGLST_RES | NEWDAT_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	if (unlikely(!priv->tx_skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		netdev_err(dev, "missing tx skb in tx interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	if (unlikely(ctrl1 & MSGLST_SET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		stats->rx_over_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		stats->rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	/* When the CC770 is sending an RTR message and it receives a regular
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	 * message that matches the id of the RTR message, it will overwrite the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	 * outgoing message in the TX register. When this happens we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	 * process the received message and try to transmit the outgoing skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	 * again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	if (unlikely(ctrl1 & NEWDAT_SET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		cc770_rx(dev, mo, ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		cc770_tx(dev, mo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	cf = (struct can_frame *)priv->tx_skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	stats->tx_bytes += cf->can_dlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	stats->tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	can_put_echo_skb(priv->tx_skb, dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	can_get_echo_skb(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	priv->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static irqreturn_t cc770_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	struct net_device *dev = (struct net_device *)dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	u8 intid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	int o, n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	/* Shared interrupts and IRQ off? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	if (priv->can.state == CAN_STATE_STOPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	if (priv->pre_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		priv->pre_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	while (n < CC770_MAX_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		/* Read the highest pending interrupt request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 		intid = cc770_read_reg(priv, interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		if (!intid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		if (intid == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 			/* Exit in case of bus-off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 			if (cc770_status_interrupt(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 			o = intid2obj(intid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 			if (o >= CC770_OBJ_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 				netdev_err(dev, "Unexpected interrupt id %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 					   intid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 			if (priv->obj_flags[o] & CC770_OBJ_FLAG_RTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 				cc770_rtr_interrupt(dev, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			else if (priv->obj_flags[o] & CC770_OBJ_FLAG_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 				cc770_rx_interrupt(dev, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 				cc770_tx_interrupt(dev, o);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	if (priv->post_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		priv->post_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	if (n >= CC770_MAX_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 		netdev_dbg(dev, "%d messages handled in ISR", n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	return (n) ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static int cc770_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	/* set chip into reset mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	set_reset_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	/* common open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	err = open_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	err = request_irq(dev->irq, &cc770_interrupt, priv->irq_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 			  dev->name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 		close_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	/* init and start chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	cc770_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static int cc770_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	set_reset_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	close_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct net_device *alloc_cc770dev(int sizeof_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	struct cc770_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	dev = alloc_candev(sizeof(struct cc770_priv) + sizeof_priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 			   CC770_ECHO_SKB_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	priv->can.bittiming_const = &cc770_bittiming_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	priv->can.do_set_bittiming = cc770_set_bittiming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	priv->can.do_set_mode = cc770_set_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	priv->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	if (sizeof_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 		priv->priv = (void *)priv + sizeof(struct cc770_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) EXPORT_SYMBOL_GPL(alloc_cc770dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) void free_cc770dev(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	free_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) EXPORT_SYMBOL_GPL(free_cc770dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static const struct net_device_ops cc770_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	.ndo_open = cc770_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	.ndo_stop = cc770_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	.ndo_start_xmit = cc770_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	.ndo_change_mtu = can_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) int register_cc770dev(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	struct cc770_priv *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	err = cc770_probe_chip(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	dev->netdev_ops = &cc770_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	dev->flags |= IFF_ECHO;	/* we support local echo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	/* Should we use additional functions? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	if (!i82527_compat && priv->control_normal_mode & CTRL_EAF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 		priv->can.do_get_berr_counter = cc770_get_berr_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 		priv->control_normal_mode = CTRL_IE | CTRL_EAF | CTRL_EIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 		netdev_dbg(dev, "i82527 mode with additional functions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 		priv->control_normal_mode = CTRL_IE | CTRL_EIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 		netdev_dbg(dev, "strict i82527 compatibility mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 	chipset_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	set_reset_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	return register_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) EXPORT_SYMBOL_GPL(register_cc770dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) void unregister_cc770dev(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	set_reset_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	unregister_candev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) EXPORT_SYMBOL_GPL(unregister_cc770dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static __init int cc770_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	if (msgobj15_eff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 		cc770_obj_flags[CC770_OBJ_RX0] |= CC770_OBJ_FLAG_EFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 		cc770_obj_flags[CC770_OBJ_RX1] &= ~CC770_OBJ_FLAG_EFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 	pr_info("CAN netdevice driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) module_init(cc770_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static __exit void cc770_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 	pr_info("driver removed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) module_exit(cc770_exit);