Commit 4f232482 authored by Stephane Grosjean's avatar Stephane Grosjean Committed by Marc Kleine-Budde

can: peak_usb: include support for a new MCU

The CANFD-USB PCAN-USB FD interface undergoes an internal component
change that requires a slight modification of its drivers, which leads
them to dynamically use endpoint numbers provided by the interface
itself. In addition to a change in the calls to the USB functions
exported by the kernel, the detection of the USB interface dedicated
to CAN must also be modified, as some PEAK-System devices support
other interfaces than CAN.

Link: https://lore.kernel.org/all/20220719120632.26774-3-s.grosjean@peak-system.comSigned-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
[mkl: add missing cpu_to_le16() conversion]
[mkl: fix networking block comment style]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent a0cf2fe6
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
#define PCAN_UFD_RX_BUFFER_SIZE 2048 #define PCAN_UFD_RX_BUFFER_SIZE 2048
#define PCAN_UFD_TX_BUFFER_SIZE 512 #define PCAN_UFD_TX_BUFFER_SIZE 512
/* struct pcan_ufd_fw_info::type */
#define PCAN_USBFD_TYPE_STD 1
#define PCAN_USBFD_TYPE_EXT 2 /* includes EP numbers */
/* read some versions info from the hw device */ /* read some versions info from the hw device */
struct __packed pcan_ufd_fw_info { struct __packed pcan_ufd_fw_info {
__le16 size_of; /* sizeof this */ __le16 size_of; /* sizeof this */
...@@ -44,6 +48,13 @@ struct __packed pcan_ufd_fw_info { ...@@ -44,6 +48,13 @@ struct __packed pcan_ufd_fw_info {
__le32 dev_id[2]; /* "device id" per CAN */ __le32 dev_id[2]; /* "device id" per CAN */
__le32 ser_no; /* S/N */ __le32 ser_no; /* S/N */
__le32 flags; /* special functions */ __le32 flags; /* special functions */
/* extended data when type == PCAN_USBFD_TYPE_EXT */
u8 cmd_out_ep; /* ep for cmd */
u8 cmd_in_ep; /* ep for replies */
u8 data_out_ep[2]; /* ep for CANx TX */
u8 data_in_ep; /* ep for CAN RX */
u8 dummy[3];
}; };
/* handle device specific info used by the netdevices */ /* handle device specific info used by the netdevices */
...@@ -171,6 +182,9 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev) ...@@ -171,6 +182,9 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev)
/* send PCAN-USB Pro FD commands synchronously */ /* send PCAN-USB Pro FD commands synchronously */
static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
{ {
struct pcan_usb_fd_device *pdev =
container_of(dev, struct pcan_usb_fd_device, dev);
struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info;
void *cmd_head = pcan_usb_fd_cmd_buffer(dev); void *cmd_head = pcan_usb_fd_cmd_buffer(dev);
int err = 0; int err = 0;
u8 *packet_ptr; u8 *packet_ptr;
...@@ -200,7 +214,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) ...@@ -200,7 +214,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
do { do {
err = usb_bulk_msg(dev->udev, err = usb_bulk_msg(dev->udev,
usb_sndbulkpipe(dev->udev, usb_sndbulkpipe(dev->udev,
PCAN_USBPRO_EP_CMDOUT), fw_info->cmd_out_ep),
packet_ptr, packet_len, packet_ptr, packet_len,
NULL, PCAN_UFD_CMD_TIMEOUT_MS); NULL, PCAN_UFD_CMD_TIMEOUT_MS);
if (err) { if (err) {
...@@ -426,6 +440,9 @@ static int pcan_usb_fd_set_bittiming_fast(struct peak_usb_device *dev, ...@@ -426,6 +440,9 @@ static int pcan_usb_fd_set_bittiming_fast(struct peak_usb_device *dev,
static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, static int pcan_usb_fd_restart_async(struct peak_usb_device *dev,
struct urb *urb, u8 *buf) struct urb *urb, u8 *buf)
{ {
struct pcan_usb_fd_device *pdev =
container_of(dev, struct pcan_usb_fd_device, dev);
struct pcan_ufd_fw_info *fw_info = &pdev->usb_if->fw_info;
u8 *pc = buf; u8 *pc = buf;
/* build the entire cmds list in the provided buffer, to go back into /* build the entire cmds list in the provided buffer, to go back into
...@@ -439,7 +456,7 @@ static int pcan_usb_fd_restart_async(struct peak_usb_device *dev, ...@@ -439,7 +456,7 @@ static int pcan_usb_fd_restart_async(struct peak_usb_device *dev,
/* complete the URB */ /* complete the URB */
usb_fill_bulk_urb(urb, dev->udev, usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT), usb_sndbulkpipe(dev->udev, fw_info->cmd_out_ep),
buf, pc - buf, buf, pc - buf,
pcan_usb_pro_restart_complete, dev); pcan_usb_pro_restart_complete, dev);
...@@ -839,6 +856,15 @@ static int pcan_usb_fd_get_berr_counter(const struct net_device *netdev, ...@@ -839,6 +856,15 @@ static int pcan_usb_fd_get_berr_counter(const struct net_device *netdev,
return 0; return 0;
} }
/* probe function for all PCAN-USB FD family usb interfaces */
static int pcan_usb_fd_probe(struct usb_interface *intf)
{
struct usb_host_interface *iface_desc = &intf->altsetting[0];
/* CAN interface is always interface #0 */
return iface_desc->desc.bInterfaceNumber;
}
/* stop interface (last chance before set bus off) */ /* stop interface (last chance before set bus off) */
static int pcan_usb_fd_stop(struct peak_usb_device *dev) static int pcan_usb_fd_stop(struct peak_usb_device *dev)
{ {
...@@ -860,6 +886,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) ...@@ -860,6 +886,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
{ {
struct pcan_usb_fd_device *pdev = struct pcan_usb_fd_device *pdev =
container_of(dev, struct pcan_usb_fd_device, dev); container_of(dev, struct pcan_usb_fd_device, dev);
struct pcan_ufd_fw_info *fw_info;
int i, err = -ENOMEM; int i, err = -ENOMEM;
/* do this for 1st channel only */ /* do this for 1st channel only */
...@@ -878,10 +905,12 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) ...@@ -878,10 +905,12 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
/* number of ts msgs to ignore before taking one into account */ /* number of ts msgs to ignore before taking one into account */
pdev->usb_if->cm_ignore_count = 5; pdev->usb_if->cm_ignore_count = 5;
fw_info = &pdev->usb_if->fw_info;
err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
PCAN_USBPRO_INFO_FW, PCAN_USBPRO_INFO_FW,
&pdev->usb_if->fw_info, fw_info,
sizeof(pdev->usb_if->fw_info)); sizeof(*fw_info));
if (err) { if (err) {
dev_err(dev->netdev->dev.parent, dev_err(dev->netdev->dev.parent,
"unable to read %s firmware info (err %d)\n", "unable to read %s firmware info (err %d)\n",
...@@ -895,14 +924,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) ...@@ -895,14 +924,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
*/ */
dev_info(dev->netdev->dev.parent, dev_info(dev->netdev->dev.parent,
"PEAK-System %s v%u fw v%u.%u.%u (%u channels)\n", "PEAK-System %s v%u fw v%u.%u.%u (%u channels)\n",
dev->adapter->name, pdev->usb_if->fw_info.hw_version, dev->adapter->name, fw_info->hw_version,
pdev->usb_if->fw_info.fw_version[0], fw_info->fw_version[0],
pdev->usb_if->fw_info.fw_version[1], fw_info->fw_version[1],
pdev->usb_if->fw_info.fw_version[2], fw_info->fw_version[2],
dev->adapter->ctrl_count); dev->adapter->ctrl_count);
/* check for ability to switch between ISO/non-ISO modes */ /* check for ability to switch between ISO/non-ISO modes */
if (pdev->usb_if->fw_info.fw_version[0] >= 2) { if (fw_info->fw_version[0] >= 2) {
/* firmware >= 2.x supports ISO/non-ISO switching */ /* firmware >= 2.x supports ISO/non-ISO switching */
dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO; dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
} else { } else {
...@@ -910,6 +939,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) ...@@ -910,6 +939,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO; dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO;
} }
/* if vendor rsp is of type 2, then it contains EP numbers to
* use for cmds pipes. If not, then default EP should be used.
*/
if (fw_info->type != cpu_to_le16(PCAN_USBFD_TYPE_EXT)) {
fw_info->cmd_out_ep = PCAN_USBPRO_EP_CMDOUT;
fw_info->cmd_in_ep = PCAN_USBPRO_EP_CMDIN;
}
/* tell the hardware the can driver is running */ /* tell the hardware the can driver is running */
err = pcan_usb_fd_drv_loaded(dev, 1); err = pcan_usb_fd_drv_loaded(dev, 1);
if (err) { if (err) {
...@@ -930,12 +967,23 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) ...@@ -930,12 +967,23 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
/* do a copy of the ctrlmode[_supported] too */ /* do a copy of the ctrlmode[_supported] too */
dev->can.ctrlmode = ppdev->dev.can.ctrlmode; dev->can.ctrlmode = ppdev->dev.can.ctrlmode;
dev->can.ctrlmode_supported = ppdev->dev.can.ctrlmode_supported; dev->can.ctrlmode_supported = ppdev->dev.can.ctrlmode_supported;
fw_info = &pdev->usb_if->fw_info;
} }
pdev->usb_if->dev[dev->ctrl_idx] = dev; pdev->usb_if->dev[dev->ctrl_idx] = dev;
dev->device_number = dev->device_number =
le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]); le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]);
/* if vendor rsp is of type 2, then it contains EP numbers to
* use for data pipes. If not, then statically defined EP are used
* (see peak_usb_create_dev()).
*/
if (fw_info->type == cpu_to_le16(PCAN_USBFD_TYPE_EXT)) {
dev->ep_msg_in = fw_info->data_in_ep;
dev->ep_msg_out = fw_info->data_out_ep[dev->ctrl_idx];
}
/* set clock domain */ /* set clock domain */
for (i = 0; i < ARRAY_SIZE(pcan_usb_fd_clk_freq); i++) for (i = 0; i < ARRAY_SIZE(pcan_usb_fd_clk_freq); i++)
if (dev->adapter->clock.freq == pcan_usb_fd_clk_freq[i]) if (dev->adapter->clock.freq == pcan_usb_fd_clk_freq[i])
...@@ -1091,7 +1139,7 @@ const struct peak_usb_adapter pcan_usb_fd = { ...@@ -1091,7 +1139,7 @@ const struct peak_usb_adapter pcan_usb_fd = {
.tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE, .tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE,
/* device callbacks */ /* device callbacks */
.intf_probe = pcan_usb_pro_probe, /* same as PCAN-USB Pro */ .intf_probe = pcan_usb_fd_probe,
.dev_init = pcan_usb_fd_init, .dev_init = pcan_usb_fd_init,
.dev_exit = pcan_usb_fd_exit, .dev_exit = pcan_usb_fd_exit,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment