Add new PMC3 flashing method

This commit is contained in:
Jeremy Soller 2020-01-16 14:40:24 -07:00
parent 5c4d946a66
commit f5c87e8f25
No known key found for this signature in database
GPG Key ID: E988B49EE78A7FB1
6 changed files with 261 additions and 195 deletions

View File

@ -76,9 +76,9 @@ void pmc_event(struct Pmc * pmc) {
pmc_sci_queue = 0; pmc_sci_queue = 0;
break; break;
case 0xDC: case 0xEC:
DEBUG(" scratch rom\n"); DEBUG(" scratch rom\n");
pmc_write(pmc, 0x33, PMC_TIMEOUT); pmc_write(pmc, 0x76, PMC_TIMEOUT);
scratch_trampoline(); scratch_trampoline();
break; break;
} }

View File

@ -10,83 +10,105 @@ volatile uint8_t __xdata __at(0x103D) ECINDAR2;
volatile uint8_t __xdata __at(0x103E) ECINDAR3; volatile uint8_t __xdata __at(0x103E) ECINDAR3;
volatile uint8_t __xdata __at(0x103F) ECINDDR; volatile uint8_t __xdata __at(0x103F) ECINDDR;
#define FLASH_SPI 0x00000000 uint8_t acpi_read(uint8_t addr) {
#define FLASH_EMBEDDED 0x40000000 uint8_t data = 0;
static int flash_transaction(uint32_t offset, uint8_t * data, int length, bool read) { switch (addr) {
int i; case 4:
for (i = 0; i < length; i++, offset++) { data = ECINDAR0;
ECINDAR3 = (uint8_t)(offset >> 24); break;
ECINDAR2 = (uint8_t)(offset >> 16); case 5:
ECINDAR1 = (uint8_t)(offset >> 8); data = ECINDAR1;
ECINDAR0 = (uint8_t)(offset); break;
if (read) { case 6:
data[i] = ECINDDR; data = ECINDAR2;
} else { break;
ECINDDR = data[i]; case 7:
} data = ECINDAR3;
break;
case 8:
data = ECINDDR;
break;
}
return data;
}
void acpi_write(uint8_t addr, uint8_t data) {
switch (addr) {
case 4:
ECINDAR0 = data;
break;
case 5:
ECINDAR1 = data;
break;
case 6:
ECINDAR2 = data;
break;
case 7:
ECINDAR3 = data;
break;
case 8:
ECINDDR = data;
break;
} }
return i;
} }
enum PmcState { enum PmcState {
PMC_STATE_DEFAULT, PMC_STATE_DEFAULT,
PMC_STATE_WRITE, PMC_STATE_ACPI_READ,
PMC_STATE_ACPI_WRITE,
PMC_STATE_ACPI_WRITE_ADDR,
}; };
static void pmc_event(struct Pmc * pmc) { void pmc_event(struct Pmc * pmc) {
static enum PmcState state = PMC_STATE_DEFAULT; static enum PmcState state = PMC_STATE_DEFAULT;
static uint8_t state_data[2] = {0, 0};
uint8_t sts = pmc_status(pmc); uint8_t sts = pmc_status(pmc);
if (sts & PMC_STS_IBF) { if (sts & PMC_STS_IBF) {
uint8_t data = pmc_read(pmc); uint8_t data = pmc_read(pmc);
if (sts & PMC_STS_CMD) { if (sts & PMC_STS_CMD) {
printf_tiny("%x\n", data); state = PMC_STATE_DEFAULT;
switch (data) {
case 0x80:
state = PMC_STATE_ACPI_READ;
break;
case 0x81:
state = PMC_STATE_ACPI_WRITE;
break;
case 0xEC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
} else {
switch (state) { switch (state) {
case PMC_STATE_DEFAULT: case PMC_STATE_ACPI_READ:
switch (data) { state = PMC_STATE_DEFAULT;
case 0x01: uint8_t value = acpi_read(data);
// Enable follow pmc_write(pmc, value);
ECINDAR3 = 0x0F; break;
break; case PMC_STATE_ACPI_WRITE:
case 0x02: state = PMC_STATE_ACPI_WRITE_ADDR;
// Generate high CE# state_data[0] = data;
data = 0; break;
flash_transaction(0x7FFFFE00, &data, 1, false); case PMC_STATE_ACPI_WRITE_ADDR:
// Fall through state = PMC_STATE_DEFAULT;
case 0x03: acpi_write(state_data[0], data);
state = PMC_STATE_WRITE; break;
break; default:
case 0x04: state = PMC_STATE_DEFAULT;
// Read data break;
flash_transaction(0x7FFFFD00, &data, 1, true);
pmc_write(pmc, data);
printf_tiny("=%x\n", data);
break;
case 0x05:
// Disable follow
ECINDAR3 = 0x00;
break;
case 0xFC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
break;
case PMC_STATE_WRITE:
// Write command or data
flash_transaction(0x7FFFFD00, &data, 1, false);
state = PMC_STATE_DEFAULT;
break;
} }
} }
} }
@ -96,6 +118,6 @@ static void pmc_event(struct Pmc * pmc) {
void main(void) { void main(void) {
printf_tiny("SCRATCH\n"); printf_tiny("SCRATCH\n");
for (;;) { for (;;) {
pmc_event(&PMC_1); pmc_event(&PMC_3);
} }
} }

View File

@ -76,9 +76,9 @@ void pmc_event(struct Pmc * pmc) {
pmc_sci_queue = 0; pmc_sci_queue = 0;
break; break;
case 0xDC: case 0xEC:
DEBUG(" scratch rom\n"); DEBUG(" scratch rom\n");
pmc_write(pmc, 0x33, PMC_TIMEOUT); pmc_write(pmc, 0x76, PMC_TIMEOUT);
scratch_trampoline(); scratch_trampoline();
break; break;
} }

View File

@ -10,83 +10,105 @@ volatile uint8_t __xdata __at(0x103D) ECINDAR2;
volatile uint8_t __xdata __at(0x103E) ECINDAR3; volatile uint8_t __xdata __at(0x103E) ECINDAR3;
volatile uint8_t __xdata __at(0x103F) ECINDDR; volatile uint8_t __xdata __at(0x103F) ECINDDR;
#define FLASH_SPI 0x00000000 uint8_t acpi_read(uint8_t addr) {
#define FLASH_EMBEDDED 0x40000000 uint8_t data = 0;
static int flash_transaction(uint32_t offset, uint8_t * data, int length, bool read) { switch (addr) {
int i; case 4:
for (i = 0; i < length; i++, offset++) { data = ECINDAR0;
ECINDAR3 = (uint8_t)(offset >> 24); break;
ECINDAR2 = (uint8_t)(offset >> 16); case 5:
ECINDAR1 = (uint8_t)(offset >> 8); data = ECINDAR1;
ECINDAR0 = (uint8_t)(offset); break;
if (read) { case 6:
data[i] = ECINDDR; data = ECINDAR2;
} else { break;
ECINDDR = data[i]; case 7:
} data = ECINDAR3;
break;
case 8:
data = ECINDDR;
break;
}
return data;
}
void acpi_write(uint8_t addr, uint8_t data) {
switch (addr) {
case 4:
ECINDAR0 = data;
break;
case 5:
ECINDAR1 = data;
break;
case 6:
ECINDAR2 = data;
break;
case 7:
ECINDAR3 = data;
break;
case 8:
ECINDDR = data;
break;
} }
return i;
} }
enum PmcState { enum PmcState {
PMC_STATE_DEFAULT, PMC_STATE_DEFAULT,
PMC_STATE_WRITE, PMC_STATE_ACPI_READ,
PMC_STATE_ACPI_WRITE,
PMC_STATE_ACPI_WRITE_ADDR,
}; };
static void pmc_event(struct Pmc * pmc) { void pmc_event(struct Pmc * pmc) {
static enum PmcState state = PMC_STATE_DEFAULT; static enum PmcState state = PMC_STATE_DEFAULT;
static uint8_t state_data[2] = {0, 0};
uint8_t sts = pmc_status(pmc); uint8_t sts = pmc_status(pmc);
if (sts & PMC_STS_IBF) { if (sts & PMC_STS_IBF) {
uint8_t data = pmc_read(pmc); uint8_t data = pmc_read(pmc);
if (sts & PMC_STS_CMD) { if (sts & PMC_STS_CMD) {
printf_tiny("%x\n", data); state = PMC_STATE_DEFAULT;
switch (data) {
case 0x80:
state = PMC_STATE_ACPI_READ;
break;
case 0x81:
state = PMC_STATE_ACPI_WRITE;
break;
case 0xEC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
} else {
switch (state) { switch (state) {
case PMC_STATE_DEFAULT: case PMC_STATE_ACPI_READ:
switch (data) { state = PMC_STATE_DEFAULT;
case 0x01: uint8_t value = acpi_read(data);
// Enable follow pmc_write(pmc, value);
ECINDAR3 = 0x0F; break;
break; case PMC_STATE_ACPI_WRITE:
case 0x02: state = PMC_STATE_ACPI_WRITE_ADDR;
// Generate high CE# state_data[0] = data;
data = 0; break;
flash_transaction(0x7FFFFE00, &data, 1, false); case PMC_STATE_ACPI_WRITE_ADDR:
// Fall through state = PMC_STATE_DEFAULT;
case 0x03: acpi_write(state_data[0], data);
state = PMC_STATE_WRITE; break;
break; default:
case 0x04: state = PMC_STATE_DEFAULT;
// Read data break;
flash_transaction(0x7FFFFD00, &data, 1, true);
pmc_write(pmc, data);
printf_tiny("=%x\n", data);
break;
case 0x05:
// Disable follow
ECINDAR3 = 0x00;
break;
case 0xFC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
break;
case PMC_STATE_WRITE:
// Write command or data
flash_transaction(0x7FFFFD00, &data, 1, false);
state = PMC_STATE_DEFAULT;
break;
} }
} }
} }
@ -96,6 +118,6 @@ static void pmc_event(struct Pmc * pmc) {
void main(void) { void main(void) {
printf_tiny("SCRATCH\n"); printf_tiny("SCRATCH\n");
for (;;) { for (;;) {
pmc_event(&PMC_1); pmc_event(&PMC_3);
} }
} }

View File

@ -76,9 +76,9 @@ void pmc_event(struct Pmc * pmc) {
pmc_sci_queue = 0; pmc_sci_queue = 0;
break; break;
case 0xDC: case 0xEC:
DEBUG(" scratch rom\n"); DEBUG(" scratch rom\n");
pmc_write(pmc, 0x33, PMC_TIMEOUT); pmc_write(pmc, 0x76, PMC_TIMEOUT);
scratch_trampoline(); scratch_trampoline();
break; break;
} }

View File

@ -10,83 +10,105 @@ volatile uint8_t __xdata __at(0x103D) ECINDAR2;
volatile uint8_t __xdata __at(0x103E) ECINDAR3; volatile uint8_t __xdata __at(0x103E) ECINDAR3;
volatile uint8_t __xdata __at(0x103F) ECINDDR; volatile uint8_t __xdata __at(0x103F) ECINDDR;
#define FLASH_SPI 0x00000000 uint8_t acpi_read(uint8_t addr) {
#define FLASH_EMBEDDED 0x40000000 uint8_t data = 0;
static int flash_transaction(uint32_t offset, uint8_t * data, int length, bool read) { switch (addr) {
int i; case 4:
for (i = 0; i < length; i++, offset++) { data = ECINDAR0;
ECINDAR3 = (uint8_t)(offset >> 24); break;
ECINDAR2 = (uint8_t)(offset >> 16); case 5:
ECINDAR1 = (uint8_t)(offset >> 8); data = ECINDAR1;
ECINDAR0 = (uint8_t)(offset); break;
if (read) { case 6:
data[i] = ECINDDR; data = ECINDAR2;
} else { break;
ECINDDR = data[i]; case 7:
} data = ECINDAR3;
break;
case 8:
data = ECINDDR;
break;
}
return data;
}
void acpi_write(uint8_t addr, uint8_t data) {
switch (addr) {
case 4:
ECINDAR0 = data;
break;
case 5:
ECINDAR1 = data;
break;
case 6:
ECINDAR2 = data;
break;
case 7:
ECINDAR3 = data;
break;
case 8:
ECINDDR = data;
break;
} }
return i;
} }
enum PmcState { enum PmcState {
PMC_STATE_DEFAULT, PMC_STATE_DEFAULT,
PMC_STATE_WRITE, PMC_STATE_ACPI_READ,
PMC_STATE_ACPI_WRITE,
PMC_STATE_ACPI_WRITE_ADDR,
}; };
static void pmc_event(struct Pmc * pmc) { void pmc_event(struct Pmc * pmc) {
static enum PmcState state = PMC_STATE_DEFAULT; static enum PmcState state = PMC_STATE_DEFAULT;
static uint8_t state_data[2] = {0, 0};
uint8_t sts = pmc_status(pmc); uint8_t sts = pmc_status(pmc);
if (sts & PMC_STS_IBF) { if (sts & PMC_STS_IBF) {
uint8_t data = pmc_read(pmc); uint8_t data = pmc_read(pmc);
if (sts & PMC_STS_CMD) { if (sts & PMC_STS_CMD) {
printf_tiny("%x\n", data); state = PMC_STATE_DEFAULT;
switch (data) {
case 0x80:
state = PMC_STATE_ACPI_READ;
break;
case 0x81:
state = PMC_STATE_ACPI_WRITE;
break;
case 0xEC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
} else {
switch (state) { switch (state) {
case PMC_STATE_DEFAULT: case PMC_STATE_ACPI_READ:
switch (data) { state = PMC_STATE_DEFAULT;
case 0x01: uint8_t value = acpi_read(data);
// Enable follow pmc_write(pmc, value);
ECINDAR3 = 0x0F; break;
break; case PMC_STATE_ACPI_WRITE:
case 0x02: state = PMC_STATE_ACPI_WRITE_ADDR;
// Generate high CE# state_data[0] = data;
data = 0; break;
flash_transaction(0x7FFFFE00, &data, 1, false); case PMC_STATE_ACPI_WRITE_ADDR:
// Fall through state = PMC_STATE_DEFAULT;
case 0x03: acpi_write(state_data[0], data);
state = PMC_STATE_WRITE; break;
break; default:
case 0x04: state = PMC_STATE_DEFAULT;
// Read data break;
flash_transaction(0x7FFFFD00, &data, 1, true);
pmc_write(pmc, data);
printf_tiny("=%x\n", data);
break;
case 0x05:
// Disable follow
ECINDAR3 = 0x00;
break;
case 0xFC:
// Clear processor caches
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
__asm__("mov 0xf7, #1");
__asm__("nop");
// Exit scratch ROM by going through trampoline
__asm__("ljmp 0x1000");
break;
}
break;
case PMC_STATE_WRITE:
// Write command or data
flash_transaction(0x7FFFFD00, &data, 1, false);
state = PMC_STATE_DEFAULT;
break;
} }
} }
} }
@ -96,6 +118,6 @@ static void pmc_event(struct Pmc * pmc) {
void main(void) { void main(void) {
printf_tiny("SCRATCH\n"); printf_tiny("SCRATCH\n");
for (;;) { for (;;) {
pmc_event(&PMC_1); pmc_event(&PMC_3);
} }
} }