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

can: peak_usb: allow flashing of the CAN channel ID



This patch adds callbacks that allow the user to set a new self-defined
CAN channel ID to all USB - CAN/CANFD interfaces of PEAK-System managed by
this driver, namely:
- PCAN-USB
- PCAN-USB FD
- PCAN-USB Pro FD
- PCAN-USB X6
- PCAN-Chip USB
- PCAN-USB Pro

The callback functions write the CAN channel ID to the non-volatile
memory of the devices.

Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: default avatarLukas Magel <lukas.magel@posteo.net>
Link: https://lore.kernel.org/all/20230116200932.157769-4-lukas.magel@posteo.net


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 517ad5e6
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -398,6 +398,25 @@ static int pcan_usb_get_can_channel_id(struct peak_usb_device *dev, u32 *can_ch_
	return err;
}

/* set a new CAN channel id in the flash memory of the device */
static int pcan_usb_set_can_channel_id(struct peak_usb_device *dev, u32 can_ch_id)
{
	u8 args[PCAN_USB_CMD_ARGS_LEN];

	/* this kind of device supports 8-bit values only */
	if (can_ch_id > U8_MAX)
		return -EINVAL;

	/* during the flash process the device disconnects during ~1.25 s.:
	 * prohibit access when interface is UP
	 */
	if (dev->netdev->flags & IFF_UP)
		return -EBUSY;

	args[0] = can_ch_id;
	return pcan_usb_send_cmd(dev, PCAN_USB_CMD_DEVID, PCAN_USB_SET, args);
}

/*
 * update current time ref with received timestamp
 */
@@ -1018,6 +1037,7 @@ const struct peak_usb_adapter pcan_usb = {
	.dev_set_bus = pcan_usb_write_mode,
	.dev_set_bittiming = pcan_usb_set_bittiming,
	.dev_get_can_channel_id = pcan_usb_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_set_can_channel_id,
	.dev_decode_buf = pcan_usb_decode_buf,
	.dev_encode_msg = pcan_usb_encode_msg,
	.dev_start = pcan_usb_start,
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct peak_usb_adapter {
				      struct can_bittiming *bt);
	int (*dev_set_bus)(struct peak_usb_device *dev, u8 onoff);
	int (*dev_get_can_channel_id)(struct peak_usb_device *dev, u32 *can_ch_id);
	int (*dev_set_can_channel_id)(struct peak_usb_device *dev, u32 can_ch_id);
	int (*dev_decode_buf)(struct peak_usb_device *dev, struct urb *urb);
	int (*dev_encode_msg)(struct peak_usb_device *dev, struct sk_buff *skb,
					u8 *obuf, size_t *size);
+26 −0
Original line number Diff line number Diff line
@@ -147,6 +147,15 @@ struct __packed pcan_ufd_ovr_msg {
	u8	unused[3];
};

#define PCAN_UFD_CMD_DEVID_SET		0x81

struct __packed pcan_ufd_device_id {
	__le16	opcode_channel;

	u16	unused;
	__le32	device_id;
};

static inline int pufd_omsg_get_channel(struct pcan_ufd_ovr_msg *om)
{
	return om->channel & 0xf;
@@ -458,6 +467,19 @@ static int pcan_usb_fd_get_can_channel_id(struct peak_usb_device *dev,
	return err;
}

/* set a new CAN channel id in the flash memory of the device */
static int pcan_usb_fd_set_can_channel_id(struct peak_usb_device *dev, u32 can_ch_id)
{
	struct pcan_ufd_device_id *cmd = pcan_usb_fd_cmd_buffer(dev);

	cmd->opcode_channel = pucan_cmd_opcode_channel(dev->ctrl_idx,
						       PCAN_UFD_CMD_DEVID_SET);
	cmd->device_id = cpu_to_le32(can_ch_id);

	/* send the command */
	return pcan_usb_fd_send_cmd(dev, ++cmd);
}

/* handle restart but in asynchronously way
 * (uses PCAN-USB Pro code to complete asynchronous request)
 */
@@ -1170,6 +1192,7 @@ const struct peak_usb_adapter pcan_usb_fd = {
	.dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
	.dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
	.dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id,
	.dev_decode_buf = pcan_usb_fd_decode_buf,
	.dev_start = pcan_usb_fd_start,
	.dev_stop = pcan_usb_fd_stop,
@@ -1245,6 +1268,7 @@ const struct peak_usb_adapter pcan_usb_chip = {
	.dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
	.dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
	.dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id,
	.dev_decode_buf = pcan_usb_fd_decode_buf,
	.dev_start = pcan_usb_fd_start,
	.dev_stop = pcan_usb_fd_stop,
@@ -1320,6 +1344,7 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
	.dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
	.dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
	.dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id,
	.dev_decode_buf = pcan_usb_fd_decode_buf,
	.dev_start = pcan_usb_fd_start,
	.dev_stop = pcan_usb_fd_stop,
@@ -1395,6 +1420,7 @@ const struct peak_usb_adapter pcan_usb_x6 = {
	.dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
	.dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
	.dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id,
	.dev_decode_buf = pcan_usb_fd_decode_buf,
	.dev_start = pcan_usb_fd_start,
	.dev_stop = pcan_usb_fd_stop,
+15 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ static u16 pcan_usb_pro_sizeof_rec[256] = {
	[PCAN_USBPRO_SETFILTR] = sizeof(struct pcan_usb_pro_filter),
	[PCAN_USBPRO_SETTS] = sizeof(struct pcan_usb_pro_setts),
	[PCAN_USBPRO_GETDEVID] = sizeof(struct pcan_usb_pro_devid),
	[PCAN_USBPRO_SETDEVID] = sizeof(struct pcan_usb_pro_devid),
	[PCAN_USBPRO_SETLED] = sizeof(struct pcan_usb_pro_setled),
	[PCAN_USBPRO_RXMSG8] = sizeof(struct pcan_usb_pro_rxmsg),
	[PCAN_USBPRO_RXMSG4] = sizeof(struct pcan_usb_pro_rxmsg) - 4,
@@ -149,6 +150,7 @@ static int pcan_msg_add_rec(struct pcan_usb_pro_msg *pm, int id, ...)

	case PCAN_USBPRO_SETBTR:
	case PCAN_USBPRO_GETDEVID:
	case PCAN_USBPRO_SETDEVID:
		*pc++ = va_arg(ap, int);
		pc += 2;
		*(__le32 *)pc = cpu_to_le32(va_arg(ap, u32));
@@ -444,6 +446,18 @@ static int pcan_usb_pro_get_can_channel_id(struct peak_usb_device *dev,
	return err;
}

static int pcan_usb_pro_set_can_channel_id(struct peak_usb_device *dev,
					   u32 can_ch_id)
{
	struct pcan_usb_pro_msg um;

	pcan_msg_init_empty(&um, dev->cmd_buf, PCAN_USB_MAX_CMD_LEN);
	pcan_msg_add_rec(&um, PCAN_USBPRO_SETDEVID, dev->ctrl_idx,
			 can_ch_id);

	return pcan_usb_pro_send_cmd(dev, &um);
}

static int pcan_usb_pro_set_bittiming(struct peak_usb_device *dev,
				      struct can_bittiming *bt)
{
@@ -1077,6 +1091,7 @@ const struct peak_usb_adapter pcan_usb_pro = {
	.dev_set_bus = pcan_usb_pro_set_bus,
	.dev_set_bittiming = pcan_usb_pro_set_bittiming,
	.dev_get_can_channel_id = pcan_usb_pro_get_can_channel_id,
	.dev_set_can_channel_id = pcan_usb_pro_set_can_channel_id,
	.dev_decode_buf = pcan_usb_pro_decode_buf,
	.dev_encode_msg = pcan_usb_pro_encode_msg,
	.dev_start = pcan_usb_pro_start,
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct __packed pcan_usb_pro_fwinfo {
#define PCAN_USBPRO_SETBTR	0x02
#define PCAN_USBPRO_SETBUSACT	0x04
#define PCAN_USBPRO_SETSILENT	0x05
#define PCAN_USBPRO_SETDEVID	0x06
#define PCAN_USBPRO_SETFILTR	0x0a
#define PCAN_USBPRO_SETTS	0x10
#define PCAN_USBPRO_GETDEVID	0x12