Lines Matching +full:role +full:- +full:switch +full:- +full:default +full:- +full:mode

7  * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "qemu/error-report.h"
14 #include "hw/i3c/dw-i3c.h"
16 #include "hw/qdev-properties.h"
242 FIELD(DEVICE_CTRL_EXTENDED, MODE, 0, 2)
297 /* Target mode is not supported, don't advertise it for now. */
368 return ARRAY_FIELD_EX32(s->regs, HW_CAPABILITY, HDR_TS); in dw_i3c_has_hdr_ts()
373 return ARRAY_FIELD_EX32(s->regs, HW_CAPABILITY, HDR_DDR); in dw_i3c_has_hdr_ddr()
382 return ARRAY_FIELD_EX32(s->regs, DEVICE_CTRL, I3C_EN) && in dw_i3c_can_transmit()
383 !ARRAY_FIELD_EX32(s->regs, DEVICE_CTRL, I3C_RESUME); in dw_i3c_can_transmit()
388 uint8_t ibi_slice_size = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_ibi_slice_size()
410 bool level = !!(s->regs[R_INTR_SIGNAL_EN] & s->regs[R_INTR_STATUS]); in dw_i3c_update_irq()
411 qemu_set_irq(s->irq, level); in dw_i3c_update_irq()
417 legacy_i2c_end_transfer(s->bus); in dw_i3c_end_transfer()
419 i3c_end_transfer(s->bus); in dw_i3c_end_transfer()
428 ret = legacy_i2c_start_transfer(s->bus, addr, is_recv); in dw_i3c_send_start()
430 ret = i3c_start_transfer(s->bus, addr, is_recv); in dw_i3c_send_start()
436 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_send_start()
438 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_send_start()
440 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ERR, 1); in dw_i3c_send_start()
441 ARRAY_FIELD_DP32(s->regs, DEVICE_CTRL, I3C_RESUME, 1); in dw_i3c_send_start()
455 /* Legacy I2C must be byte-by-byte. */ in dw_i3c_send()
457 ret = legacy_i2c_send(s->bus, data[i]); in dw_i3c_send()
464 ret = i3c_send(s->bus, data, num_to_send, num_sent); in dw_i3c_send()
470 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_send()
472 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_send()
474 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ERR, 1); in dw_i3c_send()
475 ARRAY_FIELD_DP32(s->regs, DEVICE_CTRL, I3C_RESUME, 1); in dw_i3c_send()
478 trace_dw_i3c_send(s->cfg.id, *num_sent); in dw_i3c_send()
500 data[i] = legacy_i2c_recv(s->bus); in dw_i3c_recv_data()
504 trace_dw_i3c_recv_data(s->cfg.id, *num_read); in dw_i3c_recv_data()
508 ret = i3c_recv(s->bus, data, num_to_read, num_read); in dw_i3c_recv_data()
512 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_recv_data()
514 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_recv_data()
516 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ERR, 1); in dw_i3c_recv_data()
517 ARRAY_FIELD_DP32(s->regs, DEVICE_CTRL, I3C_RESUME, 1); in dw_i3c_recv_data()
520 trace_dw_i3c_recv_data(s->cfg.id, *num_read); in dw_i3c_recv_data()
543 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ABORT, 1); in dw_i3c_ctrl_w()
547 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_ctrl_w()
549 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_ctrl_w()
552 s->regs[R_DEVICE_CTRL] = val; in dw_i3c_ctrl_w()
557 /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */ in dw_i3c_target_is_i2c()
558 uint16_t dev_index = (ARRAY_FIELD_EX32(s->regs, DEVICE_ADDR_TABLE_POINTER, in dw_i3c_target_is_i2c()
560 return FIELD_EX32(s->regs[dev_index], DEVICE_ADDR_TABLE_LOC1, in dw_i3c_target_is_i2c()
566 if (offset > s->cfg.num_addressable_devices) { in dw_i3c_target_addr()
574 /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */ in dw_i3c_target_addr()
575 uint16_t dev_index = (ARRAY_FIELD_EX32(s->regs, DEVICE_ADDR_TABLE_POINTER, in dw_i3c_target_addr()
579 return FIELD_EX32(s->regs[dev_index], DEVICE_ADDR_TABLE_LOC1, in dw_i3c_target_addr()
582 return FIELD_EX32(s->regs[dev_index], DEVICE_ADDR_TABLE_LOC1, in dw_i3c_target_addr()
588 uint8_t table_size = ARRAY_FIELD_EX32(s->regs, DEVICE_ADDR_TABLE_POINTER, in dw_i3c_addr_table_index_from_addr()
595 return -1; in dw_i3c_addr_table_index_from_addr()
601 if (s->ibi_data.send_direct_disec) { in dw_i3c_send_disec()
608 if (s->ibi_data.send_direct_disec) { in dw_i3c_send_disec()
609 dw_i3c_send_start(s, s->ibi_data.disec_addr, in dw_i3c_send_disec()
612 dw_i3c_send_byte(s, s->ibi_data.disec_byte, /*is_i2c=*/false); in dw_i3c_send_disec()
617 if (ARRAY_FIELD_EX32(s->regs, IBI_QUEUE_CTRL, NOTIFY_REJECTED_HOT_JOIN)) { in dw_i3c_handle_hj()
618 s->ibi_data.notify_ibi_nack = true; in dw_i3c_handle_hj()
621 bool nack_and_disable = ARRAY_FIELD_EX32(s->regs, DEVICE_CTRL, in dw_i3c_handle_hj()
624 s->ibi_data.ibi_queue_status = FIELD_DP32(s->ibi_data.ibi_queue_status, in dw_i3c_handle_hj()
627 s->ibi_data.ibi_nacked = true; in dw_i3c_handle_hj()
628 s->ibi_data.disec_byte = DISEC_HJ; in dw_i3c_handle_hj()
629 return -1; in dw_i3c_handle_hj()
636 if (ARRAY_FIELD_EX32(s->regs, IBI_QUEUE_CTRL, NOTIFY_REJECTED_MASTER_REQ)) { in dw_i3c_handle_ctlr_req()
637 s->ibi_data.notify_ibi_nack = true; in dw_i3c_handle_ctlr_req()
643 return -1; in dw_i3c_handle_ctlr_req()
646 /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */ in dw_i3c_handle_ctlr_req()
647 table_offset += (ARRAY_FIELD_EX32(s->regs, DEVICE_ADDR_TABLE_POINTER, in dw_i3c_handle_ctlr_req()
649 if (FIELD_EX32(s->regs[table_offset], DEVICE_ADDR_TABLE_LOC1, MR_REJECT)) { in dw_i3c_handle_ctlr_req()
650 s->ibi_data.ibi_queue_status = FIELD_DP32(s->ibi_data.ibi_queue_status, in dw_i3c_handle_ctlr_req()
653 s->ibi_data.ibi_nacked = true; in dw_i3c_handle_ctlr_req()
654 s->ibi_data.disec_addr = addr; in dw_i3c_handle_ctlr_req()
655 /* Tell the requester to disable controller role requests. */ in dw_i3c_handle_ctlr_req()
656 s->ibi_data.disec_byte = DISEC_CR; in dw_i3c_handle_ctlr_req()
657 s->ibi_data.send_direct_disec = true; in dw_i3c_handle_ctlr_req()
658 return -1; in dw_i3c_handle_ctlr_req()
665 if (ARRAY_FIELD_EX32(s->regs, IBI_QUEUE_CTRL, NOTIFY_REJECTED_SLAVE_IRQ)) { in dw_i3c_handle_targ_irq()
666 s->ibi_data.notify_ibi_nack = true; in dw_i3c_handle_targ_irq()
672 return -1; in dw_i3c_handle_targ_irq()
675 /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */ in dw_i3c_handle_targ_irq()
676 table_offset += (ARRAY_FIELD_EX32(s->regs, DEVICE_ADDR_TABLE_POINTER, in dw_i3c_handle_targ_irq()
678 if (FIELD_EX32(s->regs[table_offset], DEVICE_ADDR_TABLE_LOC1, SIR_REJECT)) { in dw_i3c_handle_targ_irq()
679 s->ibi_data.ibi_queue_status = FIELD_DP32(s->ibi_data.ibi_queue_status, in dw_i3c_handle_targ_irq()
682 s->ibi_data.ibi_nacked = true; in dw_i3c_handle_targ_irq()
683 s->ibi_data.disec_addr = addr; in dw_i3c_handle_targ_irq()
685 s->ibi_data.disec_byte = DISEC_INT; in dw_i3c_handle_targ_irq()
686 s->ibi_data.send_direct_disec = true; in dw_i3c_handle_targ_irq()
687 return -1; in dw_i3c_handle_targ_irq()
694 DWI3C *s = DW_I3C(bus->qbus.parent); in dw_i3c_ibi_handle()
696 trace_dw_i3c_ibi_handle(s->cfg.id, addr, is_recv); in dw_i3c_ibi_handle()
697 s->ibi_data.ibi_queue_status = FIELD_DP32(s->ibi_data.ibi_queue_status, in dw_i3c_ibi_handle()
715 return -1; in dw_i3c_ibi_handle()
720 DWI3C *s = DW_I3C(bus->qbus.parent); in dw_i3c_ibi_recv()
721 if (fifo8_is_full(&s->ibi_data.ibi_intermediate_queue)) { in dw_i3c_ibi_recv()
722 return -1; in dw_i3c_ibi_recv()
725 fifo8_push(&s->ibi_data.ibi_intermediate_queue, data); in dw_i3c_ibi_recv()
726 trace_dw_i3c_ibi_recv(s->cfg.id, data); in dw_i3c_ibi_recv()
732 /* Stored value is in 32-bit chunks, convert it to byte chunks. */ in dw_i3c_ibi_queue_push()
734 uint8_t num_slices = (fifo8_num_used(&s->ibi_data.ibi_intermediate_queue) / in dw_i3c_ibi_queue_push()
736 ((fifo8_num_used(&s->ibi_data.ibi_intermediate_queue) % in dw_i3c_ibi_queue_push()
747 if (s->ibi_data.ibi_nacked && !s->ibi_data.notify_ibi_nack) { in dw_i3c_ibi_queue_push()
748 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_ibi_queue_push()
750 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_ibi_queue_push()
757 s->ibi_data.ibi_queue_status = in dw_i3c_ibi_queue_push()
758 FIELD_DP32(s->ibi_data.ibi_queue_status, IBI_QUEUE_STATUS, in dw_i3c_ibi_queue_push()
760 fifo32_push(&s->ibi_queue, s->ibi_data.ibi_queue_status); in dw_i3c_ibi_queue_push()
766 if (fifo8_num_used(&s->ibi_data.ibi_intermediate_queue) < in dw_i3c_ibi_queue_push()
768 s->ibi_data.ibi_queue_status = in dw_i3c_ibi_queue_push()
769 FIELD_DP32(s->ibi_data.ibi_queue_status, IBI_QUEUE_STATUS, in dw_i3c_ibi_queue_push()
771 fifo8_num_used(&s->ibi_data.ibi_intermediate_queue)); in dw_i3c_ibi_queue_push()
772 s->ibi_data.ibi_queue_status = in dw_i3c_ibi_queue_push()
773 FIELD_DP32(s->ibi_data.ibi_queue_status, IBI_QUEUE_STATUS, in dw_i3c_ibi_queue_push()
776 s->ibi_data.ibi_queue_status = in dw_i3c_ibi_queue_push()
777 FIELD_DP32(s->ibi_data.ibi_queue_status, IBI_QUEUE_STATUS, in dw_i3c_ibi_queue_push()
782 fifo32_push(&s->ibi_queue, s->ibi_data.ibi_queue_status); in dw_i3c_ibi_queue_push()
783 /* Move each IBI byte into a 32-bit word and push it into the queue. */ in dw_i3c_ibi_queue_push()
785 if (fifo8_is_empty(&s->ibi_data.ibi_intermediate_queue)) { in dw_i3c_ibi_queue_push()
789 ibi_data.b[j & 3] = fifo8_pop(&s->ibi_data.ibi_intermediate_queue); in dw_i3c_ibi_queue_push()
790 /* We have 32-bits, push it to the IBI FIFO. */ in dw_i3c_ibi_queue_push()
792 fifo32_push(&s->ibi_queue, ibi_data.val32); in dw_i3c_ibi_queue_push()
796 /* If the data isn't 32-bit aligned, push the leftover bytes. */ in dw_i3c_ibi_queue_push()
798 fifo32_push(&s->ibi_queue, ibi_data.val32); in dw_i3c_ibi_queue_push()
802 s->ibi_data.ibi_queue_status = FIELD_DP32(s->ibi_data.ibi_queue_status, in dw_i3c_ibi_queue_push()
806 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, IBI_BUF_BLR, in dw_i3c_ibi_queue_push()
807 fifo32_num_used(&s->ibi_queue)); in dw_i3c_ibi_queue_push()
808 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, IBI_STATUS_CNT, in dw_i3c_ibi_queue_push()
811 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_ibi_queue_push()
813 if (fifo32_num_used(&s->ibi_queue) >= threshold) { in dw_i3c_ibi_queue_push()
814 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, IBI_THLD, 1); in dw_i3c_ibi_queue_push()
819 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_ibi_queue_push()
821 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS, in dw_i3c_ibi_queue_push()
827 DWI3C *s = DW_I3C(bus->qbus.parent); in dw_i3c_ibi_finish()
828 bool nack_and_disable_hj = ARRAY_FIELD_EX32(s->regs, DEVICE_CTRL, in dw_i3c_ibi_finish()
830 if (nack_and_disable_hj || s->ibi_data.send_direct_disec) { in dw_i3c_ibi_finish()
836 s->ibi_data.ibi_queue_status = 0; in dw_i3c_ibi_finish()
837 s->ibi_data.disec_addr = 0; in dw_i3c_ibi_finish()
838 s->ibi_data.disec_byte = 0; in dw_i3c_ibi_finish()
839 s->ibi_data.send_direct_disec = false; in dw_i3c_ibi_finish()
840 s->ibi_data.notify_ibi_nack = false; in dw_i3c_ibi_finish()
841 s->ibi_data.ibi_nacked = false; in dw_i3c_ibi_finish()
849 return s->regs[R_INTR_STATUS] & s->regs[R_INTR_STATUS_EN]; in dw_i3c_intr_status_r()
856 s->regs[R_INTR_STATUS] &= ~val; in dw_i3c_intr_status_w()
863 s->regs[R_INTR_STATUS_EN] = val; in dw_i3c_intr_status_en_w()
869 s->regs[R_INTR_SIGNAL_EN] = val; in dw_i3c_intr_signal_en_w()
876 s->regs[R_INTR_STATUS] = val; in dw_i3c_intr_force_w()
882 fifo32_reset(&s->cmd_queue); in dw_i3c_cmd_queue_reset()
884 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, CMD_QUEUE_EMPTY_LOC, in dw_i3c_cmd_queue_reset()
885 fifo32_num_free(&s->cmd_queue)); in dw_i3c_cmd_queue_reset()
886 uint8_t empty_threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_cmd_queue_reset()
888 if (fifo32_num_free(&s->cmd_queue) >= empty_threshold) { in dw_i3c_cmd_queue_reset()
889 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, CMD_QUEUE_RDY, 1); in dw_i3c_cmd_queue_reset()
896 fifo32_reset(&s->resp_queue); in dw_i3c_resp_queue_reset()
898 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, RESP_BUF_BLR, in dw_i3c_resp_queue_reset()
899 fifo32_num_used(&s->resp_queue)); in dw_i3c_resp_queue_reset()
904 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RESP_RDY, 0); in dw_i3c_resp_queue_reset()
910 fifo32_reset(&s->ibi_queue); in dw_i3c_ibi_queue_reset()
912 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, IBI_BUF_BLR, in dw_i3c_ibi_queue_reset()
913 fifo32_num_used(&s->resp_queue)); in dw_i3c_ibi_queue_reset()
918 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, IBI_THLD, 0); in dw_i3c_ibi_queue_reset()
924 fifo32_reset(&s->tx_queue); in dw_i3c_tx_queue_reset()
926 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, TX_BUF_EMPTY_LOC, in dw_i3c_tx_queue_reset()
927 fifo32_num_free(&s->tx_queue)); in dw_i3c_tx_queue_reset()
929 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TX_THLD, 1); in dw_i3c_tx_queue_reset()
935 fifo32_reset(&s->rx_queue); in dw_i3c_rx_queue_reset()
937 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, RX_BUF_BLR, in dw_i3c_rx_queue_reset()
938 fifo32_num_used(&s->resp_queue)); in dw_i3c_rx_queue_reset()
943 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RX_THLD, 0); in dw_i3c_rx_queue_reset()
950 trace_dw_i3c_reset(s->cfg.id); in dw_i3c_reset()
952 memcpy(s->regs, dw_i3c_resets, sizeof(s->regs)); in dw_i3c_reset()
957 ARRAY_FIELD_DP32(s->regs, DEVICE_ADDR_TABLE_POINTER, ADDR, in dw_i3c_reset()
958 s->cfg.dev_addr_table_pointer); in dw_i3c_reset()
959 ARRAY_FIELD_DP32(s->regs, DEVICE_ADDR_TABLE_POINTER, DEPTH, in dw_i3c_reset()
960 s->cfg.dev_addr_table_depth); in dw_i3c_reset()
961 ARRAY_FIELD_DP32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_reset()
963 s->cfg.dev_char_table_pointer); in dw_i3c_reset()
964 ARRAY_FIELD_DP32(s->regs, DEV_CHAR_TABLE_POINTER, DEV_CHAR_TABLE_DEPTH, in dw_i3c_reset()
965 s->cfg.dev_char_table_depth); in dw_i3c_reset()
998 if (fifo32_is_empty(&s->rx_queue)) { in dw_i3c_pop_rx()
1005 uint32_t val = fifo32_pop(&s->rx_queue); in dw_i3c_pop_rx()
1006 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, RX_BUF_BLR, in dw_i3c_pop_rx()
1007 fifo32_num_used(&s->rx_queue)); in dw_i3c_pop_rx()
1010 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, DATA_BUFFER_THLD_CTRL, in dw_i3c_pop_rx()
1013 if (fifo32_num_used(&s->rx_queue) < threshold) { in dw_i3c_pop_rx()
1014 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RX_THLD, 0); in dw_i3c_pop_rx()
1018 trace_dw_i3c_pop_rx(s->cfg.id, val); in dw_i3c_pop_rx()
1024 if (fifo32_is_empty(&s->ibi_queue)) { in dw_i3c_ibi_queue_r()
1028 uint32_t val = fifo32_pop(&s->ibi_queue); in dw_i3c_ibi_queue_r()
1029 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, IBI_BUF_BLR, in dw_i3c_ibi_queue_r()
1030 fifo32_num_used(&s->ibi_queue)); in dw_i3c_ibi_queue_r()
1032 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_ibi_queue_r()
1034 if (fifo32_num_used(&s->ibi_queue) < threshold) { in dw_i3c_ibi_queue_r()
1035 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, IBI_THLD, 0); in dw_i3c_ibi_queue_r()
1043 if (fifo32_is_empty(&s->resp_queue)) { in dw_i3c_resp_queue_port_r()
1050 uint32_t val = fifo32_pop(&s->resp_queue); in dw_i3c_resp_queue_port_r()
1051 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, RESP_BUF_BLR, in dw_i3c_resp_queue_port_r()
1052 fifo32_num_used(&s->resp_queue)); in dw_i3c_resp_queue_port_r()
1055 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_resp_queue_port_r()
1057 if (fifo32_num_used(&s->resp_queue) < threshold) { in dw_i3c_resp_queue_port_r()
1058 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RESP_RDY, 0); in dw_i3c_resp_queue_port_r()
1071 switch (addr) { in dw_i3c_read()
1090 default: in dw_i3c_read()
1091 value = s->regs[addr]; in dw_i3c_read()
1095 trace_dw_i3c_read(s->cfg.id, offset, value); in dw_i3c_read()
1108 if (!fifo32_is_full(&s->resp_queue)) { in dw_i3c_resp_queue_push()
1109 trace_dw_i3c_resp_queue_push(s->cfg.id, val); in dw_i3c_resp_queue_push()
1110 fifo32_push(&s->resp_queue, val); in dw_i3c_resp_queue_push()
1113 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, RESP_BUF_BLR, in dw_i3c_resp_queue_push()
1114 fifo32_num_used(&s->resp_queue)); in dw_i3c_resp_queue_push()
1116 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_resp_queue_push()
1118 if (fifo32_num_used(&s->resp_queue) >= threshold) { in dw_i3c_resp_queue_push()
1119 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RESP_RDY, 1); in dw_i3c_resp_queue_push()
1126 if (fifo32_is_full(&s->tx_queue)) { in dw_i3c_push_tx()
1132 trace_dw_i3c_push_tx(s->cfg.id, val); in dw_i3c_push_tx()
1133 fifo32_push(&s->tx_queue, val); in dw_i3c_push_tx()
1134 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, TX_BUF_EMPTY_LOC, in dw_i3c_push_tx()
1135 fifo32_num_free(&s->tx_queue)); in dw_i3c_push_tx()
1138 uint8_t empty_threshold = ARRAY_FIELD_EX32(s->regs, DATA_BUFFER_THLD_CTRL, in dw_i3c_push_tx()
1142 if (fifo32_num_free(&s->tx_queue) < empty_threshold) { in dw_i3c_push_tx()
1143 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TX_THLD, 0); in dw_i3c_push_tx()
1150 if (fifo32_is_empty(&s->tx_queue)) { in dw_i3c_pop_tx()
1157 uint32_t val = fifo32_pop(&s->tx_queue); in dw_i3c_pop_tx()
1158 trace_dw_i3c_pop_tx(s->cfg.id, val); in dw_i3c_pop_tx()
1159 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, TX_BUF_EMPTY_LOC, in dw_i3c_pop_tx()
1160 fifo32_num_free(&s->tx_queue)); in dw_i3c_pop_tx()
1163 uint8_t empty_threshold = ARRAY_FIELD_EX32(s->regs, DATA_BUFFER_THLD_CTRL, in dw_i3c_pop_tx()
1167 if (fifo32_num_free(&s->tx_queue) >= empty_threshold) { in dw_i3c_pop_tx()
1168 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TX_THLD, 1); in dw_i3c_pop_tx()
1176 if (fifo32_is_full(&s->rx_queue)) { in dw_i3c_push_rx()
1182 trace_dw_i3c_push_rx(s->cfg.id, val); in dw_i3c_push_rx()
1183 fifo32_push(&s->rx_queue, val); in dw_i3c_push_rx()
1185 ARRAY_FIELD_DP32(s->regs, DATA_BUFFER_STATUS_LEVEL, RX_BUF_BLR, in dw_i3c_push_rx()
1186 fifo32_num_used(&s->rx_queue)); in dw_i3c_push_rx()
1188 uint8_t threshold = ARRAY_FIELD_EX32(s->regs, DATA_BUFFER_THLD_CTRL, in dw_i3c_push_rx()
1191 if (fifo32_num_used(&s->rx_queue) >= threshold) { in dw_i3c_push_rx()
1192 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, RX_THLD, 1); in dw_i3c_push_rx()
1250 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_short_transfer()
1260 * ccc_type is always 0 in controller mode, data_len is 0 in short in dw_i3c_short_transfer()
1285 /* We're not sending the full 32-bits, break early. */ in dw_i3c_tx()
1300 * Zero it and word-align it as well in case we're reading unaligned data. in dw_i3c_rx()
1302 g_autofree uint8_t *data = g_new0(uint8_t, num + (4 - (num & 0x03))); in dw_i3c_rx()
1305 * 32-bits since the I3C API wants a 32-bit number, even though the in dw_i3c_rx()
1306 * controller can only do 16-bit transfers. in dw_i3c_rx()
1320 * If we're pushing data that isn't 32-bit aligned, push what's left. in dw_i3c_rx()
1339 trace_dw_i3c_transfer_ccc(s->cfg.id, cmd.cmd); in dw_i3c_transfer_ccc()
1372 if (ARRAY_FIELD_EX32(s->regs, DEVICE_CTRL, I3C_BROADCAST_ADDR_INC) && in dw_i3c_transfer()
1393 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_transfer()
1405 uint16_t data_len = is_recv ? bytes_transferred : arg.data_len - in dw_i3c_transfer()
1407 /* CCCT is always 0 in controller mode. */ in dw_i3c_transfer()
1420 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CMD_TID, cmd.tid); in dw_i3c_transfer_cmd()
1426 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_transfer_cmd()
1433 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_transfer_cmd()
1446 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_transfer_cmd()
1454 if (offset > s->cfg.num_addressable_devices) { in dw_i3c_update_char_table()
1464 * 4 * 32-bits of entries in the table. in dw_i3c_update_char_table()
1465 * / sizeof(uint32_t) because we're indexing into our 32-bit reg array. in dw_i3c_update_char_table()
1467 uint16_t dev_index = (ARRAY_FIELD_EX32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_update_char_table()
1471 s->regs[dev_index] = pid & 0xffffffff; in dw_i3c_update_char_table()
1473 s->regs[dev_index + 1] = FIELD_DP32(s->regs[dev_index + 1], in dw_i3c_update_char_table()
1476 s->regs[dev_index + 2] = FIELD_DP32(s->regs[dev_index + 2], in dw_i3c_update_char_table()
1479 s->regs[dev_index + 2] = FIELD_DP32(s->regs[dev_index + 2], in dw_i3c_update_char_table()
1482 s->regs[dev_index + 3] = FIELD_DP32(s->regs[dev_index + 3], in dw_i3c_update_char_table()
1487 uint8_t idx = ARRAY_FIELD_EX32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_update_char_table()
1491 if (idx >= ARRAY_FIELD_EX32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_update_char_table()
1495 ARRAY_FIELD_DP32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_update_char_table()
1572 * left to assign. CCCT is always 0 in controller mode. in dw_i3c_addr_assign_cmd()
1576 cmd.dev_count - i); in dw_i3c_addr_assign_cmd()
1582 if (fifo32_is_empty(&s->cmd_queue)) { in dw_i3c_cmd_queue_pop()
1588 uint32_t val = fifo32_pop(&s->cmd_queue); in dw_i3c_cmd_queue_pop()
1590 uint8_t empty_threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_cmd_queue_pop()
1592 uint8_t cmd_queue_empty_loc = ARRAY_FIELD_EX32(s->regs, in dw_i3c_cmd_queue_pop()
1596 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, CMD_QUEUE_EMPTY_LOC, in dw_i3c_cmd_queue_pop()
1599 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, CMD_QUEUE_RDY, 1); in dw_i3c_cmd_queue_pop()
1608 ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS, in dw_i3c_cmd_queue_execute()
1620 if (fifo32_num_used(&s->cmd_queue) & 1) { in dw_i3c_cmd_queue_execute()
1624 while (!fifo32_is_empty(&s->cmd_queue)) { in dw_i3c_cmd_queue_execute()
1629 trace_dw_i3c_cmd_queue_execute(s->cfg.id, cmd.word, arg.word); in dw_i3c_cmd_queue_execute()
1632 switch (cmd_attr) { in dw_i3c_cmd_queue_execute()
1649 default: in dw_i3c_cmd_queue_execute()
1662 if (fifo32_is_full(&s->cmd_queue)) { in dw_i3c_cmd_queue_push()
1668 trace_dw_i3c_cmd_queue_push(s->cfg.id, val); in dw_i3c_cmd_queue_push()
1669 fifo32_push(&s->cmd_queue, val); in dw_i3c_cmd_queue_push()
1671 uint8_t empty_threshold = ARRAY_FIELD_EX32(s->regs, QUEUE_THLD_CTRL, in dw_i3c_cmd_queue_push()
1673 uint8_t cmd_queue_empty_loc = ARRAY_FIELD_EX32(s->regs, in dw_i3c_cmd_queue_push()
1677 cmd_queue_empty_loc--; in dw_i3c_cmd_queue_push()
1678 ARRAY_FIELD_DP32(s->regs, QUEUE_STATUS_LEVEL, CMD_QUEUE_EMPTY_LOC, in dw_i3c_cmd_queue_push()
1682 ARRAY_FIELD_DP32(s->regs, INTR_STATUS, CMD_QUEUE_RDY, 0); in dw_i3c_cmd_queue_push()
1691 switch (cmd_attr) { in dw_i3c_cmd_queue_port_w()
1703 default: in dw_i3c_cmd_queue_port_w()
1720 trace_dw_i3c_write(s->cfg.id, offset, value); in dw_i3c_write()
1723 switch (addr) { in dw_i3c_write()
1767 default: in dw_i3c_write()
1768 s->regs[addr] = val32; in dw_i3c_write()
1793 memcpy(s->regs, dw_i3c_resets, sizeof(s->regs)); in dw_i3c_reset_enter()
1798 ARRAY_FIELD_DP32(s->regs, DEVICE_ADDR_TABLE_POINTER, ADDR, in dw_i3c_reset_enter()
1799 s->cfg.dev_addr_table_pointer); in dw_i3c_reset_enter()
1800 ARRAY_FIELD_DP32(s->regs, DEVICE_ADDR_TABLE_POINTER, DEPTH, in dw_i3c_reset_enter()
1801 s->cfg.dev_addr_table_depth); in dw_i3c_reset_enter()
1802 ARRAY_FIELD_DP32(s->regs, DEV_CHAR_TABLE_POINTER, in dw_i3c_reset_enter()
1804 s->cfg.dev_char_table_pointer); in dw_i3c_reset_enter()
1805 ARRAY_FIELD_DP32(s->regs, DEV_CHAR_TABLE_POINTER, DEV_CHAR_TABLE_DEPTH, in dw_i3c_reset_enter()
1806 s->cfg.dev_char_table_depth); in dw_i3c_reset_enter()
1812 g_autofree char *name = g_strdup_printf(TYPE_DW_I3C ".%d", s->cfg.id); in dw_i3c_realize()
1814 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); in dw_i3c_realize()
1816 memory_region_init_io(&s->mr, OBJECT(s), &dw_i3c_ops, s, name, in dw_i3c_realize()
1818 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); in dw_i3c_realize()
1820 fifo32_create(&s->cmd_queue, s->cfg.cmd_resp_queue_capacity_bytes); in dw_i3c_realize()
1821 fifo32_create(&s->resp_queue, s->cfg.cmd_resp_queue_capacity_bytes); in dw_i3c_realize()
1822 fifo32_create(&s->tx_queue, s->cfg.tx_rx_queue_capacity_bytes); in dw_i3c_realize()
1823 fifo32_create(&s->rx_queue, s->cfg.tx_rx_queue_capacity_bytes); in dw_i3c_realize()
1824 fifo32_create(&s->ibi_queue, s->cfg.ibi_queue_capacity_bytes); in dw_i3c_realize()
1826 fifo8_create(&s->ibi_data.ibi_intermediate_queue, in dw_i3c_realize()
1827 s->cfg.ibi_queue_capacity_bytes * 8); in dw_i3c_realize()
1829 s->bus = i3c_init_bus(DEVICE(s), name); in dw_i3c_realize()
1830 I3CBusClass *bc = I3C_BUS_GET_CLASS(s->bus); in dw_i3c_realize()
1831 bc->ibi_handle = dw_i3c_ibi_handle; in dw_i3c_realize()
1832 bc->ibi_recv = dw_i3c_ibi_recv; in dw_i3c_realize()
1833 bc->ibi_finish = dw_i3c_ibi_finish; in dw_i3c_realize()
1837 DEFINE_PROP_UINT8("device-id", DWI3C, cfg.id, 0),
1838 DEFINE_PROP_UINT8("command-response-queue-capacity-bytes", DWI3C,
1840 DEFINE_PROP_UINT16("tx-rx-queue-capacity-bytes", DWI3C,
1842 DEFINE_PROP_UINT8("ibi-queue-capacity-bytes", DWI3C,
1844 DEFINE_PROP_UINT8("num-addressable-devices", DWI3C,
1846 DEFINE_PROP_UINT16("dev-addr-table-pointer", DWI3C,
1848 DEFINE_PROP_UINT16("dev-addr-table-depth", DWI3C,
1850 DEFINE_PROP_UINT16("dev-char-table-pointer", DWI3C,
1852 DEFINE_PROP_UINT16("dev-char-table-depth", DWI3C,
1861 rc->phases.enter = dw_i3c_reset_enter; in dw_i3c_class_init()
1863 dc->desc = "DesignWare I3C Controller"; in dw_i3c_class_init()
1864 dc->realize = dw_i3c_realize; in dw_i3c_class_init()
1865 dc->vmsd = &vmstate_dw_i3c; in dw_i3c_class_init()