0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "nci_spi: %s: " fmt, __func__
0007
0008 #include <linux/module.h>
0009
0010 #include <linux/export.h>
0011 #include <linux/spi/spi.h>
0012 #include <linux/crc-ccitt.h>
0013 #include <net/nfc/nci_core.h>
0014
0015 #define NCI_SPI_ACK_SHIFT 6
0016 #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F
0017
0018 #define NCI_SPI_SEND_TIMEOUT (NCI_CMD_TIMEOUT > NCI_DATA_TIMEOUT ? \
0019 NCI_CMD_TIMEOUT : NCI_DATA_TIMEOUT)
0020
0021 #define NCI_SPI_DIRECT_WRITE 0x01
0022 #define NCI_SPI_DIRECT_READ 0x02
0023
0024 #define ACKNOWLEDGE_NONE 0
0025 #define ACKNOWLEDGE_ACK 1
0026 #define ACKNOWLEDGE_NACK 2
0027
0028 #define CRC_INIT 0xFFFF
0029
0030 static int __nci_spi_send(struct nci_spi *nspi, const struct sk_buff *skb,
0031 int cs_change)
0032 {
0033 struct spi_message m;
0034 struct spi_transfer t;
0035
0036 memset(&t, 0, sizeof(struct spi_transfer));
0037
0038 if (skb) {
0039 t.tx_buf = skb->data;
0040 t.len = skb->len;
0041 } else {
0042
0043 t.tx_buf = &t;
0044 t.len = 0;
0045 }
0046 t.cs_change = cs_change;
0047 t.delay.value = nspi->xfer_udelay;
0048 t.delay.unit = SPI_DELAY_UNIT_USECS;
0049 t.speed_hz = nspi->xfer_speed_hz;
0050
0051 spi_message_init(&m);
0052 spi_message_add_tail(&t, &m);
0053
0054 return spi_sync(nspi->spi, &m);
0055 }
0056
0057 int nci_spi_send(struct nci_spi *nspi,
0058 struct completion *write_handshake_completion,
0059 struct sk_buff *skb)
0060 {
0061 unsigned int payload_len = skb->len;
0062 unsigned char *hdr;
0063 int ret;
0064 long completion_rc;
0065
0066
0067 hdr = skb_push(skb, NCI_SPI_HDR_LEN);
0068 hdr[0] = NCI_SPI_DIRECT_WRITE;
0069 hdr[1] = nspi->acknowledge_mode;
0070 hdr[2] = payload_len >> 8;
0071 hdr[3] = payload_len & 0xFF;
0072
0073 if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
0074 u16 crc;
0075
0076 crc = crc_ccitt(CRC_INIT, skb->data, skb->len);
0077 skb_put_u8(skb, crc >> 8);
0078 skb_put_u8(skb, crc & 0xFF);
0079 }
0080
0081 if (write_handshake_completion) {
0082
0083 ret = __nci_spi_send(nspi, NULL, 1);
0084 if (ret)
0085 goto done;
0086
0087
0088 if (wait_for_completion_timeout(write_handshake_completion,
0089 msecs_to_jiffies(1000)) == 0) {
0090 ret = -ETIME;
0091 goto done;
0092 }
0093 }
0094
0095 ret = __nci_spi_send(nspi, skb, 0);
0096 if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED)
0097 goto done;
0098
0099 reinit_completion(&nspi->req_completion);
0100 completion_rc = wait_for_completion_interruptible_timeout(
0101 &nspi->req_completion,
0102 NCI_SPI_SEND_TIMEOUT);
0103
0104 if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK)
0105 ret = -EIO;
0106
0107 done:
0108 kfree_skb(skb);
0109
0110 return ret;
0111 }
0112 EXPORT_SYMBOL_GPL(nci_spi_send);
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
0125 u8 acknowledge_mode, unsigned int delay,
0126 struct nci_dev *ndev)
0127 {
0128 struct nci_spi *nspi;
0129
0130 nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL);
0131 if (!nspi)
0132 return NULL;
0133
0134 nspi->acknowledge_mode = acknowledge_mode;
0135 nspi->xfer_udelay = delay;
0136
0137 nspi->xfer_speed_hz = 0;
0138 nspi->spi = spi;
0139 nspi->ndev = ndev;
0140 init_completion(&nspi->req_completion);
0141
0142 return nspi;
0143 }
0144 EXPORT_SYMBOL_GPL(nci_spi_allocate_spi);
0145
0146 static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge)
0147 {
0148 struct sk_buff *skb;
0149 unsigned char *hdr;
0150 u16 crc;
0151 int ret;
0152
0153 skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL);
0154
0155
0156 hdr = skb_push(skb, NCI_SPI_HDR_LEN);
0157 hdr[0] = NCI_SPI_DIRECT_WRITE;
0158 hdr[1] = NCI_SPI_CRC_ENABLED;
0159 hdr[2] = acknowledge << NCI_SPI_ACK_SHIFT;
0160 hdr[3] = 0;
0161
0162 crc = crc_ccitt(CRC_INIT, skb->data, skb->len);
0163 skb_put_u8(skb, crc >> 8);
0164 skb_put_u8(skb, crc & 0xFF);
0165
0166 ret = __nci_spi_send(nspi, skb, 0);
0167
0168 kfree_skb(skb);
0169
0170 return ret;
0171 }
0172
0173 static struct sk_buff *__nci_spi_read(struct nci_spi *nspi)
0174 {
0175 struct sk_buff *skb;
0176 struct spi_message m;
0177 unsigned char req[2], resp_hdr[2];
0178 struct spi_transfer tx, rx;
0179 unsigned short rx_len = 0;
0180 int ret;
0181
0182 spi_message_init(&m);
0183
0184 memset(&tx, 0, sizeof(struct spi_transfer));
0185 req[0] = NCI_SPI_DIRECT_READ;
0186 req[1] = nspi->acknowledge_mode;
0187 tx.tx_buf = req;
0188 tx.len = 2;
0189 tx.cs_change = 0;
0190 tx.speed_hz = nspi->xfer_speed_hz;
0191 spi_message_add_tail(&tx, &m);
0192
0193 memset(&rx, 0, sizeof(struct spi_transfer));
0194 rx.rx_buf = resp_hdr;
0195 rx.len = 2;
0196 rx.cs_change = 1;
0197 rx.speed_hz = nspi->xfer_speed_hz;
0198 spi_message_add_tail(&rx, &m);
0199
0200 ret = spi_sync(nspi->spi, &m);
0201 if (ret)
0202 return NULL;
0203
0204 if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED)
0205 rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) +
0206 resp_hdr[1] + NCI_SPI_CRC_LEN;
0207 else
0208 rx_len = (resp_hdr[0] << 8) | resp_hdr[1];
0209
0210 skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL);
0211 if (!skb)
0212 return NULL;
0213
0214 spi_message_init(&m);
0215
0216 memset(&rx, 0, sizeof(struct spi_transfer));
0217 rx.rx_buf = skb_put(skb, rx_len);
0218 rx.len = rx_len;
0219 rx.cs_change = 0;
0220 rx.delay.value = nspi->xfer_udelay;
0221 rx.delay.unit = SPI_DELAY_UNIT_USECS;
0222 rx.speed_hz = nspi->xfer_speed_hz;
0223 spi_message_add_tail(&rx, &m);
0224
0225 ret = spi_sync(nspi->spi, &m);
0226 if (ret)
0227 goto receive_error;
0228
0229 if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
0230 *(u8 *)skb_push(skb, 1) = resp_hdr[1];
0231 *(u8 *)skb_push(skb, 1) = resp_hdr[0];
0232 }
0233
0234 return skb;
0235
0236 receive_error:
0237 kfree_skb(skb);
0238
0239 return NULL;
0240 }
0241
0242 static int nci_spi_check_crc(struct sk_buff *skb)
0243 {
0244 u16 crc_data = (skb->data[skb->len - 2] << 8) |
0245 skb->data[skb->len - 1];
0246 int ret;
0247
0248 ret = (crc_ccitt(CRC_INIT, skb->data, skb->len - NCI_SPI_CRC_LEN)
0249 == crc_data);
0250
0251 skb_trim(skb, skb->len - NCI_SPI_CRC_LEN);
0252
0253 return ret;
0254 }
0255
0256 static u8 nci_spi_get_ack(struct sk_buff *skb)
0257 {
0258 u8 ret;
0259
0260 ret = skb->data[0] >> NCI_SPI_ACK_SHIFT;
0261
0262
0263 skb_pull(skb, 2);
0264
0265 return ret;
0266 }
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 struct sk_buff *nci_spi_read(struct nci_spi *nspi)
0280 {
0281 struct sk_buff *skb;
0282
0283
0284 skb = __nci_spi_read(nspi);
0285 if (!skb)
0286 goto done;
0287
0288 if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) {
0289 if (!nci_spi_check_crc(skb)) {
0290 send_acknowledge(nspi, ACKNOWLEDGE_NACK);
0291 goto done;
0292 }
0293
0294
0295
0296
0297 nspi->req_result = nci_spi_get_ack(skb);
0298 if (nspi->req_result)
0299 complete(&nspi->req_completion);
0300 }
0301
0302
0303
0304
0305 if (!skb->len) {
0306 kfree_skb(skb);
0307 skb = NULL;
0308 goto done;
0309 }
0310
0311 if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED)
0312 send_acknowledge(nspi, ACKNOWLEDGE_ACK);
0313
0314 done:
0315
0316 return skb;
0317 }
0318 EXPORT_SYMBOL_GPL(nci_spi_read);
0319
0320 MODULE_LICENSE("GPL");