Signed-off-by: Gerhard Uttenthaler <uttenthaler@xxxxxxxxxxxxxxxx> --- drivers/net/can/usb/ems_usb.c | 141 +++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 6a9ea6a4e687..d6b52b265536 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -108,6 +108,17 @@ MODULE_LICENSE("GPL v2"); */ #define EMS_USB_ARM7_CLOCK 8000000 +/* CPC-USB/FD supports the following CAN clocks + */ +#define EMS_USB_FD_8MHZ 8000000 +#define EMS_USB_FD_16MHZ 16000000 +#define EMS_USB_FD_20MHZ 20000000 +#define EMS_USB_FD_24MHZ 24000000 +#define EMS_USB_FD_32MHZ 32000000 +#define EMS_USB_FD_40MHZ 40000000 +#define EMS_USB_FD_80MHZ 80000000 +#define EMS_USB_FD_CLOCK EMS_USB_FD_40MHZ + #define CPC_TX_QUEUE_TRIGGER_LOW 25 #define CPC_TX_QUEUE_TRIGGER_HIGH 35 @@ -970,6 +981,30 @@ static const struct can_bittiming_const ems_usb_bittiming_const_arm7 = { .brp_inc = 1, }; +static const struct can_bittiming_const ems_usb_bittiming_const_generic = { + .name = "ems_usb_fd", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 128, + .sjw_max = 128, + .brp_min = 1, + .brp_max = 512, + .brp_inc = 1, +}; + +static const struct can_bittiming_const ems_usb_bittiming_const_generic_data = { + .name = "ems_usb_fd", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode) { struct ems_usb *dev = netdev_priv(netdev); @@ -1016,6 +1051,76 @@ static int ems_usb_set_bittiming_arm7(struct net_device *netdev) return ems_usb_command_msg(dev, &dev->active_params); } +static int ems_usb_set_bittiming_generic(struct net_device *netdev) +{ + struct ems_usb *dev = netdev_priv(netdev); + struct can_bittiming *bt = &dev->can.bittiming; + struct cpc_generic_can_params *gcp = + &dev->active_params.msg.can_params.cc_params.generic; + int err; + + gcp->config = 0; + gcp->can_clk = dev->can.clock.freq; + + gcp->n.tseg1 = bt->prop_seg + bt->phase_seg1; + gcp->n.tseg2 = bt->phase_seg2; + gcp->n.brp = bt->brp; + gcp->n.sjw = bt->sjw; + + err = ems_usb_clear_cmd_queue(dev); + if (err) + return err; + + netdev_info(netdev, "Set nominal bit timing for CPC-USB/FD with config %X\n", + gcp->config); + netdev_info(netdev, "CAN Clock: %uMHz, Tseg1: %u, Tseg2: %u, BRP: %u, SJW: %u\n", + gcp->can_clk / 1000000, + gcp->n.tseg1, + gcp->n.tseg2, + gcp->n.brp, + gcp->n.sjw); + + return ems_usb_command_msg(dev, &dev->active_params); +} + +static int ems_usb_set_bittiming_generic_data(struct net_device *netdev) +{ + struct ems_usb *dev = netdev_priv(netdev); + struct can_bittiming *bt = &dev->can.data_bittiming; + struct cpc_generic_can_params *gcp = + &dev->active_params.msg.can_params.cc_params.generic; + int err; + + if (dev->can.ctrlmode & CAN_CTRLMODE_FD) { + gcp->config |= CPC_GENERICCONF_FD; + if (dev->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) + gcp->config |= CPC_GENERICCONF_FD_BOSCH; + } else { + // If CAN FD is not requested we can return here + return 0; + } + + gcp->d.tseg1 = bt->prop_seg + bt->phase_seg1; + gcp->d.tseg2 = bt->phase_seg2; + gcp->d.brp = bt->brp; + gcp->d.sjw = bt->sjw; + + err = ems_usb_clear_cmd_queue(dev); + if (err) + return err; + + netdev_info(netdev, "Set data bit timing for CPC-USB/FD with config %X\n", + gcp->config); + netdev_info(netdev, "CAN Clock: %uMHz, Tseg1: %u, Tseg2: %u, BRP: %u, SJW: %u\n", + gcp->can_clk / 1000000, + gcp->d.tseg1, + gcp->d.tseg2, + gcp->d.brp, + gcp->d.sjw); + + return ems_usb_command_msg(dev, &dev->active_params); +} + static void init_params_sja1000(struct ems_cpc_msg *msg) { struct cpc_sja1000_params *sja1000 = @@ -1024,6 +1129,8 @@ static void init_params_sja1000(struct ems_cpc_msg *msg) msg->type = CPC_CMD_TYPE_CAN_PARAMS; msg->length = sizeof(struct cpc_can_params); msg->msgid = 0; + msg->ts_sec = 0; + msg->ts_nsec = 0; msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000; @@ -1046,6 +1153,24 @@ static void init_params_sja1000(struct ems_cpc_msg *msg) sja1000->mode = SJA1000_MOD_RM; } +static void init_params_generic(struct ems_cpc_msg *msg) +{ + struct cpc_generic_can_params *gcp = + &msg->msg.can_params.cc_params.generic; + + msg->type = CPC_CMD_TYPE_CAN_PARAMS; + msg->length = sizeof(struct cpc_can_params); + msg->msgid = 0; + msg->ts_sec = 0; + msg->ts_nsec = 0; + + memset((u8 *)gcp, 0, sizeof(struct cpc_generic_can_params)); + msg->msg.can_params.cc_type = CPC_CC_TYPE_GENERIC; + + gcp->config = CPC_GENERICCONF_RESET_MODE; + gcp->can_clk = EMS_USB_FD_CLOCK; +} + /* probe function for new CPC-USB devices */ static int ems_usb_probe(struct usb_interface *intf, @@ -1076,14 +1201,26 @@ static int ems_usb_probe(struct usb_interface *intf, dev->can.bittiming_const = &ems_usb_bittiming_const_arm7; dev->can.do_set_bittiming = ems_usb_set_bittiming_arm7; dev->can.do_set_mode = ems_usb_set_mode; - dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY; + dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY; init_params_sja1000(&dev->active_params); dev->ems_usb_write_mode = ems_usb_write_mode_arm7; dev->bulk_rd_buf_size = 64; break; case USB_CPCUSB_FD_PRODUCT_ID: - // Placeholder for next patchess + dev->can.clock.freq = EMS_USB_FD_CLOCK; + dev->can.bittiming_const = &ems_usb_bittiming_const_generic; + dev->can.data_bittiming_const = &ems_usb_bittiming_const_generic_data; + dev->can.do_set_bittiming = ems_usb_set_bittiming_generic; + dev->can.do_set_data_bittiming = ems_usb_set_bittiming_generic_data; + dev->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_ONE_SHOT | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO; + init_params_generic(&dev->active_params); + dev->bulk_rd_buf_size = 512; break; default: -- 2.26.2 -- EMS Dr. Thomas Wuensche e.K. Sonnenhang 3 85304 Ilmmuenster HR Ingolstadt, HRA 170106 Phone: +49-8441-490260 Fax : +49-8441-81860 http://www.ems-wuensche.com