aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/janz-ican3.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 5d04f5464faf..f13bb8d9bb84 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -84,6 +84,7 @@
84#define MSG_COFFREQ 0x42 84#define MSG_COFFREQ 0x42
85#define MSG_CONREQ 0x43 85#define MSG_CONREQ 0x43
86#define MSG_CCONFREQ 0x47 86#define MSG_CCONFREQ 0x47
87#define MSG_NMTS 0xb0
87#define MSG_LMTS 0xb4 88#define MSG_LMTS 0xb4
88 89
89/* 90/*
@@ -130,6 +131,22 @@
130 131
131#define ICAN3_CAN_DLC_MASK 0x0f 132#define ICAN3_CAN_DLC_MASK 0x0f
132 133
134/* Janz ICAN3 NMTS subtypes */
135#define NMTS_CREATE_NODE_REQ 0x0
136#define NMTS_SLAVE_STATE_IND 0x8
137#define NMTS_SLAVE_EVENT_IND 0x9
138
139/* Janz ICAN3 LMTS subtypes */
140#define LMTS_BUSON_REQ 0x0
141#define LMTS_BUSOFF_REQ 0x1
142#define LMTS_CAN_CONF_REQ 0x2
143
144/* Janz ICAN3 NMTS Event indications */
145#define NE_LOCAL_OCCURRED 0x3
146#define NE_LOCAL_RESOLVED 0x2
147#define NE_REMOTE_OCCURRED 0xc
148#define NE_REMOTE_RESOLVED 0x8
149
133/* 150/*
134 * SJA1000 Status and Error Register Definitions 151 * SJA1000 Status and Error Register Definitions
135 * 152 *
@@ -800,21 +817,41 @@ static int ican3_set_bus_state(struct ican3_dev *mod, bool on)
800 return ican3_send_msg(mod, &msg); 817 return ican3_send_msg(mod, &msg);
801 818
802 } else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) { 819 } else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) {
820 /* bittiming + can-on/off request */
803 memset(&msg, 0, sizeof(msg)); 821 memset(&msg, 0, sizeof(msg));
804 msg.spec = MSG_LMTS; 822 msg.spec = MSG_LMTS;
805 if (on) { 823 if (on) {
806 msg.len = cpu_to_le16(4); 824 msg.len = cpu_to_le16(4);
807 msg.data[0] = 0; 825 msg.data[0] = LMTS_BUSON_REQ;
808 msg.data[1] = 0; 826 msg.data[1] = 0;
809 msg.data[2] = btr0; 827 msg.data[2] = btr0;
810 msg.data[3] = btr1; 828 msg.data[3] = btr1;
811 } else { 829 } else {
812 msg.len = cpu_to_le16(2); 830 msg.len = cpu_to_le16(2);
813 msg.data[0] = 1; 831 msg.data[0] = LMTS_BUSOFF_REQ;
814 msg.data[1] = 0; 832 msg.data[1] = 0;
815 } 833 }
834 res = ican3_send_msg(mod, &msg);
835 if (res)
836 return res;
816 837
817 return ican3_send_msg(mod, &msg); 838 if (on) {
839 /* create NMT Slave Node for error processing
840 * class 2 (with error capability, see CiA/DS203-1)
841 * id 1
842 * name locnod1 (must be exactly 7 bytes)
843 */
844 memset(&msg, 0, sizeof(msg));
845 msg.spec = MSG_NMTS;
846 msg.len = cpu_to_le16(11);
847 msg.data[0] = NMTS_CREATE_NODE_REQ;
848 msg.data[1] = 0;
849 msg.data[2] = 2; /* node class */
850 msg.data[3] = 1; /* node id */
851 strcpy(msg.data + 4, "locnod1"); /* node name */
852 return ican3_send_msg(mod, &msg);
853 }
854 return 0;
818 } 855 }
819 return -ENOTSUPP; 856 return -ENOTSUPP;
820} 857}
@@ -849,12 +886,23 @@ static int ican3_set_buserror(struct ican3_dev *mod, u8 quota)
849{ 886{
850 struct ican3_msg msg; 887 struct ican3_msg msg;
851 888
852 memset(&msg, 0, sizeof(msg)); 889 if (mod->fwtype == ICAN3_FWTYPE_ICANOS) {
853 msg.spec = MSG_CCONFREQ; 890 memset(&msg, 0, sizeof(msg));
854 msg.len = cpu_to_le16(2); 891 msg.spec = MSG_CCONFREQ;
855 msg.data[0] = 0x00; 892 msg.len = cpu_to_le16(2);
856 msg.data[1] = quota; 893 msg.data[0] = 0x00;
857 894 msg.data[1] = quota;
895 } else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) {
896 memset(&msg, 0, sizeof(msg));
897 msg.spec = MSG_LMTS;
898 msg.len = cpu_to_le16(4);
899 msg.data[0] = LMTS_CAN_CONF_REQ;
900 msg.data[1] = 0x00;
901 msg.data[2] = 0x00;
902 msg.data[3] = quota;
903 } else {
904 return -ENOTSUPP;
905 }
858 return ican3_send_msg(mod, &msg); 906 return ican3_send_msg(mod, &msg);
859} 907}
860 908
@@ -1150,6 +1198,41 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)
1150 } 1198 }
1151} 1199}
1152 1200
1201/* Handle NMTS Slave Event Indication Messages from the firmware */
1202static void ican3_handle_nmtsind(struct ican3_dev *mod, struct ican3_msg *msg)
1203{
1204 u16 subspec;
1205
1206 subspec = msg->data[0] + msg->data[1] * 0x100;
1207 if (subspec == NMTS_SLAVE_EVENT_IND) {
1208 switch (msg->data[2]) {
1209 case NE_LOCAL_OCCURRED:
1210 case NE_LOCAL_RESOLVED:
1211 /* now follows the same message as Raw ICANOS CEVTIND
1212 * shift the data at the same place and call this method
1213 */
1214 le16_add_cpu(&msg->len, -3);
1215 memmove(msg->data, msg->data + 3, le16_to_cpu(msg->len));
1216 ican3_handle_cevtind(mod, msg);
1217 break;
1218 case NE_REMOTE_OCCURRED:
1219 case NE_REMOTE_RESOLVED:
1220 /* should not occurre, ignore */
1221 break;
1222 default:
1223 netdev_warn(mod->ndev, "unknown NMTS event indication %x\n",
1224 msg->data[2]);
1225 break;
1226 }
1227 } else if (subspec == NMTS_SLAVE_STATE_IND) {
1228 /* ignore state indications */
1229 } else {
1230 netdev_warn(mod->ndev, "unhandled NMTS indication %x\n",
1231 subspec);
1232 return;
1233 }
1234}
1235
1153static void ican3_handle_unknown_message(struct ican3_dev *mod, 1236static void ican3_handle_unknown_message(struct ican3_dev *mod,
1154 struct ican3_msg *msg) 1237 struct ican3_msg *msg)
1155{ 1238{
@@ -1179,6 +1262,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
1179 case MSG_INQUIRY: 1262 case MSG_INQUIRY:
1180 ican3_handle_inquiry(mod, msg); 1263 ican3_handle_inquiry(mod, msg);
1181 break; 1264 break;
1265 case MSG_NMTS:
1266 ican3_handle_nmtsind(mod, msg);
1267 break;
1182 default: 1268 default:
1183 ican3_handle_unknown_message(mod, msg); 1269 ican3_handle_unknown_message(mod, msg);
1184 break; 1270 break;