MC3302_SDK_V1.1.9_202507281.../bsp/ramboot/drivers/spi/spi-mc.c
2025-11-11 12:08:31 +08:00

366 lines
7.9 KiB
C
Executable File

#include <common.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <mach/spic.h>
#include <mach/dma.h>
#include <mach/uart_drv.h>
struct spi_cfg {
u8 *tx_buf;
u8 *rx_buf;
u32 rx_xfer_len;
u32 tx_xfer_len;
};
#define SPI_FIFO_DEPTH (128)
#define SPI_RX_ONE_TIME (128)
#define OFFSET_SPI_CTRL0 (0x00)
#define OFFSET_SPI_CTRL1 (0x04)
#define OFFSET_SPI_SSIENR (0x08)
#define OFFSET_SPI_MWCR (0x0c)
#define OFFSET_SPI_SER (0x10)
#define OFFSET_SPI_BAUD (0x14)
#define OFFSET_SPI_TXFTLR (0x18)
#define OFFSET_SPI_RXFTLR (0x1c)
#define OFFSET_SPI_TXFLR (0x20)
#define OFFSET_SPI_RXFLR (0x24)
#define OFFSET_SPI_SR (0x28)
#define OFFSET_SPI_IMR (0x2c)
#define OFFSET_SPI_ISR (0x30)
#define OFFSET_SPI_RISR (0x34)
#define OFFSET_SPI_TXOICR (0x38)
#define OFFSET_SPI_RXOICR (0x3c)
#define OFFSET_SPI_RXUICR (0x40)
#define OFFSET_SPI_MSTICR (0x44)
#define OFFSET_SPI_ICR (0x48)
#define OFFSET_SPI_DMACR (0x4c)
#define OFFSET_SPI_DMATDLR (0x50)
#define OFFSET_SPI_DMARDLR (0x54)
#define OFFSET_SPI_IDR (0x58)
#define OFFSET_SPI_SSI_COMPVER (0x5c)
#define OFFSET_SPI_DR (0x60)
#define OFFSET_SPI_RX_SAMPLE_DELAY (0xf0)
struct spi_cfg spi;
void molchip_spi_clk_enable(void)
{
/* gpio en */
setbits_le32(REG_CEN_PERI_APB_CLK_CTRL, CKG_APB_GPIO_EN);
/* SPI0_CS --> GPIO8_3*/
setbits_le32(0xB070004, BIT(3));
setbits_le32(0xB070008, BIT(3));
setbits_le32(0xB070000, BIT(3));
/* 13*13 SPI1_CS --> GPIO10_0*/
setbits_le32(0xB090004, BIT(0));
setbits_le32(0xB090008, BIT(0));
setbits_le32(0xB090000, BIT(0));
/* 11*11 SPI1_CS --> GPIO4_7*/
setbits_le32(0xB030004, BIT(7));
setbits_le32(0xB030008, BIT(7));
setbits_le32(0xB030000, BIT(7));
setbits_le32(REG_CEN_PERI_CLK_CTRL, CKG_SPI0_EN | CKG_SPI1_EN);
setbits_le32(REG_CEN_PERI_APB_CLK_CTRL, CKG_APB_SPI0_EN | CKG_APB_SPI1_EN);
}
void reset_spi(void)
{
u32 val,i;
/* SPI RESET */
val = __raw_readl(REG_AP_PERI_SOFT_RST0);
val |= (SPI0_SOFT_RST | SPI1_SOFT_RST);
__raw_writel(val,REG_AP_PERI_SOFT_RST0);
for(i=0;i<0x1000;i++);
val = __raw_readl(REG_AP_PERI_SOFT_RST0);
val &= ~SPI0_SOFT_RST;
val &= ~SPI1_SOFT_RST;
__raw_writel(val,REG_AP_PERI_SOFT_RST0);
}
void mc_spi_enable(uint base, u32 enable)
{
u32 val;
if(enable)
val = 1;
else
val = 0;
spi_writel(base + OFFSET_SPI_SSIENR,SPI_BF(SER,val));
}
void mc_spi_set_polarity(uint base, u32 polarity)
{
u32 val;
val = spi_readl(base + OFFSET_SPI_CTRL0);
val = SPI_BFINS(SCPOL,polarity,val);
spi_writel(base + OFFSET_SPI_CTRL0,val);
}
void mc_spi_set_phase(uint base, u32 phase)
{
u32 val;
val = spi_readl(base + OFFSET_SPI_CTRL0);
val = SPI_BFINS(SCPH,phase,val);
spi_writel(base + OFFSET_SPI_CTRL0, val);
}
void mc_spi_set_frame_format(uint base, u32 format)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_CTRL0);
val = SPI_BFINS(FRF,format,val);
spi_writel(base + OFFSET_SPI_CTRL0, val);
}
void mc_spi_set_data_size(uint base, u32 size)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_CTRL0);
val = SPI_BFINS(DFS,size,val);
spi_writel(base + OFFSET_SPI_CTRL0, val);
}
void mc_spi_set_transfer_mode(uint base, u32 mode)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_CTRL0);
val = SPI_BFINS(TMOD,mode,val);
spi_writel(base + OFFSET_SPI_CTRL0, val);
}
void mc_spi_set_read_data_num(uint base, u32 num)
{
u32 val = 0;
val = SPI_BF(NDF, num -1);
spi_writel(base + OFFSET_SPI_CTRL1, val);
}
void mc_spi_set_baudrate(uint base, u32 baudrate)
{
u32 val = 0;
val = SPI_BF(SCKDV, baudrate);
spi_writel(base + OFFSET_SPI_BAUD, val);
}
void mc_spi_disable_irq(uint base, u32 irq)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_IMR);
val &= ~irq;
spi_writel(base + OFFSET_SPI_IMR, val);
}
void mc_spi_enable_irq(uint base, u32 irq)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_IMR);
val |= irq;
spi_writel(base + OFFSET_SPI_IMR, val);
}
u32 mc_spi_get_status(uint base)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_SR);
return val;
}
void mc_spi_enable_port(uint base, u32 port)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_SER);
port = 1 << port;
val = SPI_BFINS(SSIEN,port,val);
spi_writel(base + OFFSET_SPI_SER, val);
}
void mc_spi_disable_port(uint base, u32 port)
{
u32 val = 0;
val = spi_readl(base + OFFSET_SPI_SER);
port = 0 << port;
val = SPI_BFINS(SSIEN,port,val);
spi_writel(base + OFFSET_SPI_SER,val);
}
void mc_spi_rx_sample_delay(uint base, u32 delay)
{
delay = delay & 0xff;
spi_writel(base + OFFSET_SPI_RX_SAMPLE_DELAY,delay);
}
static inline u32 tx_max(u32 base)
{
u32 tx_room, rxtx_gap;
tx_room = SPI_FIFO_DEPTH - __raw_readl(base + OFFSET_SPI_TXFLR);
rxtx_gap = SPI_FIFO_DEPTH - (spi.rx_xfer_len - spi.tx_xfer_len);
return min3(spi.tx_xfer_len, tx_room, rxtx_gap);
}
static inline u32 rx_max(u32 base)
{
return min(spi.rx_xfer_len, __raw_readl(base + OFFSET_SPI_RXFLR));
}
static void dw_writer(u32 base)
{
u32 max = tx_max(base);
u32 data_reg = base + OFFSET_SPI_DR;
while (max--) {
if (spi.tx_buf)
__raw_writel(*spi.tx_buf++, data_reg);
else
__raw_writel(0xff, data_reg);
--spi.tx_xfer_len;
}
}
static void dw_reader(u32 base)
{
u32 max = rx_max(base);
u32 data_reg = base + OFFSET_SPI_DR;
while (max--) {
if (spi.rx_buf)
*spi.rx_buf++ = __raw_readl(data_reg);
--spi.rx_xfer_len;
}
}
void mc_spi_xfer_set_cs(u32 base, u8 enable)
{
switch (enable)
{
case false:
if (base == REG_SPI0_BASE){
clrbits_le32(0xB070000, BIT(3));
} else if (base == REG_SPI1_BASE) {
clrbits_le32(0xB090000, BIT(0));//13*13 board
clrbits_le32(0xB030000, BIT(7));//11*11 board
}
break;
case true:
if (base == REG_SPI0_BASE){
setbits_le32(0xB070000, BIT(3));
} else if (base == REG_SPI1_BASE) {
setbits_le32(0xB090000, BIT(0));//13*13 board
setbits_le32(0xB030000, BIT(7));//11*11 board
}
break;
default:
break;
}
}
void mc_spi_set_slave_mode(u32 base, u8 is_slave)
{
switch (is_slave)
{
case true:
if (base == REG_SPI0_BASE)
setbits_le32(0xC0000C8, BIT(0));
else if (base == REG_SPI1_BASE)
setbits_le32(0xC0000C8, BIT(1));
break;
case false:
clrbits_le32(0xC0000C8, BIT(0) | BIT(1));
break;
default:
break;
}
}
int mc_spi_xfer(u32 base, u8 *tx_buf, u8 *rx_buf, u32 len, u8 is_slave)
{
u32 i;
spi.tx_buf = tx_buf;
spi.rx_buf = rx_buf;
spi.rx_xfer_len = spi.tx_xfer_len = len;
mc_spi_set_slave_mode(base,is_slave);
mc_spi_xfer_set_cs(base,false);
mc_spi_enable_port(base,SPI_PORT0);
mc_spi_enable(base,SPI_ENABLE);
do {
dw_writer(base);
for(i=0;i<100000;i++);
dw_reader(base);
} while (spi.rx_xfer_len);
mc_spi_xfer_set_cs(base,true);
if (is_slave) {
is_slave = !is_slave;
mc_spi_set_slave_mode(base,is_slave);
}
return 0;
}
void mc_spi_init(u32 base)
{
/* disable spi */
mc_spi_enable(base,SPI_DISABLE);
/* frame format */
mc_spi_set_frame_format(base,SPI_FORMAT_MOTO);
/* spi polarty */
mc_spi_set_polarity(base,SPI_POLARITY_LOW);
/* spi phase */
mc_spi_set_phase(base,SPI_PHASE_SCLK_TOGGLE_MIDDLE);
/* spi transfer mode */
mc_spi_set_transfer_mode(base,SPI_TX_RX_MODE);
/* transfer data size */
mc_spi_set_data_size(base,SPI_DATA_SIZE_8BIT);
/* baudrate */
mc_spi_set_baudrate(base,0x30);//0x30-->500k 0xf0-->100k
/* mask intr */
mc_spi_disable_irq(base,0x3f);
/* enable cs */
mc_spi_enable_port(base,SPI_PORT0);
mc_spi_enable(base,SPI_ENABLE);
}
void mc_spi_pinmux_cfg(void)
{
__raw_writel(0x2, 0x10200160);//SPI0_CLK
__raw_writel(0x2, 0x10200164);//SPI0_DO
__raw_writel(0x2, 0x10200168);//SPI0_DI
__raw_writel(0x1, 0x1020016C);//SPI0_CSN0 GPIO8_3
/* 13*13 */
__raw_writel(0x7, 0x102001a4);
__raw_writel(0x1, 0x102001a8);//SPI1_CSN0 GPIO10_0
__raw_writel(0x7, 0x102001ac);
__raw_writel(0x7, 0x102001b0);
/* 11*11 */
__raw_writel(0x6, 0x102000a8);
__raw_writel(0x1, 0x102000ac);//SPI1_CSN0 GPIO4_7
__raw_writel(0x6, 0x102000b0);
__raw_writel(0x6, 0x102000b4);
}
void board_spi_init(void)
{
molchip_spi_clk_enable();
reset_spi();
mc_spi_pinmux_cfg();
mc_spi_init(REG_SPI0_BASE);
mc_spi_init(REG_SPI1_BASE);
}