AMS Sansa: Change some #defines in debug-as3525 from "(SANSA_E200V2) || defined(SANSA...
[kugel-rb.git] / firmware / target / arm / s3c2440 / gigabeat-fx / i2c-meg-fx.c
blob836dedd462871758adfc60cda713468db55cd505
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by Michael Sevakis
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 ****************************************************************************/
21 #include "system.h"
22 #include "i2c-meg-fx.h"
24 static struct wakeup i2c_wake; /* Transfer completion signal */
25 static struct mutex i2c_mtx; /* Mutual exclusion */
26 static unsigned char *buf_ptr; /* Next byte to transfer */
27 static int buf_count; /* Number of bytes remaining to transfer */
29 static void i2c_stop(void)
31 /* Generate STOP */
32 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;
34 /* No more interrupts, clear pending interrupt to continue */
35 IICCON &= ~(I2C_TXRX_INTPND | I2C_TXRX_INTENB);
38 void i2c_write(int addr, const unsigned char *buf, int count)
40 if (count <= 0)
41 return;
43 mutex_lock(&i2c_mtx);
45 /* Turn on I2C clock */
46 s3c_regset32(&CLKCON, 1 << 16);
48 /* Set mode to master transmitter and enable lines */
49 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;
51 /* Set buffer start and count */
52 buf_ptr = (unsigned char *)buf;
53 buf_count = count;
55 /* Send slave address and then data */
56 SRCPND = IIC_MASK;
57 INTPND = IIC_MASK;
59 IICCON |= I2C_TXRX_INTENB;
61 /* Load slave address into shift register */
62 IICDS = addr & 0xfe;
64 /* Generate START */
65 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_START | I2C_RXTX_ENB;
67 if (wakeup_wait(&i2c_wake, HZ) != OBJ_WAIT_SUCCEEDED)
69 /* Something went wrong - stop transmission */
70 int oldlevel = disable_irq_save();
71 i2c_stop();
72 restore_irq(oldlevel);
75 /* Go back to slave receive mode and disable lines */
76 IICSTAT = 0;
78 /* Turn off I2C clock */
79 s3c_regclr32(&CLKCON, 1 << 16);
81 mutex_unlock(&i2c_mtx);
84 void i2c_init(void)
86 /* Init kernel objects */
87 wakeup_init(&i2c_wake);
88 mutex_init(&i2c_mtx);
90 /* Clear pending source */
91 SRCPND = IIC_MASK;
92 INTPND = IIC_MASK;
94 /* Enable i2c interrupt in controller */
95 s3c_regclr32(&INTMOD, IIC_MASK);
96 s3c_regclr32(&INTMSK, IIC_MASK);
98 /* Turn on I2C clock */
99 s3c_regset32(&CLKCON, 1 << 16);
101 /* Set GPE15 (IICSDA) and GPE14 (IICSCL) to IIC */
102 GPECON = (GPECON & ~((3 << 30) | (3 << 28))) |
103 ((2 << 30) | (2 << 28));
105 /* Bus ACK, IICCLK: fPCLK / 16, Rx/Tx Int: Disable, Tx clock: IICCLK/8 */
106 /* OF PCLK: 49.1568MHz / 16 / 8 = 384.0375 kHz */
107 IICCON = (7 << 0);
109 /* SDA line delayed 0 PCLKs */
110 IICLC = (0 << 0);
112 /* Turn off I2C clock */
113 s3c_regclr32(&CLKCON, 1 << 16);
116 void IIC(void)
118 for (;;)
120 /* If ack was received from last byte and bytes are remaining */
121 if (--buf_count >= 0 && (IICSTAT & I2C_ACK_L) == 0)
123 /* Write next byte to shift register */
124 IICDS = *buf_ptr++;
126 /* Clear pending interrupt to continue */
127 IICCON &= ~I2C_TXRX_INTPND;
128 break;
131 /* Finished */
133 /* Generate STOP */
134 i2c_stop();
136 /* Signal thread */
137 wakeup_signal(&i2c_wake);
138 break;
141 /* Ack */
142 SRCPND = IIC_MASK;
143 INTPND = IIC_MASK;