summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-06-26 02:11:30 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-06-26 02:11:30 +0000
commit7fb0f71668ac574efc7e0f2b8b85d603eb24ea2a (patch)
treeb324403e582d346cadb21b5d554f7c015acf3e74
parent13de6583acdcbf14a31c64577a24a58f07acab6c (diff)
downloadrockbox-7fb0f71668ac574efc7e0f2b8b85d603eb24ea2a.tar.gz
rockbox-7fb0f71668ac574efc7e0f2b8b85d603eb24ea2a.zip
Gigabeat: Replace generic i2c driver with one that uses the CPU's builtin controller. Add some clocking registers to 'View I/O ports'.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13720 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/debug_menu.c3
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c165
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h26
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c6
5 files changed, 109 insertions, 92 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 691e9f5070..0b39430d56 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1178,6 +1178,9 @@ bool dbg_ports(void)
1178 snprintf(buf, sizeof(buf), "SRCPND: %08x INTMOD: %08x", SRCPND, INTMOD); lcd_puts(0, line++, buf); 1178 snprintf(buf, sizeof(buf), "SRCPND: %08x INTMOD: %08x", SRCPND, INTMOD); lcd_puts(0, line++, buf);
1179 snprintf(buf, sizeof(buf), "INTMSK: %08x INTPND: %08x", INTMSK, INTPND); lcd_puts(0, line++, buf); 1179 snprintf(buf, sizeof(buf), "INTMSK: %08x INTPND: %08x", INTMSK, INTPND); lcd_puts(0, line++, buf);
1180 snprintf(buf, sizeof(buf), "CLKCON: %08x CLKSLOW: %08x", CLKCON, CLKSLOW); lcd_puts(0, line++, buf); 1180 snprintf(buf, sizeof(buf), "CLKCON: %08x CLKSLOW: %08x", CLKCON, CLKSLOW); lcd_puts(0, line++, buf);
1181 snprintf(buf, sizeof(buf), "MPLLCON: %08x UPLLCON: %08x", MPLLCON, UPLLCON); lcd_puts(0, line++, buf);
1182 snprintf(buf, sizeof(buf), "CLKDIVN: %08x", CLKDIVN); lcd_puts(0, line++, buf);
1183
1181 lcd_update(); 1184 lcd_update();
1182 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL)) 1185 if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
1183 return false; 1186 return false;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index c642196d5c..28ef38e8db 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -512,7 +512,6 @@ target/arm/usb-pp.c
512 512
513#ifdef GIGABEAT_F 513#ifdef GIGABEAT_F
514#ifndef SIMULATOR 514#ifndef SIMULATOR
515drivers/generic_i2c.c
516target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c 515target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
517target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c 516target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
518target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c 517target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
index 670d6cd04c..45140c0f0c 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing 10 * Copyright (C) 2007 by Michael Sevakis
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -16,119 +16,110 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h" 19#include "system.h"
24#include "logf.h" 20#include "i2c-meg-fx.h"
25#include "debug.h" 21
26#include "string.h" 22/* Only implements sending bytes for now. Adding receiving bytes should be
27#include "generic_i2c.h" 23 straightforward if needed. No yielding is present since the calls only
28 24 involve setting audio codec registers - a very rare event. */
29static void i2c_sda_output(void) 25
26/* Wait for a condition on the bus, optionally returning it */
27#define COND_RET _c;
28#define COND_VOID
29#define WAIT_COND(cond, ret) \
30 ({ \
31 int _t = current_tick + 2; \
32 bool _c; \
33 while (1) { \
34 _c = !!(cond); \
35 if (_c || TIME_AFTER(current_tick, _t)) \
36 break; \
37 } \
38 ret \
39 })
40
41static int i2c_getack(void)
30{ 42{
31 GPECON |= (1 << 30); 43 /* Wait for ACK: 0 = ack received, 1 = ack not received */
44 WAIT_COND(IICCON & I2C_TXRX_INTPND, COND_VOID);
45 return IICSTAT & I2C_ACK_L;
32} 46}
33 47
34static void i2c_sda_input(void) 48static int i2c_start(void)
35{ 49{
36 GPECON &= ~(3 << 30); 50 /* Generate START */
51 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_START | I2C_RXTX_ENB;
52 return i2c_getack();
37} 53}
38 54
39static void i2c_sda_lo(void) 55static void i2c_stop(void)
40{ 56{
41 GPEDAT &= ~(1 << 15); 57 /* Generate STOP */
58 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;
59 /* Clear pending interrupt to continue */
60 IICCON &= ~I2C_TXRX_INTPND;
42} 61}
43 62
44static void i2c_sda_hi(void) 63static int i2c_outb(unsigned char byte)
45{ 64{
46 GPEDAT |= (1 << 15); 65 /* Write byte to shift register */
66 IICDS = byte;
67 /* Clear pending interrupt to continue */
68 IICCON &= ~I2C_TXRX_INTPND;
69 return i2c_getack();
47} 70}
48 71
49static int i2c_sda(void) 72void i2c_write(int addr, const unsigned char *buf, int count)
50{ 73{
51 return GPEDAT & (1 << 15); 74 /* Turn on I2C clock */
52} 75 CLKCON |= (1 << 16);
53 76
54static void i2c_scl_output(void) 77 /* Set mode to master transmitter and enable lines */
55{ 78 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;
56 GPECON |= (1 << 28);
57}
58 79
59static void i2c_scl_input(void) 80 /* Wait for bus to be available */
60{ 81 if (WAIT_COND(!(IICSTAT & I2C_BUSY), COND_RET))
61 GPECON &= ~(3 << 28); 82 {
62} 83 /* Send slave address and then data */
84 IICCON &= ~I2C_TXRX_INTPND;
85 IICCON |= I2C_TXRX_INTENB;
63 86
64static void i2c_scl_lo(void) 87 IICDS = addr & 0xfe;
65{
66 GPEDAT &= ~(1 << 14);
67}
68 88
69static int i2c_scl(void) 89 if (i2c_start() == 0)
70{ 90 while (count-- > 0 && i2c_outb(*buf++) == 0);
71 return GPEDAT & (1 << 14);
72}
73
74static void i2c_scl_hi(void)
75{
76 i2c_scl_input();
77 while(!i2c_scl());
78 GPEDAT |= (1 << 14);
79 i2c_scl_output();
80}
81 91
92 i2c_stop();
82 93
94 IICCON &= ~I2C_TXRX_INTENB;
95 }
83 96
84static void i2c_delay(void) 97 /* Go back to slave receive mode and disable lines */
85{ 98 IICSTAT = 0;
86 unsigned _x;
87 99
88 /* The i2c can clock at 500KHz: 2uS period -> 1uS half period */ 100 /* Turn off I2C clock */
89 /* about 30 cycles overhead + X * 7 */ 101 CLKCON &= ~(1 << 16);
90 /* 300MHz: 1000nS @3.36nS/cyc = 297cyc: X = 38*/
91 /* 100MHz: 1000nS @10nS/cyc = 100cyc : X = 10 */
92 for (_x = 38; _x; _x--)
93 {
94 /* burn CPU cycles */
95 /* gcc makes it an inc loop - check with objdump for asm timing */
96 }
97} 102}
98 103
104void i2c_init(void)
105{
106 /* We poll I2C interrupts */
107 INTMSK |= (1 << 27);
99 108
109 /* Turn on I2C clock */
110 CLKCON |= (1 << 16);
100 111
101struct i2c_interface s3c2440_i2c = { 112 /* Set GPE15 (IICSDA) and GPE14 (IICSCL) to IIC */
102 0x34, /* Address */ 113 GPECON = (GPECON & ~((3 << 30) | (3 << 28))) |
103 114 ((2 << 30) | (2 << 28));
104 /* Bit-banged interface definitions */
105 i2c_scl_hi, /* Drive SCL high, might sleep on clk stretch */
106 i2c_scl_lo, /* Drive SCL low */
107 i2c_sda_hi, /* Drive SDA high */
108 i2c_sda_lo, /* Drive SDA low */
109 i2c_sda_input, /* Set SDA as input */
110 i2c_sda_output, /* Set SDA as output */
111 i2c_scl_input, /* Set SCL as input */
112 i2c_scl_output, /* Set SCL as output */
113 i2c_scl, /* Read SCL, returns 0 or nonzero */
114 i2c_sda, /* Read SDA, returns 0 or nonzero */
115 115
116 i2c_delay, /* START SDA hold time (tHD:SDA) */ 116 /* Bus ACK, IICCLK: fPCLK / 16, Rx/Tx Int: Disable, Tx clock: IICCLK/8 */
117 i2c_delay, /* SDA hold time (tHD:DAT) */ 117 /* OF PCLK: 49.1568MHz / 16 / 8 = 384.0375 kHz */
118 i2c_delay, /* SDA setup time (tSU:DAT) */ 118 IICCON = (7 << 0);
119 i2c_delay, /* STOP setup time (tSU:STO) */
120 i2c_delay, /* Rep. START setup time (tSU:STA) */
121 i2c_delay, /* SCL high period (tHIGH) */
122};
123 119
124void i2c_init(void) 120 /* SDA line delayed 0 PCLKs */
125{ 121 IICLC = (0 << 0);
126 /* Set GPE15 (SDA) and GPE14 (SCL) to 1 */
127 GPECON = (GPECON & ~(0xF<<28)) | 5<<28;
128 i2c_add_node(&s3c2440_i2c);
129}
130 122
131void i2c_send(int bus_address, int reg_address, const unsigned char buf) 123 /* Turn off I2C clock */
132{ 124 CLKCON &= ~(1 << 16);
133 i2c_write_data(bus_address, reg_address, &buf, 1);
134} 125}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
index cf69230487..829b7eb91c 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing 10 * Copyright (C) 2007 by Michael Sevakis
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -19,4 +19,26 @@
19 19
20/* chip-specific i2c functions */ 20/* chip-specific i2c functions */
21 21
22void i2c_send(int bus_address, int reg_address, const unsigned char buf); 22/* IICCON */
23#define I2C_ACKGEN (1 << 7)
24#define I2C_TXCLK_512 (1 << 6)
25#define I2C_TXRX_INTENB (1 << 5)
26#define I2C_TXRX_INTPND (1 << 4)
27
28/* IICSTAT */
29#define I2C_MODE_MASTER (2 << 6)
30#define I2C_MODE_TX (1 << 6)
31#define I2C_BUSY (1 << 5)
32#define I2C_START (1 << 5)
33#define I2C_RXTX_ENB (1 << 4)
34#define I2C_BUS_ARB_FAILED (1 << 3)
35#define I2C_S_ADDR_STAT (1 << 2)
36#define I2C_S_ADDR_MATCH (1 << 1)
37#define I2C_ACK_L (1 << 0)
38
39/* IICLC */
40#define I2C_FLT_ENB (1 << 2)
41
42void i2c_init(void);
43void i2c_write(int addr, const unsigned char *data, int count);
44
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
index 0696b7aa0c..345991580c 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
@@ -26,7 +26,6 @@
26#include "cpu.h" 26#include "cpu.h"
27#include "kernel.h" 27#include "kernel.h"
28#include "sound.h" 28#include "sound.h"
29#include "i2c.h"
30#include "i2c-meg-fx.h" 29#include "i2c-meg-fx.h"
31 30
32void audiohw_init(void) 31void audiohw_init(void)
@@ -44,5 +43,8 @@ void audiohw_init(void)
44 43
45void wmcodec_write(int reg, int data) 44void wmcodec_write(int reg, int data)
46{ 45{
47 i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff); 46 unsigned char d[2];
47 d[0] = (reg << 1) | ((data & 0x100) >> 8);
48 d[1] = data;
49 i2c_write(0x34, d, 2);
48} 50}