1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Maurus Cuelenaere
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 #include "i2c-dm320.h"
27 #define I2C_SCS_COND_START 0x0001
28 #define I2C_SCS_COND_STOP 0x0002
29 #define I2C_SCS_XMIT 0x0004
31 #define I2C_TX_ACK (1 << 8)
33 static struct mutex i2c_mtx
;
35 static inline void i2c_begin(void)
40 static inline void i2c_end(void)
42 mutex_unlock(&i2c_mtx
);
45 static inline bool i2c_getack(void)
47 return (IO_I2C_RXDATA
>> 8) & 1;
50 static inline void i2c_ack(void)
52 IO_I2C_TXDATA
|= I2C_TX_ACK
;
55 #define WAIT_FOR_I2C if(IO_I2C_SCS & 0x4){ \
56 while(IO_I2C_SCS & 0x4) { \
57 asm volatile("nop"); \
61 static inline void i2c_start(void)
63 IO_I2C_SCS
|= I2C_SCS_XMIT
;
67 int i2c_write(unsigned short address
, const unsigned char *buf
, int count
)
72 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | (address
>0x7F ? 0 : 1 ) | I2C_TX_ACK
;
73 IO_I2C_SCS
&= ~0x3; //clear conditions
74 IO_I2C_SCS
|= I2C_SCS_COND_START
; // write 'start condition'
78 if(address
>0x7F){ // check if it is 10-bit instead of 7-bit
79 IO_I2C_TXDATA
= ( (address
>> 7) & 0xFF) | I2C_TX_ACK
;
80 IO_I2C_SCS
&= ~0x3; //normal transfer
83 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF) | 1 | I2C_TX_ACK
;
84 IO_I2C_SCS
&= ~0x3; //clear conditions
85 IO_I2C_SCS
|= I2C_SCS_COND_START
; //write 'start condition'
90 for(i
=0; i
<count
; i
++){
91 IO_I2C_TXDATA
= buf
[i
] | I2C_TX_ACK
;
92 IO_I2C_SCS
&= ~0x3; //normal transfer
98 IO_I2C_SCS
&= ~0x3; //clear conditions
99 IO_I2C_SCS
|= I2C_SCS_COND_STOP
; //write 'stop condition'
106 int i2c_read(unsigned short address
, unsigned char* buf
, int count
)
111 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | (address
>0x7F ? 0 : 1 ) | I2C_TX_ACK
;
112 IO_I2C_SCS
&= ~0x3; //clear conditions
113 IO_I2C_SCS
|= I2C_SCS_COND_START
; // write 'start condition'
117 if(address
>0x7F){ // check if it is 10-bit instead of 7-bit
118 IO_I2C_TXDATA
= ( (address
>> 7) & 0xFF ) | I2C_TX_ACK
;
119 IO_I2C_SCS
&= ~0x3; //normal transfer
122 IO_I2C_TXDATA
= ( (address
<< 1) & 0xFF ) | 1 | I2C_TX_ACK
;
123 IO_I2C_SCS
&= ~0x3; //clear conditions
124 IO_I2C_SCS
|= I2C_SCS_COND_START
; //write 'start condition'
129 for(i
=0; i
<count
; i
++){
131 IO_I2C_TXDATA
= 0xFF | ( (count
-1)==i
? I2C_TX_ACK
: 0);
132 IO_I2C_SCS
&= ~0x3; //normal transfer
135 temp
= IO_I2C_RXDATA
;
136 buf
[i
] = temp
& 0xFF;
137 ack
= (temp
& 0x100) >> 8;
139 IO_I2C_SCS
&= ~0x3; //clear conditions
140 IO_I2C_SCS
|= I2C_SCS_COND_STOP
; //write 'stop condition'
149 mutex_init(&i2c_mtx
);
151 #ifdef CREATIVE_ZVx //TODO: mimic OF I2C clock settings; currently this is done by the bootloader
152 IO_CLK_MOD2
&= ~CLK_MOD2_I2C
; // turn I²C clock off (just to be sure)
153 IO_CLK_LPCTL1
&= ~1; // set Powerdown mode to off
154 IO_CLK_SEL0
&= ~0x800; // set I²C clock to PLLA
155 IO_CLK_DIV4
&= ~0x1F; // I²C clock division = 1
156 IO_CLK_MOD2
|= CLK_MOD2_I2C
; // enable I²C clock
158 IO_I2C_SCS
&= ~0x8; //set clock to 100 kHz
159 IO_INTC_EINT2
&= ~INTR_EINT2_I2C
; // disable I²C interrupt