1 /* ieee802154_kw41z.c - NXP KW41Z driver */
2 
3 /*
4  * Copyright (c) 2017 Linaro Limited
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define DT_DRV_COMPAT nxp_kw41z_ieee802154
10 
11 #define LOG_MODULE_NAME ieee802154_kw41z
12 #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/device.h>
19 #include <zephyr/init.h>
20 #include <zephyr/irq.h>
21 #include <zephyr/net/ieee802154_radio.h>
22 #include <zephyr/net/net_if.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/sys/byteorder.h>
25 #include <zephyr/random/random.h>
26 
27 #include "fsl_xcvr.h"
28 
29 #if defined(CONFIG_NET_L2_OPENTHREAD)
30 #include <zephyr/net/openthread.h>
31 #endif
32 
33 
34 /*
35  * For non-invasive tracing of IRQ events. Sometimes the print logs
36  * will shift the timings around so this trace buffer can be used to
37  * post inspect conditions to see what sequence of events occurred.
38  */
39 
40 #define KW41_DBG_TRACE_WTRM	0
41 #define KW41_DBG_TRACE_RX	1
42 #define KW41_DBG_TRACE_TX	2
43 #define KW41_DBG_TRACE_CCA	3
44 #define KW41_DBG_TRACE_TMR3	0xFF
45 
46 #if defined(CONFIG_KW41_DBG_TRACE)
47 
48 #define KW41_DBG_TRACE_SIZE 30
49 
50 struct kw41_dbg_trace {
51 	uint8_t	type;
52 	uint32_t	time;
53 	uint32_t	irqsts;
54 	uint32_t	phy_ctrl;
55 	uint32_t	seq_state;
56 };
57 
58 struct kw41_dbg_trace kw41_dbg[KW41_DBG_TRACE_SIZE];
59 int kw41_dbg_idx;
60 
61 #define KW_DBG_TRACE(_type, _irqsts, _phy_ctrl, _seq_state) \
62 	do { \
63 		kw41_dbg[kw41_dbg_idx].type = (_type); \
64 		kw41_dbg[kw41_dbg_idx].time = \
65 			ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT; \
66 		kw41_dbg[kw41_dbg_idx].irqsts = (_irqsts); \
67 		kw41_dbg[kw41_dbg_idx].phy_ctrl = (_phy_ctrl); \
68 		kw41_dbg[kw41_dbg_idx].seq_state = (_seq_state); \
69 		if (++kw41_dbg_idx == KW41_DBG_TRACE_SIZE) { \
70 			kw41_dbg_idx = 0; \
71 		} \
72 	} while (false)
73 
74 #else
75 
76 #define KW_DBG_TRACE(_type, _irqsts, _phy_ctrl, _seq_state)
77 
78 #endif
79 
80 #define KW41Z_DEFAULT_CHANNEL		26
81 #define KW41Z_CCA_TIME			8
82 #define KW41Z_SHR_PHY_TIME		12
83 #define KW41Z_PER_BYTE_TIME		2
84 #define KW41Z_ACK_WAIT_TIME		54
85 #define KW41Z_PRE_RX_WAIT_TIME		1
86 #define KW40Z_POST_SEQ_WAIT_TIME	1
87 
88 #define RADIO_0_IRQ_PRIO		0x0
89 #define KW41Z_FCS_LENGTH		2
90 #define KW41Z_PSDU_LENGTH		125
91 #define KW41Z_OUTPUT_POWER_MAX		4
92 #define KW41Z_OUTPUT_POWER_MIN		(-31)
93 
94 #define IEEE802154_ACK_LENGTH		5
95 
96 #define BM_ZLL_IRQSTS_TMRxMSK (ZLL_IRQSTS_TMR1MSK_MASK | \
97 				ZLL_IRQSTS_TMR2MSK_MASK | \
98 				ZLL_IRQSTS_TMR3MSK_MASK | \
99 				ZLL_IRQSTS_TMR4MSK_MASK)
100 
101 /*
102  * Clear channel assessment types. Note that there is an extra one when
103  * bit 26 is included for "No CCA before transmit" if we are handling
104  * ACK frames but we will let the hardware handle that automatically.
105  */
106 enum {
107 	KW41Z_CCA_ED,       /* Energy detect */
108 	KW41Z_CCA_MODE1,    /* Energy above threshold   */
109 	KW41Z_CCA_MODE2,    /* Carrier sense only       */
110 	KW41Z_CCA_MODE3     /* Mode 1 + Mode 2          */
111 };
112 
113 /*
114  * KW41Z has a sequencer that can run in any of the following states.
115  */
116 enum {
117 	KW41Z_STATE_IDLE,
118 	KW41Z_STATE_RX,
119 	KW41Z_STATE_TX,
120 	KW41Z_STATE_CCA,
121 	KW41Z_STATE_TXRX,
122 	KW41Z_STATE_CCCA
123 };
124 
125 /* Lookup table for PA_PWR register */
126 static const uint8_t pa_pwr_lt[] = {
127 	1,                   /* -31.1 dBm: -31 */
128 	2, 2, 2, 2, 2, 2, 2, /* -25.0 dBm: -30, -29, -28, -27, -26, -25 */
129 	4, 4, 4, 4, 4,       /* -19.0 dBm: -24, -23, -22, -21, -20, -19 */
130 	6, 6, 6,             /* -15.6 dBm: -18, -17, -16 */
131 	8, 8,                /* -13.1 dBm: -15, -14 */
132 	10, 10,              /* -11.2 dBm: -13, -12 */
133 	12, 12,              /* - 9.6 dBm: -11, -10 */
134 	14,                  /* - 8.3 dBm: -9 */
135 	16,                  /* - 7.2 dBm: -8 */
136 	18,                  /* - 6.2 dBm: -7 */
137 	20,                  /* - 5.3 dBm: -6 */
138 	22,                  /* - 4.5 dBm: -5 */
139 	24,                  /* - 3.8 dBm: -4 */
140 	28,                  /* - 2.5 dBm: -3 */
141 	30,                  /* - 1.9 dBm: -2 */
142 	34,                  /* - 1.0 dBm: -1 */
143 	40,                  /* + 0.3 dBm:  0 */
144 	44,                  /* + 1.1 dBm: +1 */
145 	50,                  /* + 2.1 dBm: +2 */
146 	58,                  /* + 3.1 dBm: +3 */
147 	62                   /* + 3.5 dBm: +4 */
148 };
149 
150 struct kw41z_context {
151 	struct net_if *iface;
152 	uint8_t mac_addr[8];
153 
154 	struct k_sem seq_sync;
155 	atomic_t seq_retval;
156 
157 	uint32_t rx_warmup_time;
158 	uint32_t tx_warmup_time;
159 
160 	bool frame_pending; /* FP bit state from the most recent ACK frame. */
161 };
162 
163 static struct kw41z_context kw41z_context_data;
164 
kw41z_get_instant_state(void)165 static inline uint8_t kw41z_get_instant_state(void)
166 {
167 	return (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) >>
168 	       ZLL_SEQ_STATE_SEQ_STATE_SHIFT;
169 }
170 
kw41z_get_seq_state(void)171 static inline uint8_t kw41z_get_seq_state(void)
172 {
173 	return (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) >>
174 	       ZLL_PHY_CTRL_XCVSEQ_SHIFT;
175 }
176 
kw41z_set_seq_state(uint8_t state)177 static inline void kw41z_set_seq_state(uint8_t state)
178 {
179 #if CONFIG_SOC_MKW40Z4
180 	/*
181 	 * KW40Z seems to require a small delay when switching to IDLE state
182 	 * after a programmed sequence is complete.
183 	 */
184 	if (state == KW41Z_STATE_IDLE) {
185 		k_busy_wait(KW40Z_POST_SEQ_WAIT_TIME);
186 	}
187 #endif
188 
189 	ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_XCVSEQ_MASK) |
190 			ZLL_PHY_CTRL_XCVSEQ(state);
191 }
192 
kw41z_wait_for_idle(void)193 static inline void kw41z_wait_for_idle(void)
194 {
195 	uint8_t state = kw41z_get_instant_state();
196 
197 	while (state != KW41Z_STATE_IDLE) {
198 		state = kw41z_get_instant_state();
199 	}
200 
201 	if (state != KW41Z_STATE_IDLE) {
202 		LOG_ERR("Error waiting for idle state");
203 	}
204 }
205 
kw41z_phy_abort(void)206 static void kw41z_phy_abort(void)
207 {
208 	unsigned int key;
209 
210 	key = irq_lock();
211 
212 	/* Mask SEQ interrupt */
213 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK;
214 	/* Disable timer trigger (for scheduled XCVSEQ) */
215 	if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_TMRTRIGEN_MASK) {
216 		ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMRTRIGEN_MASK;
217 		/* give the FSM enough time to start if it was triggered */
218 		while ((XCVR_MISC->XCVR_CTRL &
219 			XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) == 0) {
220 		}
221 	}
222 
223 	/* If XCVR is not idle, abort current SEQ */
224 	if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) {
225 		ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
226 		/* wait for Sequence Idle (if not already) */
227 
228 		while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {
229 		}
230 	}
231 
232 	/* Stop timers */
233 	ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR1CMP_EN_MASK |
234 			ZLL_PHY_CTRL_TMR2CMP_EN_MASK |
235 			ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
236 			ZLL_PHY_CTRL_TC3TMOUT_MASK);
237 
238 	/*
239 	 * Clear all IRQ bits to avoid unexpected interrupts.
240 	 *
241 	 * For Coverity, this is a pointer to a register bank and the IRQSTS
242 	 * register bits get cleared when a 1 is written to them so doing a
243 	 * reg=reg may generate a warning but it is needed to clear the bits.
244 	 */
245 	ZLL->IRQSTS = ZLL->IRQSTS;
246 
247 	irq_unlock(key);
248 }
249 
kw41z_isr_timeout_cleanup(void)250 static void kw41z_isr_timeout_cleanup(void)
251 {
252 	uint32_t irqsts;
253 
254 	/*
255 	 * Set the PHY sequencer back to IDLE and disable TMR3 comparator
256 	 * and timeout
257 	 */
258 	ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
259 			ZLL_PHY_CTRL_TC3TMOUT_MASK   |
260 			ZLL_PHY_CTRL_XCVSEQ_MASK);
261 
262 	/* Mask SEQ, RX, TX and CCA interrupts */
263 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
264 			ZLL_PHY_CTRL_RXMSK_MASK  |
265 			ZLL_PHY_CTRL_TXMSK_MASK  |
266 			ZLL_PHY_CTRL_SEQMSK_MASK;
267 
268 	while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {
269 	}
270 
271 	irqsts = ZLL->IRQSTS;
272 	/* Mask TMR3 interrupt */
273 	irqsts |= ZLL_IRQSTS_TMR3MSK_MASK;
274 
275 	ZLL->IRQSTS = irqsts;
276 }
277 
kw41z_isr_seq_cleanup(void)278 static void kw41z_isr_seq_cleanup(void)
279 {
280 	uint32_t irqsts;
281 
282 	/* Set the PHY sequencer back to IDLE */
283 	ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
284 	/* Mask SEQ, RX, TX and CCA interrupts */
285 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
286 			ZLL_PHY_CTRL_RXMSK_MASK  |
287 			ZLL_PHY_CTRL_TXMSK_MASK  |
288 			ZLL_PHY_CTRL_SEQMSK_MASK;
289 
290 	while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {
291 	}
292 
293 	irqsts = ZLL->IRQSTS;
294 	/* Mask TMR3 interrupt */
295 	irqsts |= ZLL_IRQSTS_TMR3MSK_MASK;
296 
297 	/* Clear transceiver interrupts except TMRxIRQ */
298 	irqsts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK |
299 		ZLL_IRQSTS_TMR2IRQ_MASK |
300 		ZLL_IRQSTS_TMR3IRQ_MASK |
301 		ZLL_IRQSTS_TMR4IRQ_MASK);
302 	ZLL->IRQSTS = irqsts;
303 }
304 
kw41z_enable_seq_irq(void)305 static inline void kw41z_enable_seq_irq(void)
306 {
307 	ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
308 }
309 
kw41z_disable_seq_irq(void)310 static inline void kw41z_disable_seq_irq(void)
311 {
312 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK;
313 }
314 
315 /*
316  * Set the T3CMP timer comparator. The 'timeout' value is an offset from
317  * now.
318  */
kw41z_tmr3_set_timeout(uint32_t timeout)319 static void kw41z_tmr3_set_timeout(uint32_t timeout)
320 {
321 	uint32_t irqsts;
322 
323 	/* Add in the current time so that we can get the comparator to
324 	 * match appropriately to our offset time.
325 	 */
326 	timeout += ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT;
327 
328 	/* disable TMR3 compare */
329 	ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
330 	ZLL->T3CMP = timeout & ZLL_T3CMP_T3CMP_MASK;
331 
332 	/* acknowledge TMR3 IRQ */
333 	irqsts  = ZLL->IRQSTS & BM_ZLL_IRQSTS_TMRxMSK;
334 	irqsts |= ZLL_IRQSTS_TMR3IRQ_MASK;
335 	ZLL->IRQSTS = irqsts;
336 	/* enable TMR3 compare and autosequence stop by TC3 match */
337 	ZLL->PHY_CTRL |=
338 		(ZLL_PHY_CTRL_TMR3CMP_EN_MASK | ZLL_PHY_CTRL_TC3TMOUT_MASK);
339 }
340 
kw41z_tmr3_disable(void)341 static void kw41z_tmr3_disable(void)
342 {
343 	uint32_t irqsts;
344 
345 	/*
346 	 * disable TMR3 compare and disable autosequence stop by TC3
347 	 * match
348 	 */
349 	ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
350 			ZLL_PHY_CTRL_TC3TMOUT_MASK);
351 	/* mask TMR3 interrupt (do not change other IRQ status) */
352 	irqsts  = ZLL->IRQSTS & BM_ZLL_IRQSTS_TMRxMSK;
353 	irqsts |= ZLL_IRQSTS_TMR3MSK_MASK;
354 	/* acknowledge TMR3 IRQ */
355 	irqsts |= ZLL_IRQSTS_TMR3IRQ_MASK;
356 
357 	ZLL->IRQSTS = irqsts;
358 }
359 
kw41z_get_capabilities(const struct device * dev)360 static enum ieee802154_hw_caps kw41z_get_capabilities(const struct device *dev)
361 {
362 	return IEEE802154_HW_FCS | IEEE802154_HW_FILTER |
363 	       IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK;
364 }
365 
kw41z_cca(const struct device * dev)366 static int kw41z_cca(const struct device *dev)
367 {
368 	struct kw41z_context *kw41z = dev->data;
369 
370 	kw41z_phy_abort();
371 
372 	k_sem_init(&kw41z->seq_sync, 0, 1);
373 
374 	kw41z_enable_seq_irq();
375 	ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_CCATYPE_MASK) |
376 			ZLL_PHY_CTRL_CCATYPE(KW41Z_CCA_MODE1);
377 
378 	kw41z_set_seq_state(KW41Z_STATE_CCA);
379 
380 	k_sem_take(&kw41z->seq_sync, K_FOREVER);
381 
382 	return kw41z->seq_retval;
383 }
384 
kw41z_set_channel(const struct device * dev,uint16_t channel)385 static int kw41z_set_channel(const struct device *dev, uint16_t channel)
386 {
387 	if (channel < 11 || channel > 26) {
388 		return channel < 11 ? -ENOTSUP : -EINVAL;
389 	}
390 
391 	ZLL->CHANNEL_NUM0 = channel;
392 	return 0;
393 }
394 
kw41z_set_pan_id(const struct device * dev,uint16_t pan_id)395 static int kw41z_set_pan_id(const struct device *dev, uint16_t pan_id)
396 {
397 	ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0 &
398 			       ~ZLL_MACSHORTADDRS0_MACPANID0_MASK) |
399 			      ZLL_MACSHORTADDRS0_MACPANID0(pan_id);
400 	return 0;
401 }
402 
kw41z_set_short_addr(const struct device * dev,uint16_t short_addr)403 static int kw41z_set_short_addr(const struct device *dev, uint16_t short_addr)
404 {
405 	ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0 &
406 			       ~ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK) |
407 			      ZLL_MACSHORTADDRS0_MACSHORTADDRS0(short_addr);
408 	return 0;
409 }
410 
kw41z_set_ieee_addr(const struct device * dev,const uint8_t * ieee_addr)411 static int kw41z_set_ieee_addr(const struct device *dev,
412 			       const uint8_t *ieee_addr)
413 {
414 	uint32_t val;
415 
416 	memcpy(&val, ieee_addr, sizeof(val));
417 	ZLL->MACLONGADDRS0_LSB = val;
418 
419 	memcpy(&val, ieee_addr + sizeof(val), sizeof(val));
420 	ZLL->MACLONGADDRS0_MSB = val;
421 
422 	return 0;
423 }
424 
kw41z_filter(const struct device * dev,bool set,enum ieee802154_filter_type type,const struct ieee802154_filter * filter)425 static int kw41z_filter(const struct device *dev,
426 			bool set,
427 			enum ieee802154_filter_type type,
428 			const struct ieee802154_filter *filter)
429 {
430 	LOG_DBG("Applying filter %u", type);
431 
432 	if (!set) {
433 		return -ENOTSUP;
434 	}
435 
436 	if (type == IEEE802154_FILTER_TYPE_IEEE_ADDR) {
437 		return kw41z_set_ieee_addr(dev, filter->ieee_addr);
438 	} else if (type == IEEE802154_FILTER_TYPE_SHORT_ADDR) {
439 		return kw41z_set_short_addr(dev, filter->short_addr);
440 	} else if (type == IEEE802154_FILTER_TYPE_PAN_ID) {
441 		return kw41z_set_pan_id(dev, filter->pan_id);
442 	}
443 
444 	return -ENOTSUP;
445 }
446 
kw41z_set_txpower(const struct device * dev,int16_t dbm)447 static int kw41z_set_txpower(const struct device *dev, int16_t dbm)
448 {
449 	if (dbm < KW41Z_OUTPUT_POWER_MIN) {
450 		LOG_INF("TX-power %d dBm below min of %d dBm, using %d dBm",
451 			    dbm,
452 			    KW41Z_OUTPUT_POWER_MIN,
453 			    KW41Z_OUTPUT_POWER_MIN);
454 		dbm = KW41Z_OUTPUT_POWER_MIN;
455 	} else if (dbm > KW41Z_OUTPUT_POWER_MAX) {
456 		LOG_INF("TX-power %d dBm above max of %d dBm, using %d dBm",
457 			    dbm,
458 			    KW41Z_OUTPUT_POWER_MAX,
459 			    KW41Z_OUTPUT_POWER_MAX);
460 		dbm = KW41Z_OUTPUT_POWER_MAX;
461 	}
462 
463 	ZLL->PA_PWR = pa_pwr_lt[dbm - KW41Z_OUTPUT_POWER_MIN];
464 
465 	return 0;
466 }
467 
kw41z_start(const struct device * dev)468 static int kw41z_start(const struct device *dev)
469 {
470 	irq_enable(Radio_1_IRQn);
471 
472 	kw41z_set_seq_state(KW41Z_STATE_RX);
473 	kw41z_enable_seq_irq();
474 
475 	return 0;
476 }
477 
kw41z_stop(const struct device * dev)478 static int kw41z_stop(const struct device *dev)
479 {
480 	irq_disable(Radio_1_IRQn);
481 
482 	kw41z_disable_seq_irq();
483 	kw41z_set_seq_state(KW41Z_STATE_IDLE);
484 
485 	return 0;
486 }
487 
kw41z_convert_lqi(uint8_t hw_lqi)488 static uint8_t kw41z_convert_lqi(uint8_t hw_lqi)
489 {
490 	if (hw_lqi >= 220U) {
491 		return 255;
492 	} else {
493 		return (hw_lqi * 51U) / 44;
494 	}
495 }
496 
kw41z_rx(struct kw41z_context * kw41z,uint8_t len)497 static inline void kw41z_rx(struct kw41z_context *kw41z, uint8_t len)
498 {
499 	struct net_pkt *pkt = NULL;
500 	struct net_buf *buf = NULL;
501 	uint8_t pkt_len, hw_lqi;
502 	int rslt;
503 
504 	LOG_DBG("ENTRY: len: %d", len);
505 
506 #if defined(CONFIG_NET_L2_OPENTHREAD)
507 	/*
508 	 * OpenThread stack expects a receive frame to include the FCS
509 	 */
510 	pkt_len = len;
511 #else
512 	pkt_len = len - KW41Z_FCS_LENGTH;
513 #endif
514 
515 	pkt = net_pkt_rx_alloc_with_buffer(kw41z->iface, pkt_len,
516 					   AF_UNSPEC, 0, K_NO_WAIT);
517 	if (!pkt) {
518 		LOG_ERR("No buf available");
519 		goto out;
520 	}
521 
522 	buf = pkt->buffer;
523 
524 #if CONFIG_SOC_MKW41Z4
525 	/* PKT_BUFFER_RX needs to be accessed aligned to 16 bits */
526 	for (uint16_t reg_val = 0, i = 0; i < pkt_len; i++) {
527 		if (i % 2 == 0U) {
528 			reg_val = ZLL->PKT_BUFFER_RX[i/2U];
529 			buf->data[i] = reg_val & 0xFF;
530 		} else {
531 			buf->data[i] = reg_val >> 8;
532 		}
533 	}
534 #else /* CONFIG_SOC_MKW40Z4 */
535 	/* PKT_BUFFER needs to be accessed aligned to 32 bits */
536 	for (uint32_t reg_val = 0, i = 0; i < pkt_len; i++) {
537 		switch (i % 4) {
538 		case 0:
539 			reg_val = ZLL->PKT_BUFFER[i/4U];
540 			buf->data[i] = reg_val & 0xFF;
541 			break;
542 		case 1:
543 			buf->data[i] = (reg_val >> 8) & 0xFF;
544 			break;
545 		case 2:
546 			buf->data[i] = (reg_val >> 16) & 0xFF;
547 			break;
548 		default:
549 			buf->data[i] = reg_val >> 24;
550 		}
551 	}
552 #endif
553 
554 	net_buf_add(buf, pkt_len);
555 
556 	hw_lqi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >>
557 		 ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT;
558 	net_pkt_set_ieee802154_lqi(pkt, kw41z_convert_lqi(hw_lqi));
559 	/* ToDo: get the rssi as well and use net_pkt_set_ieee802154_rssi() */
560 
561 	rslt = net_recv_data(kw41z->iface, pkt);
562 	if (rslt < 0) {
563 		LOG_ERR("RCV Packet dropped by NET stack: %d", rslt);
564 		goto out;
565 	}
566 
567 	return;
568 out:
569 	if (pkt) {
570 		net_pkt_unref(pkt);
571 	}
572 }
573 
574 #define ACK_FRAME_LEN 3
575 #define ACK_FRAME_TYPE (2 << 0)
576 #define ACK_FRAME_PENDING_BIT (1 << 4)
577 
handle_ack(struct kw41z_context * kw41z,uint8_t seq_number)578 static void handle_ack(struct kw41z_context *kw41z, uint8_t seq_number)
579 {
580 	struct net_pkt *ack_pkt;
581 	uint8_t ack_psdu[ACK_FRAME_LEN];
582 
583 	ack_pkt = net_pkt_rx_alloc_with_buffer(kw41z->iface, ACK_FRAME_LEN,
584 					       AF_UNSPEC, 0, K_NO_WAIT);
585 	if (!ack_pkt) {
586 		LOG_ERR("No free packet available.");
587 		return;
588 	}
589 
590 	/* Re-create ACK frame. */
591 	ack_psdu[0] = kw41z_context_data.frame_pending ?
592 		      ACK_FRAME_TYPE | ACK_FRAME_PENDING_BIT : ACK_FRAME_TYPE;
593 	ack_psdu[1] = 0;
594 	ack_psdu[2] = seq_number;
595 
596 	if (net_pkt_write(ack_pkt, ack_psdu, sizeof(ack_psdu)) < 0) {
597 		LOG_ERR("Failed to write to a packet.");
598 		goto out;
599 	}
600 
601 	/* Use some fake values for LQI and RSSI. */
602 	(void)net_pkt_set_ieee802154_lqi(ack_pkt, 80);
603 	(void)net_pkt_set_ieee802154_rssi_dbm(ack_pkt, -40);
604 
605 	net_pkt_cursor_init(ack_pkt);
606 
607 	if (ieee802154_handle_ack(kw41z->iface, ack_pkt) != NET_OK) {
608 		LOG_INF("ACK packet not handled - releasing.");
609 	}
610 
611 out:
612 	net_pkt_unref(ack_pkt);
613 }
614 
kw41z_tx(const struct device * dev,enum ieee802154_tx_mode mode,struct net_pkt * pkt,struct net_buf * frag)615 static int kw41z_tx(const struct device *dev, enum ieee802154_tx_mode mode,
616 		    struct net_pkt *pkt, struct net_buf *frag)
617 {
618 	struct kw41z_context *kw41z = dev->data;
619 	uint8_t payload_len = frag->len;
620 	uint32_t tx_timeout;
621 	uint8_t xcvseq;
622 	unsigned int key;
623 
624 	if (mode != IEEE802154_TX_MODE_DIRECT) {
625 		NET_ERR("TX mode %d not supported", mode);
626 		return -ENOTSUP;
627 	}
628 
629 	/*
630 	 * The transmit requests are preceded by the CCA request. On
631 	 * completion of the CCA the sequencer should be in the IDLE
632 	 * state.
633 	 */
634 	if (kw41z_get_seq_state() != KW41Z_STATE_IDLE) {
635 		LOG_WRN("Can't initiate new SEQ state");
636 		return -EBUSY;
637 	}
638 
639 	if (payload_len > KW41Z_PSDU_LENGTH) {
640 		LOG_ERR("Payload too long");
641 		return 0;
642 	}
643 
644 	key = irq_lock();
645 
646 	/* Disable the 802.15.4 radio IRQ */
647 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TRCV_MSK_MASK;
648 	kw41z_disable_seq_irq();
649 
650 #if CONFIG_SOC_MKW41Z4
651 	((uint8_t *)ZLL->PKT_BUFFER_TX)[0] = payload_len + KW41Z_FCS_LENGTH;
652 	memcpy(((uint8_t *)ZLL->PKT_BUFFER_TX) + 1,
653 		(void *)frag->data, payload_len);
654 #else /* CONFIG_SOC_MKW40Z4 */
655 	((uint8_t *)ZLL->PKT_BUFFER)[0] = payload_len + KW41Z_FCS_LENGTH;
656 	memcpy(((uint8_t *)ZLL->PKT_BUFFER) + 1,
657 		(void *)frag->data, payload_len);
658 #endif
659 
660 	/* Set CCA mode */
661 	ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_CCATYPE_MASK) |
662 			ZLL_PHY_CTRL_CCATYPE(KW41Z_CCA_MODE1);
663 
664 	/* Clear all IRQ flags */
665 	ZLL->IRQSTS = ZLL->IRQSTS;
666 
667 	/* Perform automatic reception of ACK frame, if required */
668 	if (ieee802154_is_ar_flag_set(frag)) {
669 		tx_timeout = kw41z->tx_warmup_time + KW41Z_SHR_PHY_TIME +
670 				 payload_len * KW41Z_PER_BYTE_TIME + 10 +
671 				 KW41Z_ACK_WAIT_TIME;
672 
673 		LOG_DBG("AUTOACK ENABLED: len: %d, timeout: %d, seq: %d",
674 			payload_len, tx_timeout, frag->data[2]);
675 
676 		kw41z_tmr3_set_timeout(tx_timeout);
677 		ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK;
678 		xcvseq = KW41Z_STATE_TXRX;
679 	} else {
680 		LOG_DBG("AUTOACK DISABLED: len: %d, seq: %d",
681 			payload_len, frag->data[2]);
682 
683 		ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK;
684 		xcvseq = KW41Z_STATE_TX;
685 	}
686 
687 	kw41z_enable_seq_irq();
688 	/*
689 	 * PHY_CTRL is sensitive to multiple writes that can kick off
690 	 * the sequencer engine causing TX with AR request to send the
691 	 * TX frame multiple times.
692 	 *
693 	 * To minimize, ensure there is only one write to PHY_CTRL with
694 	 * TXRX sequence enable and the 802.15.4 radio IRQ.
695 	 */
696 	ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_TRCV_MSK_MASK) | xcvseq;
697 	irq_unlock(key);
698 	k_sem_take(&kw41z->seq_sync, K_FOREVER);
699 
700 	if ((kw41z->seq_retval == 0) && ieee802154_is_ar_flag_set(frag)) {
701 		handle_ack(kw41z, frag->data[2]);
702 	}
703 
704 	LOG_DBG("seq_retval: %ld", kw41z->seq_retval);
705 	return kw41z->seq_retval;
706 }
707 
kw41z_isr(int unused)708 static void kw41z_isr(int unused)
709 {
710 	uint32_t irqsts = ZLL->IRQSTS;
711 	uint8_t state = kw41z_get_seq_state();
712 	uint8_t restart_rx = 1U;
713 	uint32_t rx_len;
714 
715 	/*
716 	 * Variable is used in debug output to capture the state of the
717 	 * sequencer at interrupt.
718 	 */
719 	uint32_t seq_state = ZLL->SEQ_STATE;
720 
721 	LOG_DBG("ENTRY: irqsts: 0x%08X, PHY_CTRL: 0x%08X, "
722 		"SEQ_STATE: 0x%08X, SEQ_CTRL: 0x%08X, TMR: %d, state: %d",
723 		irqsts, (unsigned int)ZLL->PHY_CTRL,
724 		(unsigned int)seq_state,
725 		(unsigned int)ZLL->SEQ_CTRL_STS,
726 		(unsigned int)(ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT),
727 		state);
728 
729 	/* Clear interrupts */
730 	ZLL->IRQSTS = irqsts;
731 
732 	if (irqsts & ZLL_IRQSTS_FILTERFAIL_IRQ_MASK) {
733 		LOG_DBG("Incoming RX failed packet filtering rules: "
734 			"CODE: 0x%08X, irqsts: 0x%08X, PHY_CTRL: 0x%08X, "
735 			"SEQ_STATE: 0x%08X, state: %d",
736 			(unsigned int)ZLL->FILTERFAIL_CODE,
737 			irqsts,
738 			(unsigned int)ZLL->PHY_CTRL,
739 			(unsigned int)seq_state, state);
740 
741 		restart_rx = 0U;
742 
743 	} else if ((!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_RX_WMRK_MSK_MASK)) &&
744 	    (irqsts & ZLL_IRQSTS_RXWTRMRKIRQ_MASK)) {
745 		/*
746 		 * There is a bug in the KW41Z where in noisy environments
747 		 * the RX sequence can get lost. The watermark mask IRQ can
748 		 * start TMR3 to complete the rest of the read or to assert
749 		 * IRQ if the sequencer gets lost so we can reset things.
750 		 * Note that a TX from the upper layers will also reset
751 		 * things so the problem is contained a bit in normal
752 		 * operation.
753 		 */
754 		rx_len = (irqsts & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK)
755 			>> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT;
756 
757 		KW_DBG_TRACE(KW41_DBG_TRACE_WTRM, irqsts,
758 			(unsigned int)ZLL->PHY_CTRL, seq_state);
759 
760 		if (rx_len > IEEE802154_ACK_LENGTH) {
761 
762 			LOG_DBG("WMRK irq: seq_state: 0x%08x, rx_len: %d",
763 				seq_state, rx_len);
764 			/*
765 			 * Assume the RX includes an auto-ACK so set the
766 			 * timer to include the RX frame size, crc, IFS,
767 			 * and ACK length and convert to symbols.
768 			 *
769 			 * IFS is 12 symbols
770 			 *
771 			 * ACK frame is 11 bytes: 4 preamble, 1 start of
772 			 * frame, 1 frame length, 2 frame control,
773 			 * 1 sequence, 2 FCS. Times two to convert to symbols.
774 			 */
775 			rx_len = rx_len * 2U + 12 + 22 + 2;
776 			kw41z_tmr3_set_timeout(rx_len);
777 		}
778 		restart_rx = 0U;
779 	}
780 
781 	/* Sequence done IRQ */
782 	if ((state != KW41Z_STATE_IDLE) && (irqsts & ZLL_IRQSTS_SEQIRQ_MASK)) {
783 		/*
784 		 * PLL unlock, the autosequence has been aborted due to
785 		 * PLL unlock
786 		 */
787 		if (irqsts & ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK) {
788 			LOG_ERR("PLL unlock error");
789 			kw41z_isr_seq_cleanup();
790 			restart_rx = 1U;
791 		}
792 		/*
793 		 * TMR3 timeout, the autosequence has been aborted due to
794 		 * TMR3 timeout
795 		 */
796 		else if ((irqsts & ZLL_IRQSTS_TMR3IRQ_MASK) &&
797 			(!(irqsts & ZLL_IRQSTS_RXIRQ_MASK)) &&
798 			(state != KW41Z_STATE_TX)) {
799 
800 			LOG_DBG("a) TMR3 timeout: irqsts: 0x%08X, "
801 				"seq_state: 0x%08X, PHY_CTRL: 0x%08X, "
802 				"state: %d",
803 				irqsts, seq_state,
804 				(unsigned int)ZLL->PHY_CTRL, state);
805 
806 			KW_DBG_TRACE(KW41_DBG_TRACE_TMR3, irqsts,
807 				(unsigned int)ZLL->PHY_CTRL, seq_state);
808 
809 			kw41z_isr_timeout_cleanup();
810 			restart_rx = 1U;
811 
812 			if (state == KW41Z_STATE_TXRX) {
813 				/* TODO: What is the right error for no ACK? */
814 				atomic_set(&kw41z_context_data.seq_retval,
815 					   -EBUSY);
816 				k_sem_give(&kw41z_context_data.seq_sync);
817 			}
818 		} else {
819 			kw41z_isr_seq_cleanup();
820 
821 			switch (state) {
822 			case KW41Z_STATE_RX:
823 				LOG_DBG("RX seq done: SEQ_STATE: 0x%08X",
824 					(unsigned int)seq_state);
825 
826 				KW_DBG_TRACE(KW41_DBG_TRACE_RX, irqsts,
827 					(unsigned int)ZLL->PHY_CTRL, seq_state);
828 
829 				kw41z_tmr3_disable();
830 
831 				rx_len = (ZLL->IRQSTS &
832 					  ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >>
833 					  ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT;
834 
835 				if (irqsts & ZLL_IRQSTS_RXIRQ_MASK) {
836 					if (rx_len != 0U) {
837 						kw41z_rx(&kw41z_context_data,
838 							rx_len);
839 					}
840 				}
841 				restart_rx = 1U;
842 				break;
843 			case KW41Z_STATE_TXRX:
844 				LOG_DBG("TXRX seq done");
845 				kw41z_tmr3_disable();
846 				/* Store the frame pending bit status. */
847 				kw41z_context_data.frame_pending =
848 					irqsts & ZLL_IRQSTS_RX_FRM_PEND_MASK;
849 			case KW41Z_STATE_TX:
850 				LOG_DBG("TX seq done");
851 				KW_DBG_TRACE(KW41_DBG_TRACE_TX, irqsts,
852 					(unsigned int)ZLL->PHY_CTRL, seq_state);
853 				if (irqsts & ZLL_IRQSTS_CCA_MASK) {
854 					atomic_set(
855 						&kw41z_context_data.seq_retval,
856 						-EBUSY);
857 				} else {
858 					atomic_set(
859 						&kw41z_context_data.seq_retval,
860 						0);
861 				}
862 
863 				k_sem_give(&kw41z_context_data.seq_sync);
864 				restart_rx = 1U;
865 
866 				break;
867 			case KW41Z_STATE_CCA:
868 				LOG_DBG("CCA seq done");
869 				KW_DBG_TRACE(KW41_DBG_TRACE_CCA, irqsts,
870 					(unsigned int)ZLL->PHY_CTRL, seq_state);
871 				if (irqsts & ZLL_IRQSTS_CCA_MASK) {
872 					atomic_set(
873 						&kw41z_context_data.seq_retval,
874 						-EBUSY);
875 					restart_rx = 1U;
876 				} else {
877 					atomic_set(
878 						&kw41z_context_data.seq_retval,
879 						0);
880 					restart_rx = 0U;
881 				}
882 
883 				k_sem_give(&kw41z_context_data.seq_sync);
884 				break;
885 			default:
886 				LOG_DBG("Unhandled state: %d", state);
887 				restart_rx = 1U;
888 				break;
889 			}
890 		}
891 	} else {
892 		/* Timer 3 Compare Match */
893 		if ((irqsts & ZLL_IRQSTS_TMR3IRQ_MASK) &&
894 			(!(irqsts & ZLL_IRQSTS_TMR3MSK_MASK))) {
895 
896 			LOG_DBG("b) TMR3 timeout: irqsts: 0x%08X, "
897 				"seq_state: 0x%08X, state: %d",
898 				irqsts, seq_state, state);
899 
900 			kw41z_tmr3_disable();
901 			restart_rx = 0U;
902 			if (state != KW41Z_STATE_IDLE) {
903 				kw41z_isr_timeout_cleanup();
904 				restart_rx = 1U;
905 				/* If we are not running an automated
906 				 * sequence then handle event. TMR3 can expire
907 				 * during Recv/Ack sequence where the transmit
908 				 * of the ACK is not being interrupted.
909 				 */
910 			}
911 		}
912 	}
913 
914 	/* Restart RX */
915 	if (restart_rx) {
916 		LOG_DBG("RESET RX");
917 		kw41z_phy_abort();
918 		kw41z_set_seq_state(KW41Z_STATE_RX);
919 		kw41z_enable_seq_irq();
920 	}
921 }
922 
get_mac(const struct device * dev)923 static inline uint8_t *get_mac(const struct device *dev)
924 {
925 	struct kw41z_context *kw41z = dev->data;
926 
927 	/*
928 	 * The KW40Z has two 32-bit registers for the MAC address where
929 	 * 40 bits of the registers are factory programmed to be unique
930 	 * and the rest are to be assigned as the "company-specific" value.
931 	 * 802.15.4 defines a EUI-64 64-bit address with company specific
932 	 * being 24 or 36 bits with the unique value being 24 or 40 bits.
933 	 *
934 	 * TODO: Grab from RSIM->MAC_LSB/MAC_MSB for the unique 40 bits
935 	 *       and how to allow for a OUI portion?
936 	 */
937 
938 	uint32_t *ptr = (uint32_t *)(kw41z->mac_addr);
939 
940 	UNALIGNED_PUT(sys_rand32_get(), ptr);
941 	ptr = (uint32_t *)(kw41z->mac_addr + 4);
942 	UNALIGNED_PUT(sys_rand32_get(), ptr);
943 
944 	/*
945 	 * Clear bit 0 to ensure it isn't a multicast address and set
946 	 * bit 1 to indicate address is locally administered and may
947 	 * not be globally unique.
948 	 */
949 	kw41z->mac_addr[0] = (kw41z->mac_addr[0] & ~0x01) | 0x02;
950 
951 	return kw41z->mac_addr;
952 }
953 
kw41z_init(const struct device * dev)954 static int kw41z_init(const struct device *dev)
955 {
956 	struct kw41z_context *kw41z = dev->data;
957 	xcvrStatus_t xcvrStatus;
958 
959 	xcvrStatus = XCVR_Init(ZIGBEE_MODE, DR_500KBPS);
960 	if (xcvrStatus != gXcvrSuccess_c) {
961 		return -EIO;
962 	}
963 
964 	/* Disable all timers, enable AUTOACK, mask all interrupts */
965 	ZLL->PHY_CTRL = ZLL_PHY_CTRL_CCATYPE(KW41Z_CCA_MODE1)	|
966 			ZLL_PHY_CTRL_CRC_MSK_MASK		|
967 			ZLL_PHY_CTRL_PLL_UNLOCK_MSK_MASK	|
968 			/*ZLL_PHY_CTRL_FILTERFAIL_MSK_MASK	|*/
969 			ZLL_PHY_CTRL_RX_WMRK_MSK_MASK	|
970 			ZLL_PHY_CTRL_CCAMSK_MASK		|
971 			ZLL_PHY_CTRL_RXMSK_MASK			|
972 			ZLL_PHY_CTRL_TXMSK_MASK			|
973 			ZLL_PHY_CTRL_CCABFRTX_MASK		|
974 			ZLL_PHY_CTRL_SEQMSK_MASK;
975 
976 #if CONFIG_SOC_MKW41Z4
977 	ZLL->PHY_CTRL |= ZLL_IRQSTS_WAKE_IRQ_MASK;
978 #endif
979 
980 	ZLL->PHY_CTRL |= ZLL_PHY_CTRL_AUTOACK_MASK;
981 
982 	/*
983 	 * Clear all PP IRQ bits to avoid unexpected interrupts immediately
984 	 * after init disable all timer interrupts
985 	 */
986 	ZLL->IRQSTS = ZLL->IRQSTS;
987 
988 	/* Clear HW indirect queue */
989 	ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK;
990 
991 	/* Accept FrameVersion 0 and 1 packets, reject all others */
992 	ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_PROMISCUOUS_MASK;
993 	ZLL->RX_FRAME_FILTER &= ~ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK;
994 	ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3)	|
995 			       ZLL_RX_FRAME_FILTER_CMD_FT_MASK		|
996 			       ZLL_RX_FRAME_FILTER_DATA_FT_MASK		|
997 			       ZLL_RX_FRAME_FILTER_ACK_FT_MASK		|
998 			       ZLL_RX_FRAME_FILTER_BEACON_FT_MASK;
999 
1000 	/* Set prescaler to obtain 1 symbol (16us) timebase */
1001 	ZLL->TMR_PRESCALE = 0x05;
1002 
1003 	kw41z_tmr3_disable();
1004 
1005 	/* Compute warmup times (scaled to 16us) */
1006 	kw41z->rx_warmup_time = (XCVR_TSM->END_OF_SEQ &
1007 				 XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >>
1008 				XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
1009 	kw41z->tx_warmup_time = (XCVR_TSM->END_OF_SEQ &
1010 				 XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK) >>
1011 				XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT;
1012 
1013 	if (kw41z->rx_warmup_time & 0x0F) {
1014 		kw41z->rx_warmup_time = 1 + (kw41z->rx_warmup_time >> 4);
1015 	} else {
1016 		kw41z->rx_warmup_time = kw41z->rx_warmup_time >> 4;
1017 	}
1018 
1019 	if (kw41z->tx_warmup_time & 0x0F) {
1020 		kw41z->tx_warmup_time = 1 + (kw41z->tx_warmup_time >> 4);
1021 	} else {
1022 		kw41z->tx_warmup_time = kw41z->tx_warmup_time >> 4;
1023 	}
1024 
1025 	/* Set CCA threshold to -75 dBm */
1026 	ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK;
1027 	ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_CCA1_THRESH(0xB5);
1028 
1029 	/* Set the default power level */
1030 	kw41z_set_txpower(dev, 0);
1031 
1032 	/* Adjust ACK delay to fulfill the 802.15.4 turnaround requirements */
1033 	ZLL->ACKDELAY &= ~ZLL_ACKDELAY_ACKDELAY_MASK;
1034 	ZLL->ACKDELAY |= ZLL_ACKDELAY_ACKDELAY(-8);
1035 
1036 	/* Adjust LQI compensation */
1037 	ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK;
1038 	ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(96);
1039 
1040 	/* Enable the RxWatermark IRQ  */
1041 	ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_RX_WMRK_MSK_MASK);
1042 	/* Set Rx watermark level */
1043 	ZLL->RX_WTR_MARK = 0;
1044 
1045 
1046 	/* Set default channel to 2405 MHZ */
1047 	kw41z_set_channel(dev, KW41Z_DEFAULT_CHANNEL);
1048 
1049 	/* Unmask Transceiver Global Interrupts */
1050 	ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TRCV_MSK_MASK;
1051 
1052 	/* Configure Radio IRQ */
1053 	NVIC_ClearPendingIRQ(Radio_1_IRQn);
1054 	IRQ_CONNECT(Radio_1_IRQn, RADIO_0_IRQ_PRIO, kw41z_isr, 0, 0);
1055 
1056 	return 0;
1057 }
1058 
kw41z_iface_init(struct net_if * iface)1059 static void kw41z_iface_init(struct net_if *iface)
1060 {
1061 	const struct device *dev = net_if_get_device(iface);
1062 	struct kw41z_context *kw41z = dev->data;
1063 	uint8_t *mac = get_mac(dev);
1064 
1065 #if defined(CONFIG_KW41_DBG_TRACE)
1066 	kw41_dbg_idx = 0;
1067 #endif
1068 
1069 	net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);
1070 	kw41z->iface = iface;
1071 	ieee802154_init(iface);
1072 }
1073 
kw41z_configure(const struct device * dev,enum ieee802154_config_type type,const struct ieee802154_config * config)1074 static int kw41z_configure(const struct device *dev,
1075 			   enum ieee802154_config_type type,
1076 			   const struct ieee802154_config *config)
1077 {
1078 	return 0;
1079 }
1080 
1081 /* driver-allocated attribute memory - constant across all driver instances */
1082 IEEE802154_DEFINE_PHY_SUPPORTED_CHANNELS(drv_attr, 11, 26);
1083 
kw41z_attr_get(const struct device * dev,enum ieee802154_attr attr,struct ieee802154_attr_value * value)1084 static int kw41z_attr_get(const struct device *dev, enum ieee802154_attr attr,
1085 			  struct ieee802154_attr_value *value)
1086 {
1087 	ARG_UNUSED(dev);
1088 
1089 	return ieee802154_attr_get_channel_page_and_range(
1090 		attr, IEEE802154_ATTR_PHY_CHANNEL_PAGE_ZERO_OQPSK_2450_BPSK_868_915,
1091 		&drv_attr.phy_supported_channels, value);
1092 }
1093 
1094 static struct ieee802154_radio_api kw41z_radio_api = {
1095 	.iface_api.init	= kw41z_iface_init,
1096 
1097 	.get_capabilities	= kw41z_get_capabilities,
1098 	.cca			= kw41z_cca,
1099 	.set_channel		= kw41z_set_channel,
1100 	.filter			= kw41z_filter,
1101 	.set_txpower		= kw41z_set_txpower,
1102 	.start			= kw41z_start,
1103 	.stop			= kw41z_stop,
1104 	.tx			= kw41z_tx,
1105 	.configure		= kw41z_configure,
1106 	.attr_get		= kw41z_attr_get,
1107 };
1108 
1109 #if defined(CONFIG_NET_L2_IEEE802154)
1110 
1111 #define L2 IEEE802154_L2
1112 #define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(IEEE802154_L2)
1113 #define MTU KW41Z_PSDU_LENGTH
1114 
1115 #elif defined(CONFIG_NET_L2_OPENTHREAD)
1116 
1117 #define L2 OPENTHREAD_L2
1118 #define L2_CTX_TYPE NET_L2_GET_CTX_TYPE(OPENTHREAD_L2)
1119 #define MTU 1280
1120 
1121 #endif
1122 
1123 NET_DEVICE_DT_INST_DEFINE(
1124 	0,
1125 	kw41z_init,                         /* Initialization Function */
1126 	NULL,              /* No PM API support */
1127 	&kw41z_context_data,                /* Context data */
1128 	NULL,                               /* Configuration info */
1129 	CONFIG_IEEE802154_KW41Z_INIT_PRIO,  /* Initial priority */
1130 	&kw41z_radio_api,                   /* API interface functions */
1131 	L2,                                 /* L2 */
1132 	L2_CTX_TYPE,                        /* L2 context type */
1133 	MTU);                               /* MTU size */
1134