Lines Matching +full:- +full:sc
3 * SPDX-License-Identifier: Apache-2.0
18 #define SMSC_LOCK(sc) k_mutex_lock(&(sc)->lock, K_FOREVER) argument
19 #define SMSC_UNLOCK(sc) k_mutex_unlock(&(sc)->lock) argument
78 struct smsc_data sc; member
89 static ALWAYS_INLINE void smsc_select_bank(struct smsc_data *sc, uint16_t bank) in smsc_select_bank() argument
91 sys_write16(bank & BSR_BANK_MASK, sc->smsc_reg + BSR); in smsc_select_bank()
94 static ALWAYS_INLINE unsigned int smsc_current_bank(struct smsc_data *sc) in smsc_current_bank() argument
96 return FIELD_GET(BSR_BANK_MASK, sys_read16(sc->smsc_reg + BSR)); in smsc_current_bank()
99 static void smsc_mmu_wait(struct smsc_data *sc) in smsc_mmu_wait() argument
101 __ASSERT((smsc_current_bank(sc) == 2), "%s called when not in bank 2", __func__); in smsc_mmu_wait()
102 while (sys_read16(sc->smsc_reg + MMUCR) & MMUCR_BUSY) { in smsc_mmu_wait()
107 static ALWAYS_INLINE uint8_t smsc_read_1(struct smsc_data *sc, int offset) in smsc_read_1() argument
109 return sys_read8(sc->smsc_reg + offset); in smsc_read_1()
112 static ALWAYS_INLINE uint16_t smsc_read_2(struct smsc_data *sc, int offset) in smsc_read_2() argument
114 return sys_read16(sc->smsc_reg + offset); in smsc_read_2()
117 static ALWAYS_INLINE void smsc_read_multi_2(struct smsc_data *sc, int offset, uint16_t *datap, in smsc_read_multi_2() argument
120 while (count--) { in smsc_read_multi_2()
121 *datap++ = sys_read16(sc->smsc_reg + offset); in smsc_read_multi_2()
125 static ALWAYS_INLINE void smsc_write_1(struct smsc_data *sc, int offset, uint8_t val) in smsc_write_1() argument
127 sys_write8(val, sc->smsc_reg + offset); in smsc_write_1()
130 static ALWAYS_INLINE void smsc_write_2(struct smsc_data *sc, int offset, uint16_t val) in smsc_write_2() argument
132 sys_write16(val, sc->smsc_reg + offset); in smsc_write_2()
135 static ALWAYS_INLINE void smsc_write_multi_2(struct smsc_data *sc, int offset, uint16_t *datap, in smsc_write_multi_2() argument
138 while (count--) { in smsc_write_multi_2()
139 sys_write16(*datap++, sc->smsc_reg + offset); in smsc_write_multi_2()
143 static uint32_t smsc_mii_bitbang_read(struct smsc_data *sc) in smsc_mii_bitbang_read() argument
147 __ASSERT(FIELD_GET(BSR_BANK_MASK, smsc_read_2(sc, BSR)) == 3, in smsc_mii_bitbang_read()
149 FIELD_GET(BSR_BANK_MASK, smsc_read_2(sc, BSR))); in smsc_mii_bitbang_read()
151 val = smsc_read_2(sc, MGMT); in smsc_mii_bitbang_read()
157 static void smsc_mii_bitbang_write(struct smsc_data *sc, uint16_t val) in smsc_mii_bitbang_write() argument
159 __ASSERT(FIELD_GET(BSR_BANK_MASK, smsc_read_2(sc, BSR)) == 3, in smsc_mii_bitbang_write()
161 FIELD_GET(BSR_BANK_MASK, smsc_read_2(sc, BSR))); in smsc_mii_bitbang_write()
163 smsc_write_2(sc, MGMT, val); in smsc_mii_bitbang_write()
167 static void smsc_miibus_sync(struct smsc_data *sc) in smsc_miibus_sync() argument
174 smsc_mii_bitbang_write(sc, v); in smsc_miibus_sync()
176 smsc_mii_bitbang_write(sc, v | MDC); in smsc_miibus_sync()
177 smsc_mii_bitbang_write(sc, v); in smsc_miibus_sync()
181 static void smsc_miibus_sendbits(struct smsc_data *sc, uint32_t data, int nbits) in smsc_miibus_sendbits() argument
187 smsc_mii_bitbang_write(sc, v); in smsc_miibus_sendbits()
189 for (i = 1 << (nbits - 1); i != 0; i >>= 1) { in smsc_miibus_sendbits()
196 smsc_mii_bitbang_write(sc, v); in smsc_miibus_sendbits()
197 smsc_mii_bitbang_write(sc, v | MDC); in smsc_miibus_sendbits()
198 smsc_mii_bitbang_write(sc, v); in smsc_miibus_sendbits()
202 static int smsc_miibus_readreg(struct smsc_data *sc, int phy, int reg) in smsc_miibus_readreg() argument
206 irq_disable(sc->irq); in smsc_miibus_readreg()
207 SMSC_LOCK(sc); in smsc_miibus_readreg()
209 smsc_select_bank(sc, 3); in smsc_miibus_readreg()
211 smsc_miibus_sync(sc); in smsc_miibus_readreg()
213 smsc_miibus_sendbits(sc, MII_COMMAND_START, 2); in smsc_miibus_readreg()
214 smsc_miibus_sendbits(sc, MII_COMMAND_READ, 2); in smsc_miibus_readreg()
215 smsc_miibus_sendbits(sc, phy, 5); in smsc_miibus_readreg()
216 smsc_miibus_sendbits(sc, reg, 5); in smsc_miibus_readreg()
218 /* Switch direction to PHY -> host */ in smsc_miibus_readreg()
219 smsc_mii_bitbang_write(sc, MDIRHOST); in smsc_miibus_readreg()
220 smsc_mii_bitbang_write(sc, MDIRHOST | MDC); in smsc_miibus_readreg()
221 smsc_mii_bitbang_write(sc, MDIRHOST); in smsc_miibus_readreg()
224 err = smsc_mii_bitbang_read(sc) & MDI; in smsc_miibus_readreg()
227 smsc_mii_bitbang_write(sc, MDIRHOST | MDC); in smsc_miibus_readreg()
228 smsc_mii_bitbang_write(sc, MDIRHOST); in smsc_miibus_readreg()
233 /* Read data prior to clock low-high transition. */ in smsc_miibus_readreg()
234 if (err == 0 && (smsc_mii_bitbang_read(sc) & MDI) != 0) { in smsc_miibus_readreg()
238 smsc_mii_bitbang_write(sc, MDIRHOST | MDC); in smsc_miibus_readreg()
239 smsc_mii_bitbang_write(sc, MDIRHOST); in smsc_miibus_readreg()
242 /* Set direction to host -> PHY, without a clock transition. */ in smsc_miibus_readreg()
243 smsc_mii_bitbang_write(sc, MDIRPHY); in smsc_miibus_readreg()
245 SMSC_UNLOCK(sc); in smsc_miibus_readreg()
246 irq_enable(sc->irq); in smsc_miibus_readreg()
251 static void smsc_miibus_writereg(struct smsc_data *sc, int phy, int reg, uint16_t val) in smsc_miibus_writereg() argument
253 irq_disable(sc->irq); in smsc_miibus_writereg()
254 SMSC_LOCK(sc); in smsc_miibus_writereg()
256 smsc_select_bank(sc, 3); in smsc_miibus_writereg()
258 smsc_miibus_sync(sc); in smsc_miibus_writereg()
260 smsc_miibus_sendbits(sc, MII_COMMAND_START, 2); in smsc_miibus_writereg()
261 smsc_miibus_sendbits(sc, MII_COMMAND_WRITE, 2); in smsc_miibus_writereg()
262 smsc_miibus_sendbits(sc, phy, 5); in smsc_miibus_writereg()
263 smsc_miibus_sendbits(sc, reg, 5); in smsc_miibus_writereg()
264 smsc_miibus_sendbits(sc, MII_COMMAND_ACK, 2); in smsc_miibus_writereg()
265 smsc_miibus_sendbits(sc, val, 16); in smsc_miibus_writereg()
267 smsc_mii_bitbang_write(sc, MDIRPHY); in smsc_miibus_writereg()
269 SMSC_UNLOCK(sc); in smsc_miibus_writereg()
270 irq_enable(sc->irq); in smsc_miibus_writereg()
273 static void smsc_reset(struct smsc_data *sc) in smsc_reset() argument
280 smsc_select_bank(sc, 2); in smsc_reset()
281 smsc_write_1(sc, MSK, 0); in smsc_reset()
286 smsc_select_bank(sc, 0); in smsc_reset()
287 smsc_write_2(sc, RCR, RCR_SOFT_RST); in smsc_reset()
292 smsc_select_bank(sc, 1); in smsc_reset()
293 smsc_write_2(sc, CR, CR_EPH_POWER_EN); in smsc_reset()
299 smsc_select_bank(sc, 0); in smsc_reset()
300 smsc_write_2(sc, TCR, 0); in smsc_reset()
301 smsc_write_2(sc, RCR, 0); in smsc_reset()
306 smsc_select_bank(sc, 1); in smsc_reset()
307 ctr = smsc_read_2(sc, CTR); in smsc_reset()
309 smsc_write_2(sc, CTR, ctr); in smsc_reset()
314 smsc_select_bank(sc, 2); in smsc_reset()
315 smsc_mmu_wait(sc); in smsc_reset()
316 smsc_write_2(sc, MMUCR, FIELD_PREP(MMUCR_CMD_MASK, MMUCR_CMD_MMU_RESET)); in smsc_reset()
317 smsc_mmu_wait(sc); in smsc_reset()
320 static void smsc_enable(struct smsc_data *sc) in smsc_enable() argument
325 smsc_select_bank(sc, 0); in smsc_enable()
326 smsc_write_2(sc, RPCR, in smsc_enable()
334 smsc_write_2(sc, TCR, TCR_TXENA | TCR_PAD_EN); in smsc_enable()
335 smsc_write_2(sc, RCR, RCR_RXEN | RCR_STRIP_CRC); in smsc_enable()
340 smsc_select_bank(sc, 2); in smsc_enable()
341 smsc_write_1(sc, ACK, 0); in smsc_enable()
346 smsc_select_bank(sc, 2); in smsc_enable()
347 sc->smsc_mask = RCV_INT; in smsc_enable()
348 smsc_write_1(sc, MSK, sc->smsc_mask); in smsc_enable()
351 static int smsc_check(struct smsc_data *sc) in smsc_check() argument
355 val = smsc_read_2(sc, BSR); in smsc_check()
358 return -ENODEV; in smsc_check()
361 smsc_write_2(sc, BSR, 0); in smsc_check()
362 val = smsc_read_2(sc, BSR); in smsc_check()
365 return -ENODEV; in smsc_check()
368 smsc_select_bank(sc, 3); in smsc_check()
369 val = smsc_read_2(sc, REV); in smsc_check()
373 return -ENODEV; in smsc_check()
383 struct smsc_data *sc = &data->sc; in smsc_recv_pkt() local
387 smsc_select_bank(sc, 2); in smsc_recv_pkt()
388 packet = smsc_read_1(sc, FIFO_RX); in smsc_recv_pkt()
393 smsc_select_bank(sc, 2); in smsc_recv_pkt()
394 smsc_write_1(sc, PNR, packet); in smsc_recv_pkt()
395 smsc_write_2(sc, PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR); in smsc_recv_pkt()
400 status = smsc_read_2(sc, DATA0); in smsc_recv_pkt()
401 val16 = smsc_read_2(sc, DATA0); in smsc_recv_pkt()
406 len -= PKT_CTRL_DATA_LEN; in smsc_recv_pkt()
427 smsc_select_bank(sc, 2); in smsc_recv_pkt()
428 smsc_write_1(sc, PNR, packet); in smsc_recv_pkt()
434 smsc_write_2(sc, PTR, 4 | PTR_READ | PTR_RCV | PTR_AUTO_INCR); in smsc_recv_pkt()
435 smsc_read_multi_2(sc, DATA0, (uint16_t *)rx_buffer, len / 2); in smsc_recv_pkt()
437 rx_buffer[len - 1] = smsc_read_1(sc, DATA0); in smsc_recv_pkt()
440 pkt = net_pkt_rx_alloc_with_buffer(data->iface, len, AF_UNSPEC, 0, in smsc_recv_pkt()
454 ret = net_recv_data(data->iface, pkt); in smsc_recv_pkt()
465 smsc_mmu_wait(sc); in smsc_recv_pkt()
466 smsc_write_2(sc, MMUCR, FIELD_PREP(MMUCR_CMD_MASK, MMUCR_CMD_RELEASE)); in smsc_recv_pkt()
467 smsc_mmu_wait(sc); in smsc_recv_pkt()
469 packet = smsc_read_1(sc, FIFO_RX); in smsc_recv_pkt()
472 sc->smsc_mask |= RCV_INT; in smsc_recv_pkt()
473 smsc_write_1(sc, MSK, sc->smsc_mask); in smsc_recv_pkt()
476 static int smsc_send_pkt(struct smsc_data *sc, uint8_t *buf, uint16_t len) in smsc_send_pkt() argument
481 SMSC_LOCK(sc); in smsc_send_pkt()
485 smsc_select_bank(sc, 2); in smsc_send_pkt()
486 smsc_mmu_wait(sc); in smsc_send_pkt()
487 smsc_write_2(sc, MMUCR, FIELD_PREP(MMUCR_CMD_MASK, MMUCR_CMD_TX_ALLOC)); in smsc_send_pkt()
492 for (polling_count = TX_ALLOC_WAIT_TIME; polling_count > 0; polling_count--) { in smsc_send_pkt()
493 if (smsc_read_1(sc, IST) & ALLOC_INT) { in smsc_send_pkt()
501 SMSC_UNLOCK(sc); in smsc_send_pkt()
503 return -1; in smsc_send_pkt()
506 packet = smsc_read_1(sc, ARR); in smsc_send_pkt()
508 SMSC_UNLOCK(sc); in smsc_send_pkt()
510 return -1; in smsc_send_pkt()
516 smsc_write_1(sc, PNR, packet); in smsc_send_pkt()
517 smsc_write_2(sc, PTR, PTR_AUTO_INCR); in smsc_send_pkt()
522 smsc_write_2(sc, DATA0, 0); in smsc_send_pkt()
523 smsc_write_2(sc, DATA0, len + PKT_CTRL_DATA_LEN); in smsc_send_pkt()
524 smsc_write_multi_2(sc, DATA0, (uint16_t *)buf, len / 2); in smsc_send_pkt()
528 smsc_write_2(sc, DATA0, (CTRL_ODD << 8) | buf[len - 1]); in smsc_send_pkt()
530 smsc_write_2(sc, DATA0, 0); in smsc_send_pkt()
536 smsc_mmu_wait(sc); in smsc_send_pkt()
537 smsc_write_2(sc, MMUCR, FIELD_PREP(MMUCR_CMD_MASK, MMUCR_CMD_ENQUEUE)); in smsc_send_pkt()
542 sc->smsc_mask |= (TX_EMPTY_INT | TX_INT); in smsc_send_pkt()
543 smsc_write_1(sc, MSK, sc->smsc_mask); in smsc_send_pkt()
545 SMSC_UNLOCK(sc); in smsc_send_pkt()
555 struct smsc_data *sc = CONTAINER_OF(item, struct smsc_data, isr_work); in smsc_isr_task() local
556 struct eth_context *data = CONTAINER_OF(sc, struct eth_context, sc); in smsc_isr_task()
560 SMSC_LOCK(sc); in smsc_isr_task()
563 smsc_select_bank(sc, 0); in smsc_isr_task()
564 mem_info = smsc_read_2(sc, MIR); in smsc_isr_task()
566 smsc_select_bank(sc, 2); in smsc_isr_task()
567 status = smsc_read_1(sc, IST); in smsc_isr_task()
569 smsc_read_1(sc, MSK), mem_info, smsc_read_2(sc, FIFO)); in smsc_isr_task()
571 status &= sc->smsc_mask; in smsc_isr_task()
583 packet = smsc_read_1(sc, FIFO_TX); in smsc_isr_task()
585 smsc_select_bank(sc, 2); in smsc_isr_task()
586 smsc_write_1(sc, PNR, packet); in smsc_isr_task()
587 smsc_write_2(sc, PTR, PTR_READ | PTR_AUTO_INCR); in smsc_isr_task()
589 smsc_select_bank(sc, 0); in smsc_isr_task()
590 ephsr = smsc_read_2(sc, EPHSR); in smsc_isr_task()
596 smsc_select_bank(sc, 2); in smsc_isr_task()
597 smsc_mmu_wait(sc); in smsc_isr_task()
598 smsc_write_2(sc, MMUCR, in smsc_isr_task()
601 smsc_select_bank(sc, 0); in smsc_isr_task()
602 tcr = smsc_read_2(sc, TCR); in smsc_isr_task()
604 smsc_write_2(sc, TCR, tcr); in smsc_isr_task()
610 smsc_select_bank(sc, 2); in smsc_isr_task()
611 smsc_write_1(sc, ACK, TX_INT); in smsc_isr_task()
618 smsc_write_1(sc, ACK, RCV_INT); in smsc_isr_task()
626 smsc_write_1(sc, ACK, TX_EMPTY_INT); in smsc_isr_task()
627 sc->smsc_mask &= ~TX_EMPTY_INT; in smsc_isr_task()
631 smsc_select_bank(sc, 2); in smsc_isr_task()
632 smsc_write_1(sc, MSK, sc->smsc_mask); in smsc_isr_task()
634 SMSC_UNLOCK(sc); in smsc_isr_task()
637 static int smsc_init(struct smsc_data *sc) in smsc_init() argument
642 ret = smsc_check(sc); in smsc_init()
647 SMSC_LOCK(sc); in smsc_init()
648 smsc_reset(sc); in smsc_init()
649 SMSC_UNLOCK(sc); in smsc_init()
651 smsc_select_bank(sc, 3); in smsc_init()
652 val = smsc_read_2(sc, REV); in smsc_init()
653 sc->smsc_chip = FIELD_GET(REV_CHIP_MASK, val); in smsc_init()
654 sc->smsc_rev = FIELD_GET(REV_REV_MASK, val); in smsc_init()
656 smsc_select_bank(sc, 1); in smsc_init()
657 sc->mac[0] = smsc_read_1(sc, IAR0); in smsc_init()
658 sc->mac[1] = smsc_read_1(sc, IAR1); in smsc_init()
659 sc->mac[2] = smsc_read_1(sc, IAR2); in smsc_init()
660 sc->mac[3] = smsc_read_1(sc, IAR3); in smsc_init()
661 sc->mac[4] = smsc_read_1(sc, IAR4); in smsc_init()
662 sc->mac[5] = smsc_read_1(sc, IAR5); in smsc_init()
669 const struct eth_config *cfg = dev->config; in eth_get_phy()
671 return cfg->phy_dev; in eth_get_phy()
678 struct eth_context *data = dev->data; in phy_link_state_changed()
680 if (state->is_up) { in phy_link_state_changed()
681 net_eth_carrier_on(data->iface); in phy_link_state_changed()
683 net_eth_carrier_off(data->iface); in phy_link_state_changed()
701 struct eth_context *data = dev->data; in eth_tx()
702 struct smsc_data *sc = &data->sc; in eth_tx() local
708 return -1; in eth_tx()
711 return smsc_send_pkt(sc, tx_buffer, len); in eth_tx()
723 struct eth_context *data = dev->data; in eth_smsc_set_config()
724 struct smsc_data *sc = &data->sc; in eth_smsc_set_config() local
727 SMSC_LOCK(sc); in eth_smsc_set_config()
728 smsc_select_bank(sc, 0); in eth_smsc_set_config()
729 reg_val = smsc_read_1(sc, RCR); in eth_smsc_set_config()
730 if (config->promisc_mode && !(reg_val & RCR_PRMS)) { in eth_smsc_set_config()
731 smsc_write_1(sc, RCR, reg_val | RCR_PRMS); in eth_smsc_set_config()
732 } else if (!config->promisc_mode && (reg_val & RCR_PRMS)) { in eth_smsc_set_config()
733 smsc_write_1(sc, RCR, reg_val & ~RCR_PRMS); in eth_smsc_set_config()
735 ret = -EALREADY; in eth_smsc_set_config()
737 SMSC_UNLOCK(sc); in eth_smsc_set_config()
742 ret = -ENOTSUP; in eth_smsc_set_config()
752 struct eth_context *data = dev->data; in eth_initialize()
753 const struct eth_config *cfg = dev->config; in eth_initialize()
754 const struct device *phy_dev = cfg->phy_dev; in eth_initialize()
755 struct smsc_data *sc = &data->sc; in eth_initialize() local
761 smsc_reset(sc); in eth_initialize()
762 smsc_enable(sc); in eth_initialize()
764 LOG_INF("MAC %02x:%02x:%02x:%02x:%02x:%02x", sc->mac[0], sc->mac[1], sc->mac[2], sc->mac[3], in eth_initialize()
765 sc->mac[4], sc->mac[5]); in eth_initialize()
767 net_if_set_link_addr(iface, sc->mac, sizeof(sc->mac), NET_LINK_ETHERNET); in eth_initialize()
768 data->iface = iface; in eth_initialize()
787 struct eth_context *data = dev->data; in eth_smsc_isr()
788 struct smsc_data *sc = &data->sc; in eth_smsc_isr() local
791 curbank = smsc_current_bank(sc); in eth_smsc_isr()
796 smsc_select_bank(sc, 2); in eth_smsc_isr()
797 smsc_write_1(sc, MSK, 0); in eth_smsc_isr()
799 smsc_select_bank(sc, curbank); in eth_smsc_isr()
800 k_work_submit(&(sc->isr_work)); in eth_smsc_isr()
805 struct eth_context *data = (struct eth_context *)dev->data; in eth_init()
806 struct smsc_data *sc = &data->sc; in eth_init() local
809 ret = k_mutex_init(&sc->lock); in eth_init()
814 k_work_init(&sc->isr_work, smsc_isr_task); in eth_init()
820 sc->smsc_reg = DEVICE_MMIO_GET(dev); in eth_init()
821 sc->irq = DT_INST_IRQN(0); in eth_init()
823 smsc_init(sc); in eth_init()
861 const struct mdio_smsc_config *cfg = dev->config; in mdio_smsc_read()
862 const struct device *eth_dev = cfg->eth_dev; in mdio_smsc_read()
863 struct eth_context *eth_data = eth_dev->data; in mdio_smsc_read()
864 struct smsc_data *sc = ð_data->sc; in mdio_smsc_read() local
866 *data = smsc_miibus_readreg(sc, prtad, devad); in mdio_smsc_read()
873 const struct mdio_smsc_config *cfg = dev->config; in mdio_smsc_write()
874 const struct device *eth_dev = cfg->eth_dev; in mdio_smsc_write()
875 struct eth_context *eth_data = eth_dev->data; in mdio_smsc_write()
876 struct smsc_data *sc = ð_data->sc; in mdio_smsc_write() local
878 smsc_miibus_writereg(sc, prtad, devad, data); in mdio_smsc_write()