1*1dd728f5SVitor Soares // SPDX-License-Identifier: GPL-2.0 2*1dd728f5SVitor Soares /* 3*1dd728f5SVitor Soares * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. 4*1dd728f5SVitor Soares * 5*1dd728f5SVitor Soares * Author: Vitor Soares <vitor.soares@synopsys.com> 6*1dd728f5SVitor Soares */ 7*1dd728f5SVitor Soares 8*1dd728f5SVitor Soares #include <linux/bitops.h> 9*1dd728f5SVitor Soares #include <linux/clk.h> 10*1dd728f5SVitor Soares #include <linux/completion.h> 11*1dd728f5SVitor Soares #include <linux/err.h> 12*1dd728f5SVitor Soares #include <linux/errno.h> 13*1dd728f5SVitor Soares #include <linux/i3c/master.h> 14*1dd728f5SVitor Soares #include <linux/interrupt.h> 15*1dd728f5SVitor Soares #include <linux/ioport.h> 16*1dd728f5SVitor Soares #include <linux/iopoll.h> 17*1dd728f5SVitor Soares #include <linux/list.h> 18*1dd728f5SVitor Soares #include <linux/module.h> 19*1dd728f5SVitor Soares #include <linux/of.h> 20*1dd728f5SVitor Soares #include <linux/platform_device.h> 21*1dd728f5SVitor Soares #include <linux/reset.h> 22*1dd728f5SVitor Soares #include <linux/slab.h> 23*1dd728f5SVitor Soares 24*1dd728f5SVitor Soares #define DEVICE_CTRL 0x0 25*1dd728f5SVitor Soares #define DEV_CTRL_ENABLE BIT(31) 26*1dd728f5SVitor Soares #define DEV_CTRL_RESUME BIT(30) 27*1dd728f5SVitor Soares #define DEV_CTRL_HOT_JOIN_NACK BIT(8) 28*1dd728f5SVitor Soares #define DEV_CTRL_I2C_SLAVE_PRESENT BIT(7) 29*1dd728f5SVitor Soares 30*1dd728f5SVitor Soares #define DEVICE_ADDR 0x4 31*1dd728f5SVitor Soares #define DEV_ADDR_DYNAMIC_ADDR_VALID BIT(31) 32*1dd728f5SVitor Soares #define DEV_ADDR_DYNAMIC(x) (((x) << 16) & GENMASK(22, 16)) 33*1dd728f5SVitor Soares 34*1dd728f5SVitor Soares #define HW_CAPABILITY 0x8 35*1dd728f5SVitor Soares #define COMMAND_QUEUE_PORT 0xc 36*1dd728f5SVitor Soares #define COMMAND_PORT_TOC BIT(30) 37*1dd728f5SVitor Soares #define COMMAND_PORT_READ_TRANSFER BIT(28) 38*1dd728f5SVitor Soares #define COMMAND_PORT_SDAP BIT(27) 39*1dd728f5SVitor Soares #define COMMAND_PORT_ROC BIT(26) 40*1dd728f5SVitor Soares #define COMMAND_PORT_SPEED(x) (((x) << 21) & GENMASK(23, 21)) 41*1dd728f5SVitor Soares #define COMMAND_PORT_DEV_INDEX(x) (((x) << 16) & GENMASK(20, 16)) 42*1dd728f5SVitor Soares #define COMMAND_PORT_CP BIT(15) 43*1dd728f5SVitor Soares #define COMMAND_PORT_CMD(x) (((x) << 7) & GENMASK(14, 7)) 44*1dd728f5SVitor Soares #define COMMAND_PORT_TID(x) (((x) << 3) & GENMASK(6, 3)) 45*1dd728f5SVitor Soares 46*1dd728f5SVitor Soares #define COMMAND_PORT_ARG_DATA_LEN(x) (((x) << 16) & GENMASK(31, 16)) 47*1dd728f5SVitor Soares #define COMMAND_PORT_ARG_DATA_LEN_MAX 65536 48*1dd728f5SVitor Soares #define COMMAND_PORT_TRANSFER_ARG 0x01 49*1dd728f5SVitor Soares 50*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_DATA_BYTE_3(x) (((x) << 24) & GENMASK(31, 24)) 51*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_DATA_BYTE_2(x) (((x) << 16) & GENMASK(23, 16)) 52*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_DATA_BYTE_1(x) (((x) << 8) & GENMASK(15, 8)) 53*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_BYTE_STRB_3 BIT(5) 54*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_BYTE_STRB_2 BIT(4) 55*1dd728f5SVitor Soares #define COMMAND_PORT_SDA_BYTE_STRB_1 BIT(3) 56*1dd728f5SVitor Soares #define COMMAND_PORT_SHORT_DATA_ARG 0x02 57*1dd728f5SVitor Soares 58*1dd728f5SVitor Soares #define COMMAND_PORT_DEV_COUNT(x) (((x) << 21) & GENMASK(25, 21)) 59*1dd728f5SVitor Soares #define COMMAND_PORT_ADDR_ASSGN_CMD 0x03 60*1dd728f5SVitor Soares 61*1dd728f5SVitor Soares #define RESPONSE_QUEUE_PORT 0x10 62*1dd728f5SVitor Soares #define RESPONSE_PORT_ERR_STATUS(x) (((x) & GENMASK(31, 28)) >> 28) 63*1dd728f5SVitor Soares #define RESPONSE_NO_ERROR 0 64*1dd728f5SVitor Soares #define RESPONSE_ERROR_CRC 1 65*1dd728f5SVitor Soares #define RESPONSE_ERROR_PARITY 2 66*1dd728f5SVitor Soares #define RESPONSE_ERROR_FRAME 3 67*1dd728f5SVitor Soares #define RESPONSE_ERROR_IBA_NACK 4 68*1dd728f5SVitor Soares #define RESPONSE_ERROR_ADDRESS_NACK 5 69*1dd728f5SVitor Soares #define RESPONSE_ERROR_OVER_UNDER_FLOW 6 70*1dd728f5SVitor Soares #define RESPONSE_ERROR_TRANSF_ABORT 8 71*1dd728f5SVitor Soares #define RESPONSE_ERROR_I2C_W_NACK_ERR 9 72*1dd728f5SVitor Soares #define RESPONSE_PORT_TID(x) (((x) & GENMASK(27, 24)) >> 24) 73*1dd728f5SVitor Soares #define RESPONSE_PORT_DATA_LEN(x) ((x) & GENMASK(15, 0)) 74*1dd728f5SVitor Soares 75*1dd728f5SVitor Soares #define RX_TX_DATA_PORT 0x14 76*1dd728f5SVitor Soares #define IBI_QUEUE_STATUS 0x18 77*1dd728f5SVitor Soares #define QUEUE_THLD_CTRL 0x1c 78*1dd728f5SVitor Soares #define QUEUE_THLD_CTRL_RESP_BUF_MASK GENMASK(15, 8) 79*1dd728f5SVitor Soares #define QUEUE_THLD_CTRL_RESP_BUF(x) (((x) - 1) << 8) 80*1dd728f5SVitor Soares 81*1dd728f5SVitor Soares #define DATA_BUFFER_THLD_CTRL 0x20 82*1dd728f5SVitor Soares #define DATA_BUFFER_THLD_CTRL_RX_BUF GENMASK(11, 8) 83*1dd728f5SVitor Soares 84*1dd728f5SVitor Soares #define IBI_QUEUE_CTRL 0x24 85*1dd728f5SVitor Soares #define IBI_MR_REQ_REJECT 0x2C 86*1dd728f5SVitor Soares #define IBI_SIR_REQ_REJECT 0x30 87*1dd728f5SVitor Soares #define IBI_REQ_REJECT_ALL GENMASK(31, 0) 88*1dd728f5SVitor Soares 89*1dd728f5SVitor Soares #define RESET_CTRL 0x34 90*1dd728f5SVitor Soares #define RESET_CTRL_IBI_QUEUE BIT(5) 91*1dd728f5SVitor Soares #define RESET_CTRL_RX_FIFO BIT(4) 92*1dd728f5SVitor Soares #define RESET_CTRL_TX_FIFO BIT(3) 93*1dd728f5SVitor Soares #define RESET_CTRL_RESP_QUEUE BIT(2) 94*1dd728f5SVitor Soares #define RESET_CTRL_CMD_QUEUE BIT(1) 95*1dd728f5SVitor Soares #define RESET_CTRL_SOFT BIT(0) 96*1dd728f5SVitor Soares 97*1dd728f5SVitor Soares #define SLV_EVENT_CTRL 0x38 98*1dd728f5SVitor Soares #define INTR_STATUS 0x3c 99*1dd728f5SVitor Soares #define INTR_STATUS_EN 0x40 100*1dd728f5SVitor Soares #define INTR_SIGNAL_EN 0x44 101*1dd728f5SVitor Soares #define INTR_FORCE 0x48 102*1dd728f5SVitor Soares #define INTR_BUSOWNER_UPDATE_STAT BIT(13) 103*1dd728f5SVitor Soares #define INTR_IBI_UPDATED_STAT BIT(12) 104*1dd728f5SVitor Soares #define INTR_READ_REQ_RECV_STAT BIT(11) 105*1dd728f5SVitor Soares #define INTR_DEFSLV_STAT BIT(10) 106*1dd728f5SVitor Soares #define INTR_TRANSFER_ERR_STAT BIT(9) 107*1dd728f5SVitor Soares #define INTR_DYN_ADDR_ASSGN_STAT BIT(8) 108*1dd728f5SVitor Soares #define INTR_CCC_UPDATED_STAT BIT(6) 109*1dd728f5SVitor Soares #define INTR_TRANSFER_ABORT_STAT BIT(5) 110*1dd728f5SVitor Soares #define INTR_RESP_READY_STAT BIT(4) 111*1dd728f5SVitor Soares #define INTR_CMD_QUEUE_READY_STAT BIT(3) 112*1dd728f5SVitor Soares #define INTR_IBI_THLD_STAT BIT(2) 113*1dd728f5SVitor Soares #define INTR_RX_THLD_STAT BIT(1) 114*1dd728f5SVitor Soares #define INTR_TX_THLD_STAT BIT(0) 115*1dd728f5SVitor Soares #define INTR_ALL (INTR_BUSOWNER_UPDATE_STAT | \ 116*1dd728f5SVitor Soares INTR_IBI_UPDATED_STAT | \ 117*1dd728f5SVitor Soares INTR_READ_REQ_RECV_STAT | \ 118*1dd728f5SVitor Soares INTR_DEFSLV_STAT | \ 119*1dd728f5SVitor Soares INTR_TRANSFER_ERR_STAT | \ 120*1dd728f5SVitor Soares INTR_DYN_ADDR_ASSGN_STAT | \ 121*1dd728f5SVitor Soares INTR_CCC_UPDATED_STAT | \ 122*1dd728f5SVitor Soares INTR_TRANSFER_ABORT_STAT | \ 123*1dd728f5SVitor Soares INTR_RESP_READY_STAT | \ 124*1dd728f5SVitor Soares INTR_CMD_QUEUE_READY_STAT | \ 125*1dd728f5SVitor Soares INTR_IBI_THLD_STAT | \ 126*1dd728f5SVitor Soares INTR_TX_THLD_STAT | \ 127*1dd728f5SVitor Soares INTR_RX_THLD_STAT) 128*1dd728f5SVitor Soares 129*1dd728f5SVitor Soares #define INTR_MASTER_MASK (INTR_TRANSFER_ERR_STAT | \ 130*1dd728f5SVitor Soares INTR_RESP_READY_STAT) 131*1dd728f5SVitor Soares 132*1dd728f5SVitor Soares #define QUEUE_STATUS_LEVEL 0x4c 133*1dd728f5SVitor Soares #define QUEUE_STATUS_IBI_STATUS_CNT(x) (((x) & GENMASK(28, 24)) >> 24) 134*1dd728f5SVitor Soares #define QUEUE_STATUS_IBI_BUF_BLR(x) (((x) & GENMASK(23, 16)) >> 16) 135*1dd728f5SVitor Soares #define QUEUE_STATUS_LEVEL_RESP(x) (((x) & GENMASK(15, 8)) >> 8) 136*1dd728f5SVitor Soares #define QUEUE_STATUS_LEVEL_CMD(x) ((x) & GENMASK(7, 0)) 137*1dd728f5SVitor Soares 138*1dd728f5SVitor Soares #define DATA_BUFFER_STATUS_LEVEL 0x50 139*1dd728f5SVitor Soares #define DATA_BUFFER_STATUS_LEVEL_TX(x) ((x) & GENMASK(7, 0)) 140*1dd728f5SVitor Soares 141*1dd728f5SVitor Soares #define PRESENT_STATE 0x54 142*1dd728f5SVitor Soares #define CCC_DEVICE_STATUS 0x58 143*1dd728f5SVitor Soares #define DEVICE_ADDR_TABLE_POINTER 0x5c 144*1dd728f5SVitor Soares #define DEVICE_ADDR_TABLE_DEPTH(x) (((x) & GENMASK(31, 16)) >> 16) 145*1dd728f5SVitor Soares #define DEVICE_ADDR_TABLE_ADDR(x) ((x) & GENMASK(7, 0)) 146*1dd728f5SVitor Soares 147*1dd728f5SVitor Soares #define DEV_CHAR_TABLE_POINTER 0x60 148*1dd728f5SVitor Soares #define VENDOR_SPECIFIC_REG_POINTER 0x6c 149*1dd728f5SVitor Soares #define SLV_PID_VALUE 0x74 150*1dd728f5SVitor Soares #define SLV_CHAR_CTRL 0x78 151*1dd728f5SVitor Soares #define SLV_MAX_LEN 0x7c 152*1dd728f5SVitor Soares #define MAX_READ_TURNAROUND 0x80 153*1dd728f5SVitor Soares #define MAX_DATA_SPEED 0x84 154*1dd728f5SVitor Soares #define SLV_DEBUG_STATUS 0x88 155*1dd728f5SVitor Soares #define SLV_INTR_REQ 0x8c 156*1dd728f5SVitor Soares #define DEVICE_CTRL_EXTENDED 0xb0 157*1dd728f5SVitor Soares #define SCL_I3C_OD_TIMING 0xb4 158*1dd728f5SVitor Soares #define SCL_I3C_PP_TIMING 0xb8 159*1dd728f5SVitor Soares #define SCL_I3C_TIMING_HCNT(x) (((x) << 16) & GENMASK(23, 16)) 160*1dd728f5SVitor Soares #define SCL_I3C_TIMING_LCNT(x) ((x) & GENMASK(7, 0)) 161*1dd728f5SVitor Soares #define SCL_I3C_TIMING_CNT_MIN 5 162*1dd728f5SVitor Soares 163*1dd728f5SVitor Soares #define SCL_I2C_FM_TIMING 0xbc 164*1dd728f5SVitor Soares #define SCL_I2C_FM_TIMING_HCNT(x) (((x) << 16) & GENMASK(31, 16)) 165*1dd728f5SVitor Soares #define SCL_I2C_FM_TIMING_LCNT(x) ((x) & GENMASK(15, 0)) 166*1dd728f5SVitor Soares 167*1dd728f5SVitor Soares #define SCL_I2C_FMP_TIMING 0xc0 168*1dd728f5SVitor Soares #define SCL_I2C_FMP_TIMING_HCNT(x) (((x) << 16) & GENMASK(23, 16)) 169*1dd728f5SVitor Soares #define SCL_I2C_FMP_TIMING_LCNT(x) ((x) & GENMASK(15, 0)) 170*1dd728f5SVitor Soares 171*1dd728f5SVitor Soares #define SCL_EXT_LCNT_TIMING 0xc8 172*1dd728f5SVitor Soares #define SCL_EXT_LCNT_4(x) (((x) << 24) & GENMASK(31, 24)) 173*1dd728f5SVitor Soares #define SCL_EXT_LCNT_3(x) (((x) << 16) & GENMASK(23, 16)) 174*1dd728f5SVitor Soares #define SCL_EXT_LCNT_2(x) (((x) << 8) & GENMASK(15, 8)) 175*1dd728f5SVitor Soares #define SCL_EXT_LCNT_1(x) ((x) & GENMASK(7, 0)) 176*1dd728f5SVitor Soares 177*1dd728f5SVitor Soares #define SCL_EXT_TERMN_LCNT_TIMING 0xcc 178*1dd728f5SVitor Soares #define BUS_FREE_TIMING 0xd4 179*1dd728f5SVitor Soares #define BUS_I3C_MST_FREE(x) ((x) & GENMASK(15, 0)) 180*1dd728f5SVitor Soares 181*1dd728f5SVitor Soares #define BUS_IDLE_TIMING 0xd8 182*1dd728f5SVitor Soares #define I3C_VER_ID 0xe0 183*1dd728f5SVitor Soares #define I3C_VER_TYPE 0xe4 184*1dd728f5SVitor Soares #define EXTENDED_CAPABILITY 0xe8 185*1dd728f5SVitor Soares #define SLAVE_CONFIG 0xec 186*1dd728f5SVitor Soares 187*1dd728f5SVitor Soares #define DEV_ADDR_TABLE_LEGACY_I2C_DEV BIT(31) 188*1dd728f5SVitor Soares #define DEV_ADDR_TABLE_DYNAMIC_ADDR(x) (((x) << 16) & GENMASK(23, 16)) 189*1dd728f5SVitor Soares #define DEV_ADDR_TABLE_STATIC_ADDR(x) ((x) & GENMASK(6, 0)) 190*1dd728f5SVitor Soares #define DEV_ADDR_TABLE_LOC(start, idx) ((start) + ((idx) << 2)) 191*1dd728f5SVitor Soares 192*1dd728f5SVitor Soares #define MAX_DEVS 32 193*1dd728f5SVitor Soares 194*1dd728f5SVitor Soares #define I3C_BUS_SDR1_SCL_RATE 8000000 195*1dd728f5SVitor Soares #define I3C_BUS_SDR2_SCL_RATE 6000000 196*1dd728f5SVitor Soares #define I3C_BUS_SDR3_SCL_RATE 4000000 197*1dd728f5SVitor Soares #define I3C_BUS_SDR4_SCL_RATE 2000000 198*1dd728f5SVitor Soares #define I3C_BUS_I2C_FM_TLOW_MIN_NS 1300 199*1dd728f5SVitor Soares #define I3C_BUS_I2C_FMP_TLOW_MIN_NS 500 200*1dd728f5SVitor Soares #define I3C_BUS_THIGH_MAX_NS 41 201*1dd728f5SVitor Soares 202*1dd728f5SVitor Soares #define XFER_TIMEOUT (msecs_to_jiffies(1000)) 203*1dd728f5SVitor Soares 204*1dd728f5SVitor Soares struct dw_i3c_master_caps { 205*1dd728f5SVitor Soares u8 cmdfifodepth; 206*1dd728f5SVitor Soares u8 datafifodepth; 207*1dd728f5SVitor Soares }; 208*1dd728f5SVitor Soares 209*1dd728f5SVitor Soares struct dw_i3c_cmd { 210*1dd728f5SVitor Soares u32 cmd_lo; 211*1dd728f5SVitor Soares u32 cmd_hi; 212*1dd728f5SVitor Soares u16 tx_len; 213*1dd728f5SVitor Soares const void *tx_buf; 214*1dd728f5SVitor Soares u16 rx_len; 215*1dd728f5SVitor Soares void *rx_buf; 216*1dd728f5SVitor Soares u8 error; 217*1dd728f5SVitor Soares }; 218*1dd728f5SVitor Soares 219*1dd728f5SVitor Soares struct dw_i3c_xfer { 220*1dd728f5SVitor Soares struct list_head node; 221*1dd728f5SVitor Soares struct completion comp; 222*1dd728f5SVitor Soares int ret; 223*1dd728f5SVitor Soares unsigned int ncmds; 224*1dd728f5SVitor Soares struct dw_i3c_cmd cmds[0]; 225*1dd728f5SVitor Soares }; 226*1dd728f5SVitor Soares 227*1dd728f5SVitor Soares struct dw_i3c_master { 228*1dd728f5SVitor Soares struct i3c_master_controller base; 229*1dd728f5SVitor Soares u16 maxdevs; 230*1dd728f5SVitor Soares u16 datstartaddr; 231*1dd728f5SVitor Soares u32 free_pos; 232*1dd728f5SVitor Soares struct { 233*1dd728f5SVitor Soares struct list_head list; 234*1dd728f5SVitor Soares struct dw_i3c_xfer *cur; 235*1dd728f5SVitor Soares spinlock_t lock; 236*1dd728f5SVitor Soares } xferqueue; 237*1dd728f5SVitor Soares struct dw_i3c_master_caps caps; 238*1dd728f5SVitor Soares void __iomem *regs; 239*1dd728f5SVitor Soares struct reset_control *core_rst; 240*1dd728f5SVitor Soares struct clk *core_clk; 241*1dd728f5SVitor Soares char version[5]; 242*1dd728f5SVitor Soares char type[5]; 243*1dd728f5SVitor Soares u8 addrs[MAX_DEVS]; 244*1dd728f5SVitor Soares }; 245*1dd728f5SVitor Soares 246*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data { 247*1dd728f5SVitor Soares u8 index; 248*1dd728f5SVitor Soares }; 249*1dd728f5SVitor Soares 250*1dd728f5SVitor Soares static u8 even_parity(u8 p) 251*1dd728f5SVitor Soares { 252*1dd728f5SVitor Soares p ^= p >> 4; 253*1dd728f5SVitor Soares p &= 0xf; 254*1dd728f5SVitor Soares 255*1dd728f5SVitor Soares return (0x9669 >> p) & 1; 256*1dd728f5SVitor Soares } 257*1dd728f5SVitor Soares 258*1dd728f5SVitor Soares static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m, 259*1dd728f5SVitor Soares const struct i3c_ccc_cmd *cmd) 260*1dd728f5SVitor Soares { 261*1dd728f5SVitor Soares if (cmd->ndests > 1) 262*1dd728f5SVitor Soares return false; 263*1dd728f5SVitor Soares 264*1dd728f5SVitor Soares switch (cmd->id) { 265*1dd728f5SVitor Soares case I3C_CCC_ENEC(true): 266*1dd728f5SVitor Soares case I3C_CCC_ENEC(false): 267*1dd728f5SVitor Soares case I3C_CCC_DISEC(true): 268*1dd728f5SVitor Soares case I3C_CCC_DISEC(false): 269*1dd728f5SVitor Soares case I3C_CCC_ENTAS(0, true): 270*1dd728f5SVitor Soares case I3C_CCC_ENTAS(0, false): 271*1dd728f5SVitor Soares case I3C_CCC_RSTDAA(true): 272*1dd728f5SVitor Soares case I3C_CCC_RSTDAA(false): 273*1dd728f5SVitor Soares case I3C_CCC_ENTDAA: 274*1dd728f5SVitor Soares case I3C_CCC_SETMWL(true): 275*1dd728f5SVitor Soares case I3C_CCC_SETMWL(false): 276*1dd728f5SVitor Soares case I3C_CCC_SETMRL(true): 277*1dd728f5SVitor Soares case I3C_CCC_SETMRL(false): 278*1dd728f5SVitor Soares case I3C_CCC_ENTHDR(0): 279*1dd728f5SVitor Soares case I3C_CCC_SETDASA: 280*1dd728f5SVitor Soares case I3C_CCC_SETNEWDA: 281*1dd728f5SVitor Soares case I3C_CCC_GETMWL: 282*1dd728f5SVitor Soares case I3C_CCC_GETMRL: 283*1dd728f5SVitor Soares case I3C_CCC_GETPID: 284*1dd728f5SVitor Soares case I3C_CCC_GETBCR: 285*1dd728f5SVitor Soares case I3C_CCC_GETDCR: 286*1dd728f5SVitor Soares case I3C_CCC_GETSTATUS: 287*1dd728f5SVitor Soares case I3C_CCC_GETMXDS: 288*1dd728f5SVitor Soares case I3C_CCC_GETHDRCAP: 289*1dd728f5SVitor Soares return true; 290*1dd728f5SVitor Soares default: 291*1dd728f5SVitor Soares return false; 292*1dd728f5SVitor Soares } 293*1dd728f5SVitor Soares } 294*1dd728f5SVitor Soares 295*1dd728f5SVitor Soares static inline struct dw_i3c_master * 296*1dd728f5SVitor Soares to_dw_i3c_master(struct i3c_master_controller *master) 297*1dd728f5SVitor Soares { 298*1dd728f5SVitor Soares return container_of(master, struct dw_i3c_master, base); 299*1dd728f5SVitor Soares } 300*1dd728f5SVitor Soares 301*1dd728f5SVitor Soares static void dw_i3c_master_disable(struct dw_i3c_master *master) 302*1dd728f5SVitor Soares { 303*1dd728f5SVitor Soares writel(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_ENABLE, 304*1dd728f5SVitor Soares master->regs + DEVICE_CTRL); 305*1dd728f5SVitor Soares } 306*1dd728f5SVitor Soares 307*1dd728f5SVitor Soares static void dw_i3c_master_enable(struct dw_i3c_master *master) 308*1dd728f5SVitor Soares { 309*1dd728f5SVitor Soares writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_ENABLE, 310*1dd728f5SVitor Soares master->regs + DEVICE_CTRL); 311*1dd728f5SVitor Soares } 312*1dd728f5SVitor Soares 313*1dd728f5SVitor Soares static int dw_i3c_master_get_addr_pos(struct dw_i3c_master *master, u8 addr) 314*1dd728f5SVitor Soares { 315*1dd728f5SVitor Soares int pos; 316*1dd728f5SVitor Soares 317*1dd728f5SVitor Soares for (pos = 0; pos < master->maxdevs; pos++) { 318*1dd728f5SVitor Soares if (addr == master->addrs[pos]) 319*1dd728f5SVitor Soares return pos; 320*1dd728f5SVitor Soares } 321*1dd728f5SVitor Soares 322*1dd728f5SVitor Soares return -EINVAL; 323*1dd728f5SVitor Soares } 324*1dd728f5SVitor Soares 325*1dd728f5SVitor Soares static int dw_i3c_master_get_free_pos(struct dw_i3c_master *master) 326*1dd728f5SVitor Soares { 327*1dd728f5SVitor Soares if (!(master->free_pos & GENMASK(master->maxdevs - 1, 0))) 328*1dd728f5SVitor Soares return -ENOSPC; 329*1dd728f5SVitor Soares 330*1dd728f5SVitor Soares return ffs(master->free_pos) - 1; 331*1dd728f5SVitor Soares } 332*1dd728f5SVitor Soares 333*1dd728f5SVitor Soares static void dw_i3c_master_wr_tx_fifo(struct dw_i3c_master *master, 334*1dd728f5SVitor Soares const u8 *bytes, int nbytes) 335*1dd728f5SVitor Soares { 336*1dd728f5SVitor Soares writesl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); 337*1dd728f5SVitor Soares if (nbytes & 3) { 338*1dd728f5SVitor Soares u32 tmp = 0; 339*1dd728f5SVitor Soares 340*1dd728f5SVitor Soares memcpy(&tmp, bytes + (nbytes & ~3), nbytes & 3); 341*1dd728f5SVitor Soares writesl(master->regs + RX_TX_DATA_PORT, &tmp, 1); 342*1dd728f5SVitor Soares } 343*1dd728f5SVitor Soares } 344*1dd728f5SVitor Soares 345*1dd728f5SVitor Soares static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, 346*1dd728f5SVitor Soares u8 *bytes, int nbytes) 347*1dd728f5SVitor Soares { 348*1dd728f5SVitor Soares readsl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4); 349*1dd728f5SVitor Soares if (nbytes & 3) { 350*1dd728f5SVitor Soares u32 tmp; 351*1dd728f5SVitor Soares 352*1dd728f5SVitor Soares readsl(master->regs + RX_TX_DATA_PORT, &tmp, 1); 353*1dd728f5SVitor Soares memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3); 354*1dd728f5SVitor Soares } 355*1dd728f5SVitor Soares } 356*1dd728f5SVitor Soares 357*1dd728f5SVitor Soares static struct dw_i3c_xfer * 358*1dd728f5SVitor Soares dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds) 359*1dd728f5SVitor Soares { 360*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 361*1dd728f5SVitor Soares 362*1dd728f5SVitor Soares xfer = kzalloc(struct_size(xfer, cmds, ncmds), GFP_KERNEL); 363*1dd728f5SVitor Soares if (!xfer) 364*1dd728f5SVitor Soares return NULL; 365*1dd728f5SVitor Soares 366*1dd728f5SVitor Soares INIT_LIST_HEAD(&xfer->node); 367*1dd728f5SVitor Soares xfer->ncmds = ncmds; 368*1dd728f5SVitor Soares xfer->ret = -ETIMEDOUT; 369*1dd728f5SVitor Soares 370*1dd728f5SVitor Soares return xfer; 371*1dd728f5SVitor Soares } 372*1dd728f5SVitor Soares 373*1dd728f5SVitor Soares static void dw_i3c_master_free_xfer(struct dw_i3c_xfer *xfer) 374*1dd728f5SVitor Soares { 375*1dd728f5SVitor Soares kfree(xfer); 376*1dd728f5SVitor Soares } 377*1dd728f5SVitor Soares 378*1dd728f5SVitor Soares static void dw_i3c_master_start_xfer_locked(struct dw_i3c_master *master) 379*1dd728f5SVitor Soares { 380*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer = master->xferqueue.cur; 381*1dd728f5SVitor Soares unsigned int i; 382*1dd728f5SVitor Soares u32 thld_ctrl; 383*1dd728f5SVitor Soares 384*1dd728f5SVitor Soares if (!xfer) 385*1dd728f5SVitor Soares return; 386*1dd728f5SVitor Soares 387*1dd728f5SVitor Soares for (i = 0; i < xfer->ncmds; i++) { 388*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd = &xfer->cmds[i]; 389*1dd728f5SVitor Soares 390*1dd728f5SVitor Soares dw_i3c_master_wr_tx_fifo(master, cmd->tx_buf, cmd->tx_len); 391*1dd728f5SVitor Soares } 392*1dd728f5SVitor Soares 393*1dd728f5SVitor Soares thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); 394*1dd728f5SVitor Soares thld_ctrl &= ~QUEUE_THLD_CTRL_RESP_BUF_MASK; 395*1dd728f5SVitor Soares thld_ctrl |= QUEUE_THLD_CTRL_RESP_BUF(xfer->ncmds); 396*1dd728f5SVitor Soares writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); 397*1dd728f5SVitor Soares 398*1dd728f5SVitor Soares for (i = 0; i < xfer->ncmds; i++) { 399*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd = &xfer->cmds[i]; 400*1dd728f5SVitor Soares 401*1dd728f5SVitor Soares writel(cmd->cmd_hi, master->regs + COMMAND_QUEUE_PORT); 402*1dd728f5SVitor Soares writel(cmd->cmd_lo, master->regs + COMMAND_QUEUE_PORT); 403*1dd728f5SVitor Soares } 404*1dd728f5SVitor Soares } 405*1dd728f5SVitor Soares 406*1dd728f5SVitor Soares static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master, 407*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer) 408*1dd728f5SVitor Soares { 409*1dd728f5SVitor Soares unsigned long flags; 410*1dd728f5SVitor Soares 411*1dd728f5SVitor Soares init_completion(&xfer->comp); 412*1dd728f5SVitor Soares spin_lock_irqsave(&master->xferqueue.lock, flags); 413*1dd728f5SVitor Soares if (master->xferqueue.cur) { 414*1dd728f5SVitor Soares list_add_tail(&xfer->node, &master->xferqueue.list); 415*1dd728f5SVitor Soares } else { 416*1dd728f5SVitor Soares master->xferqueue.cur = xfer; 417*1dd728f5SVitor Soares dw_i3c_master_start_xfer_locked(master); 418*1dd728f5SVitor Soares } 419*1dd728f5SVitor Soares spin_unlock_irqrestore(&master->xferqueue.lock, flags); 420*1dd728f5SVitor Soares } 421*1dd728f5SVitor Soares 422*1dd728f5SVitor Soares static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, 423*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer) 424*1dd728f5SVitor Soares { 425*1dd728f5SVitor Soares unsigned long flags; 426*1dd728f5SVitor Soares 427*1dd728f5SVitor Soares spin_lock_irqsave(&master->xferqueue.lock, flags); 428*1dd728f5SVitor Soares if (master->xferqueue.cur == xfer) { 429*1dd728f5SVitor Soares u32 status; 430*1dd728f5SVitor Soares 431*1dd728f5SVitor Soares master->xferqueue.cur = NULL; 432*1dd728f5SVitor Soares 433*1dd728f5SVitor Soares writel(RESET_CTRL_RX_FIFO | RESET_CTRL_TX_FIFO | 434*1dd728f5SVitor Soares RESET_CTRL_RESP_QUEUE | RESET_CTRL_CMD_QUEUE, 435*1dd728f5SVitor Soares master->regs + RESET_CTRL); 436*1dd728f5SVitor Soares 437*1dd728f5SVitor Soares readl_poll_timeout_atomic(master->regs + RESET_CTRL, status, 438*1dd728f5SVitor Soares !status, 10, 1000000); 439*1dd728f5SVitor Soares } else { 440*1dd728f5SVitor Soares list_del_init(&xfer->node); 441*1dd728f5SVitor Soares } 442*1dd728f5SVitor Soares spin_unlock_irqrestore(&master->xferqueue.lock, flags); 443*1dd728f5SVitor Soares } 444*1dd728f5SVitor Soares 445*1dd728f5SVitor Soares static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr) 446*1dd728f5SVitor Soares { 447*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer = master->xferqueue.cur; 448*1dd728f5SVitor Soares int i, ret = 0; 449*1dd728f5SVitor Soares u32 nresp; 450*1dd728f5SVitor Soares 451*1dd728f5SVitor Soares if (!xfer) 452*1dd728f5SVitor Soares return; 453*1dd728f5SVitor Soares 454*1dd728f5SVitor Soares nresp = readl(master->regs + QUEUE_STATUS_LEVEL); 455*1dd728f5SVitor Soares nresp = QUEUE_STATUS_LEVEL_RESP(nresp); 456*1dd728f5SVitor Soares 457*1dd728f5SVitor Soares for (i = 0; i < nresp; i++) { 458*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd; 459*1dd728f5SVitor Soares u32 resp; 460*1dd728f5SVitor Soares 461*1dd728f5SVitor Soares resp = readl(master->regs + RESPONSE_QUEUE_PORT); 462*1dd728f5SVitor Soares 463*1dd728f5SVitor Soares cmd = &xfer->cmds[RESPONSE_PORT_TID(resp)]; 464*1dd728f5SVitor Soares cmd->rx_len = RESPONSE_PORT_DATA_LEN(resp); 465*1dd728f5SVitor Soares cmd->error = RESPONSE_PORT_ERR_STATUS(resp); 466*1dd728f5SVitor Soares if (cmd->rx_len && !cmd->error) 467*1dd728f5SVitor Soares dw_i3c_master_read_rx_fifo(master, cmd->rx_buf, 468*1dd728f5SVitor Soares cmd->rx_len); 469*1dd728f5SVitor Soares } 470*1dd728f5SVitor Soares 471*1dd728f5SVitor Soares for (i = 0; i < nresp; i++) { 472*1dd728f5SVitor Soares switch (xfer->cmds[i].error) { 473*1dd728f5SVitor Soares case RESPONSE_NO_ERROR: 474*1dd728f5SVitor Soares break; 475*1dd728f5SVitor Soares case RESPONSE_ERROR_PARITY: 476*1dd728f5SVitor Soares case RESPONSE_ERROR_IBA_NACK: 477*1dd728f5SVitor Soares case RESPONSE_ERROR_TRANSF_ABORT: 478*1dd728f5SVitor Soares case RESPONSE_ERROR_CRC: 479*1dd728f5SVitor Soares case RESPONSE_ERROR_FRAME: 480*1dd728f5SVitor Soares ret = -EIO; 481*1dd728f5SVitor Soares break; 482*1dd728f5SVitor Soares case RESPONSE_ERROR_OVER_UNDER_FLOW: 483*1dd728f5SVitor Soares ret = -ENOSPC; 484*1dd728f5SVitor Soares break; 485*1dd728f5SVitor Soares case RESPONSE_ERROR_I2C_W_NACK_ERR: 486*1dd728f5SVitor Soares case RESPONSE_ERROR_ADDRESS_NACK: 487*1dd728f5SVitor Soares default: 488*1dd728f5SVitor Soares ret = -EINVAL; 489*1dd728f5SVitor Soares break; 490*1dd728f5SVitor Soares } 491*1dd728f5SVitor Soares } 492*1dd728f5SVitor Soares 493*1dd728f5SVitor Soares xfer->ret = ret; 494*1dd728f5SVitor Soares complete(&xfer->comp); 495*1dd728f5SVitor Soares 496*1dd728f5SVitor Soares if (ret < 0) { 497*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 498*1dd728f5SVitor Soares writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME, 499*1dd728f5SVitor Soares master->regs + DEVICE_CTRL); 500*1dd728f5SVitor Soares } 501*1dd728f5SVitor Soares 502*1dd728f5SVitor Soares xfer = list_first_entry_or_null(&master->xferqueue.list, 503*1dd728f5SVitor Soares struct dw_i3c_xfer, 504*1dd728f5SVitor Soares node); 505*1dd728f5SVitor Soares if (xfer) 506*1dd728f5SVitor Soares list_del_init(&xfer->node); 507*1dd728f5SVitor Soares 508*1dd728f5SVitor Soares master->xferqueue.cur = xfer; 509*1dd728f5SVitor Soares dw_i3c_master_start_xfer_locked(master); 510*1dd728f5SVitor Soares } 511*1dd728f5SVitor Soares 512*1dd728f5SVitor Soares static int dw_i3c_clk_cfg(struct dw_i3c_master *master) 513*1dd728f5SVitor Soares { 514*1dd728f5SVitor Soares unsigned long core_rate, core_period; 515*1dd728f5SVitor Soares u32 scl_timing; 516*1dd728f5SVitor Soares u8 hcnt, lcnt; 517*1dd728f5SVitor Soares 518*1dd728f5SVitor Soares core_rate = clk_get_rate(master->core_clk); 519*1dd728f5SVitor Soares if (!core_rate) 520*1dd728f5SVitor Soares return -EINVAL; 521*1dd728f5SVitor Soares 522*1dd728f5SVitor Soares core_period = DIV_ROUND_UP(1000000000, core_rate); 523*1dd728f5SVitor Soares 524*1dd728f5SVitor Soares hcnt = DIV_ROUND_UP(I3C_BUS_THIGH_MAX_NS, core_period) - 1; 525*1dd728f5SVitor Soares if (hcnt < SCL_I3C_TIMING_CNT_MIN) 526*1dd728f5SVitor Soares hcnt = SCL_I3C_TIMING_CNT_MIN; 527*1dd728f5SVitor Soares 528*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_TYP_I3C_SCL_RATE) - hcnt; 529*1dd728f5SVitor Soares if (lcnt < SCL_I3C_TIMING_CNT_MIN) 530*1dd728f5SVitor Soares lcnt = SCL_I3C_TIMING_CNT_MIN; 531*1dd728f5SVitor Soares 532*1dd728f5SVitor Soares scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); 533*1dd728f5SVitor Soares writel(scl_timing, master->regs + SCL_I3C_PP_TIMING); 534*1dd728f5SVitor Soares 535*1dd728f5SVitor Soares if (!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_I2C_SLAVE_PRESENT)) 536*1dd728f5SVitor Soares writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING); 537*1dd728f5SVitor Soares 538*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, core_period); 539*1dd728f5SVitor Soares scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); 540*1dd728f5SVitor Soares writel(scl_timing, master->regs + SCL_I3C_OD_TIMING); 541*1dd728f5SVitor Soares 542*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR1_SCL_RATE) - hcnt; 543*1dd728f5SVitor Soares scl_timing = SCL_EXT_LCNT_1(lcnt); 544*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR2_SCL_RATE) - hcnt; 545*1dd728f5SVitor Soares scl_timing |= SCL_EXT_LCNT_2(lcnt); 546*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR3_SCL_RATE) - hcnt; 547*1dd728f5SVitor Soares scl_timing |= SCL_EXT_LCNT_3(lcnt); 548*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR4_SCL_RATE) - hcnt; 549*1dd728f5SVitor Soares scl_timing |= SCL_EXT_LCNT_4(lcnt); 550*1dd728f5SVitor Soares writel(scl_timing, master->regs + SCL_EXT_LCNT_TIMING); 551*1dd728f5SVitor Soares 552*1dd728f5SVitor Soares return 0; 553*1dd728f5SVitor Soares } 554*1dd728f5SVitor Soares 555*1dd728f5SVitor Soares static int dw_i2c_clk_cfg(struct dw_i3c_master *master) 556*1dd728f5SVitor Soares { 557*1dd728f5SVitor Soares unsigned long core_rate, core_period; 558*1dd728f5SVitor Soares u16 hcnt, lcnt; 559*1dd728f5SVitor Soares u32 scl_timing; 560*1dd728f5SVitor Soares 561*1dd728f5SVitor Soares core_rate = clk_get_rate(master->core_clk); 562*1dd728f5SVitor Soares if (!core_rate) 563*1dd728f5SVitor Soares return -EINVAL; 564*1dd728f5SVitor Soares 565*1dd728f5SVitor Soares core_period = DIV_ROUND_UP(1000000000, core_rate); 566*1dd728f5SVitor Soares 567*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FMP_TLOW_MIN_NS, core_period); 568*1dd728f5SVitor Soares hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_PLUS_SCL_RATE) - lcnt; 569*1dd728f5SVitor Soares scl_timing = SCL_I2C_FMP_TIMING_HCNT(hcnt) | 570*1dd728f5SVitor Soares SCL_I2C_FMP_TIMING_LCNT(lcnt); 571*1dd728f5SVitor Soares writel(scl_timing, master->regs + SCL_I2C_FMP_TIMING); 572*1dd728f5SVitor Soares 573*1dd728f5SVitor Soares lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FM_TLOW_MIN_NS, core_period); 574*1dd728f5SVitor Soares hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_SCL_RATE) - lcnt; 575*1dd728f5SVitor Soares scl_timing = SCL_I2C_FM_TIMING_HCNT(hcnt) | 576*1dd728f5SVitor Soares SCL_I2C_FM_TIMING_LCNT(lcnt); 577*1dd728f5SVitor Soares writel(scl_timing, master->regs + SCL_I2C_FM_TIMING); 578*1dd728f5SVitor Soares 579*1dd728f5SVitor Soares writel(BUS_I3C_MST_FREE(lcnt), master->regs + BUS_FREE_TIMING); 580*1dd728f5SVitor Soares writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT, 581*1dd728f5SVitor Soares master->regs + DEVICE_CTRL); 582*1dd728f5SVitor Soares 583*1dd728f5SVitor Soares return 0; 584*1dd728f5SVitor Soares } 585*1dd728f5SVitor Soares 586*1dd728f5SVitor Soares static int dw_i3c_master_bus_init(struct i3c_master_controller *m) 587*1dd728f5SVitor Soares { 588*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 589*1dd728f5SVitor Soares struct i3c_bus *bus = i3c_master_get_bus(m); 590*1dd728f5SVitor Soares struct i3c_device_info info = { }; 591*1dd728f5SVitor Soares u32 thld_ctrl; 592*1dd728f5SVitor Soares int ret; 593*1dd728f5SVitor Soares 594*1dd728f5SVitor Soares switch (bus->mode) { 595*1dd728f5SVitor Soares case I3C_BUS_MODE_MIXED_FAST: 596*1dd728f5SVitor Soares ret = dw_i2c_clk_cfg(master); 597*1dd728f5SVitor Soares if (ret) 598*1dd728f5SVitor Soares return ret; 599*1dd728f5SVitor Soares case I3C_BUS_MODE_PURE: 600*1dd728f5SVitor Soares ret = dw_i3c_clk_cfg(master); 601*1dd728f5SVitor Soares if (ret) 602*1dd728f5SVitor Soares return ret; 603*1dd728f5SVitor Soares break; 604*1dd728f5SVitor Soares default: 605*1dd728f5SVitor Soares return -EINVAL; 606*1dd728f5SVitor Soares } 607*1dd728f5SVitor Soares 608*1dd728f5SVitor Soares thld_ctrl = readl(master->regs + QUEUE_THLD_CTRL); 609*1dd728f5SVitor Soares thld_ctrl &= ~QUEUE_THLD_CTRL_RESP_BUF_MASK; 610*1dd728f5SVitor Soares writel(thld_ctrl, master->regs + QUEUE_THLD_CTRL); 611*1dd728f5SVitor Soares 612*1dd728f5SVitor Soares thld_ctrl = readl(master->regs + DATA_BUFFER_THLD_CTRL); 613*1dd728f5SVitor Soares thld_ctrl &= ~DATA_BUFFER_THLD_CTRL_RX_BUF; 614*1dd728f5SVitor Soares writel(thld_ctrl, master->regs + DATA_BUFFER_THLD_CTRL); 615*1dd728f5SVitor Soares 616*1dd728f5SVitor Soares writel(INTR_ALL, master->regs + INTR_STATUS); 617*1dd728f5SVitor Soares writel(INTR_MASTER_MASK, master->regs + INTR_STATUS_EN); 618*1dd728f5SVitor Soares writel(INTR_MASTER_MASK, master->regs + INTR_SIGNAL_EN); 619*1dd728f5SVitor Soares 620*1dd728f5SVitor Soares ret = i3c_master_get_free_addr(m, 0); 621*1dd728f5SVitor Soares if (ret < 0) 622*1dd728f5SVitor Soares return ret; 623*1dd728f5SVitor Soares 624*1dd728f5SVitor Soares writel(DEV_ADDR_DYNAMIC_ADDR_VALID | DEV_ADDR_DYNAMIC(ret), 625*1dd728f5SVitor Soares master->regs + DEVICE_ADDR); 626*1dd728f5SVitor Soares 627*1dd728f5SVitor Soares memset(&info, 0, sizeof(info)); 628*1dd728f5SVitor Soares info.dyn_addr = ret; 629*1dd728f5SVitor Soares 630*1dd728f5SVitor Soares ret = i3c_master_set_info(&master->base, &info); 631*1dd728f5SVitor Soares if (ret) 632*1dd728f5SVitor Soares return ret; 633*1dd728f5SVitor Soares 634*1dd728f5SVitor Soares writel(IBI_REQ_REJECT_ALL, master->regs + IBI_SIR_REQ_REJECT); 635*1dd728f5SVitor Soares writel(IBI_REQ_REJECT_ALL, master->regs + IBI_MR_REQ_REJECT); 636*1dd728f5SVitor Soares 637*1dd728f5SVitor Soares /* For now don't support Hot-Join */ 638*1dd728f5SVitor Soares writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_HOT_JOIN_NACK, 639*1dd728f5SVitor Soares master->regs + DEVICE_CTRL); 640*1dd728f5SVitor Soares 641*1dd728f5SVitor Soares dw_i3c_master_enable(master); 642*1dd728f5SVitor Soares 643*1dd728f5SVitor Soares return 0; 644*1dd728f5SVitor Soares } 645*1dd728f5SVitor Soares 646*1dd728f5SVitor Soares static void dw_i3c_master_bus_cleanup(struct i3c_master_controller *m) 647*1dd728f5SVitor Soares { 648*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 649*1dd728f5SVitor Soares 650*1dd728f5SVitor Soares dw_i3c_master_disable(master); 651*1dd728f5SVitor Soares } 652*1dd728f5SVitor Soares 653*1dd728f5SVitor Soares static int dw_i3c_ccc_set(struct dw_i3c_master *master, 654*1dd728f5SVitor Soares struct i3c_ccc_cmd *ccc) 655*1dd728f5SVitor Soares { 656*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 657*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd; 658*1dd728f5SVitor Soares int ret, pos = 0; 659*1dd728f5SVitor Soares 660*1dd728f5SVitor Soares if (ccc->id & I3C_CCC_DIRECT) { 661*1dd728f5SVitor Soares pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr); 662*1dd728f5SVitor Soares if (pos < 0) 663*1dd728f5SVitor Soares return pos; 664*1dd728f5SVitor Soares } 665*1dd728f5SVitor Soares 666*1dd728f5SVitor Soares xfer = dw_i3c_master_alloc_xfer(master, 1); 667*1dd728f5SVitor Soares if (!xfer) 668*1dd728f5SVitor Soares return -ENOMEM; 669*1dd728f5SVitor Soares 670*1dd728f5SVitor Soares cmd = xfer->cmds; 671*1dd728f5SVitor Soares cmd->tx_buf = ccc->dests[0].payload.data; 672*1dd728f5SVitor Soares cmd->tx_len = ccc->dests[0].payload.len; 673*1dd728f5SVitor Soares 674*1dd728f5SVitor Soares cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) | 675*1dd728f5SVitor Soares COMMAND_PORT_TRANSFER_ARG; 676*1dd728f5SVitor Soares 677*1dd728f5SVitor Soares cmd->cmd_lo = COMMAND_PORT_CP | 678*1dd728f5SVitor Soares COMMAND_PORT_DEV_INDEX(pos) | 679*1dd728f5SVitor Soares COMMAND_PORT_CMD(ccc->id) | 680*1dd728f5SVitor Soares COMMAND_PORT_TOC | 681*1dd728f5SVitor Soares COMMAND_PORT_ROC; 682*1dd728f5SVitor Soares 683*1dd728f5SVitor Soares dw_i3c_master_enqueue_xfer(master, xfer); 684*1dd728f5SVitor Soares if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 685*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 686*1dd728f5SVitor Soares 687*1dd728f5SVitor Soares ret = xfer->ret; 688*1dd728f5SVitor Soares if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK) 689*1dd728f5SVitor Soares ccc->err = I3C_ERROR_M2; 690*1dd728f5SVitor Soares 691*1dd728f5SVitor Soares dw_i3c_master_free_xfer(xfer); 692*1dd728f5SVitor Soares 693*1dd728f5SVitor Soares return ret; 694*1dd728f5SVitor Soares } 695*1dd728f5SVitor Soares 696*1dd728f5SVitor Soares static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc) 697*1dd728f5SVitor Soares { 698*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 699*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd; 700*1dd728f5SVitor Soares int ret, pos; 701*1dd728f5SVitor Soares 702*1dd728f5SVitor Soares pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr); 703*1dd728f5SVitor Soares if (pos < 0) 704*1dd728f5SVitor Soares return pos; 705*1dd728f5SVitor Soares 706*1dd728f5SVitor Soares xfer = dw_i3c_master_alloc_xfer(master, 1); 707*1dd728f5SVitor Soares if (!xfer) 708*1dd728f5SVitor Soares return -ENOMEM; 709*1dd728f5SVitor Soares 710*1dd728f5SVitor Soares cmd = xfer->cmds; 711*1dd728f5SVitor Soares cmd->rx_buf = ccc->dests[0].payload.data; 712*1dd728f5SVitor Soares cmd->rx_len = ccc->dests[0].payload.len; 713*1dd728f5SVitor Soares 714*1dd728f5SVitor Soares cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) | 715*1dd728f5SVitor Soares COMMAND_PORT_TRANSFER_ARG; 716*1dd728f5SVitor Soares 717*1dd728f5SVitor Soares cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER | 718*1dd728f5SVitor Soares COMMAND_PORT_CP | 719*1dd728f5SVitor Soares COMMAND_PORT_DEV_INDEX(pos) | 720*1dd728f5SVitor Soares COMMAND_PORT_CMD(ccc->id) | 721*1dd728f5SVitor Soares COMMAND_PORT_TOC | 722*1dd728f5SVitor Soares COMMAND_PORT_ROC; 723*1dd728f5SVitor Soares 724*1dd728f5SVitor Soares dw_i3c_master_enqueue_xfer(master, xfer); 725*1dd728f5SVitor Soares if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 726*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 727*1dd728f5SVitor Soares 728*1dd728f5SVitor Soares ret = xfer->ret; 729*1dd728f5SVitor Soares if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK) 730*1dd728f5SVitor Soares ccc->err = I3C_ERROR_M2; 731*1dd728f5SVitor Soares dw_i3c_master_free_xfer(xfer); 732*1dd728f5SVitor Soares 733*1dd728f5SVitor Soares return ret; 734*1dd728f5SVitor Soares } 735*1dd728f5SVitor Soares 736*1dd728f5SVitor Soares static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m, 737*1dd728f5SVitor Soares struct i3c_ccc_cmd *ccc) 738*1dd728f5SVitor Soares { 739*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 740*1dd728f5SVitor Soares int ret = 0; 741*1dd728f5SVitor Soares 742*1dd728f5SVitor Soares if (ccc->id == I3C_CCC_ENTDAA) 743*1dd728f5SVitor Soares return -EINVAL; 744*1dd728f5SVitor Soares 745*1dd728f5SVitor Soares if (ccc->rnw) 746*1dd728f5SVitor Soares ret = dw_i3c_ccc_get(master, ccc); 747*1dd728f5SVitor Soares else 748*1dd728f5SVitor Soares ret = dw_i3c_ccc_set(master, ccc); 749*1dd728f5SVitor Soares 750*1dd728f5SVitor Soares return ret; 751*1dd728f5SVitor Soares } 752*1dd728f5SVitor Soares 753*1dd728f5SVitor Soares static int dw_i3c_master_daa(struct i3c_master_controller *m) 754*1dd728f5SVitor Soares { 755*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 756*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 757*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd; 758*1dd728f5SVitor Soares u32 olddevs, newdevs; 759*1dd728f5SVitor Soares u8 p, last_addr = 0; 760*1dd728f5SVitor Soares int ret, pos; 761*1dd728f5SVitor Soares 762*1dd728f5SVitor Soares olddevs = ~(master->free_pos); 763*1dd728f5SVitor Soares 764*1dd728f5SVitor Soares /* Prepare DAT before launching DAA. */ 765*1dd728f5SVitor Soares for (pos = 0; pos < master->maxdevs; pos++) { 766*1dd728f5SVitor Soares if (olddevs & BIT(pos)) 767*1dd728f5SVitor Soares continue; 768*1dd728f5SVitor Soares 769*1dd728f5SVitor Soares ret = i3c_master_get_free_addr(m, last_addr + 1); 770*1dd728f5SVitor Soares if (ret < 0) 771*1dd728f5SVitor Soares return -ENOSPC; 772*1dd728f5SVitor Soares 773*1dd728f5SVitor Soares master->addrs[pos] = ret; 774*1dd728f5SVitor Soares p = even_parity(ret); 775*1dd728f5SVitor Soares last_addr = ret; 776*1dd728f5SVitor Soares ret |= (p << 7); 777*1dd728f5SVitor Soares 778*1dd728f5SVitor Soares writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret), 779*1dd728f5SVitor Soares master->regs + 780*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, pos)); 781*1dd728f5SVitor Soares } 782*1dd728f5SVitor Soares 783*1dd728f5SVitor Soares xfer = dw_i3c_master_alloc_xfer(master, 1); 784*1dd728f5SVitor Soares if (!xfer) 785*1dd728f5SVitor Soares return -ENOMEM; 786*1dd728f5SVitor Soares 787*1dd728f5SVitor Soares pos = dw_i3c_master_get_free_pos(master); 788*1dd728f5SVitor Soares cmd = &xfer->cmds[0]; 789*1dd728f5SVitor Soares cmd->cmd_hi = 0x1; 790*1dd728f5SVitor Soares cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) | 791*1dd728f5SVitor Soares COMMAND_PORT_DEV_INDEX(pos) | 792*1dd728f5SVitor Soares COMMAND_PORT_CMD(I3C_CCC_ENTDAA) | 793*1dd728f5SVitor Soares COMMAND_PORT_ADDR_ASSGN_CMD | 794*1dd728f5SVitor Soares COMMAND_PORT_TOC | 795*1dd728f5SVitor Soares COMMAND_PORT_ROC; 796*1dd728f5SVitor Soares 797*1dd728f5SVitor Soares dw_i3c_master_enqueue_xfer(master, xfer); 798*1dd728f5SVitor Soares if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 799*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 800*1dd728f5SVitor Soares 801*1dd728f5SVitor Soares newdevs = GENMASK(master->maxdevs - cmd->rx_len - 1, 0); 802*1dd728f5SVitor Soares newdevs &= ~olddevs; 803*1dd728f5SVitor Soares 804*1dd728f5SVitor Soares for (pos = 0; pos < master->maxdevs; pos++) { 805*1dd728f5SVitor Soares if (newdevs & BIT(pos)) 806*1dd728f5SVitor Soares i3c_master_add_i3c_dev_locked(m, master->addrs[pos]); 807*1dd728f5SVitor Soares } 808*1dd728f5SVitor Soares 809*1dd728f5SVitor Soares dw_i3c_master_free_xfer(xfer); 810*1dd728f5SVitor Soares 811*1dd728f5SVitor Soares i3c_master_disec_locked(m, I3C_BROADCAST_ADDR, 812*1dd728f5SVitor Soares I3C_CCC_EVENT_HJ | 813*1dd728f5SVitor Soares I3C_CCC_EVENT_MR | 814*1dd728f5SVitor Soares I3C_CCC_EVENT_SIR); 815*1dd728f5SVitor Soares 816*1dd728f5SVitor Soares return 0; 817*1dd728f5SVitor Soares } 818*1dd728f5SVitor Soares 819*1dd728f5SVitor Soares static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev, 820*1dd728f5SVitor Soares struct i3c_priv_xfer *i3c_xfers, 821*1dd728f5SVitor Soares int i3c_nxfers) 822*1dd728f5SVitor Soares { 823*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 824*1dd728f5SVitor Soares struct i3c_master_controller *m = i3c_dev_get_master(dev); 825*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 826*1dd728f5SVitor Soares unsigned int nrxwords = 0, ntxwords = 0; 827*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 828*1dd728f5SVitor Soares int i, ret = 0; 829*1dd728f5SVitor Soares 830*1dd728f5SVitor Soares if (!i3c_nxfers) 831*1dd728f5SVitor Soares return 0; 832*1dd728f5SVitor Soares 833*1dd728f5SVitor Soares if (i3c_nxfers > master->caps.cmdfifodepth) 834*1dd728f5SVitor Soares return -ENOTSUPP; 835*1dd728f5SVitor Soares 836*1dd728f5SVitor Soares for (i = 0; i < i3c_nxfers; i++) { 837*1dd728f5SVitor Soares if (i3c_xfers[i].len > COMMAND_PORT_ARG_DATA_LEN_MAX) 838*1dd728f5SVitor Soares return -ENOTSUPP; 839*1dd728f5SVitor Soares } 840*1dd728f5SVitor Soares 841*1dd728f5SVitor Soares for (i = 0; i < i3c_nxfers; i++) { 842*1dd728f5SVitor Soares if (i3c_xfers[i].rnw) 843*1dd728f5SVitor Soares nrxwords += DIV_ROUND_UP(i3c_xfers[i].len, 4); 844*1dd728f5SVitor Soares else 845*1dd728f5SVitor Soares ntxwords += DIV_ROUND_UP(i3c_xfers[i].len, 4); 846*1dd728f5SVitor Soares } 847*1dd728f5SVitor Soares 848*1dd728f5SVitor Soares if (ntxwords > master->caps.datafifodepth || 849*1dd728f5SVitor Soares nrxwords > master->caps.datafifodepth) 850*1dd728f5SVitor Soares return -ENOTSUPP; 851*1dd728f5SVitor Soares 852*1dd728f5SVitor Soares xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers); 853*1dd728f5SVitor Soares if (!xfer) 854*1dd728f5SVitor Soares return -ENOMEM; 855*1dd728f5SVitor Soares 856*1dd728f5SVitor Soares for (i = 0; i < i3c_nxfers; i++) { 857*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd = &xfer->cmds[i]; 858*1dd728f5SVitor Soares 859*1dd728f5SVitor Soares cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(i3c_xfers[i].len) | 860*1dd728f5SVitor Soares COMMAND_PORT_TRANSFER_ARG; 861*1dd728f5SVitor Soares 862*1dd728f5SVitor Soares if (i3c_xfers[i].rnw) { 863*1dd728f5SVitor Soares cmd->rx_buf = i3c_xfers[i].data.in; 864*1dd728f5SVitor Soares cmd->rx_len = i3c_xfers[i].len; 865*1dd728f5SVitor Soares cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER | 866*1dd728f5SVitor Soares COMMAND_PORT_SPEED(dev->info.max_read_ds); 867*1dd728f5SVitor Soares 868*1dd728f5SVitor Soares } else { 869*1dd728f5SVitor Soares cmd->tx_buf = i3c_xfers[i].data.out; 870*1dd728f5SVitor Soares cmd->tx_len = i3c_xfers[i].len; 871*1dd728f5SVitor Soares cmd->cmd_lo = 872*1dd728f5SVitor Soares COMMAND_PORT_SPEED(dev->info.max_write_ds); 873*1dd728f5SVitor Soares } 874*1dd728f5SVitor Soares 875*1dd728f5SVitor Soares cmd->cmd_lo |= COMMAND_PORT_TID(i) | 876*1dd728f5SVitor Soares COMMAND_PORT_DEV_INDEX(data->index) | 877*1dd728f5SVitor Soares COMMAND_PORT_ROC; 878*1dd728f5SVitor Soares 879*1dd728f5SVitor Soares if (i == (i3c_nxfers - 1)) 880*1dd728f5SVitor Soares cmd->cmd_lo |= COMMAND_PORT_TOC; 881*1dd728f5SVitor Soares } 882*1dd728f5SVitor Soares 883*1dd728f5SVitor Soares dw_i3c_master_enqueue_xfer(master, xfer); 884*1dd728f5SVitor Soares if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 885*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 886*1dd728f5SVitor Soares 887*1dd728f5SVitor Soares ret = xfer->ret; 888*1dd728f5SVitor Soares dw_i3c_master_free_xfer(xfer); 889*1dd728f5SVitor Soares 890*1dd728f5SVitor Soares return ret; 891*1dd728f5SVitor Soares } 892*1dd728f5SVitor Soares 893*1dd728f5SVitor Soares static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, 894*1dd728f5SVitor Soares u8 old_dyn_addr) 895*1dd728f5SVitor Soares { 896*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 897*1dd728f5SVitor Soares struct i3c_master_controller *m = i3c_dev_get_master(dev); 898*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 899*1dd728f5SVitor Soares 900*1dd728f5SVitor Soares writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr), 901*1dd728f5SVitor Soares master->regs + 902*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 903*1dd728f5SVitor Soares 904*1dd728f5SVitor Soares if (!old_dyn_addr) 905*1dd728f5SVitor Soares return 0; 906*1dd728f5SVitor Soares 907*1dd728f5SVitor Soares master->addrs[data->index] = dev->info.dyn_addr; 908*1dd728f5SVitor Soares 909*1dd728f5SVitor Soares return 0; 910*1dd728f5SVitor Soares } 911*1dd728f5SVitor Soares 912*1dd728f5SVitor Soares static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) 913*1dd728f5SVitor Soares { 914*1dd728f5SVitor Soares struct i3c_master_controller *m = i3c_dev_get_master(dev); 915*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 916*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data; 917*1dd728f5SVitor Soares int pos; 918*1dd728f5SVitor Soares 919*1dd728f5SVitor Soares pos = dw_i3c_master_get_free_pos(master); 920*1dd728f5SVitor Soares if (pos < 0) 921*1dd728f5SVitor Soares return pos; 922*1dd728f5SVitor Soares 923*1dd728f5SVitor Soares data = kzalloc(sizeof(*data), GFP_KERNEL); 924*1dd728f5SVitor Soares if (!data) 925*1dd728f5SVitor Soares return -ENOMEM; 926*1dd728f5SVitor Soares 927*1dd728f5SVitor Soares data->index = pos; 928*1dd728f5SVitor Soares master->addrs[pos] = dev->info.dyn_addr; 929*1dd728f5SVitor Soares master->free_pos &= ~BIT(pos); 930*1dd728f5SVitor Soares i3c_dev_set_master_data(dev, data); 931*1dd728f5SVitor Soares 932*1dd728f5SVitor Soares writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr), 933*1dd728f5SVitor Soares master->regs + 934*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 935*1dd728f5SVitor Soares 936*1dd728f5SVitor Soares return 0; 937*1dd728f5SVitor Soares } 938*1dd728f5SVitor Soares 939*1dd728f5SVitor Soares static void dw_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev) 940*1dd728f5SVitor Soares { 941*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); 942*1dd728f5SVitor Soares struct i3c_master_controller *m = i3c_dev_get_master(dev); 943*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 944*1dd728f5SVitor Soares 945*1dd728f5SVitor Soares writel(0, 946*1dd728f5SVitor Soares master->regs + 947*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 948*1dd728f5SVitor Soares 949*1dd728f5SVitor Soares i3c_dev_set_master_data(dev, NULL); 950*1dd728f5SVitor Soares master->addrs[data->index] = 0; 951*1dd728f5SVitor Soares master->free_pos |= BIT(data->index); 952*1dd728f5SVitor Soares kfree(data); 953*1dd728f5SVitor Soares } 954*1dd728f5SVitor Soares 955*1dd728f5SVitor Soares static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, 956*1dd728f5SVitor Soares const struct i2c_msg *i2c_xfers, 957*1dd728f5SVitor Soares int i2c_nxfers) 958*1dd728f5SVitor Soares { 959*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev); 960*1dd728f5SVitor Soares struct i3c_master_controller *m = i2c_dev_get_master(dev); 961*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 962*1dd728f5SVitor Soares unsigned int nrxwords = 0, ntxwords = 0; 963*1dd728f5SVitor Soares struct dw_i3c_xfer *xfer; 964*1dd728f5SVitor Soares int i, ret = 0; 965*1dd728f5SVitor Soares 966*1dd728f5SVitor Soares if (!i2c_nxfers) 967*1dd728f5SVitor Soares return 0; 968*1dd728f5SVitor Soares 969*1dd728f5SVitor Soares if (i2c_nxfers > master->caps.cmdfifodepth) 970*1dd728f5SVitor Soares return -ENOTSUPP; 971*1dd728f5SVitor Soares 972*1dd728f5SVitor Soares for (i = 0; i < i2c_nxfers; i++) { 973*1dd728f5SVitor Soares if (i2c_xfers[i].len > COMMAND_PORT_ARG_DATA_LEN_MAX) 974*1dd728f5SVitor Soares return -ENOTSUPP; 975*1dd728f5SVitor Soares } 976*1dd728f5SVitor Soares 977*1dd728f5SVitor Soares for (i = 0; i < i2c_nxfers; i++) { 978*1dd728f5SVitor Soares if (i2c_xfers[i].flags & I2C_M_RD) 979*1dd728f5SVitor Soares nrxwords += DIV_ROUND_UP(i2c_xfers[i].len, 4); 980*1dd728f5SVitor Soares else 981*1dd728f5SVitor Soares ntxwords += DIV_ROUND_UP(i2c_xfers[i].len, 4); 982*1dd728f5SVitor Soares } 983*1dd728f5SVitor Soares 984*1dd728f5SVitor Soares if (ntxwords > master->caps.datafifodepth || 985*1dd728f5SVitor Soares nrxwords > master->caps.datafifodepth) 986*1dd728f5SVitor Soares return -ENOTSUPP; 987*1dd728f5SVitor Soares 988*1dd728f5SVitor Soares xfer = dw_i3c_master_alloc_xfer(master, i2c_nxfers); 989*1dd728f5SVitor Soares if (!xfer) 990*1dd728f5SVitor Soares return -ENOMEM; 991*1dd728f5SVitor Soares 992*1dd728f5SVitor Soares for (i = 0; i < i2c_nxfers; i++) { 993*1dd728f5SVitor Soares struct dw_i3c_cmd *cmd = &xfer->cmds[i]; 994*1dd728f5SVitor Soares 995*1dd728f5SVitor Soares cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(i2c_xfers[i].len) | 996*1dd728f5SVitor Soares COMMAND_PORT_TRANSFER_ARG; 997*1dd728f5SVitor Soares 998*1dd728f5SVitor Soares cmd->cmd_lo = COMMAND_PORT_TID(i) | 999*1dd728f5SVitor Soares COMMAND_PORT_DEV_INDEX(data->index) | 1000*1dd728f5SVitor Soares COMMAND_PORT_ROC; 1001*1dd728f5SVitor Soares 1002*1dd728f5SVitor Soares if (i2c_xfers[i].flags & I2C_M_RD) { 1003*1dd728f5SVitor Soares cmd->cmd_lo |= COMMAND_PORT_READ_TRANSFER; 1004*1dd728f5SVitor Soares cmd->rx_buf = i2c_xfers[i].buf; 1005*1dd728f5SVitor Soares cmd->rx_len = i2c_xfers[i].len; 1006*1dd728f5SVitor Soares } else { 1007*1dd728f5SVitor Soares cmd->tx_buf = i2c_xfers[i].buf; 1008*1dd728f5SVitor Soares cmd->tx_len = i2c_xfers[i].len; 1009*1dd728f5SVitor Soares } 1010*1dd728f5SVitor Soares 1011*1dd728f5SVitor Soares if (i == (i2c_nxfers - 1)) 1012*1dd728f5SVitor Soares cmd->cmd_lo |= COMMAND_PORT_TOC; 1013*1dd728f5SVitor Soares } 1014*1dd728f5SVitor Soares 1015*1dd728f5SVitor Soares dw_i3c_master_enqueue_xfer(master, xfer); 1016*1dd728f5SVitor Soares if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT)) 1017*1dd728f5SVitor Soares dw_i3c_master_dequeue_xfer(master, xfer); 1018*1dd728f5SVitor Soares 1019*1dd728f5SVitor Soares ret = xfer->ret; 1020*1dd728f5SVitor Soares dw_i3c_master_free_xfer(xfer); 1021*1dd728f5SVitor Soares 1022*1dd728f5SVitor Soares return ret; 1023*1dd728f5SVitor Soares } 1024*1dd728f5SVitor Soares 1025*1dd728f5SVitor Soares static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) 1026*1dd728f5SVitor Soares { 1027*1dd728f5SVitor Soares struct i3c_master_controller *m = i2c_dev_get_master(dev); 1028*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 1029*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data; 1030*1dd728f5SVitor Soares int pos; 1031*1dd728f5SVitor Soares 1032*1dd728f5SVitor Soares pos = dw_i3c_master_get_free_pos(master); 1033*1dd728f5SVitor Soares if (pos < 0) 1034*1dd728f5SVitor Soares return pos; 1035*1dd728f5SVitor Soares 1036*1dd728f5SVitor Soares data = kzalloc(sizeof(*data), GFP_KERNEL); 1037*1dd728f5SVitor Soares if (!data) 1038*1dd728f5SVitor Soares return -ENOMEM; 1039*1dd728f5SVitor Soares 1040*1dd728f5SVitor Soares data->index = pos; 1041*1dd728f5SVitor Soares master->addrs[pos] = dev->boardinfo->base.addr; 1042*1dd728f5SVitor Soares master->free_pos &= ~BIT(pos); 1043*1dd728f5SVitor Soares i2c_dev_set_master_data(dev, data); 1044*1dd728f5SVitor Soares 1045*1dd728f5SVitor Soares writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV | 1046*1dd728f5SVitor Soares DEV_ADDR_TABLE_STATIC_ADDR(dev->boardinfo->base.addr), 1047*1dd728f5SVitor Soares master->regs + 1048*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 1049*1dd728f5SVitor Soares 1050*1dd728f5SVitor Soares return 0; 1051*1dd728f5SVitor Soares } 1052*1dd728f5SVitor Soares 1053*1dd728f5SVitor Soares static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) 1054*1dd728f5SVitor Soares { 1055*1dd728f5SVitor Soares struct dw_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev); 1056*1dd728f5SVitor Soares struct i3c_master_controller *m = i2c_dev_get_master(dev); 1057*1dd728f5SVitor Soares struct dw_i3c_master *master = to_dw_i3c_master(m); 1058*1dd728f5SVitor Soares 1059*1dd728f5SVitor Soares writel(0, 1060*1dd728f5SVitor Soares master->regs + 1061*1dd728f5SVitor Soares DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); 1062*1dd728f5SVitor Soares 1063*1dd728f5SVitor Soares i2c_dev_set_master_data(dev, NULL); 1064*1dd728f5SVitor Soares master->addrs[data->index] = 0; 1065*1dd728f5SVitor Soares master->free_pos |= BIT(data->index); 1066*1dd728f5SVitor Soares kfree(data); 1067*1dd728f5SVitor Soares } 1068*1dd728f5SVitor Soares 1069*1dd728f5SVitor Soares static u32 dw_i3c_master_i2c_funcs(struct i3c_master_controller *m) 1070*1dd728f5SVitor Soares { 1071*1dd728f5SVitor Soares return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 1072*1dd728f5SVitor Soares } 1073*1dd728f5SVitor Soares 1074*1dd728f5SVitor Soares static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id) 1075*1dd728f5SVitor Soares { 1076*1dd728f5SVitor Soares struct dw_i3c_master *master = dev_id; 1077*1dd728f5SVitor Soares u32 status; 1078*1dd728f5SVitor Soares 1079*1dd728f5SVitor Soares status = readl(master->regs + INTR_STATUS); 1080*1dd728f5SVitor Soares 1081*1dd728f5SVitor Soares if (!(status & readl(master->regs + INTR_STATUS_EN))) { 1082*1dd728f5SVitor Soares writel(INTR_ALL, master->regs + INTR_STATUS); 1083*1dd728f5SVitor Soares return IRQ_NONE; 1084*1dd728f5SVitor Soares } 1085*1dd728f5SVitor Soares 1086*1dd728f5SVitor Soares spin_lock(&master->xferqueue.lock); 1087*1dd728f5SVitor Soares dw_i3c_master_end_xfer_locked(master, status); 1088*1dd728f5SVitor Soares if (status | INTR_TRANSFER_ERR_STAT) 1089*1dd728f5SVitor Soares writel(INTR_TRANSFER_ERR_STAT, master->regs + INTR_STATUS); 1090*1dd728f5SVitor Soares spin_unlock(&master->xferqueue.lock); 1091*1dd728f5SVitor Soares 1092*1dd728f5SVitor Soares return IRQ_HANDLED; 1093*1dd728f5SVitor Soares } 1094*1dd728f5SVitor Soares 1095*1dd728f5SVitor Soares static const struct i3c_master_controller_ops dw_mipi_i3c_ops = { 1096*1dd728f5SVitor Soares .bus_init = dw_i3c_master_bus_init, 1097*1dd728f5SVitor Soares .bus_cleanup = dw_i3c_master_bus_cleanup, 1098*1dd728f5SVitor Soares .attach_i3c_dev = dw_i3c_master_attach_i3c_dev, 1099*1dd728f5SVitor Soares .reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev, 1100*1dd728f5SVitor Soares .detach_i3c_dev = dw_i3c_master_detach_i3c_dev, 1101*1dd728f5SVitor Soares .do_daa = dw_i3c_master_daa, 1102*1dd728f5SVitor Soares .supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd, 1103*1dd728f5SVitor Soares .send_ccc_cmd = dw_i3c_master_send_ccc_cmd, 1104*1dd728f5SVitor Soares .priv_xfers = dw_i3c_master_priv_xfers, 1105*1dd728f5SVitor Soares .attach_i2c_dev = dw_i3c_master_attach_i2c_dev, 1106*1dd728f5SVitor Soares .detach_i2c_dev = dw_i3c_master_detach_i2c_dev, 1107*1dd728f5SVitor Soares .i2c_xfers = dw_i3c_master_i2c_xfers, 1108*1dd728f5SVitor Soares .i2c_funcs = dw_i3c_master_i2c_funcs, 1109*1dd728f5SVitor Soares }; 1110*1dd728f5SVitor Soares 1111*1dd728f5SVitor Soares static int dw_i3c_probe(struct platform_device *pdev) 1112*1dd728f5SVitor Soares { 1113*1dd728f5SVitor Soares struct dw_i3c_master *master; 1114*1dd728f5SVitor Soares struct resource *res; 1115*1dd728f5SVitor Soares int ret, irq; 1116*1dd728f5SVitor Soares 1117*1dd728f5SVitor Soares master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); 1118*1dd728f5SVitor Soares if (!master) 1119*1dd728f5SVitor Soares return -ENOMEM; 1120*1dd728f5SVitor Soares 1121*1dd728f5SVitor Soares res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1122*1dd728f5SVitor Soares master->regs = devm_ioremap_resource(&pdev->dev, res); 1123*1dd728f5SVitor Soares if (IS_ERR(master->regs)) 1124*1dd728f5SVitor Soares return PTR_ERR(master->regs); 1125*1dd728f5SVitor Soares 1126*1dd728f5SVitor Soares master->core_clk = devm_clk_get(&pdev->dev, NULL); 1127*1dd728f5SVitor Soares if (IS_ERR(master->core_clk)) 1128*1dd728f5SVitor Soares return PTR_ERR(master->core_clk); 1129*1dd728f5SVitor Soares 1130*1dd728f5SVitor Soares master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev, 1131*1dd728f5SVitor Soares "core_rst"); 1132*1dd728f5SVitor Soares if (IS_ERR(master->core_rst)) 1133*1dd728f5SVitor Soares return PTR_ERR(master->core_rst); 1134*1dd728f5SVitor Soares 1135*1dd728f5SVitor Soares ret = clk_prepare_enable(master->core_clk); 1136*1dd728f5SVitor Soares if (ret) 1137*1dd728f5SVitor Soares goto err_disable_core_clk; 1138*1dd728f5SVitor Soares 1139*1dd728f5SVitor Soares reset_control_deassert(master->core_rst); 1140*1dd728f5SVitor Soares 1141*1dd728f5SVitor Soares spin_lock_init(&master->xferqueue.lock); 1142*1dd728f5SVitor Soares INIT_LIST_HEAD(&master->xferqueue.list); 1143*1dd728f5SVitor Soares 1144*1dd728f5SVitor Soares writel(INTR_ALL, master->regs + INTR_STATUS); 1145*1dd728f5SVitor Soares irq = platform_get_irq(pdev, 0); 1146*1dd728f5SVitor Soares ret = devm_request_irq(&pdev->dev, irq, 1147*1dd728f5SVitor Soares dw_i3c_master_irq_handler, 0, 1148*1dd728f5SVitor Soares dev_name(&pdev->dev), master); 1149*1dd728f5SVitor Soares if (ret) 1150*1dd728f5SVitor Soares goto err_assert_rst; 1151*1dd728f5SVitor Soares 1152*1dd728f5SVitor Soares platform_set_drvdata(pdev, master); 1153*1dd728f5SVitor Soares 1154*1dd728f5SVitor Soares /* Information regarding the FIFOs/QUEUEs depth */ 1155*1dd728f5SVitor Soares ret = readl(master->regs + QUEUE_STATUS_LEVEL); 1156*1dd728f5SVitor Soares master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret); 1157*1dd728f5SVitor Soares 1158*1dd728f5SVitor Soares ret = readl(master->regs + DATA_BUFFER_STATUS_LEVEL); 1159*1dd728f5SVitor Soares master->caps.datafifodepth = DATA_BUFFER_STATUS_LEVEL_TX(ret); 1160*1dd728f5SVitor Soares 1161*1dd728f5SVitor Soares ret = readl(master->regs + DEVICE_ADDR_TABLE_POINTER); 1162*1dd728f5SVitor Soares master->datstartaddr = ret; 1163*1dd728f5SVitor Soares master->maxdevs = ret >> 16; 1164*1dd728f5SVitor Soares master->free_pos = GENMASK(master->maxdevs - 1, 0); 1165*1dd728f5SVitor Soares 1166*1dd728f5SVitor Soares ret = i3c_master_register(&master->base, &pdev->dev, 1167*1dd728f5SVitor Soares &dw_mipi_i3c_ops, false); 1168*1dd728f5SVitor Soares if (ret) 1169*1dd728f5SVitor Soares goto err_assert_rst; 1170*1dd728f5SVitor Soares 1171*1dd728f5SVitor Soares return 0; 1172*1dd728f5SVitor Soares 1173*1dd728f5SVitor Soares err_assert_rst: 1174*1dd728f5SVitor Soares reset_control_assert(master->core_rst); 1175*1dd728f5SVitor Soares 1176*1dd728f5SVitor Soares err_disable_core_clk: 1177*1dd728f5SVitor Soares clk_disable_unprepare(master->core_clk); 1178*1dd728f5SVitor Soares 1179*1dd728f5SVitor Soares return ret; 1180*1dd728f5SVitor Soares } 1181*1dd728f5SVitor Soares 1182*1dd728f5SVitor Soares static int dw_i3c_remove(struct platform_device *pdev) 1183*1dd728f5SVitor Soares { 1184*1dd728f5SVitor Soares struct dw_i3c_master *master = platform_get_drvdata(pdev); 1185*1dd728f5SVitor Soares int ret; 1186*1dd728f5SVitor Soares 1187*1dd728f5SVitor Soares ret = i3c_master_unregister(&master->base); 1188*1dd728f5SVitor Soares if (ret) 1189*1dd728f5SVitor Soares return ret; 1190*1dd728f5SVitor Soares 1191*1dd728f5SVitor Soares reset_control_assert(master->core_rst); 1192*1dd728f5SVitor Soares 1193*1dd728f5SVitor Soares clk_disable_unprepare(master->core_clk); 1194*1dd728f5SVitor Soares 1195*1dd728f5SVitor Soares return 0; 1196*1dd728f5SVitor Soares } 1197*1dd728f5SVitor Soares 1198*1dd728f5SVitor Soares static const struct of_device_id dw_i3c_master_of_match[] = { 1199*1dd728f5SVitor Soares { .compatible = "snps,dw-i3c-master-1.00a", }, 1200*1dd728f5SVitor Soares {}, 1201*1dd728f5SVitor Soares }; 1202*1dd728f5SVitor Soares MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match); 1203*1dd728f5SVitor Soares 1204*1dd728f5SVitor Soares static struct platform_driver dw_i3c_driver = { 1205*1dd728f5SVitor Soares .probe = dw_i3c_probe, 1206*1dd728f5SVitor Soares .remove = dw_i3c_remove, 1207*1dd728f5SVitor Soares .driver = { 1208*1dd728f5SVitor Soares .name = "dw-i3c-master", 1209*1dd728f5SVitor Soares .of_match_table = of_match_ptr(dw_i3c_master_of_match), 1210*1dd728f5SVitor Soares }, 1211*1dd728f5SVitor Soares }; 1212*1dd728f5SVitor Soares module_platform_driver(dw_i3c_driver); 1213*1dd728f5SVitor Soares 1214*1dd728f5SVitor Soares MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>"); 1215*1dd728f5SVitor Soares MODULE_DESCRIPTION("DesignWare MIPI I3C driver"); 1216*1dd728f5SVitor Soares MODULE_LICENSE("GPL v2"); 1217