1 /* 2 * ASPEED I3C Controller 3 * 4 * Copyright (C) 2021 ASPEED Technology Inc. 5 * Copyright (C) 2023 Google, LLC 6 * 7 * This code is licensed under the GPL version 2 or later. See 8 * the COPYING file in the top-level directory. 9 */ 10 11 #ifndef ASPEED_I3C_H 12 #define ASPEED_I3C_H 13 14 #include "qemu/fifo32.h" 15 #include "hw/i3c/i3c.h" 16 #include "hw/sysbus.h" 17 18 #define TYPE_ASPEED_I3C "aspeed.i3c" 19 #define TYPE_ASPEED_I3C_DEVICE "aspeed.i3c.device" 20 OBJECT_DECLARE_TYPE(AspeedI3CState, AspeedI3CClass, ASPEED_I3C) 21 22 #define ASPEED_I3C_NR_REGS (0x70 >> 2) 23 #define ASPEED_I3C_DEVICE_NR_REGS (0x300 >> 2) 24 #define ASPEED_I3C_NR_DEVICES 6 25 26 #define ASPEED_I3C_CMD_QUEUE_CAPACITY 0x10 27 #define ASPEED_I3C_RESP_QUEUE_CAPACITY 0x10 28 #define ASPEED_I3C_TX_QUEUE_CAPACITY 0x40 29 #define ASPEED_I3C_RX_QUEUE_CAPACITY 0x40 30 #define ASPEED_I3C_IBI_QUEUE_CAPACITY 0x10 31 32 /* From datasheet. */ 33 #define ASPEED_I3C_CMD_ATTR_TRANSFER_CMD 0 34 #define ASPEED_I3C_CMD_ATTR_TRANSFER_ARG 1 35 #define ASPEED_I3C_CMD_ATTR_SHORT_DATA_ARG 2 36 #define ASPEED_I3C_CMD_ATTR_ADDR_ASSIGN_CMD 3 37 38 /* Enum values from datasheet. */ 39 typedef enum AspeedI3CRespQueueErr { 40 ASPEED_I3C_RESP_QUEUE_ERR_NONE = 0, 41 ASPEED_I3C_RESP_QUEUE_ERR_CRC = 1, 42 ASPEED_I3C_RESP_QUEUE_ERR_PARITY = 2, 43 ASPEED_I3C_RESP_QUEUE_ERR_FRAME = 3, 44 ASPEED_I3C_RESP_QUEUE_ERR_BROADCAST_NACK = 4, 45 ASPEED_I3C_RESP_QUEUE_ERR_DAA_NACK = 5, 46 ASPEED_I3C_RESP_QUEUE_ERR_OVERFLOW = 6, 47 ASPEED_I3C_RESP_QUEUE_ERR_ABORTED = 8, 48 ASPEED_I3C_RESP_QUEUE_ERR_I2C_NACK = 9, 49 } AspeedI3CRespQueueErr; 50 51 typedef enum AspeedI3CTransferState { 52 ASPEED_I3C_TRANSFER_STATE_IDLE = 0x00, 53 ASPEED_I3C_TRANSFER_STATE_START = 0x01, 54 ASPEED_I3C_TRANSFER_STATE_RESTART = 0x02, 55 ASPEED_I3C_TRANSFER_STATE_STOP = 0x03, 56 ASPEED_I3C_TRANSFER_STATE_START_HOLD = 0x04, 57 ASPEED_I3C_TRANSFER_STATE_BROADCAST_W = 0x05, 58 ASPEED_I3C_TRANSFER_STATE_BROADCAST_R = 0x06, 59 ASPEED_I3C_TRANSFER_STATE_DAA = 0x07, 60 ASPEED_I3C_TRANSFER_STATE_DAA_GEN = 0x08, 61 ASPEED_I3C_TRANSFER_STATE_CCC_BYTE = 0x0b, 62 ASPEED_I3C_TRANSFER_STATE_HDR_CMD = 0x0c, 63 ASPEED_I3C_TRANSFER_STATE_WRITE = 0x0d, 64 ASPEED_I3C_TRANSFER_STATE_READ = 0x0e, 65 ASPEED_I3C_TRANSFER_STATE_IBI_READ = 0x0f, 66 ASPEED_I3C_TRANSFER_STATE_IBI_DIS = 0x10, 67 ASPEED_I3C_TRANSFER_STATE_HDR_DDR_CRC = 0x11, 68 ASPEED_I3C_TRANSFER_STATE_CLK_STRETCH = 0x12, 69 ASPEED_I3C_TRANSFER_STATE_HALT = 0x13, 70 } AspeedI3CTransferState; 71 72 typedef enum AspeedI3CTransferStatus { 73 ASPEED_I3C_TRANSFER_STATUS_IDLE = 0x00, 74 ASPEED_I3C_TRANSFER_STATUS_BROACAST_CCC = 0x01, 75 ASPEED_I3C_TRANSFER_STATUS_DIRECT_CCC_W = 0x02, 76 ASPEED_I3C_TRANSFER_STATUS_DIRECT_CCC_R = 0x03, 77 ASPEED_I3C_TRANSFER_STATUS_ENTDAA = 0x04, 78 ASPEED_I3C_TRANSFER_STATUS_SETDASA = 0x05, 79 ASPEED_I3C_TRANSFER_STATUS_I3C_SDR_W = 0x06, 80 ASPEED_I3C_TRANSFER_STATUS_I3C_SDR_R = 0x07, 81 ASPEED_I3C_TRANSFER_STATUS_I2C_SDR_W = 0x08, 82 ASPEED_I3C_TRANSFER_STATUS_I2C_SDR_R = 0x09, 83 ASPEED_I3C_TRANSFER_STATUS_HDR_TS_W = 0x0a, 84 ASPEED_I3C_TRANSFER_STATUS_HDR_TS_R = 0x0b, 85 ASPEED_I3C_TRANSFER_STATUS_HDR_DDR_W = 0x0c, 86 ASPEED_I3C_TRANSFER_STATUS_HDR_DDR_R = 0x0d, 87 ASPEED_I3C_TRANSFER_STATUS_IBI = 0x0e, 88 ASPEED_I3C_TRANSFER_STATUS_HALT = 0x0f, 89 } AspeedI3CTransferStatus; 90 91 /* 92 * Transfer commands and arguments are 32-bit wide values that the user passes 93 * into the command queue. We interpret each 32-bit word based on the cmd_attr 94 * field. 95 */ 96 typedef struct AspeedI3CTransferCmd { 97 uint8_t cmd_attr:3; 98 uint8_t tid:4; /* Transaction ID */ 99 uint16_t cmd:8; 100 uint8_t cp:1; /* Command present */ 101 uint8_t dev_index:5; 102 uint8_t speed:3; 103 uint8_t resv0:1; 104 uint8_t dbp:1; /* Defining byte present */ 105 uint8_t roc:1; /* Response on completion */ 106 uint8_t sdap:1; /* Short data argument present */ 107 uint8_t rnw:1; /* Read not write */ 108 uint8_t resv1:1; 109 uint8_t toc:1; /* Termination (I3C STOP) on completion */ 110 uint8_t pec:1; /* Parity error check enabled */ 111 } AspeedI3CTransferCmd; 112 113 typedef struct AspeedI3CTransferArg { 114 uint8_t cmd_attr:3; 115 uint8_t resv:5; 116 uint8_t db; /* Defining byte */ 117 uint16_t data_len; 118 } AspeedI3CTransferArg; 119 120 typedef struct AspeedI3CShortArg { 121 uint8_t cmd_attr:3; 122 uint8_t byte_strb:3; 123 uint8_t resv:2; 124 uint8_t byte0; 125 uint8_t byte1; 126 uint8_t byte2; 127 } AspeedI3CShortArg; 128 129 typedef struct AspeedI3CAddrAssignCmd { 130 uint8_t cmd_attr:3; 131 uint8_t tid:4; /* Transaction ID */ 132 uint16_t cmd:8; 133 uint8_t resv0:1; 134 uint8_t dev_index:5; 135 uint16_t dev_count:5; 136 uint8_t roc:1; /* Response on completion */ 137 uint8_t resv1:3; 138 uint8_t toc:1; /* Termination (I3C STOP) on completion */ 139 uint8_t resv2:1; 140 } AspeedI3CAddrAssignCmd; 141 142 typedef union AspeedI3CCmdQueueData { 143 uint32_t word; 144 AspeedI3CTransferCmd transfer_cmd; 145 AspeedI3CTransferArg transfer_arg; 146 AspeedI3CShortArg short_arg; 147 AspeedI3CAddrAssignCmd addr_assign_cmd; 148 } AspeedI3CCmdQueueData; 149 150 /* 151 * When we receive an IBI with data, we need to store it temporarily until 152 * the target is finished sending data. Then we can set the IBI queue status 153 * appropriately. 154 */ 155 typedef struct AspeedI3CDeviceIBIData { 156 /* Do we notify the user that an IBI was NACKed? */ 157 bool notify_ibi_nack; 158 /* Intermediate storage of IBI_QUEUE_STATUS. */ 159 uint32_t ibi_queue_status; 160 /* Temporary buffer to store IBI data from the target. */ 161 Fifo8 ibi_intermediate_queue; 162 /* The address we should send a CCC_DISEC to. */ 163 uint8_t disec_addr; 164 /* The byte we should send along with the CCC_DISEC. */ 165 uint8_t disec_byte; 166 /* Should we send a direct DISEC CCC? (As opposed to global). */ 167 bool send_direct_disec; 168 /* Was this IBI NACKed? */ 169 bool ibi_nacked; 170 } AspeedI3CDeviceIBIData; 171 172 OBJECT_DECLARE_SIMPLE_TYPE(AspeedI3CDevice, ASPEED_I3C_DEVICE) 173 typedef struct AspeedI3CDevice { 174 /* <private> */ 175 SysBusDevice parent; 176 177 /* <public> */ 178 MemoryRegion mr; 179 qemu_irq irq; 180 I3CBus *bus; 181 182 Fifo32 cmd_queue; 183 Fifo32 resp_queue; 184 Fifo32 tx_queue; 185 Fifo32 rx_queue; 186 Fifo32 ibi_queue; 187 188 /* Temporary storage for IBI data. */ 189 AspeedI3CDeviceIBIData ibi_data; 190 191 uint8_t id; 192 uint32_t regs[ASPEED_I3C_DEVICE_NR_REGS]; 193 } AspeedI3CDevice; 194 195 typedef struct AspeedI3CState { 196 /* <private> */ 197 SysBusDevice parent; 198 199 /* <public> */ 200 MemoryRegion iomem; 201 MemoryRegion iomem_container; 202 qemu_irq irq; 203 204 uint32_t regs[ASPEED_I3C_NR_REGS]; 205 AspeedI3CDevice devices[ASPEED_I3C_NR_DEVICES]; 206 } AspeedI3CState; 207 #endif /* ASPEED_I3C_H */ 208