Lines Matching full:tc6
14 /* OPEN Alliance TC6 registers */
159 static int oa_tc6_spi_transfer(struct oa_tc6 *tc6, in oa_tc6_spi_transfer() argument
166 xfer.tx_buf = tc6->spi_data_tx_buf; in oa_tc6_spi_transfer()
167 xfer.rx_buf = tc6->spi_data_rx_buf; in oa_tc6_spi_transfer()
169 xfer.tx_buf = tc6->spi_ctrl_tx_buf; in oa_tc6_spi_transfer()
170 xfer.rx_buf = tc6->spi_ctrl_rx_buf; in oa_tc6_spi_transfer()
177 return spi_sync(tc6->spi, &msg); in oa_tc6_spi_transfer()
210 static void oa_tc6_update_ctrl_write_data(struct oa_tc6 *tc6, u32 value[], in oa_tc6_update_ctrl_write_data() argument
213 __be32 *tx_buf = tc6->spi_ctrl_tx_buf + OA_TC6_CTRL_HEADER_SIZE; in oa_tc6_update_ctrl_write_data()
228 static void oa_tc6_prepare_ctrl_spi_buf(struct oa_tc6 *tc6, u32 address, in oa_tc6_prepare_ctrl_spi_buf() argument
232 __be32 *tx_buf = tc6->spi_ctrl_tx_buf; in oa_tc6_prepare_ctrl_spi_buf()
237 oa_tc6_update_ctrl_write_data(tc6, value, length); in oa_tc6_prepare_ctrl_spi_buf()
240 static int oa_tc6_check_ctrl_write_reply(struct oa_tc6 *tc6, u8 size) in oa_tc6_check_ctrl_write_reply() argument
242 u8 *tx_buf = tc6->spi_ctrl_tx_buf; in oa_tc6_check_ctrl_write_reply()
243 u8 *rx_buf = tc6->spi_ctrl_rx_buf; in oa_tc6_check_ctrl_write_reply()
256 static int oa_tc6_check_ctrl_read_reply(struct oa_tc6 *tc6, u8 size) in oa_tc6_check_ctrl_read_reply() argument
258 u32 *rx_buf = tc6->spi_ctrl_rx_buf + OA_TC6_CTRL_IGNORED_SIZE; in oa_tc6_check_ctrl_read_reply()
259 u32 *tx_buf = tc6->spi_ctrl_tx_buf; in oa_tc6_check_ctrl_read_reply()
270 static void oa_tc6_copy_ctrl_read_data(struct oa_tc6 *tc6, u32 value[], in oa_tc6_copy_ctrl_read_data() argument
273 __be32 *rx_buf = tc6->spi_ctrl_rx_buf + OA_TC6_CTRL_IGNORED_SIZE + in oa_tc6_copy_ctrl_read_data()
280 static int oa_tc6_perform_ctrl(struct oa_tc6 *tc6, u32 address, u32 value[], in oa_tc6_perform_ctrl() argument
287 oa_tc6_prepare_ctrl_spi_buf(tc6, address, value, length, reg_op); in oa_tc6_perform_ctrl()
292 ret = oa_tc6_spi_transfer(tc6, OA_TC6_CTRL_HEADER, size); in oa_tc6_perform_ctrl()
294 dev_err(&tc6->spi->dev, "SPI transfer failed for control: %d\n", in oa_tc6_perform_ctrl()
301 return oa_tc6_check_ctrl_write_reply(tc6, size); in oa_tc6_perform_ctrl()
304 ret = oa_tc6_check_ctrl_read_reply(tc6, size); in oa_tc6_perform_ctrl()
308 oa_tc6_copy_ctrl_read_data(tc6, value, length); in oa_tc6_perform_ctrl()
315 * @tc6: oa_tc6 struct.
324 int oa_tc6_read_registers(struct oa_tc6 *tc6, u32 address, u32 value[], in oa_tc6_read_registers() argument
330 dev_err(&tc6->spi->dev, "Invalid register length parameter\n"); in oa_tc6_read_registers()
334 mutex_lock(&tc6->spi_ctrl_lock); in oa_tc6_read_registers()
335 ret = oa_tc6_perform_ctrl(tc6, address, value, length, in oa_tc6_read_registers()
337 mutex_unlock(&tc6->spi_ctrl_lock); in oa_tc6_read_registers()
345 * @tc6: oa_tc6 struct.
351 int oa_tc6_read_register(struct oa_tc6 *tc6, u32 address, u32 *value) in oa_tc6_read_register() argument
353 return oa_tc6_read_registers(tc6, address, value, 1); in oa_tc6_read_register()
359 * @tc6: oa_tc6 struct.
368 int oa_tc6_write_registers(struct oa_tc6 *tc6, u32 address, u32 value[], in oa_tc6_write_registers() argument
374 dev_err(&tc6->spi->dev, "Invalid register length parameter\n"); in oa_tc6_write_registers()
378 mutex_lock(&tc6->spi_ctrl_lock); in oa_tc6_write_registers()
379 ret = oa_tc6_perform_ctrl(tc6, address, value, length, in oa_tc6_write_registers()
381 mutex_unlock(&tc6->spi_ctrl_lock); in oa_tc6_write_registers()
389 * @tc6: oa_tc6 struct.
395 int oa_tc6_write_register(struct oa_tc6 *tc6, u32 address, u32 value) in oa_tc6_write_register() argument
397 return oa_tc6_write_registers(tc6, address, &value, 1); in oa_tc6_write_register()
401 static int oa_tc6_check_phy_reg_direct_access_capability(struct oa_tc6 *tc6) in oa_tc6_check_phy_reg_direct_access_capability() argument
406 ret = oa_tc6_read_register(tc6, OA_TC6_REG_STDCAP, ®val); in oa_tc6_check_phy_reg_direct_access_capability()
423 struct oa_tc6 *tc6 = bus->priv; in oa_tc6_mdiobus_read() local
427 ret = oa_tc6_read_register(tc6, OA_TC6_PHY_STD_REG_ADDR_BASE | in oa_tc6_mdiobus_read()
439 struct oa_tc6 *tc6 = bus->priv; in oa_tc6_mdiobus_write() local
441 return oa_tc6_write_register(tc6, OA_TC6_PHY_STD_REG_ADDR_BASE | in oa_tc6_mdiobus_write()
467 struct oa_tc6 *tc6 = bus->priv; in oa_tc6_mdiobus_read_c45() local
475 ret = oa_tc6_read_register(tc6, (ret << 16) | regnum, ®val); in oa_tc6_mdiobus_read_c45()
485 struct oa_tc6 *tc6 = bus->priv; in oa_tc6_mdiobus_write_c45() local
492 return oa_tc6_write_register(tc6, (ret << 16) | regnum, val); in oa_tc6_mdiobus_write_c45()
495 static int oa_tc6_mdiobus_register(struct oa_tc6 *tc6) in oa_tc6_mdiobus_register() argument
499 tc6->mdiobus = mdiobus_alloc(); in oa_tc6_mdiobus_register()
500 if (!tc6->mdiobus) { in oa_tc6_mdiobus_register()
501 netdev_err(tc6->netdev, "MDIO bus alloc failed\n"); in oa_tc6_mdiobus_register()
505 tc6->mdiobus->priv = tc6; in oa_tc6_mdiobus_register()
506 tc6->mdiobus->read = oa_tc6_mdiobus_read; in oa_tc6_mdiobus_register()
507 tc6->mdiobus->write = oa_tc6_mdiobus_write; in oa_tc6_mdiobus_register()
518 tc6->mdiobus->read_c45 = oa_tc6_mdiobus_read_c45; in oa_tc6_mdiobus_register()
519 tc6->mdiobus->write_c45 = oa_tc6_mdiobus_write_c45; in oa_tc6_mdiobus_register()
520 tc6->mdiobus->name = "oa-tc6-mdiobus"; in oa_tc6_mdiobus_register()
521 tc6->mdiobus->parent = tc6->dev; in oa_tc6_mdiobus_register()
523 snprintf(tc6->mdiobus->id, ARRAY_SIZE(tc6->mdiobus->id), "%s", in oa_tc6_mdiobus_register()
524 dev_name(&tc6->spi->dev)); in oa_tc6_mdiobus_register()
526 ret = mdiobus_register(tc6->mdiobus); in oa_tc6_mdiobus_register()
528 netdev_err(tc6->netdev, "Could not register MDIO bus\n"); in oa_tc6_mdiobus_register()
529 mdiobus_free(tc6->mdiobus); in oa_tc6_mdiobus_register()
536 static void oa_tc6_mdiobus_unregister(struct oa_tc6 *tc6) in oa_tc6_mdiobus_unregister() argument
538 mdiobus_unregister(tc6->mdiobus); in oa_tc6_mdiobus_unregister()
539 mdiobus_free(tc6->mdiobus); in oa_tc6_mdiobus_unregister()
542 static int oa_tc6_phy_init(struct oa_tc6 *tc6) in oa_tc6_phy_init() argument
546 ret = oa_tc6_check_phy_reg_direct_access_capability(tc6); in oa_tc6_phy_init()
548 netdev_err(tc6->netdev, in oa_tc6_phy_init()
553 ret = oa_tc6_mdiobus_register(tc6); in oa_tc6_phy_init()
557 tc6->phydev = phy_find_first(tc6->mdiobus); in oa_tc6_phy_init()
558 if (!tc6->phydev) { in oa_tc6_phy_init()
559 netdev_err(tc6->netdev, "No PHY found\n"); in oa_tc6_phy_init()
560 oa_tc6_mdiobus_unregister(tc6); in oa_tc6_phy_init()
564 tc6->phydev->is_internal = true; in oa_tc6_phy_init()
565 ret = phy_connect_direct(tc6->netdev, tc6->phydev, in oa_tc6_phy_init()
569 netdev_err(tc6->netdev, "Can't attach PHY to %s\n", in oa_tc6_phy_init()
570 tc6->mdiobus->id); in oa_tc6_phy_init()
571 oa_tc6_mdiobus_unregister(tc6); in oa_tc6_phy_init()
575 phy_attached_info(tc6->netdev->phydev); in oa_tc6_phy_init()
580 static void oa_tc6_phy_exit(struct oa_tc6 *tc6) in oa_tc6_phy_exit() argument
582 phy_disconnect(tc6->phydev); in oa_tc6_phy_exit()
583 oa_tc6_mdiobus_unregister(tc6); in oa_tc6_phy_exit()
586 static int oa_tc6_read_status0(struct oa_tc6 *tc6) in oa_tc6_read_status0() argument
591 ret = oa_tc6_read_register(tc6, OA_TC6_REG_STATUS0, ®val); in oa_tc6_read_status0()
593 dev_err(&tc6->spi->dev, "STATUS0 register read failed: %d\n", in oa_tc6_read_status0()
601 static int oa_tc6_sw_reset_macphy(struct oa_tc6 *tc6) in oa_tc6_sw_reset_macphy() argument
606 ret = oa_tc6_write_register(tc6, OA_TC6_REG_RESET, regval); in oa_tc6_sw_reset_macphy()
611 ret = readx_poll_timeout(oa_tc6_read_status0, tc6, regval, in oa_tc6_sw_reset_macphy()
619 return oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, regval); in oa_tc6_sw_reset_macphy()
622 static int oa_tc6_unmask_macphy_error_interrupts(struct oa_tc6 *tc6) in oa_tc6_unmask_macphy_error_interrupts() argument
627 ret = oa_tc6_read_register(tc6, OA_TC6_REG_INT_MASK0, ®val); in oa_tc6_unmask_macphy_error_interrupts()
636 return oa_tc6_write_register(tc6, OA_TC6_REG_INT_MASK0, regval); in oa_tc6_unmask_macphy_error_interrupts()
639 static int oa_tc6_enable_data_transfer(struct oa_tc6 *tc6) in oa_tc6_enable_data_transfer() argument
644 ret = oa_tc6_read_register(tc6, OA_TC6_REG_CONFIG0, &value); in oa_tc6_enable_data_transfer()
651 return oa_tc6_write_register(tc6, OA_TC6_REG_CONFIG0, value); in oa_tc6_enable_data_transfer()
654 static void oa_tc6_cleanup_ongoing_rx_skb(struct oa_tc6 *tc6) in oa_tc6_cleanup_ongoing_rx_skb() argument
656 if (tc6->rx_skb) { in oa_tc6_cleanup_ongoing_rx_skb()
657 tc6->netdev->stats.rx_dropped++; in oa_tc6_cleanup_ongoing_rx_skb()
658 kfree_skb(tc6->rx_skb); in oa_tc6_cleanup_ongoing_rx_skb()
659 tc6->rx_skb = NULL; in oa_tc6_cleanup_ongoing_rx_skb()
663 static void oa_tc6_cleanup_ongoing_tx_skb(struct oa_tc6 *tc6) in oa_tc6_cleanup_ongoing_tx_skb() argument
665 if (tc6->ongoing_tx_skb) { in oa_tc6_cleanup_ongoing_tx_skb()
666 tc6->netdev->stats.tx_dropped++; in oa_tc6_cleanup_ongoing_tx_skb()
667 kfree_skb(tc6->ongoing_tx_skb); in oa_tc6_cleanup_ongoing_tx_skb()
668 tc6->ongoing_tx_skb = NULL; in oa_tc6_cleanup_ongoing_tx_skb()
672 static int oa_tc6_process_extended_status(struct oa_tc6 *tc6) in oa_tc6_process_extended_status() argument
677 ret = oa_tc6_read_register(tc6, OA_TC6_REG_STATUS0, &value); in oa_tc6_process_extended_status()
679 netdev_err(tc6->netdev, "STATUS0 register read failed: %d\n", in oa_tc6_process_extended_status()
685 ret = oa_tc6_write_register(tc6, OA_TC6_REG_STATUS0, value); in oa_tc6_process_extended_status()
687 netdev_err(tc6->netdev, "STATUS0 register write failed: %d\n", in oa_tc6_process_extended_status()
693 tc6->rx_buf_overflow = true; in oa_tc6_process_extended_status()
694 oa_tc6_cleanup_ongoing_rx_skb(tc6); in oa_tc6_process_extended_status()
696 tc6->netdev->name); in oa_tc6_process_extended_status()
700 netdev_err(tc6->netdev, "Transmit protocol error\n"); in oa_tc6_process_extended_status()
707 netdev_err(tc6->netdev, "Loss of frame error\n"); in oa_tc6_process_extended_status()
711 netdev_err(tc6->netdev, "Header error\n"); in oa_tc6_process_extended_status()
718 static int oa_tc6_process_rx_chunk_footer(struct oa_tc6 *tc6, u32 footer) in oa_tc6_process_rx_chunk_footer() argument
725 tc6->tx_credits = FIELD_GET(OA_TC6_DATA_FOOTER_TX_CREDITS, footer); in oa_tc6_process_rx_chunk_footer()
726 tc6->rx_chunks_available = FIELD_GET(OA_TC6_DATA_FOOTER_RX_CHUNKS, in oa_tc6_process_rx_chunk_footer()
730 int ret = oa_tc6_process_extended_status(tc6); in oa_tc6_process_rx_chunk_footer()
741 netdev_err(tc6->netdev, "Rxd header bad error\n"); in oa_tc6_process_rx_chunk_footer()
746 netdev_err(tc6->netdev, "Config unsync error\n"); in oa_tc6_process_rx_chunk_footer()
753 static void oa_tc6_submit_rx_skb(struct oa_tc6 *tc6) in oa_tc6_submit_rx_skb() argument
755 tc6->rx_skb->protocol = eth_type_trans(tc6->rx_skb, tc6->netdev); in oa_tc6_submit_rx_skb()
756 tc6->netdev->stats.rx_packets++; in oa_tc6_submit_rx_skb()
757 tc6->netdev->stats.rx_bytes += tc6->rx_skb->len; in oa_tc6_submit_rx_skb()
759 netif_rx(tc6->rx_skb); in oa_tc6_submit_rx_skb()
761 tc6->rx_skb = NULL; in oa_tc6_submit_rx_skb()
764 static void oa_tc6_update_rx_skb(struct oa_tc6 *tc6, u8 *payload, u8 length) in oa_tc6_update_rx_skb() argument
766 memcpy(skb_put(tc6->rx_skb, length), payload, length); in oa_tc6_update_rx_skb()
769 static int oa_tc6_allocate_rx_skb(struct oa_tc6 *tc6) in oa_tc6_allocate_rx_skb() argument
771 tc6->rx_skb = netdev_alloc_skb_ip_align(tc6->netdev, tc6->netdev->mtu + in oa_tc6_allocate_rx_skb()
773 if (!tc6->rx_skb) { in oa_tc6_allocate_rx_skb()
774 tc6->netdev->stats.rx_dropped++; in oa_tc6_allocate_rx_skb()
781 static int oa_tc6_prcs_complete_rx_frame(struct oa_tc6 *tc6, u8 *payload, in oa_tc6_prcs_complete_rx_frame() argument
786 ret = oa_tc6_allocate_rx_skb(tc6); in oa_tc6_prcs_complete_rx_frame()
790 oa_tc6_update_rx_skb(tc6, payload, size); in oa_tc6_prcs_complete_rx_frame()
792 oa_tc6_submit_rx_skb(tc6); in oa_tc6_prcs_complete_rx_frame()
797 static int oa_tc6_prcs_rx_frame_start(struct oa_tc6 *tc6, u8 *payload, u16 size) in oa_tc6_prcs_rx_frame_start() argument
801 ret = oa_tc6_allocate_rx_skb(tc6); in oa_tc6_prcs_rx_frame_start()
805 oa_tc6_update_rx_skb(tc6, payload, size); in oa_tc6_prcs_rx_frame_start()
810 static void oa_tc6_prcs_rx_frame_end(struct oa_tc6 *tc6, u8 *payload, u16 size) in oa_tc6_prcs_rx_frame_end() argument
812 oa_tc6_update_rx_skb(tc6, payload, size); in oa_tc6_prcs_rx_frame_end()
814 oa_tc6_submit_rx_skb(tc6); in oa_tc6_prcs_rx_frame_end()
817 static void oa_tc6_prcs_ongoing_rx_frame(struct oa_tc6 *tc6, u8 *payload, in oa_tc6_prcs_ongoing_rx_frame() argument
820 oa_tc6_update_rx_skb(tc6, payload, OA_TC6_CHUNK_PAYLOAD_SIZE); in oa_tc6_prcs_ongoing_rx_frame()
823 static int oa_tc6_prcs_rx_chunk_payload(struct oa_tc6 *tc6, u8 *data, in oa_tc6_prcs_rx_chunk_payload() argument
835 if (start_valid && tc6->rx_buf_overflow) in oa_tc6_prcs_rx_chunk_payload()
836 tc6->rx_buf_overflow = false; in oa_tc6_prcs_rx_chunk_payload()
838 if (tc6->rx_buf_overflow) in oa_tc6_prcs_rx_chunk_payload()
844 return oa_tc6_prcs_complete_rx_frame(tc6, in oa_tc6_prcs_rx_chunk_payload()
852 return oa_tc6_prcs_rx_frame_start(tc6, in oa_tc6_prcs_rx_chunk_payload()
860 oa_tc6_prcs_rx_frame_end(tc6, data, size); in oa_tc6_prcs_rx_chunk_payload()
872 if (tc6->rx_skb) { in oa_tc6_prcs_rx_chunk_payload()
874 oa_tc6_prcs_rx_frame_end(tc6, data, size); in oa_tc6_prcs_rx_chunk_payload()
877 return oa_tc6_prcs_rx_frame_start(tc6, in oa_tc6_prcs_rx_chunk_payload()
883 oa_tc6_prcs_ongoing_rx_frame(tc6, data, footer); in oa_tc6_prcs_rx_chunk_payload()
888 static u32 oa_tc6_get_rx_chunk_footer(struct oa_tc6 *tc6, u16 footer_offset) in oa_tc6_get_rx_chunk_footer() argument
890 u8 *rx_buf = tc6->spi_data_rx_buf; in oa_tc6_get_rx_chunk_footer()
898 static int oa_tc6_process_spi_data_rx_buf(struct oa_tc6 *tc6, u16 length) in oa_tc6_process_spi_data_rx_buf() argument
907 footer = oa_tc6_get_rx_chunk_footer(tc6, i * OA_TC6_CHUNK_SIZE + in oa_tc6_process_spi_data_rx_buf()
910 ret = oa_tc6_process_rx_chunk_footer(tc6, footer); in oa_tc6_process_spi_data_rx_buf()
919 u8 *payload = tc6->spi_data_rx_buf + i * in oa_tc6_process_spi_data_rx_buf()
922 ret = oa_tc6_prcs_rx_chunk_payload(tc6, payload, in oa_tc6_process_spi_data_rx_buf()
949 static void oa_tc6_add_tx_skb_to_spi_buf(struct oa_tc6 *tc6) in oa_tc6_add_tx_skb_to_spi_buf() argument
952 __be32 *tx_buf = tc6->spi_data_tx_buf + tc6->spi_data_tx_buf_offset; in oa_tc6_add_tx_skb_to_spi_buf()
953 u16 remaining_len = tc6->ongoing_tx_skb->len - tc6->tx_skb_offset; in oa_tc6_add_tx_skb_to_spi_buf()
954 u8 *tx_skb_data = tc6->ongoing_tx_skb->data + tc6->tx_skb_offset; in oa_tc6_add_tx_skb_to_spi_buf()
967 if (!tc6->tx_skb_offset) in oa_tc6_add_tx_skb_to_spi_buf()
978 tc6->tx_skb_offset += length_to_copy; in oa_tc6_add_tx_skb_to_spi_buf()
983 if (tc6->ongoing_tx_skb->len == tc6->tx_skb_offset) { in oa_tc6_add_tx_skb_to_spi_buf()
986 tc6->tx_skb_offset = 0; in oa_tc6_add_tx_skb_to_spi_buf()
987 tc6->netdev->stats.tx_bytes += tc6->ongoing_tx_skb->len; in oa_tc6_add_tx_skb_to_spi_buf()
988 tc6->netdev->stats.tx_packets++; in oa_tc6_add_tx_skb_to_spi_buf()
989 kfree_skb(tc6->ongoing_tx_skb); in oa_tc6_add_tx_skb_to_spi_buf()
990 tc6->ongoing_tx_skb = NULL; in oa_tc6_add_tx_skb_to_spi_buf()
995 tc6->spi_data_tx_buf_offset += OA_TC6_CHUNK_SIZE; in oa_tc6_add_tx_skb_to_spi_buf()
998 static u16 oa_tc6_prepare_spi_tx_buf_for_tx_skbs(struct oa_tc6 *tc6) in oa_tc6_prepare_spi_tx_buf_for_tx_skbs() argument
1005 for (used_tx_credits = 0; used_tx_credits < tc6->tx_credits; in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1007 if (!tc6->ongoing_tx_skb) { in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1008 spin_lock_bh(&tc6->tx_skb_lock); in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1009 tc6->ongoing_tx_skb = tc6->waiting_tx_skb; in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1010 tc6->waiting_tx_skb = NULL; in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1011 spin_unlock_bh(&tc6->tx_skb_lock); in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1013 if (!tc6->ongoing_tx_skb) in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1015 oa_tc6_add_tx_skb_to_spi_buf(tc6); in oa_tc6_prepare_spi_tx_buf_for_tx_skbs()
1021 static void oa_tc6_add_empty_chunks_to_spi_buf(struct oa_tc6 *tc6, in oa_tc6_add_empty_chunks_to_spi_buf() argument
1031 __be32 *tx_buf = tc6->spi_data_tx_buf + in oa_tc6_add_empty_chunks_to_spi_buf()
1032 tc6->spi_data_tx_buf_offset; in oa_tc6_add_empty_chunks_to_spi_buf()
1035 tc6->spi_data_tx_buf_offset += OA_TC6_CHUNK_SIZE; in oa_tc6_add_empty_chunks_to_spi_buf()
1039 static u16 oa_tc6_prepare_spi_tx_buf_for_rx_chunks(struct oa_tc6 *tc6, u16 len) in oa_tc6_prepare_spi_tx_buf_for_rx_chunks() argument
1048 if (tx_chunks >= tc6->rx_chunks_available) in oa_tc6_prepare_spi_tx_buf_for_rx_chunks()
1051 needed_empty_chunks = tc6->rx_chunks_available - tx_chunks; in oa_tc6_prepare_spi_tx_buf_for_rx_chunks()
1053 oa_tc6_add_empty_chunks_to_spi_buf(tc6, needed_empty_chunks); in oa_tc6_prepare_spi_tx_buf_for_rx_chunks()
1058 static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6) in oa_tc6_try_spi_transfer() argument
1065 tc6->spi_data_tx_buf_offset = 0; in oa_tc6_try_spi_transfer()
1067 if (tc6->ongoing_tx_skb || tc6->waiting_tx_skb) in oa_tc6_try_spi_transfer()
1068 spi_len = oa_tc6_prepare_spi_tx_buf_for_tx_skbs(tc6); in oa_tc6_try_spi_transfer()
1070 spi_len = oa_tc6_prepare_spi_tx_buf_for_rx_chunks(tc6, spi_len); in oa_tc6_try_spi_transfer()
1072 if (tc6->int_flag) { in oa_tc6_try_spi_transfer()
1073 tc6->int_flag = false; in oa_tc6_try_spi_transfer()
1075 oa_tc6_add_empty_chunks_to_spi_buf(tc6, 1); in oa_tc6_try_spi_transfer()
1083 ret = oa_tc6_spi_transfer(tc6, OA_TC6_DATA_HEADER, spi_len); in oa_tc6_try_spi_transfer()
1085 netdev_err(tc6->netdev, "SPI data transfer failed: %d\n", in oa_tc6_try_spi_transfer()
1090 ret = oa_tc6_process_spi_data_rx_buf(tc6, spi_len); in oa_tc6_try_spi_transfer()
1095 oa_tc6_cleanup_ongoing_tx_skb(tc6); in oa_tc6_try_spi_transfer()
1096 oa_tc6_cleanup_ongoing_rx_skb(tc6); in oa_tc6_try_spi_transfer()
1097 netdev_err(tc6->netdev, "Device error: %d\n", ret); in oa_tc6_try_spi_transfer()
1101 if (!tc6->waiting_tx_skb && netif_queue_stopped(tc6->netdev)) in oa_tc6_try_spi_transfer()
1102 netif_wake_queue(tc6->netdev); in oa_tc6_try_spi_transfer()
1110 struct oa_tc6 *tc6 = data; in oa_tc6_spi_thread_handler() local
1117 wait_event_interruptible(tc6->spi_wq, tc6->int_flag || in oa_tc6_spi_thread_handler()
1118 (tc6->waiting_tx_skb && in oa_tc6_spi_thread_handler()
1119 tc6->tx_credits) || in oa_tc6_spi_thread_handler()
1125 ret = oa_tc6_try_spi_transfer(tc6); in oa_tc6_spi_thread_handler()
1133 static int oa_tc6_update_buffer_status_from_register(struct oa_tc6 *tc6) in oa_tc6_update_buffer_status_from_register() argument
1142 ret = oa_tc6_read_register(tc6, OA_TC6_REG_BUFFER_STATUS, &value); in oa_tc6_update_buffer_status_from_register()
1146 tc6->tx_credits = FIELD_GET(BUFFER_STATUS_TX_CREDITS_AVAILABLE, value); in oa_tc6_update_buffer_status_from_register()
1147 tc6->rx_chunks_available = FIELD_GET(BUFFER_STATUS_RX_CHUNKS_AVAILABLE, in oa_tc6_update_buffer_status_from_register()
1155 struct oa_tc6 *tc6 = data; in oa_tc6_macphy_isr() local
1164 tc6->int_flag = true; in oa_tc6_macphy_isr()
1166 wake_up_interruptible(&tc6->spi_wq); in oa_tc6_macphy_isr()
1174 * @tc6: oa_tc6 struct.
1178 int oa_tc6_zero_align_receive_frame_enable(struct oa_tc6 *tc6) in oa_tc6_zero_align_receive_frame_enable() argument
1183 ret = oa_tc6_read_register(tc6, OA_TC6_REG_CONFIG0, ®val); in oa_tc6_zero_align_receive_frame_enable()
1190 return oa_tc6_write_register(tc6, OA_TC6_REG_CONFIG0, regval); in oa_tc6_zero_align_receive_frame_enable()
1197 * @tc6: oa_tc6 struct.
1203 netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb) in oa_tc6_start_xmit() argument
1205 if (tc6->waiting_tx_skb) { in oa_tc6_start_xmit()
1206 netif_stop_queue(tc6->netdev); in oa_tc6_start_xmit()
1212 tc6->netdev->stats.tx_dropped++; in oa_tc6_start_xmit()
1216 spin_lock_bh(&tc6->tx_skb_lock); in oa_tc6_start_xmit()
1217 tc6->waiting_tx_skb = skb; in oa_tc6_start_xmit()
1218 spin_unlock_bh(&tc6->tx_skb_lock); in oa_tc6_start_xmit()
1221 wake_up_interruptible(&tc6->spi_wq); in oa_tc6_start_xmit()
1237 struct oa_tc6 *tc6; in oa_tc6_init() local
1240 tc6 = devm_kzalloc(&spi->dev, sizeof(*tc6), GFP_KERNEL); in oa_tc6_init()
1241 if (!tc6) in oa_tc6_init()
1244 tc6->spi = spi; in oa_tc6_init()
1245 tc6->netdev = netdev; in oa_tc6_init()
1247 mutex_init(&tc6->spi_ctrl_lock); in oa_tc6_init()
1248 spin_lock_init(&tc6->tx_skb_lock); in oa_tc6_init()
1251 tc6->spi->rt = true; in oa_tc6_init()
1252 spi_setup(tc6->spi); in oa_tc6_init()
1254 tc6->spi_ctrl_tx_buf = devm_kzalloc(&tc6->spi->dev, in oa_tc6_init()
1257 if (!tc6->spi_ctrl_tx_buf) in oa_tc6_init()
1260 tc6->spi_ctrl_rx_buf = devm_kzalloc(&tc6->spi->dev, in oa_tc6_init()
1263 if (!tc6->spi_ctrl_rx_buf) in oa_tc6_init()
1266 tc6->spi_data_tx_buf = devm_kzalloc(&tc6->spi->dev, in oa_tc6_init()
1269 if (!tc6->spi_data_tx_buf) in oa_tc6_init()
1272 tc6->spi_data_rx_buf = devm_kzalloc(&tc6->spi->dev, in oa_tc6_init()
1275 if (!tc6->spi_data_rx_buf) in oa_tc6_init()
1278 ret = oa_tc6_sw_reset_macphy(tc6); in oa_tc6_init()
1280 dev_err(&tc6->spi->dev, in oa_tc6_init()
1285 ret = oa_tc6_unmask_macphy_error_interrupts(tc6); in oa_tc6_init()
1287 dev_err(&tc6->spi->dev, in oa_tc6_init()
1292 ret = oa_tc6_phy_init(tc6); in oa_tc6_init()
1294 dev_err(&tc6->spi->dev, in oa_tc6_init()
1299 ret = oa_tc6_enable_data_transfer(tc6); in oa_tc6_init()
1301 dev_err(&tc6->spi->dev, "Failed to enable data transfer: %d\n", in oa_tc6_init()
1306 ret = oa_tc6_update_buffer_status_from_register(tc6); in oa_tc6_init()
1308 dev_err(&tc6->spi->dev, in oa_tc6_init()
1313 init_waitqueue_head(&tc6->spi_wq); in oa_tc6_init()
1315 tc6->spi_thread = kthread_run(oa_tc6_spi_thread_handler, tc6, in oa_tc6_init()
1316 "oa-tc6-spi-thread"); in oa_tc6_init()
1317 if (IS_ERR(tc6->spi_thread)) { in oa_tc6_init()
1318 dev_err(&tc6->spi->dev, "Failed to create SPI thread\n"); in oa_tc6_init()
1322 sched_set_fifo(tc6->spi_thread); in oa_tc6_init()
1324 ret = devm_request_irq(&tc6->spi->dev, tc6->spi->irq, oa_tc6_macphy_isr, in oa_tc6_init()
1325 IRQF_TRIGGER_FALLING, dev_name(&tc6->spi->dev), in oa_tc6_init()
1326 tc6); in oa_tc6_init()
1328 dev_err(&tc6->spi->dev, "Failed to request macphy isr %d\n", in oa_tc6_init()
1339 tc6->int_flag = true; in oa_tc6_init()
1340 wake_up_interruptible(&tc6->spi_wq); in oa_tc6_init()
1342 return tc6; in oa_tc6_init()
1345 kthread_stop(tc6->spi_thread); in oa_tc6_init()
1347 oa_tc6_phy_exit(tc6); in oa_tc6_init()
1354 * @tc6: oa_tc6 struct.
1356 void oa_tc6_exit(struct oa_tc6 *tc6) in oa_tc6_exit() argument
1358 oa_tc6_phy_exit(tc6); in oa_tc6_exit()
1359 kthread_stop(tc6->spi_thread); in oa_tc6_exit()
1360 dev_kfree_skb_any(tc6->ongoing_tx_skb); in oa_tc6_exit()
1361 dev_kfree_skb_any(tc6->waiting_tx_skb); in oa_tc6_exit()
1362 dev_kfree_skb_any(tc6->rx_skb); in oa_tc6_exit()