1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
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)
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
)
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
;
55 /* Send slave address and then data */
59 IICCON
|= I2C_TXRX_INTENB
;
61 /* Load slave address into shift register */
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();
72 restore_irq(oldlevel
);
75 /* Go back to slave receive mode and disable lines */
78 /* Turn off I2C clock */
79 s3c_regclr32(&CLKCON
, 1 << 16);
81 mutex_unlock(&i2c_mtx
);
86 /* Init kernel objects */
87 wakeup_init(&i2c_wake
);
90 /* Clear pending source */
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 */
109 /* SDA line delayed 0 PCLKs */
112 /* Turn off I2C clock */
113 s3c_regclr32(&CLKCON
, 1 << 16);
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 */
126 /* Clear pending interrupt to continue */
127 IICCON
&= ~I2C_TXRX_INTPND
;
137 wakeup_signal(&i2c_wake
);