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