aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-10-04 06:12:03 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-10-07 08:11:20 -0400
commit7227c0216d2f879d548e8028dc0298a6156ae633 (patch)
treefec015c588e0c69d9b30f92239d8729d54304a58 /drivers/nfc
parent9f7b57f28cb7513d3245e74cd7536304306d1cc0 (diff)
NFC: port100: Add target mode support
This implements the target NFC digital operations tg_configure_hw(), tg_listen(), tg_listen_mdaa(), and tg_send_cmd(). The target mode supports NFC-A technology at 106kbits/s and NFC-F technologies at 212 and 424kbits/s. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Cc: Stephen Tiedemann <stephen.tiedemann@gmail.com> Tested-by: Cho, Yu-Chen <acho@suse.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/port100.c321
1 files changed, 317 insertions, 4 deletions
diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c
index 99a6dd79393d..8a0571eb2627 100644
--- a/drivers/nfc/port100.c
+++ b/drivers/nfc/port100.c
@@ -75,6 +75,11 @@ static u8 ack_frame[PORT100_FRAME_ACK_SIZE] = {
75#define PORT100_CMD_IN_SET_PROTOCOL 0x02 75#define PORT100_CMD_IN_SET_PROTOCOL 0x02
76#define PORT100_CMD_IN_COMM_RF 0x04 76#define PORT100_CMD_IN_COMM_RF 0x04
77 77
78#define PORT100_CMD_TG_SET_RF 0x40
79#define PORT100_CMD_TG_SET_PROTOCOL 0x42
80#define PORT100_CMD_TG_SET_RF_OFF 0x46
81#define PORT100_CMD_TG_COMM_RF 0x48
82
78#define PORT100_CMD_SWITCH_RF 0x06 83#define PORT100_CMD_SWITCH_RF 0x06
79 84
80#define PORT100_CMD_RESPONSE(cmd) (cmd + 1) 85#define PORT100_CMD_RESPONSE(cmd) (cmd + 1)
@@ -87,6 +92,9 @@ static u8 ack_frame[PORT100_FRAME_ACK_SIZE] = {
87#define PORT100_CMD_STATUS_OK 0x00 92#define PORT100_CMD_STATUS_OK 0x00
88#define PORT100_CMD_STATUS_TIMEOUT 0x80 93#define PORT100_CMD_STATUS_TIMEOUT 0x80
89 94
95#define PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK 0x01
96#define PORT100_MDAA_TGT_WAS_ACTIVATED_MASK 0x02
97
90struct port100; 98struct port100;
91 99
92typedef void (*port100_send_async_complete_t)(struct port100 *dev, void *arg, 100typedef void (*port100_send_async_complete_t)(struct port100 *dev, void *arg,
@@ -133,6 +141,41 @@ static const struct port100_in_rf_setting in_rf_settings[] = {
133 }, 141 },
134}; 142};
135 143
144/**
145 * Setting sets structure for tg_set_rf command
146 *
147 * @tg_set_number: Represents the entry index in the port-100 RF Base Table.
148 * This table contains multiple RF setting sets required for RF
149 * communication. this field is used for both send and receive
150 * settings.
151 *
152 * @tg_comm_type: Sets the communication type to be used to send and receive
153 * data.
154 */
155struct port100_tg_rf_setting {
156 u8 tg_set_number;
157 u8 tg_comm_type;
158} __packed;
159
160#define PORT100_COMM_TYPE_TG_106A 0x0B
161#define PORT100_COMM_TYPE_TG_212F 0x0C
162#define PORT100_COMM_TYPE_TG_424F 0x0D
163
164static const struct port100_tg_rf_setting tg_rf_settings[] = {
165 [NFC_DIGITAL_RF_TECH_106A] = {
166 .tg_set_number = 8,
167 .tg_comm_type = PORT100_COMM_TYPE_TG_106A,
168 },
169 [NFC_DIGITAL_RF_TECH_212F] = {
170 .tg_set_number = 8,
171 .tg_comm_type = PORT100_COMM_TYPE_TG_212F,
172 },
173 [NFC_DIGITAL_RF_TECH_424F] = {
174 .tg_set_number = 8,
175 .tg_comm_type = PORT100_COMM_TYPE_TG_424F,
176 },
177};
178
136#define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00 179#define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00
137#define PORT100_IN_PROT_ADD_CRC 0x01 180#define PORT100_IN_PROT_ADD_CRC 0x01
138#define PORT100_IN_PROT_CHECK_CRC 0x02 181#define PORT100_IN_PROT_CHECK_CRC 0x02
@@ -156,6 +199,13 @@ static const struct port100_in_rf_setting in_rf_settings[] = {
156 199
157#define PORT100_IN_MAX_NUM_PROTOCOLS 19 200#define PORT100_IN_MAX_NUM_PROTOCOLS 19
158 201
202#define PORT100_TG_PROT_TU 0x00
203#define PORT100_TG_PROT_RF_OFF 0x01
204#define PORT100_TG_PROT_CRM 0x02
205#define PORT100_TG_PROT_END 0x03
206
207#define PORT100_TG_MAX_NUM_PROTOCOLS 3
208
159struct port100_protocol { 209struct port100_protocol {
160 u8 number; 210 u8 number;
161 u8 value; 211 u8 value;
@@ -282,6 +332,47 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = {
282 }, 332 },
283}; 333};
284 334
335static struct port100_protocol
336tg_protocols[][PORT100_TG_MAX_NUM_PROTOCOLS + 1] = {
337 [NFC_DIGITAL_FRAMING_NFCA_SHORT] = {
338 { PORT100_TG_PROT_END, 0 },
339 },
340 [NFC_DIGITAL_FRAMING_NFCA_STANDARD] = {
341 { PORT100_TG_PROT_END, 0 },
342 },
343 [NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A] = {
344 { PORT100_TG_PROT_END, 0 },
345 },
346 [NFC_DIGITAL_FRAMING_NFCA_T1T] = {
347 { PORT100_TG_PROT_END, 0 },
348 },
349 [NFC_DIGITAL_FRAMING_NFCA_T2T] = {
350 { PORT100_TG_PROT_END, 0 },
351 },
352 [NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = {
353 { PORT100_TG_PROT_TU, 1 },
354 { PORT100_TG_PROT_RF_OFF, 0 },
355 { PORT100_TG_PROT_CRM, 7 },
356 { PORT100_TG_PROT_END, 0 },
357 },
358 [NFC_DIGITAL_FRAMING_NFCF] = {
359 { PORT100_TG_PROT_END, 0 },
360 },
361 [NFC_DIGITAL_FRAMING_NFCF_T3T] = {
362 { PORT100_TG_PROT_END, 0 },
363 },
364 [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = {
365 { PORT100_TG_PROT_TU, 1 },
366 { PORT100_TG_PROT_RF_OFF, 0 },
367 { PORT100_TG_PROT_CRM, 7 },
368 { PORT100_TG_PROT_END, 0 },
369 },
370 [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = {
371 { PORT100_TG_PROT_RF_OFF, 1 },
372 { PORT100_TG_PROT_END, 0 },
373 },
374};
375
285struct port100 { 376struct port100 {
286 struct nfc_digital_dev *nfc_digital_dev; 377 struct nfc_digital_dev *nfc_digital_dev;
287 378
@@ -348,6 +439,14 @@ struct port100_tg_comm_rf_cmd {
348 u8 data[]; 439 u8 data[];
349} __packed; 440} __packed;
350 441
442struct port100_tg_comm_rf_res {
443 u8 comm_type;
444 u8 ar_status;
445 u8 target_activated;
446 __le32 status;
447 u8 data[];
448} __packed;
449
351/* The rule: value + checksum = 0 */ 450/* The rule: value + checksum = 0 */
352static inline u8 port100_checksum(u16 value) 451static inline u8 port100_checksum(u16 value)
353{ 452{
@@ -1002,17 +1101,176 @@ static int port100_in_send_cmd(struct nfc_digital_dev *ddev,
1002 port100_in_comm_rf_complete, cb_arg); 1101 port100_in_comm_rf_complete, cb_arg);
1003} 1102}
1004 1103
1104static int port100_tg_set_rf(struct nfc_digital_dev *ddev, u8 rf)
1105{
1106 struct port100 *dev = nfc_digital_get_drvdata(ddev);
1107 struct sk_buff *skb;
1108 struct sk_buff *resp;
1109 int rc;
1110
1111 if (rf >= NFC_DIGITAL_RF_TECH_LAST)
1112 return -EINVAL;
1113
1114 skb = port100_alloc_skb(dev, sizeof(struct port100_tg_rf_setting));
1115 if (!skb)
1116 return -ENOMEM;
1117
1118 memcpy(skb_put(skb, sizeof(struct port100_tg_rf_setting)),
1119 &tg_rf_settings[rf],
1120 sizeof(struct port100_tg_rf_setting));
1121
1122 resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_RF, skb);
1123
1124 if (IS_ERR(resp))
1125 return PTR_ERR(resp);
1126
1127 rc = resp->data[0];
1128
1129 dev_kfree_skb(resp);
1130
1131 return rc;
1132}
1133
1134static int port100_tg_set_framing(struct nfc_digital_dev *ddev, int param)
1135{
1136 struct port100 *dev = nfc_digital_get_drvdata(ddev);
1137 struct port100_protocol *protocols;
1138 struct sk_buff *skb;
1139 struct sk_buff *resp;
1140 int rc;
1141 int num_protocols;
1142 size_t size;
1143
1144 if (param >= NFC_DIGITAL_FRAMING_LAST)
1145 return -EINVAL;
1146
1147 protocols = tg_protocols[param];
1148
1149 num_protocols = 0;
1150 while (protocols[num_protocols].number != PORT100_TG_PROT_END)
1151 num_protocols++;
1152
1153 if (!num_protocols)
1154 return 0;
1155
1156 size = sizeof(struct port100_protocol) * num_protocols;
1157
1158 skb = port100_alloc_skb(dev, size);
1159 if (!skb)
1160 return -ENOMEM;
1161
1162 memcpy(skb_put(skb, size), protocols, size);
1163
1164 resp = port100_send_cmd_sync(dev, PORT100_CMD_TG_SET_PROTOCOL, skb);
1165
1166 if (IS_ERR(resp))
1167 return PTR_ERR(resp);
1168
1169 rc = resp->data[0];
1170
1171 dev_kfree_skb(resp);
1172
1173 return rc;
1174}
1175
1005static int port100_tg_configure_hw(struct nfc_digital_dev *ddev, int type, 1176static int port100_tg_configure_hw(struct nfc_digital_dev *ddev, int type,
1006 int param) 1177 int param)
1007{ 1178{
1008 return -EOPNOTSUPP; 1179 if (type == NFC_DIGITAL_CONFIG_RF_TECH)
1180 return port100_tg_set_rf(ddev, param);
1181
1182 if (type == NFC_DIGITAL_CONFIG_FRAMING)
1183 return port100_tg_set_framing(ddev, param);
1184
1185 return -EINVAL;
1186}
1187
1188static bool port100_tg_target_activated(struct port100 *dev, u8 tgt_activated)
1189{
1190 u8 mask;
1191
1192 switch (dev->cmd_type) {
1193 case PORT100_CMD_TYPE_0:
1194 mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK;
1195 break;
1196 case PORT100_CMD_TYPE_1:
1197 mask = PORT100_MDAA_TGT_HAS_BEEN_ACTIVATED_MASK |
1198 PORT100_MDAA_TGT_WAS_ACTIVATED_MASK;
1199 break;
1200 default:
1201 nfc_err(&dev->interface->dev, "Unknonwn command type.\n");
1202 return false;
1203 }
1204
1205 return ((tgt_activated & mask) == mask);
1206}
1207
1208static void port100_tg_comm_rf_complete(struct port100 *dev, void *arg,
1209 struct sk_buff *resp)
1210{
1211 u32 status;
1212 struct port100_cb_arg *cb_arg = arg;
1213 nfc_digital_cmd_complete_t cb = cb_arg->complete_cb;
1214 struct port100_tg_comm_rf_res *hdr;
1215
1216 if (IS_ERR(resp))
1217 goto exit;
1218
1219 hdr = (struct port100_tg_comm_rf_res *)resp->data;
1220
1221 status = le32_to_cpu(hdr->status);
1222
1223 if (cb_arg->mdaa &&
1224 !port100_tg_target_activated(dev, hdr->target_activated)) {
1225 kfree_skb(resp);
1226 resp = ERR_PTR(-ETIMEDOUT);
1227
1228 goto exit;
1229 }
1230
1231 skb_pull(resp, sizeof(struct port100_tg_comm_rf_res));
1232
1233 if (status != PORT100_CMD_STATUS_OK) {
1234 kfree_skb(resp);
1235
1236 if (status == PORT100_CMD_STATUS_TIMEOUT)
1237 resp = ERR_PTR(-ETIMEDOUT);
1238 else
1239 resp = ERR_PTR(-EIO);
1240 }
1241
1242exit:
1243 cb(dev->nfc_digital_dev, cb_arg->complete_arg, resp);
1244
1245 kfree(cb_arg);
1009} 1246}
1010 1247
1011static int port100_tg_send_cmd(struct nfc_digital_dev *ddev, 1248static int port100_tg_send_cmd(struct nfc_digital_dev *ddev,
1012 struct sk_buff *skb, u16 timeout, 1249 struct sk_buff *skb, u16 timeout,
1013 nfc_digital_cmd_complete_t cb, void *arg) 1250 nfc_digital_cmd_complete_t cb, void *arg)
1014{ 1251{
1015 return -EOPNOTSUPP; 1252 struct port100 *dev = nfc_digital_get_drvdata(ddev);
1253 struct port100_tg_comm_rf_cmd *hdr;
1254 struct port100_cb_arg *cb_arg;
1255
1256 cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL);
1257 if (!cb_arg)
1258 return -ENOMEM;
1259
1260 cb_arg->complete_cb = cb;
1261 cb_arg->complete_arg = arg;
1262
1263 skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd));
1264
1265 hdr = (struct port100_tg_comm_rf_cmd *)skb->data;
1266
1267 memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd));
1268 hdr->guard_time = cpu_to_le16(500);
1269 hdr->send_timeout = cpu_to_le16(0xFFFF);
1270 hdr->recv_timeout = cpu_to_le16(timeout);
1271
1272 return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb,
1273 port100_tg_comm_rf_complete, cb_arg);
1016} 1274}
1017 1275
1018static int port100_listen_mdaa(struct nfc_digital_dev *ddev, 1276static int port100_listen_mdaa(struct nfc_digital_dev *ddev,
@@ -1020,13 +1278,68 @@ static int port100_listen_mdaa(struct nfc_digital_dev *ddev,
1020 u16 timeout, 1278 u16 timeout,
1021 nfc_digital_cmd_complete_t cb, void *arg) 1279 nfc_digital_cmd_complete_t cb, void *arg)
1022{ 1280{
1023 return -EOPNOTSUPP; 1281 struct port100 *dev = nfc_digital_get_drvdata(ddev);
1282 struct port100_tg_comm_rf_cmd *hdr;
1283 struct port100_cb_arg *cb_arg;
1284 struct sk_buff *skb;
1285 int rc;
1286
1287 rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
1288 NFC_DIGITAL_RF_TECH_106A);
1289 if (rc)
1290 return rc;
1291
1292 rc = port100_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
1293 NFC_DIGITAL_FRAMING_NFCA_NFC_DEP);
1294 if (rc)
1295 return rc;
1296
1297 cb_arg = kzalloc(sizeof(struct port100_cb_arg), GFP_KERNEL);
1298 if (!cb_arg)
1299 return -ENOMEM;
1300
1301 cb_arg->complete_cb = cb;
1302 cb_arg->complete_arg = arg;
1303 cb_arg->mdaa = 1;
1304
1305 skb = port100_alloc_skb(dev, 0);
1306 if (!skb) {
1307 kfree(cb_arg);
1308 return -ENOMEM;
1309 }
1310
1311 skb_push(skb, sizeof(struct port100_tg_comm_rf_cmd));
1312 hdr = (struct port100_tg_comm_rf_cmd *)skb->data;
1313
1314 memset(hdr, 0, sizeof(struct port100_tg_comm_rf_cmd));
1315
1316 hdr->guard_time = 0;
1317 hdr->send_timeout = cpu_to_le16(0xFFFF);
1318 hdr->mdaa = 1;
1319 hdr->nfca_param[0] = (params->sens_res >> 8) & 0xFF;
1320 hdr->nfca_param[1] = params->sens_res & 0xFF;
1321 memcpy(hdr->nfca_param + 2, params->nfcid1, 3);
1322 hdr->nfca_param[5] = params->sel_res;
1323 memcpy(hdr->nfcf_param, params->nfcid2, 8);
1324 hdr->nfcf_param[16] = (params->sc >> 8) & 0xFF;
1325 hdr->nfcf_param[17] = params->sc & 0xFF;
1326 hdr->recv_timeout = cpu_to_le16(timeout);
1327
1328 return port100_send_cmd_async(dev, PORT100_CMD_TG_COMM_RF, skb,
1329 port100_tg_comm_rf_complete, cb_arg);
1024} 1330}
1025 1331
1026static int port100_listen(struct nfc_digital_dev *ddev, u16 timeout, 1332static int port100_listen(struct nfc_digital_dev *ddev, u16 timeout,
1027 nfc_digital_cmd_complete_t cb, void *arg) 1333 nfc_digital_cmd_complete_t cb, void *arg)
1028{ 1334{
1029 return -EOPNOTSUPP; 1335 struct port100 *dev = nfc_digital_get_drvdata(ddev);
1336 struct sk_buff *skb;
1337
1338 skb = port100_alloc_skb(dev, 0);
1339 if (!skb)
1340 return -ENOMEM;
1341
1342 return port100_tg_send_cmd(ddev, skb, timeout, cb, arg);
1030} 1343}
1031 1344
1032static struct nfc_digital_ops port100_digital_ops = { 1345static struct nfc_digital_ops port100_digital_ops = {