mirror of
https://github.com/garrettsworkshop/ROMBUSDriver.git
synced 2025-02-17 20:30:25 +00:00
165 lines
5.3 KiB
C
165 lines
5.3 KiB
C
#include "spi.h"
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
/* Platform dependent macros and functions needed to be modified */
|
|
/*-------------------------------------------------------------------------*/
|
|
#define CS_H() bset(P0) /* Set MMC CS "high" */
|
|
#define CS_L() bclr(P0) /* Set MMC CS "low" */
|
|
#define CK_H() bset(P1) /* Set MMC SCLK "high" */
|
|
#define CK_L() bclr(P1) /* Set MMC SCLK "low" */
|
|
#define DI_H() bset(P2) /* Set MMC DI "high" */
|
|
#define DI_L() bclr(P2) /* Set MMC DI "low" */
|
|
#define DO btest(P3) /* Test MMC DO (high:true, low:false) */
|
|
|
|
|
|
// Command listing
|
|
/* T16: Transfer 16-bit
|
|
* First, the 16-bit value encoded in the address bits A[17:2] is latched.
|
|
* The data output mux is set to the current RXR and the cycle completes.
|
|
* Shortly after /AS rises, the SPI transfer engine begins
|
|
* transferring the latched value.
|
|
*/
|
|
/* T16S: Transfer 16-bit Swapped
|
|
* Same as T16L but read data is byte-swapped.
|
|
*/
|
|
/* MERT: Measure Elapsed time and Reset Timer
|
|
* The elapsed time since the last MERT command is returned in D[31:24]
|
|
* and the timer is reset.
|
|
*/
|
|
/* SKIP1: Skip Clocks with MOSI "1"
|
|
*
|
|
*/
|
|
/* SKIP0: Skip Clocks with MOSI "0"
|
|
*
|
|
*/
|
|
/* T8S: Transfer 8-bit Swapped
|
|
* Same as T8 but read data is byte-swapped.
|
|
*/
|
|
/* T8: Transfer 8-bit
|
|
* First, the 8-bit value encoded in the address bits A[9:2] is latched.
|
|
* The data output mux is set to the current RXR and the cycle completes.
|
|
* Shortly after /AS rises, the SPI transfer engine begins
|
|
* transferring the latched value.
|
|
*/
|
|
/* WRC: Write Command
|
|
* The command encoded in address bits A[9:2] is sent to the command target
|
|
* corresponding to the address bits A[15:10].
|
|
* Command targets:
|
|
* $00 - Set bitbang
|
|
* A[2] - SCS value
|
|
*/
|
|
/* RDRXR: Read Receive Data Register
|
|
* The the current RXR is returned in D[31:16] and the cycle completes.
|
|
*/
|
|
/* RDRXRS: Read Receive Data Register Swapped
|
|
* Same as RDRXR but read data is byte-swapped.
|
|
*/
|
|
/* MAGIC: Write Command
|
|
* Write sequence $FF $00 $55 $AA $C1 $AD
|
|
* to enable registers at $40890000-$4097FFFF.
|
|
* Write anything else to disable them.
|
|
* Always reads 0xC1AD
|
|
*/
|
|
|
|
// SPI controller address map:
|
|
// 40940000-4097FFFF (256 kB, D[31:16]) T16S. Write transfer data in A[17:2].
|
|
// 40900000-4093FFFF (256 kB, D[31:16]) T16. Write transfer data in A[17:2].
|
|
// 408C0000-408FFFFF (320 kB) reserved
|
|
// 408A0000-408AFFFF ( 64 kB, D[31:24]) WRC. Write port address in A[15:10] and data in A[9:2].
|
|
// 40891C00-4089FFFF ( 55 kB) reserved
|
|
// 40892000-408923FF ( 1 kB, D[31:24]) MERT.
|
|
// 40891C00-40891FFF ( 1 kB) SKIP1. Write bytes to skip in A[9:2].
|
|
// 40891800-40891BFF ( 1 kB) SKIP0. Write bytes to skip in A[9:2].
|
|
// 40891400-408917FF ( 1 kB, D[31:16]) T8S. Write transfer data in A[9:2].
|
|
// 40891000-408913FF ( 1 kB, D[31:16]) T8. Write transfer data in A[9:2].
|
|
// 40890C00-40890FFF ( 1 kB, D[31:16]) RDRXRS.
|
|
// 40890800-40890BFF ( 1 kB, D[31:16]) RDRXR.
|
|
// 40890400-408907FF ( 1 kB) reserved
|
|
// 40890000-408903FF ( 1 kB, D[31:24]) MAGIC. Write magic numbers in A[9:2].
|
|
// 40880000-408FFFFF ( 64 kB, D[31:00]) ROMBUS driver data
|
|
|
|
#define RB_T16S(x) (*(volatile int*) (0x40940000 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_T16(x) (*(volatile int*) (0x40900000 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_RDS(a) (*(volatile char*) (0x408B0000 + ((a && 0x003F)<<10)) )
|
|
#define RB_WRC(a,d) (*(volatile char*) (0x408A0000 + ((a && 0x003F)<<10)
|
|
+ ((d && 0x00FF)<<02)) )
|
|
#define RB_MERT(x) (*(volatile char*) (0x40892000 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_SKIP1(n) (*(volatile char*) (0x40891C00 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_SKIP0(n) (*(volatile char*) (0x40891800 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_T8S(x) (*(volatile int*) (0x40891400 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_T8(x) (*(volatile int*) (0x40891000 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_RDRXRS (*(volatile int*) (0x40890C00 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_RDRXR (*(volatile int*) (0x40890800 + ((x && 0xFFFF)<<02)) )
|
|
#define RB_WRMOSI(x) (*(volatile char*) (0x40890400 + ((x && 0x0001)<<02)) )
|
|
#define RB_MAGIC(x) (*(volatile char*) (0x40890000 + ((x && 0xFFFF)<<02)) )
|
|
|
|
#define SPI_GET_MISO(d) (d & 1)
|
|
|
|
void spi_select() {
|
|
ret = *SPI_CMD_SEL0;
|
|
ret = *SPI_CMD_SEL1;
|
|
ret = *SPI_CMD_SEL2;
|
|
ret = *SPI_CMD_SEL3;
|
|
}
|
|
void spi_deselect() {
|
|
ret = *SPI_CMD_DES0;
|
|
ret = *SPI_CMD_DES1;
|
|
ret = *SPI_CMD_DES2;
|
|
ret = *SPI_CMD_DES3;
|
|
}
|
|
|
|
void spi_tx_slow(char d) {
|
|
for (int i = 0; i < 8; i++) {
|
|
*SPI_CMD_BBA((0 & 0x02) | (d & 0x01));
|
|
*SPI_CMD_BBA((1 & 0x02) | (d & 0x01));
|
|
d >>= 1;
|
|
}
|
|
*SPI_CMD_BBA((0 & 0x02) | (0 & 0x01));
|
|
}
|
|
|
|
char spi_rx_slow() {
|
|
char ret = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
|
|
ret = (ret << 1) + (*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)) & 1);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void spi_skip_slow(int n) {
|
|
while (n-- > 0) {
|
|
for (int i = 0; i < 8; i++) {
|
|
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
|
|
}
|
|
}
|
|
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
|
|
}
|
|
|
|
void spi_tx_8(char d) {
|
|
*SPI_CMD_SH8(d);
|
|
}
|
|
|
|
char spi_rx_8() {
|
|
*SPI_CMD_SH8(0xFF);
|
|
return *SPI_CMD_RD & 0xFF;
|
|
}
|
|
|
|
void spi_tx_16(int d) {
|
|
*SPI_CMD_SH16(d);
|
|
}
|
|
|
|
int spi_rx_16() {
|
|
*SPI_CMD_SH16(0xFFFF);
|
|
return *SPI_CMD_RD & 0xFFFF;
|
|
}
|
|
|
|
void spi_skip(int n) {
|
|
while (n-- > 0) {
|
|
for (int i = 0; i < 8; i++) {
|
|
*SPI_CMD_SH8(0xFF);
|
|
}
|
|
}
|
|
}
|