1 /* 2 * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com> 3 * Copyright (C) 2017 Jonathan Liu <net147@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of 8 * the License, or (at your option) any later version. 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/i2c.h> 13 #include <linux/iopoll.h> 14 15 #include "sun4i_hdmi.h" 16 17 #define SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK ( \ 18 SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION | \ 19 SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW | \ 20 SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW | \ 21 SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR | \ 22 SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR | \ 23 SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR \ 24 ) 25 26 /* FIFO request bit is set when FIFO level is above RX_THRESHOLD during read */ 27 #define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX 28 /* FIFO request bit is set when FIFO level is below TX_THRESHOLD during write */ 29 #define TX_THRESHOLD 1 30 31 static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read) 32 { 33 /* 34 * 1 byte takes 9 clock cycles (8 bits + 1 ACK) = 90 us for 100 kHz 35 * clock. As clock rate is fixed, just round it up to 100 us. 36 */ 37 const unsigned long byte_time_ns = 100; 38 const u32 mask = SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | 39 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | 40 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE; 41 u32 reg; 42 43 /* Limit transfer length by FIFO threshold */ 44 len = min_t(int, len, read ? (RX_THRESHOLD + 1) : 45 (SUN4I_HDMI_DDC_FIFO_SIZE - TX_THRESHOLD + 1)); 46 47 /* Wait until error, FIFO request bit set or transfer complete */ 48 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG, reg, 49 reg & mask, len * byte_time_ns, 100000)) 50 return -ETIMEDOUT; 51 52 if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) 53 return -EIO; 54 55 if (read) 56 readsb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); 57 else 58 writesb(hdmi->base + SUN4I_HDMI_DDC_FIFO_DATA_REG, buf, len); 59 60 /* Clear FIFO request bit */ 61 writel(SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST, 62 hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 63 64 return len; 65 } 66 67 static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg) 68 { 69 int i, len; 70 u32 reg; 71 72 /* Set FIFO direction */ 73 reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 74 reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; 75 reg |= (msg->flags & I2C_M_RD) ? 76 SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : 77 SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; 78 writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 79 80 /* Set I2C address */ 81 writel(SUN4I_HDMI_DDC_ADDR_SLAVE(msg->addr), 82 hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); 83 84 /* Set FIFO RX/TX thresholds and clear FIFO */ 85 reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 86 reg |= SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR; 87 reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MASK; 88 reg |= SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES(RX_THRESHOLD); 89 reg &= ~SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MASK; 90 reg |= SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES(TX_THRESHOLD); 91 writel(reg, hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); 92 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG, 93 reg, 94 !(reg & SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR), 95 100, 2000)) 96 return -EIO; 97 98 /* Set transfer length */ 99 writel(msg->len, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); 100 101 /* Set command */ 102 writel(msg->flags & I2C_M_RD ? 103 SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : 104 SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE, 105 hdmi->base + SUN4I_HDMI_DDC_CMD_REG); 106 107 /* Clear interrupt status bits */ 108 writel(SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK | 109 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST | 110 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE, 111 hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 112 113 /* Start command */ 114 reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 115 writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, 116 hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 117 118 /* Transfer bytes */ 119 for (i = 0; i < msg->len; i += len) { 120 len = fifo_transfer(hdmi, msg->buf + i, msg->len - i, 121 msg->flags & I2C_M_RD); 122 if (len <= 0) 123 return len; 124 } 125 126 /* Wait for command to finish */ 127 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, 128 reg, 129 !(reg & SUN4I_HDMI_DDC_CTRL_START_CMD), 130 100, 100000)) 131 return -EIO; 132 133 /* Check for errors */ 134 reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); 135 if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) || 136 !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) { 137 return -EIO; 138 } 139 140 return 0; 141 } 142 143 static int sun4i_hdmi_i2c_xfer(struct i2c_adapter *adap, 144 struct i2c_msg *msgs, int num) 145 { 146 struct sun4i_hdmi *hdmi = i2c_get_adapdata(adap); 147 u32 reg; 148 int err, i, ret = num; 149 150 for (i = 0; i < num; i++) { 151 if (!msgs[i].len) 152 return -EINVAL; 153 if (msgs[i].len > SUN4I_HDMI_DDC_BYTE_COUNT_MAX) 154 return -EINVAL; 155 } 156 157 /* Reset I2C controller */ 158 writel(SUN4I_HDMI_DDC_CTRL_ENABLE | SUN4I_HDMI_DDC_CTRL_RESET, 159 hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); 160 if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG, reg, 161 !(reg & SUN4I_HDMI_DDC_CTRL_RESET), 162 100, 2000)) 163 return -EIO; 164 165 writel(SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE | 166 SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE, 167 hdmi->base + SUN4I_HDMI_DDC_LINE_CTRL_REG); 168 169 clk_prepare_enable(hdmi->ddc_clk); 170 clk_set_rate(hdmi->ddc_clk, 100000); 171 172 for (i = 0; i < num; i++) { 173 err = xfer_msg(hdmi, &msgs[i]); 174 if (err) { 175 ret = err; 176 break; 177 } 178 } 179 180 clk_disable_unprepare(hdmi->ddc_clk); 181 return ret; 182 } 183 184 static u32 sun4i_hdmi_i2c_func(struct i2c_adapter *adap) 185 { 186 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 187 } 188 189 static const struct i2c_algorithm sun4i_hdmi_i2c_algorithm = { 190 .master_xfer = sun4i_hdmi_i2c_xfer, 191 .functionality = sun4i_hdmi_i2c_func, 192 }; 193 194 int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi) 195 { 196 struct i2c_adapter *adap; 197 int ret = 0; 198 199 ret = sun4i_ddc_create(hdmi, hdmi->tmds_clk); 200 if (ret) 201 return ret; 202 203 adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL); 204 if (!adap) 205 return -ENOMEM; 206 207 adap->owner = THIS_MODULE; 208 adap->class = I2C_CLASS_DDC; 209 adap->algo = &sun4i_hdmi_i2c_algorithm; 210 strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name)); 211 i2c_set_adapdata(adap, hdmi); 212 213 ret = i2c_add_adapter(adap); 214 if (ret) 215 return ret; 216 217 hdmi->i2c = adap; 218 219 return ret; 220 } 221