1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Maurus Cuelenaere
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "i2c-dm320.h"
25 #define I2C_SCS_COND_START 0x0001
26 #define I2C_SCS_COND_STOP 0x0002
27 #define I2C_SCS_XMIT 0x0004
29 #define I2C_TX_ACK (1 << 20)
31 static struct mutex i2c_mtx
;
33 static inline void i2c_begin(void)
38 static inline void i2c_end(void)
40 mutex_unlock(&i2c_mtx
);
43 static inline bool i2c_getack(void)
45 return (IO_I2C_RXDATA
& 0x100)>>8;
48 #define WAIT_FOR_I2C if(IO_I2C_SCS & 0x4){ \
49 while(IO_I2C_SCS & 0x4) { \
50 asm volatile("nop"); \
54 static inline void i2c_start(void)
56 IO_I2C_SCS
|= I2C_SCS_XMIT
;
60 int i2c_write(unsigned short address
, const unsigned char *buf
, int count
)
65 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | (address
>0x7F ? 0 : 1 ) | I2C_TX_ACK
;
66 IO_I2C_SCS
&= ~0x3; //clear conditions
67 IO_I2C_SCS
|= I2C_SCS_COND_START
; // write 'start condition'
71 if(address
>0x7F){ // check if it is 10-bit instead of 7-bit
72 IO_I2C_TXDATA
= ( (address
>> 7) & 0xFF) | I2C_TX_ACK
;
73 IO_I2C_SCS
&= ~0x3; //normal transfer
76 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF) | 1 | I2C_TX_ACK
;
77 IO_I2C_SCS
&= ~0x3; //clear conditions
78 IO_I2C_SCS
|= I2C_SCS_COND_START
; //write 'start condition'
83 for(i
=0; i
<count
; i
++){
84 IO_I2C_TXDATA
= buf
[i
] | I2C_TX_ACK
;
85 IO_I2C_SCS
&= ~0x3; //normal transfer
91 IO_I2C_SCS
&= ~0x3; //clear conditions
92 IO_I2C_SCS
|= I2C_SCS_COND_STOP
; //write 'stop condition'
99 int i2c_read(unsigned short address
, unsigned char* buf
, int count
)
104 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | (address
>0x7F ? 0 : 1 ) | I2C_TX_ACK
;
105 IO_I2C_SCS
&= ~0x3; //clear conditions
106 IO_I2C_SCS
|= I2C_SCS_COND_START
; // write 'start condition'
110 if(address
>0x7F){ // check if it is 10-bit instead of 7-bit
111 IO_I2C_TXDATA
= ( (address
>> 7) & 0xFF ) | I2C_TX_ACK
;
112 IO_I2C_SCS
&= ~0x3; //normal transfer
115 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | 1 | I2C_TX_ACK
;
116 IO_I2C_SCS
&= ~0x3; //clear conditions
117 IO_I2C_SCS
|= I2C_SCS_COND_START
; //write 'start condition'
122 for(i
=0; i
<count
; i
++){
124 IO_I2C_TXDATA
= 0xFF | ( (count
-1)==i
? I2C_TX_ACK
: 0);
125 IO_I2C_SCS
&= ~0x3; //normal transfer
128 temp
= IO_I2C_RXDATA
;
129 buf
[i
] = temp
& 0xFF;
130 ack
= (temp
& 0x100) >> 8;
132 IO_I2C_SCS
&= ~0x3; //clear conditions
133 IO_I2C_SCS
|= I2C_SCS_COND_STOP
; //write 'stop condition'
142 #if 0 //TODO: mimic OF I2C clock settings; currently this is done by the bootloader
143 IO_CLK_MOD2
&= ~CLK_MOD2_I2C
; // turn I²C clock off (just to be sure)
144 IO_CLK_LPCTL1
&= ~1; // set Powerdown mode to off
145 IO_CLK_SEL0
&= ~0x800; // set I²C clock to PLLA
146 IO_CLK_DIV4
&= ~0x1F; // I²C clock division = 1
147 IO_CLK_MOD2
|= CLK_MOD2_I2C
; // enable I²C clock
149 IO_I2C_SCS
&= ~0x8; //set clock to 100 kHz
150 IO_INTC_EINT2
&= ~INTR_EINT2_I2C
; // disable I²C interrupt