blob: fdedf63b56f738486e19ff85951b8e59a7ebef46 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Laurie8a14c392016-06-07 13:40:11 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpigen.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Duncan Laurie8a14c392016-06-07 13:40:11 -07005#include <console/console.h>
6#include <device/device.h>
Aaron Durbinb7d79cd2018-01-22 21:31:48 -07007#include <device/i2c_bus.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02008#include <device/i2c_simple.h>
Duncan Laurie222381e2016-06-21 10:41:19 -07009#include <string.h>
Duncan Laurie8a14c392016-06-07 13:40:11 -070010#include <timer.h>
Felix Helda7041562022-01-31 14:21:57 +010011#include <types.h>
Chris Chingb8dc63b2017-12-06 14:26:15 -070012#include "dw_i2c.h"
Duncan Laurie8a14c392016-06-07 13:40:11 -070013
Duncan Lauriea87170b2016-11-03 10:43:14 -070014/* Use a ~10ms timeout for various operations */
Chris Chingb8dc63b2017-12-06 14:26:15 -070015#define DW_I2C_TIMEOUT_US 10000
Jes Klinke19baa9d2022-02-22 16:00:09 -080016/* Timeout for waiting for FIFO to flush */
17#define DW_I2C_FLUSH_TIMEOUT_US 160000
Duncan Laurie8a14c392016-06-07 13:40:11 -070018
19/* High and low times in different speed modes (in ns) */
20enum {
Duncan Laurie88a1f142016-06-13 10:28:36 -070021 /* SDA Hold Time */
22 DEFAULT_SDA_HOLD_TIME = 300,
Duncan Laurie8a14c392016-06-07 13:40:11 -070023 /* Standard Speed */
24 MIN_SS_SCL_HIGHTIME = 4000,
25 MIN_SS_SCL_LOWTIME = 4700,
Duncan Laurie88a1f142016-06-13 10:28:36 -070026 /* Fast Speed */
Duncan Laurie8a14c392016-06-07 13:40:11 -070027 MIN_FS_SCL_HIGHTIME = 600,
28 MIN_FS_SCL_LOWTIME = 1300,
Duncan Laurie88a1f142016-06-13 10:28:36 -070029 /* Fast Plus Speed */
30 MIN_FP_SCL_HIGHTIME = 260,
31 MIN_FP_SCL_LOWTIME = 500,
Duncan Laurie8a14c392016-06-07 13:40:11 -070032 /* High Speed */
33 MIN_HS_SCL_HIGHTIME = 60,
34 MIN_HS_SCL_LOWTIME = 160,
35};
36
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -060037/* Frequency represented as ticks per ns. Can also be used to calculate
38 * the number of ticks to meet a time target or the period. */
39struct freq {
40 uint32_t ticks;
41 uint32_t ns;
42};
43
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +053044/* Control register definitions */
45enum {
46 CONTROL_MASTER_MODE = (1 << 0),
47 CONTROL_SPEED_SS = (1 << 1),
Felix Held6151ff32022-02-03 15:31:55 +010048 CONTROL_SPEED_FS = (2 << 1),
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +053049 CONTROL_SPEED_HS = (3 << 1),
50 CONTROL_SPEED_MASK = (3 << 1),
51 CONTROL_10BIT_SLAVE = (1 << 3),
52 CONTROL_10BIT_MASTER = (1 << 4),
53 CONTROL_RESTART_ENABLE = (1 << 5),
54 CONTROL_SLAVE_DISABLE = (1 << 6),
55};
56
57/* Command/Data register definitions */
58enum {
59 CMD_DATA_CMD = (1 << 8),
60 CMD_DATA_STOP = (1 << 9),
61};
62
63/* Status register definitions */
64enum {
65 STATUS_ACTIVITY = (1 << 0),
66 STATUS_TX_FIFO_NOT_FULL = (1 << 1),
67 STATUS_TX_FIFO_EMPTY = (1 << 2),
68 STATUS_RX_FIFO_NOT_EMPTY = (1 << 3),
69 STATUS_RX_FIFO_FULL = (1 << 4),
70 STATUS_MASTER_ACTIVITY = (1 << 5),
71 STATUS_SLAVE_ACTIVITY = (1 << 6),
72};
73
74/* Enable register definitions */
75enum {
76 ENABLE_CONTROLLER = (1 << 0),
77};
78
79/* Interrupt status register definitions */
80enum {
81 INTR_STAT_RX_UNDER = (1 << 0),
82 INTR_STAT_RX_OVER = (1 << 1),
83 INTR_STAT_RX_FULL = (1 << 2),
84 INTR_STAT_TX_OVER = (1 << 3),
85 INTR_STAT_TX_EMPTY = (1 << 4),
86 INTR_STAT_RD_REQ = (1 << 5),
87 INTR_STAT_TX_ABORT = (1 << 6),
88 INTR_STAT_RX_DONE = (1 << 7),
89 INTR_STAT_ACTIVITY = (1 << 8),
90 INTR_STAT_STOP_DET = (1 << 9),
91 INTR_STAT_START_DET = (1 << 10),
92 INTR_STAT_GEN_CALL = (1 << 11),
93};
94
Chris Chingb8dc63b2017-12-06 14:26:15 -070095/* I2C Controller MMIO register space */
96struct dw_i2c_regs {
Raul E Rangel6191b852020-04-09 11:37:05 -060097 uint32_t control; /* 0x0 */
98 uint32_t target_addr; /* 0x4 */
99 uint32_t slave_addr; /* 0x8 */
100 uint32_t master_addr; /* 0xc */
101 uint32_t cmd_data; /* 0x10 */
102 uint32_t ss_scl_hcnt; /* 0x14 */
103 uint32_t ss_scl_lcnt; /* 0x18 */
104 uint32_t fs_scl_hcnt; /* 0x1c */
105 uint32_t fs_scl_lcnt; /* 0x20 */
106 uint32_t hs_scl_hcnt; /* 0x24 */
107 uint32_t hs_scl_lcnt; /* 0x28 */
108 uint32_t intr_stat; /* 0x2c */
109 uint32_t intr_mask; /* 0x30 */
110 uint32_t raw_intr_stat; /* 0x34 */
111 uint32_t rx_thresh; /* 0x38 */
112 uint32_t tx_thresh; /* 0x3c */
113 uint32_t clear_intr; /* 0x40 */
114 uint32_t clear_rx_under_intr; /* 0x44 */
115 uint32_t clear_rx_over_intr; /* 0x48 */
116 uint32_t clear_tx_over_intr; /* 0x4c */
117 uint32_t clear_rd_req_intr; /* 0x50 */
118 uint32_t clear_tx_abrt_intr; /* 0x54 */
119 uint32_t clear_rx_done_intr; /* 0x58 */
120 uint32_t clear_activity_intr; /* 0x5c */
121 uint32_t clear_stop_det_intr; /* 0x60 */
122 uint32_t clear_start_det_intr; /* 0x64 */
123 uint32_t clear_gen_call_intr; /* 0x68 */
124 uint32_t enable; /* 0x6c */
125 uint32_t status; /* 0x70 */
126 uint32_t tx_level; /* 0x74 */
127 uint32_t rx_level; /* 0x78 */
128 uint32_t sda_hold; /* 0x7c */
129 uint32_t tx_abort_source; /* 0x80 */
130 uint32_t slv_data_nak_only; /* 0x84 */
131 uint32_t dma_cr; /* 0x88 */
132 uint32_t dma_tdlr; /* 0x8c */
133 uint32_t dma_rdlr; /* 0x90 */
134 uint32_t sda_setup; /* 0x94 */
135 uint32_t ack_general_call; /* 0x98 */
136 uint32_t enable_status; /* 0x9c */
137 uint32_t fs_spklen; /* 0xa0 */
138 uint32_t hs_spklen; /* 0xa4 */
139 uint32_t clr_restart_det; /* 0xa8 */
140 uint32_t reserved[18]; /* 0xac - 0xf0 */
141 uint32_t comp_param1; /* 0xf4 */
142 uint32_t comp_version; /* 0xf8 */
143 uint32_t comp_type; /* 0xfc */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700144} __packed;
145
Raul E Rangel6191b852020-04-09 11:37:05 -0600146/* Constant value defined in the DesignWare DW_apb_i2c Databook. */
147#define DW_I2C_COMP_TYPE 0x44570140
148
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600149static const struct i2c_descriptor {
150 enum i2c_speed speed;
151 struct freq freq;
152 int min_thigh_ns;
153 int min_tlow_ns;
154} speed_descriptors[] = {
155 {
156 .speed = I2C_SPEED_STANDARD,
157 .freq = {
158 .ticks = 100,
159 .ns = 1000*1000,
160 },
161 .min_thigh_ns = MIN_SS_SCL_HIGHTIME,
162 .min_tlow_ns = MIN_SS_SCL_LOWTIME,
163 },
164 {
165 .speed = I2C_SPEED_FAST,
166 .freq = {
167 .ticks = 400,
168 .ns = 1000*1000,
169 },
170 .min_thigh_ns = MIN_FS_SCL_HIGHTIME,
171 .min_tlow_ns = MIN_FS_SCL_LOWTIME,
172 },
173 {
174 .speed = I2C_SPEED_FAST_PLUS,
175 .freq = {
176 .ticks = 1,
177 .ns = 1000,
178 },
179 .min_thigh_ns = MIN_FP_SCL_HIGHTIME,
180 .min_tlow_ns = MIN_FP_SCL_LOWTIME,
181 },
182 {
183 /* 100pF max capacitance */
184 .speed = I2C_SPEED_HIGH,
185 .freq = {
186 .ticks = 3400,
187 .ns = 1000*1000,
188 },
189 .min_thigh_ns = MIN_HS_SCL_HIGHTIME,
190 .min_tlow_ns = MIN_HS_SCL_LOWTIME,
191 },
192};
193
194static const struct soc_clock {
195 int clk_speed_mhz;
196 struct freq freq;
197} soc_clocks[] = {
198 {
199 .clk_speed_mhz = 120,
200 .freq = {
201 .ticks = 120,
202 .ns = 1000,
203 },
204 },
205 {
206 .clk_speed_mhz = 133,
207 .freq = {
208 .ticks = 400,
209 .ns = 3000,
210 },
211 },
Duncan Laurie4afefd62018-12-05 15:38:13 -0800212 {
Martin Rothba37b942019-12-16 23:19:29 -0700213 .clk_speed_mhz = 150,
214 .freq = {
215 .ticks = 600,
216 .ns = 4000,
217 },
218 },
219 {
Duncan Laurie4afefd62018-12-05 15:38:13 -0800220 .clk_speed_mhz = 216,
221 .freq = {
222 .ticks = 1080,
223 .ns = 5000,
224 },
225 },
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600226};
227
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600228static const struct i2c_descriptor *get_bus_descriptor(enum i2c_speed speed)
229{
230 size_t i;
231
232 for (i = 0; i < ARRAY_SIZE(speed_descriptors); i++)
233 if (speed == speed_descriptors[i].speed)
234 return &speed_descriptors[i];
235
236 return NULL;
237}
238
239static const struct soc_clock *get_soc_descriptor(int ic_clk)
240{
241 size_t i;
242
243 for (i = 0; i < ARRAY_SIZE(soc_clocks); i++)
244 if (ic_clk == soc_clocks[i].clk_speed_mhz)
245 return &soc_clocks[i];
246
247 return NULL;
248}
249
250static int counts_from_time(const struct freq *f, int ns)
251{
252 return DIV_ROUND_UP(f->ticks * ns, f->ns);
253}
254
255static int counts_from_freq(const struct freq *fast, const struct freq *slow)
256{
257 return DIV_ROUND_UP(fast->ticks * slow->ns, fast->ns * slow->ticks);
258}
259
Duncan Laurie8a14c392016-06-07 13:40:11 -0700260/* Enable this I2C controller */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700261static void dw_i2c_enable(struct dw_i2c_regs *regs)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700262{
263 uint32_t enable = read32(&regs->enable);
264
265 if (!(enable & ENABLE_CONTROLLER))
266 write32(&regs->enable, enable | ENABLE_CONTROLLER);
267}
268
269/* Disable this I2C controller */
Felix Held2a542da2022-01-31 14:36:30 +0100270static enum cb_err dw_i2c_disable(struct dw_i2c_regs *regs)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700271{
272 uint32_t enable = read32(&regs->enable);
273
274 if (enable & ENABLE_CONTROLLER) {
275 struct stopwatch sw;
276
277 write32(&regs->enable, enable & ~ENABLE_CONTROLLER);
278
279 /* Wait for enable bit to clear */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700280 stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US);
Duncan Laurie772555a22016-09-12 11:20:27 -0700281 while (read32(&regs->enable_status) & ENABLE_CONTROLLER)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700282 if (stopwatch_expired(&sw))
Felix Held2a542da2022-01-31 14:36:30 +0100283 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700284 }
285
Felix Held2a542da2022-01-31 14:36:30 +0100286 return CB_SUCCESS;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700287}
288
289/* Wait for this I2C controller to go idle for transmit */
Felix Held2a542da2022-01-31 14:36:30 +0100290static enum cb_err dw_i2c_wait_for_bus_idle(struct dw_i2c_regs *regs)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700291{
292 struct stopwatch sw;
293
294 /* Start timeout for up to 16 bytes in FIFO */
Jes Klinke19baa9d2022-02-22 16:00:09 -0800295 stopwatch_init_usecs_expire(&sw, DW_I2C_FLUSH_TIMEOUT_US);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700296
297 while (!stopwatch_expired(&sw)) {
298 uint32_t status = read32(&regs->status);
299
300 /* Check for master activity and keep waiting */
301 if (status & STATUS_MASTER_ACTIVITY)
302 continue;
303
304 /* Check for TX FIFO empty to indicate TX idle */
305 if (status & STATUS_TX_FIFO_EMPTY)
Felix Held2a542da2022-01-31 14:36:30 +0100306 return CB_SUCCESS;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700307 }
308
309 /* Timed out while waiting for bus to go idle */
Felix Held2a542da2022-01-31 14:36:30 +0100310 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700311}
312
313/* Transfer one byte of one segment, sending stop bit if requested */
Felix Held2a542da2022-01-31 14:36:30 +0100314static enum cb_err dw_i2c_transfer_byte(struct dw_i2c_regs *regs,
315 const struct i2c_msg *segment,
316 size_t byte, int send_stop)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700317{
318 struct stopwatch sw;
319 uint32_t cmd = CMD_DATA_CMD; /* Read op */
320
Jes Klinke19baa9d2022-02-22 16:00:09 -0800321 stopwatch_init_usecs_expire(&sw, CONFIG_I2C_TRANSFER_TIMEOUT_US);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700322
Nico Huber029dfff2017-07-12 17:59:16 +0200323 if (!(segment->flags & I2C_M_RD)) {
Duncan Laurie8a14c392016-06-07 13:40:11 -0700324 /* Write op only: Wait for FIFO not full */
325 while (!(read32(&regs->status) & STATUS_TX_FIFO_NOT_FULL)) {
326 if (stopwatch_expired(&sw)) {
327 printk(BIOS_ERR, "I2C transmit timeout\n");
Felix Held2a542da2022-01-31 14:36:30 +0100328 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700329 }
330 }
331 cmd = segment->buf[byte];
332 }
333
334 /* Send stop on last byte, if desired */
335 if (send_stop && byte == segment->len - 1)
336 cmd |= CMD_DATA_STOP;
337
338 write32(&regs->cmd_data, cmd);
339
Nico Huber029dfff2017-07-12 17:59:16 +0200340 if (segment->flags & I2C_M_RD) {
Duncan Laurie8a14c392016-06-07 13:40:11 -0700341 /* Read op only: Wait for FIFO data and store it */
342 while (!(read32(&regs->status) & STATUS_RX_FIFO_NOT_EMPTY)) {
343 if (stopwatch_expired(&sw)) {
344 printk(BIOS_ERR, "I2C receive timeout\n");
Felix Held2a542da2022-01-31 14:36:30 +0100345 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700346 }
347 }
348 segment->buf[byte] = read32(&regs->cmd_data);
349 }
350
Felix Held2a542da2022-01-31 14:36:30 +0100351 return CB_SUCCESS;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700352}
353
Felix Held2a542da2022-01-31 14:36:30 +0100354static enum cb_err _dw_i2c_transfer(unsigned int bus, const struct i2c_msg *segments,
355 size_t count)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700356{
357 struct stopwatch sw;
Chris Chingb8dc63b2017-12-06 14:26:15 -0700358 struct dw_i2c_regs *regs;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700359 size_t byte;
Felix Held2a542da2022-01-31 14:36:30 +0100360 enum cb_err ret = CB_ERR;
Matt DeVillier57097132022-04-11 17:10:09 -0500361 bool seg_zero_len = segments->len == 0;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700362
Chris Chingb8dc63b2017-12-06 14:26:15 -0700363 regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700364 if (!regs) {
365 printk(BIOS_ERR, "I2C bus %u base address not found\n", bus);
Felix Held2a542da2022-01-31 14:36:30 +0100366 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700367 }
368
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700369 /* The assumption is that the host controller is disabled -- either
Elyes HAOUAS18958382018-08-07 12:23:16 +0200370 after running this function or from performing the initialization
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700371 sequence in dw_i2c_init(). */
Duncan Laurie8a14c392016-06-07 13:40:11 -0700372
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700373 /* Set target slave address */
374 write32(&regs->target_addr, segments->slave);
375
376 dw_i2c_enable(regs);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700377
Matt DeVillier57097132022-04-11 17:10:09 -0500378 if (seg_zero_len)
379 /* stop immediately */
380 write32(&regs->cmd_data, CMD_DATA_STOP);
381
Duncan Laurie8a14c392016-06-07 13:40:11 -0700382 /* Process each segment */
383 while (count--) {
Julius Wernercd49cce2019-03-05 16:53:33 -0800384 if (CONFIG(DRIVERS_I2C_DESIGNWARE_DEBUG)) {
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700385 printk(BIOS_DEBUG, "i2c %u:%02x %s %d bytes : ",
Nico Huber029dfff2017-07-12 17:59:16 +0200386 bus, segments->slave,
387 (segments->flags & I2C_M_RD) ? "R" : "W",
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700388 segments->len);
Chris Chingb8dc63b2017-12-06 14:26:15 -0700389 }
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700390
Duncan Laurie8a14c392016-06-07 13:40:11 -0700391 /* Read or write each byte in segment */
392 for (byte = 0; byte < segments->len; byte++) {
393 /*
394 * Set stop condition on final segment only.
395 * Repeated start will be automatically generated
396 * by the controller on R->W or W->R switch.
397 */
Felix Held2a542da2022-01-31 14:36:30 +0100398 if (dw_i2c_transfer_byte(regs, segments, byte, count == 0) !=
399 CB_SUCCESS) {
Duncan Laurie8a14c392016-06-07 13:40:11 -0700400 printk(BIOS_ERR, "I2C %s failed: bus %u "
Nico Huber029dfff2017-07-12 17:59:16 +0200401 "addr 0x%02x\n",
402 (segments->flags & I2C_M_RD) ?
403 "read" : "write", bus, segments->slave);
Duncan Laurie772555a22016-09-12 11:20:27 -0700404 goto out;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700405 }
406 }
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700407
Julius Wernercd49cce2019-03-05 16:53:33 -0800408 if (CONFIG(DRIVERS_I2C_DESIGNWARE_DEBUG)) {
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700409 int j;
410 for (j = 0; j < segments->len; j++)
411 printk(BIOS_DEBUG, "%02x ", segments->buf[j]);
Maulik V Vaghela794d0972018-03-20 16:52:00 +0530412 printk(BIOS_DEBUG, "\n");
Duncan Laurief8a7b2c2016-09-12 11:21:40 -0700413 }
414
Duncan Laurie8a14c392016-06-07 13:40:11 -0700415 segments++;
416 }
417
418 /* Wait for interrupt status to indicate transfer is complete */
Jes Klinke19baa9d2022-02-22 16:00:09 -0800419 stopwatch_init_usecs_expire(&sw, CONFIG_I2C_TRANSFER_TIMEOUT_US);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700420 while (!(read32(&regs->raw_intr_stat) & INTR_STAT_STOP_DET)) {
421 if (stopwatch_expired(&sw)) {
422 printk(BIOS_ERR, "I2C stop bit not received\n");
Duncan Laurie772555a22016-09-12 11:20:27 -0700423 goto out;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700424 }
425 }
426
427 /* Read to clear INTR_STAT_STOP_DET */
428 read32(&regs->clear_stop_det_intr);
429
Kangheui Wonb2c39b52020-11-09 17:49:48 +1100430 /* Check TX abort */
431 if (read32(&regs->raw_intr_stat) & INTR_STAT_TX_ABORT) {
Matt DeVillier57097132022-04-11 17:10:09 -0500432 printk(seg_zero_len ? BIOS_SPEW : BIOS_ERR, "I2C TX abort detected (%08x)\n",
433 read32(&regs->tx_abort_source));
Kangheui Wonb2c39b52020-11-09 17:49:48 +1100434 /* clear INTR_STAT_TX_ABORT */
435 read32(&regs->clear_tx_abrt_intr);
436 goto out;
437 }
438
Duncan Laurie8a14c392016-06-07 13:40:11 -0700439 /* Wait for the bus to go idle */
Felix Held2a542da2022-01-31 14:36:30 +0100440 if (dw_i2c_wait_for_bus_idle(regs) != CB_SUCCESS) {
Duncan Laurie8a14c392016-06-07 13:40:11 -0700441 printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus);
Duncan Laurie772555a22016-09-12 11:20:27 -0700442 goto out;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700443 }
444
445 /* Flush the RX FIFO in case it is not empty */
Jes Klinke19baa9d2022-02-22 16:00:09 -0800446 stopwatch_init_usecs_expire(&sw, DW_I2C_FLUSH_TIMEOUT_US);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700447 while (read32(&regs->status) & STATUS_RX_FIFO_NOT_EMPTY) {
448 if (stopwatch_expired(&sw)) {
449 printk(BIOS_ERR, "I2C timeout flushing RX FIFO\n");
Duncan Laurie772555a22016-09-12 11:20:27 -0700450 goto out;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700451 }
452 read32(&regs->cmd_data);
453 }
454
Felix Held2a542da2022-01-31 14:36:30 +0100455 ret = CB_SUCCESS;
Duncan Laurie772555a22016-09-12 11:20:27 -0700456
457out:
458 read32(&regs->clear_intr);
Chris Chingb8dc63b2017-12-06 14:26:15 -0700459 dw_i2c_disable(regs);
Duncan Laurie772555a22016-09-12 11:20:27 -0700460 return ret;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700461}
462
Felix Heldabdf6842022-01-31 16:02:05 +0100463static enum cb_err dw_i2c_transfer(unsigned int bus, const struct i2c_msg *msg, size_t count)
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700464{
465 const struct i2c_msg *orig_msg = msg;
466 size_t i;
467 size_t start;
468 uint16_t addr;
469
Matt DeVillier57097132022-04-11 17:10:09 -0500470 if (!msg)
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700471 return -1;
472
473 /* Break up the transfers at the differing slave address boundary. */
474 addr = orig_msg->slave;
475
476 for (i = 0, start = 0; i < count; i++, msg++) {
477 if (addr != msg->slave) {
Felix Held2a542da2022-01-31 14:36:30 +0100478 if (_dw_i2c_transfer(bus, &orig_msg[start], i - start) != CB_SUCCESS)
Felix Held8ed02de82022-01-31 15:59:17 +0100479 return CB_ERR;
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700480 start = i;
481 addr = msg->slave;
482 }
483 }
484
Felix Held8ed02de82022-01-31 15:59:17 +0100485 return _dw_i2c_transfer(bus, &orig_msg[start], count - start);
Aaron Durbin97d58bc2018-01-30 17:29:08 -0700486}
487
Nico Huber58173862017-08-01 17:09:35 +0200488/* Global I2C bus handler, defined in include/device/i2c_simple.h */
489int platform_i2c_transfer(unsigned int bus, struct i2c_msg *msg, int count)
490{
Felix Held8ed02de82022-01-31 15:59:17 +0100491 return dw_i2c_transfer(bus, msg, count < 0 ? 0 : count) == CB_SUCCESS ? 0 : -1;
Nico Huber58173862017-08-01 17:09:35 +0200492}
493
Felix Held2a542da2022-01-31 14:36:30 +0100494static enum cb_err dw_i2c_set_speed_config(unsigned int bus,
495 const struct dw_i2c_speed_config *config)
Duncan Laurie88a1f142016-06-13 10:28:36 -0700496{
Chris Chingb8dc63b2017-12-06 14:26:15 -0700497 struct dw_i2c_regs *regs;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700498 void *hcnt_reg, *lcnt_reg;
499
Chris Chingb8dc63b2017-12-06 14:26:15 -0700500 regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus);
Duncan Laurie88a1f142016-06-13 10:28:36 -0700501 if (!regs || !config)
Felix Held2a542da2022-01-31 14:36:30 +0100502 return CB_ERR;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700503
504 /* Nothing to do if no values are set */
505 if (!config->scl_lcnt && !config->scl_hcnt && !config->sda_hold)
Felix Held2a542da2022-01-31 14:36:30 +0100506 return CB_SUCCESS;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700507
Naresh G Solanki14deaee2017-07-19 17:14:33 +0530508 if (config->speed >= I2C_SPEED_HIGH) {
509 /* High and Fast Ultra speed */
Duncan Laurie8a14c392016-06-07 13:40:11 -0700510 hcnt_reg = &regs->hs_scl_hcnt;
511 lcnt_reg = &regs->hs_scl_lcnt;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700512 } else if (config->speed >= I2C_SPEED_FAST) {
Naresh G Solanki14deaee2017-07-19 17:14:33 +0530513 /* Fast and Fast-Plus speed */
Duncan Laurie8a14c392016-06-07 13:40:11 -0700514 hcnt_reg = &regs->fs_scl_hcnt;
515 lcnt_reg = &regs->fs_scl_lcnt;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700516 } else {
517 /* Standard speed */
518 hcnt_reg = &regs->ss_scl_hcnt;
519 lcnt_reg = &regs->ss_scl_lcnt;
520 }
521
522 /* SCL count must be set after the speed is selected */
523 if (config->scl_hcnt)
524 write32(hcnt_reg, config->scl_hcnt);
525 if (config->scl_lcnt)
526 write32(lcnt_reg, config->scl_lcnt);
527
528 /* Set SDA Hold Time register */
529 if (config->sda_hold)
530 write32(&regs->sda_hold, config->sda_hold);
531
Felix Held2a542da2022-01-31 14:36:30 +0100532 return CB_SUCCESS;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700533}
534
Felix Held2a542da2022-01-31 14:36:30 +0100535static enum cb_err dw_i2c_gen_config_rise_fall_time(struct dw_i2c_regs *regs,
536 enum i2c_speed speed,
537 const struct dw_i2c_bus_config *bcfg,
538 int ic_clk,
539 struct dw_i2c_speed_config *config)
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600540{
541 const struct i2c_descriptor *bus;
542 const struct soc_clock *soc;
543 int fall_cnt, rise_cnt, min_tlow_cnt, min_thigh_cnt, spk_cnt;
544 int hcnt, lcnt, period_cnt, diff, tot;
Aaron Durbinc5f10f92017-03-31 14:46:26 -0500545 int data_hold_time_ns;
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600546
547 bus = get_bus_descriptor(speed);
548 soc = get_soc_descriptor(ic_clk);
549
550 if (bus == NULL) {
Chris Chingb8dc63b2017-12-06 14:26:15 -0700551 printk(BIOS_ERR, "dw_i2c: invalid bus speed %d\n", speed);
Felix Held2a542da2022-01-31 14:36:30 +0100552 return CB_ERR;
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600553 }
554
555 if (soc == NULL) {
Chris Chingb8dc63b2017-12-06 14:26:15 -0700556 printk(BIOS_ERR, "dw_i2c: invalid SoC clock speed %d MHz\n",
Aaron Durbinbff8c5ec2016-11-18 08:10:35 -0600557 ic_clk);
Felix Held2a542da2022-01-31 14:36:30 +0100558 return CB_ERR;
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600559 }
560
561 /* Get the proper spike suppression count based on target speed. */
562 if (speed >= I2C_SPEED_HIGH)
563 spk_cnt = read32(&regs->hs_spklen);
564 else
565 spk_cnt = read32(&regs->fs_spklen);
566
567 /* Find the period, rise, fall, min tlow, and min thigh in terms of
568 * counts of SoC clock. */
569 period_cnt = counts_from_freq(&soc->freq, &bus->freq);
570 rise_cnt = counts_from_time(&soc->freq, bcfg->rise_time_ns);
571 fall_cnt = counts_from_time(&soc->freq, bcfg->fall_time_ns);
572 min_tlow_cnt = counts_from_time(&soc->freq, bus->min_tlow_ns);
573 min_thigh_cnt = counts_from_time(&soc->freq, bus->min_thigh_ns);
574
Chris Chingb8dc63b2017-12-06 14:26:15 -0700575 printk(DW_I2C_DEBUG, "dw_i2c: SoC %d/%d ns Bus: %d/%d ns\n",
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600576 soc->freq.ticks, soc->freq.ns, bus->freq.ticks, bus->freq.ns);
Chris Chingb8dc63b2017-12-06 14:26:15 -0700577 printk(DW_I2C_DEBUG,
Reka Norman4bc2ca52022-04-12 09:11:35 +1000578 "dw_i2c: period %d rise %d fall %d tlow %d thigh %d spk %d\n",
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600579 period_cnt, rise_cnt, fall_cnt, min_tlow_cnt, min_thigh_cnt,
580 spk_cnt);
581
582 /*
583 * Back solve for hcnt and lcnt according to the following equations.
584 * SCL_High_time = [(HCNT + IC_*_SPKLEN + 7) * ic_clk] + SCL_Fall_time
585 * SCL_Low_time = [(LCNT + 1) * ic_clk] - SCL_Fall_time + SCL_Rise_time
586 */
587 hcnt = min_thigh_cnt - fall_cnt - 7 - spk_cnt;
588 lcnt = min_tlow_cnt - rise_cnt + fall_cnt - 1;
589
590 if (hcnt < 0 || lcnt < 0) {
Chris Chingb8dc63b2017-12-06 14:26:15 -0700591 printk(BIOS_ERR, "dw_i2c: bad counts. hcnt = %d lcnt = %d\n",
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600592 hcnt, lcnt);
Felix Held2a542da2022-01-31 14:36:30 +0100593 return CB_ERR;
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600594 }
595
596 /* Now add things back up to ensure the period is hit. If off,
597 * split the difference and bias to lcnt for remainder. */
598 tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
599
600 if (tot < period_cnt) {
601 diff = (period_cnt - tot) / 2;
602 hcnt += diff;
603 lcnt += diff;
604 tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
605 lcnt += period_cnt - tot;
606 }
607
608 config->speed = speed;
609 config->scl_lcnt = lcnt;
610 config->scl_hcnt = hcnt;
Aaron Durbinc5f10f92017-03-31 14:46:26 -0500611
612 /* Use internal default unless other value is specified. */
613 data_hold_time_ns = DEFAULT_SDA_HOLD_TIME;
614 if (bcfg->data_hold_time_ns)
615 data_hold_time_ns = bcfg->data_hold_time_ns;
616
617 config->sda_hold = counts_from_time(&soc->freq, data_hold_time_ns);
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600618
Chris Chingb8dc63b2017-12-06 14:26:15 -0700619 printk(DW_I2C_DEBUG, "dw_i2c: hcnt = %d lcnt = %d sda hold = %d\n",
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600620 hcnt, lcnt, config->sda_hold);
621
Felix Held2a542da2022-01-31 14:36:30 +0100622 return CB_SUCCESS;
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600623}
624
Felix Held7edf9102022-01-31 15:56:14 +0100625enum cb_err dw_i2c_gen_speed_config(uintptr_t dw_i2c_addr,
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -0600626 enum i2c_speed speed,
Chris Chingb8dc63b2017-12-06 14:26:15 -0700627 const struct dw_i2c_bus_config *bcfg,
628 struct dw_i2c_speed_config *config)
Duncan Laurie88a1f142016-06-13 10:28:36 -0700629{
Chris Chingb8dc63b2017-12-06 14:26:15 -0700630 const int ic_clk = CONFIG_DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ;
631 struct dw_i2c_regs *regs;
Aaron Durbin4668ba72016-11-09 17:09:40 -0600632 int i;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700633
Chris Chingb8dc63b2017-12-06 14:26:15 -0700634 regs = (struct dw_i2c_regs *)dw_i2c_addr;
635
636 _Static_assert(CONFIG_DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ != 0,
637 "DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ can't be zero!");
Duncan Laurie88a1f142016-06-13 10:28:36 -0700638
Aaron Durbin4668ba72016-11-09 17:09:40 -0600639 /* Apply board specific override for this speed if found */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700640 for (i = 0; i < DW_I2C_SPEED_CONFIG_COUNT; i++) {
Aaron Durbin4668ba72016-11-09 17:09:40 -0600641 if (bcfg->speed_config[i].speed != speed)
642 continue;
643 memcpy(config, &bcfg->speed_config[i], sizeof(*config));
Felix Held7edf9102022-01-31 15:56:14 +0100644 return CB_SUCCESS;
Aaron Durbin4668ba72016-11-09 17:09:40 -0600645 }
646
Kyösti Mälkki2263e9b2021-04-28 09:13:21 +0300647 /* Use the time calculation. */
Felix Held7edf9102022-01-31 15:56:14 +0100648 return dw_i2c_gen_config_rise_fall_time(regs, speed, bcfg, ic_clk, config);
Duncan Laurie88a1f142016-06-13 10:28:36 -0700649}
650
Felix Held2a542da2022-01-31 14:36:30 +0100651static enum cb_err dw_i2c_set_speed(unsigned int bus, enum i2c_speed speed,
652 const struct dw_i2c_bus_config *bcfg)
Duncan Laurie88a1f142016-06-13 10:28:36 -0700653{
Chris Chingb8dc63b2017-12-06 14:26:15 -0700654 struct dw_i2c_regs *regs;
655 struct dw_i2c_speed_config config;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700656 uint32_t control;
657
658 /* Clock must be provided by Kconfig */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700659 regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus);
Duncan Laurie88a1f142016-06-13 10:28:36 -0700660 if (!regs || !speed)
Felix Held2a542da2022-01-31 14:36:30 +0100661 return CB_ERR;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700662
663 control = read32(&regs->control);
664 control &= ~CONTROL_SPEED_MASK;
665
Naresh G Solanki14deaee2017-07-19 17:14:33 +0530666 if (speed >= I2C_SPEED_HIGH) {
667 /* High and Fast-Ultra speed share config registers */
Duncan Laurie88a1f142016-06-13 10:28:36 -0700668 control |= CONTROL_SPEED_HS;
669 } else if (speed >= I2C_SPEED_FAST) {
Naresh G Solanki14deaee2017-07-19 17:14:33 +0530670 /* Fast speed and Fast-Plus */
Duncan Laurie88a1f142016-06-13 10:28:36 -0700671 control |= CONTROL_SPEED_FS;
672 } else {
673 /* Standard speed */
674 control |= CONTROL_SPEED_SS;
675 }
676
677 /* Generate speed config based on clock */
Felix Held7edf9102022-01-31 15:56:14 +0100678 if (dw_i2c_gen_speed_config((uintptr_t)regs, speed, bcfg, &config) != CB_SUCCESS)
Felix Held2a542da2022-01-31 14:36:30 +0100679 return CB_ERR;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700680
Duncan Laurie8a14c392016-06-07 13:40:11 -0700681 /* Select this speed in the control register */
682 write32(&regs->control, control);
683
Duncan Laurie88a1f142016-06-13 10:28:36 -0700684 /* Write the speed config that was generated earlier */
Chris Chingb8dc63b2017-12-06 14:26:15 -0700685 dw_i2c_set_speed_config(bus, &config);
Duncan Laurie88a1f142016-06-13 10:28:36 -0700686
Felix Held2a542da2022-01-31 14:36:30 +0100687 return CB_SUCCESS;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700688}
689
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530690/*
691 * Initialize this bus controller and set the speed.
692 *
693 * The bus speed can be passed in Hz or using values from device/i2c.h and
694 * will default to I2C_SPEED_FAST if it is not provided.
695 */
Felix Held3d945892022-01-31 15:52:36 +0100696enum cb_err dw_i2c_init(unsigned int bus, const struct dw_i2c_bus_config *bcfg)
Duncan Laurie8a14c392016-06-07 13:40:11 -0700697{
Chris Chingb8dc63b2017-12-06 14:26:15 -0700698 struct dw_i2c_regs *regs;
Aaron Durbin4668ba72016-11-09 17:09:40 -0600699 enum i2c_speed speed;
700
701 if (!bcfg)
Felix Held3d945892022-01-31 15:52:36 +0100702 return CB_ERR;
Aaron Durbin4668ba72016-11-09 17:09:40 -0600703
704 speed = bcfg->speed ? : I2C_SPEED_FAST;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700705
Chris Chingb8dc63b2017-12-06 14:26:15 -0700706 regs = (struct dw_i2c_regs *)dw_i2c_base_address(bus);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700707 if (!regs) {
708 printk(BIOS_ERR, "I2C bus %u base address not found\n", bus);
Felix Held3d945892022-01-31 15:52:36 +0100709 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700710 }
711
Raul E Rangel6191b852020-04-09 11:37:05 -0600712 if (read32(&regs->comp_type) != DW_I2C_COMP_TYPE) {
713 printk(BIOS_ERR, "I2C bus %u has unknown type 0x%x.\n", bus,
714 read32(&regs->comp_type));
Felix Held3d945892022-01-31 15:52:36 +0100715 return CB_ERR;
Raul E Rangel6191b852020-04-09 11:37:05 -0600716 }
717
718 printk(BIOS_DEBUG, "I2C bus %u version 0x%x\n", bus, read32(&regs->comp_version));
719
Felix Held2a542da2022-01-31 14:36:30 +0100720 if (dw_i2c_disable(regs) != CB_SUCCESS) {
Duncan Laurie8a14c392016-06-07 13:40:11 -0700721 printk(BIOS_ERR, "I2C timeout disabling bus %u\n", bus);
Felix Held3d945892022-01-31 15:52:36 +0100722 return CB_ERR;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700723 }
724
725 /* Put controller in master mode with restart enabled */
726 write32(&regs->control, CONTROL_MASTER_MODE | CONTROL_SLAVE_DISABLE |
727 CONTROL_RESTART_ENABLE);
728
729 /* Set bus speed to FAST by default */
Felix Held2a542da2022-01-31 14:36:30 +0100730 if (dw_i2c_set_speed(bus, speed, bcfg) != CB_SUCCESS) {
Duncan Laurie88a1f142016-06-13 10:28:36 -0700731 printk(BIOS_ERR, "I2C failed to set speed for bus %u\n", bus);
Felix Held3d945892022-01-31 15:52:36 +0100732 return CB_ERR;
Duncan Laurie88a1f142016-06-13 10:28:36 -0700733 }
Duncan Laurie8a14c392016-06-07 13:40:11 -0700734
735 /* Set RX/TX thresholds to smallest values */
736 write32(&regs->rx_thresh, 0);
737 write32(&regs->tx_thresh, 0);
738
Kangheui Wonb2c39b52020-11-09 17:49:48 +1100739 /* Enable stop detection and TX abort interrupt */
740 write32(&regs->intr_mask, INTR_STAT_STOP_DET | INTR_STAT_TX_ABORT);
Duncan Laurie8a14c392016-06-07 13:40:11 -0700741
Julius Werner540a9802019-12-09 13:03:29 -0800742 printk(BIOS_INFO, "DW I2C bus %u at %p (%u KHz)\n",
Aaron Durbin4668ba72016-11-09 17:09:40 -0600743 bus, regs, speed / KHz);
Duncan Laurie88a1f142016-06-13 10:28:36 -0700744
Felix Held3d945892022-01-31 15:52:36 +0100745 return CB_SUCCESS;
Duncan Laurie8a14c392016-06-07 13:40:11 -0700746}
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700747
748/*
749 * Write ACPI object to describe speed configuration.
750 *
751 * ACPI Object: Name ("xxxx", Package () { scl_lcnt, scl_hcnt, sda_hold }
752 *
753 * SSCN: I2C_SPEED_STANDARD
754 * FMCN: I2C_SPEED_FAST
755 * FPCN: I2C_SPEED_FAST_PLUS
756 * HSCN: I2C_SPEED_HIGH
757 */
758static void dw_i2c_acpi_write_speed_config(
759 const struct dw_i2c_speed_config *config)
760{
761 if (!config)
762 return;
763 if (!config->scl_lcnt && !config->scl_hcnt && !config->sda_hold)
764 return;
765
766 if (config->speed >= I2C_SPEED_HIGH)
767 acpigen_write_name("HSCN");
768 else if (config->speed >= I2C_SPEED_FAST_PLUS)
769 acpigen_write_name("FPCN");
770 else if (config->speed >= I2C_SPEED_FAST)
771 acpigen_write_name("FMCN");
772 else
773 acpigen_write_name("SSCN");
774
775 /* Package () { scl_lcnt, scl_hcnt, sda_hold } */
776 acpigen_write_package(3);
777 acpigen_write_word(config->scl_hcnt);
778 acpigen_write_word(config->scl_lcnt);
779 acpigen_write_dword(config->sda_hold);
780 acpigen_pop_len();
781}
782
783/*
784 * The device should already be enabled and out of reset,
785 * either from early init in coreboot or SiliconInit in FSP.
786 */
787void dw_i2c_dev_init(struct device *dev)
788{
789 const struct dw_i2c_bus_config *config;
790 int bus = dw_i2c_soc_dev_to_bus(dev);
791
792 if (bus < 0)
793 return;
794
Aaron Durbinb94a2752018-01-24 16:58:18 -0700795 config = dw_i2c_get_soc_cfg(bus);
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700796
797 if (!config)
798 return;
799
800 dw_i2c_init(bus, config);
801}
802
803/*
804 * Generate I2C timing information into the SSDT for the OS driver to consume,
805 * optionally applying override values provided by the caller.
806 */
Furquan Shaikh7536a392020-04-24 21:59:21 -0700807void dw_i2c_acpi_fill_ssdt(const struct device *dev)
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700808{
809 const struct dw_i2c_bus_config *bcfg;
810 uintptr_t dw_i2c_addr;
811 struct dw_i2c_speed_config sgen;
Tim Wawrzynczakba0a3932019-07-17 09:25:59 -0600812 int bus;
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700813 const char *path;
Werner Zeh1e02ad32021-05-31 07:08:17 +0200814 unsigned int speed, i;
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700815
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700816 bus = dw_i2c_soc_dev_to_bus(dev);
817
818 if (bus < 0)
819 return;
820
Aaron Durbinb94a2752018-01-24 16:58:18 -0700821 bcfg = dw_i2c_get_soc_cfg(bus);
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700822
823 if (!bcfg)
824 return;
825
826 dw_i2c_addr = dw_i2c_base_address(bus);
827 if (!dw_i2c_addr)
828 return;
829
830 path = acpi_device_path(dev);
831 if (!path)
832 return;
833
Tim Wawrzynczakba0a3932019-07-17 09:25:59 -0600834 /* Ensure a default speed is available */
835 speed = (bcfg->speed == 0) ? I2C_SPEED_FAST : bcfg->speed;
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700836
Werner Zeh1e02ad32021-05-31 07:08:17 +0200837 /* Report currently used timing values for the OS driver */
838 acpigen_write_scope(path);
Felix Held7edf9102022-01-31 15:56:14 +0100839 if (dw_i2c_gen_speed_config(dw_i2c_addr, speed, bcfg, &sgen) == CB_SUCCESS) {
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700840 dw_i2c_acpi_write_speed_config(&sgen);
841 }
Werner Zeh1e02ad32021-05-31 07:08:17 +0200842 /* Now check if there are more speed settings available and report them as well. */
843 for (i = 0; i < DW_I2C_SPEED_CONFIG_COUNT; i++) {
844 if (bcfg->speed_config[i].speed && speed != bcfg->speed_config[i].speed)
845 dw_i2c_acpi_write_speed_config(&bcfg->speed_config[i]);
846 }
847 acpigen_write_scope_end();
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700848}
849
850static int dw_i2c_dev_transfer(struct device *dev,
851 const struct i2c_msg *msg, size_t count)
852{
853 return dw_i2c_transfer(dw_i2c_soc_dev_to_bus(dev), msg, count);
854}
855
856const struct i2c_bus_operations dw_i2c_bus_ops = {
857 .transfer = dw_i2c_dev_transfer,
858};