[PATCH v2 09/16] can: ems_usb: Added CAN controller initialization for CAN FD

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch added initialization code for CPC-USB/FD 

Signed-off-by: Gerhard Uttenthaler <uttenthaler@xxxxxxxxxxxxxxxx>
---
 drivers/net/can/usb/ems_usb.c | 136 ++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 41f9fb126e0a..96012052a375 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -56,6 +56,7 @@ MODULE_LICENSE("GPL v2");
 #define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
 
 #define CPC_CC_TYPE_SJA1000 2 /* NXP CAN controller */
+#define CPC_CC_TYPE_GENERIC 6 /* GENERIC CAN controller */
 
 #define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
 
@@ -77,6 +78,7 @@ MODULE_LICENSE("GPL v2");
 #define USB_CPCUSB_VENDOR_ID 0x12D6
 
 #define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
+#define USB_CPCUSB_FD_PRODUCT_ID   0x0544
 
 /* Mode register NXP LPC2119/SJA1000 CAN Controller */
 #define SJA1000_MOD_NORMAL 0x00
@@ -104,6 +106,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
 
@@ -265,6 +278,7 @@ MODULE_DEVICE_TABLE(usb, ems_usb_table);
 #define CPC_HEADER_SIZE     4
 #define INTR_IN_BUFFER_SIZE 4
 #define CPC_USB_ARM7_RX_BUFFER_SIZE 64
+#define CPC_USB_FD_RX_BUFFER_SIZE 512
 
 #define MAX_RX_URBS 10
 #define MAX_TX_URBS 10
@@ -974,6 +988,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);
@@ -1019,6 +1057,69 @@ 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 = cpu_to_le32(dev->can.clock.freq);
+
+	gcp->nominal_bitrate.tseg1 = cpu_to_le16(bt->prop_seg + bt->phase_seg1);
+	gcp->nominal_bitrate.tseg2 = cpu_to_le16(bt->phase_seg2);
+	gcp->nominal_bitrate.brp = cpu_to_le16(bt->brp);
+	gcp->nominal_bitrate.sjw = cpu_to_le16(bt->sjw);
+
+	err = ems_usb_clear_cmd_queue(dev);
+	if (err)
+		return err;
+
+	netdev_dbg(netdev, "Set nominal bitrate: CAN Clock: %uMHz, Tseg1: %u, Tseg2: %u, BRP: %u, SJW: %u\n",
+		   le32_to_cpu(gcp->can_clk) / 1000000,
+		   gcp->nominal_bitrate.tseg1,
+		   gcp->nominal_bitrate.tseg2,
+		   gcp->nominal_bitrate.brp,
+		   gcp->nominal_bitrate.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))
+		return 0;
+	gcp->config |= cpu_to_le32(CPC_GENERICCONF_FD);
+
+	if (dev->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
+		gcp->config |= cpu_to_le32(CPC_GENERICCONF_FD_BOSCH);
+
+	gcp->data_bitrate.tseg1 = cpu_to_le16(bt->prop_seg + bt->phase_seg1);
+	gcp->data_bitrate.tseg2 = cpu_to_le16(bt->phase_seg2);
+	gcp->data_bitrate.brp = cpu_to_le16(bt->brp);
+	gcp->data_bitrate.sjw = cpu_to_le16(bt->sjw);
+
+	err = ems_usb_clear_cmd_queue(dev);
+	if (err)
+		return err;
+
+	netdev_dbg(netdev, "Set data bitrate: Tseg1: %u, Tseg2: %u, BRP: %u, SJW: %u\n",
+		   gcp->data_bitrate.tseg1,
+		   gcp->data_bitrate.tseg2,
+		   gcp->data_bitrate.brp,
+		   gcp->data_bitrate.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 =
@@ -1027,6 +1128,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;
 
@@ -1049,6 +1152,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 = cpu_to_le32(CPC_GENERICCONF_RESET_MODE);
+	gcp->can_clk = cpu_to_le32(EMS_USB_FD_CLOCK);
+}
+
 /* probe function for new CPC-USB devices
  */
 static int ems_usb_probe(struct usb_interface *intf,
@@ -1085,6 +1206,21 @@ static int ems_usb_probe(struct usb_interface *intf,
 		dev->bulk_rd_buf_size = CPC_USB_ARM7_RX_BUFFER_SIZE;
 	break;
 
+	case USB_CPCUSB_FD_PRODUCT_ID:
+		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 = CPC_USB_FD_RX_BUFFER_SIZE;
+	break;
+
 	default:
 		err = -ENODEV;
 		goto cleanup_candev;
-- 
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



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux