Commit a7e8511f authored by Stephane Grosjean's avatar Stephane Grosjean Committed by Marc Kleine-Budde
Browse files

can: peak_usb: add support of ethtool set_phys_id()

This patch makes it possible to specifically flash the LED of a CAN
port of the CAN-USB interfaces of PEAK-System.

Link: https://lore.kernel.org/r/20210309122141.3276927-1-mkl@pengutronix.de


Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
[mkl: use common prefix PCAN_ for defines]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent cfe2a4ca
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>

#include <linux/can.h>
#include <linux/can/dev.h>
@@ -40,6 +41,7 @@
#define PCAN_USB_CMD_REGISTER	9
#define PCAN_USB_CMD_EXT_VCC	10
#define PCAN_USB_CMD_ERR_FR	11
#define PCAN_USB_CMD_LED	12

/* PCAN_USB_CMD_SET_BUS number arg */
#define PCAN_USB_BUS_XCVER		2
@@ -248,6 +250,15 @@ static int pcan_usb_set_ext_vcc(struct peak_usb_device *dev, u8 onoff)
	return pcan_usb_send_cmd(dev, PCAN_USB_CMD_EXT_VCC, PCAN_USB_SET, args);
}

static int pcan_usb_set_led(struct peak_usb_device *dev, u8 onoff)
{
	u8 args[PCAN_USB_CMD_ARGS_LEN] = {
		[0] = !!onoff,
	};

	return pcan_usb_send_cmd(dev, PCAN_USB_CMD_LED, PCAN_USB_SET, args);
}

/*
 * set bittiming value to can
 */
@@ -971,6 +982,40 @@ static int pcan_usb_probe(struct usb_interface *intf)
	return 0;
}

static int pcan_usb_set_phys_id(struct net_device *netdev,
				enum ethtool_phys_id_state state)
{
	struct peak_usb_device *dev = netdev_priv(netdev);
	int err = 0;

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		/* call ON/OFF twice a second */
		return 2;

	case ETHTOOL_ID_OFF:
		err = pcan_usb_set_led(dev, 0);
		break;

	case ETHTOOL_ID_ON:
		fallthrough;

	case ETHTOOL_ID_INACTIVE:
		/* restore LED default */
		err = pcan_usb_set_led(dev, 1);
		break;

	default:
		break;
	}

	return err;
}

static const struct ethtool_ops pcan_usb_ethtool_ops = {
	.set_phys_id = pcan_usb_set_phys_id,
};

/*
 * describe the PCAN-USB adapter
 */
@@ -1001,6 +1046,8 @@ const struct peak_usb_adapter pcan_usb = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb),

	.ethtool_ops = &pcan_usb_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 16,
	.ts_period = 24575, /* calibration period in ts. */
+4 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/ethtool.h>

#include <linux/can.h>
#include <linux/can/dev.h>
@@ -820,6 +821,9 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,

	netdev->flags |= IFF_ECHO; /* we support local echo */

	/* add ethtool support */
	netdev->ethtool_ops = peak_usb_adapter->ethtool_ops;

	init_usb_anchor(&dev->rx_submitted);

	init_usb_anchor(&dev->tx_submitted);
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ struct peak_usb_adapter {
	const struct can_bittiming_const * const data_bittiming_const;
	unsigned int ctrl_count;

	const struct ethtool_ops *ethtool_ops;

	int (*intf_probe)(struct usb_interface *intf);

	int (*dev_init)(struct peak_usb_device *dev);
+34 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>

#include <linux/can.h>
#include <linux/can/dev.h>
@@ -1006,6 +1007,31 @@ static void pcan_usb_fd_free(struct peak_usb_device *dev)
	}
}

/* blink LED's */
static int pcan_usb_fd_set_phys_id(struct net_device *netdev,
				   enum ethtool_phys_id_state state)
{
	struct peak_usb_device *dev = netdev_priv(netdev);
	int err = 0;

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		err = pcan_usb_fd_set_can_led(dev, PCAN_UFD_LED_FAST);
		break;
	case ETHTOOL_ID_INACTIVE:
		err = pcan_usb_fd_set_can_led(dev, PCAN_UFD_LED_DEF);
		break;
	default:
		break;
	}

	return err;
}

static const struct ethtool_ops pcan_usb_fd_ethtool_ops = {
	.set_phys_id = pcan_usb_fd_set_phys_id,
};

/* describes the PCAN-USB FD adapter */
static const struct can_bittiming_const pcan_usb_fd_const = {
	.name = "pcan_usb_fd",
@@ -1047,6 +1073,8 @@ const struct peak_usb_adapter pcan_usb_fd = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),

	.ethtool_ops = &pcan_usb_fd_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 32,
	.ts_period = 1000000, /* calibration period in ts. */
@@ -1120,6 +1148,8 @@ const struct peak_usb_adapter pcan_usb_chip = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),

	.ethtool_ops = &pcan_usb_fd_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 32,
	.ts_period = 1000000, /* calibration period in ts. */
@@ -1193,6 +1223,8 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),

	.ethtool_ops = &pcan_usb_fd_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 32,
	.ts_period = 1000000, /* calibration period in ts. */
@@ -1266,6 +1298,8 @@ const struct peak_usb_adapter pcan_usb_x6 = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),

	.ethtool_ops = &pcan_usb_fd_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 32,
	.ts_period = 1000000, /* calibration period in ts. */
+33 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/ethtool.h>

#include <linux/can.h>
#include <linux/can/dev.h>
@@ -906,7 +907,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
	usb_if->dev[dev->ctrl_idx] = dev;

	/* set LED in default state (end of init phase) */
	pcan_usb_pro_set_led(dev, 0, 1);
	pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_DEVICE, 1);

	kfree(bi);
	kfree(fi);
@@ -990,6 +991,35 @@ int pcan_usb_pro_probe(struct usb_interface *intf)
	return 0;
}

static int pcan_usb_pro_set_phys_id(struct net_device *netdev,
				    enum ethtool_phys_id_state state)
{
	struct peak_usb_device *dev = netdev_priv(netdev);
	int err = 0;

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		/* fast blinking forever */
		err = pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_BLINK_FAST,
					   0xffffffff);
		break;

	case ETHTOOL_ID_INACTIVE:
		/* restore LED default */
		err = pcan_usb_pro_set_led(dev, PCAN_USBPRO_LED_DEVICE, 1);
		break;

	default:
		break;
	}

	return err;
}

static const struct ethtool_ops pcan_usb_pro_ethtool_ops = {
	.set_phys_id = pcan_usb_pro_set_phys_id,
};

/*
 * describe the PCAN-USB Pro adapter
 */
@@ -1018,6 +1048,8 @@ const struct peak_usb_adapter pcan_usb_pro = {
	/* size of device private data */
	.sizeof_dev_private = sizeof(struct pcan_usb_pro_device),

	.ethtool_ops = &pcan_usb_pro_ethtool_ops,

	/* timestamps usage */
	.ts_used_bits = 32,
	.ts_period = 1000000, /* calibration period in ts. */
Loading