diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c | 165 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h | 26 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c | 6 |
4 files changed, 106 insertions, 92 deletions
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 |
515 | drivers/generic_i2c.c | ||
516 | target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c | 515 | target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c |
517 | target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c | 516 | target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c |
518 | target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c | 517 | target/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. */ | |
29 | static 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 | |||
41 | static 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 | ||
34 | static void i2c_sda_input(void) | 48 | static 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 | ||
39 | static void i2c_sda_lo(void) | 55 | static 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 | ||
44 | static void i2c_sda_hi(void) | 63 | static 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 | ||
49 | static int i2c_sda(void) | 72 | void 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 | ||
54 | static 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 | ||
59 | static 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 | ||
64 | static void i2c_scl_lo(void) | 87 | IICDS = addr & 0xfe; |
65 | { | ||
66 | GPEDAT &= ~(1 << 14); | ||
67 | } | ||
68 | 88 | ||
69 | static 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 | |||
74 | static 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 | ||
84 | static 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 | ||
104 | void 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 | ||
101 | struct 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 | ||
124 | void 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 | ||
131 | void 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 | ||
22 | void 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 | |||
42 | void i2c_init(void); | ||
43 | void 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 | ||
32 | void audiohw_init(void) | 31 | void audiohw_init(void) |
@@ -44,5 +43,8 @@ void audiohw_init(void) | |||
44 | 43 | ||
45 | void wmcodec_write(int reg, int data) | 44 | void 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 | } |