refactored SPI and CODEC drivers, getting ready to move all SPI ops to the ARM11

This commit is contained in:
Wolfvak 2019-04-21 20:30:28 -03:00 committed by d0k3
parent 1b04ca4fa1
commit b52bf3b9a5
3 changed files with 87 additions and 125 deletions

View File

@ -25,32 +25,16 @@
#define CPAD_FACTOR (150) #define CPAD_FACTOR (150)
/* SPI stuff */ /* SPI stuff */
static void CODEC_DualTX(u8 *tx0, u8 len0, u8 *tx1, u8 len1) static void CODEC_WriteRead(u32 *txb, u8 txl, u32 *rxb, u8 rxl)
{ {
SPI_XferInfo xfers[2]; SPI_XferInfo xfers[2];
xfers[0].buf = (u32*)tx0; xfers[0].buf = txb;
xfers[0].len = len0; xfers[0].len = txl;
xfers[0].read = false; xfers[0].read = false;
xfers[1].buf = (u32*)tx1; xfers[1].buf = rxb;
xfers[1].len = len1; xfers[1].len = rxl;
xfers[1].read = false;
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
}
static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len,
u8 *rx_buf, u8 rx_len)
{
SPI_XferInfo xfers[2];
xfers[0].buf = (u32*)tx_buf;
xfers[0].len = tx_len;
xfers[0].read = false;
xfers[1].buf = (u32*)rx_buf;
xfers[1].len = rx_len;
xfers[1].read = true; xfers[1].read = true;
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2); SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
@ -58,60 +42,49 @@ static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len,
static void CODEC_RegSelect(u8 reg) static void CODEC_RegSelect(u8 reg)
{ {
u8 buffer1[4]; SPI_XferInfo xfer;
u8 buffer2[0x40]; u32 cmd;
buffer1[0] = 0; cmd = reg << 8;
buffer2[0] = reg;
CODEC_DualTX(buffer1, 1, buffer2, 1); xfer.buf = &cmd;
xfer.len = 2;
xfer.read = false;
SPI_DoXfer(CODEC_SPI_DEV, &xfer, 1);
} }
static u8 CODEC_RegRead(u8 offset) static u8 CODEC_RegRead(u8 reg)
{ {
u8 buffer_wr[8]; u32 cmd, ret;
u8 buffer_rd[0x40]; cmd = (reg << 1) | 1;
CODEC_WriteRead(&cmd, 1, &ret, 1);
buffer_wr[0] = 1 | (offset << 1); return ret;
CODEC_WriteRead(buffer_wr, 1, buffer_rd, 1);
return buffer_rd[0];
} }
static void CODEC_RegWrite(u8 reg, u8 val) static void CODEC_RegWrite(u8 reg, u8 val)
{ {
u8 buffer1[8]; SPI_XferInfo xfer;
u8 buffer2[0x40]; u32 cmd;
buffer1[0] = (reg << 1); // Write cmd = (val << 8) | (reg << 1);
buffer2[0] = val;
CODEC_DualTX(buffer1, 1, buffer2, 1); xfer.buf = &cmd;
xfer.len = 2;
xfer.read = false;
SPI_DoXfer(CODEC_SPI_DEV, &xfer, 1);
} }
static void CODEC_RegReadBuf(u8 offset, void *buffer, u8 size) static void CODEC_RegReadBuf(u8 reg, u32 *out, u8 size)
{ {
u8 buffer_wr[0x10]; u32 cmd = (reg << 1) | 1;
CODEC_WriteRead(&cmd, 1, out, size);
buffer_wr[0] = 1 | (offset << 1);
CODEC_WriteRead(buffer_wr, 1, buffer, size);
} }
static void CODEC_RegMask(u8 offset, u8 mask0, u8 mask1) static void CODEC_RegMask(u8 reg, u8 mask0, u8 mask1)
{ {
u8 buffer1[4]; CODEC_RegWrite(reg, (CODEC_RegRead(reg) & ~mask1) | (mask0 & mask1));
u8 buffer2[0x40];
buffer1[0] = 1 | (offset << 1);
CODEC_WriteRead(buffer1, 1, buffer2, 1);
buffer1[0] = offset << 1;
buffer2[0] = (buffer2[0] & ~mask1) | (mask0 & mask1);
CODEC_DualTX(buffer1, 1, buffer2, 1);
} }
void CODEC_Init(void) void CODEC_Init(void)
@ -147,7 +120,7 @@ void CODEC_Init(void)
CODEC_RegMask(0x25, 0x10, 0x3C); CODEC_RegMask(0x25, 0x10, 0x3C);
} }
static void CODEC_GetRawData(u8 *buffer) void CODEC_GetRawData(u32 *buffer)
{ {
CODEC_RegSelect(0x67); CODEC_RegSelect(0x67);
CODEC_RegRead(0x26); CODEC_RegRead(0x26);
@ -157,11 +130,12 @@ static void CODEC_GetRawData(u8 *buffer)
void CODEC_Get(CODEC_Input *input) void CODEC_Get(CODEC_Input *input)
{ {
u8 raw_data[0x34]; u32 raw_data_buf[0x34 / 4];
u8 *raw_data = (u8*)raw_data_buf;
s16 cpad_x, cpad_y; s16 cpad_x, cpad_y;
bool ts_pressed; bool ts_pressed;
CODEC_GetRawData(raw_data); CODEC_GetRawData(raw_data_buf);
cpad_x = ((raw_data[0x24] << 8 | raw_data[0x25]) & 0xFFF) - 2048; cpad_x = ((raw_data[0x24] << 8 | raw_data[0x25]) & 0xFFF) - 2048;
cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048; cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048;

View File

@ -9,4 +9,5 @@ typedef struct {
void CODEC_Init(void); void CODEC_Init(void);
void CODEC_GetRawData(u32 *buffer);
void CODEC_Get(CODEC_Input *input); void CODEC_Get(CODEC_Input *input);

View File

@ -15,83 +15,73 @@
#include "hw/spi.h" #include "hw/spi.h"
#define CFG_SPI_CNT ((vu32*)0x101401C0) #define REG_CFG_SPI_CNT ((vu16*)0x101401C0)
// TODO: CURRENTLY HARDCODED FOR DEVICE 3 (TOUCHSCREEN) #define REG_SPI(bus, reg) (*((vu32*)((bus) + (reg))))
// IF ANY OTHER DEVICES ARE TO BE USED, ANOTHER BUS MUST
// BE ACCESSED, CHECK 3dbrew.org/wiki/SPI_{Registers, Services}
static const u32 SPI_Buses[] = { 0x10142800 };
#define REG_SPI(b, n) (*(vu32*)(SPI_Buses[b] + (n)))
#define REG_SPI_CNT REG_SPI(0, 0x00) #define REG_SPI_BUS0 (0x10160800)
#define REG_SPI_DONE REG_SPI(0, 0x04) #define REG_SPI_BUS1 (0x10142800)
#define REG_SPI_BLKLEN REG_SPI(0, 0x08) #define REG_SPI_BUS2 (0x10143800)
#define REG_SPI_FIFO REG_SPI(0, 0x0C)
#define REG_SPI_STATUS REG_SPI(0, 0x10)
#define SPI_CNT_BUSY BIT(15) #define REG_SPI_CONTROL 0x00
#define SPI_CNT_START BIT(15) #define REG_SPI_DONE 0x04
#define REG_SPI_BLKLEN 0x08
#define REG_SPI_FIFO 0x0C
#define REG_SPI_STAT 0x10
#define SPI_CNT_READ (0) #define SPI_CONTROL_RATE(n) (n)
#define SPI_CNT_WRITE BIT(13) #define SPI_CONTROL_CS(n) ((n) << 6)
#define SPI_DIRECTION_READ (0)
#define SPI_CNT_RATE(n) (n) #define SPI_DIRECTION_WRITE BIT(13)
#define SPI_CNT_CS(n) ((n) << 6) #define SPI_CONTROL_BUSY BIT(15)
#define SPI_CONTROL_START BIT(15)
#define SPI_STAT_BUSY BIT(0) #define SPI_STAT_BUSY BIT(0)
#define SPI_FIFO_WIDTH (32) #define SPI_FIFO_WIDTH (32)
static u8 SPI_GetDevSelect(u32 dev) static struct {
u32 bus;
u32 regcfg;
} SPI_Devices[] = {
{REG_SPI_BUS0, SPI_CONTROL_RATE(2) | SPI_CONTROL_CS(0)}, // device 0
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(1)},
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(2)},
{REG_SPI_BUS1, SPI_CONTROL_RATE(5) | SPI_CONTROL_CS(0)},
// TODO: complete this table
};
static void SPI_WaitBusy(u32 bus)
{ {
static const u8 SPI_DevSelect[] = { 0, 1, 2, 0, 1, 2 }; while(REG_SPI(bus, REG_SPI_CONTROL) & SPI_CONTROL_BUSY);
if (dev < countof(SPI_DevSelect)) {
return SPI_DevSelect[dev];
} else {
return 0;
}
} }
static u8 SPI_GetDevBaudrate(u32 dev) static void SPI_WaitFIFO(u32 bus)
{ {
static const u8 SPI_BaudRates[] = { 2, 0, 0, 5 }; while(REG_SPI(bus, REG_SPI_STAT) & SPI_STAT_BUSY);
if (dev < countof(SPI_BaudRates)) {
return SPI_BaudRates[dev];
} else {
return 0;
}
} }
static void SPI_WaitBusy(void) static void SPI_Done(u32 bus)
{ {
while(REG_SPI_CNT & SPI_CNT_BUSY); REG_SPI(bus, REG_SPI_DONE) = 0;
} }
static void SPI_WaitFIFO(void) static void SPI_SingleXfer(u32 reg, u32 bus, u32 *buffer, u32 len, bool read)
{
while(REG_SPI_STATUS & SPI_STAT_BUSY);
}
static void SPI_Done(void)
{
REG_SPI_DONE = 0;
}
static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len)
{ {
u32 pos = 0; u32 pos = 0;
REG_SPI_BLKLEN = len; REG_SPI(bus, REG_SPI_BLKLEN) = len;
REG_SPI_CNT = reg | (read ? SPI_CNT_READ : SPI_CNT_WRITE) | SPI_CNT_START; REG_SPI(bus, REG_SPI_CONTROL) = reg |
(read ? SPI_DIRECTION_READ : SPI_DIRECTION_WRITE) | SPI_CONTROL_START;
do { do {
if ((pos % SPI_FIFO_WIDTH) == 0) if ((pos % SPI_FIFO_WIDTH) == 0)
SPI_WaitFIFO(); SPI_WaitFIFO(bus);
if (read) { if (read) {
buffer[pos / 4] = REG_SPI_FIFO; buffer[pos / 4] = REG_SPI(bus, REG_SPI_FIFO);
} else { } else {
REG_SPI_FIFO = buffer[pos / 4]; REG_SPI(bus, REG_SPI_FIFO) = buffer[pos / 4];
} }
pos += 4; pos += 4;
@ -100,30 +90,27 @@ static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len)
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt) int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt)
{ {
u32 dev_cfg; u32 bus;
int baud, cs; u32 dev_reg;
baud = SPI_GetDevBaudrate(dev); bus = SPI_Devices[dev].bus;
cs = SPI_GetDevSelect(dev); dev_reg = SPI_Devices[dev].regcfg;
dev_cfg = SPI_CNT_RATE(baud) | SPI_CNT_CS(cs);
for (u32 i = 0; i < xfer_cnt; i++) { for (u32 i = 0; i < xfer_cnt; i++) {
SPI_XferInfo *xfer = &xfers[i]; SPI_XferInfo *xfer = &xfers[i];
SPI_WaitBusy(); SPI_WaitBusy(bus);
SPI_SingleXfer(dev_cfg, xfer->read, xfer->buf, xfer->len); SPI_SingleXfer(dev_reg, bus, xfer->buf, xfer->len, xfer->read);
} }
SPI_WaitBusy(); SPI_WaitBusy(bus);
SPI_Done(); SPI_Done(bus);
return 0; return 0;
} }
void SPI_Init(void) void SPI_Init(void)
{ {
// Hack: here all registers should be set to the "new" mode // This cuts off access from the old SPI
// but GM9 uses the old interface to access NVRAM // interface used during the NDS days
// as such, only the bus used by CODEC will be set to new *REG_CFG_SPI_CNT = 7;
// *CFG_SPI_CNT = 7;
*CFG_SPI_CNT = BIT(1);
} }