blob: a497514bafdd57071d484b9dae24b3b54b82bba0 [file] [log] [blame]
Daisuke Nojiri05949142014-11-21 15:33:26 -08001/*
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -08002 * This file is part of the coreboot project.
Daisuke Nojiri05949142014-11-21 15:33:26 -08003 *
Sourabh Banerjee89208652015-02-19 16:43:26 +05304 * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
Daisuke Nojiri05949142014-11-21 15:33:26 -08005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <arch/io.h>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080031#include <console/console.h>
32#include <delay.h>
33#include <soc/iomap.h>
34#include <stdlib.h>
35#include <soc/qup.h>
36
37#define TIMEOUT_CNT 100000
Daisuke Nojiri05949142014-11-21 15:33:26 -080038
39//TODO: refactor the following array to iomap driver.
40static unsigned gsbi_qup_base[] = {
Sourabh Banerjee89208652015-02-19 16:43:26 +053041 (unsigned)GSBI_QUP1_BASE,
42 (unsigned)GSBI_QUP2_BASE,
43 (unsigned)GSBI_QUP3_BASE,
44 (unsigned)GSBI_QUP4_BASE,
45 (unsigned)GSBI_QUP5_BASE,
46 (unsigned)GSBI_QUP6_BASE,
47 (unsigned)GSBI_QUP7_BASE,
Daisuke Nojiri05949142014-11-21 15:33:26 -080048};
49
50#define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg)))
Daisuke Nojiri05949142014-11-21 15:33:26 -080051
52static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id)
53{
Julius Werner2f37bd62015-02-19 14:51:15 -080054 uint32_t reg_val = read32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
Daisuke Nojiri05949142014-11-21 15:33:26 -080055
Julius Werner2f37bd62015-02-19 14:51:15 -080056 if (read32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)))
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080057 return QUP_ERR_XFER_FAIL;
58 if (reg_val & QUP_I2C_INVALID_READ_ADDR)
59 return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
60 if (reg_val & QUP_I2C_FAILED_MASK)
61 return QUP_ERR_I2C_FAILED;
62 if (reg_val & QUP_I2C_ARB_LOST)
63 return QUP_ERR_I2C_ARB_LOST;
64 if (reg_val & QUP_I2C_BUS_ERROR)
65 return QUP_ERR_I2C_BUS_ERROR;
Sourabh Banerjeef36cffc2015-02-27 19:18:11 +053066 if (reg_val & QUP_I2C_INVALID_WRITE)
67 return QUP_ERR_I2C_INVALID_WRITE;
68 if (reg_val & QUP_I2C_PACKET_NACK)
69 return QUP_ERR_I2C_NACK;
70 if (reg_val & QUP_I2C_INVALID_TAG)
71 return QUP_ERR_I2C_INVALID_TAG;
Daisuke Nojiri05949142014-11-21 15:33:26 -080072
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080073 return QUP_SUCCESS;
Daisuke Nojiri05949142014-11-21 15:33:26 -080074}
75
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080076static int check_bit_state(uint32_t *reg, int wait_for)
77{
78 unsigned int count = TIMEOUT_CNT;
79
Julius Werner2f37bd62015-02-19 14:51:15 -080080 while ((read32(reg) & (QUP_STATE_VALID_MASK | QUP_STATE_MASK)) !=
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080081 (QUP_STATE_VALID | wait_for)) {
82 if (count == 0)
83 return QUP_ERR_TIMEOUT;
84 count--;
85 udelay(1);
86 }
87
88 return QUP_SUCCESS;
89}
90
91/*
92 * Check whether GSBIn_QUP State is valid
93 */
Daisuke Nojiri05949142014-11-21 15:33:26 -080094static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned wait_for)
95{
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080096 return check_bit_state(QUP_ADDR(gsbi_id, QUP_STATE), wait_for);
Daisuke Nojiri05949142014-11-21 15:33:26 -080097}
98
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -080099qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id)
100{
101 /*
102 * Writing a one clears the status bits.
103 * Bit31-25, Bit1 and Bit0 are reserved.
104 */
105 //TODO: Define each status bit. OR all status bits in a single macro.
Julius Werner2f37bd62015-02-19 14:51:15 -0800106 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS), 0x3FFFFFC);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800107 return QUP_SUCCESS;
108}
109
110static qup_return_t qup_reset_master_status(gsbi_id_t gsbi_id)
111{
Julius Werner2f37bd62015-02-19 14:51:15 -0800112 write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS), 0x7C);
113 write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN), 0x7C);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800114 qup_reset_i2c_master_status(gsbi_id);
115 return QUP_SUCCESS;
116}
117
118static qup_return_t qup_fifo_wait_for(gsbi_id_t gsbi_id, uint32_t status)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800119{
120 qup_return_t ret = QUP_ERR_UNDEFINED;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800121 unsigned int count = TIMEOUT_CNT;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800122
Julius Werner2f37bd62015-02-19 14:51:15 -0800123 while (!(read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status)) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800124 ret = qup_i2c_master_status(gsbi_id);
125 if (ret)
126 return ret;
127 if (count == 0)
128 return QUP_ERR_TIMEOUT;
129 count--;
130 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800131
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800132 return QUP_SUCCESS;
133}
Daisuke Nojiri05949142014-11-21 15:33:26 -0800134
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800135static qup_return_t qup_fifo_wait_while(gsbi_id_t gsbi_id, uint32_t status)
136{
137 qup_return_t ret = QUP_ERR_UNDEFINED;
138 unsigned int count = TIMEOUT_CNT;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800139
Julius Werner2f37bd62015-02-19 14:51:15 -0800140 while (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800141 ret = qup_i2c_master_status(gsbi_id);
142 if (ret)
143 return ret;
144 if (count == 0)
145 return QUP_ERR_TIMEOUT;
146 count--;
147 }
148
149 return QUP_SUCCESS;
150}
151
152static qup_return_t qup_i2c_write_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
153 uint8_t stop_seq)
154{
155 qup_return_t ret = QUP_ERR_UNDEFINED;
156 uint8_t addr = p_tx_obj->p.iic.addr;
157 uint8_t *data_ptr = p_tx_obj->p.iic.data;
158 unsigned data_len = p_tx_obj->p.iic.data_len;
159 unsigned idx = 0;
160
161 qup_reset_master_status(gsbi_id);
162 qup_set_state(gsbi_id, QUP_STATE_RUN);
163
Julius Werner2f37bd62015-02-19 14:51:15 -0800164 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
165 (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800166
167 while (data_len) {
168 if (data_len == 1 && stop_seq) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800169 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800170 QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data_ptr[idx]));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800171 } else {
Julius Werner2f37bd62015-02-19 14:51:15 -0800172 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800173 QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data_ptr[idx]));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800174 }
175 data_len--;
176 idx++;
177 if (data_len) {
178 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_FULL);
179 if (ret)
180 return ret;
181 }
182 /* Hardware sets the OUTPUT_SERVICE_FLAG flag to 1 when
Daisuke Nojiri05949142014-11-21 15:33:26 -0800183 OUTPUT_FIFO_NOT_EMPTY flag in the QUP_OPERATIONAL
184 register changes from 1 to 0, indicating that software
185 can write more data to the output FIFO. Software should
186 set OUTPUT_SERVICE_FLAG to 1 to clear it to 0, which
187 means that software knows to return to fill the output
188 FIFO with data.
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800189 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800190 if (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800191 OUTPUT_SERVICE_FLAG) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800192 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
193 OUTPUT_SERVICE_FLAG);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800194 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800195 }
Daisuke Nojiri05949142014-11-21 15:33:26 -0800196
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800197 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
198 if (ret)
199 return ret;
200
201 qup_set_state(gsbi_id, QUP_STATE_PAUSE);
Sourabh Banerjeef36cffc2015-02-27 19:18:11 +0530202 return qup_i2c_master_status(gsbi_id);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800203}
204
205static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode,
206 qup_data_t *p_tx_obj, uint8_t stop_seq)
207{
208 qup_return_t ret = QUP_ERR_UNDEFINED;
209
210 switch (mode) {
211 case QUP_MODE_FIFO:
212 ret = qup_i2c_write_fifo(gsbi_id, p_tx_obj, stop_seq);
213 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800214 default:
215 ret = QUP_ERR_UNSUPPORTED;
216 }
217
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800218 if (ret) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800219 qup_set_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800220 printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800221 }
222
223 return ret;
224}
225
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800226static qup_return_t qup_i2c_read_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj)
227{
228 qup_return_t ret = QUP_ERR_UNDEFINED;
229 uint8_t addr = p_tx_obj->p.iic.addr;
230 uint8_t *data_ptr = p_tx_obj->p.iic.data;
231 unsigned data_len = p_tx_obj->p.iic.data_len;
232 unsigned idx = 0;
233
234 qup_reset_master_status(gsbi_id);
235 qup_set_state(gsbi_id, QUP_STATE_RUN);
236
Julius Werner2f37bd62015-02-19 14:51:15 -0800237 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800238 QUP_I2C_START_SEQ | (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800239
Julius Werner2f37bd62015-02-19 14:51:15 -0800240 write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
Julius Werner94184762015-02-19 20:19:23 -0800241 QUP_I2C_RECV_SEQ | data_len);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800242
243 ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
244 if (ret)
245 return ret;
246
Julius Werner2f37bd62015-02-19 14:51:15 -0800247 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800248
249 while (data_len) {
250 uint32_t data;
251
252 ret = qup_fifo_wait_for(gsbi_id, INPUT_SERVICE_FLAG);
253 if (ret)
254 return ret;
255
Julius Werner2f37bd62015-02-19 14:51:15 -0800256 data = read32(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO));
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800257
258 /*
259 * Process tag and corresponding data value. For I2C master
260 * mini-core, data in FIFO is composed of 16 bits and is divided
261 * into an 8-bit tag for the upper bits and 8-bit data for the
262 * lower bits. The 8-bit tag indicates whether the byte is the
263 * last byte, or if a bus error happened during the receipt of
264 * the byte.
265 */
266 if ((QUP_I2C_MI_TAG(data)) == QUP_I2C_MIDATA_SEQ) {
267 /* Tag: MIDATA = Master input data.*/
268 data_ptr[idx] = QUP_I2C_DATA(data);
269 idx++;
270 data_len--;
Julius Werner2f37bd62015-02-19 14:51:15 -0800271 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
272 INPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800273 } else if (QUP_I2C_MI_TAG(data) == QUP_I2C_MISTOP_SEQ) {
274 /* Tag: MISTOP: Last byte of master input. */
275 data_ptr[idx] = QUP_I2C_DATA(data);
276 idx++;
277 data_len--;
278 break;
279 } else {
280 /* Tag: MINACK: Invalid master input data.*/
281 break;
282 }
283 }
284
Julius Werner2f37bd62015-02-19 14:51:15 -0800285 write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800286 p_tx_obj->p.iic.data_len = idx;
287 qup_set_state(gsbi_id, QUP_STATE_PAUSE);
288
289 return QUP_SUCCESS;
290}
291
Daisuke Nojiri05949142014-11-21 15:33:26 -0800292static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode,
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800293 qup_data_t *p_tx_obj)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800294{
295 qup_return_t ret = QUP_ERR_UNDEFINED;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800296
297 switch (mode) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800298 case QUP_MODE_FIFO:
299 ret = qup_i2c_read_fifo(gsbi_id, p_tx_obj);
300 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800301 default:
302 ret = QUP_ERR_UNSUPPORTED;
303 }
304
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800305 if (ret) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800306 qup_set_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800307 printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800308 }
309
310 return ret;
311}
312
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800313qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800314{
315 qup_return_t ret = QUP_ERR_UNDEFINED;
316 uint32_t reg_val;
317
318 /* Reset the QUP core.*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800319 write32(QUP_ADDR(gsbi_id, QUP_SW_RESET), 0x1);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800320
321 /*Wait till the reset takes effect */
322 ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET);
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800323 if (ret)
324 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800325
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800326 /* Reset the config */
Julius Werner2f37bd62015-02-19 14:51:15 -0800327 write32(QUP_ADDR(gsbi_id, QUP_CONFIG), 0);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800328
329 /*Program the config register*/
330 /*Set N value*/
331 reg_val = 0x0F;
332 /*Set protocol*/
333 switch (config_ptr->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800334 case QUP_MINICORE_I2C_MASTER:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800335 reg_val |= ((config_ptr->protocol &
336 QUP_MINI_CORE_PROTO_MASK) <<
337 QUP_MINI_CORE_PROTO_SHFT);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800338 break;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800339 default:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800340 ret = QUP_ERR_UNSUPPORTED;
341 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800342 }
Julius Werner2f37bd62015-02-19 14:51:15 -0800343 write32(QUP_ADDR(gsbi_id, QUP_CONFIG), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800344
345 /*Reset i2c clk cntl register*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800346 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), 0);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800347
348 /*Set QUP IO Mode*/
349 switch (config_ptr->mode) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800350 case QUP_MODE_FIFO:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800351 reg_val = QUP_OUTPUT_BIT_SHIFT_EN |
352 ((config_ptr->mode & QUP_MODE_MASK) <<
353 QUP_OUTPUT_MODE_SHFT) |
354 ((config_ptr->mode & QUP_MODE_MASK) <<
355 QUP_INPUT_MODE_SHFT);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800356 break;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800357 default:
Daisuke Nojiri05949142014-11-21 15:33:26 -0800358 ret = QUP_ERR_UNSUPPORTED;
359 goto bailout;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800360 }
Julius Werner2f37bd62015-02-19 14:51:15 -0800361 write32(QUP_ADDR(gsbi_id, QUP_IO_MODES), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800362
363 /*Set i2c clk cntl*/
364 reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT);
365 reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency)
366 / 2) - QUP_DIVIDER_MIN_VAL) &
367 QUP_FS_DIVIDER_MASK);
Julius Werner2f37bd62015-02-19 14:51:15 -0800368 write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), reg_val);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800369
370bailout:
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800371 if (ret)
372 printk(BIOS_ERR, "failed to init qup (%d)\n", ret);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800373
374 return ret;
375}
376
377qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
378{
379 qup_return_t ret = QUP_ERR_UNDEFINED;
Julius Werner2f37bd62015-02-19 14:51:15 -0800380 unsigned curr_state = read32(QUP_ADDR(gsbi_id, QUP_STATE));
Daisuke Nojiri05949142014-11-21 15:33:26 -0800381
382 if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE)
383 && (curr_state & QUP_STATE_VALID_MASK)) {
384 /*
385 * For PAUSE_STATE to RESET_STATE transition,
386 * two writes of 10[binary]) are required for the
387 * transition to complete.
388 */
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800389 if (QUP_STATE_PAUSE == curr_state && QUP_STATE_RESET == state) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800390 write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
391 write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800392 } else {
Julius Werner2f37bd62015-02-19 14:51:15 -0800393 write32(QUP_ADDR(gsbi_id, QUP_STATE), state);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800394 }
395 ret = qup_wait_for_state(gsbi_id, state);
396 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800397
Daisuke Nojiri05949142014-11-21 15:33:26 -0800398 return ret;
399}
400
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800401static qup_return_t qup_i2c_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
402 uint8_t stop_seq)
Daisuke Nojiri05949142014-11-21 15:33:26 -0800403{
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800404 qup_return_t ret = QUP_ERR_UNDEFINED;
Julius Werner2f37bd62015-02-19 14:51:15 -0800405 uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800406 QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
407
408 ret = qup_i2c_write(gsbi_id, mode, p_tx_obj, stop_seq);
409 if (0) {
410 int i;
411 printk(BIOS_DEBUG, "i2c tx bus %d device %2.2x:",
412 gsbi_id, p_tx_obj->p.iic.addr);
413 for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
414 printk(BIOS_DEBUG, " %2.2x", p_tx_obj->p.iic.data[i]);
415 printk(BIOS_DEBUG, "\n");
416 }
417
418 return ret;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800419}
420
421qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
422 uint8_t stop_seq)
423{
424 qup_return_t ret = QUP_ERR_UNDEFINED;
425
Julius Werner2f37bd62015-02-19 14:51:15 -0800426 if (p_tx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800427 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800428 switch (p_tx_obj->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800429 case QUP_MINICORE_I2C_MASTER:
430 ret = qup_i2c_send_data(gsbi_id, p_tx_obj, stop_seq);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800431 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800432 default:
433 ret = QUP_ERR_UNSUPPORTED;
434 }
435 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800436
437 return ret;
438}
439
440static qup_return_t qup_i2c_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
441{
442 qup_return_t ret = QUP_ERR_UNDEFINED;
Julius Werner2f37bd62015-02-19 14:51:15 -0800443 uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800444 QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
445
446 ret = qup_i2c_read(gsbi_id, mode, p_rx_obj);
447 if (0) {
448 int i;
449 printk(BIOS_DEBUG, "i2c rxed on bus %d device %2.2x:",
450 gsbi_id, p_rx_obj->p.iic.addr);
451 for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
452 printk(BIOS_DEBUG, " %2.2x", p_rx_obj->p.iic.data[i]);
453 printk(BIOS_DEBUG, "\n");
454 }
455
Daisuke Nojiri05949142014-11-21 15:33:26 -0800456 return ret;
457}
458
459qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
460{
461 qup_return_t ret = QUP_ERR_UNDEFINED;
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800462
Julius Werner2f37bd62015-02-19 14:51:15 -0800463 if (p_rx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800464 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
Daisuke Nojiri05949142014-11-21 15:33:26 -0800465 switch (p_rx_obj->protocol) {
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800466 case QUP_MINICORE_I2C_MASTER:
467 ret = qup_i2c_recv_data(gsbi_id, p_rx_obj);
Daisuke Nojiri05949142014-11-21 15:33:26 -0800468 break;
Daisuke Nojiri05949142014-11-21 15:33:26 -0800469 default:
470 ret = QUP_ERR_UNSUPPORTED;
471 }
472 }
Vadim Bendebury6fe4e5e2014-12-06 10:44:58 -0800473
Daisuke Nojiri05949142014-11-21 15:33:26 -0800474 return ret;
475}