Lines Matching +full:write +full:- +full:watermark
1 /* ieee802154_kw41z.c - NXP KW41Z driver */
6 * SPDX-License-Identifier: Apache-2.0
35 * For non-invasive tracing of IRQ events. Sometimes the print logs
65 ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT; \
92 #define KW41Z_OUTPUT_POWER_MIN (-31)
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 */
167 return (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) >> in kw41z_get_instant_state()
173 return (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) >> in kw41z_get_seq_state()
189 ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_XCVSEQ_MASK) | in kw41z_set_seq_state()
213 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK; in kw41z_phy_abort()
215 if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_TMRTRIGEN_MASK) { in kw41z_phy_abort()
216 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMRTRIGEN_MASK; in kw41z_phy_abort()
218 while ((XCVR_MISC->XCVR_CTRL & in kw41z_phy_abort()
224 if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) { in kw41z_phy_abort()
225 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK; in kw41z_phy_abort()
228 while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) { in kw41z_phy_abort()
233 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR1CMP_EN_MASK | in kw41z_phy_abort()
245 ZLL->IRQSTS = ZLL->IRQSTS; in kw41z_phy_abort()
258 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK | in kw41z_isr_timeout_cleanup()
263 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK | in kw41z_isr_timeout_cleanup()
268 while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) { in kw41z_isr_timeout_cleanup()
271 irqsts = ZLL->IRQSTS; in kw41z_isr_timeout_cleanup()
275 ZLL->IRQSTS = irqsts; in kw41z_isr_timeout_cleanup()
283 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK; in kw41z_isr_seq_cleanup()
285 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK | in kw41z_isr_seq_cleanup()
290 while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) { in kw41z_isr_seq_cleanup()
293 irqsts = ZLL->IRQSTS; in kw41z_isr_seq_cleanup()
302 ZLL->IRQSTS = irqsts; in kw41z_isr_seq_cleanup()
307 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK; in kw41z_enable_seq_irq()
312 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK; in kw41z_disable_seq_irq()
326 timeout += ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT; in kw41z_tmr3_set_timeout()
329 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK; in kw41z_tmr3_set_timeout()
330 ZLL->T3CMP = timeout & ZLL_T3CMP_T3CMP_MASK; in kw41z_tmr3_set_timeout()
333 irqsts = ZLL->IRQSTS & BM_ZLL_IRQSTS_TMRxMSK; in kw41z_tmr3_set_timeout()
335 ZLL->IRQSTS = irqsts; in kw41z_tmr3_set_timeout()
337 ZLL->PHY_CTRL |= in kw41z_tmr3_set_timeout()
349 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK | in kw41z_tmr3_disable()
352 irqsts = ZLL->IRQSTS & BM_ZLL_IRQSTS_TMRxMSK; in kw41z_tmr3_disable()
357 ZLL->IRQSTS = irqsts; in kw41z_tmr3_disable()
368 struct kw41z_context *kw41z = dev->data; in kw41z_cca()
372 k_sem_init(&kw41z->seq_sync, 0, 1); in kw41z_cca()
375 ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_CCATYPE_MASK) | in kw41z_cca()
380 k_sem_take(&kw41z->seq_sync, K_FOREVER); in kw41z_cca()
382 return kw41z->seq_retval; in kw41z_cca()
388 return channel < 11 ? -ENOTSUP : -EINVAL; in kw41z_set_channel()
391 ZLL->CHANNEL_NUM0 = channel; in kw41z_set_channel()
397 ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0 & in kw41z_set_pan_id()
405 ZLL->MACSHORTADDRS0 = (ZLL->MACSHORTADDRS0 & in kw41z_set_short_addr()
417 ZLL->MACLONGADDRS0_LSB = val; in kw41z_set_ieee_addr()
420 ZLL->MACLONGADDRS0_MSB = val; in kw41z_set_ieee_addr()
433 return -ENOTSUP; in kw41z_filter()
437 return kw41z_set_ieee_addr(dev, filter->ieee_addr); in kw41z_filter()
439 return kw41z_set_short_addr(dev, filter->short_addr); in kw41z_filter()
441 return kw41z_set_pan_id(dev, filter->pan_id); in kw41z_filter()
444 return -ENOTSUP; in kw41z_filter()
450 LOG_INF("TX-power %d dBm below min of %d dBm, using %d dBm", in kw41z_set_txpower()
456 LOG_INF("TX-power %d dBm above max of %d dBm, using %d dBm", in kw41z_set_txpower()
463 ZLL->PA_PWR = pa_pwr_lt[dbm - KW41Z_OUTPUT_POWER_MIN]; in kw41z_set_txpower()
512 pkt_len = len - KW41Z_FCS_LENGTH; in kw41z_rx()
515 pkt = net_pkt_rx_alloc_with_buffer(kw41z->iface, pkt_len, in kw41z_rx()
522 buf = pkt->buffer; in kw41z_rx()
528 reg_val = ZLL->PKT_BUFFER_RX[i/2U]; in kw41z_rx()
529 buf->data[i] = reg_val & 0xFF; in kw41z_rx()
531 buf->data[i] = reg_val >> 8; in kw41z_rx()
539 reg_val = ZLL->PKT_BUFFER[i/4U]; in kw41z_rx()
540 buf->data[i] = reg_val & 0xFF; in kw41z_rx()
543 buf->data[i] = (reg_val >> 8) & 0xFF; in kw41z_rx()
546 buf->data[i] = (reg_val >> 16) & 0xFF; in kw41z_rx()
549 buf->data[i] = reg_val >> 24; in kw41z_rx()
556 hw_lqi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> in kw41z_rx()
561 rslt = net_recv_data(kw41z->iface, pkt); in kw41z_rx()
583 ack_pkt = net_pkt_rx_alloc_with_buffer(kw41z->iface, ACK_FRAME_LEN, in handle_ack()
590 /* Re-create ACK frame. */ in handle_ack()
597 LOG_ERR("Failed to write to a packet."); in handle_ack()
603 (void)net_pkt_set_ieee802154_rssi_dbm(ack_pkt, -40); in handle_ack()
607 if (ieee802154_handle_ack(kw41z->iface, ack_pkt) != NET_OK) { in handle_ack()
608 LOG_INF("ACK packet not handled - releasing."); in handle_ack()
618 struct kw41z_context *kw41z = dev->data; in kw41z_tx()
619 uint8_t payload_len = frag->len; in kw41z_tx()
626 return -ENOTSUP; in kw41z_tx()
636 return -EBUSY; in kw41z_tx()
647 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TRCV_MSK_MASK; in kw41z_tx()
651 ((uint8_t *)ZLL->PKT_BUFFER_TX)[0] = payload_len + KW41Z_FCS_LENGTH; in kw41z_tx()
652 memcpy(((uint8_t *)ZLL->PKT_BUFFER_TX) + 1, in kw41z_tx()
653 (void *)frag->data, payload_len); in kw41z_tx()
655 ((uint8_t *)ZLL->PKT_BUFFER)[0] = payload_len + KW41Z_FCS_LENGTH; in kw41z_tx()
656 memcpy(((uint8_t *)ZLL->PKT_BUFFER) + 1, in kw41z_tx()
657 (void *)frag->data, payload_len); in kw41z_tx()
661 ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_CCATYPE_MASK) | in kw41z_tx()
665 ZLL->IRQSTS = ZLL->IRQSTS; in kw41z_tx()
669 tx_timeout = kw41z->tx_warmup_time + KW41Z_SHR_PHY_TIME + in kw41z_tx()
674 payload_len, tx_timeout, frag->data[2]); in kw41z_tx()
677 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK; in kw41z_tx()
681 payload_len, frag->data[2]); in kw41z_tx()
683 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK; in kw41z_tx()
693 * To minimize, ensure there is only one write to PHY_CTRL with in kw41z_tx()
696 ZLL->PHY_CTRL = (ZLL->PHY_CTRL & ~ZLL_PHY_CTRL_TRCV_MSK_MASK) | xcvseq; in kw41z_tx()
698 k_sem_take(&kw41z->seq_sync, K_FOREVER); in kw41z_tx()
700 if ((kw41z->seq_retval == 0) && ieee802154_is_ar_flag_set(frag)) { in kw41z_tx()
701 handle_ack(kw41z, frag->data[2]); in kw41z_tx()
704 LOG_DBG("seq_retval: %ld", kw41z->seq_retval); in kw41z_tx()
705 return kw41z->seq_retval; in kw41z_tx()
710 uint32_t irqsts = ZLL->IRQSTS; in kw41z_isr()
719 uint32_t seq_state = ZLL->SEQ_STATE; in kw41z_isr()
723 irqsts, (unsigned int)ZLL->PHY_CTRL, in kw41z_isr()
725 (unsigned int)ZLL->SEQ_CTRL_STS, in kw41z_isr()
726 (unsigned int)(ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT), in kw41z_isr()
730 ZLL->IRQSTS = irqsts; in kw41z_isr()
736 (unsigned int)ZLL->FILTERFAIL_CODE, in kw41z_isr()
738 (unsigned int)ZLL->PHY_CTRL, in kw41z_isr()
743 } else if ((!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_RX_WMRK_MSK_MASK)) && in kw41z_isr()
747 * the RX sequence can get lost. The watermark mask IRQ can in kw41z_isr()
758 (unsigned int)ZLL->PHY_CTRL, seq_state); in kw41z_isr()
765 * Assume the RX includes an auto-ACK so set the in kw41z_isr()
804 (unsigned int)ZLL->PHY_CTRL, state); in kw41z_isr()
807 (unsigned int)ZLL->PHY_CTRL, seq_state); in kw41z_isr()
815 -EBUSY); in kw41z_isr()
827 (unsigned int)ZLL->PHY_CTRL, seq_state); in kw41z_isr()
831 rx_len = (ZLL->IRQSTS & in kw41z_isr()
852 (unsigned int)ZLL->PHY_CTRL, seq_state); in kw41z_isr()
856 -EBUSY); in kw41z_isr()
870 (unsigned int)ZLL->PHY_CTRL, seq_state); in kw41z_isr()
874 -EBUSY); in kw41z_isr()
925 struct kw41z_context *kw41z = dev->data; in get_mac()
928 * The KW40Z has two 32-bit registers for the MAC address where in get_mac()
930 * and the rest are to be assigned as the "company-specific" value. in get_mac()
931 * 802.15.4 defines a EUI-64 64-bit address with company specific in get_mac()
934 * TODO: Grab from RSIM->MAC_LSB/MAC_MSB for the unique 40 bits in get_mac()
938 sys_rand_get(kw41z->mac_addr, sizeof(kw41z->mac_addr)); in get_mac()
945 kw41z->mac_addr[0] = (kw41z->mac_addr[0] & ~0x01) | 0x02; in get_mac()
947 return kw41z->mac_addr; in get_mac()
952 struct kw41z_context *kw41z = dev->data; in kw41z_init()
957 return -EIO; in kw41z_init()
961 ZLL->PHY_CTRL = ZLL_PHY_CTRL_CCATYPE(KW41Z_CCA_MODE1) | in kw41z_init()
973 ZLL->PHY_CTRL |= ZLL_IRQSTS_WAKE_IRQ_MASK; in kw41z_init()
976 ZLL->PHY_CTRL |= ZLL_PHY_CTRL_AUTOACK_MASK; in kw41z_init()
982 ZLL->IRQSTS = ZLL->IRQSTS; in kw41z_init()
985 ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK; in kw41z_init()
988 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_PROMISCUOUS_MASK; in kw41z_init()
989 ZLL->RX_FRAME_FILTER &= ~ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK; in kw41z_init()
990 ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) | in kw41z_init()
997 ZLL->TMR_PRESCALE = 0x05; in kw41z_init()
1002 kw41z->rx_warmup_time = (XCVR_TSM->END_OF_SEQ & in kw41z_init()
1005 kw41z->tx_warmup_time = (XCVR_TSM->END_OF_SEQ & in kw41z_init()
1009 if (kw41z->rx_warmup_time & 0x0F) { in kw41z_init()
1010 kw41z->rx_warmup_time = 1 + (kw41z->rx_warmup_time >> 4); in kw41z_init()
1012 kw41z->rx_warmup_time = kw41z->rx_warmup_time >> 4; in kw41z_init()
1015 if (kw41z->tx_warmup_time & 0x0F) { in kw41z_init()
1016 kw41z->tx_warmup_time = 1 + (kw41z->tx_warmup_time >> 4); in kw41z_init()
1018 kw41z->tx_warmup_time = kw41z->tx_warmup_time >> 4; in kw41z_init()
1021 /* Set CCA threshold to -75 dBm */ in kw41z_init()
1022 ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK; in kw41z_init()
1023 ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_CCA1_THRESH(0xB5); in kw41z_init()
1029 ZLL->ACKDELAY &= ~ZLL_ACKDELAY_ACKDELAY_MASK; in kw41z_init()
1030 ZLL->ACKDELAY |= ZLL_ACKDELAY_ACKDELAY(-8); in kw41z_init()
1033 ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK; in kw41z_init()
1034 ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(96); in kw41z_init()
1037 ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_RX_WMRK_MSK_MASK); in kw41z_init()
1038 /* Set Rx watermark level */ in kw41z_init()
1039 ZLL->RX_WTR_MARK = 0; in kw41z_init()
1046 ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TRCV_MSK_MASK; in kw41z_init()
1058 struct kw41z_context *kw41z = dev->data; in kw41z_iface_init()
1066 kw41z->iface = iface; in kw41z_iface_init()
1077 /* driver-allocated attribute memory - constant across all driver instances */