Fix a bunch of boot.lds files so that they build with newer ld. The stack/bss section...
[kugel-rb.git] / firmware / target / arm / tms320dm320 / i2c-dm320.c
blob8bcc84dd8fc42453c5527d28abcd9724d6263c75
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * DM320 I²C driver
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 ****************************************************************************/
23 #include "system.h"
24 #include "thread.h"
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)
37 mutex_lock(&i2c_mtx);
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"); \
58 } \
59 } \
61 static inline void i2c_start(void)
63 IO_I2C_SCS |= I2C_SCS_XMIT;
64 return;
67 int i2c_write(unsigned short address, const unsigned char *buf, int count)
69 int i;
70 int ret=0;
71 i2c_begin();
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'
75 i2c_start();
76 WAIT_FOR_I2C;
77 /* experimental */
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
81 i2c_start();
82 WAIT_FOR_I2C;
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'
86 i2c_start();
87 WAIT_FOR_I2C;
90 for(i=0; i<count; i++){
91 IO_I2C_TXDATA = buf[i] | I2C_TX_ACK;
92 IO_I2C_SCS &= ~0x3; //normal transfer
93 i2c_start();
94 WAIT_FOR_I2C;
95 if(!i2c_getack())
96 ret = -1;
98 IO_I2C_SCS &= ~0x3; //clear conditions
99 IO_I2C_SCS |= I2C_SCS_COND_STOP; //write 'stop condition'
100 i2c_start();
101 WAIT_FOR_I2C;
102 i2c_end();
103 return ret;
106 int i2c_read(unsigned short address, unsigned char* buf, int count)
108 int i;
109 int ack=0;
110 i2c_begin();
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'
114 i2c_start();
115 WAIT_FOR_I2C;
116 /* experimental */
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
120 i2c_start();
121 WAIT_FOR_I2C;
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'
125 i2c_start();
126 WAIT_FOR_I2C;
129 for(i=0; i<count; i++){
130 unsigned short temp;
131 IO_I2C_TXDATA = 0xFF | ( (count-1)==i ? I2C_TX_ACK : 0);
132 IO_I2C_SCS &= ~0x3; //normal transfer
133 i2c_start();
134 WAIT_FOR_I2C;
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'
141 i2c_start();
142 WAIT_FOR_I2C;
143 i2c_end();
144 return ack;
147 void i2c_init(void)
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
157 #endif
158 IO_I2C_SCS &= ~0x8; //set clock to 100 kHz
159 IO_INTC_EINT2 &= ~INTR_EINT2_I2C; // disable I²C interrupt