2006-08-21 15:06:08 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "hwcompat.h"
|
|
|
|
#include "logf.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "string.h"
|
|
|
|
|
|
|
|
#define SLAVE_ADDRESS 0xCC
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
#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))
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
#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))
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
#define SCL_SDA_HI (GPHDAT |= (3 << 9))
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-20 22:16:01 +00:00
|
|
|
/* The SC606 can clock at 400KHz: */
|
|
|
|
/* Clock period high is 600nS and low is 1300nS */
|
2007-01-05 08:50:09 +00:00
|
|
|
/* The high and low times are different enough to need different timings */
|
2007-01-20 22:16:01 +00:00
|
|
|
/* 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 */
|
2007-02-08 10:21:37 +00:00
|
|
|
#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)
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static void sc606_i2c_start(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
SCL_SDA_HI;
|
|
|
|
DELAY;
|
|
|
|
SDA_LO;
|
|
|
|
DELAY;
|
|
|
|
SCL_LO;
|
|
|
|
}
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static void sc606_i2c_restart(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
SCL_SDA_HI;
|
|
|
|
DELAY;
|
|
|
|
SDA_LO;
|
|
|
|
DELAY;
|
|
|
|
SCL_LO;
|
|
|
|
}
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static void sc606_i2c_stop(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
SDA_LO;
|
|
|
|
SCL_HI;
|
2007-01-05 08:50:09 +00:00
|
|
|
DELAY_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
SDA_HI;
|
|
|
|
}
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static void sc606_i2c_ack(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
SDA_LO;
|
|
|
|
SCL_HI;
|
2007-01-05 08:50:09 +00:00
|
|
|
DELAY_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
SCL_LO;
|
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static int sc606_i2c_getack(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
2007-01-05 08:50:09 +00:00
|
|
|
int ret;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
/* Don't need a delay since follows a data bit with a delay on the end */
|
2006-08-21 15:06:08 +00:00
|
|
|
SDA_INPUT; /* And set to input */
|
|
|
|
DELAY;
|
2007-01-05 08:50:09 +00:00
|
|
|
SCL_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
ret = (SDA != 0); /* ack failed if SDA is not low */
|
|
|
|
DELAY_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
|
|
|
SCL_LO;
|
2007-01-05 08:50:09 +00:00
|
|
|
DELAY_LO;
|
|
|
|
|
|
|
|
SDA_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
SDA_OUTPUT;
|
2007-01-05 08:50:09 +00:00
|
|
|
DELAY_LO;
|
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void sc606_i2c_outb(unsigned char byte)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* clock out each bit, MSB first */
|
2007-01-20 22:16:01 +00:00
|
|
|
for (i = 0x80; i; i >>= 1)
|
2007-01-05 08:50:09 +00:00
|
|
|
{
|
2007-01-20 22:16:01 +00:00
|
|
|
if (i & byte)
|
2007-01-05 08:50:09 +00:00
|
|
|
{
|
|
|
|
SDA_HI;
|
2007-01-20 22:16:01 +00:00
|
|
|
}
|
|
|
|
else
|
2007-01-05 08:50:09 +00:00
|
|
|
{
|
|
|
|
SDA_LO;
|
|
|
|
}
|
|
|
|
DELAY;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
SCL_HI;
|
|
|
|
DELAY_HI;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
SCL_LO;
|
|
|
|
DELAY_LO;
|
2006-08-21 15:06:08 +00:00
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
SDA_HI;
|
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
static unsigned char sc606_i2c_inb(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-12-29 02:49:12 +00:00
|
|
|
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
/* returns number of acks that were bad */
|
2006-08-21 15:06:08 +00:00
|
|
|
int sc606_write(unsigned char reg, unsigned char data)
|
|
|
|
{
|
2007-01-07 06:38:57 +00:00
|
|
|
int x;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
|
|
|
sc606_i2c_start();
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
sc606_i2c_outb(SLAVE_ADDRESS);
|
|
|
|
x = sc606_i2c_getack();
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
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();
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
sc606_i2c_stop();
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
int sc606_read(unsigned char reg, unsigned char* data)
|
|
|
|
{
|
2007-01-07 06:38:57 +00:00
|
|
|
int x;
|
2006-08-21 15:06:08 +00:00
|
|
|
|
|
|
|
sc606_i2c_start();
|
|
|
|
sc606_i2c_outb(SLAVE_ADDRESS);
|
2007-01-05 08:50:09 +00:00
|
|
|
x = sc606_i2c_getack();
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
sc606_i2c_outb(reg);
|
2007-01-05 08:50:09 +00:00
|
|
|
x += sc606_i2c_getack();
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
sc606_i2c_restart();
|
|
|
|
sc606_i2c_outb(SLAVE_ADDRESS | 1);
|
2007-01-05 08:50:09 +00:00
|
|
|
x += sc606_i2c_getack();
|
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
*data = sc606_i2c_inb();
|
|
|
|
sc606_i2c_stop();
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2007-01-05 08:50:09 +00:00
|
|
|
|
|
|
|
|
2006-08-22 08:04:51 +00:00
|
|
|
void sc606_init(void)
|
2006-08-21 15:06:08 +00:00
|
|
|
{
|
2007-01-04 09:26:32 +00:00
|
|
|
volatile int i;
|
2007-01-20 22:16:01 +00:00
|
|
|
|
2006-08-21 15:06:08 +00:00
|
|
|
/* 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 */
|
2007-01-04 09:26:32 +00:00
|
|
|
for (i = 200; i; i--)
|
|
|
|
{
|
2007-01-05 08:50:09 +00:00
|
|
|
DELAY_LO;
|
2007-01-04 09:26:32 +00:00
|
|
|
}
|
2006-08-21 15:06:08 +00:00
|
|
|
|
|
|
|
/* Set GPH9 (SDA) and GPH10 (SCL) to 1 */
|
|
|
|
GPHUP &= ~(3<<9);
|
|
|
|
GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18;
|
|
|
|
}
|
|
|
|
|