blob: e7b45d6eca3ea2760453300aa65f54165a413bf7 [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
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08004#include <console/console.h>
5#include <delay.h>
Jes Klinke19baa9d2022-02-22 16:00:09 -08006#include <timer.h>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08007#include <soc/iomap.h>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08008#include <soc/qup.h>
9
10#define TIMEOUT_CNT 100000
Daisuke Nojiri05949142014-11-21 15:33:26 -080011
12//TODO: refactor the following array to iomap driver.
Martin Roth57e89092019-10-23 21:45:23 -060013static unsigned int gsbi_qup_base[] = {
14 (unsigned int)GSBI_QUP1_BASE,
15 (unsigned int)GSBI_QUP2_BASE,
16 (unsigned int)GSBI_QUP3_BASE,
17 (unsigned int)GSBI_QUP4_BASE,
18 (unsigned int)GSBI_QUP5_BASE,
19 (unsigned int)GSBI_QUP6_BASE,
20 (unsigned int)GSBI_QUP7_BASE,
Daisuke Nojiri05949142014-11-21 15:33:26 -080021};
22
23#define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg)))
Daisuke Nojiri05949142014-11-21 15:33:26 -080024
25static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id)
26{
Julius Werner2f37bd62015-02-19 14:51:15 -080027 uint32_t reg_val = read32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
Daisuke Nojiri05949142014-11-21 15:33:26 -080028
Julius Werner2f37bd62015-02-19 14:51:15 -080029 if (read32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)))
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080030 return QUP_ERR_XFER_FAIL;
31 if (reg_val & QUP_I2C_INVALID_READ_ADDR)
32 return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
33 if (reg_val & QUP_I2C_FAILED_MASK)
34 return QUP_ERR_I2C_FAILED;
35 if (reg_val & QUP_I2C_ARB_LOST)
36 return QUP_ERR_I2C_ARB_LOST;
37 if (reg_val & QUP_I2C_BUS_ERROR)
38 return QUP_ERR_I2C_BUS_ERROR;
Sourabh Banerjeef36cffc2015-02-27 19:18:11 +053039 if (reg_val & QUP_I2C_INVALID_WRITE)
40 return QUP_ERR_I2C_INVALID_WRITE;
41 if (reg_val & QUP_I2C_PACKET_NACK)
42 return QUP_ERR_I2C_NACK;
43 if (reg_val & QUP_I2C_INVALID_TAG)
44 return QUP_ERR_I2C_INVALID_TAG;
Daisuke Nojiri05949142014-11-21 15:33:26 -080045
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080046 return QUP_SUCCESS;
Daisuke Nojiri05949142014-11-21 15:33:26 -080047}
48
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080049static int check_bit_state(uint32_t *reg, int wait_for)
50{
51 unsigned int count = TIMEOUT_CNT;
52
Julius Werner2f37bd62015-02-19 14:51:15 -080053 while ((read32(reg) & (QUP_STATE_VALID_MASK | QUP_STATE_MASK)) !=
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080054 (QUP_STATE_VALID | wait_for)) {
55 if (count == 0)
56 return QUP_ERR_TIMEOUT;
57 count--;
58 udelay(1);
59 }
60
61 return QUP_SUCCESS;
62}
63
64/*
65 * Check whether GSBIn_QUP State is valid
66 */
Martin Roth57e89092019-10-23 21:45:23 -060067static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned int wait_for)
Daisuke Nojiri05949142014-11-21 15:33:26 -080068{
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080069 return check_bit_state(QUP_ADDR(gsbi_id, QUP_STATE), wait_for);
Daisuke Nojiri05949142014-11-21 15:33:26 -080070}
71
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080072qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id)
73{
74 /*
75 * Writing a one clears the status bits.
76 * Bit31-25, Bit1 and Bit0 are reserved.
77 */
78 //TODO: Define each status bit. OR all status bits in a single macro.
Julius Werner2f37bd62015-02-19 14:51:15 -080079 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS), 0x3FFFFFC);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080080 return QUP_SUCCESS;
81}
82
83static qup_return_t qup_reset_master_status(gsbi_id_t gsbi_id)
84{
Julius Werner2f37bd62015-02-19 14:51:15 -080085 write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS), 0x7C);
86 write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN), 0x7C);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080087 qup_reset_i2c_master_status(gsbi_id);
88 return QUP_SUCCESS;
89}
90
Jes Klinke19baa9d2022-02-22 16:00:09 -080091static qup_return_t qup_fifo_wait_for(gsbi_id_t gsbi_id, uint32_t status,
92 struct stopwatch *timeout)
Daisuke Nojiri05949142014-11-21 15:33:26 -080093{
94 qup_return_t ret = QUP_ERR_UNDEFINED;
Daisuke Nojiri05949142014-11-21 15:33:26 -080095
Julius Werner2f37bd62015-02-19 14:51:15 -080096 while (!(read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status)) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080097 ret = qup_i2c_master_status(gsbi_id);
98 if (ret)
99 return ret;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800100 if (stopwatch_expired(timeout))
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800101 return QUP_ERR_TIMEOUT;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800102 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800103
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800104 return QUP_SUCCESS;
105}
Daisuke Nojiri05949142014-11-21 15:33:26 -0800106
Jes Klinke19baa9d2022-02-22 16:00:09 -0800107static qup_return_t qup_fifo_wait_while(gsbi_id_t gsbi_id, uint32_t status,
108 struct stopwatch *timeout)
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800109{
110 qup_return_t ret = QUP_ERR_UNDEFINED;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800111
Julius Werner2f37bd62015-02-19 14:51:15 -0800112 while (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800113 ret = qup_i2c_master_status(gsbi_id);
114 if (ret)
115 return ret;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800116 if (stopwatch_expired(timeout))
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800117 return QUP_ERR_TIMEOUT;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800118 }
119
120 return QUP_SUCCESS;
121}
122
123static qup_return_t qup_i2c_write_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
124 uint8_t stop_seq)
125{
126 qup_return_t ret = QUP_ERR_UNDEFINED;
127 uint8_t addr = p_tx_obj->p.iic.addr;
128 uint8_t *data_ptr = p_tx_obj->p.iic.data;
Martin Roth57e89092019-10-23 21:45:23 -0600129 unsigned int data_len = p_tx_obj->p.iic.data_len;
130 unsigned int idx = 0;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800131 struct stopwatch timeout;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800132
133 qup_reset_master_status(gsbi_id);
134 qup_set_state(gsbi_id, QUP_STATE_RUN);
135
Julius Werner2f37bd62015-02-19 14:51:15 -0800136 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
137 (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800138
Jes Klinke19baa9d2022-02-22 16:00:09 -0800139 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800140 while (data_len) {
141 if (data_len == 1 && stop_seq) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800142 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800143 QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data_ptr[idx]));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800144 } else {
Julius Werner2f37bd62015-02-19 14:51:15 -0800145 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800146 QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data_ptr[idx]));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800147 }
148 data_len--;
149 idx++;
150 if (data_len) {
Jes Klinke19baa9d2022-02-22 16:00:09 -0800151 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_FULL,
152 &timeout);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800153 if (ret)
154 return ret;
155 }
156 /* Hardware sets the OUTPUT_SERVICE_FLAG flag to 1 when
Daisuke Nojiri05949142014-11-21 15:33:26 -0800157 OUTPUT_FIFO_NOT_EMPTY flag in the QUP_OPERATIONAL
158 register changes from 1 to 0, indicating that software
159 can write more data to the output FIFO. Software should
160 set OUTPUT_SERVICE_FLAG to 1 to clear it to 0, which
161 means that software knows to return to fill the output
162 FIFO with data.
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800163 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800164 if (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800165 OUTPUT_SERVICE_FLAG) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800166 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
167 OUTPUT_SERVICE_FLAG);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800168 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800169 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800170
Jes Klinke19baa9d2022-02-22 16:00:09 -0800171 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY, &timeout);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800172 if (ret)
173 return ret;
174
175 qup_set_state(gsbi_id, QUP_STATE_PAUSE);
Sourabh Banerjeef36cffc2015-02-27 19:18:11 +0530176 return qup_i2c_master_status(gsbi_id);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800177}
178
179static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode,
180 qup_data_t *p_tx_obj, uint8_t stop_seq)
181{
182 qup_return_t ret = QUP_ERR_UNDEFINED;
183
184 switch (mode) {
185 case QUP_MODE_FIFO:
186 ret = qup_i2c_write_fifo(gsbi_id, p_tx_obj, stop_seq);
187 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800188 default:
189 ret = QUP_ERR_UNSUPPORTED;
190 }
191
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800192 if (ret) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800193 qup_set_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800194 printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800195 }
196
197 return ret;
198}
199
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800200static qup_return_t qup_i2c_read_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj)
201{
202 qup_return_t ret = QUP_ERR_UNDEFINED;
203 uint8_t addr = p_tx_obj->p.iic.addr;
204 uint8_t *data_ptr = p_tx_obj->p.iic.data;
Martin Roth57e89092019-10-23 21:45:23 -0600205 unsigned int data_len = p_tx_obj->p.iic.data_len;
206 unsigned int idx = 0;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800207 struct stopwatch timeout;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800208
209 qup_reset_master_status(gsbi_id);
210 qup_set_state(gsbi_id, QUP_STATE_RUN);
211
Julius Werner2f37bd62015-02-19 14:51:15 -0800212 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800213 QUP_I2C_START_SEQ | (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800214
Julius Werner2f37bd62015-02-19 14:51:15 -0800215 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800216 QUP_I2C_RECV_SEQ | data_len);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800217
Jes Klinke19baa9d2022-02-22 16:00:09 -0800218 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
219 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY, &timeout);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800220 if (ret)
221 return ret;
222
Julius Werner2f37bd62015-02-19 14:51:15 -0800223 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800224
225 while (data_len) {
226 uint32_t data;
227
Jes Klinke19baa9d2022-02-22 16:00:09 -0800228 ret = qup_fifo_wait_for(gsbi_id, INPUT_SERVICE_FLAG, &timeout);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800229 if (ret)
230 return ret;
231
Julius Werner2f37bd62015-02-19 14:51:15 -0800232 data = read32(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800233
234 /*
235 * Process tag and corresponding data value. For I2C master
236 * mini-core, data in FIFO is composed of 16 bits and is divided
237 * into an 8-bit tag for the upper bits and 8-bit data for the
238 * lower bits. The 8-bit tag indicates whether the byte is the
239 * last byte, or if a bus error happened during the receipt of
240 * the byte.
241 */
242 if ((QUP_I2C_MI_TAG(data)) == QUP_I2C_MIDATA_SEQ) {
243 /* Tag: MIDATA = Master input data.*/
244 data_ptr[idx] = QUP_I2C_DATA(data);
245 idx++;
246 data_len--;
Julius Werner2f37bd62015-02-19 14:51:15 -0800247 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
248 INPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800249 } else if (QUP_I2C_MI_TAG(data) == QUP_I2C_MISTOP_SEQ) {
250 /* Tag: MISTOP: Last byte of master input. */
251 data_ptr[idx] = QUP_I2C_DATA(data);
252 idx++;
253 data_len--;
254 break;
255 } else {
256 /* Tag: MINACK: Invalid master input data.*/
257 break;
258 }
259 }
260
Julius Werner2f37bd62015-02-19 14:51:15 -0800261 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800262 p_tx_obj->p.iic.data_len = idx;
263 qup_set_state(gsbi_id, QUP_STATE_PAUSE);
264
265 return QUP_SUCCESS;
266}
267
Daisuke Nojiri05949142014-11-21 15:33:26 -0800268static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode,
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800269 qup_data_t *p_tx_obj)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800270{
271 qup_return_t ret = QUP_ERR_UNDEFINED;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800272
273 switch (mode) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800274 case QUP_MODE_FIFO:
275 ret = qup_i2c_read_fifo(gsbi_id, p_tx_obj);
276 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800277 default:
278 ret = QUP_ERR_UNSUPPORTED;
279 }
280
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800281 if (ret) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800282 qup_set_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800283 printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800284 }
285
286 return ret;
287}
288
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800289qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800290{
291 qup_return_t ret = QUP_ERR_UNDEFINED;
292 uint32_t reg_val;
293
294 /* Reset the QUP core.*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800295 write32(QUP_ADDR(gsbi_id, QUP_SW_RESET), 0x1);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800296
297 /*Wait till the reset takes effect */
298 ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800299 if (ret)
300 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800301
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800302 /* Reset the config */
Julius Werner2f37bd62015-02-19 14:51:15 -0800303 write32(QUP_ADDR(gsbi_id, QUP_CONFIG), 0);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800304
305 /*Program the config register*/
306 /*Set N value*/
307 reg_val = 0x0F;
308 /*Set protocol*/
309 switch (config_ptr->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800310 case QUP_MINICORE_I2C_MASTER:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800311 reg_val |= ((config_ptr->protocol &
312 QUP_MINI_CORE_PROTO_MASK) <<
313 QUP_MINI_CORE_PROTO_SHFT);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800314 break;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800315 default:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800316 ret = QUP_ERR_UNSUPPORTED;
317 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800318 }
Julius Werner2f37bd62015-02-19 14:51:15 -0800319 write32(QUP_ADDR(gsbi_id, QUP_CONFIG), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800320
321 /*Reset i2c clk cntl register*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800322 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), 0);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800323
324 /*Set QUP IO Mode*/
325 switch (config_ptr->mode) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800326 case QUP_MODE_FIFO:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800327 reg_val = QUP_OUTPUT_BIT_SHIFT_EN |
328 ((config_ptr->mode & QUP_MODE_MASK) <<
329 QUP_OUTPUT_MODE_SHFT) |
330 ((config_ptr->mode & QUP_MODE_MASK) <<
331 QUP_INPUT_MODE_SHFT);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800332 break;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800333 default:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800334 ret = QUP_ERR_UNSUPPORTED;
335 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800336 }
Julius Werner2f37bd62015-02-19 14:51:15 -0800337 write32(QUP_ADDR(gsbi_id, QUP_IO_MODES), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800338
339 /*Set i2c clk cntl*/
340 reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT);
341 reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency)
342 / 2) - QUP_DIVIDER_MIN_VAL) &
343 QUP_FS_DIVIDER_MASK);
Julius Werner2f37bd62015-02-19 14:51:15 -0800344 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800345
346bailout:
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800347 if (ret)
348 printk(BIOS_ERR, "failed to init qup (%d)\n", ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800349
350 return ret;
351}
352
353qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
354{
355 qup_return_t ret = QUP_ERR_UNDEFINED;
Martin Roth57e89092019-10-23 21:45:23 -0600356 unsigned int curr_state = read32(QUP_ADDR(gsbi_id, QUP_STATE));
Daisuke Nojiri05949142014-11-21 15:33:26 -0800357
Julius Werner7c712bb2019-05-01 16:51:20 -0700358 if (state <= QUP_STATE_PAUSE && (curr_state & QUP_STATE_VALID_MASK)) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800359 /*
360 * For PAUSE_STATE to RESET_STATE transition,
361 * two writes of 10[binary]) are required for the
362 * transition to complete.
363 */
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800364 if (QUP_STATE_PAUSE == curr_state && QUP_STATE_RESET == state) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800365 write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
366 write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800367 } else {
Julius Werner2f37bd62015-02-19 14:51:15 -0800368 write32(QUP_ADDR(gsbi_id, QUP_STATE), state);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800369 }
370 ret = qup_wait_for_state(gsbi_id, state);
371 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800372
Daisuke Nojiri05949142014-11-21 15:33:26 -0800373 return ret;
374}
375
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800376static qup_return_t qup_i2c_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
377 uint8_t stop_seq)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800378{
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800379 qup_return_t ret = QUP_ERR_UNDEFINED;
Julius Werner2f37bd62015-02-19 14:51:15 -0800380 uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800381 QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
382
383 ret = qup_i2c_write(gsbi_id, mode, p_tx_obj, stop_seq);
384 if (0) {
385 int i;
386 printk(BIOS_DEBUG, "i2c tx bus %d device %2.2x:",
387 gsbi_id, p_tx_obj->p.iic.addr);
388 for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
389 printk(BIOS_DEBUG, " %2.2x", p_tx_obj->p.iic.data[i]);
390 printk(BIOS_DEBUG, "\n");
391 }
392
393 return ret;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800394}
395
396qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
397 uint8_t stop_seq)
398{
399 qup_return_t ret = QUP_ERR_UNDEFINED;
400
Julius Werner2f37bd62015-02-19 14:51:15 -0800401 if (p_tx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800402 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800403 switch (p_tx_obj->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800404 case QUP_MINICORE_I2C_MASTER:
405 ret = qup_i2c_send_data(gsbi_id, p_tx_obj, stop_seq);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800406 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800407 default:
408 ret = QUP_ERR_UNSUPPORTED;
409 }
410 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800411
412 return ret;
413}
414
415static qup_return_t qup_i2c_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
416{
417 qup_return_t ret = QUP_ERR_UNDEFINED;
Julius Werner2f37bd62015-02-19 14:51:15 -0800418 uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800419 QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
420
421 ret = qup_i2c_read(gsbi_id, mode, p_rx_obj);
422 if (0) {
423 int i;
424 printk(BIOS_DEBUG, "i2c rxed on bus %d device %2.2x:",
425 gsbi_id, p_rx_obj->p.iic.addr);
426 for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
427 printk(BIOS_DEBUG, " %2.2x", p_rx_obj->p.iic.data[i]);
428 printk(BIOS_DEBUG, "\n");
429 }
430
Daisuke Nojiri05949142014-11-21 15:33:26 -0800431 return ret;
432}
433
434qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
435{
436 qup_return_t ret = QUP_ERR_UNDEFINED;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800437
Julius Werner2f37bd62015-02-19 14:51:15 -0800438 if (p_rx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800439 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800440 switch (p_rx_obj->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800441 case QUP_MINICORE_I2C_MASTER:
442 ret = qup_i2c_recv_data(gsbi_id, p_rx_obj);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800443 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800444 default:
445 ret = QUP_ERR_UNSUPPORTED;
446 }
447 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800448
Daisuke Nojiri05949142014-11-21 15:33:26 -0800449 return ret;
450}