mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-15 16:12:28 -05:00
revert the last changes because they prevent some Gigabeats from shutting down
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13372 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
d92e09556f
commit
685001f0d4
1 changed files with 107 additions and 86 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "logf.h"
|
||||
|
|
@ -8,132 +9,147 @@
|
|||
|
||||
#define SLAVE_ADDRESS 0xCC
|
||||
|
||||
#define USE_ASM
|
||||
|
||||
/* This I2C driver tristates the outputs instead of driving logic high's */
|
||||
#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 SDA_LO_OUT (GPHCON |= (1 << 18));(GPHDAT &= ~(1 << 9));
|
||||
#define SDA_HI_IN (GPHCON &= ~(3 << 18))
|
||||
|
||||
#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_LO_OUT (GPHCON |= (1 << 20));(GPHDAT &= ~(1 << 10));
|
||||
#define SCL_HI_IN (GPHCON &= ~(3 << 20));while(!SCL);
|
||||
|
||||
/* 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 = 2 + 4 * loops
|
||||
* 100MHz = 10nS per cycle: LO:1300nS=130:33 HI:600nS=60:15
|
||||
* 300MHz = 3.33nS per cycle:
|
||||
* LO:1300nS=394:99
|
||||
* HI:600nS=182:21
|
||||
* MID(50/50):950(1900/2)ns=288:72
|
||||
*/
|
||||
#define SCL_SDA_HI (GPHDAT |= (3 << 9))
|
||||
|
||||
#ifdef USE_ASM
|
||||
/* 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)
|
||||
|
||||
#define DELAY_LO 99
|
||||
#define DELAY_MID 72
|
||||
#define DELAY_HI 46
|
||||
/* This delay loop takes 4 cycles/loop to execute plus 2 for setup */
|
||||
#define DELAY(dly) \
|
||||
asm volatile( "mov r0,%0 \n" \
|
||||
"1: \n" \
|
||||
"subs r0,r0,#1 \n" \
|
||||
"bhi 1b \n" \
|
||||
: : "r"((dly)) : "r0" );
|
||||
|
||||
#else
|
||||
|
||||
#define DELAY_LO 51
|
||||
#define DELAY_MID 35
|
||||
#define DELAY_HI 21
|
||||
#define DELAY(dly) do{int x;for(x=(dly);x;x--);} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
static void sc606_i2c_start(void)
|
||||
{
|
||||
SDA_HI_IN;
|
||||
SCL_HI_IN;
|
||||
DELAY(DELAY_MID);
|
||||
SDA_LO_OUT;
|
||||
DELAY(DELAY_MID);
|
||||
SCL_LO_OUT;
|
||||
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_OUT;
|
||||
SCL_HI_IN;
|
||||
DELAY(DELAY_HI);
|
||||
SDA_HI_IN;
|
||||
SDA_LO;
|
||||
SCL_HI;
|
||||
DELAY_HI;
|
||||
SDA_HI;
|
||||
}
|
||||
|
||||
static void sc606_i2c_ack(void)
|
||||
{
|
||||
SDA_HI_IN;
|
||||
SCL_HI_IN;
|
||||
|
||||
DELAY(DELAY_HI);
|
||||
SCL_LO_OUT;
|
||||
SDA_LO;
|
||||
SCL_HI;
|
||||
DELAY_HI;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
static bool sc606_i2c_getack(void)
|
||||
|
||||
|
||||
static int sc606_i2c_getack(void)
|
||||
{
|
||||
bool ret;
|
||||
int ret;
|
||||
|
||||
SDA_HI_IN;
|
||||
DELAY(DELAY_MID);
|
||||
SCL_HI_IN;
|
||||
/* 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;
|
||||
ret = (SDA != 0); /* ack failed if SDA is not low */
|
||||
DELAY_HI;
|
||||
|
||||
SCL_LO_OUT;
|
||||
DELAY(DELAY_LO);
|
||||
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 )
|
||||
for (i = 0x80; i; i >>= 1)
|
||||
{
|
||||
if ( i & byte )
|
||||
SDA_HI_IN;
|
||||
if (i & byte)
|
||||
{
|
||||
SDA_HI;
|
||||
}
|
||||
else
|
||||
SDA_LO_OUT;
|
||||
DELAY(DELAY_MID);
|
||||
SCL_HI_IN;
|
||||
DELAY(DELAY_HI);
|
||||
SCL_LO_OUT;
|
||||
{
|
||||
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;
|
||||
int i;
|
||||
unsigned char byte = 0;
|
||||
|
||||
/* clock in each bit, MSB first */
|
||||
SDA_HI_IN;
|
||||
for ( i=0x80; i; i>>=1 )
|
||||
{
|
||||
SCL_HI_IN;
|
||||
DELAY(DELAY_HI);
|
||||
if ( SDA )
|
||||
byte |= i;
|
||||
SCL_LO_OUT;
|
||||
DELAY(DELAY_LO);
|
||||
}
|
||||
SDA_INPUT; /* And set to input */
|
||||
/* clock in each bit, MSB first */
|
||||
for (i = 0x80; i; i >>= 1) {
|
||||
SCL_HI;
|
||||
|
||||
sc606_i2c_ack();
|
||||
return byte;
|
||||
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)
|
||||
{
|
||||
|
|
@ -147,7 +163,7 @@ int sc606_write(unsigned char reg, unsigned char data)
|
|||
sc606_i2c_outb(reg);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_start();
|
||||
sc606_i2c_restart();
|
||||
|
||||
sc606_i2c_outb(SLAVE_ADDRESS);
|
||||
x += sc606_i2c_getack();
|
||||
|
|
@ -160,6 +176,8 @@ int sc606_write(unsigned char reg, unsigned char data)
|
|||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sc606_read(unsigned char reg, unsigned char* data)
|
||||
{
|
||||
int x;
|
||||
|
|
@ -171,7 +189,7 @@ int sc606_read(unsigned char reg, unsigned char* data)
|
|||
sc606_i2c_outb(reg);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_start();
|
||||
sc606_i2c_restart();
|
||||
sc606_i2c_outb(SLAVE_ADDRESS | 1);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
|
|
@ -181,6 +199,8 @@ int sc606_read(unsigned char reg, unsigned char* data)
|
|||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sc606_init(void)
|
||||
{
|
||||
volatile int i;
|
||||
|
|
@ -194,11 +214,12 @@ void sc606_init(void)
|
|||
|
||||
/* About 400us - needs 350us */
|
||||
for (i = 200; i; i--)
|
||||
DELAY(DELAY_LO);
|
||||
{
|
||||
DELAY_LO;
|
||||
}
|
||||
|
||||
/* Set GPH9 (SDA) and GPH10 (SCL) to 1 */
|
||||
GPHUP &= ~(3<<9);
|
||||
SCL_HI_IN;
|
||||
SDA_HI_IN;
|
||||
GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue