blob: e3a4e5e69eb92bcae34c9b28d6e496c440f3232f [file] [log] [blame]
Patrick Georgi70517072020-05-10 18:47:05 +02001/* SPDX-License-Identifier: BSD-3-Clause */
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05302
3#include <device/mmio.h>
4#include <console/console.h>
5#include <delay.h>
Jes Klinke19baa9d2022-02-22 16:00:09 -08006#include <timer.h>
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05307#include <soc/gpio.h>
8#include <soc/iomap.h>
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +05309#include <soc/qup.h>
10
11#define TIMEOUT_CNT 100
12
13#define QUP_ADDR(id, reg) (blsp_qup_base(id) + (reg))
14
15#define QUP_DEBUG 0
16
17#define QUPDBG BIOS_ERR, "\t-> "
18
19#if QUP_DEBUG
20#define qup_write32(a, v) do { \
21 write32(a, v); \
Julius Werner540a9802019-12-09 13:03:29 -080022 printk(QUPDBG "%s(%d): write32(%p, 0x%x)\n", \
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +053023 __func__, __LINE__, a, v); \
24} while (0)
25#else
26#define qup_write32 write32
27#endif
28
29struct i2c_clk_div_fld {
30 u32 clk_freq_out;
31 u8 fs_div;
32 u8 ht_div;
33};
34
35static struct i2c_clk_div_fld i2c_clk_div_map[] = {
36 {100000, 124, 62},
37 {400000, 28, 14},
38 {1000000, 8, 5},
39};
40
41static void i2c_set_mstr_clk_ctl(unsigned int id, unsigned int hz)
42{
43 int i;
44 struct i2c_clk_div_fld *itr = i2c_clk_div_map;
45 u8 fs_div = 0;
46 u8 ht_div = 0;
47 u32 mstr_clk_ctl;
48
49 for (i = 0; i < ARRAY_SIZE(i2c_clk_div_map); ++i, ++itr) {
50 if (hz == itr->clk_freq_out) {
51 if (!fs_div)
52 fs_div = itr->fs_div;
53 if (!ht_div)
54 ht_div = itr->ht_div;
55 break;
56 }
57 }
58
59 /* format values in clk-ctl cache */
60 mstr_clk_ctl = ((ht_div & 0xff) << 16) | (fs_div & 0xff);
61 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), mstr_clk_ctl);
62}
63
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +053064static qup_return_t qup_i2c_master_status(blsp_qup_id_t id)
65{
66 uint32_t reg_val = read32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS));
67
68 if (read32(QUP_ADDR(id, QUP_ERROR_FLAGS)))
69 return QUP_ERR_XFER_FAIL;
70
71#if QUP_DEBUG
72 printk(QUPDBG "%s: 0x%x\n", __func__, reg_val);
73#endif
74
75 if (reg_val & QUP_I2C_INVALID_READ_ADDR)
76 return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
77 if (reg_val & QUP_I2C_FAILED_MASK)
78 return QUP_ERR_I2C_FAILED;
79 if (reg_val & QUP_I2C_ARB_LOST)
80 return QUP_ERR_I2C_ARB_LOST;
81 if (reg_val & QUP_I2C_BUS_ERROR)
82 return QUP_ERR_I2C_BUS_ERROR;
83 if (reg_val & QUP_I2C_INVALID_WRITE)
84 return QUP_ERR_I2C_INVALID_WRITE;
85 if (reg_val & QUP_I2C_PACKET_NACK)
86 return QUP_ERR_I2C_NACK;
87 if (reg_val & QUP_I2C_INVALID_TAG)
88 return QUP_ERR_I2C_INVALID_TAG;
89
90 return QUP_SUCCESS;
91}
92
93static int check_bit_state(uint32_t *reg, int wait_for)
94{
95 unsigned int count = TIMEOUT_CNT;
96
97 while ((read32(reg) & (QUP_STATE_VALID_MASK | QUP_STATE_MASK)) !=
98 (QUP_STATE_VALID | wait_for)) {
99 if (count == 0)
100 return QUP_ERR_TIMEOUT;
101 count--;
102 }
103
104 return QUP_SUCCESS;
105}
106
107/*
108 * Check whether GSBIn_QUP State is valid
109 */
110static qup_return_t qup_wait_for_state(blsp_qup_id_t id, unsigned int wait_for)
111{
112 return check_bit_state(QUP_ADDR(id, QUP_STATE), wait_for);
113}
114
115qup_return_t qup_reset_i2c_master_status(blsp_qup_id_t id)
116{
117 /*
118 * The I2C_STATUS is a status register.
119 * Writing any value clears the status bits.
120 */
121 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS), 0);
122 return QUP_SUCCESS;
123}
124
125static qup_return_t qup_reset_master_status(blsp_qup_id_t id)
126{
127 qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS), 0x3C);
128 qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS_EN), 0x3C);
129 qup_reset_i2c_master_status(id);
130 return QUP_SUCCESS;
131}
132
Jes Klinke19baa9d2022-02-22 16:00:09 -0800133static qup_return_t qup_fifo_wait_for(blsp_qup_id_t id, uint32_t status,
134 struct stopwatch *timeout)
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530135{
136 qup_return_t ret = QUP_ERR_UNDEFINED;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530137
138 while (!(read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status)) {
139 ret = qup_i2c_master_status(id);
140 if (ret)
141 return ret;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800142 if (stopwatch_expired(timeout))
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530143 return QUP_ERR_TIMEOUT;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530144 }
145
146 return QUP_SUCCESS;
147}
148
Jes Klinke19baa9d2022-02-22 16:00:09 -0800149static qup_return_t qup_fifo_wait_while(blsp_qup_id_t id, uint32_t status,
150 struct stopwatch *timeout)
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530151{
152 qup_return_t ret = QUP_ERR_UNDEFINED;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530153
154 while (read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status) {
155 ret = qup_i2c_master_status(id);
156 if (ret)
157 return ret;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800158 if (stopwatch_expired(timeout))
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530159 return QUP_ERR_TIMEOUT;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530160 }
161
162 return QUP_SUCCESS;
163}
164
165static inline uint32_t qup_i2c_create_output_tag(int stop, u8 data)
166{
167 uint32_t tag;
168
169 if (stop)
170 tag = QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data);
171 else
172 tag = QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data);
173
174 return tag;
175}
176
Jes Klinke19baa9d2022-02-22 16:00:09 -0800177static inline qup_return_t qup_i2c_write_fifo_flush(blsp_qup_id_t id,
178 struct stopwatch *timeout)
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530179{
180 qup_return_t ret = QUP_ERR_UNDEFINED;
181
182 qup_write32(QUP_ADDR(id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
183
184 mdelay(4); /* TPM seems to need this */
185
Jes Klinke19baa9d2022-02-22 16:00:09 -0800186 ret = qup_fifo_wait_while(id, OUTPUT_FIFO_NOT_EMPTY, timeout);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530187 if (ret)
188 return ret;
189
190 ret = qup_i2c_master_status(id);
191
192 if (ret)
193 printk(BIOS_DEBUG, "%s: error\n", __func__);
194
195 return ret;
196}
197
198static qup_return_t qup_i2c_write_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj,
199 uint8_t stop_seq)
200{
201 qup_return_t ret = QUP_ERR_UNDEFINED;
202 uint8_t addr = p_tx_obj->p.iic.addr;
203 uint8_t *data_ptr = p_tx_obj->p.iic.data;
204 unsigned int data_len = p_tx_obj->p.iic.data_len;
205 unsigned int idx = 0;
206 uint32_t tag, *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800207 struct stopwatch timeout;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530208
209 qup_reset_master_status(id);
210
211 qup_write32(QUP_ADDR(id, QUP_MX_OUTPUT_COUNT), data_len + 1);
212
213 qup_set_state(id, QUP_STATE_RUN);
214
215 /*
216 * Since UNPACK enable is set in io mode register, populate 2 tags
217 * for each fifo register.
218 *
219 * Create the first tag as follows, with the start tag and first byte
220 * of the data to be written
221 * +--------+--------+--------+--------+
222 * | STOP / | data | START | ADDR |
223 * |DATA tag| byte | tag | << 1 |
224 * +--------+--------+--------+--------+
225 * rest will be created in the following while loop.
226 */
227 tag = qup_i2c_create_output_tag(data_len == 1 && stop_seq,
228 data_ptr[idx]);
229 tag = ((tag << 16) & 0xffff0000) |
230 (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr));
231 data_len--;
232 idx++;
233
234 qup_write32(fifo, tag);
235
Jes Klinke19baa9d2022-02-22 16:00:09 -0800236 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530237 while (data_len) {
238
239 tag = qup_i2c_create_output_tag(data_len == 1 && stop_seq,
240 data_ptr[idx]);
241 data_len--;
242 idx++;
243
244 if (data_len) {
245 tag |= qup_i2c_create_output_tag(
246 data_len == 1 && stop_seq,
247 data_ptr[idx]) << 16;
248 data_len--;
249 idx++;
250 }
251
252 qup_write32(fifo, tag);
253
Jes Klinke19baa9d2022-02-22 16:00:09 -0800254 ret = qup_i2c_write_fifo_flush(id, &timeout);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530255
256 if (ret) {
257 printk(QUPDBG "%s: error\n", __func__);
258 return ret;
259 }
260 }
261
Jes Klinke19baa9d2022-02-22 16:00:09 -0800262 ret = qup_i2c_write_fifo_flush(id, &timeout);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530263
264 qup_set_state(id, QUP_STATE_RESET);
265
266 return ret;
267}
268
269static qup_return_t qup_i2c_write(blsp_qup_id_t id, uint8_t mode,
270 qup_data_t *p_tx_obj, uint8_t stop_seq)
271{
272 qup_return_t ret = QUP_ERR_UNDEFINED;
273
274 switch (mode) {
275 case QUP_MODE_FIFO:
276 case QUP_MODE_BLOCK:
277 ret = qup_i2c_write_fifo(id, p_tx_obj, stop_seq);
278 break;
279 default:
280 ret = QUP_ERR_UNSUPPORTED;
281 }
282
283 if (ret) {
284 qup_set_state(id, QUP_STATE_RESET);
285 printk(QUPDBG "%s() failed (%d)\n", __func__, ret);
286 }
287
288 return ret;
289}
290
291static int qup_i2c_parse_tag(uint32_t data, uint8_t *data_ptr, uint32_t len)
292{
293 int i, idx = 0;
294 int max = (len > 2) ? 2 : len;
295
296 for (i = 0; i < max; i++) {
297 switch (QUP_I2C_MI_TAG(data)) {
298 case QUP_I2C_MIDATA_SEQ:
299 data_ptr[idx] = QUP_I2C_DATA(data);
300 idx++;
301 break;
302 case QUP_I2C_MISTOP_SEQ:
303 data_ptr[idx] = QUP_I2C_DATA(data);
304 idx++;
305 return idx;
306 default:
307 printk(QUPDBG "%s: Unexpected tag (0x%x)\n", __func__,
308 QUP_I2C_MI_TAG(data));
309 return -1;
310 }
311
312 data = (data >> 16);
313 }
314
315 return idx;
316}
317
318static qup_return_t qup_i2c_read_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj)
319{
320 qup_return_t ret = QUP_ERR_UNDEFINED;
321 uint8_t addr = p_tx_obj->p.iic.addr;
322 uint8_t *data_ptr = p_tx_obj->p.iic.data;
323 unsigned int data_len = p_tx_obj->p.iic.data_len;
324 unsigned int idx = 0;
325 uint32_t *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800326 struct stopwatch timeout;
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530327
328 qup_reset_master_status(id);
329
330 qup_write32(QUP_ADDR(id, QUP_IO_MODES),
331 QUP_UNPACK_EN | QUP_PACK_EN |
332 ((QUP_MODE_BLOCK & QUP_MODE_MASK) <<
333 QUP_OUTPUT_MODE_SHFT) |
334 ((QUP_MODE_BLOCK & QUP_MODE_MASK) <<
335 QUP_INPUT_MODE_SHFT));
336
337 qup_write32(QUP_ADDR(id, QUP_MX_INPUT_COUNT), data_len);
338
339 qup_set_state(id, QUP_STATE_RUN);
340
341 qup_write32(fifo, (QUP_I2C_START_SEQ |
342 (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ)) |
343 ((QUP_I2C_RECV_SEQ | data_len) << 16));
344
Jes Klinke19baa9d2022-02-22 16:00:09 -0800345 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
346 ret = qup_i2c_write_fifo_flush(id, &timeout);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530347 if (ret) {
348 printk(QUPDBG "%s: OUTPUT_FIFO_NOT_EMPTY\n", __func__);
349 return ret;
350 }
351
Jes Klinke19baa9d2022-02-22 16:00:09 -0800352 ret = qup_fifo_wait_for(id, INPUT_SERVICE_FLAG, &timeout);
Prudhvi Yarlagadda58ed1732019-04-15 21:32:12 +0530353 if (ret) {
354 printk(QUPDBG "%s: INPUT_SERVICE_FLAG\n", __func__);
355 return ret;
356 }
357
358 fifo = QUP_ADDR(id, QUP_INPUT_FIFO);
359
360 while (data_len) {
361 uint32_t data;
362 int count;
363
364 data = read32(fifo);
365 mdelay(1);
366
367 count = qup_i2c_parse_tag(data, data_ptr + idx, data_len);
368
369 if (count < 0) {
370 printk(QUPDBG "%s: Cannot parse tag 0x%x\n",
371 __func__, data);
372 qup_set_state(id, QUP_STATE_PAUSE);
373
374 return QUP_ERR_I2C_INVALID_TAG;
375 }
376
377 idx += count;
378 data_len -= count;
379
380 qup_write32(QUP_ADDR(id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
381 }
382
383 p_tx_obj->p.iic.data_len = idx;
384
385 qup_write32(QUP_ADDR(id, QUP_MX_READ_COUNT), 0);
386
387 qup_set_state(id, QUP_STATE_RESET);
388
389 return QUP_SUCCESS;
390}
391
392static qup_return_t qup_i2c_read(blsp_qup_id_t id, uint8_t mode,
393 qup_data_t *p_tx_obj)
394{
395 qup_return_t ret = QUP_ERR_UNDEFINED;
396
397 qup_set_state(id, QUP_STATE_RESET);
398
399 switch (mode) {
400 case QUP_MODE_FIFO:
401 case QUP_MODE_BLOCK:
402 ret = qup_i2c_read_fifo(id, p_tx_obj);
403 break;
404 default:
405 ret = QUP_ERR_UNSUPPORTED;
406 }
407
408 if (ret) {
409 qup_set_state(id, QUP_STATE_RESET);
410 printk(QUPDBG "%s() failed (%d)\n", __func__, ret);
411 }
412
413 return ret;
414}
415
416qup_return_t qup_init(blsp_qup_id_t id, const qup_config_t *config_ptr)
417{
418 qup_return_t ret = QUP_ERR_UNDEFINED;
419 uint32_t reg_val;
420
421 /* Reset the QUP core.*/
422 qup_write32(QUP_ADDR(id, QUP_SW_RESET), 0x1);
423
424 /* Wait till the reset takes effect */
425 ret = qup_wait_for_state(id, QUP_STATE_RESET);
426 if (ret)
427 goto bailout;
428
429 /* Reset the config */
430 qup_write32(QUP_ADDR(id, QUP_CONFIG), 0);
431
432 /* Program the config register */
433 /* Set N value */
434 reg_val = 0x0F;
435 /* Set protocol */
436 switch (config_ptr->protocol) {
437 case QUP_MINICORE_I2C_MASTER:
438 reg_val |= ((config_ptr->protocol &
439 QUP_MINI_CORE_PROTO_MASK) <<
440 QUP_MINI_CORE_PROTO_SHFT);
441 break;
442 default:
443 ret = QUP_ERR_UNSUPPORTED;
444 goto bailout;
445 }
446 reg_val |= QUP_APP_CLK_ON_EN | QUP_CORE_CLK_ON_EN;
447 qup_write32(QUP_ADDR(id, QUP_CONFIG), reg_val);
448
449 /* Choose version 1 tag */
450 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CONFIG), 0);
451
452 /* Reset i2c clk cntl register */
453 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), 0);
454
455 /* Set QUP IO Mode */
456 switch (config_ptr->mode) {
457 case QUP_MODE_FIFO:
458 case QUP_MODE_BLOCK:
459 reg_val = QUP_UNPACK_EN | QUP_PACK_EN |
460 ((config_ptr->mode & QUP_MODE_MASK) <<
461 QUP_OUTPUT_MODE_SHFT) |
462 ((config_ptr->mode & QUP_MODE_MASK) <<
463 QUP_INPUT_MODE_SHFT);
464 break;
465 default:
466 ret = QUP_ERR_UNSUPPORTED;
467 goto bailout;
468 }
469 qup_write32(QUP_ADDR(id, QUP_IO_MODES), reg_val);
470
471 /*Set i2c clk cntl*/
472 i2c_set_mstr_clk_ctl(id, 400000);
473
474 qup_set_state(id, QUP_STATE_RESET);
475bailout:
476 if (ret)
477 printk(QUPDBG "failed to init qup (%d)\n", ret);
478
479 return ret;
480}
481
482qup_return_t qup_set_state(blsp_qup_id_t id, uint32_t state)
483{
484 qup_return_t ret = QUP_ERR_UNDEFINED;
485 unsigned int curr_state = read32(QUP_ADDR(id, QUP_STATE));
486
487 if ((state <= QUP_STATE_PAUSE)
488 && (curr_state & QUP_STATE_VALID_MASK)) {
489 /*
490 * For PAUSE_STATE to RESET_STATE transition,
491 * two writes of 10[binary]) are required for the
492 * transition to complete.
493 */
494 if (curr_state == QUP_STATE_PAUSE && state == QUP_STATE_RESET) {
495 qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
496 qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
497 } else {
498 qup_write32(QUP_ADDR(id, QUP_STATE), state);
499 }
500 ret = qup_wait_for_state(id, state);
501 }
502
503 return ret;
504}
505
506static qup_return_t qup_i2c_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
507 uint8_t stop_seq)
508{
509 qup_return_t ret = QUP_ERR_UNDEFINED;
510 uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
511 QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
512
513 ret = qup_i2c_write(id, mode, p_tx_obj, stop_seq);
514 if (QUP_DEBUG) {
515 int i;
516
517 printk(BIOS_DEBUG, "i2c tx bus %d device %2.2x:",
518 id, p_tx_obj->p.iic.addr);
519 for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
520 printk(BIOS_DEBUG, " %2.2x", p_tx_obj->p.iic.data[i]);
521 printk(BIOS_DEBUG, "\n");
522 }
523
524 return ret;
525}
526
527qup_return_t qup_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
528 uint8_t stop_seq)
529{
530 qup_return_t ret = QUP_ERR_UNDEFINED;
531
532 if (p_tx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
533 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
534 switch (p_tx_obj->protocol) {
535 case QUP_MINICORE_I2C_MASTER:
536 ret = qup_i2c_send_data(id, p_tx_obj, stop_seq);
537 break;
538 default:
539 ret = QUP_ERR_UNSUPPORTED;
540 }
541 }
542
543 return ret;
544}
545
546static qup_return_t qup_i2c_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
547{
548 qup_return_t ret = QUP_ERR_UNDEFINED;
549 uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
550 QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
551
552 ret = qup_i2c_read(id, mode, p_rx_obj);
553 if (QUP_DEBUG) {
554 int i;
555
556 printk(BIOS_DEBUG, "i2c rxed on bus %d device %2.2x:",
557 id, p_rx_obj->p.iic.addr);
558 for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
559 printk(BIOS_DEBUG, " %2.2x", p_rx_obj->p.iic.data[i]);
560 printk(BIOS_DEBUG, "\n");
561 }
562
563 return ret;
564}
565
566qup_return_t qup_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
567{
568 qup_return_t ret = QUP_ERR_UNDEFINED;
569
570 if (p_rx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
571 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
572 switch (p_rx_obj->protocol) {
573 case QUP_MINICORE_I2C_MASTER:
574 ret = qup_i2c_recv_data(id, p_rx_obj);
575 break;
576 default:
577 ret = QUP_ERR_UNSUPPORTED;
578 }
579 }
580
581 return ret;
582}