1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50#include <linux/cdev.h>
51#include <linux/clk-provider.h>
52#include <linux/debugfs.h>
53#include <linux/delay.h>
54#include <linux/gpio.h>
55#include <linux/ieee802154.h>
56#include <linux/kfifo.h>
57#include <linux/of.h>
58#include <linux/of_device.h>
59#include <linux/of_gpio.h>
60#include <linux/module.h>
61#include <linux/mutex.h>
62#include <linux/poll.h>
63#include <linux/skbuff.h>
64#include <linux/slab.h>
65#include <linux/spi/spi.h>
66#include <linux/spinlock.h>
67#include <linux/string.h>
68#include <linux/workqueue.h>
69#include <linux/interrupt.h>
70
71#include <net/ieee802154_netdev.h>
72#include <net/mac802154.h>
73
74#define DRIVER_NAME "ca8210"
75
76
77#define ONE_MHZ 1000000
78#define TWO_MHZ (2 * ONE_MHZ)
79#define FOUR_MHZ (4 * ONE_MHZ)
80#define EIGHT_MHZ (8 * ONE_MHZ)
81#define SIXTEEN_MHZ (16 * ONE_MHZ)
82
83
84#define CA8210_SPI_BUF_SIZE 256
85#define CA8210_SYNC_TIMEOUT 1000
86
87
88#define CA8210_TEST_INT_FILE_NAME "ca8210_test"
89#define CA8210_TEST_INT_FIFO_SIZE 256
90
91
92#define MAC_SUCCESS (0x00)
93#define MAC_ERROR (0x01)
94#define MAC_CANCELLED (0x02)
95#define MAC_READY_FOR_POLL (0x03)
96#define MAC_COUNTER_ERROR (0xDB)
97#define MAC_IMPROPER_KEY_TYPE (0xDC)
98#define MAC_IMPROPER_SECURITY_LEVEL (0xDD)
99#define MAC_UNSUPPORTED_LEGACY (0xDE)
100#define MAC_UNSUPPORTED_SECURITY (0xDF)
101#define MAC_BEACON_LOST (0xE0)
102#define MAC_CHANNEL_ACCESS_FAILURE (0xE1)
103#define MAC_DENIED (0xE2)
104#define MAC_DISABLE_TRX_FAILURE (0xE3)
105#define MAC_SECURITY_ERROR (0xE4)
106#define MAC_FRAME_TOO_LONG (0xE5)
107#define MAC_INVALID_GTS (0xE6)
108#define MAC_INVALID_HANDLE (0xE7)
109#define MAC_INVALID_PARAMETER (0xE8)
110#define MAC_NO_ACK (0xE9)
111#define MAC_NO_BEACON (0xEA)
112#define MAC_NO_DATA (0xEB)
113#define MAC_NO_SHORT_ADDRESS (0xEC)
114#define MAC_OUT_OF_CAP (0xED)
115#define MAC_PAN_ID_CONFLICT (0xEE)
116#define MAC_REALIGNMENT (0xEF)
117#define MAC_TRANSACTION_EXPIRED (0xF0)
118#define MAC_TRANSACTION_OVERFLOW (0xF1)
119#define MAC_TX_ACTIVE (0xF2)
120#define MAC_UNAVAILABLE_KEY (0xF3)
121#define MAC_UNSUPPORTED_ATTRIBUTE (0xF4)
122#define MAC_INVALID_ADDRESS (0xF5)
123#define MAC_ON_TIME_TOO_LONG (0xF6)
124#define MAC_PAST_TIME (0xF7)
125#define MAC_TRACKING_OFF (0xF8)
126#define MAC_INVALID_INDEX (0xF9)
127#define MAC_LIMIT_REACHED (0xFA)
128#define MAC_READ_ONLY (0xFB)
129#define MAC_SCAN_IN_PROGRESS (0xFC)
130#define MAC_SUPERFRAME_OVERLAP (0xFD)
131#define MAC_SYSTEM_ERROR (0xFF)
132
133
134#define HWME_EDTHRESHOLD (0x04)
135#define HWME_EDVALUE (0x06)
136#define HWME_SYSCLKOUT (0x0F)
137#define HWME_LQILIMIT (0x11)
138
139
140#define TDME_CHANNEL (0x00)
141#define TDME_ATM_CONFIG (0x06)
142
143#define MAX_HWME_ATTRIBUTE_SIZE 16
144#define MAX_TDME_ATTRIBUTE_SIZE 2
145
146
147#define PHY_CURRENT_CHANNEL (0x00)
148#define PHY_TRANSMIT_POWER (0x02)
149#define PHY_CCA_MODE (0x03)
150#define MAC_ASSOCIATION_PERMIT (0x41)
151#define MAC_AUTO_REQUEST (0x42)
152#define MAC_BATT_LIFE_EXT (0x43)
153#define MAC_BATT_LIFE_EXT_PERIODS (0x44)
154#define MAC_BEACON_PAYLOAD (0x45)
155#define MAC_BEACON_PAYLOAD_LENGTH (0x46)
156#define MAC_BEACON_ORDER (0x47)
157#define MAC_GTS_PERMIT (0x4d)
158#define MAC_MAX_CSMA_BACKOFFS (0x4e)
159#define MAC_MIN_BE (0x4f)
160#define MAC_PAN_ID (0x50)
161#define MAC_PROMISCUOUS_MODE (0x51)
162#define MAC_RX_ON_WHEN_IDLE (0x52)
163#define MAC_SHORT_ADDRESS (0x53)
164#define MAC_SUPERFRAME_ORDER (0x54)
165#define MAC_ASSOCIATED_PAN_COORD (0x56)
166#define MAC_MAX_BE (0x57)
167#define MAC_MAX_FRAME_RETRIES (0x59)
168#define MAC_RESPONSE_WAIT_TIME (0x5A)
169#define MAC_SECURITY_ENABLED (0x5D)
170
171#define MAC_AUTO_REQUEST_SECURITY_LEVEL (0x78)
172#define MAC_AUTO_REQUEST_KEY_ID_MODE (0x79)
173
174#define NS_IEEE_ADDRESS (0xFF)
175
176
177#define MAC_MODE_NO_ADDR (0x00)
178#define MAC_MODE_SHORT_ADDR (0x02)
179#define MAC_MODE_LONG_ADDR (0x03)
180
181
182#define MAX_BEACON_OVERHEAD (75)
183#define MAX_BEACON_PAYLOAD_LENGTH (IEEE802154_MTU - MAX_BEACON_OVERHEAD)
184
185#define MAX_ATTRIBUTE_SIZE (122)
186#define MAX_DATA_SIZE (114)
187
188#define CA8210_VALID_CHANNELS (0x07FFF800)
189
190
191#define CA8210_MAC_WORKAROUNDS (0)
192#define CA8210_MAC_MPW (0)
193
194
195#define LS_BYTE(x) ((u8)((x) & 0xFF))
196#define MS_BYTE(x) ((u8)(((x) >> 8) & 0xFF))
197
198
199
200#define MCPS_DATA_REQUEST (0x00)
201#define MLME_ASSOCIATE_REQUEST (0x02)
202#define MLME_ASSOCIATE_RESPONSE (0x03)
203#define MLME_DISASSOCIATE_REQUEST (0x04)
204#define MLME_GET_REQUEST (0x05)
205#define MLME_ORPHAN_RESPONSE (0x06)
206#define MLME_RESET_REQUEST (0x07)
207#define MLME_RX_ENABLE_REQUEST (0x08)
208#define MLME_SCAN_REQUEST (0x09)
209#define MLME_SET_REQUEST (0x0A)
210#define MLME_START_REQUEST (0x0B)
211#define MLME_POLL_REQUEST (0x0D)
212#define HWME_SET_REQUEST (0x0E)
213#define HWME_GET_REQUEST (0x0F)
214#define TDME_SETSFR_REQUEST (0x11)
215#define TDME_GETSFR_REQUEST (0x12)
216#define TDME_SET_REQUEST (0x14)
217
218#define MCPS_DATA_INDICATION (0x00)
219#define MCPS_DATA_CONFIRM (0x01)
220#define MLME_RESET_CONFIRM (0x0A)
221#define MLME_SET_CONFIRM (0x0E)
222#define MLME_START_CONFIRM (0x0F)
223#define HWME_SET_CONFIRM (0x12)
224#define HWME_GET_CONFIRM (0x13)
225#define HWME_WAKEUP_INDICATION (0x15)
226#define TDME_SETSFR_CONFIRM (0x17)
227
228
229
230#define SPI_S2M (0x20)
231
232#define SPI_SYN (0x40)
233
234
235#define SPI_IDLE (0xFF)
236#define SPI_NACK (0xF0)
237
238#define SPI_MCPS_DATA_REQUEST (MCPS_DATA_REQUEST)
239#define SPI_MCPS_DATA_INDICATION (MCPS_DATA_INDICATION + SPI_S2M)
240#define SPI_MCPS_DATA_CONFIRM (MCPS_DATA_CONFIRM + SPI_S2M)
241
242#define SPI_MLME_ASSOCIATE_REQUEST (MLME_ASSOCIATE_REQUEST)
243#define SPI_MLME_RESET_REQUEST (MLME_RESET_REQUEST + SPI_SYN)
244#define SPI_MLME_SET_REQUEST (MLME_SET_REQUEST + SPI_SYN)
245#define SPI_MLME_START_REQUEST (MLME_START_REQUEST + SPI_SYN)
246#define SPI_MLME_RESET_CONFIRM (MLME_RESET_CONFIRM + SPI_S2M + SPI_SYN)
247#define SPI_MLME_SET_CONFIRM (MLME_SET_CONFIRM + SPI_S2M + SPI_SYN)
248#define SPI_MLME_START_CONFIRM (MLME_START_CONFIRM + SPI_S2M + SPI_SYN)
249
250#define SPI_HWME_SET_REQUEST (HWME_SET_REQUEST + SPI_SYN)
251#define SPI_HWME_GET_REQUEST (HWME_GET_REQUEST + SPI_SYN)
252#define SPI_HWME_SET_CONFIRM (HWME_SET_CONFIRM + SPI_S2M + SPI_SYN)
253#define SPI_HWME_GET_CONFIRM (HWME_GET_CONFIRM + SPI_S2M + SPI_SYN)
254#define SPI_HWME_WAKEUP_INDICATION (HWME_WAKEUP_INDICATION + SPI_S2M)
255
256#define SPI_TDME_SETSFR_REQUEST (TDME_SETSFR_REQUEST + SPI_SYN)
257#define SPI_TDME_SET_REQUEST (TDME_SET_REQUEST + SPI_SYN)
258#define SPI_TDME_SETSFR_CONFIRM (TDME_SETSFR_CONFIRM + SPI_S2M + SPI_SYN)
259
260
261
262#define CA8210_SFR_PACFG (0xB1)
263#define CA8210_SFR_MACCON (0xD8)
264#define CA8210_SFR_PACFGIB (0xFE)
265
266#define CA8210_SFR_LOTXCAL (0xBF)
267#define CA8210_SFR_PTHRH (0xD1)
268#define CA8210_SFR_PRECFG (0xD3)
269#define CA8210_SFR_LNAGX40 (0xE1)
270#define CA8210_SFR_LNAGX41 (0xE2)
271#define CA8210_SFR_LNAGX42 (0xE3)
272#define CA8210_SFR_LNAGX43 (0xE4)
273#define CA8210_SFR_LNAGX44 (0xE5)
274#define CA8210_SFR_LNAGX45 (0xE6)
275#define CA8210_SFR_LNAGX46 (0xE7)
276#define CA8210_SFR_LNAGX47 (0xE9)
277
278#define PACFGIB_DEFAULT_CURRENT (0x3F)
279#define PTHRH_DEFAULT_THRESHOLD (0x5A)
280#define LNAGX40_DEFAULT_GAIN (0x29)
281#define LNAGX41_DEFAULT_GAIN (0x54)
282#define LNAGX42_DEFAULT_GAIN (0x6C)
283#define LNAGX43_DEFAULT_GAIN (0x7A)
284#define LNAGX44_DEFAULT_GAIN (0x84)
285#define LNAGX45_DEFAULT_GAIN (0x8B)
286#define LNAGX46_DEFAULT_GAIN (0x92)
287#define LNAGX47_DEFAULT_GAIN (0x96)
288
289#define CA8210_IOCTL_HARD_RESET (0x00)
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304struct cas_control {
305 struct spi_message msg;
306 struct spi_transfer transfer;
307
308 u8 tx_buf[CA8210_SPI_BUF_SIZE];
309 u8 tx_in_buf[CA8210_SPI_BUF_SIZE];
310
311 struct ca8210_priv *priv;
312};
313
314
315
316
317
318
319
320
321struct ca8210_test {
322 struct dentry *ca8210_dfs_spi_int;
323 struct kfifo up_fifo;
324 wait_queue_head_t readq;
325};
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355struct ca8210_priv {
356 struct spi_device *spi;
357 struct ieee802154_hw *hw;
358 bool hw_registered;
359 spinlock_t lock;
360 struct workqueue_struct *mlme_workqueue;
361 struct workqueue_struct *irq_workqueue;
362 struct sk_buff *tx_skb;
363 u8 nextmsduhandle;
364 struct clk *clk;
365 int last_dsn;
366 struct ca8210_test test;
367 bool async_tx_pending;
368 u8 *sync_command_response;
369 struct completion ca8210_is_awake;
370 int sync_down, sync_up;
371 struct completion spi_transfer_complete, sync_exchange_complete;
372 bool promiscuous;
373 int retries;
374};
375
376
377
378
379
380
381
382
383struct work_priv_container {
384 struct work_struct work;
385 struct ca8210_priv *priv;
386};
387
388
389
390
391
392
393
394
395
396
397
398struct ca8210_platform_data {
399 bool extclockenable;
400 unsigned int extclockfreq;
401 unsigned int extclockgpio;
402 int gpio_reset;
403 int gpio_irq;
404 int irq_id;
405};
406
407
408
409
410
411
412
413
414struct fulladdr {
415 u8 mode;
416 u8 pan_id[2];
417 u8 address[8];
418};
419
420
421
422
423
424
425
426union macaddr {
427 u16 short_address;
428 u8 ieee_address[8];
429};
430
431
432
433
434
435
436
437
438
439struct secspec {
440 u8 security_level;
441 u8 key_id_mode;
442 u8 key_source[8];
443 u8 key_index;
444};
445
446
447struct mcps_data_request_pset {
448 u8 src_addr_mode;
449 struct fulladdr dst;
450 u8 msdu_length;
451 u8 msdu_handle;
452 u8 tx_options;
453 u8 msdu[MAX_DATA_SIZE];
454};
455
456struct mlme_set_request_pset {
457 u8 pib_attribute;
458 u8 pib_attribute_index;
459 u8 pib_attribute_length;
460 u8 pib_attribute_value[MAX_ATTRIBUTE_SIZE];
461};
462
463struct hwme_set_request_pset {
464 u8 hw_attribute;
465 u8 hw_attribute_length;
466 u8 hw_attribute_value[MAX_HWME_ATTRIBUTE_SIZE];
467};
468
469struct hwme_get_request_pset {
470 u8 hw_attribute;
471};
472
473struct tdme_setsfr_request_pset {
474 u8 sfr_page;
475 u8 sfr_address;
476 u8 sfr_value;
477};
478
479
480struct hwme_set_confirm_pset {
481 u8 status;
482 u8 hw_attribute;
483};
484
485struct hwme_get_confirm_pset {
486 u8 status;
487 u8 hw_attribute;
488 u8 hw_attribute_length;
489 u8 hw_attribute_value[MAX_HWME_ATTRIBUTE_SIZE];
490};
491
492struct tdme_setsfr_confirm_pset {
493 u8 status;
494 u8 sfr_page;
495 u8 sfr_address;
496};
497
498struct mac_message {
499 u8 command_id;
500 u8 length;
501 union {
502 struct mcps_data_request_pset data_req;
503 struct mlme_set_request_pset set_req;
504 struct hwme_set_request_pset hwme_set_req;
505 struct hwme_get_request_pset hwme_get_req;
506 struct tdme_setsfr_request_pset tdme_set_sfr_req;
507 struct hwme_set_confirm_pset hwme_set_cnf;
508 struct hwme_get_confirm_pset hwme_get_cnf;
509 struct tdme_setsfr_confirm_pset tdme_set_sfr_cnf;
510 u8 u8param;
511 u8 status;
512 u8 payload[148];
513 } pdata;
514};
515
516union pa_cfg_sfr {
517 struct {
518 u8 bias_current_trim : 3;
519 u8 : 1;
520 u8 buffer_capacitor_trim : 3;
521 u8 boost : 1;
522 };
523 u8 paib;
524};
525
526struct preamble_cfg_sfr {
527 u8 timeout_symbols : 3;
528 u8 acquisition_symbols : 3;
529 u8 search_symbols : 2;
530};
531
532static int (*cascoda_api_upstream)(
533 const u8 *buf,
534 size_t len,
535 void *device_ref
536);
537
538
539
540
541
542
543
544
545static int link_to_linux_err(int link_status)
546{
547 if (link_status < 0) {
548
549 return link_status;
550 }
551 switch (link_status) {
552 case MAC_SUCCESS:
553 case MAC_REALIGNMENT:
554 return 0;
555 case MAC_IMPROPER_KEY_TYPE:
556 return -EKEYREJECTED;
557 case MAC_IMPROPER_SECURITY_LEVEL:
558 case MAC_UNSUPPORTED_LEGACY:
559 case MAC_DENIED:
560 return -EACCES;
561 case MAC_BEACON_LOST:
562 case MAC_NO_ACK:
563 case MAC_NO_BEACON:
564 return -ENETUNREACH;
565 case MAC_CHANNEL_ACCESS_FAILURE:
566 case MAC_TX_ACTIVE:
567 case MAC_SCAN_IN_PROGRESS:
568 return -EBUSY;
569 case MAC_DISABLE_TRX_FAILURE:
570 case MAC_OUT_OF_CAP:
571 return -EAGAIN;
572 case MAC_FRAME_TOO_LONG:
573 return -EMSGSIZE;
574 case MAC_INVALID_GTS:
575 case MAC_PAST_TIME:
576 return -EBADSLT;
577 case MAC_INVALID_HANDLE:
578 return -EBADMSG;
579 case MAC_INVALID_PARAMETER:
580 case MAC_UNSUPPORTED_ATTRIBUTE:
581 case MAC_ON_TIME_TOO_LONG:
582 case MAC_INVALID_INDEX:
583 return -EINVAL;
584 case MAC_NO_DATA:
585 return -ENODATA;
586 case MAC_NO_SHORT_ADDRESS:
587 return -EFAULT;
588 case MAC_PAN_ID_CONFLICT:
589 return -EADDRINUSE;
590 case MAC_TRANSACTION_EXPIRED:
591 return -ETIME;
592 case MAC_TRANSACTION_OVERFLOW:
593 return -ENOBUFS;
594 case MAC_UNAVAILABLE_KEY:
595 return -ENOKEY;
596 case MAC_INVALID_ADDRESS:
597 return -ENXIO;
598 case MAC_TRACKING_OFF:
599 case MAC_SUPERFRAME_OVERLAP:
600 return -EREMOTEIO;
601 case MAC_LIMIT_REACHED:
602 return -EDQUOT;
603 case MAC_READ_ONLY:
604 return -EROFS;
605 default:
606 return -EPROTO;
607 }
608}
609
610
611
612
613
614
615
616
617
618
619static int ca8210_test_int_driver_write(
620 const u8 *buf,
621 size_t len,
622 void *spi
623)
624{
625 struct ca8210_priv *priv = spi_get_drvdata(spi);
626 struct ca8210_test *test = &priv->test;
627 char *fifo_buffer;
628 int i;
629
630 dev_dbg(
631 &priv->spi->dev,
632 "test_interface: Buffering upstream message:\n"
633 );
634 for (i = 0; i < len; i++)
635 dev_dbg(&priv->spi->dev, "%#03x\n", buf[i]);
636
637 fifo_buffer = kmalloc(len, GFP_KERNEL);
638 if (!fifo_buffer)
639 return -ENOMEM;
640 memcpy(fifo_buffer, buf, len);
641 kfifo_in(&test->up_fifo, &fifo_buffer, 4);
642 wake_up_interruptible(&priv->test.readq);
643
644 return 0;
645}
646
647
648
649static int ca8210_net_rx(
650 struct ieee802154_hw *hw,
651 u8 *command,
652 size_t len
653);
654static u8 mlme_reset_request_sync(
655 u8 set_default_pib,
656 void *device_ref
657);
658static int ca8210_spi_transfer(
659 struct spi_device *spi,
660 const u8 *buf,
661 size_t len
662);
663
664
665
666
667
668
669static void ca8210_reset_send(struct spi_device *spi, unsigned int ms)
670{
671 struct ca8210_platform_data *pdata = spi->dev.platform_data;
672 struct ca8210_priv *priv = spi_get_drvdata(spi);
673 long status;
674
675 gpio_set_value(pdata->gpio_reset, 0);
676 reinit_completion(&priv->ca8210_is_awake);
677 msleep(ms);
678 gpio_set_value(pdata->gpio_reset, 1);
679 priv->promiscuous = false;
680
681
682 status = wait_for_completion_interruptible_timeout(
683 &priv->ca8210_is_awake,
684 msecs_to_jiffies(CA8210_SYNC_TIMEOUT)
685 );
686 if (status == 0) {
687 dev_crit(
688 &spi->dev,
689 "Fatal: No wakeup from ca8210 after reset!\n"
690 );
691 }
692
693 dev_dbg(&spi->dev, "Reset the device\n");
694}
695
696
697
698
699
700
701static void ca8210_mlme_reset_worker(struct work_struct *work)
702{
703 struct work_priv_container *wpc = container_of(
704 work,
705 struct work_priv_container,
706 work
707 );
708 struct ca8210_priv *priv = wpc->priv;
709
710 mlme_reset_request_sync(0, priv->spi);
711 kfree(wpc);
712}
713
714
715
716
717
718
719
720
721
722static void ca8210_rx_done(struct cas_control *cas_ctl)
723{
724 u8 *buf;
725 u8 len;
726 struct work_priv_container *mlme_reset_wpc;
727 struct ca8210_priv *priv = cas_ctl->priv;
728
729 buf = cas_ctl->tx_in_buf;
730 len = buf[1] + 2;
731 if (len > CA8210_SPI_BUF_SIZE) {
732 dev_crit(
733 &priv->spi->dev,
734 "Received packet len (%d) erroneously long\n",
735 len
736 );
737 goto finish;
738 }
739
740 if (buf[0] & SPI_SYN) {
741 if (priv->sync_command_response) {
742 memcpy(priv->sync_command_response, buf, len);
743 complete(&priv->sync_exchange_complete);
744 } else {
745 if (cascoda_api_upstream)
746 cascoda_api_upstream(buf, len, priv->spi);
747 priv->sync_up++;
748 }
749 } else {
750 if (cascoda_api_upstream)
751 cascoda_api_upstream(buf, len, priv->spi);
752 }
753
754 ca8210_net_rx(priv->hw, buf, len);
755 if (buf[0] == SPI_MCPS_DATA_CONFIRM) {
756 if (buf[3] == MAC_TRANSACTION_OVERFLOW) {
757 dev_info(
758 &priv->spi->dev,
759 "Waiting for transaction overflow to stabilise...\n");
760 msleep(2000);
761 dev_info(
762 &priv->spi->dev,
763 "Resetting MAC...\n");
764
765 mlme_reset_wpc = kmalloc(sizeof(*mlme_reset_wpc),
766 GFP_KERNEL);
767 if (!mlme_reset_wpc)
768 goto finish;
769 INIT_WORK(
770 &mlme_reset_wpc->work,
771 ca8210_mlme_reset_worker
772 );
773 mlme_reset_wpc->priv = priv;
774 queue_work(priv->mlme_workqueue, &mlme_reset_wpc->work);
775 }
776 } else if (buf[0] == SPI_HWME_WAKEUP_INDICATION) {
777 dev_notice(
778 &priv->spi->dev,
779 "Wakeup indication received, reason:\n"
780 );
781 switch (buf[2]) {
782 case 0:
783 dev_notice(
784 &priv->spi->dev,
785 "Transceiver woken up from Power Up / System Reset\n"
786 );
787 break;
788 case 1:
789 dev_notice(
790 &priv->spi->dev,
791 "Watchdog Timer Time-Out\n"
792 );
793 break;
794 case 2:
795 dev_notice(
796 &priv->spi->dev,
797 "Transceiver woken up from Power-Off by Sleep Timer Time-Out\n");
798 break;
799 case 3:
800 dev_notice(
801 &priv->spi->dev,
802 "Transceiver woken up from Power-Off by GPIO Activity\n"
803 );
804 break;
805 case 4:
806 dev_notice(
807 &priv->spi->dev,
808 "Transceiver woken up from Standby by Sleep Timer Time-Out\n"
809 );
810 break;
811 case 5:
812 dev_notice(
813 &priv->spi->dev,
814 "Transceiver woken up from Standby by GPIO Activity\n"
815 );
816 break;
817 case 6:
818 dev_notice(
819 &priv->spi->dev,
820 "Sleep-Timer Time-Out in Active Mode\n"
821 );
822 break;
823 default:
824 dev_warn(&priv->spi->dev, "Wakeup reason unknown\n");
825 break;
826 }
827 complete(&priv->ca8210_is_awake);
828 }
829
830finish:;
831}
832
833static int ca8210_remove(struct spi_device *spi_device);
834
835
836
837
838
839
840static void ca8210_spi_transfer_complete(void *context)
841{
842 struct cas_control *cas_ctl = context;
843 struct ca8210_priv *priv = cas_ctl->priv;
844 bool duplex_rx = false;
845 int i;
846 u8 retry_buffer[CA8210_SPI_BUF_SIZE];
847
848 if (
849 cas_ctl->tx_in_buf[0] == SPI_NACK ||
850 (cas_ctl->tx_in_buf[0] == SPI_IDLE &&
851 cas_ctl->tx_in_buf[1] == SPI_NACK)
852 ) {
853
854 dev_info(&priv->spi->dev, "ca8210 was busy during attempted write\n");
855 if (cas_ctl->tx_buf[0] == SPI_IDLE) {
856 dev_warn(
857 &priv->spi->dev,
858 "IRQ servicing NACKd, dropping transfer\n"
859 );
860 kfree(cas_ctl);
861 return;
862 }
863 if (priv->retries > 3) {
864 dev_err(&priv->spi->dev, "too many retries!\n");
865 kfree(cas_ctl);
866 ca8210_remove(priv->spi);
867 return;
868 }
869 memcpy(retry_buffer, cas_ctl->tx_buf, CA8210_SPI_BUF_SIZE);
870 kfree(cas_ctl);
871 ca8210_spi_transfer(
872 priv->spi,
873 retry_buffer,
874 CA8210_SPI_BUF_SIZE
875 );
876 priv->retries++;
877 dev_info(&priv->spi->dev, "retried spi write\n");
878 return;
879 } else if (
880 cas_ctl->tx_in_buf[0] != SPI_IDLE &&
881 cas_ctl->tx_in_buf[0] != SPI_NACK
882 ) {
883 duplex_rx = true;
884 }
885
886 if (duplex_rx) {
887 dev_dbg(&priv->spi->dev, "READ CMD DURING TX\n");
888 for (i = 0; i < cas_ctl->tx_in_buf[1] + 2; i++)
889 dev_dbg(
890 &priv->spi->dev,
891 "%#03x\n",
892 cas_ctl->tx_in_buf[i]
893 );
894 ca8210_rx_done(cas_ctl);
895 }
896 complete(&priv->spi_transfer_complete);
897 kfree(cas_ctl);
898 priv->retries = 0;
899}
900
901
902
903
904
905
906
907
908
909static int ca8210_spi_transfer(
910 struct spi_device *spi,
911 const u8 *buf,
912 size_t len
913)
914{
915 int i, status = 0;
916 struct ca8210_priv *priv;
917 struct cas_control *cas_ctl;
918
919 if (!spi) {
920 pr_crit("NULL spi device passed to %s\n", __func__);
921 return -ENODEV;
922 }
923
924 priv = spi_get_drvdata(spi);
925 reinit_completion(&priv->spi_transfer_complete);
926
927 dev_dbg(&spi->dev, "ca8210_spi_transfer called\n");
928
929 cas_ctl = kmalloc(sizeof(*cas_ctl), GFP_ATOMIC);
930 if (!cas_ctl)
931 return -ENOMEM;
932
933 cas_ctl->priv = priv;
934 memset(cas_ctl->tx_buf, SPI_IDLE, CA8210_SPI_BUF_SIZE);
935 memset(cas_ctl->tx_in_buf, SPI_IDLE, CA8210_SPI_BUF_SIZE);
936 memcpy(cas_ctl->tx_buf, buf, len);
937
938 for (i = 0; i < len; i++)
939 dev_dbg(&spi->dev, "%#03x\n", cas_ctl->tx_buf[i]);
940
941 spi_message_init(&cas_ctl->msg);
942
943 cas_ctl->transfer.tx_nbits = 1;
944 cas_ctl->transfer.rx_nbits = 1;
945 cas_ctl->transfer.speed_hz = 0;
946 cas_ctl->transfer.bits_per_word = 0;
947 cas_ctl->transfer.tx_buf = cas_ctl->tx_buf;
948 cas_ctl->transfer.rx_buf = cas_ctl->tx_in_buf;
949 cas_ctl->transfer.delay_usecs = 0;
950 cas_ctl->transfer.cs_change = 0;
951 cas_ctl->transfer.len = sizeof(struct mac_message);
952 cas_ctl->msg.complete = ca8210_spi_transfer_complete;
953 cas_ctl->msg.context = cas_ctl;
954
955 spi_message_add_tail(
956 &cas_ctl->transfer,
957 &cas_ctl->msg
958 );
959
960 status = spi_async(spi, &cas_ctl->msg);
961 if (status < 0) {
962 dev_crit(
963 &spi->dev,
964 "status %d from spi_sync in write\n",
965 status
966 );
967 }
968
969 return status;
970}
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985static int ca8210_spi_exchange(
986 const u8 *buf,
987 size_t len,
988 u8 *response,
989 void *device_ref
990)
991{
992 int status = 0;
993 struct spi_device *spi = device_ref;
994 struct ca8210_priv *priv = spi->dev.driver_data;
995 long wait_remaining;
996
997 if ((buf[0] & SPI_SYN) && response) {
998 reinit_completion(&priv->sync_exchange_complete);
999 priv->sync_command_response = response;
1000 }
1001
1002 do {
1003 reinit_completion(&priv->spi_transfer_complete);
1004 status = ca8210_spi_transfer(priv->spi, buf, len);
1005 if (status) {
1006 dev_warn(
1007 &spi->dev,
1008 "spi write failed, returned %d\n",
1009 status
1010 );
1011 if (status == -EBUSY)
1012 continue;
1013 if (((buf[0] & SPI_SYN) && response))
1014 complete(&priv->sync_exchange_complete);
1015 goto cleanup;
1016 }
1017
1018 wait_remaining = wait_for_completion_interruptible_timeout(
1019 &priv->spi_transfer_complete,
1020 msecs_to_jiffies(1000)
1021 );
1022 if (wait_remaining == -ERESTARTSYS) {
1023 status = -ERESTARTSYS;
1024 } else if (wait_remaining == 0) {
1025 dev_err(
1026 &spi->dev,
1027 "SPI downstream transfer timed out!\n"
1028 );
1029 status = -ETIME;
1030 goto cleanup;
1031 }
1032 } while (status < 0);
1033
1034 if (!((buf[0] & SPI_SYN) && response))
1035 goto cleanup;
1036
1037 wait_remaining = wait_for_completion_interruptible_timeout(
1038 &priv->sync_exchange_complete,
1039 msecs_to_jiffies(CA8210_SYNC_TIMEOUT)
1040 );
1041 if (wait_remaining == -ERESTARTSYS) {
1042 status = -ERESTARTSYS;
1043 } else if (wait_remaining == 0) {
1044 dev_err(
1045 &spi->dev,
1046 "Synchronous confirm timeout\n"
1047 );
1048 status = -ETIME;
1049 }
1050
1051cleanup:
1052 priv->sync_command_response = NULL;
1053 return status;
1054}
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067static irqreturn_t ca8210_interrupt_handler(int irq, void *dev_id)
1068{
1069 struct ca8210_priv *priv = dev_id;
1070 int status;
1071
1072 dev_dbg(&priv->spi->dev, "irq: Interrupt occurred\n");
1073 do {
1074 status = ca8210_spi_transfer(priv->spi, NULL, 0);
1075 if (status && (status != -EBUSY)) {
1076 dev_warn(
1077 &priv->spi->dev,
1078 "spi read failed, returned %d\n",
1079 status
1080 );
1081 }
1082 } while (status == -EBUSY);
1083 return IRQ_HANDLED;
1084}
1085
1086static int (*cascoda_api_downstream)(
1087 const u8 *buf,
1088 size_t len,
1089 u8 *response,
1090 void *device_ref
1091) = ca8210_spi_exchange;
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104static u8 tdme_setsfr_request_sync(
1105 u8 sfr_page,
1106 u8 sfr_address,
1107 u8 sfr_value,
1108 void *device_ref
1109)
1110{
1111 int ret;
1112 struct mac_message command, response;
1113 struct spi_device *spi = device_ref;
1114
1115 command.command_id = SPI_TDME_SETSFR_REQUEST;
1116 command.length = 3;
1117 command.pdata.tdme_set_sfr_req.sfr_page = sfr_page;
1118 command.pdata.tdme_set_sfr_req.sfr_address = sfr_address;
1119 command.pdata.tdme_set_sfr_req.sfr_value = sfr_value;
1120 response.command_id = SPI_IDLE;
1121 ret = cascoda_api_downstream(
1122 &command.command_id,
1123 command.length + 2,
1124 &response.command_id,
1125 device_ref
1126 );
1127 if (ret) {
1128 dev_crit(&spi->dev, "cascoda_api_downstream returned %d", ret);
1129 return MAC_SYSTEM_ERROR;
1130 }
1131
1132 if (response.command_id != SPI_TDME_SETSFR_CONFIRM) {
1133 dev_crit(
1134 &spi->dev,
1135 "sync response to SPI_TDME_SETSFR_REQUEST was not SPI_TDME_SETSFR_CONFIRM, it was %d\n",
1136 response.command_id
1137 );
1138 return MAC_SYSTEM_ERROR;
1139 }
1140
1141 return response.pdata.tdme_set_sfr_cnf.status;
1142}
1143
1144
1145
1146
1147
1148
1149
1150static u8 tdme_chipinit(void *device_ref)
1151{
1152 u8 status = MAC_SUCCESS;
1153 u8 sfr_address;
1154 struct spi_device *spi = device_ref;
1155 struct preamble_cfg_sfr pre_cfg_value = {
1156 .timeout_symbols = 3,
1157 .acquisition_symbols = 3,
1158 .search_symbols = 1,
1159 };
1160
1161 status = tdme_setsfr_request_sync(
1162 1, (sfr_address = CA8210_SFR_LNAGX40),
1163 LNAGX40_DEFAULT_GAIN, device_ref);
1164 if (status)
1165 goto finish;
1166 status = tdme_setsfr_request_sync(
1167 1, (sfr_address = CA8210_SFR_LNAGX41),
1168 LNAGX41_DEFAULT_GAIN, device_ref);
1169 if (status)
1170 goto finish;
1171 status = tdme_setsfr_request_sync(
1172 1, (sfr_address = CA8210_SFR_LNAGX42),
1173 LNAGX42_DEFAULT_GAIN, device_ref);
1174 if (status)
1175 goto finish;
1176 status = tdme_setsfr_request_sync(
1177 1, (sfr_address = CA8210_SFR_LNAGX43),
1178 LNAGX43_DEFAULT_GAIN, device_ref);
1179 if (status)
1180 goto finish;
1181 status = tdme_setsfr_request_sync(
1182 1, (sfr_address = CA8210_SFR_LNAGX44),
1183 LNAGX44_DEFAULT_GAIN, device_ref);
1184 if (status)
1185 goto finish;
1186 status = tdme_setsfr_request_sync(
1187 1, (sfr_address = CA8210_SFR_LNAGX45),
1188 LNAGX45_DEFAULT_GAIN, device_ref);
1189 if (status)
1190 goto finish;
1191 status = tdme_setsfr_request_sync(
1192 1, (sfr_address = CA8210_SFR_LNAGX46),
1193 LNAGX46_DEFAULT_GAIN, device_ref);
1194 if (status)
1195 goto finish;
1196 status = tdme_setsfr_request_sync(
1197 1, (sfr_address = CA8210_SFR_LNAGX47),
1198 LNAGX47_DEFAULT_GAIN, device_ref);
1199 if (status)
1200 goto finish;
1201
1202 status = tdme_setsfr_request_sync(
1203 1, (sfr_address = CA8210_SFR_PRECFG),
1204 *((u8 *)&pre_cfg_value), device_ref);
1205 if (status)
1206 goto finish;
1207
1208 status = tdme_setsfr_request_sync(
1209 1, (sfr_address = CA8210_SFR_PTHRH),
1210 PTHRH_DEFAULT_THRESHOLD, device_ref);
1211 if (status)
1212 goto finish;
1213
1214 status = tdme_setsfr_request_sync(
1215 0, (sfr_address = CA8210_SFR_PACFGIB),
1216 PACFGIB_DEFAULT_CURRENT, device_ref);
1217 if (status)
1218 goto finish;
1219
1220finish:
1221 if (status != MAC_SUCCESS) {
1222 dev_err(
1223 &spi->dev,
1224 "failed to set sfr at %#03x, status = %#03x\n",
1225 sfr_address,
1226 status
1227 );
1228 }
1229 return status;
1230}
1231
1232
1233
1234
1235
1236
1237
1238
1239static u8 tdme_channelinit(u8 channel, void *device_ref)
1240{
1241
1242
1243
1244 u8 txcalval;
1245
1246 if (channel >= 25)
1247 txcalval = 0xA7;
1248 else if (channel >= 23)
1249 txcalval = 0xA8;
1250 else if (channel >= 22)
1251 txcalval = 0xA9;
1252 else if (channel >= 20)
1253 txcalval = 0xAA;
1254 else if (channel >= 17)
1255 txcalval = 0xAB;
1256 else if (channel >= 16)
1257 txcalval = 0xAC;
1258 else if (channel >= 14)
1259 txcalval = 0xAD;
1260 else if (channel >= 12)
1261 txcalval = 0xAE;
1262 else
1263 txcalval = 0xAF;
1264
1265 return tdme_setsfr_request_sync(
1266 1,
1267 CA8210_SFR_LOTXCAL,
1268 txcalval,
1269 device_ref
1270 );
1271}
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283static u8 tdme_checkpibattribute(
1284 u8 pib_attribute,
1285 u8 pib_attribute_length,
1286 const void *pib_attribute_value
1287)
1288{
1289 u8 status = MAC_SUCCESS;
1290 u8 value;
1291
1292 value = *((u8 *)pib_attribute_value);
1293
1294 switch (pib_attribute) {
1295
1296 case PHY_TRANSMIT_POWER:
1297 if (value > 0x3F)
1298 status = MAC_INVALID_PARAMETER;
1299 break;
1300 case PHY_CCA_MODE:
1301 if (value > 0x03)
1302 status = MAC_INVALID_PARAMETER;
1303 break;
1304
1305 case MAC_BATT_LIFE_EXT_PERIODS:
1306 if ((value < 6) || (value > 41))
1307 status = MAC_INVALID_PARAMETER;
1308 break;
1309 case MAC_BEACON_PAYLOAD:
1310 if (pib_attribute_length > MAX_BEACON_PAYLOAD_LENGTH)
1311 status = MAC_INVALID_PARAMETER;
1312 break;
1313 case MAC_BEACON_PAYLOAD_LENGTH:
1314 if (value > MAX_BEACON_PAYLOAD_LENGTH)
1315 status = MAC_INVALID_PARAMETER;
1316 break;
1317 case MAC_BEACON_ORDER:
1318 if (value > 15)
1319 status = MAC_INVALID_PARAMETER;
1320 break;
1321 case MAC_MAX_BE:
1322 if ((value < 3) || (value > 8))
1323 status = MAC_INVALID_PARAMETER;
1324 break;
1325 case MAC_MAX_CSMA_BACKOFFS:
1326 if (value > 5)
1327 status = MAC_INVALID_PARAMETER;
1328 break;
1329 case MAC_MAX_FRAME_RETRIES:
1330 if (value > 7)
1331 status = MAC_INVALID_PARAMETER;
1332 break;
1333 case MAC_MIN_BE:
1334 if (value > 8)
1335 status = MAC_INVALID_PARAMETER;
1336 break;
1337 case MAC_RESPONSE_WAIT_TIME:
1338 if ((value < 2) || (value > 64))
1339 status = MAC_INVALID_PARAMETER;
1340 break;
1341 case MAC_SUPERFRAME_ORDER:
1342 if (value > 15)
1343 status = MAC_INVALID_PARAMETER;
1344 break;
1345
1346 case MAC_ASSOCIATED_PAN_COORD:
1347 case MAC_ASSOCIATION_PERMIT:
1348 case MAC_AUTO_REQUEST:
1349 case MAC_BATT_LIFE_EXT:
1350 case MAC_GTS_PERMIT:
1351 case MAC_PROMISCUOUS_MODE:
1352 case MAC_RX_ON_WHEN_IDLE:
1353 case MAC_SECURITY_ENABLED:
1354 if (value > 1)
1355 status = MAC_INVALID_PARAMETER;
1356 break;
1357
1358 case MAC_AUTO_REQUEST_SECURITY_LEVEL:
1359 if (value > 7)
1360 status = MAC_INVALID_PARAMETER;
1361 break;
1362 case MAC_AUTO_REQUEST_KEY_ID_MODE:
1363 if (value > 3)
1364 status = MAC_INVALID_PARAMETER;
1365 break;
1366 default:
1367 break;
1368 }
1369
1370 return status;
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384static u8 tdme_settxpower(u8 txp, void *device_ref)
1385{
1386 u8 status;
1387 s8 txp_val;
1388 u8 txp_ext;
1389 union pa_cfg_sfr pa_cfg_val;
1390
1391
1392 txp_ext = 0x3F & txp;
1393 if (txp_ext & 0x20)
1394 txp_ext += 0xC0;
1395 txp_val = (s8)txp_ext;
1396
1397 if (CA8210_MAC_MPW) {
1398 if (txp_val > 0) {
1399
1400 pa_cfg_val.bias_current_trim = 3;
1401 pa_cfg_val.buffer_capacitor_trim = 5;
1402 pa_cfg_val.boost = 1;
1403 } else {
1404
1405 pa_cfg_val.bias_current_trim = 3;
1406 pa_cfg_val.buffer_capacitor_trim = 7;
1407 pa_cfg_val.boost = 0;
1408 }
1409
1410 status = tdme_setsfr_request_sync(
1411 0,
1412 CA8210_SFR_PACFG,
1413 pa_cfg_val.paib,
1414 device_ref
1415 );
1416 } else {
1417
1418
1419
1420 if (txp_val > 8) {
1421 pa_cfg_val.paib = 0x3F;
1422 } else if (txp_val == 8) {
1423 pa_cfg_val.paib = 0x32;
1424 } else if (txp_val == 7) {
1425 pa_cfg_val.paib = 0x22;
1426 } else if (txp_val == 6) {
1427 pa_cfg_val.paib = 0x18;
1428 } else if (txp_val == 5) {
1429 pa_cfg_val.paib = 0x10;
1430 } else if (txp_val == 4) {
1431 pa_cfg_val.paib = 0x0C;
1432 } else if (txp_val == 3) {
1433 pa_cfg_val.paib = 0x08;
1434 } else if (txp_val == 2) {
1435 pa_cfg_val.paib = 0x05;
1436 } else if (txp_val == 1) {
1437 pa_cfg_val.paib = 0x03;
1438 } else if (txp_val == 0) {
1439 pa_cfg_val.paib = 0x01;
1440 } else {
1441 pa_cfg_val.paib = 0x00;
1442 }
1443
1444 status = tdme_setsfr_request_sync(
1445 0,
1446 CA8210_SFR_PACFGIB,
1447 pa_cfg_val.paib,
1448 device_ref
1449 );
1450 }
1451
1452 return status;
1453}
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470static u8 mcps_data_request(
1471 u8 src_addr_mode,
1472 u8 dst_address_mode,
1473 u16 dst_pan_id,
1474 union macaddr *dst_addr,
1475 u8 msdu_length,
1476 u8 *msdu,
1477 u8 msdu_handle,
1478 u8 tx_options,
1479 struct secspec *security,
1480 void *device_ref
1481)
1482{
1483 struct secspec *psec;
1484 struct mac_message command;
1485
1486 command.command_id = SPI_MCPS_DATA_REQUEST;
1487 command.pdata.data_req.src_addr_mode = src_addr_mode;
1488 command.pdata.data_req.dst.mode = dst_address_mode;
1489 if (dst_address_mode != MAC_MODE_NO_ADDR) {
1490 command.pdata.data_req.dst.pan_id[0] = LS_BYTE(dst_pan_id);
1491 command.pdata.data_req.dst.pan_id[1] = MS_BYTE(dst_pan_id);
1492 if (dst_address_mode == MAC_MODE_SHORT_ADDR) {
1493 command.pdata.data_req.dst.address[0] = LS_BYTE(
1494 dst_addr->short_address
1495 );
1496 command.pdata.data_req.dst.address[1] = MS_BYTE(
1497 dst_addr->short_address
1498 );
1499 } else {
1500 memcpy(
1501 command.pdata.data_req.dst.address,
1502 dst_addr->ieee_address,
1503 8
1504 );
1505 }
1506 }
1507 command.pdata.data_req.msdu_length = msdu_length;
1508 command.pdata.data_req.msdu_handle = msdu_handle;
1509 command.pdata.data_req.tx_options = tx_options;
1510 memcpy(command.pdata.data_req.msdu, msdu, msdu_length);
1511 psec = (struct secspec *)(command.pdata.data_req.msdu + msdu_length);
1512 command.length = sizeof(struct mcps_data_request_pset) -
1513 MAX_DATA_SIZE + msdu_length;
1514 if (!security || (security->security_level == 0)) {
1515 psec->security_level = 0;
1516 command.length += 1;
1517 } else {
1518 *psec = *security;
1519 command.length += sizeof(struct secspec);
1520 }
1521
1522 if (ca8210_spi_transfer(device_ref, &command.command_id,
1523 command.length + 2))
1524 return MAC_SYSTEM_ERROR;
1525
1526 return MAC_SUCCESS;
1527}
1528
1529
1530
1531
1532
1533
1534
1535
1536static u8 mlme_reset_request_sync(
1537 u8 set_default_pib,
1538 void *device_ref
1539)
1540{
1541 u8 status;
1542 struct mac_message command, response;
1543 struct spi_device *spi = device_ref;
1544
1545 command.command_id = SPI_MLME_RESET_REQUEST;
1546 command.length = 1;
1547 command.pdata.u8param = set_default_pib;
1548
1549 if (cascoda_api_downstream(
1550 &command.command_id,
1551 command.length + 2,
1552 &response.command_id,
1553 device_ref)) {
1554 dev_err(&spi->dev, "cascoda_api_downstream failed\n");
1555 return MAC_SYSTEM_ERROR;
1556 }
1557
1558 if (response.command_id != SPI_MLME_RESET_CONFIRM)
1559 return MAC_SYSTEM_ERROR;
1560
1561 status = response.pdata.status;
1562
1563
1564 if (CA8210_MAC_WORKAROUNDS && set_default_pib && (!status)) {
1565 status = tdme_setsfr_request_sync(
1566 0,
1567 CA8210_SFR_MACCON,
1568 0,
1569 device_ref
1570 );
1571 }
1572
1573 return status;
1574}
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586static u8 mlme_set_request_sync(
1587 u8 pib_attribute,
1588 u8 pib_attribute_index,
1589 u8 pib_attribute_length,
1590 const void *pib_attribute_value,
1591 void *device_ref
1592)
1593{
1594 u8 status;
1595 struct mac_message command, response;
1596
1597
1598
1599
1600 if (tdme_checkpibattribute(
1601 pib_attribute, pib_attribute_length, pib_attribute_value)) {
1602 return MAC_INVALID_PARAMETER;
1603 }
1604
1605 if (pib_attribute == PHY_CURRENT_CHANNEL) {
1606 status = tdme_channelinit(
1607 *((u8 *)pib_attribute_value),
1608 device_ref
1609 );
1610 if (status)
1611 return status;
1612 }
1613
1614 if (pib_attribute == PHY_TRANSMIT_POWER) {
1615 return tdme_settxpower(
1616 *((u8 *)pib_attribute_value),
1617 device_ref
1618 );
1619 }
1620
1621 command.command_id = SPI_MLME_SET_REQUEST;
1622 command.length = sizeof(struct mlme_set_request_pset) -
1623 MAX_ATTRIBUTE_SIZE + pib_attribute_length;
1624 command.pdata.set_req.pib_attribute = pib_attribute;
1625 command.pdata.set_req.pib_attribute_index = pib_attribute_index;
1626 command.pdata.set_req.pib_attribute_length = pib_attribute_length;
1627 memcpy(
1628 command.pdata.set_req.pib_attribute_value,
1629 pib_attribute_value,
1630 pib_attribute_length
1631 );
1632
1633 if (cascoda_api_downstream(
1634 &command.command_id,
1635 command.length + 2,
1636 &response.command_id,
1637 device_ref)) {
1638 return MAC_SYSTEM_ERROR;
1639 }
1640
1641 if (response.command_id != SPI_MLME_SET_CONFIRM)
1642 return MAC_SYSTEM_ERROR;
1643
1644 return response.pdata.status;
1645}
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656static u8 hwme_set_request_sync(
1657 u8 hw_attribute,
1658 u8 hw_attribute_length,
1659 u8 *hw_attribute_value,
1660 void *device_ref
1661)
1662{
1663 struct mac_message command, response;
1664
1665 command.command_id = SPI_HWME_SET_REQUEST;
1666 command.length = 2 + hw_attribute_length;
1667 command.pdata.hwme_set_req.hw_attribute = hw_attribute;
1668 command.pdata.hwme_set_req.hw_attribute_length = hw_attribute_length;
1669 memcpy(
1670 command.pdata.hwme_set_req.hw_attribute_value,
1671 hw_attribute_value,
1672 hw_attribute_length
1673 );
1674
1675 if (cascoda_api_downstream(
1676 &command.command_id,
1677 command.length + 2,
1678 &response.command_id,
1679 device_ref)) {
1680 return MAC_SYSTEM_ERROR;
1681 }
1682
1683 if (response.command_id != SPI_HWME_SET_CONFIRM)
1684 return MAC_SYSTEM_ERROR;
1685
1686 return response.pdata.hwme_set_cnf.status;
1687}
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698static u8 hwme_get_request_sync(
1699 u8 hw_attribute,
1700 u8 *hw_attribute_length,
1701 u8 *hw_attribute_value,
1702 void *device_ref
1703)
1704{
1705 struct mac_message command, response;
1706
1707 command.command_id = SPI_HWME_GET_REQUEST;
1708 command.length = 1;
1709 command.pdata.hwme_get_req.hw_attribute = hw_attribute;
1710
1711 if (cascoda_api_downstream(
1712 &command.command_id,
1713 command.length + 2,
1714 &response.command_id,
1715 device_ref)) {
1716 return MAC_SYSTEM_ERROR;
1717 }
1718
1719 if (response.command_id != SPI_HWME_GET_CONFIRM)
1720 return MAC_SYSTEM_ERROR;
1721
1722 if (response.pdata.hwme_get_cnf.status == MAC_SUCCESS) {
1723 *hw_attribute_length =
1724 response.pdata.hwme_get_cnf.hw_attribute_length;
1725 memcpy(
1726 hw_attribute_value,
1727 response.pdata.hwme_get_cnf.hw_attribute_value,
1728 *hw_attribute_length
1729 );
1730 }
1731
1732 return response.pdata.hwme_get_cnf.status;
1733}
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746static int ca8210_async_xmit_complete(
1747 struct ieee802154_hw *hw,
1748 u8 msduhandle,
1749 u8 status)
1750{
1751 struct ca8210_priv *priv = hw->priv;
1752
1753 if (priv->nextmsduhandle != msduhandle) {
1754 dev_err(
1755 &priv->spi->dev,
1756 "Unexpected msdu_handle on data confirm, Expected %d, got %d\n",
1757 priv->nextmsduhandle,
1758 msduhandle
1759 );
1760 return -EIO;
1761 }
1762
1763 priv->async_tx_pending = false;
1764 priv->nextmsduhandle++;
1765
1766 if (status) {
1767 dev_err(
1768 &priv->spi->dev,
1769 "Link transmission unsuccessful, status = %d\n",
1770 status
1771 );
1772 if (status != MAC_TRANSACTION_OVERFLOW) {
1773 ieee802154_wake_queue(priv->hw);
1774 return 0;
1775 }
1776 }
1777 ieee802154_xmit_complete(priv->hw, priv->tx_skb, true);
1778
1779 return 0;
1780}
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795static int ca8210_skb_rx(
1796 struct ieee802154_hw *hw,
1797 size_t len,
1798 u8 *data_ind
1799)
1800{
1801 struct ieee802154_hdr hdr;
1802 int msdulen;
1803 int hlen;
1804 u8 mpdulinkquality = data_ind[23];
1805 struct sk_buff *skb;
1806 struct ca8210_priv *priv = hw->priv;
1807
1808
1809 skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr));
1810 if (!skb)
1811 return -ENOMEM;
1812
1813 skb_reserve(skb, sizeof(hdr));
1814
1815 msdulen = data_ind[22];
1816 if (msdulen > IEEE802154_MTU) {
1817 dev_err(
1818 &priv->spi->dev,
1819 "received erroneously large msdu length!\n"
1820 );
1821 kfree_skb(skb);
1822 return -EMSGSIZE;
1823 }
1824 dev_dbg(&priv->spi->dev, "skb buffer length = %d\n", msdulen);
1825
1826 if (priv->promiscuous)
1827 goto copy_payload;
1828
1829
1830 hdr.sec.level = data_ind[29 + msdulen];
1831 dev_dbg(&priv->spi->dev, "security level: %#03x\n", hdr.sec.level);
1832 if (hdr.sec.level > 0) {
1833 hdr.sec.key_id_mode = data_ind[30 + msdulen];
1834 memcpy(&hdr.sec.extended_src, &data_ind[31 + msdulen], 8);
1835 hdr.sec.key_id = data_ind[39 + msdulen];
1836 }
1837 hdr.source.mode = data_ind[0];
1838 dev_dbg(&priv->spi->dev, "srcAddrMode: %#03x\n", hdr.source.mode);
1839 hdr.source.pan_id = *(u16 *)&data_ind[1];
1840 dev_dbg(&priv->spi->dev, "srcPanId: %#06x\n", hdr.source.pan_id);
1841 memcpy(&hdr.source.extended_addr, &data_ind[3], 8);
1842 hdr.dest.mode = data_ind[11];
1843 dev_dbg(&priv->spi->dev, "dstAddrMode: %#03x\n", hdr.dest.mode);
1844 hdr.dest.pan_id = *(u16 *)&data_ind[12];
1845 dev_dbg(&priv->spi->dev, "dstPanId: %#06x\n", hdr.dest.pan_id);
1846 memcpy(&hdr.dest.extended_addr, &data_ind[14], 8);
1847
1848
1849 hdr.fc.type = 1;
1850 if (hdr.sec.level)
1851 hdr.fc.security_enabled = 1;
1852 else
1853 hdr.fc.security_enabled = 0;
1854 if (data_ind[1] != data_ind[12] || data_ind[2] != data_ind[13])
1855 hdr.fc.intra_pan = 1;
1856 else
1857 hdr.fc.intra_pan = 0;
1858 hdr.fc.dest_addr_mode = hdr.dest.mode;
1859 hdr.fc.source_addr_mode = hdr.source.mode;
1860
1861
1862 hlen = ieee802154_hdr_push(skb, &hdr);
1863
1864 if (hlen < 0) {
1865 dev_crit(&priv->spi->dev, "failed to push mac hdr onto skb!\n");
1866 kfree_skb(skb);
1867 return hlen;
1868 }
1869
1870 skb_reset_mac_header(skb);
1871 skb->mac_len = hlen;
1872
1873copy_payload:
1874
1875
1876 skb_put_data(skb, &data_ind[29], msdulen);
1877
1878 ieee802154_rx_irqsafe(hw, skb, mpdulinkquality);
1879 return 0;
1880}
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895static int ca8210_net_rx(struct ieee802154_hw *hw, u8 *command, size_t len)
1896{
1897 struct ca8210_priv *priv = hw->priv;
1898 unsigned long flags;
1899 u8 status;
1900
1901 dev_dbg(&priv->spi->dev, "ca8210_net_rx(), CmdID = %d\n", command[0]);
1902
1903 if (command[0] == SPI_MCPS_DATA_INDICATION) {
1904
1905 spin_lock_irqsave(&priv->lock, flags);
1906 if (command[26] == priv->last_dsn) {
1907 dev_dbg(
1908 &priv->spi->dev,
1909 "DSN %d resend received, ignoring...\n",
1910 command[26]
1911 );
1912 spin_unlock_irqrestore(&priv->lock, flags);
1913 return 0;
1914 }
1915 priv->last_dsn = command[26];
1916 spin_unlock_irqrestore(&priv->lock, flags);
1917 return ca8210_skb_rx(hw, len - 2, command + 2);
1918 } else if (command[0] == SPI_MCPS_DATA_CONFIRM) {
1919 status = command[3];
1920 if (priv->async_tx_pending) {
1921 return ca8210_async_xmit_complete(
1922 hw,
1923 command[2],
1924 status
1925 );
1926 }
1927 }
1928
1929 return 0;
1930}
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940static int ca8210_skb_tx(
1941 struct sk_buff *skb,
1942 u8 msduhandle,
1943 struct ca8210_priv *priv
1944)
1945{
1946 int status;
1947 struct ieee802154_hdr header = { 0 };
1948 struct secspec secspec;
1949 unsigned int mac_len;
1950
1951 dev_dbg(&priv->spi->dev, "ca8210_skb_tx() called\n");
1952
1953
1954
1955
1956 mac_len = ieee802154_hdr_peek_addrs(skb, &header);
1957
1958 secspec.security_level = header.sec.level;
1959 secspec.key_id_mode = header.sec.key_id_mode;
1960 if (secspec.key_id_mode == 2)
1961 memcpy(secspec.key_source, &header.sec.short_src, 4);
1962 else if (secspec.key_id_mode == 3)
1963 memcpy(secspec.key_source, &header.sec.extended_src, 8);
1964 secspec.key_index = header.sec.key_id;
1965
1966
1967 status = mcps_data_request(
1968 header.source.mode,
1969 header.dest.mode,
1970 header.dest.pan_id,
1971 (union macaddr *)&header.dest.extended_addr,
1972 skb->len - mac_len,
1973 &skb->data[mac_len],
1974 msduhandle,
1975 header.fc.ack_request,
1976 &secspec,
1977 priv->spi
1978 );
1979 return link_to_linux_err(status);
1980}
1981
1982
1983
1984
1985
1986
1987
1988static int ca8210_start(struct ieee802154_hw *hw)
1989{
1990 int status;
1991 u8 rx_on_when_idle;
1992 u8 lqi_threshold = 0;
1993 struct ca8210_priv *priv = hw->priv;
1994
1995 priv->last_dsn = -1;
1996
1997 rx_on_when_idle = 1;
1998 status = mlme_set_request_sync(
1999 MAC_RX_ON_WHEN_IDLE,
2000 0,
2001 1,
2002 &rx_on_when_idle,
2003 priv->spi
2004 );
2005 if (status) {
2006 dev_crit(
2007 &priv->spi->dev,
2008 "Setting rx_on_when_idle failed, status = %d\n",
2009 status
2010 );
2011 return link_to_linux_err(status);
2012 }
2013 status = hwme_set_request_sync(
2014 HWME_LQILIMIT,
2015 1,
2016 &lqi_threshold,
2017 priv->spi
2018 );
2019 if (status) {
2020 dev_crit(
2021 &priv->spi->dev,
2022 "Setting lqilimit failed, status = %d\n",
2023 status
2024 );
2025 return link_to_linux_err(status);
2026 }
2027
2028 return 0;
2029}
2030
2031
2032
2033
2034
2035
2036
2037static void ca8210_stop(struct ieee802154_hw *hw)
2038{
2039}
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049static int ca8210_xmit_async(struct ieee802154_hw *hw, struct sk_buff *skb)
2050{
2051 struct ca8210_priv *priv = hw->priv;
2052 int status;
2053
2054 dev_dbg(&priv->spi->dev, "calling ca8210_xmit_async()\n");
2055
2056 priv->tx_skb = skb;
2057 priv->async_tx_pending = true;
2058 status = ca8210_skb_tx(skb, priv->nextmsduhandle, priv);
2059 return status;
2060}
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070static int ca8210_get_ed(struct ieee802154_hw *hw, u8 *level)
2071{
2072 u8 lenvar;
2073 struct ca8210_priv *priv = hw->priv;
2074
2075 return link_to_linux_err(
2076 hwme_get_request_sync(HWME_EDVALUE, &lenvar, level, priv->spi)
2077 );
2078}
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089static int ca8210_set_channel(
2090 struct ieee802154_hw *hw,
2091 u8 page,
2092 u8 channel
2093)
2094{
2095 u8 status;
2096 struct ca8210_priv *priv = hw->priv;
2097
2098 status = mlme_set_request_sync(
2099 PHY_CURRENT_CHANNEL,
2100 0,
2101 1,
2102 &channel,
2103 priv->spi
2104 );
2105 if (status) {
2106 dev_err(
2107 &priv->spi->dev,
2108 "error setting channel, MLME-SET.confirm status = %d\n",
2109 status
2110 );
2111 }
2112 return link_to_linux_err(status);
2113}
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128static int ca8210_set_hw_addr_filt(
2129 struct ieee802154_hw *hw,
2130 struct ieee802154_hw_addr_filt *filt,
2131 unsigned long changed
2132)
2133{
2134 u8 status = 0;
2135 struct ca8210_priv *priv = hw->priv;
2136
2137 if (changed & IEEE802154_AFILT_PANID_CHANGED) {
2138 status = mlme_set_request_sync(
2139 MAC_PAN_ID,
2140 0,
2141 2,
2142 &filt->pan_id, priv->spi
2143 );
2144 if (status) {
2145 dev_err(
2146 &priv->spi->dev,
2147 "error setting pan id, MLME-SET.confirm status = %d",
2148 status
2149 );
2150 return link_to_linux_err(status);
2151 }
2152 }
2153 if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
2154 status = mlme_set_request_sync(
2155 MAC_SHORT_ADDRESS,
2156 0,
2157 2,
2158 &filt->short_addr, priv->spi
2159 );
2160 if (status) {
2161 dev_err(
2162 &priv->spi->dev,
2163 "error setting short address, MLME-SET.confirm status = %d",
2164 status
2165 );
2166 return link_to_linux_err(status);
2167 }
2168 }
2169 if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
2170 status = mlme_set_request_sync(
2171 NS_IEEE_ADDRESS,
2172 0,
2173 8,
2174 &filt->ieee_addr,
2175 priv->spi
2176 );
2177 if (status) {
2178 dev_err(
2179 &priv->spi->dev,
2180 "error setting ieee address, MLME-SET.confirm status = %d",
2181 status
2182 );
2183 return link_to_linux_err(status);
2184 }
2185 }
2186
2187 return 0;
2188}
2189
2190
2191
2192
2193
2194
2195
2196
2197static int ca8210_set_tx_power(struct ieee802154_hw *hw, s32 mbm)
2198{
2199 struct ca8210_priv *priv = hw->priv;
2200
2201 mbm /= 100;
2202 return link_to_linux_err(
2203 mlme_set_request_sync(PHY_TRANSMIT_POWER, 0, 1, &mbm, priv->spi)
2204 );
2205}
2206
2207
2208
2209
2210
2211
2212
2213
2214static int ca8210_set_cca_mode(
2215 struct ieee802154_hw *hw,
2216 const struct wpan_phy_cca *cca
2217)
2218{
2219 u8 status;
2220 u8 cca_mode;
2221 struct ca8210_priv *priv = hw->priv;
2222
2223 cca_mode = cca->mode & 3;
2224 if (cca_mode == 3 && cca->opt == NL802154_CCA_OPT_ENERGY_CARRIER_OR) {
2225
2226 cca_mode = 0;
2227 }
2228 status = mlme_set_request_sync(
2229 PHY_CCA_MODE,
2230 0,
2231 1,
2232 &cca_mode,
2233 priv->spi
2234 );
2235 if (status) {
2236 dev_err(
2237 &priv->spi->dev,
2238 "error setting cca mode, MLME-SET.confirm status = %d",
2239 status
2240 );
2241 }
2242 return link_to_linux_err(status);
2243}
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255static int ca8210_set_cca_ed_level(struct ieee802154_hw *hw, s32 level)
2256{
2257 u8 status;
2258 u8 ed_threshold = (level / 100) * 2 + 256;
2259 struct ca8210_priv *priv = hw->priv;
2260
2261 status = hwme_set_request_sync(
2262 HWME_EDTHRESHOLD,
2263 1,
2264 &ed_threshold,
2265 priv->spi
2266 );
2267 if (status) {
2268 dev_err(
2269 &priv->spi->dev,
2270 "error setting ed threshold, HWME-SET.confirm status = %d",
2271 status
2272 );
2273 }
2274 return link_to_linux_err(status);
2275}
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286static int ca8210_set_csma_params(
2287 struct ieee802154_hw *hw,
2288 u8 min_be,
2289 u8 max_be,
2290 u8 retries
2291)
2292{
2293 u8 status;
2294 struct ca8210_priv *priv = hw->priv;
2295
2296 status = mlme_set_request_sync(MAC_MIN_BE, 0, 1, &min_be, priv->spi);
2297 if (status) {
2298 dev_err(
2299 &priv->spi->dev,
2300 "error setting min be, MLME-SET.confirm status = %d",
2301 status
2302 );
2303 return link_to_linux_err(status);
2304 }
2305 status = mlme_set_request_sync(MAC_MAX_BE, 0, 1, &max_be, priv->spi);
2306 if (status) {
2307 dev_err(
2308 &priv->spi->dev,
2309 "error setting max be, MLME-SET.confirm status = %d",
2310 status
2311 );
2312 return link_to_linux_err(status);
2313 }
2314 status = mlme_set_request_sync(
2315 MAC_MAX_CSMA_BACKOFFS,
2316 0,
2317 1,
2318 &retries,
2319 priv->spi
2320 );
2321 if (status) {
2322 dev_err(
2323 &priv->spi->dev,
2324 "error setting max csma backoffs, MLME-SET.confirm status = %d",
2325 status
2326 );
2327 }
2328 return link_to_linux_err(status);
2329}
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341static int ca8210_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
2342{
2343 u8 status;
2344 struct ca8210_priv *priv = hw->priv;
2345
2346 status = mlme_set_request_sync(
2347 MAC_MAX_FRAME_RETRIES,
2348 0,
2349 1,
2350 &retries,
2351 priv->spi
2352 );
2353 if (status) {
2354 dev_err(
2355 &priv->spi->dev,
2356 "error setting frame retries, MLME-SET.confirm status = %d",
2357 status
2358 );
2359 }
2360 return link_to_linux_err(status);
2361}
2362
2363static int ca8210_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
2364{
2365 u8 status;
2366 struct ca8210_priv *priv = hw->priv;
2367
2368 status = mlme_set_request_sync(
2369 MAC_PROMISCUOUS_MODE,
2370 0,
2371 1,
2372 (const void*)&on,
2373 priv->spi
2374 );
2375 if (status) {
2376 dev_err(
2377 &priv->spi->dev,
2378 "error setting promiscuous mode, MLME-SET.confirm status = %d",
2379 status
2380 );
2381 } else {
2382 priv->promiscuous = on;
2383 }
2384 return link_to_linux_err(status);
2385}
2386
2387static const struct ieee802154_ops ca8210_phy_ops = {
2388 .start = ca8210_start,
2389 .stop = ca8210_stop,
2390 .xmit_async = ca8210_xmit_async,
2391 .ed = ca8210_get_ed,
2392 .set_channel = ca8210_set_channel,
2393 .set_hw_addr_filt = ca8210_set_hw_addr_filt,
2394 .set_txpower = ca8210_set_tx_power,
2395 .set_cca_mode = ca8210_set_cca_mode,
2396 .set_cca_ed_level = ca8210_set_cca_ed_level,
2397 .set_csma_params = ca8210_set_csma_params,
2398 .set_frame_retries = ca8210_set_frame_retries,
2399 .set_promiscuous_mode = ca8210_set_promiscuous_mode
2400};
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411static int ca8210_test_int_open(struct inode *inodp, struct file *filp)
2412{
2413 struct ca8210_priv *priv = inodp->i_private;
2414
2415 filp->private_data = priv;
2416 return 0;
2417}
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427static int ca8210_test_check_upstream(u8 *buf, void *device_ref)
2428{
2429 int ret;
2430 u8 response[CA8210_SPI_BUF_SIZE];
2431
2432 if (buf[0] == SPI_MLME_SET_REQUEST) {
2433 ret = tdme_checkpibattribute(buf[2], buf[4], buf + 5);
2434 if (ret) {
2435 response[0] = SPI_MLME_SET_CONFIRM;
2436 response[1] = 3;
2437 response[2] = MAC_INVALID_PARAMETER;
2438 response[3] = buf[2];
2439 response[4] = buf[3];
2440 if (cascoda_api_upstream)
2441 cascoda_api_upstream(response, 5, device_ref);
2442 return ret;
2443 }
2444 }
2445 if (buf[0] == SPI_MLME_ASSOCIATE_REQUEST) {
2446 return tdme_channelinit(buf[2], device_ref);
2447 } else if (buf[0] == SPI_MLME_START_REQUEST) {
2448 return tdme_channelinit(buf[4], device_ref);
2449 } else if (
2450 (buf[0] == SPI_MLME_SET_REQUEST) &&
2451 (buf[2] == PHY_CURRENT_CHANNEL)
2452 ) {
2453 return tdme_channelinit(buf[5], device_ref);
2454 } else if (
2455 (buf[0] == SPI_TDME_SET_REQUEST) &&
2456 (buf[2] == TDME_CHANNEL)
2457 ) {
2458 return tdme_channelinit(buf[4], device_ref);
2459 } else if (
2460 (CA8210_MAC_WORKAROUNDS) &&
2461 (buf[0] == SPI_MLME_RESET_REQUEST) &&
2462 (buf[2] == 1)
2463 ) {
2464
2465 return tdme_setsfr_request_sync(
2466 0,
2467 CA8210_SFR_MACCON,
2468 0,
2469 device_ref
2470 );
2471 }
2472 return 0;
2473}
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485static ssize_t ca8210_test_int_user_write(
2486 struct file *filp,
2487 const char __user *in_buf,
2488 size_t len,
2489 loff_t *off
2490)
2491{
2492 int ret;
2493 struct ca8210_priv *priv = filp->private_data;
2494 u8 command[CA8210_SPI_BUF_SIZE];
2495
2496 if (len > CA8210_SPI_BUF_SIZE) {
2497 dev_warn(
2498 &priv->spi->dev,
2499 "userspace requested erroneously long write (%zu)\n",
2500 len
2501 );
2502 return -EMSGSIZE;
2503 }
2504
2505 ret = copy_from_user(command, in_buf, len);
2506 if (ret) {
2507 dev_err(
2508 &priv->spi->dev,
2509 "%d bytes could not be copied from userspace\n",
2510 ret
2511 );
2512 return -EIO;
2513 }
2514
2515 ret = ca8210_test_check_upstream(command, priv->spi);
2516 if (ret == 0) {
2517 ret = ca8210_spi_exchange(
2518 command,
2519 command[1] + 2,
2520 NULL,
2521 priv->spi
2522 );
2523 if (ret < 0) {
2524
2525 dev_err(
2526 &priv->spi->dev,
2527 "spi exchange failed\n"
2528 );
2529 return ret;
2530 }
2531 if (command[0] & SPI_SYN)
2532 priv->sync_down++;
2533 }
2534
2535 return len;
2536}
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552static ssize_t ca8210_test_int_user_read(
2553 struct file *filp,
2554 char __user *buf,
2555 size_t len,
2556 loff_t *offp
2557)
2558{
2559 int i, cmdlen;
2560 struct ca8210_priv *priv = filp->private_data;
2561 unsigned char *fifo_buffer;
2562 unsigned long bytes_not_copied;
2563
2564 if (filp->f_flags & O_NONBLOCK) {
2565
2566 if (kfifo_is_empty(&priv->test.up_fifo))
2567 return 0;
2568 } else {
2569
2570 wait_event_interruptible(
2571 priv->test.readq,
2572 !kfifo_is_empty(&priv->test.up_fifo)
2573 );
2574 }
2575
2576 if (kfifo_out(&priv->test.up_fifo, &fifo_buffer, 4) != 4) {
2577 dev_err(
2578 &priv->spi->dev,
2579 "test_interface: Wrong number of elements popped from upstream fifo\n"
2580 );
2581 return 0;
2582 }
2583 cmdlen = fifo_buffer[1];
2584 bytes_not_copied = cmdlen + 2;
2585
2586 bytes_not_copied = copy_to_user(buf, fifo_buffer, bytes_not_copied);
2587 if (bytes_not_copied > 0) {
2588 dev_err(
2589 &priv->spi->dev,
2590 "%lu bytes could not be copied to user space!\n",
2591 bytes_not_copied
2592 );
2593 }
2594
2595 dev_dbg(&priv->spi->dev, "test_interface: Cmd len = %d\n", cmdlen);
2596
2597 dev_dbg(&priv->spi->dev, "test_interface: Read\n");
2598 for (i = 0; i < cmdlen + 2; i++)
2599 dev_dbg(&priv->spi->dev, "%#03x\n", fifo_buffer[i]);
2600
2601 kfree(fifo_buffer);
2602
2603 return cmdlen + 2;
2604}
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615static long ca8210_test_int_ioctl(
2616 struct file *filp,
2617 unsigned int ioctl_num,
2618 unsigned long ioctl_param
2619)
2620{
2621 struct ca8210_priv *priv = filp->private_data;
2622
2623 switch (ioctl_num) {
2624 case CA8210_IOCTL_HARD_RESET:
2625 ca8210_reset_send(priv->spi, ioctl_param);
2626 break;
2627 default:
2628 break;
2629 }
2630 return 0;
2631}
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641static unsigned int ca8210_test_int_poll(
2642 struct file *filp,
2643 struct poll_table_struct *ptable
2644)
2645{
2646 unsigned int return_flags = 0;
2647 struct ca8210_priv *priv = filp->private_data;
2648
2649 poll_wait(filp, &priv->test.readq, ptable);
2650 if (!kfifo_is_empty(&priv->test.up_fifo))
2651 return_flags |= (POLLIN | POLLRDNORM);
2652 if (wait_event_interruptible(
2653 priv->test.readq,
2654 !kfifo_is_empty(&priv->test.up_fifo))) {
2655 return POLLERR;
2656 }
2657 return return_flags;
2658}
2659
2660static const struct file_operations test_int_fops = {
2661 .read = ca8210_test_int_user_read,
2662 .write = ca8210_test_int_user_write,
2663 .open = ca8210_test_int_open,
2664 .release = NULL,
2665 .unlocked_ioctl = ca8210_test_int_ioctl,
2666 .poll = ca8210_test_int_poll
2667};
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678static int ca8210_get_platform_data(
2679 struct spi_device *spi_device,
2680 struct ca8210_platform_data *pdata
2681)
2682{
2683 int ret = 0;
2684
2685 if (!spi_device->dev.of_node)
2686 return -EINVAL;
2687
2688 pdata->extclockenable = of_property_read_bool(
2689 spi_device->dev.of_node,
2690 "extclock-enable"
2691 );
2692 if (pdata->extclockenable) {
2693 ret = of_property_read_u32(
2694 spi_device->dev.of_node,
2695 "extclock-freq",
2696 &pdata->extclockfreq
2697 );
2698 if (ret < 0)
2699 return ret;
2700
2701 ret = of_property_read_u32(
2702 spi_device->dev.of_node,
2703 "extclock-gpio",
2704 &pdata->extclockgpio
2705 );
2706 }
2707
2708 return ret;
2709}
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723static int ca8210_config_extern_clk(
2724 struct ca8210_platform_data *pdata,
2725 struct spi_device *spi,
2726 bool on
2727)
2728{
2729 u8 clkparam[2];
2730
2731 if (on) {
2732 dev_info(&spi->dev, "Switching external clock on\n");
2733 switch (pdata->extclockfreq) {
2734 case SIXTEEN_MHZ:
2735 clkparam[0] = 1;
2736 break;
2737 case EIGHT_MHZ:
2738 clkparam[0] = 2;
2739 break;
2740 case FOUR_MHZ:
2741 clkparam[0] = 3;
2742 break;
2743 case TWO_MHZ:
2744 clkparam[0] = 4;
2745 break;
2746 case ONE_MHZ:
2747 clkparam[0] = 5;
2748 break;
2749 default:
2750 dev_crit(&spi->dev, "Invalid extclock-freq\n");
2751 return -EINVAL;
2752 }
2753 clkparam[1] = pdata->extclockgpio;
2754 } else {
2755 dev_info(&spi->dev, "Switching external clock off\n");
2756 clkparam[0] = 0;
2757 clkparam[1] = 0;
2758 }
2759 return link_to_linux_err(
2760 hwme_set_request_sync(HWME_SYSCLKOUT, 2, clkparam, spi)
2761 );
2762}
2763
2764
2765
2766
2767
2768
2769
2770static int ca8210_register_ext_clock(struct spi_device *spi)
2771{
2772 struct device_node *np = spi->dev.of_node;
2773 struct ca8210_priv *priv = spi_get_drvdata(spi);
2774 struct ca8210_platform_data *pdata = spi->dev.platform_data;
2775 int ret = 0;
2776
2777 if (!np)
2778 return -EFAULT;
2779
2780 priv->clk = clk_register_fixed_rate(
2781 &spi->dev,
2782 np->name,
2783 NULL,
2784 0,
2785 pdata->extclockfreq
2786 );
2787
2788 if (IS_ERR(priv->clk)) {
2789 dev_crit(&spi->dev, "Failed to register external clk\n");
2790 return PTR_ERR(priv->clk);
2791 }
2792 ret = of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
2793 if (ret) {
2794 clk_unregister(priv->clk);
2795 dev_crit(
2796 &spi->dev,
2797 "Failed to register external clock as clock provider\n"
2798 );
2799 } else {
2800 dev_info(&spi->dev, "External clock set as clock provider\n");
2801 }
2802
2803 return ret;
2804}
2805
2806
2807
2808
2809
2810
2811static void ca8210_unregister_ext_clock(struct spi_device *spi)
2812{
2813 struct ca8210_priv *priv = spi_get_drvdata(spi);
2814
2815 if (!priv->clk)
2816 return
2817
2818 of_clk_del_provider(spi->dev.of_node);
2819 clk_unregister(priv->clk);
2820 dev_info(&spi->dev, "External clock unregistered\n");
2821}
2822
2823
2824
2825
2826
2827
2828
2829static int ca8210_reset_init(struct spi_device *spi)
2830{
2831 int ret;
2832 struct ca8210_platform_data *pdata = spi->dev.platform_data;
2833
2834 pdata->gpio_reset = of_get_named_gpio(
2835 spi->dev.of_node,
2836 "reset-gpio",
2837 0
2838 );
2839
2840 ret = gpio_direction_output(pdata->gpio_reset, 1);
2841 if (ret < 0) {
2842 dev_crit(
2843 &spi->dev,
2844 "Reset GPIO %d did not set to output mode\n",
2845 pdata->gpio_reset
2846 );
2847 }
2848
2849 return ret;
2850}
2851
2852
2853
2854
2855
2856
2857
2858static int ca8210_interrupt_init(struct spi_device *spi)
2859{
2860 int ret;
2861 struct ca8210_platform_data *pdata = spi->dev.platform_data;
2862
2863 pdata->gpio_irq = of_get_named_gpio(
2864 spi->dev.of_node,
2865 "irq-gpio",
2866 0
2867 );
2868
2869 pdata->irq_id = gpio_to_irq(pdata->gpio_irq);
2870 if (pdata->irq_id < 0) {
2871 dev_crit(
2872 &spi->dev,
2873 "Could not get irq for gpio pin %d\n",
2874 pdata->gpio_irq
2875 );
2876 gpio_free(pdata->gpio_irq);
2877 return pdata->irq_id;
2878 }
2879
2880 ret = request_irq(
2881 pdata->irq_id,
2882 ca8210_interrupt_handler,
2883 IRQF_TRIGGER_FALLING,
2884 "ca8210-irq",
2885 spi_get_drvdata(spi)
2886 );
2887 if (ret) {
2888 dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
2889 gpio_unexport(pdata->gpio_irq);
2890 gpio_free(pdata->gpio_irq);
2891 }
2892
2893 return ret;
2894}
2895
2896
2897
2898
2899
2900
2901
2902static int ca8210_dev_com_init(struct ca8210_priv *priv)
2903{
2904 priv->mlme_workqueue = alloc_ordered_workqueue(
2905 "MLME work queue",
2906 WQ_UNBOUND
2907 );
2908 if (!priv->mlme_workqueue) {
2909 dev_crit(&priv->spi->dev, "alloc of mlme_workqueue failed!\n");
2910 return -ENOMEM;
2911 }
2912
2913 priv->irq_workqueue = alloc_ordered_workqueue(
2914 "ca8210 irq worker",
2915 WQ_UNBOUND
2916 );
2917 if (!priv->irq_workqueue) {
2918 dev_crit(&priv->spi->dev, "alloc of irq_workqueue failed!\n");
2919 return -ENOMEM;
2920 }
2921
2922 return 0;
2923}
2924
2925
2926
2927
2928
2929static void ca8210_dev_com_clear(struct ca8210_priv *priv)
2930{
2931 flush_workqueue(priv->mlme_workqueue);
2932 destroy_workqueue(priv->mlme_workqueue);
2933 flush_workqueue(priv->irq_workqueue);
2934 destroy_workqueue(priv->irq_workqueue);
2935}
2936
2937#define CA8210_MAX_TX_POWERS (9)
2938static const s32 ca8210_tx_powers[CA8210_MAX_TX_POWERS] = {
2939 800, 700, 600, 500, 400, 300, 200, 100, 0
2940};
2941
2942#define CA8210_MAX_ED_LEVELS (21)
2943static const s32 ca8210_ed_levels[CA8210_MAX_ED_LEVELS] = {
2944 -10300, -10250, -10200, -10150, -10100, -10050, -10000, -9950, -9900,
2945 -9850, -9800, -9750, -9700, -9650, -9600, -9550, -9500, -9450, -9400,
2946 -9350, -9300
2947};
2948
2949
2950
2951
2952
2953
2954static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
2955{
2956
2957 ca8210_hw->phy->supported.channels[0] = CA8210_VALID_CHANNELS;
2958 ca8210_hw->phy->supported.tx_powers_size = CA8210_MAX_TX_POWERS;
2959 ca8210_hw->phy->supported.tx_powers = ca8210_tx_powers;
2960 ca8210_hw->phy->supported.cca_ed_levels_size = CA8210_MAX_ED_LEVELS;
2961 ca8210_hw->phy->supported.cca_ed_levels = ca8210_ed_levels;
2962 ca8210_hw->phy->current_channel = 18;
2963 ca8210_hw->phy->current_page = 0;
2964 ca8210_hw->phy->transmit_power = 800;
2965 ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER;
2966 ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND;
2967 ca8210_hw->phy->cca_ed_level = -9800;
2968 ca8210_hw->phy->symbol_duration = 16;
2969 ca8210_hw->phy->lifs_period = 40;
2970 ca8210_hw->phy->sifs_period = 12;
2971 ca8210_hw->flags =
2972 IEEE802154_HW_AFILT |
2973 IEEE802154_HW_OMIT_CKSUM |
2974 IEEE802154_HW_FRAME_RETRIES |
2975 IEEE802154_HW_PROMISCUOUS |
2976 IEEE802154_HW_CSMA_PARAMS;
2977 ca8210_hw->phy->flags =
2978 WPAN_PHY_FLAG_TXPOWER |
2979 WPAN_PHY_FLAG_CCA_ED_LEVEL |
2980 WPAN_PHY_FLAG_CCA_MODE;
2981}
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994static int ca8210_test_interface_init(struct ca8210_priv *priv)
2995{
2996 struct ca8210_test *test = &priv->test;
2997 char node_name[32];
2998
2999 snprintf(
3000 node_name,
3001 sizeof(node_name),
3002 "ca8210@%d_%d",
3003 priv->spi->master->bus_num,
3004 priv->spi->chip_select
3005 );
3006
3007 test->ca8210_dfs_spi_int = debugfs_create_file(
3008 node_name,
3009 0600,
3010 NULL,
3011 priv,
3012 &test_int_fops
3013 );
3014 if (IS_ERR(test->ca8210_dfs_spi_int)) {
3015 dev_err(
3016 &priv->spi->dev,
3017 "Error %ld when creating debugfs node\n",
3018 PTR_ERR(test->ca8210_dfs_spi_int)
3019 );
3020 return PTR_ERR(test->ca8210_dfs_spi_int);
3021 }
3022 debugfs_create_symlink("ca8210", NULL, node_name);
3023 init_waitqueue_head(&test->readq);
3024 return kfifo_alloc(
3025 &test->up_fifo,
3026 CA8210_TEST_INT_FIFO_SIZE,
3027 GFP_KERNEL
3028 );
3029}
3030
3031
3032
3033
3034
3035static void ca8210_test_interface_clear(struct ca8210_priv *priv)
3036{
3037 struct ca8210_test *test = &priv->test;
3038
3039 if (!IS_ERR(test->ca8210_dfs_spi_int))
3040 debugfs_remove(test->ca8210_dfs_spi_int);
3041 kfifo_free(&test->up_fifo);
3042 dev_info(&priv->spi->dev, "Test interface removed\n");
3043}
3044
3045
3046
3047
3048
3049
3050
3051static int ca8210_remove(struct spi_device *spi_device)
3052{
3053 struct ca8210_priv *priv;
3054 struct ca8210_platform_data *pdata;
3055
3056 dev_info(&spi_device->dev, "Removing ca8210\n");
3057
3058 pdata = spi_device->dev.platform_data;
3059 if (pdata) {
3060 if (pdata->extclockenable) {
3061 ca8210_unregister_ext_clock(spi_device);
3062 ca8210_config_extern_clk(pdata, spi_device, 0);
3063 }
3064 free_irq(pdata->irq_id, spi_device->dev.driver_data);
3065 kfree(pdata);
3066 spi_device->dev.platform_data = NULL;
3067 }
3068
3069 priv = spi_get_drvdata(spi_device);
3070 if (priv) {
3071 dev_info(
3072 &spi_device->dev,
3073 "sync_down = %d, sync_up = %d\n",
3074 priv->sync_down,
3075 priv->sync_up
3076 );
3077 ca8210_dev_com_clear(spi_device->dev.driver_data);
3078 if (priv->hw) {
3079 if (priv->hw_registered)
3080 ieee802154_unregister_hw(priv->hw);
3081 ieee802154_free_hw(priv->hw);
3082 priv->hw = NULL;
3083 dev_info(
3084 &spi_device->dev,
3085 "Unregistered & freed ieee802154_hw.\n"
3086 );
3087 }
3088 if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS))
3089 ca8210_test_interface_clear(priv);
3090 }
3091
3092 return 0;
3093}
3094
3095
3096
3097
3098
3099
3100
3101static int ca8210_probe(struct spi_device *spi_device)
3102{
3103 struct ca8210_priv *priv;
3104 struct ieee802154_hw *hw;
3105 struct ca8210_platform_data *pdata;
3106 int ret;
3107
3108 dev_info(&spi_device->dev, "Inserting ca8210\n");
3109
3110
3111 hw = ieee802154_alloc_hw(sizeof(struct ca8210_priv), &ca8210_phy_ops);
3112 if (!hw) {
3113 dev_crit(&spi_device->dev, "ieee802154_alloc_hw failed\n");
3114 ret = -ENOMEM;
3115 goto error;
3116 }
3117
3118 priv = hw->priv;
3119 priv->hw = hw;
3120 priv->spi = spi_device;
3121 hw->parent = &spi_device->dev;
3122 spin_lock_init(&priv->lock);
3123 priv->async_tx_pending = false;
3124 priv->hw_registered = false;
3125 priv->sync_up = 0;
3126 priv->sync_down = 0;
3127 priv->promiscuous = false;
3128 priv->retries = 0;
3129 init_completion(&priv->ca8210_is_awake);
3130 init_completion(&priv->spi_transfer_complete);
3131 init_completion(&priv->sync_exchange_complete);
3132 spi_set_drvdata(priv->spi, priv);
3133 if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) {
3134 cascoda_api_upstream = ca8210_test_int_driver_write;
3135 ca8210_test_interface_init(priv);
3136 } else {
3137 cascoda_api_upstream = NULL;
3138 }
3139 ca8210_hw_setup(hw);
3140 ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
3141
3142 pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
3143 if (!pdata) {
3144 ret = -ENOMEM;
3145 goto error;
3146 }
3147
3148 ret = ca8210_get_platform_data(priv->spi, pdata);
3149 if (ret) {
3150 dev_crit(&spi_device->dev, "ca8210_get_platform_data failed\n");
3151 goto error;
3152 }
3153 priv->spi->dev.platform_data = pdata;
3154
3155 ret = ca8210_dev_com_init(priv);
3156 if (ret) {
3157 dev_crit(&spi_device->dev, "ca8210_dev_com_init failed\n");
3158 goto error;
3159 }
3160 ret = ca8210_reset_init(priv->spi);
3161 if (ret) {
3162 dev_crit(&spi_device->dev, "ca8210_reset_init failed\n");
3163 goto error;
3164 }
3165
3166 ret = ca8210_interrupt_init(priv->spi);
3167 if (ret) {
3168 dev_crit(&spi_device->dev, "ca8210_interrupt_init failed\n");
3169 goto error;
3170 }
3171
3172 msleep(100);
3173
3174 ca8210_reset_send(priv->spi, 1);
3175
3176 ret = tdme_chipinit(priv->spi);
3177 if (ret) {
3178 dev_crit(&spi_device->dev, "tdme_chipinit failed\n");
3179 goto error;
3180 }
3181
3182 if (pdata->extclockenable) {
3183 ret = ca8210_config_extern_clk(pdata, priv->spi, 1);
3184 if (ret) {
3185 dev_crit(
3186 &spi_device->dev,
3187 "ca8210_config_extern_clk failed\n"
3188 );
3189 goto error;
3190 }
3191 ret = ca8210_register_ext_clock(priv->spi);
3192 if (ret) {
3193 dev_crit(
3194 &spi_device->dev,
3195 "ca8210_register_ext_clock failed\n"
3196 );
3197 goto error;
3198 }
3199 }
3200
3201 ret = ieee802154_register_hw(hw);
3202 if (ret) {
3203 dev_crit(&spi_device->dev, "ieee802154_register_hw failed\n");
3204 goto error;
3205 }
3206 priv->hw_registered = true;
3207
3208 return 0;
3209error:
3210 msleep(100);
3211 ca8210_remove(spi_device);
3212 return link_to_linux_err(ret);
3213}
3214
3215static const struct of_device_id ca8210_of_ids[] = {
3216 {.compatible = "cascoda,ca8210", },
3217 {},
3218};
3219MODULE_DEVICE_TABLE(of, ca8210_of_ids);
3220
3221static struct spi_driver ca8210_spi_driver = {
3222 .driver = {
3223 .name = DRIVER_NAME,
3224 .owner = THIS_MODULE,
3225 .of_match_table = of_match_ptr(ca8210_of_ids),
3226 },
3227 .probe = ca8210_probe,
3228 .remove = ca8210_remove
3229};
3230
3231module_spi_driver(ca8210_spi_driver);
3232
3233MODULE_AUTHOR("Harry Morris <h.morris@cascoda.com>");
3234MODULE_DESCRIPTION("CA-8210 SoftMAC driver");
3235MODULE_LICENSE("Dual BSD/GPL");
3236MODULE_VERSION("1.0");
3237