blob: 9d1d70670b9546c76f401343fc3b8a3e92f02ea6 [file] [log] [blame]
Ryan Chen0c7132a2023-01-30 14:19:24 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright ASPEED Technology Inc.
4 */
Ryan Chen0c7132a2023-01-30 14:19:24 +08005#include <clk.h>
6#include <dm.h>
7#include <errno.h>
8#include <fdtdec.h>
9#include <i2c.h>
10#include <log.h>
11#include <regmap.h>
12#include <reset.h>
13#include <asm/io.h>
14#include <linux/iopoll.h>
15#include "ast2600_i2c.h"
16
17/* Device private data */
18struct ast2600_i2c_priv {
19 struct clk clk;
20 struct ast2600_i2c_regs *regs;
21 void __iomem *global;
22};
23
24static int ast2600_i2c_read_data(struct ast2600_i2c_priv *priv, u8 chip_addr,
25 u8 *buffer, size_t len, bool send_stop)
26{
27 int rx_cnt, ret = 0;
28 u32 cmd, isr;
29
30 for (rx_cnt = 0; rx_cnt < len; rx_cnt++, buffer++) {
31 cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) |
32 I2CM_RX_CMD;
33 if (!rx_cnt)
34 cmd |= I2CM_START_CMD;
35
36 if ((len - 1) == rx_cnt)
37 cmd |= I2CM_RX_CMD_LAST;
38
39 if (send_stop && ((len - 1) == rx_cnt))
40 cmd |= I2CM_STOP_CMD;
41
42 writel(cmd, &priv->regs->cmd_sts);
43
44 ret = readl_poll_timeout(&priv->regs->isr, isr,
45 isr & I2CM_PKT_DONE,
46 I2C_TIMEOUT_US);
47 if (ret)
48 return -ETIMEDOUT;
49
50 *buffer =
51 I2CC_GET_RX_BUFF(readl(&priv->regs->trx_buff));
52
53 writel(I2CM_PKT_DONE, &priv->regs->isr);
54
55 if (isr & I2CM_TX_NAK)
56 return -EREMOTEIO;
57 }
58
59 return 0;
60}
61
62static int ast2600_i2c_write_data(struct ast2600_i2c_priv *priv, u8 chip_addr,
63 u8 *buffer, size_t len, bool send_stop)
64{
65 int tx_cnt, ret = 0;
66 u32 cmd, isr;
67
68 if (!len) {
69 cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) |
70 I2CM_START_CMD;
71 writel(cmd, &priv->regs->cmd_sts);
72 ret = readl_poll_timeout(&priv->regs->isr, isr,
73 isr & I2CM_PKT_DONE,
74 I2C_TIMEOUT_US);
75 if (ret)
76 return -ETIMEDOUT;
77
78 writel(I2CM_PKT_DONE, &priv->regs->isr);
79
80 if (isr & I2CM_TX_NAK)
81 return -EREMOTEIO;
82 }
83
84 for (tx_cnt = 0; tx_cnt < len; tx_cnt++, buffer++) {
85 cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr);
86 cmd |= I2CM_TX_CMD;
87
88 if (!tx_cnt)
89 cmd |= I2CM_START_CMD;
90
91 if (send_stop && ((len - 1) == tx_cnt))
92 cmd |= I2CM_STOP_CMD;
93
94 writel(*buffer, &priv->regs->trx_buff);
95 writel(cmd, &priv->regs->cmd_sts);
96 ret = readl_poll_timeout(&priv->regs->isr, isr,
97 isr & I2CM_PKT_DONE,
98 I2C_TIMEOUT_US);
99 if (ret)
100 return -ETIMEDOUT;
101
102 writel(I2CM_PKT_DONE, &priv->regs->isr);
103
104 if (isr & I2CM_TX_NAK)
105 return -EREMOTEIO;
106 }
107
108 return 0;
109}
110
111static int ast2600_i2c_deblock(struct udevice *dev)
112{
113 struct ast2600_i2c_priv *priv = dev_get_priv(dev);
114 u32 csr = readl(&priv->regs->cmd_sts);
115 u32 isr;
116 int ret;
117
118 /* reinit */
119 writel(0, &priv->regs->fun_ctrl);
120 /* Enable Master Mode. Assuming single-master */
121 writel(I2CC_BUS_AUTO_RELEASE | I2CC_MASTER_EN |
122 I2CC_MULTI_MASTER_DIS,
123 &priv->regs->fun_ctrl);
124
125 csr = readl(&priv->regs->cmd_sts);
126
127 if (!(csr & I2CC_SDA_LINE_STS) &&
128 (csr & I2CC_SCL_LINE_STS)) {
129 debug("Bus stuck (%x), attempting recovery\n", csr);
130 writel(I2CM_RECOVER_CMD_EN, &priv->regs->cmd_sts);
131 ret = readl_poll_timeout(&priv->regs->isr, isr,
132 isr & (I2CM_BUS_RECOVER_FAIL |
133 I2CM_BUS_RECOVER),
134 I2C_TIMEOUT_US);
135 writel(~0, &priv->regs->isr);
136 if (ret)
137 return -EREMOTEIO;
138 }
139
140 return 0;
141}
142
143static int ast2600_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
144{
145 struct ast2600_i2c_priv *priv = dev_get_priv(dev);
146 int ret;
147
148 if (readl(&priv->regs->trx_buff) & I2CC_BUS_BUSY_STS)
149 return -EREMOTEIO;
150
151 for (; nmsgs > 0; nmsgs--, msg++) {
152 if (msg->flags & I2C_M_RD) {
153 debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
154 msg->addr, msg->len, msg->flags);
155 ret = ast2600_i2c_read_data(priv, msg->addr, msg->buf,
156 msg->len, (nmsgs == 1));
157 } else {
158 debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
159 msg->addr, msg->len, msg->flags);
160 ret = ast2600_i2c_write_data(priv, msg->addr, msg->buf,
161 msg->len, (nmsgs == 1));
162 }
163 if (ret) {
164 debug("%s: error (%d)\n", __func__, ret);
165 return -EREMOTEIO;
166 }
167 }
168
169 return 0;
170}
171
172static int ast2600_i2c_set_speed(struct udevice *dev, unsigned int speed)
173{
174 struct ast2600_i2c_priv *priv = dev_get_priv(dev);
175 unsigned long base_clk1, base_clk2, base_clk3, base_clk4;
176 int multiply = 10;
177 int baseclk_idx;
178 u32 clk_div_reg;
179 u32 apb_clk;
180 u32 scl_low;
181 u32 scl_high;
182 int divisor;
183 int inc = 0;
184 u32 data;
185
186 debug("Setting speed for I2C%d to <%u>\n", dev->seq_, speed);
187 if (!speed) {
188 debug("No valid speed specified\n");
189 return -EINVAL;
190 }
191
192 apb_clk = clk_get_rate(&priv->clk);
193
194 clk_div_reg = readl(priv->global + I2CG_CLK_DIV_CTRL);
195
196 base_clk1 = (apb_clk * multiply) / (((GET_CLK1_DIV(clk_div_reg) + 2) * multiply) / 2);
197 base_clk2 = (apb_clk * multiply) / (((GET_CLK2_DIV(clk_div_reg) + 2) * multiply) / 2);
198 base_clk3 = (apb_clk * multiply) / (((GET_CLK3_DIV(clk_div_reg) + 2) * multiply) / 2);
199 base_clk4 = (apb_clk * multiply) / (((GET_CLK4_DIV(clk_div_reg) + 2) * multiply) / 2);
200
201 if ((apb_clk / speed) <= 32) {
202 baseclk_idx = 0;
203 divisor = DIV_ROUND_UP(apb_clk, speed);
204 } else if ((base_clk1 / speed) <= 32) {
205 baseclk_idx = 1;
206 divisor = DIV_ROUND_UP(base_clk1, speed);
207 } else if ((base_clk2 / speed) <= 32) {
208 baseclk_idx = 2;
209 divisor = DIV_ROUND_UP(base_clk2, speed);
210 } else if ((base_clk3 / speed) <= 32) {
211 baseclk_idx = 3;
212 divisor = DIV_ROUND_UP(base_clk3, speed);
213 } else {
214 baseclk_idx = 4;
215 divisor = DIV_ROUND_UP(base_clk4, speed);
216 inc = 0;
217 while ((divisor + inc) > 32) {
218 inc |= divisor & 0x1;
219 divisor >>= 1;
220 baseclk_idx++;
221 }
222 divisor += inc;
223 }
224 divisor = min_t(int, divisor, 32);
225 baseclk_idx &= 0xf;
226 scl_low = ((divisor * 9) / 16) - 1;
227 scl_low = min_t(u32, scl_low, 0xf);
228 scl_high = (divisor - scl_low - 2) & 0xf;
229 /* Divisor : Base Clock : tCKHighMin : tCK High : tCK Low */
230 data = ((scl_high - 1) << 20) | (scl_high << 16) | (scl_low << 12) |
231 baseclk_idx;
232 /* Set AC Timing */
233 writel(data, &priv->regs->ac_timing);
234
235 return 0;
236}
237
238static int ast2600_i2c_probe(struct udevice *dev)
239{
240 struct ast2600_i2c_priv *priv = dev_get_priv(dev);
241 ofnode i2c_global_node;
242
243 /* find global base address */
244 i2c_global_node = ofnode_get_parent(dev_ofnode(dev));
245 priv->global = (void *)ofnode_get_addr(i2c_global_node);
246 if (IS_ERR(priv->global)) {
247 debug("%s(): can't get global\n", __func__);
248 return PTR_ERR(priv->global);
249 }
250
251 /* Reset device */
252 writel(0, &priv->regs->fun_ctrl);
253 /* Enable Master Mode. Assuming single-master */
254 writel(I2CC_BUS_AUTO_RELEASE | I2CC_MASTER_EN |
255 I2CC_MULTI_MASTER_DIS,
256 &priv->regs->fun_ctrl);
257
258 writel(0, &priv->regs->ier);
259 /* Clear Interrupt */
260 writel(~0, &priv->regs->isr);
261
262 return 0;
263}
264
265static int ast2600_i2c_of_to_plat(struct udevice *dev)
266{
267 struct ast2600_i2c_priv *priv = dev_get_priv(dev);
268 int ret;
269
270 priv->regs = dev_read_addr_ptr(dev);
271 if (!priv->regs)
272 return -EINVAL;
273
274 ret = clk_get_by_index(dev, 0, &priv->clk);
275 if (ret < 0) {
276 debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
277 ret);
278 return ret;
279 }
280
281 return 0;
282}
283
284static const struct dm_i2c_ops ast2600_i2c_ops = {
285 .xfer = ast2600_i2c_xfer,
286 .deblock = ast2600_i2c_deblock,
287 .set_bus_speed = ast2600_i2c_set_speed,
288};
289
290static const struct udevice_id ast2600_i2c_ids[] = {
291 { .compatible = "aspeed,ast2600-i2c" },
292 {},
293};
294
295U_BOOT_DRIVER(ast2600_i2c) = {
296 .name = "ast2600_i2c",
297 .id = UCLASS_I2C,
298 .of_match = ast2600_i2c_ids,
299 .probe = ast2600_i2c_probe,
300 .of_to_plat = ast2600_i2c_of_to_plat,
301 .priv_auto = sizeof(struct ast2600_i2c_priv),
302 .ops = &ast2600_i2c_ops,
303};
304
305struct ast2600_i2c_global_priv {
306 void __iomem *regs;
307 struct reset_ctl reset;
308};
309
310/*
311 * APB clk : 100Mhz
312 * div : scl : baseclk [APB/((div/2) + 1)] : tBuf [1/bclk * 16]
313 * I2CG10[31:24] base clk4 for i2c auto recovery timeout counter (0xC6)
314 * I2CG10[23:16] base clk3 for Standard-mode (100Khz) min tBuf 4.7us
315 * 0x3c : 100.8Khz : 3.225Mhz : 4.96us
316 * 0x3d : 99.2Khz : 3.174Mhz : 5.04us
317 * 0x3e : 97.65Khz : 3.125Mhz : 5.12us
318 * 0x40 : 97.75Khz : 3.03Mhz : 5.28us
319 * 0x41 : 99.5Khz : 2.98Mhz : 5.36us (default)
320 * I2CG10[15:8] base clk2 for Fast-mode (400Khz) min tBuf 1.3us
321 * 0x12 : 400Khz : 10Mhz : 1.6us
322 * I2CG10[7:0] base clk1 for Fast-mode Plus (1Mhz) min tBuf 0.5us
323 * 0x08 : 1Mhz : 20Mhz : 0.8us
324 */
325
326static int aspeed_i2c_global_probe(struct udevice *dev)
327{
328 struct ast2600_i2c_global_priv *i2c_global = dev_get_priv(dev);
329 void __iomem *regs;
330 int ret = 0;
331
332 i2c_global->regs = dev_read_addr_ptr(dev);
333 if (!i2c_global->regs)
334 return -EINVAL;
335
336 debug("%s(dev=%p)\n", __func__, dev);
337
338 regs = i2c_global->regs;
339
340 ret = reset_get_by_index(dev, 0, &i2c_global->reset);
341 if (ret) {
342 printf("%s(): Failed to get reset signal\n", __func__);
343 return ret;
344 }
345
346 reset_deassert(&i2c_global->reset);
347
348 writel(GLOBAL_INIT, regs + I2CG_CTRL);
349 writel(I2CCG_DIV_CTRL, regs + I2CG_CLK_DIV_CTRL);
350
351 return 0;
352}
353
354static const struct udevice_id aspeed_i2c_global_ids[] = {
355 { .compatible = "aspeed,ast2600-i2c-global", },
356 { }
357};
358
359U_BOOT_DRIVER(aspeed_i2c_global) = {
360 .name = "aspeed_i2c_global",
361 .id = UCLASS_MISC,
362 .of_match = aspeed_i2c_global_ids,
363 .probe = aspeed_i2c_global_probe,
364 .priv_auto = sizeof(struct ast2600_i2c_global_priv),
365};