From f44f961812c059b69df19ac5bd828986ba10513f Mon Sep 17 00:00:00 2001 From: Marcoen Hirschberg Date: Wed, 18 Apr 2007 12:22:27 +0000 Subject: move the Gigabeat from gigabeat/meg-fx to s3c2440/gigabeat-fx to avoid problems with possible ports in the future: Gigabeat S/V (i.mx31 based) and Kenwood HD20GA7/HD20GA9 (s3c2440 based) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13200 a1c6a512-1295-4272-9138-f99709370657 --- .../target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c | 225 +++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c') diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c new file mode 100644 index 0000000000..e69eab432a --- /dev/null +++ b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c @@ -0,0 +1,225 @@ +#include "config.h" +#include "cpu.h" +#include +#include "kernel.h" +#include "system.h" +#include "logf.h" +#include "debug.h" +#include "string.h" + +#define SLAVE_ADDRESS 0xCC + +#define SDA_LO (GPHDAT &= ~(1 << 9)) +#define SDA_HI (GPHDAT |= (1 << 9)) +#define SDA_INPUT (GPHCON &= ~(3 << 18)) +#define SDA_OUTPUT (GPHCON |= (1 << 18)) +#define SDA (GPHDAT & (1 << 9)) + +#define SCL_LO (GPHDAT &= ~(1 << 10)) +#define SCL_HI (GPHDAT |= (1 << 10)) +#define SCL_INPUT (GPHCON &= ~(3 << 20)) +#define SCL_OUTPUT (GPHCON |= (1 << 20)) +#define SCL (GPHDAT & (1 << 10)) + +#define SCL_SDA_HI (GPHDAT |= (3 << 9)) + +/* The SC606 can clock at 400KHz: */ +/* Clock period high is 600nS and low is 1300nS */ +/* The high and low times are different enough to need different timings */ +/* cycles delayed = 30 + 7 * loops */ +/* 100MHz = 10nS per cycle: LO:1300nS=130:14 HI:600nS=60:9 */ +/* 300MHz = 3.36nS per cycle: LO:1300nS=387:51 HI:600nS=179:21 */ +#define DELAY_LO do{int x;for(x=51;x;x--);} while (0) +#define DELAY do{int x;for(x=35;x;x--);} while (0) +#define DELAY_HI do{int x;for(x=21;x;x--);} while (0) + + + +static void sc606_i2c_start(void) +{ + SCL_SDA_HI; + DELAY; + SDA_LO; + DELAY; + SCL_LO; +} + +static void sc606_i2c_restart(void) +{ + SCL_SDA_HI; + DELAY; + SDA_LO; + DELAY; + SCL_LO; +} + +static void sc606_i2c_stop(void) +{ + SDA_LO; + SCL_HI; + DELAY_HI; + SDA_HI; +} + +static void sc606_i2c_ack(void) +{ + + SDA_LO; + SCL_HI; + DELAY_HI; + SCL_LO; +} + + + +static int sc606_i2c_getack(void) +{ + int ret; + + /* Don't need a delay since follows a data bit with a delay on the end */ + SDA_INPUT; /* And set to input */ + DELAY; + SCL_HI; + + ret = (SDA != 0); /* ack failed if SDA is not low */ + DELAY_HI; + + SCL_LO; + DELAY_LO; + + SDA_HI; + SDA_OUTPUT; + DELAY_LO; + + return ret; +} + + + +static void sc606_i2c_outb(unsigned char byte) +{ + int i; + + /* clock out each bit, MSB first */ + for (i = 0x80; i; i >>= 1) + { + if (i & byte) + { + SDA_HI; + } + else + { + SDA_LO; + } + DELAY; + + SCL_HI; + DELAY_HI; + + SCL_LO; + DELAY_LO; + } + + SDA_HI; + +} + + + +static unsigned char sc606_i2c_inb(void) +{ + int i; + unsigned char byte = 0; + + SDA_INPUT; /* And set to input */ + /* clock in each bit, MSB first */ + for (i = 0x80; i; i >>= 1) { + SCL_HI; + + if (SDA) + byte |= i; + + SCL_LO; + } + SDA_OUTPUT; + + sc606_i2c_ack(); + + return byte; +} + + + +/* returns number of acks that were bad */ +int sc606_write(unsigned char reg, unsigned char data) +{ + int x; + + sc606_i2c_start(); + + sc606_i2c_outb(SLAVE_ADDRESS); + x = sc606_i2c_getack(); + + sc606_i2c_outb(reg); + x += sc606_i2c_getack(); + + sc606_i2c_restart(); + + sc606_i2c_outb(SLAVE_ADDRESS); + x += sc606_i2c_getack(); + + sc606_i2c_outb(data); + x += sc606_i2c_getack(); + + sc606_i2c_stop(); + + return x; +} + + + +int sc606_read(unsigned char reg, unsigned char* data) +{ + int x; + + sc606_i2c_start(); + sc606_i2c_outb(SLAVE_ADDRESS); + x = sc606_i2c_getack(); + + sc606_i2c_outb(reg); + x += sc606_i2c_getack(); + + sc606_i2c_restart(); + sc606_i2c_outb(SLAVE_ADDRESS | 1); + x += sc606_i2c_getack(); + + *data = sc606_i2c_inb(); + sc606_i2c_stop(); + + return x; +} + + + +void sc606_init(void) +{ + volatile int i; + + /* Set GPB2 (EN) to 1 */ + GPBCON = (GPBCON & ~(3<<4)) | 1<<4; + + /* Turn enable line on */ + GPBDAT |= 1<<2; + /* OFF GPBDAT &= ~(1 << 2); */ + + /* About 400us - needs 350us */ + for (i = 200; i; i--) + { + DELAY_LO; + } + + /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ + GPHUP &= ~(3<<9); + GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18; +} + -- cgit v1.2.3