blob: cce7ed94c7629f6d0370a649dbfab426e8b655b5 [file] [log] [blame]
Patrick Georgi70517072020-05-10 18:47:05 +02001/* SPDX-License-Identifier: BSD-3-Clause */
Daisuke Nojiri05949142014-11-21 15:33:26 -08002
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08003#include <console/console.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02004#include <device/i2c_simple.h>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08005#include <string.h>
6#include <soc/gsbi.h>
7#include <soc/qup.h>
Daisuke Nojiri05949142014-11-21 15:33:26 -08008
Sourabh Banerjee89208652015-02-19 16:43:26 +05309static qup_config_t gsbi1_qup_config = {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080010 QUP_MINICORE_I2C_MASTER,
11 100000,
12 24000000,
Sourabh Banerjee89208652015-02-19 16:43:26 +053013 QUP_MODE_FIFO,
14 0
15};
16
17static qup_config_t gsbi4_qup_config = {
18 QUP_MINICORE_I2C_MASTER,
19 100000,
20 24000000,
21 QUP_MODE_FIFO,
22 0
23};
24
25static qup_config_t gsbi7_qup_config = {
26 QUP_MINICORE_I2C_MASTER,
27 100000,
28 24000000,
29 QUP_MODE_FIFO,
30 0
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080031};
Daisuke Nojiri05949142014-11-21 15:33:26 -080032
33static int i2c_read(uint32_t gsbi_id, uint8_t slave,
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080034 uint8_t *data, int data_len)
Daisuke Nojiri05949142014-11-21 15:33:26 -080035{
36 qup_data_t obj;
37 qup_return_t qup_ret = 0;
38
39 memset(&obj, 0, sizeof(obj));
40 obj.protocol = QUP_MINICORE_I2C_MASTER;
41 obj.p.iic.addr = slave;
42 obj.p.iic.data_len = data_len;
43 obj.p.iic.data = data;
44 qup_ret = qup_recv_data(gsbi_id, &obj);
45
46 if (QUP_SUCCESS != qup_ret)
47 return 1;
48 else
49 return 0;
50}
51
52static int i2c_write(uint32_t gsbi_id, uint8_t slave,
53 uint8_t *data, int data_len, uint8_t stop_seq)
54{
55 qup_data_t obj;
56 qup_return_t qup_ret = 0;
57
58 memset(&obj, 0, sizeof(obj));
59 obj.protocol = QUP_MINICORE_I2C_MASTER;
60 obj.p.iic.addr = slave;
61 obj.p.iic.data_len = data_len;
62 obj.p.iic.data = data;
63 qup_ret = qup_send_data(gsbi_id, &obj, stop_seq);
64
65 if (QUP_SUCCESS != qup_ret)
66 return 1;
67 else
68 return 0;
69}
70
Martin Roth57e89092019-10-23 21:45:23 -060071static int i2c_init(unsigned int bus)
Daisuke Nojiri05949142014-11-21 15:33:26 -080072{
Martin Roth57e89092019-10-23 21:45:23 -060073 unsigned int gsbi_id = bus;
Sourabh Banerjee89208652015-02-19 16:43:26 +053074 qup_config_t *qup_config;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080075
Sourabh Banerjee89208652015-02-19 16:43:26 +053076 switch (gsbi_id) {
77 case GSBI_ID_1:
78 qup_config = &gsbi1_qup_config;
79 break;
80 case GSBI_ID_4:
81 qup_config = &gsbi4_qup_config;
82 break;
83 case GSBI_ID_7:
84 qup_config = &gsbi7_qup_config;
85 break;
86 default:
Martin Roth26f97f92021-10-01 14:53:22 -060087 printk(BIOS_ERR, "QUP configuration not defined for GSBI%d.\n",
Sourabh Banerjee89208652015-02-19 16:43:26 +053088 gsbi_id);
89 return 1;
90 }
91
92 if (qup_config->initialized)
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080093 return 0;
94
95 if (gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY)) {
96 printk(BIOS_ERR, "failed to initialize gsbi\n");
97 return 1;
98 }
99
Sourabh Banerjee89208652015-02-19 16:43:26 +0530100 if (qup_init(gsbi_id, qup_config)) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800101 printk(BIOS_ERR, "failed to initialize qup\n");
102 return 1;
103 }
104
105 if (qup_reset_i2c_master_status(gsbi_id)) {
106 printk(BIOS_ERR, "failed to reset i2c master status\n");
107 return 1;
108 }
109
Sourabh Banerjee89208652015-02-19 16:43:26 +0530110 qup_config->initialized = 1;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800111 return 0;
112}
113
Martin Roth57e89092019-10-23 21:45:23 -0600114int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
Nico Huber029dfff2017-07-12 17:59:16 +0200115 int seg_count)
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800116{
Nico Huber029dfff2017-07-12 17:59:16 +0200117 struct i2c_msg *seg = segments;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800118 int ret = 0;
119
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800120 if (i2c_init(bus))
121 return 1;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800122
Sourabh Banerjee54cc8ba2015-02-27 19:11:19 +0530123 while (!ret && seg_count--) {
Nico Huber029dfff2017-07-12 17:59:16 +0200124 if (seg->flags & I2C_M_RD)
125 ret = i2c_read(bus, seg->slave, seg->buf, seg->len);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800126 else
Nico Huber029dfff2017-07-12 17:59:16 +0200127 ret = i2c_write(bus, seg->slave, seg->buf, seg->len,
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800128 (seg_count ? 0 : 1));
Daisuke Nojiri05949142014-11-21 15:33:26 -0800129 seg++;
130 }
131
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800132 if (ret) {
133 qup_set_state(bus, QUP_STATE_RESET);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800134 return 1;
135 }
136
137 return 0;
138}