1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
27 #include "dma-imx233.h"
28 #include "i2c-imx233.h"
29 #include "pinctrl-imx233.h"
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.
52 struct i2c_dma_command_t
54 struct apb_dma_command_t dma
;
57 /* copy buffer copy */
60 /* padded to next multiple of cache line size (32 bytes) */
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
);
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
);
96 __REG_CLR(HW_I2C_CTRL0
) = __BLOCK_SFTRST
| __BLOCK_CLKGATE
;
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
101 * HW_I2C_CTRL1[ACK_MODE] has default value of 0. It should be set to 1 to enable the fix for
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
);
119 __REG_CLR(HW_I2C_CTRL0
) = __BLOCK_CLKGATE
;
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
)
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
)
134 return I2C_BUFFER_FULL
;
136 i2c_buffer_end
= end_off
;
139 /* copy data to buffer */
140 memcpy(i2c_buffer
+ start_off
, buffer
, size
);
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
;
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
;
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
));
185 enum imx233_i2c_error_t
imx233_i2c_end(unsigned timeout
)
187 if(i2c_nr_stages
== 0)
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
);
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
)
210 ret
= imx233_i2c_finalize();
212 __REG_SET(HW_I2C_CTRL0
) = __BLOCK_CLKGATE
;
213 mutex_unlock(&i2c_mutex
);
221 int i2c_write(int device
, const unsigned char* buf
, int count
)
223 uint8_t addr
= device
;
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;
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;
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
};
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
);