linux/drivers/net/can/janz-ican3.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Janz MODULbus VMOD-ICAN3 CAN Interface Driver
 *
 * Copyright (c) 2010 Ira W. Snyder <[email protected]>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/platform_device.h>

#include <linux/netdevice.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/skb.h>
#include <linux/can/error.h>

#include <linux/mfd/janz.h>
#include <asm/io.h>

/* the DPM has 64k of memory, organized into 256x 256 byte pages */
#define DPM_NUM_PAGES
#define DPM_PAGE_SIZE
#define DPM_PAGE_ADDR(p)

/* JANZ ICAN3 "old-style" host interface queue page numbers */
#define QUEUE_OLD_CONTROL
#define QUEUE_OLD_RB0
#define QUEUE_OLD_RB1
#define QUEUE_OLD_WB0
#define QUEUE_OLD_WB1

/* Janz ICAN3 "old-style" host interface control registers */
#define MSYNC_PEER
#define MSYNC_LOCL
#define TARGET_RUNNING
#define FIRMWARE_STAMP

#define MSYNC_RB0
#define MSYNC_RB1
#define MSYNC_RBLW
#define MSYNC_RB_MASK

#define MSYNC_WB0
#define MSYNC_WB1
#define MSYNC_WBLW
#define MSYNC_WB_MASK

/* Janz ICAN3 "new-style" host interface queue page numbers */
#define QUEUE_TOHOST
#define QUEUE_FROMHOST_MID
#define QUEUE_FROMHOST_HIGH
#define QUEUE_FROMHOST_LOW

/* The first free page in the DPM is #9 */
#define DPM_FREE_START

/* Janz ICAN3 "new-style" and "fast" host interface descriptor flags */
#define DESC_VALID
#define DESC_WRAP
#define DESC_INTERRUPT
#define DESC_IVALID
#define DESC_LEN(len)

/* Janz ICAN3 Firmware Messages */
#define MSG_CONNECTI
#define MSG_DISCONNECT
#define MSG_IDVERS
#define MSG_MSGLOST
#define MSG_NEWHOSTIF
#define MSG_INQUIRY
#define MSG_SETAFILMASK
#define MSG_INITFDPMQUEUE
#define MSG_HWCONF
#define MSG_FMSGLOST
#define MSG_CEVTIND
#define MSG_CBTRREQ
#define MSG_COFFREQ
#define MSG_CONREQ
#define MSG_CCONFREQ
#define MSG_NMTS
#define MSG_LMTS

/*
 * Janz ICAN3 CAN Inquiry Message Types
 *
 * NOTE: there appears to be a firmware bug here. You must send
 * NOTE: INQUIRY_STATUS and expect to receive an INQUIRY_EXTENDED
 * NOTE: response. The controller never responds to a message with
 * NOTE: the INQUIRY_EXTENDED subspec :(
 */
#define INQUIRY_STATUS
#define INQUIRY_TERMINATION
#define INQUIRY_EXTENDED

/* Janz ICAN3 CAN Set Acceptance Filter Mask Message Types */
#define SETAFILMASK_REJECT
#define SETAFILMASK_FASTIF

/* Janz ICAN3 CAN Hardware Configuration Message Types */
#define HWCONF_TERMINATE_ON
#define HWCONF_TERMINATE_OFF

/* Janz ICAN3 CAN Event Indication Message Types */
#define CEVTIND_EI
#define CEVTIND_DOI
#define CEVTIND_LOST
#define CEVTIND_FULL
#define CEVTIND_BEI

#define CEVTIND_CHIP_SJA1000

#define ICAN3_BUSERR_QUOTA_MAX

/* Janz ICAN3 CAN Frame Conversion */
#define ICAN3_SNGL
#define ICAN3_ECHO
#define ICAN3_EFF_RTR
#define ICAN3_SFF_RTR
#define ICAN3_EFF

#define ICAN3_CAN_TYPE_MASK
#define ICAN3_CAN_TYPE_SFF
#define ICAN3_CAN_TYPE_EFF

#define ICAN3_CAN_DLC_MASK

/* Janz ICAN3 NMTS subtypes */
#define NMTS_CREATE_NODE_REQ
#define NMTS_SLAVE_STATE_IND
#define NMTS_SLAVE_EVENT_IND

/* Janz ICAN3 LMTS subtypes */
#define LMTS_BUSON_REQ
#define LMTS_BUSOFF_REQ
#define LMTS_CAN_CONF_REQ

/* Janz ICAN3 NMTS Event indications */
#define NE_LOCAL_OCCURRED
#define NE_LOCAL_RESOLVED
#define NE_REMOTE_OCCURRED
#define NE_REMOTE_RESOLVED

/*
 * SJA1000 Status and Error Register Definitions
 *
 * Copied from drivers/net/can/sja1000/sja1000.h
 */

/* status register content */
#define SR_BS
#define SR_ES
#define SR_TS
#define SR_RS
#define SR_TCS
#define SR_TBS
#define SR_DOS
#define SR_RBS

#define SR_CRIT

/* ECC register */
#define ECC_SEG
#define ECC_DIR
#define ECC_ERR
#define ECC_BIT
#define ECC_FORM
#define ECC_STUFF
#define ECC_MASK

/* Number of buffers for use in the "new-style" host interface */
#define ICAN3_NEW_BUFFERS

/* Number of buffers for use in the "fast" host interface */
#define ICAN3_TX_BUFFERS
#define ICAN3_RX_BUFFERS

/* SJA1000 Clock Input */
#define ICAN3_CAN_CLOCK

/* Janz ICAN3 firmware types */
enum ican3_fwtype {};

/* Driver Name */
#define DRV_NAME

/* DPM Control Registers -- starts at offset 0x100 in the MODULbus registers */
struct ican3_dpm_control {};

struct ican3_dev {};

struct ican3_msg {};

struct ican3_new_desc {};

struct ican3_fast_desc {};

/* write to the window basic address register */
static inline void ican3_set_page(struct ican3_dev *mod, unsigned int page)
{}

/*
 * ICAN3 "old-style" host interface
 */

/*
 * Receive a message from the ICAN3 "old-style" firmware interface
 *
 * LOCKING: must hold mod->lock
 *
 * returns 0 on success, -ENOMEM when no message exists
 */
static int ican3_old_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * Send a message through the "old-style" firmware interface
 *
 * LOCKING: must hold mod->lock
 *
 * returns 0 on success, -ENOMEM when no free space exists
 */
static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * ICAN3 "new-style" Host Interface Setup
 */

static void ican3_init_new_host_interface(struct ican3_dev *mod)
{}

/*
 * ICAN3 Fast Host Interface Setup
 */

static void ican3_init_fast_host_interface(struct ican3_dev *mod)
{}

/*
 * ICAN3 "new-style" Host Interface Message Helpers
 */

/*
 * LOCKING: must hold mod->lock
 */
static int ican3_new_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * LOCKING: must hold mod->lock
 */
static int ican3_new_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * Message Send / Recv Helpers
 */

static int ican3_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * Quick Pre-constructed Messages
 */

static int ican3_msg_connect(struct ican3_dev *mod)
{}

static int ican3_msg_disconnect(struct ican3_dev *mod)
{}

static int ican3_msg_newhostif(struct ican3_dev *mod)
{}

static int ican3_msg_fasthostif(struct ican3_dev *mod)
{}

/*
 * Setup the CAN filter to either accept or reject all
 * messages from the CAN bus.
 */
static int ican3_set_id_filter(struct ican3_dev *mod, bool accept)
{}

/*
 * Bring the CAN bus online or offline
 */
static int ican3_set_bus_state(struct ican3_dev *mod, bool on)
{}

static int ican3_set_termination(struct ican3_dev *mod, bool on)
{}

static int ican3_send_inquiry(struct ican3_dev *mod, u8 subspec)
{}

static int ican3_set_buserror(struct ican3_dev *mod, u8 quota)
{}

/*
 * ICAN3 to Linux CAN Frame Conversion
 */

static void ican3_to_can_frame(struct ican3_dev *mod,
			       struct ican3_fast_desc *desc,
			       struct can_frame *cf)
{}

static void can_frame_to_ican3(struct ican3_dev *mod,
			       struct can_frame *cf,
			       struct ican3_fast_desc *desc)
{}

/*
 * Interrupt Handling
 */

/*
 * Handle an ID + Version message response from the firmware. We never generate
 * this message in production code, but it is very useful when debugging to be
 * able to display this message.
 */
static void ican3_handle_idvers(struct ican3_dev *mod, struct ican3_msg *msg)
{}

static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * Handle CAN Event Indication Messages from the firmware
 *
 * The ICAN3 firmware provides the values of some SJA1000 registers when it
 * generates this message. The code below is largely copied from the
 * drivers/net/can/sja1000/sja1000.c file, and adapted as necessary
 */
static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
{}

static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/* Handle NMTS Slave Event Indication Messages from the firmware */
static void ican3_handle_nmtsind(struct ican3_dev *mod, struct ican3_msg *msg)
{}

static void ican3_handle_unknown_message(struct ican3_dev *mod,
					struct ican3_msg *msg)
{}

/*
 * Handle a control message from the firmware
 */
static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
{}

/*
 * The ican3 needs to store all echo skbs, and therefore cannot
 * use the generic infrastructure for this.
 */
static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)
{}

static unsigned int ican3_get_echo_skb(struct ican3_dev *mod)
{}

/*
 * Compare an skb with an existing echo skb
 *
 * This function will be used on devices which have a hardware loopback.
 * On these devices, this function can be used to compare a received skb
 * with the saved echo skbs so that the hardware echo skb can be dropped.
 *
 * Returns true if the skb's are identical, false otherwise.
 */
static bool ican3_echo_skb_matches(struct ican3_dev *mod, struct sk_buff *skb)
{}

/*
 * Check that there is room in the TX ring to transmit another skb
 *
 * LOCKING: must hold mod->lock
 */
static bool ican3_txok(struct ican3_dev *mod)
{}

/*
 * Receive one CAN frame from the hardware
 *
 * CONTEXT: must be called from user context
 */
static int ican3_recv_skb(struct ican3_dev *mod)
{}

static int ican3_napi(struct napi_struct *napi, int budget)
{}

static irqreturn_t ican3_irq(int irq, void *dev_id)
{}

/*
 * Firmware reset, startup, and shutdown
 */

/*
 * Reset an ICAN module to its power-on state
 *
 * CONTEXT: no network device registered
 */
static int ican3_reset_module(struct ican3_dev *mod)
{}

static void ican3_shutdown_module(struct ican3_dev *mod)
{}

/*
 * Startup an ICAN module, bringing it into fast mode
 */
static int ican3_startup_module(struct ican3_dev *mod)
{}

/*
 * CAN Network Device
 */

static int ican3_open(struct net_device *ndev)
{}

static int ican3_stop(struct net_device *ndev)
{}

static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
{}

static const struct net_device_ops ican3_netdev_ops =;

static const struct ethtool_ops ican3_ethtool_ops =;

/*
 * Low-level CAN Device
 */

/* This structure was stolen from drivers/net/can/sja1000/sja1000.c */
static const struct can_bittiming_const ican3_bittiming_const =;

static int ican3_set_mode(struct net_device *ndev, enum can_mode mode)
{}

static int ican3_get_berr_counter(const struct net_device *ndev,
				  struct can_berr_counter *bec)
{}

/*
 * Sysfs Attributes
 */

static ssize_t termination_show(struct device *dev,
				struct device_attribute *attr,
				char *buf)
{}

static ssize_t termination_store(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{}

static ssize_t fwinfo_show(struct device *dev,
			   struct device_attribute *attr,
			   char *buf)
{}

static DEVICE_ATTR_RW(termination);
static DEVICE_ATTR_RO(fwinfo);

static struct attribute *ican3_sysfs_attrs[] =;

static const struct attribute_group ican3_sysfs_attr_group =;

/*
 * PCI Subsystem
 */

static int ican3_probe(struct platform_device *pdev)
{}

static void ican3_remove(struct platform_device *pdev)
{}

static struct platform_driver ican3_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();