Browse Source

add ls2k spi driver.

Change-Id: Id1dfb78353a4b7cbe8801000e19b308677e18b7d
Signed-off-by: QiaoChong <qiaochong@loongson.cn>
master
QiaoChong 8 years ago
committed by Chong Qiao
parent
commit
40190b2b36
  1. 310
      Targets/LS2K/dev/spi_w.c

310
Targets/LS2K/dev/spi_w.c

@ -7,6 +7,10 @@
#include <pmon.h>
//#include <include/types.h>
#include <pflash.h>
#include <linux/spi.h>
#include "spinand_mt29f.h"
#include "spinand_lld.h"
#include "m25p80.h"
#define SPI_BASE 0x1fff0220
#define PMON_ADDR 0xa1000000
@ -14,6 +18,7 @@
#define SPCR 0x0
#define SPSR 0x1
#define FIFO 0x2
#define TXFIFO 0x2
#define RXFIFO 0x2
#define SPER 0x3
@ -34,14 +39,20 @@ void spi_initw()
{
SET_SPI(SPSR, 0xc0);
SET_SPI(PARAM, 0x40); //espr:0100
SET_SPI(SPER, 0x05); //spre:01
SET_SPI(PARAM2,0x01);
#ifdef LS2H_SPI_HIGHSPEED
SET_SPI(SPER, 0x04); //spre:01
SET_SPI(SPCR, 0x51);
#else
SET_SPI(SPER, 0x05); //spre:01
SET_SPI(SPCR, 0x50);
#endif
SET_SPI(SOFTCS,0xff);
}
void spi_initr()
{
SET_SPI(PARAM, 0x47); //espr:0100
SET_SPI(PARAM, 0x41); //espr:0100
}
@ -53,7 +64,7 @@ int read_sr(void)
{
int val;
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
SET_SPI(TXFIFO,0x05);
while((GET_SPI(SPSR))&RFEMPTY);
@ -64,11 +75,32 @@ int read_sr(void)
val = GET_SPI(RXFIFO);
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
return val;
}
void wait_sr(void)
{
int val;
SET_SPI(SOFTCS,0x01|0xee);
SET_SPI(TXFIFO,0x05);
while((GET_SPI(SPSR))&RFEMPTY);
val = GET_SPI(RXFIFO);
do{
SET_SPI(TXFIFO,0x00);
while((GET_SPI(SPSR)&RFEMPTY) == RFEMPTY);
val = GET_SPI(RXFIFO);
} while(val & 1);
SET_SPI(SOFTCS,0x11|0xee);
return val;
}
////////////set write enable//////////
int set_wren(void)
@ -81,14 +113,14 @@ int set_wren(void)
res = read_sr();
}
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
SET_SPI(TXFIFO,0x6);
while((GET_SPI(SPSR))&RFEMPTY == RFEMPTY){
}
GET_SPI(RXFIFO);
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
return 1;
}
@ -106,7 +138,7 @@ int write_sr(char val)
res = read_sr();
}
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
SET_SPI(TXFIFO,0x01);
while((GET_SPI(SPSR))&RFEMPTY == RFEMPTY){
@ -119,7 +151,7 @@ int write_sr(char val)
}
GET_SPI(RXFIFO);
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
return 1;
@ -137,7 +169,7 @@ int erase_all(void)
{
res = read_sr();
}
SET_SPI(SOFTCS,0x1);
SET_SPI(SOFTCS,0x1|0xee);
SET_SPI(TXFIFO,0xC7);
while((GET_SPI(SPSR))&RFEMPTY == RFEMPTY){
@ -145,7 +177,7 @@ int erase_all(void)
}
GET_SPI(RXFIFO);
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
while(i++){
if(read_sr() & 0x1 == 0x1){
if(i % 10000 == 0)
@ -170,7 +202,7 @@ void spi_read_id(void)
val = read_sr();
}
/*CE 0*/
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
/*READ ID CMD*/
SET_SPI(TXFIFO,0x9f);
while((GET_SPI(SPSR))&RFEMPTY == RFEMPTY){
@ -203,7 +235,7 @@ void spi_read_id(void)
printf("Device ID-memory_capacity: %x\n",val);
/*CE 1*/
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
}
@ -221,7 +253,7 @@ void spi_write_byte(unsigned int addr,unsigned char data)
{
val = read_sr();
}
SET_SPI(SOFTCS,0x01);/*CE 0*/
SET_SPI(SOFTCS,0x01|0xee);/*CE 0*/
SET_SPI(TXFIFO,0x2);/*byte_program */
while((GET_SPI(SPSR))&RFEMPTY == RFEMPTY){
@ -258,7 +290,7 @@ void spi_write_byte(unsigned int addr,unsigned char data)
val = GET_SPI(RXFIFO);
/*CE 1*/
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
}
int write_pmon_byte(int argc,char ** argv)
@ -442,7 +474,7 @@ int spi_erase_area(unsigned int saddr,unsigned int eaddr,unsigned sectorsize)
for(addr=saddr;addr<eaddr;addr+=sectorsize)
{
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
set_wren();
@ -452,7 +484,7 @@ int spi_erase_area(unsigned int saddr,unsigned int eaddr,unsigned sectorsize)
set_wren();
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
/*
* 0x20 erase 4kbyte of memory array
@ -476,16 +508,83 @@ int spi_erase_area(unsigned int saddr,unsigned int eaddr,unsigned sectorsize)
while((GET_SPI(SPSR))&RFEMPTY);
GET_SPI(RXFIFO);
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
while(read_sr()&1);
}
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
delay(10);
return 0;
}
int spi_write_bytes(unsigned int addr,unsigned char *buffer, int size)
{
int i;
/*byte_program,CE 0, cmd 0x2,addr2,addr1,addr0,data in,CE 1*/
unsigned char addr2,addr1,addr0;
unsigned char val;
addr2 = (addr & 0xff0000)>>16;
addr1 = (addr & 0x00ff00)>>8;
addr0 = (addr & 0x0000ff);
size = (size>(256-addr0))?(256-addr0):size;
set_wren();
SET_SPI(SOFTCS,0x01|0xee);/*CE 0*/
/*write 5 data to fifo, depth>4?*/
SET_SPI(TXFIFO,0x2);/*byte_program */
/*send addr2*/
SET_SPI(TXFIFO,addr2);
/*send addr1*/
SET_SPI(TXFIFO,addr1);
/*send addr0*/
SET_SPI(TXFIFO,addr0);
for(i=0;i<4;i++)
{
while((GET_SPI(SPSR)&RFEMPTY) == RFEMPTY);
val = GET_SPI(RXFIFO);
}
for(i=0;i<size;i++)
{
/*send data(one byte)*/
SET_SPI(TXFIFO,buffer[i]);
while((GET_SPI(SPSR)&RFEMPTY) == RFEMPTY);
val = GET_SPI(RXFIFO);
}
/*CE 1*/
SET_SPI(SOFTCS,0x11|0xee);
wait_sr();
return size;
}
#ifdef LS2H_SPI_WRITEBYTES
int spi_write_area(int flashaddr,char *buffer,int size)
{
int cnt;
spi_initw();
//SET_SPI(SOFTCS,0x10|0xee);
write_sr(0x00);
for(;size > 0;)
{
/// if((flashaddr&0xfffff)==0)printf("%x\n",flashaddr);
cnt = spi_write_bytes(flashaddr,buffer, size);
size -= cnt;
flashaddr += cnt;
buffer += cnt;
}
SET_SPI(SOFTCS,0x11|0xee);
delay(10);
return 0;
}
#else
int spi_write_area(int flashaddr,char *buffer,int size)
{
int j;
@ -498,10 +597,11 @@ int spi_write_area(int flashaddr,char *buffer,int size)
dotik(32, 0);
}
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
delay(10);
return 0;
}
#endif
int spi_read_area(int flashaddr,char *buffer,int size)
@ -509,7 +609,7 @@ int spi_read_area(int flashaddr,char *buffer,int size)
int i;
spi_initw();
SET_SPI(SOFTCS,0x01);
SET_SPI(SOFTCS,0x01|0xee);
SET_SPI(TXFIFO,0x03);
@ -536,7 +636,7 @@ int spi_read_area(int flashaddr,char *buffer,int size)
buffer[i] = GET_SPI(RXFIFO);
}
SET_SPI(SOFTCS,0x11);
SET_SPI(SOFTCS,0x11|0xee);
delay(10);
return 0;
}
@ -577,6 +677,174 @@ int fl_erase_device(void *fl_base, int size, int verbose)
return 0;
}
//---------------------------------------
#define prefetch(x) (x)
static struct ls1x_spi {
void *base;
} ls1x_spi0 = { 0xbfff0220} ;
struct spi_device spi_nand =
{
.dev = &ls1x_spi0,
.chip_select = 1,
};
struct spi_device spi_nand1 =
{
.dev = &ls1x_spi0,
.chip_select = 0,
};
static char ls1x_spi_write_reg(struct ls1x_spi *spi,
unsigned char reg, unsigned char data)
{
(*(volatile unsigned char *)(spi->base +reg)) = data;
}
static char ls1x_spi_read_reg(struct ls1x_spi *spi,
unsigned char reg)
{
return(*(volatile unsigned char *)(spi->base + reg));
}
static int
ls1x_spi_write_read_8bit(struct spi_device *spi,
const u8 **tx_buf, u8 **rx_buf, unsigned int num)
{
struct ls1x_spi *ls1x_spi = spi->dev;
unsigned char value;
int i;
if (tx_buf && *tx_buf){
ls1x_spi_write_reg(ls1x_spi, FIFO, *((*tx_buf)++));
while((ls1x_spi_read_reg(ls1x_spi, SPSR) & 0x1) == 1);
}else{
ls1x_spi_write_reg(ls1x_spi, FIFO, 0);
while((ls1x_spi_read_reg(ls1x_spi, SPSR) & 0x1) == 1);
}
if (rx_buf && *rx_buf) {
*(*rx_buf)++ = ls1x_spi_read_reg(ls1x_spi, FIFO);
}else{
ls1x_spi_read_reg(ls1x_spi, FIFO);
}
return 1;
}
static unsigned int
ls1x_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
{
struct ls1x_spi *ls1x_spi;
unsigned int count;
int word_len;
const u8 *tx = xfer->tx_buf;
u8 *rx = xfer->rx_buf;
ls1x_spi = spi->dev;
count = xfer->len;
do {
if (ls1x_spi_write_read_8bit(spi, &tx, &rx, count) < 0)
goto out;
count--;
} while (count);
out:
return xfer->len - count;
//return count;
}
int spi_sync(struct spi_device *spi, struct spi_message *m)
{
struct ls1x_spi *ls1x_spi = &ls1x_spi0;
struct spi_transfer *t = NULL;
unsigned long flags;
int cs;
int param;
m->actual_length = 0;
m->status = 0;
if (list_empty(&m->transfers) /*|| !m->complete*/)
return -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
printf("message rejected : "
"invalid transfer data buffers\n");
goto msg_rejected;
}
/*other things not check*/
}
param = ls1x_spi_read_reg(ls1x_spi, PARAM);
ls1x_spi_write_reg(ls1x_spi, PARAM, param&~1);
cs = ls1x_spi_read_reg(ls1x_spi, SOFTCS) & ~(0x11<<spi->chip_select);
ls1x_spi_write_reg(ls1x_spi, SOFTCS, (0x1 << spi->chip_select)|cs);
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->len)
m->actual_length +=
ls1x_spi_write_read(spi, t);
}
ls1x_spi_write_reg(ls1x_spi, SOFTCS, (0x11<<spi->chip_select)|cs);
ls1x_spi_write_reg(ls1x_spi, PARAM, param);
return 0;
msg_rejected:
m->status = -EINVAL;
if (m->complete)
m->complete(m->context);
return -EINVAL;
}
#if NSPINAND_MT29F||NSPINAND_LLD
int spinand_probe(struct spi_device *spi_nand);
int ls2h_spi_nand_probe()
{
spi_initw();
#ifdef CONFIG_SPINAND_CS
spi_nand.chip_select = CONFIG_SPINAND_CS;
#endif
spinand_probe(&spi_nand);
spi_initr();
}
#endif
#if NM25P80
int ls2h_m25p_probe()
{
spi_initw();
m25p_probe(&spi_nand1, "gd25q128");
m25p_probe(&spi_nand, "gd25q128");
spi_initr();
}
#endif
//----------------------------------------
static const Cmd Cmds[] =
{
{"MyCmds"},

Loading…
Cancel
Save