blob: 4b525b69488a7128fba1daddfc80a150f45d1bf6 [file] [log] [blame]
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -08001/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
Shashank Mittalc69512e2010-09-22 16:40:48 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -080012 * * Neither the name of The Linux Foundation, Inc. nor the names of its
Shashank Mittalc69512e2010-09-22 16:40:48 -070013 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * QUP driver for Qualcomm MSM platforms
31 *
32 */
33
34#include <debug.h>
35#include <arch/arm.h>
36#include <reg.h>
37#include <kernel/thread.h>
Greg Griscod2471ef2011-07-14 13:00:42 -070038#include <dev/gpio.h>
39#include <stdlib.h>
40#include <string.h>
Shashank Mittalc69512e2010-09-22 16:40:48 -070041
Amol Jadic52c8a32011-07-12 11:27:04 -070042#include <gsbi.h>
Shashank Mittalc69512e2010-09-22 16:40:48 -070043#include <i2c_qup.h>
44#include <platform/irqs.h>
45#include <platform/iomap.h>
Amol Jadic52c8a32011-07-12 11:27:04 -070046#include <platform/gpio.h>
47#include <platform/clock.h>
Greg Griscod2471ef2011-07-14 13:00:42 -070048#include <platform/timer.h>
49#include <platform/interrupts.h>
50
Shashank Mittalc69512e2010-09-22 16:40:48 -070051static struct qup_i2c_dev *dev_addr = NULL;
52
53/* QUP Registers */
54enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -080055 QUP_CONFIG = 0x0,
56 QUP_STATE = 0x4,
57 QUP_IO_MODE = 0x8,
58 QUP_SW_RESET = 0xC,
59 QUP_OPERATIONAL = 0x18,
60 QUP_ERROR_FLAGS = 0x1C,
61 QUP_ERROR_FLAGS_EN = 0x20,
62 QUP_MX_READ_CNT = 0x208,
63 QUP_MX_INPUT_CNT = 0x200,
64 QUP_MX_WR_CNT = 0x100,
65 QUP_OUT_DEBUG = 0x108,
66 QUP_OUT_FIFO_CNT = 0x10C,
67 QUP_OUT_FIFO_BASE = 0x110,
68 QUP_IN_READ_CUR = 0x20C,
69 QUP_IN_DEBUG = 0x210,
70 QUP_IN_FIFO_CNT = 0x214,
71 QUP_IN_FIFO_BASE = 0x218,
72 QUP_I2C_CLK_CTL = 0x400,
73 QUP_I2C_STATUS = 0x404,
Shashank Mittalc69512e2010-09-22 16:40:48 -070074};
75
76/* QUP States and reset values */
77enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -080078 QUP_RESET_STATE = 0,
79 QUP_RUN_STATE = 1U,
80 QUP_STATE_MASK = 3U,
81 QUP_PAUSE_STATE = 3U,
82 QUP_STATE_VALID = 1U << 2,
83 QUP_I2C_MAST_GEN = 1U << 4,
84 QUP_OPERATIONAL_RESET = 0xFF0,
85 QUP_I2C_STATUS_RESET = 0xFFFFFC,
Shashank Mittalc69512e2010-09-22 16:40:48 -070086};
87
88/* QUP OPERATIONAL FLAGS */
89enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -080090 QUP_OUT_SVC_FLAG = 1U << 8,
91 QUP_IN_SVC_FLAG = 1U << 9,
92 QUP_MX_INPUT_DONE = 1U << 11,
Shashank Mittalc69512e2010-09-22 16:40:48 -070093};
94
95/* I2C mini core related values */
96enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -080097 I2C_MINI_CORE = 2U << 8,
98 I2C_N_VAL = 0xF,
Shashank Mittalc69512e2010-09-22 16:40:48 -070099
100};
101
102/* Packing Unpacking words in FIFOs , and IO modes*/
103enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800104 QUP_WR_BLK_MODE = 1U << 10,
105 QUP_RD_BLK_MODE = 1U << 12,
106 QUP_UNPACK_EN = 1U << 14,
107 QUP_PACK_EN = 1U << 15,
Shashank Mittalc69512e2010-09-22 16:40:48 -0700108};
109
110/* QUP tags */
111enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800112 QUP_OUT_NOP = 0,
113 QUP_OUT_START = 1U << 8,
114 QUP_OUT_DATA = 2U << 8,
115 QUP_OUT_STOP = 3U << 8,
116 QUP_OUT_REC = 4U << 8,
117 QUP_IN_DATA = 5U << 8,
118 QUP_IN_STOP = 6U << 8,
119 QUP_IN_NACK = 7U << 8,
Shashank Mittalc69512e2010-09-22 16:40:48 -0700120};
121
122/* Status, Error flags */
123enum {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 I2C_STATUS_WR_BUFFER_FULL = 1U << 0,
125 I2C_STATUS_BUS_ACTIVE = 1U << 8,
126 I2C_STATUS_ERROR_MASK = 0x38000FC,
127 QUP_I2C_NACK_FLAG = 1U << 3,
128 QUP_IN_NOT_EMPTY = 1U << 5,
129 QUP_STATUS_ERROR_FLAGS = 0x7C,
Shashank Mittalc69512e2010-09-22 16:40:48 -0700130};
131
Subbaraman Narayanamurthydcc8e932011-05-25 18:13:37 -0700132#ifdef DEBUG_QUP
Shashank Mittalc69512e2010-09-22 16:40:48 -0700133static void qup_print_status(struct qup_i2c_dev *dev)
134{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800135 unsigned val;
136 val = readl(dev->qup_base + QUP_CONFIG);
137 dprintf(INFO, "Qup config is :0x%x\n", val);
138 val = readl(dev->qup_base + QUP_STATE);
139 dprintf(INFO, "Qup state is :0x%x\n", val);
140 val = readl(dev->qup_base + QUP_IO_MODE);
141 dprintf(INFO, "Qup mode is :0x%x\n", val);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700142}
143#else
144static inline void qup_print_status(struct qup_i2c_dev *dev)
145{
146}
147#endif
148
Shashank Mittalc69512e2010-09-22 16:40:48 -0700149static irqreturn_t qup_i2c_interrupt(void)
150{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800151 struct qup_i2c_dev *dev = dev_addr;
152 if (!dev) {
153 dprintf(CRITICAL,
154 "dev_addr is NULL, that means i2c_qup_init failed...\n");
155 return IRQ_FAIL;
156 }
157 unsigned status = readl(dev->qup_base + QUP_I2C_STATUS);
158 unsigned status1 = readl(dev->qup_base + QUP_ERROR_FLAGS);
159 unsigned op_flgs = readl(dev->qup_base + QUP_OPERATIONAL);
160 int err = 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700161
Ajay Dudanib01e5062011-12-03 23:23:42 -0800162 if (!dev->msg)
163 return IRQ_HANDLED;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700164
Ajay Dudanib01e5062011-12-03 23:23:42 -0800165 if (status & I2C_STATUS_ERROR_MASK) {
166 dprintf(CRITICAL, "QUP: I2C status flags :0x%x \n", status);
167 err = -status;
168 /* Clear Error interrupt if it's a level triggered interrupt */
169 if (dev->num_irqs == 1) {
170 writel(QUP_RESET_STATE, dev->qup_base + QUP_STATE);
171 }
172 goto intr_done;
173 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700174
Ajay Dudanib01e5062011-12-03 23:23:42 -0800175 if (status1 & 0x7F) {
176 dprintf(CRITICAL, "QUP: QUP status flags :0x%x\n", status1);
177 err = -status1;
178 /* Clear Error interrupt if it's a level triggered interrupt */
179 if (dev->num_irqs == 1)
180 writel((status1 & QUP_STATUS_ERROR_FLAGS),
181 dev->qup_base + QUP_ERROR_FLAGS);
182 goto intr_done;
183 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700184
Ajay Dudanib01e5062011-12-03 23:23:42 -0800185 if (op_flgs & QUP_OUT_SVC_FLAG)
186 writel(QUP_OUT_SVC_FLAG, dev->qup_base + QUP_OPERATIONAL);
187 if (dev->msg->flags == I2C_M_RD) {
188 if ((op_flgs & QUP_MX_INPUT_DONE)
189 || (op_flgs & QUP_IN_SVC_FLAG))
190 writel(QUP_IN_SVC_FLAG,
191 dev->qup_base + QUP_OPERATIONAL);
192 else
193 return IRQ_HANDLED;
194 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700195
Ajay Dudanib01e5062011-12-03 23:23:42 -0800196 intr_done:
197 dev->err = err;
198 return IRQ_HANDLED;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700199}
200
201static int qup_i2c_poll_writeready(struct qup_i2c_dev *dev)
202{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800203 unsigned retries = 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700204
Ajay Dudanib01e5062011-12-03 23:23:42 -0800205 while (retries != 2000) {
206 unsigned status = readl(dev->qup_base + QUP_I2C_STATUS);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700207
Ajay Dudanib01e5062011-12-03 23:23:42 -0800208 if (!(status & I2C_STATUS_WR_BUFFER_FULL)) {
209 if (!(status & I2C_STATUS_BUS_ACTIVE))
210 return 0;
211 else /* 1-bit delay before we check for bus busy */
212 udelay(dev->one_bit_t);
213 }
214 if (retries++ == 1000)
215 udelay(100);
216 }
217 qup_print_status(dev);
218 return -ETIMEDOUT;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700219}
220
221static int qup_i2c_poll_state(struct qup_i2c_dev *dev, unsigned state)
222{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800223 unsigned retries = 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700224
Ajay Dudanib01e5062011-12-03 23:23:42 -0800225 dprintf(INFO, "Polling Status for state:0x%x\n", state);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700226
Ajay Dudanib01e5062011-12-03 23:23:42 -0800227 while (retries != 2000) {
228 unsigned status = readl(dev->qup_base + QUP_STATE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700229
Ajay Dudanib01e5062011-12-03 23:23:42 -0800230 if ((status & (QUP_STATE_VALID | state)) ==
231 (QUP_STATE_VALID | state))
232 return 0;
233 else if (retries++ == 1000)
234 udelay(100);
235 }
236 return -ETIMEDOUT;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700237}
238
239#ifdef DEBUG
Ajay Dudanib01e5062011-12-03 23:23:42 -0800240static void
241qup_verify_fifo(struct qup_i2c_dev *dev, unsigned val, unsigned addr, int rdwr)
Shashank Mittalc69512e2010-09-22 16:40:48 -0700242{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800243 if (rdwr)
244 dprintf(INFO, "RD:Wrote 0x%x to out_ff:0x%x\n", val, addr);
245 else
246 dprintf(INFO, "WR:Wrote 0x%x to out_ff:0x%x\n", val, addr);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700247}
248#else
Ajay Dudanib01e5062011-12-03 23:23:42 -0800249static inline void
250qup_verify_fifo(struct qup_i2c_dev *dev, unsigned val, unsigned addr, int rdwr)
Shashank Mittalc69512e2010-09-22 16:40:48 -0700251{
252}
253#endif
254
255static void
256qup_issue_read(struct qup_i2c_dev *dev, struct i2c_msg *msg, int *idx,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800257 unsigned carry_over)
Shashank Mittalc69512e2010-09-22 16:40:48 -0700258{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800259 uint16_t addr = (msg->addr << 1) | 1;
260 /* QUP limit 256 bytes per read. By HW design, 0 in the 8-bit field is
261 treated as 256 byte read. */
262 uint16_t rd_len = ((dev->cnt == 256) ? 0 : dev->cnt);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700263
Ajay Dudanib01e5062011-12-03 23:23:42 -0800264 if (*idx % 4) {
265 writel(carry_over | ((QUP_OUT_START | addr) << 16),
266 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700267
Ajay Dudanib01e5062011-12-03 23:23:42 -0800268 qup_verify_fifo(dev, carry_over |
269 ((QUP_OUT_START | addr) << 16),
270 (unsigned)dev->qup_base + QUP_OUT_FIFO_BASE +
271 (*idx - 2), 1);
272 writel((QUP_OUT_REC | rd_len),
273 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700274
Ajay Dudanib01e5062011-12-03 23:23:42 -0800275 qup_verify_fifo(dev, (QUP_OUT_REC | rd_len),
276 (unsigned)dev->qup_base + QUP_OUT_FIFO_BASE +
277 (*idx + 2), 1);
278 } else {
279 writel(((QUP_OUT_REC | rd_len) << 16) |
280 QUP_OUT_START | addr, dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700281
Ajay Dudanib01e5062011-12-03 23:23:42 -0800282 qup_verify_fifo(dev, QUP_OUT_REC << 16 | rd_len << 16 |
283 QUP_OUT_START | addr,
284 (unsigned)dev->qup_base + QUP_OUT_FIFO_BASE +
285 (*idx), 1);
286 }
287 *idx += 4;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700288}
289
290static void
291qup_issue_write(struct qup_i2c_dev *dev, struct i2c_msg *msg, int rem,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800292 int *idx, unsigned *carry_over)
Shashank Mittalc69512e2010-09-22 16:40:48 -0700293{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800294 int entries = dev->cnt;
295 int empty_sl = dev->wr_sz - ((*idx) >> 1);
296 int i = 0;
297 unsigned val = 0;
298 unsigned last_entry = 0;
299 uint16_t addr = msg->addr << 1;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700300
Ajay Dudanib01e5062011-12-03 23:23:42 -0800301 if (dev->pos == 0) {
302 if (*idx % 4) {
303 writel(*carry_over | ((QUP_OUT_START | addr) << 16),
304 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700305
Ajay Dudanib01e5062011-12-03 23:23:42 -0800306 qup_verify_fifo(dev, *carry_over | QUP_OUT_DATA << 16 |
307 addr << 16, (unsigned)dev->qup_base +
308 QUP_OUT_FIFO_BASE + (*idx) - 2, 0);
309 } else
310 val = QUP_OUT_START | addr;
311 *idx += 2;
312 i++;
313 entries++;
314 } else {
315 /* Avoid setp time issue by adding 1 NOP when number of bytes are more
316 than FIFO/BLOCK size. setup time issue can't appear otherwise since
317 next byte to be written will always be ready */
318 val = (QUP_OUT_NOP | 1);
319 *idx += 2;
320 i++;
321 entries++;
322 }
323 if (entries > empty_sl)
324 entries = empty_sl;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700325
Ajay Dudanib01e5062011-12-03 23:23:42 -0800326 for (; i < (entries - 1); i++) {
327 if (*idx % 4) {
328 writel(val | ((QUP_OUT_DATA |
329 msg->buf[dev->pos]) << 16),
330 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700331
Ajay Dudanib01e5062011-12-03 23:23:42 -0800332 qup_verify_fifo(dev, val | QUP_OUT_DATA << 16 |
333 msg->buf[dev->pos] << 16,
334 (unsigned)dev->qup_base +
335 QUP_OUT_FIFO_BASE + (*idx) - 2, 0);
336 } else
337 val = QUP_OUT_DATA | msg->buf[dev->pos];
338 (*idx) += 2;
339 dev->pos++;
340 }
341 if (dev->pos < (msg->len - 1))
342 last_entry = QUP_OUT_DATA;
343 else if (rem > 1) /* not last array entry */
344 last_entry = QUP_OUT_DATA;
345 else
346 last_entry = QUP_OUT_STOP;
347 if ((*idx % 4) == 0) {
348 /*
349 * If read-start and read-command end up in different fifos, it
350 * may result in extra-byte being read due to extra-read cycle.
351 * Avoid that by inserting NOP as the last entry of fifo only
352 * if write command(s) leave 1 space in fifo.
353 */
354 if (rem > 1) {
355 struct i2c_msg *next = msg + 1;
Amol Jadi34a21952012-04-26 15:25:22 -0700356 if (next->addr == msg->addr && (next->flags & I2C_M_RD)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800357 && *idx == ((dev->wr_sz * 2) - 4)) {
358 writel(((last_entry | msg->buf[dev->pos]) |
359 ((1 | QUP_OUT_NOP) << 16)),
360 dev->qup_base + QUP_OUT_FIFO_BASE);
361 *idx += 2;
362 } else
363 *carry_over = (last_entry | msg->buf[dev->pos]);
364 } else {
365 writel((last_entry | msg->buf[dev->pos]),
366 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700367
Ajay Dudanib01e5062011-12-03 23:23:42 -0800368 qup_verify_fifo(dev, last_entry | msg->buf[dev->pos],
369 (unsigned)dev->qup_base +
370 QUP_OUT_FIFO_BASE + (*idx), 0);
371 }
372 } else {
373 writel(val | ((last_entry | msg->buf[dev->pos]) << 16),
374 dev->qup_base + QUP_OUT_FIFO_BASE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700375
Ajay Dudanib01e5062011-12-03 23:23:42 -0800376 qup_verify_fifo(dev, val | (last_entry << 16) |
377 (msg->buf[dev->pos] << 16),
378 (unsigned)dev->qup_base + QUP_OUT_FIFO_BASE +
379 (*idx) - 2, 0);
380 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700381
Ajay Dudanib01e5062011-12-03 23:23:42 -0800382 *idx += 2;
383 dev->pos++;
384 dev->cnt = msg->len - dev->pos;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700385}
386
387static int qup_update_state(struct qup_i2c_dev *dev, unsigned state)
388{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800389 if (qup_i2c_poll_state(dev, 0) != 0)
390 return -EIO;
391 writel(state, dev->qup_base + QUP_STATE);
392 if (qup_i2c_poll_state(dev, state) != 0)
393 return -EIO;
394 return 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700395}
396
397static int qup_set_read_mode(struct qup_i2c_dev *dev, int rd_len)
398{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800399 unsigned wr_mode =
400 (dev->wr_sz < dev->out_fifo_sz) ? QUP_WR_BLK_MODE : 0;
401 if (rd_len > 256) {
402 dprintf(INFO, "HW doesn't support READs > 256 bytes\n");
403 return -EPROTONOSUPPORT;
404 }
405 if (rd_len <= dev->in_fifo_sz) {
406 writel(wr_mode | QUP_PACK_EN | QUP_UNPACK_EN,
407 dev->qup_base + QUP_IO_MODE);
408 writel(rd_len, dev->qup_base + QUP_MX_READ_CNT);
409 } else {
410 writel(wr_mode | QUP_RD_BLK_MODE |
411 QUP_PACK_EN | QUP_UNPACK_EN,
412 dev->qup_base + QUP_IO_MODE);
413 writel(rd_len, dev->qup_base + QUP_MX_INPUT_CNT);
414 }
415 return 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700416}
417
418static int qup_set_wr_mode(struct qup_i2c_dev *dev, int rem)
419{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800420 int total_len = 0;
421 int ret = 0;
422 if (dev->msg->len >= (dev->out_fifo_sz - 1)) {
423 total_len =
424 dev->msg->len + 1 + (dev->msg->len / (dev->out_blk_sz - 1));
425 writel(QUP_WR_BLK_MODE | QUP_PACK_EN | QUP_UNPACK_EN,
426 dev->qup_base + QUP_IO_MODE);
427 dev->wr_sz = dev->out_blk_sz;
428 } else
429 writel(QUP_PACK_EN | QUP_UNPACK_EN,
430 dev->qup_base + QUP_IO_MODE);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700431
Ajay Dudanib01e5062011-12-03 23:23:42 -0800432 if (rem > 1) {
433 struct i2c_msg *next = dev->msg + 1;
434 if (next->addr == dev->msg->addr && next->flags == I2C_M_RD) {
435 ret = qup_set_read_mode(dev, next->len);
436 /* make sure read start & read command are in 1 blk */
437 if ((total_len % dev->out_blk_sz) ==
438 (dev->out_blk_sz - 1))
439 total_len += 3;
440 else
441 total_len += 2;
442 }
443 }
444 /* WRITE COUNT register valid/used only in block mode */
445 if (dev->wr_sz == dev->out_blk_sz)
446 writel(total_len, dev->qup_base + QUP_MX_WR_CNT);
447 return ret;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700448}
449
450int qup_i2c_xfer(struct qup_i2c_dev *dev, struct i2c_msg msgs[], int num)
451{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800452 int ret;
453 int rem = num;
454 int err;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700455
Ajay Dudanib01e5062011-12-03 23:23:42 -0800456 if (dev->suspended) {
457 return -EIO;
458 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700459
Ajay Dudanib01e5062011-12-03 23:23:42 -0800460 /* Set the GSBIn_QUP_APPS_CLK to 24MHz, then below figure out what speed to
461 run I2C_MASTER_CORE at. */
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800462#if !PERIPH_BLK_BLSP
Ajay Dudanib01e5062011-12-03 23:23:42 -0800463 if (dev->clk_state == 0) {
464 if (dev->clk_ctl == 0) {
465 clock_config_i2c(dev->gsbi_number, dev->src_clk_freq);
466 }
467 }
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800468#endif
469
Ajay Dudanib01e5062011-12-03 23:23:42 -0800470 /* Initialize QUP registers during first transfer */
471 if (dev->clk_ctl == 0) {
472 int fs_div;
473 int hs_div;
474 unsigned fifo_reg;
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800475#if !PERIPH_BLK_BLSP
Ajay Dudanib01e5062011-12-03 23:23:42 -0800476 /* Configure the GSBI Protocol Code for i2c */
477 writel((GSBI_PROTOCOL_CODE_I2C <<
478 GSBI_CTRL_REG_PROTOCOL_CODE_S),
479 GSBI_CTRL_REG(dev->gsbi_base));
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800480#endif
Shashank Mittalc69512e2010-09-22 16:40:48 -0700481
Ajay Dudanib01e5062011-12-03 23:23:42 -0800482 fs_div = ((dev->src_clk_freq / dev->clk_freq) / 2) - 3;
483 hs_div = 3;
484 dev->clk_ctl = ((hs_div & 0x7) << 8) | (fs_div & 0xff);
485 fifo_reg = readl(dev->qup_base + QUP_IO_MODE);
486 if (fifo_reg & 0x3)
487 dev->out_blk_sz = (fifo_reg & 0x3) * 16;
488 else
489 dev->out_blk_sz = 16;
490 if (fifo_reg & 0x60)
491 dev->in_blk_sz = ((fifo_reg & 0x60) >> 5) * 16;
492 else
493 dev->in_blk_sz = 16;
494 /*
495 * The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag'
496 * associated with each byte written/received
497 */
498 dev->out_blk_sz /= 2;
499 dev->in_blk_sz /= 2;
500 dev->out_fifo_sz =
501 dev->out_blk_sz * (2 << ((fifo_reg & 0x1C) >> 2));
502 dev->in_fifo_sz =
503 dev->in_blk_sz * (2 << ((fifo_reg & 0x380) >> 7));
504 dprintf(INFO, "QUP IN:bl:%d, ff:%d, OUT:bl:%d, ff:%d\n",
505 dev->in_blk_sz, dev->in_fifo_sz, dev->out_blk_sz,
506 dev->out_fifo_sz);
507 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700508
Ajay Dudanib01e5062011-12-03 23:23:42 -0800509 unmask_interrupt(dev->qup_irq);
510 writel(1, dev->qup_base + QUP_SW_RESET);
511 ret = qup_i2c_poll_state(dev, QUP_RESET_STATE);
512 if (ret) {
513 dprintf(INFO, "QUP Busy:Trying to recover\n");
514 goto out_err;
515 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700516
Ajay Dudanib01e5062011-12-03 23:23:42 -0800517 /* Initialize QUP registers */
518 writel(0, dev->qup_base + QUP_CONFIG);
519 writel(QUP_OPERATIONAL_RESET, dev->qup_base + QUP_OPERATIONAL);
520 writel(QUP_STATUS_ERROR_FLAGS, dev->qup_base + QUP_ERROR_FLAGS_EN);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700521
Ajay Dudanib01e5062011-12-03 23:23:42 -0800522 writel(I2C_MINI_CORE | I2C_N_VAL, dev->qup_base + QUP_CONFIG);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700523
Ajay Dudanib01e5062011-12-03 23:23:42 -0800524 /* Initialize I2C mini core registers */
525 writel(0, dev->qup_base + QUP_I2C_CLK_CTL);
526 writel(QUP_I2C_STATUS_RESET, dev->qup_base + QUP_I2C_STATUS);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700527
Ajay Dudanib01e5062011-12-03 23:23:42 -0800528 dev->cnt = msgs->len;
529 dev->pos = 0;
530 dev->msg = msgs;
531 while (rem) {
532 int filled = FALSE;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700533
Ajay Dudanib01e5062011-12-03 23:23:42 -0800534 dev->wr_sz = dev->out_fifo_sz;
535 dev->err = 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700536
Ajay Dudanib01e5062011-12-03 23:23:42 -0800537 if (qup_i2c_poll_state(dev, QUP_I2C_MAST_GEN) != 0) {
538 ret = -EIO;
539 goto out_err;
540 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700541
Ajay Dudanib01e5062011-12-03 23:23:42 -0800542 qup_print_status(dev);
543 /* HW limits Read upto 256 bytes in 1 read without stop */
544 if (dev->msg->flags & I2C_M_RD) {
545 ret = qup_set_read_mode(dev, dev->cnt);
546 if (ret != 0)
547 goto out_err;
548 } else {
549 ret = qup_set_wr_mode(dev, rem);
550 if (ret != 0)
551 goto out_err;
552 /* Don't fill block till we get interrupt */
553 if (dev->wr_sz == dev->out_blk_sz)
554 filled = TRUE;
555 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700556
Ajay Dudanib01e5062011-12-03 23:23:42 -0800557 err = qup_update_state(dev, QUP_RUN_STATE);
558 if (err < 0) {
559 ret = err;
560 goto out_err;
561 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700562
Ajay Dudanib01e5062011-12-03 23:23:42 -0800563 qup_print_status(dev);
564 writel(dev->clk_ctl, dev->qup_base + QUP_I2C_CLK_CTL);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700565
Ajay Dudanib01e5062011-12-03 23:23:42 -0800566 do {
567 int idx = 0;
568 unsigned carry_over = 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700569
Ajay Dudanib01e5062011-12-03 23:23:42 -0800570 /* Transition to PAUSE state only possible from RUN */
571 err = qup_update_state(dev, QUP_PAUSE_STATE);
572 if (err < 0) {
573 ret = err;
574 goto out_err;
575 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700576
Ajay Dudanib01e5062011-12-03 23:23:42 -0800577 qup_print_status(dev);
578 /* This operation is Write, check the next operation and decide
579 mode */
580 while (filled == FALSE) {
581 if ((msgs->flags & I2C_M_RD)
582 && (dev->cnt == msgs->len))
583 qup_issue_read(dev, msgs, &idx,
584 carry_over);
585 else if (!(msgs->flags & I2C_M_RD))
586 qup_issue_write(dev, msgs, rem, &idx,
587 &carry_over);
588 if (idx >= (dev->wr_sz << 1))
589 filled = TRUE;
590 /* Start new message */
591 if (filled == FALSE) {
592 if (msgs->flags & I2C_M_RD)
593 filled = TRUE;
594 else if (rem > 1) {
595 /* Only combine operations with same address */
596 struct i2c_msg *next = msgs + 1;
597 if (next->addr != msgs->addr
598 || next->flags == 0)
599 filled = TRUE;
600 else {
601 rem--;
602 msgs++;
603 dev->msg = msgs;
604 dev->pos = 0;
605 dev->cnt = msgs->len;
606 }
607 } else
608 filled = TRUE;
609 }
610 }
611 err = qup_update_state(dev, QUP_RUN_STATE);
612 if (err < 0) {
613 ret = err;
614 goto out_err;
615 }
616 dprintf(INFO, "idx:%d, rem:%d, num:%d, mode:%d\n",
617 idx, rem, num, dev->mode);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700618
Ajay Dudanib01e5062011-12-03 23:23:42 -0800619 qup_print_status(dev);
620 if (dev->err) {
621 if (dev->err & QUP_I2C_NACK_FLAG) {
622 dprintf(CRITICAL,
623 "I2C slave addr:0x%x not connected\n",
624 dev->msg->addr);
625 } else {
626 dprintf(INFO,
627 "QUP data xfer error %d\n",
628 dev->err);
629 }
630 ret = dev->err;
631 goto out_err;
632 }
633 if (dev->msg->flags & I2C_M_RD) {
634 int i;
635 unsigned dval = 0;
636 for (i = 0; dev->pos < dev->msg->len;
637 i++, dev->pos++) {
638 unsigned rd_status =
639 readl(dev->qup_base +
640 QUP_OPERATIONAL);
641 if (i % 2 == 0) {
642 if ((rd_status &
643 QUP_IN_NOT_EMPTY) == 0)
644 break;
645 dval =
646 readl(dev->qup_base +
647 QUP_IN_FIFO_BASE);
648 dev->msg->buf[dev->pos] =
649 dval & 0xFF;
650 } else
651 dev->msg->buf[dev->pos] =
652 ((dval & 0xFF0000) >> 16);
653 }
654 dev->cnt -= i;
655 } else
656 filled = FALSE; /* refill output FIFO */
657 }
658 while (dev->cnt > 0);
659 if (dev->cnt == 0) {
660 rem--;
661 msgs++;
662 if (rem) {
663 dev->pos = 0;
664 dev->cnt = msgs->len;
665 dev->msg = msgs;
666 }
667 }
668 /* Wait for I2C bus to be idle */
669 ret = qup_i2c_poll_writeready(dev);
670 if (ret) {
671 dprintf(INFO, "Error waiting for write ready\n");
672 goto out_err;
673 }
674 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700675
Ajay Dudanib01e5062011-12-03 23:23:42 -0800676 ret = num;
677 out_err:
678 dev->msg = NULL;
679 dev->pos = 0;
680 dev->err = 0;
681 dev->cnt = 0;
682 mask_interrupt(dev->qup_irq);
683 return ret;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700684}
685
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800686void qup_i2c_sec_init(struct qup_i2c_dev *dev, uint32_t clk_freq,
687 uint32_t src_clk_freq)
688{
689 /* Set clk_freq and src_clk_freq for i2c. */
690 dev->clk_freq = clk_freq;
691 dev->src_clk_freq = src_clk_freq;
692
693 dev->num_irqs = 1;
694
695 dev->one_bit_t = USEC_PER_SEC / dev->clk_freq;
696 dev->clk_ctl = 0;
697
698 /* Register the GSBIn QUP IRQ */
699 register_int_handler(dev->qup_irq, (int_handler) qup_i2c_interrupt, 0);
700
701 /* Then disable it */
702 mask_interrupt(dev->qup_irq);
703}
704
Ajay Dudanib01e5062011-12-03 23:23:42 -0800705struct qup_i2c_dev *qup_i2c_init(uint8_t gsbi_id, unsigned clk_freq,
706 unsigned src_clk_freq)
Shashank Mittalc69512e2010-09-22 16:40:48 -0700707{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800708 struct qup_i2c_dev *dev;
709 if (dev_addr != NULL) {
710 return dev_addr;
711 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700712
Ajay Dudanib01e5062011-12-03 23:23:42 -0800713 dev = malloc(sizeof(struct qup_i2c_dev));
714 if (!dev) {
715 return NULL;
716 }
717 dev = memset(dev, 0, sizeof(struct qup_i2c_dev));
Shashank Mittalc69512e2010-09-22 16:40:48 -0700718
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800719 /*
720 * Platform uses gsbi, setup base addresses and
721 * irq based on gsbi_id
722 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800723 dev->qup_irq = GSBI_QUP_IRQ(gsbi_id);
724 dev->qup_base = QUP_BASE(gsbi_id);
725 dev->gsbi_base = GSBI_BASE(gsbi_id);
726 dev->gsbi_number = gsbi_id;
Amol Jadic52c8a32011-07-12 11:27:04 -0700727
Ajay Dudanib01e5062011-12-03 23:23:42 -0800728 /* This must be done for qup_i2c_interrupt to work. */
729 dev_addr = dev;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700730
Ajay Dudanib01e5062011-12-03 23:23:42 -0800731 /* Initialize the GPIO for GSBIn as i2c */
732 gpio_config_i2c(dev->gsbi_number);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700733
Ajay Dudanib01e5062011-12-03 23:23:42 -0800734 /* Configure the GSBI Protocol Code for i2c */
735 writel((GSBI_PROTOCOL_CODE_I2C <<
736 GSBI_CTRL_REG_PROTOCOL_CODE_S), GSBI_CTRL_REG(dev->gsbi_base));
Shashank Mittalc69512e2010-09-22 16:40:48 -0700737
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800738 qup_i2c_sec_init(dev, clk_freq, src_clk_freq);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700739
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800740 return dev;
741}
Shashank Mittalc69512e2010-09-22 16:40:48 -0700742
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800743struct qup_i2c_dev *qup_blsp_i2c_init(uint8_t blsp_id, uint8_t qup_id,
744 uint32_t clk_freq, uint32_t src_clk_freq)
745{
746 struct qup_i2c_dev *dev;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700747
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800748 if (dev_addr != NULL) {
749 return dev_addr;
750 }
Shashank Mittalc69512e2010-09-22 16:40:48 -0700751
Channagoud Kadabi634ac6d2012-12-12 18:13:56 -0800752 dev = malloc(sizeof(struct qup_i2c_dev));
753 if (!dev) {
754 return NULL;
755 }
756 dev = memset(dev, 0, sizeof(struct qup_i2c_dev));
757
758 /* Platform uses BLSP */
759 dev->qup_irq = BLSP_QUP_IRQ(blsp_id, qup_id);
760 dev->qup_base = BLSP_QUP_BASE(blsp_id, qup_id);
761
762 /* This must be done for qup_i2c_interrupt to work. */
763 dev_addr = dev;
764
765 /* Initialize the GPIO for BLSP i2c */
766 gpio_config_blsp_i2c(blsp_id, qup_id);
767
768 clock_config_blsp_i2c(blsp_id, qup_id);
769
770 qup_i2c_sec_init(dev, clk_freq, src_clk_freq);
Shashank Mittalc69512e2010-09-22 16:40:48 -0700771
Ajay Dudanib01e5062011-12-03 23:23:42 -0800772 return dev;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700773}
774
775int qup_i2c_deinit(struct qup_i2c_dev *dev)
776{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800777 /* Disable the qup_irq */
778 mask_interrupt(dev->qup_irq);
779 /* Free the memory used for dev */
780 free(dev);
781 return 0;
Shashank Mittalc69512e2010-09-22 16:40:48 -0700782}