#include "config.h" #include "cpu.h" #include #include "kernel.h" #include "system.h" #include "hwcompat.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) /* arbitrary delay loop */ #define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0) void sc606_i2c_start(void) { SCL_SDA_HI; DELAY; SDA_LO; DELAY; SCL_LO; } void sc606_i2c_restart(void) { SCL_SDA_HI; DELAY; SDA_LO; DELAY; SCL_LO; } void sc606_i2c_stop(void) { SDA_LO; DELAY; SCL_HI; DELAY; SDA_HI; DELAY; } void sc606_i2c_ack(void) { SDA_LO; SCL_HI; DELAY; SCL_LO; } int sc606_i2c_getack(void) { int ret = 0; /* Don't need a delay since this follows a data bit with a delay on the end */ SDA_INPUT; /* And set to input */ SCL_HI; DELAY; if (SDA) /* ack failed */ ret = 1; DELAY; SCL_LO; DELAY; SDA_OUTPUT; return ret; } int 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; SCL_LO; DELAY; } return sc606_i2c_getack(); } 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; } int sc606_write(unsigned char reg, unsigned char data) { int x = 0; sc606_i2c_start(); x += sc606_i2c_outb(SLAVE_ADDRESS); x += 0x10 * sc606_i2c_outb(reg); sc606_i2c_start(); /* sc606_i2c_restart(); */ x += 0x100 * sc606_i2c_outb(SLAVE_ADDRESS); x += 0x1000 *sc606_i2c_outb(data); sc606_i2c_stop(); return x; } int sc606_read(unsigned char reg, unsigned char* data) { int x = 0; sc606_i2c_start(); sc606_i2c_outb(SLAVE_ADDRESS); sc606_i2c_outb(reg); sc606_i2c_restart(); sc606_i2c_outb(SLAVE_ADDRESS | 1); *data = sc606_i2c_inb(); sc606_i2c_stop(); return x; } void sc606_init(void) { /* 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 */ DELAY; DELAY; DELAY; DELAY; DELAY; /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */ GPHUP &= ~(3<<9); GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18; }