Commit 312a782a authored by Ruslan Marchenko's avatar Ruslan Marchenko
Browse files

Draft SPI interface

parent 33bcef3c
......@@ -111,6 +111,32 @@ err_t i2c_write16_be(uint8_t i2c_addr, uint8_t reg, uint16_t value)
return ERROR_NONE;
}
#define SSP_MIS_ROR 0x1 // Rx OverRun (Urgently need to read)
#define SSP_MIS_RT 0x2 // Rx Timeout (Has some unread data)
#define SSP_MIS_RX 0x4 // Rx Half Full (need to read)
#define SSP_MIS_TX 0x8 // Tx Half Empty (has free space to write)
/* FIFO is 8 Frames, Frame is 1 byte by default, hence we're EAGAIN(0) when full */
/* Return sent bytes at Lo byte(ret&&0xff) and read bytes at Hi (ret>>8) */
uint16_t ssp0Xfer (uint8_t *buf, uint8_t length)
{
uint8_t rx=0, tx=0;
for (tx = 0; tx < length; tx++) {
/* Move on only if TX FIFO is not full. */
if(LPC_SSP0->SR & SSP0_SR_TNF_NOTFULL) {
LPC_SSP0->DR = buf[tx];
if(LPC_SSP0->SR & SSP0_SR_RNE_NOTEMPTY) {
buf[rx] = LPC_SSP0->DR;
rx++;
}
} else {
break;
}
}
return ((rx << 8) | tx);
}
// see https://www.analog.com/media/en/technical-documentation/data-sheets/680324fa.pdf
// default = 0x41
uint8_t calc_pec(uint8_t d, uint8_t pec) {
......@@ -385,26 +411,115 @@ float chg_vin;
float chg_vbat;
int som_is_powered = 0;
void turn_som_power_on(void) {
LPC_GPIO->CLR[1] = (1 << 28); // hold in reset
#define LPC_CTL_5V 0x01 // 5V Rail regulator (U7) on/off
#define LPC_CTL_3V3 0x02 // 3V3 Rail regulator (U12) on/off
#define LPC_CTL_USB 0x04 // USB 5V rail on/off (U24) (MBREV_R1+)
#define LPC_CTL_AUX 0x08 // AUX 3V3 power rail on/off (U27), and downstream 1V8 (U17) (MBREV_R1+)
#define LPC_CTL_1V2 0x10 // DSI/USB Hub 1V2 regulator (U13) on/off
#define LPC_CTL_PCIE 0x20 // PCIe1 power supply transistor (1V5 regulator U19 and 3V3 load switch)
#define LPC_CTL_UART 0x40 // Control TXD pin of the UART to SoM
#define LPC_CTL_RNG 0x80 // RNG/SS pin of LTC4020 (NTC on MBREV_R1+): control/limit charge current
LPC_GPIO->CLR[0] = (1 << 20); // PCIe off
LPC_GPIO->CLR[1] = (1 << 19); // 1v2 off
LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+)
LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+)
uint8_t lpc_ctl_get(void) {
uint8_t ret = 0;
if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) {
LPC_GPIO->CLR[1] = (1 << 16); // 3v3 on
LPC_GPIO->CLR[1] = (1 << 15); // 5v on
if(REFORM_MOTHERBOARD_REV < REFORM_MBREV_R1) {
if(LPC_GPIO->PIN[1] & (1<<15))
ret |= LPC_CTL_5V;
if(LPC_GPIO->PIN[1] & (1<<16))
ret |= LPC_CTL_3V3;
} else {
LPC_GPIO->SET[1] = (1 << 16); // 3v3 on
LPC_GPIO->SET[1] = (1 << 15); // 5v on
if(!(LPC_GPIO->PIN[1] & (1<<15)))
ret |= LPC_CTL_5V;
if(!(LPC_GPIO->PIN[1] & (1<<16)))
ret |= LPC_CTL_3V3;
}
LPC_GPIO->SET[0] = (1 << 20); // PCIe on
LPC_GPIO->SET[1] = (1 << 19); // 1v2 on
LPC_GPIO->SET[1] = (1 << 31); // USB 5v on (R1+)
LPC_GPIO->SET[0] = (1 << 7); // AUX 3v3 on (R1+)
if(LPC_GPIO->PIN[1] & (1 << 31))
ret |= LPC_CTL_USB;
if(LPC_GPIO->PIN[0] & (1 << 7))
ret |= LPC_CTL_AUX;
if(LPC_GPIO->PIN[1] & (1 << 19))
ret |= LPC_CTL_1V2;
if(LPC_GPIO->PIN[0] & (1 << 20))
ret |= LPC_CTL_PCIE;
if((LPC_IOCON->PIO1_13 & 0x07) == 3)
ret |= LPC_CTL_UART;
if(LPC_GPIO->PIN[1] & (1 << 25))
ret |= LPC_CTL_RNG;
return ret;
}
void lpc_ctl_on(uint8_t mask) {
if(mask & LPC_CTL_5V && REFORM_MOTHERBOARD_REV < REFORM_MBREV_R1)
LPC_GPIO->SET[1] = (1 << 15);
else if(mask & LPC_CTL_5V)
LPC_GPIO->CLR[1] = (1 << 15);
if(mask & LPC_CTL_3V3 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_R1)
LPC_GPIO->SET[1] = (1 << 16);
else if(mask & LPC_CTL_3V3)
LPC_GPIO->CLR[1] = (1 << 16);
if(mask & LPC_CTL_USB)
LPC_GPIO->SET[1] = (1 << 31);
if(mask & LPC_CTL_AUX)
LPC_GPIO->SET[0] = (1 << 7);
if(mask & LPC_CTL_1V2)
LPC_GPIO->SET[1] = (1 << 19);
if(mask & LPC_CTL_PCIE)
LPC_GPIO->SET[0] = (1 << 20);
if(mask & LPC_CTL_UART)
LPC_IOCON->PIO1_13 |= 0x3;
if(mask & LPC_CTL_RNG)
enable_charge_current();
}
void lpc_ctl_off(uint8_t mask) {
if(mask & LPC_CTL_5V && REFORM_MOTHERBOARD_REV < REFORM_MBREV_R1)
LPC_GPIO->CLR[1] = (1 << 15);
else if(mask & LPC_CTL_5V)
LPC_GPIO->SET[1] = (1 << 15);
if(mask & LPC_CTL_3V3 && REFORM_MOTHERBOARD_REV < REFORM_MBREV_R1)
LPC_GPIO->CLR[1] = (1 << 16);
else if(mask & LPC_CTL_3V3)
LPC_GPIO->SET[1] = (1 << 16);
if(mask & LPC_CTL_USB)
LPC_GPIO->CLR[1] = (1 << 31);
if(mask & LPC_CTL_AUX)
LPC_GPIO->CLR[0] = (1 << 7);
if(mask & LPC_CTL_1V2)
LPC_GPIO->CLR[1] = (1 << 19);
if(mask & LPC_CTL_PCIE)
LPC_GPIO->CLR[0] = (1 << 20);
if(mask & LPC_CTL_UART)
LPC_IOCON->PIO1_13 &= ~0x7;
if(mask & LPC_CTL_RNG)
disable_charge_current();
}
void turn_som_power_on(void) {
LPC_GPIO->CLR[1] = (1 << 28); // hold in reset
lpc_ctl_off(LPC_CTL_USB | LPC_CTL_AUX | LPC_CTL_1V2 | LPC_CTL_PCIE);
lpc_ctl_on(LPC_CTL_USB | LPC_CTL_AUX | LPC_CTL_1V2 | LPC_CTL_PCIE | LPC_CTL_5V | LPC_CTL_3V3);
LPC_GPIO->SET[1] = (1 << 28); // release reset
......@@ -414,18 +529,7 @@ void turn_som_power_on(void) {
void turn_som_power_off(void) {
LPC_GPIO->CLR[1] = (1 << 28); // hold in reset
if (REFORM_MOTHERBOARD_REV >= REFORM_MBREV_R1) {
LPC_GPIO->SET[1] = (1 << 16); // 3v3 off
LPC_GPIO->SET[1] = (1 << 15); // 5v off
} else {
LPC_GPIO->CLR[1] = (1 << 16); // 3v3 off
LPC_GPIO->CLR[1] = (1 << 15); // 5v off
}
LPC_GPIO->CLR[0] = (1 << 20); // PCIe off
LPC_GPIO->CLR[1] = (1 << 19); // 1v2 off
LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+)
LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+)
lpc_ctl_off(LPC_CTL_USB | LPC_CTL_AUX | LPC_CTL_1V2 | LPC_CTL_PCIE | LPC_CTL_5V | LPC_CTL_3V3);
som_is_powered = 0;
}
......@@ -438,17 +542,11 @@ void reset_som(void) {
}
void turn_aux_power_on(void) {
LPC_GPIO->SET[0] = (1 << 20); // PCIe on
//LPC_GPIO->SET[1] = (1 << 19); // 1v2 on
//LPC_GPIO->SET[1] = (1 << 31); // USB 5v on (R1+)
//LPC_GPIO->SET[0] = (1 << 7); // AUX 3v3 on (R1+)
lpc_ctl_on(LPC_CTL_PCIE); // | LPC_CTL_1V2 | LPC_CTL_AUX | LPC_CTL_USB);
}
void turn_aux_power_off(void) {
LPC_GPIO->CLR[0] = (1 << 20); // PCIe off
//LPC_GPIO->CLR[1] = (1 << 19); // 1v2 off
//LPC_GPIO->CLR[1] = (1 << 31); // USB 5v off (R1+)
//LPC_GPIO->CLR[0] = (1 << 7); // AUX 3v3 off (R1+)
lpc_ctl_off(LPC_CTL_PCIE); // | LPC_CTL_1V2 | LPC_CTL_AUX | LPC_CTL_USB);
}
void brownout_setup(void) {
......@@ -510,10 +608,16 @@ void boardInit(void)
ssp1ClockSlow();
// SPI0 connected to the main SOM (they're controller)
NVIC_DisableIRQ(SSP0_IRQn);
ssp0Init();
ssp0ClockSlow();
// SPI chip select
// Missing SPI0 Init: SSEL0, IRQ
LPC_IOCON->PIO0_2 &= ~0x07; /* SPI SSEL I/O Config Type Input */
LPC_IOCON->PIO0_2 |= 0x01;
NVIC_EnableIRQ(SSP0_IRQn);
// Enable 3 passive interrupts: RORIM, RTIM and RXIM for async read
LPC_SSP0->IMSC |= (SSP_MIS_ROR | SSP_MIS_RT | SSP_MIS_RX);
// SPI1 chip select
LPC_GPIO->DIR[1] |= (1 << 23);
LPC_GPIO->SET[1] = (1 << 23); // active low
......@@ -807,10 +911,63 @@ void report_to_spi(void)
ssp0Send((uint8_t*)report, strlen(report));
}
void SSP0_IRQHandler(void)
{
uint8_t MISVal, RISVal, SRVal, buf[8] = {0}, i=0;
uint16_t ret = 0, mv=volts*1000.0, ma=current*1000.0;
MISVal = LPC_SSP0->MIS;
RISVal = LPC_SSP0->RIS;
SRVal = LPC_SSP0->SR;
LPC_SSP0->ICR &= 0x3;
buf[0] = REFORM_MOTHERBOARD_REV;
buf[1] = state;
buf[2] = mv >> 8;
buf[3] = mv & 0xff;
buf[4] = ma >> 8;
buf[5] = ma & 0xff;
buf[6] = capacity_percentage;
buf[7] = lpc_ctl_get();
if (RISVal & SSP_MIS_ROR) {
if(LPC_SSP0->SR & SSP0_SR_TNF_NOTFULL) {
ret = ssp0Xfer(buf, 8);
} else {
for(ret = 0; ret < 8; ret++) {
buf[ret] = LPC_SSP0->DR;
}
ret <<= 8;
}
}
else if (RISVal & SSP_MIS_RX) {
ret = ssp0Xfer(buf, 8);
}
else if (RISVal & SSP_MIS_TX) {
ret = ssp0Xfer(buf, 8);
} else {
uartSend((uint8_t*)"SPI Read Timeout\r\n", 18);
NVIC_ClearPendingIRQ(SSP0_IRQn);
return;
}
// 1234567890 12 3456789 21 234567 29 0 32 345678 42 345
sprintf(uartBuffer, "IRQ: MIS: %02X; RIS: %02X; SR: %02X:%02X; BUF[%04X]: ",
MISVal, RISVal, SRVal, (uint8_t)LPC_SSP0->SR, ret);
for(i=0; i<(ret>>8) || i<(uint8_t)ret; i++) {
sprintf(uartBuffer+45+i*3, "%02X ", buf[i]);
}
uartBuffer[45+i*3-1]=13;
uartBuffer[45+i*3]=10;
uartBuffer[45+i*3+1]=0;
uartSend((uint8_t*)uartBuffer, strlen(uartBuffer));
NVIC_ClearPendingIRQ(SSP0_IRQn);
return;
}
void WDT_IRQHandler(void)
{
// Disable WDT interrupt
NVIC_DisableIRQ(WDT_IRQn);
// Disable WDT interrupt
NVIC_DisableIRQ(WDT_IRQn);
NVIC_ClearPendingIRQ(WDT_IRQn);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment