imx233: rework i2c driver to fix dma issues
[maemo-rb.git] / firmware / target / arm / imx233 / i2c-imx233.c
blob028ddb9489cb536e8a15ce3cc1c8655b74e7deb1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2011 by amaury Pouly
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
24 #include "config.h"
25 #include "system.h"
26 #include "kernel.h"
27 #include "dma-imx233.h"
28 #include "i2c-imx233.h"
29 #include "pinctrl-imx233.h"
30 #include "string.h"
32 /**
33 * Driver Architecture:
34 * The driver has two interfaces: the good'n'old i2c_* api and a more
35 * advanced one specific to the imx233 dma architecture. The i2c_* api is
36 * implemented with the imx233_i2c_* one.
37 * Since each i2c transfer must be split into several dma transfers and we
38 * cannot do dynamic allocation, we allow for at most I2C_NR_STAGES stages.
39 * A typical read memory transfer will require 3 stages thus 4 is safe:
40 * - one with start, device address and memory address
41 * - one with repeated start and device address
42 * - one with data read and stop
43 * To make the interface easier to use and to handle the DMA/cache related
44 * issues, all the data transfers are done in a statically allocated buffer
45 * which is managed by the driver. The driver will ensure that all transfers
46 * are cache aligned and will copy back the data to user buffers at the end.
47 * The I2C_BUFFER_SIZE define controls the size of the buffer. All transfers
48 * should probably fit within 512 bytes.
51 /* Used for DMA */
52 struct i2c_dma_command_t
54 struct apb_dma_command_t dma;
55 /* PIO words */
56 uint32_t ctrl0;
57 /* copy buffer copy */
58 void *src;
59 void *dst;
60 /* padded to next multiple of cache line size (32 bytes) */
61 uint32_t pad[2];
62 } __attribute__((packed)) CACHEALIGN_ATTR;
64 __ENSURE_STRUCT_CACHE_FRIENDLY(struct i2c_dma_command_t)
66 #define I2C_NR_STAGES 4
67 #define I2C_BUFFER_SIZE 512
68 /* Current transfer */
69 static int i2c_nr_stages;
70 static struct i2c_dma_command_t i2c_stage[I2C_NR_STAGES];
71 static struct mutex i2c_mutex;
72 static struct semaphore i2c_sema;
73 static uint8_t i2c_buffer[I2C_BUFFER_SIZE] CACHEALIGN_ATTR;
74 static uint32_t i2c_buffer_end; /* current end */
76 void INT_I2C_DMA(void)
78 /* reset dma channel on error */
79 if(imx233_dma_is_channel_error_irq(APB_I2C))
80 imx233_dma_reset_channel(APB_I2C);
81 /* clear irq flags */
82 imx233_dma_clear_channel_interrupt(APB_I2C);
83 semaphore_release(&i2c_sema);
86 void imx233_i2c_init(void)
88 //imx233_reset_block(&HW_I2C_CTRL0);
89 __REG_SET(HW_I2C_CTRL0) = __BLOCK_SFTRST;
90 /* setup pins (must be done when shutdown) */
91 imx233_pinctrl_acquire_pin(0, 30, "i2c");
92 imx233_pinctrl_acquire_pin(0, 31, "i2c");
93 imx233_set_pin_function(0, 30, PINCTRL_FUNCTION_MAIN);
94 imx233_set_pin_function(0, 31, PINCTRL_FUNCTION_MAIN);
95 /* clear softreset */
96 __REG_CLR(HW_I2C_CTRL0) = __BLOCK_SFTRST | __BLOCK_CLKGATE;
97 /* Errata:
98 * When RETAIN_CLOCK is set, the ninth clock pulse (ACK) is not generated. However, the SDA
99 * line is read at the proper timing interval. If RETAIN_CLOCK is cleared, the ninth clock pulse is
100 * generated.
101 * HW_I2C_CTRL1[ACK_MODE] has default value of 0. It should be set to 1 to enable the fix for
102 * this issue.
104 __REG_SET(HW_I2C_CTRL1) = HW_I2C_CTRL1__ACK_MODE;
105 __REG_SET(HW_I2C_CTRL0) = __BLOCK_CLKGATE;
106 /* Fast-mode @ 400K */
107 HW_I2C_TIMING0 = 0x000F0007; /* tHIGH=0.6us, read at 0.3us */
108 HW_I2C_TIMING1 = 0x001F000F; /* tLOW=1.3us, write at 0.6us */
109 HW_I2C_TIMING2 = 0x0015000D;
111 mutex_init(&i2c_mutex);
112 semaphore_init(&i2c_sema, 1, 0);
115 void imx233_i2c_begin(void)
117 mutex_lock(&i2c_mutex);
118 /* wakeup */
119 __REG_CLR(HW_I2C_CTRL0) = __BLOCK_CLKGATE;
120 i2c_nr_stages = 0;
121 i2c_buffer_end = 0;
124 enum imx233_i2c_error_t imx233_i2c_add(bool start, bool transmit, void *buffer, unsigned size, bool stop)
126 if(i2c_nr_stages == I2C_NR_STAGES)
127 return I2C_ERROR;
128 /* align buffer end on cache boundary */
129 uint32_t start_off = CACHEALIGN_UP(i2c_buffer_end);
130 uint32_t end_off = start_off + size;
131 if(end_off > I2C_BUFFER_SIZE)
133 panicf("die");
134 return I2C_BUFFER_FULL;
136 i2c_buffer_end = end_off;
137 if(transmit)
139 /* copy data to buffer */
140 memcpy(i2c_buffer + start_off, buffer, size);
142 else
144 /* record pointers for finalization */
145 i2c_stage[i2c_nr_stages].src = i2c_buffer + start_off;
146 i2c_stage[i2c_nr_stages].dst = buffer;
149 if(i2c_nr_stages > 0)
151 i2c_stage[i2c_nr_stages - 1].dma.next = &i2c_stage[i2c_nr_stages].dma;
152 i2c_stage[i2c_nr_stages - 1].dma.cmd |= HW_APB_CHx_CMD__CHAIN;
153 if(!start)
154 i2c_stage[i2c_nr_stages - 1].ctrl0 |= HW_I2C_CTRL0__RETAIN_CLOCK;
156 i2c_stage[i2c_nr_stages].dma.buffer = i2c_buffer + start_off;
157 i2c_stage[i2c_nr_stages].dma.next = NULL;
158 i2c_stage[i2c_nr_stages].dma.cmd =
159 (transmit ? HW_APB_CHx_CMD__COMMAND__READ : HW_APB_CHx_CMD__COMMAND__WRITE) |
160 HW_APB_CHx_CMD__WAIT4ENDCMD |
161 1 << HW_APB_CHx_CMD__CMDWORDS_BP |
162 size << HW_APB_CHx_CMD__XFER_COUNT_BP;
163 /* assume that any read is final (send nak on last) */
164 i2c_stage[i2c_nr_stages].ctrl0 = size |
165 (transmit ? HW_I2C_CTRL0__TRANSMIT : HW_I2C_CTRL0__SEND_NAK_ON_LAST) |
166 (start ? HW_I2C_CTRL0__PRE_SEND_START : 0) |
167 (stop ? HW_I2C_CTRL0__POST_SEND_STOP : 0) |
168 HW_I2C_CTRL0__MASTER_MODE;
169 i2c_nr_stages++;
170 return I2C_SUCCESS;
173 static enum imx233_i2c_error_t imx233_i2c_finalize(void)
175 discard_dcache_range(i2c_buffer, I2C_BUFFER_SIZE);
176 for(int i = 0; i < i2c_nr_stages; i++)
178 struct i2c_dma_command_t *c = &i2c_stage[i];
179 if(__XTRACT_EX(c->dma.cmd, HW_APB_CHx_CMD__COMMAND) == HW_APB_CHx_CMD__COMMAND__WRITE)
180 memcpy(c->dst, c->src, __XTRACT_EX(c->dma.cmd, HW_APB_CHx_CMD__XFER_COUNT));
182 return I2C_SUCCESS;
185 enum imx233_i2c_error_t imx233_i2c_end(unsigned timeout)
187 if(i2c_nr_stages == 0)
188 return I2C_ERROR;
189 i2c_stage[i2c_nr_stages - 1].dma.cmd |= HW_APB_CHx_CMD__SEMAPHORE | HW_APB_CHx_CMD__IRQONCMPLT;
191 __REG_CLR(HW_I2C_CTRL1) = HW_I2C_CTRL1__ALL_IRQ;
192 imx233_dma_reset_channel(APB_I2C);
193 imx233_icoll_enable_interrupt(INT_SRC_I2C_DMA, true);
194 imx233_dma_enable_channel_interrupt(APB_I2C, true);
195 imx233_dma_start_command(APB_I2C, &i2c_stage[0].dma);
197 enum imx233_i2c_error_t ret;
198 if(semaphore_wait(&i2c_sema, timeout) == OBJ_WAIT_TIMEDOUT)
200 imx233_dma_reset_channel(APB_I2C);
201 ret = I2C_TIMEOUT;
203 else if(HW_I2C_CTRL1 & HW_I2C_CTRL1__MASTER_LOSS_IRQ)
204 ret = I2C_MASTER_LOSS;
205 else if(HW_I2C_CTRL1 & HW_I2C_CTRL1__NO_SLAVE_ACK_IRQ)
206 ret= I2C_NO_SLAVE_ACK;
207 else if(HW_I2C_CTRL1 & HW_I2C_CTRL1__EARLY_TERM_IRQ)
208 ret = I2C_SLAVE_NAK;
209 else
210 ret = imx233_i2c_finalize();
211 /* sleep */
212 __REG_SET(HW_I2C_CTRL0) = __BLOCK_CLKGATE;
213 mutex_unlock(&i2c_mutex);
214 return ret;
217 void i2c_init(void)
221 int i2c_write(int device, const unsigned char* buf, int count)
223 uint8_t addr = device;
224 imx233_i2c_begin();
225 imx233_i2c_add(true, true, &addr, 1, false); /* start + dev addr */
226 imx233_i2c_add(false, true, (void *)buf, count, true); /* data + stop */
227 return imx233_i2c_end(TIMEOUT_BLOCK);
230 int i2c_read(int device, unsigned char* buf, int count)
232 uint8_t addr = device | 1;
233 imx233_i2c_begin();
234 imx233_i2c_add(true, true, &addr, 1, false); /* start + dev addr */
235 imx233_i2c_add(false, false, buf, count, true); /* data + stop */
236 return imx233_i2c_end(TIMEOUT_BLOCK);
239 int i2c_readmem(int device, int address, unsigned char* buf, int count)
241 uint8_t start[2] = {device, address};
242 uint8_t addr_rd = device | 1;
243 imx233_i2c_begin();
244 imx233_i2c_add(true, true, start, 2, false); /* start + dev addr + addr */
245 imx233_i2c_add(true, true, &addr_rd, 1, false); /* start + dev addr */
246 imx233_i2c_add(false, false, buf, count, true); /* data + stop */
247 return imx233_i2c_end(TIMEOUT_BLOCK);
250 int i2c_writemem(int device, int address, const unsigned char* buf, int count)
252 uint8_t start[2] = {device, address};
253 imx233_i2c_begin();
254 imx233_i2c_add(true, true, start, 2, false); /* start + dev addr + addr */
255 imx233_i2c_add(false, true, (void *)buf, count, true); /* data + stop */
256 return imx233_i2c_end(TIMEOUT_BLOCK);