^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);