mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 20:55:17 -05:00
iPod Classic: prepare i2c and PMU for bootloader
When the bootloader starts only IRAM is available, the first task is to ask the PMU to verify if the iPod has previously been hibernated by OF. Due to memory limitations, the kernel cannot be used on this stage. This patch modifies I2C and PMU low level functions to not to depend on kernel (removes mutexes, and uses HW timer instead of current_tick), actual kernel functions are modified to be 'mutexed' wrappers of the new functions. Change-Id: I7cef9e95dedaf176dc0659315f3dc33166d5b116
This commit is contained in:
parent
44ce4eebd6
commit
469d645390
4 changed files with 73 additions and 53 deletions
|
|
@ -18,7 +18,7 @@
|
|||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
|
|
@ -71,68 +71,52 @@ void i2c_init()
|
|||
mutex_init(&i2c_mtx[1]);
|
||||
}
|
||||
|
||||
int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data)
|
||||
int i2c_wr(int bus, unsigned char slave, int address, int len, const unsigned char *data)
|
||||
{
|
||||
mutex_lock(&i2c_mtx[bus]);
|
||||
i2c_on(bus);
|
||||
long timeout = current_tick + HZ / 50;
|
||||
long timeout = USEC_TIMER + 20000;
|
||||
|
||||
/* START */
|
||||
IICDS(bus) = slave & ~1;
|
||||
IICSTAT(bus) = 0xF0;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (address >= 0) {
|
||||
/* write address */
|
||||
IICDS(bus) = address;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* write data */
|
||||
while (len--) {
|
||||
IICDS(bus) = *data++;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* STOP */
|
||||
IICSTAT(bus) = 0xD0;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICSTAT(bus) & (1 << 5)) != 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
i2c_off(bus);
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data)
|
||||
int i2c_rd(int bus, unsigned char slave, int address, int len, unsigned char *data)
|
||||
{
|
||||
mutex_lock(&i2c_mtx[bus]);
|
||||
i2c_on(bus);
|
||||
long timeout = current_tick + HZ / 50;
|
||||
long timeout = USEC_TIMER + 20000;
|
||||
|
||||
if (address >= 0) {
|
||||
/* START */
|
||||
|
|
@ -140,42 +124,30 @@ int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *
|
|||
IICSTAT(bus) = 0xF0;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* write address */
|
||||
IICDS(bus) = address;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (repeated) START */
|
||||
IICDS(bus) = slave | 1;
|
||||
IICSTAT(bus) = 0xB0;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
while (len--) {
|
||||
IICCON(bus) = (len == 0) ? 0x33 : 0xB3; /* NAK or ACK */
|
||||
while ((IICCON(bus) & 0x10) == 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 4;
|
||||
}
|
||||
*data++ = IICDS(bus);
|
||||
}
|
||||
|
||||
|
|
@ -183,14 +155,27 @@ int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *
|
|||
IICSTAT(bus) = 0x90;
|
||||
IICCON(bus) = 0xB3;
|
||||
while ((IICSTAT(bus) & (1 << 5)) != 0)
|
||||
if (TIME_AFTER(current_tick, timeout))
|
||||
{
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
if (TIME_AFTER(USEC_TIMER, timeout))
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
i2c_off(bus);
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_write(int bus, unsigned char slave, int address, int len, const unsigned char *data)
|
||||
{
|
||||
int ret;
|
||||
mutex_lock(&i2c_mtx[bus]);
|
||||
ret = i2c_wr(bus, slave, address, len, data);
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_read(int bus, unsigned char slave, int address, int len, unsigned char *data)
|
||||
{
|
||||
int ret;
|
||||
mutex_lock(&i2c_mtx[bus]);
|
||||
ret = i2c_rd(bus, slave, address, len, data);
|
||||
mutex_unlock(&i2c_mtx[bus]);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue