Rockchip rk27xx port initial commit. This is still work in progress.
[kugel-rb.git] / firmware / target / arm / rk27xx / i2c-rk27xx.c
blob34a6f49a320aa07551fd3b20016e310b8478e3db
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2011 by Marcin Bukat
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
23 #include "system.h"
24 #include "kernel.h"
25 #include "i2c-rk27xx.h"
27 /* NOT TESTED YET */
29 /* Driver for the rockchip rk27xx built-in I2C controller in master mode
31 Both the i2c_read and i2c_write function take the following arguments:
32 * slave, the address of the i2c slave device to read from / write to
33 * address, optional sub-address in the i2c slave (unused if -1)
34 * len, number of bytes to be transfered
35 * data, pointer to data to be transfered
36 A return value other than 0 indicates an error.
39 static struct mutex i2c_mtx;
41 static bool i2c_write_byte(uint8_t data, bool start)
43 long timeout = current_tick + HZ / 50;
45 /* START */
46 I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
47 I2C_MTXR = data;
49 if (start)
50 I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
51 else
52 I2C_LCMR = (1<<2); /* resume op */
54 I2C_CONR &= ~(1<<4); /* ACK enable */
56 /* wait for ACK from slave */
57 while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) )
58 if (TIME_AFTER(current_tick, timeout))
59 return false;
61 /* clear status bit */
62 I2C_ISR &= ~(1<<0);
64 return true;
67 static bool i2c_read_byte(unsigned char *data)
69 long timeout = current_tick + HZ / 50;
71 I2C_LCMR = (1<<2); /* resume op */
73 while (I2C_ISR & (1<<1))
74 if (TIME_AFTER(current_tick, timeout))
75 return false;
77 *data = I2C_MRXR;
79 /* clear status bit */
80 I2C_ISR &= ~(1<<1);
82 return true;
85 static bool i2c_stop(void)
87 long timeout = current_tick + HZ / 50;
89 I2C_CONR &= ~(1<<4);
90 I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
92 while (I2C_LCMR & (1<<1))
93 if (TIME_AFTER(current_tick, timeout))
94 return false;
96 return true;
99 /* route i2c bus to internal codec or external bus
100 * internal codec has 0x27 i2c slave address so
101 * access to this address is routed to internal bus.
102 * All other addresses are routed to external pads
104 static void i2c_iomux(unsigned char slave)
106 unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14);
108 if (slave == (0x27<<1))
110 /* internal codec */
111 SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14);
113 else
115 /* external I2C bus */
116 SCU_IOMUXA_CON = muxa | (1<<18);
120 void i2c_init(void)
122 mutex_init(&i2c_mtx);
124 SCU_CLKCFG &= ~(1<< 20);
126 I2C_OPR |= (1<<7); /* reset state machine */
127 sleep(HZ/100);
128 I2C_OPR &= ~((1<<7) | (1<<6)); /* clear ENABLE bit, deasert reset */
130 /* set I2C divider to stay within allowed SCL freq limit
131 * APBfreq = 50Mhz
132 * SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1))
134 I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0;
136 I2C_IER = 0x00;
138 I2C_OPR |= (1<<6); /* enable i2c core */
141 int i2c_write(unsigned char slave, int address, int len,
142 const unsigned char *data)
144 mutex_lock(&i2c_mtx);
146 i2c_iomux(slave);
148 /* START */
149 if (! i2c_write_byte(slave & ~1, true))
151 mutex_unlock(&i2c_mtx);
152 return 1;
155 if (address >= 0)
157 if (! i2c_write_byte(address, false))
159 mutex_unlock(&i2c_mtx);
160 return 2;
164 /* write data */
165 while (len--)
167 if (! i2c_write_byte(*data++, false))
169 mutex_unlock(&i2c_mtx);
170 return 4;
174 /* STOP */
175 if (! i2c_stop())
177 mutex_unlock(&i2c_mtx);
178 return 5;
181 mutex_unlock(&i2c_mtx);
182 return 0;
185 int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
187 mutex_lock(&i2c_mtx);
189 i2c_iomux(slave);
191 if (address >= 0)
193 /* START */
194 if (! i2c_write_byte(slave & ~1, true))
196 mutex_unlock(&i2c_mtx);
197 return 1;
200 /* write address */
201 if (! i2c_write_byte(address, false))
203 mutex_unlock(&i2c_mtx);
204 return 2;
208 /* (repeated) START */
209 if (! i2c_write_byte(slave | 1, true))
211 mutex_unlock(&i2c_mtx);
212 return 3;
215 I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
217 while (len)
219 if (! i2c_read_byte(data++))
221 mutex_unlock(&i2c_mtx);
222 return 4;
225 if (len == 1)
226 I2C_CONR |= (1<<4); /* NACK */
227 else
228 I2C_CONR &= ~(1<<4); /* ACK */
230 len--;
233 /* STOP */
234 if (! i2c_stop())
236 mutex_unlock(&i2c_mtx);
237 return 5;
240 mutex_unlock(&i2c_mtx);
241 return 0;