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