mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
dm9000 mutex with nandc
This commit is contained in:
@@ -26,10 +26,13 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/rk2818_nand.h>
|
||||
#include <mach/rk2818_iomap.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
#define PROGRAM_BUSY_COUNT 10000
|
||||
#define ERASE_BUSY_COUNT 20000
|
||||
@@ -38,6 +41,10 @@
|
||||
/* Define delays in microsec for NAND device operations */
|
||||
#define TROP_US_DELAY 2000
|
||||
|
||||
static struct mutex rknand_mutex;
|
||||
//static spinlock_t rknand_lock;
|
||||
|
||||
|
||||
struct rk2818_nand_mtd {
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
@@ -45,9 +52,15 @@ struct rk2818_nand_mtd {
|
||||
struct device *dev;
|
||||
const struct rk2818_nand_flash *flash_info;
|
||||
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
uint16_t col_addr;
|
||||
struct clk *clk;
|
||||
unsigned long clk_rate;
|
||||
void __iomem *regs;
|
||||
int cs; // support muliple nand chip,record current chip select
|
||||
u_char accesstime;
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
struct notifier_block freq_transition;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/* OOB placement block for use with software ecc generation */
|
||||
@@ -142,8 +155,17 @@ static void rk2818_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
|
||||
if( chip<0 )
|
||||
pRK28NC->FMCTL &=0xffffff00; // release chip select
|
||||
else
|
||||
{
|
||||
master->cs = chip;
|
||||
pRK28NC->FMCTL &=0xffffff00;
|
||||
pRK28NC ->FMCTL |= 0x1<<chip; // select chip
|
||||
}
|
||||
|
||||
pRK28NC ->FMCTL |= 0x1<<chip;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,8 +178,9 @@ static u_char rk2818_nand_read_byte(struct mtd_info *mtd)
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
u_char ret = 0;
|
||||
pRK28NC->FLCTL &= ~FL_BYPASS; // bypass mode
|
||||
ret = (u_char)(pRK28NC ->chip[0].data);
|
||||
|
||||
ret = (u_char)(pRK28NC ->chip[master->cs].data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -169,17 +192,16 @@ static u16 rk2818_nand_read_word(struct mtd_info *mtd)
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
|
||||
u_char tmp1 = 0,tmp2=0;
|
||||
u16 ret=0;
|
||||
|
||||
pRK28NC->FLCTL &= ~FL_BYPASS; // bypass mode
|
||||
|
||||
tmp1 = (u_char)(pRK28NC ->chip[0].data);
|
||||
tmp2 = (u_char)(pRK28NC ->chip[0].data);
|
||||
|
||||
tmp1 = (u_char)(pRK28NC ->chip[master->cs].data);
|
||||
tmp2 = (u_char)(pRK28NC ->chip[master->cs].data);
|
||||
|
||||
ret = (tmp2 <<8)|tmp1;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -188,9 +210,16 @@ static void rk2818_nand_read_buf(struct mtd_info *mtd, u_char* const buf, int le
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
uint32_t i;
|
||||
uint32_t i, chipnr;
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
|
||||
|
||||
|
||||
if ( len < mtd->writesize ) // read oob
|
||||
{
|
||||
pRK28NC ->BCHCTL = BCH_RST;
|
||||
@@ -211,6 +240,13 @@ static void rk2818_nand_read_buf(struct mtd_info *mtd, u_char* const buf, int le
|
||||
memcpy(buf+i*0x400,(u_char *)(pRK28NC->buf),0x400); // only use nandc sram0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
|
||||
return;
|
||||
|
||||
@@ -222,9 +258,18 @@ static void rk2818_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int l
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0, chipnr;
|
||||
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
pRK28NC->FLCTL |= FL_BYPASS; // dma mode
|
||||
|
||||
|
||||
for(i=0;i<mtd->writesize/0x400;i++)
|
||||
{
|
||||
memcpy((u_char *)(pRK28NC->buf),buf+i*0x400,0x400); // only use nandc sram0
|
||||
@@ -232,6 +277,13 @@ static void rk2818_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int l
|
||||
pRK28NC ->FLCTL = (0<<4)|FL_COR_EN|0x1<<5|FL_RDN|FL_BYPASS|FL_START;
|
||||
wait_op_done(mtd,TROP_US_DELAY,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -244,12 +296,13 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
|
||||
uint32_t timeout = 1000;
|
||||
char status,ret;
|
||||
|
||||
|
||||
switch (command) {
|
||||
|
||||
case NAND_CMD_READID:
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[0].addr = 0x0;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
pRK28NC ->chip[master->cs].addr = 0x0;
|
||||
while (timeout>0)
|
||||
{
|
||||
timeout --;
|
||||
@@ -262,18 +315,18 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
break;
|
||||
|
||||
case NAND_CMD_READ0:
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
if ( column>= 0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = column & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = column & 0xff;
|
||||
if( mtd->writesize > 512)
|
||||
pRK28NC ->chip[0].addr = (column >> 8) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (column >> 8) & 0xff;
|
||||
}
|
||||
if ( page_addr>=0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr >> 8) & 0xFF;
|
||||
pRK28NC ->chip[0].addr = (page_addr >> 16) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr >> 8) & 0xFF;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr >> 16) & 0xff;
|
||||
}
|
||||
if( mtd->writesize > 512)
|
||||
pRK28NC ->chip[0].cmd = NAND_CMD_READSTART;
|
||||
@@ -283,7 +336,7 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
break;
|
||||
|
||||
case NAND_CMD_READ1:
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
break;
|
||||
|
||||
case NAND_CMD_READOOB:
|
||||
@@ -291,26 +344,26 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
if( mtd->writesize > 512 )
|
||||
command = NAND_CMD_READ0; // ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>oob
|
||||
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
|
||||
if ( mtd->writesize >512 )
|
||||
{
|
||||
if ( column>= 0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = (column + mtd->writesize) & 0xff;
|
||||
pRK28NC ->chip[0].addr = ( (column + mtd->writesize) >> 8) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (column + mtd->writesize) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = ( (column + mtd->writesize) >> 8) & 0xff;
|
||||
}
|
||||
if ( page_addr>=0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr >> 8) & 0xFF;
|
||||
pRK28NC ->chip[0].addr = (page_addr >> 16) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr >> 8) & 0xFF;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr >> 16) & 0xff;
|
||||
}
|
||||
pRK28NC ->chip[0].cmd = NAND_CMD_READSTART;
|
||||
pRK28NC ->chip[master->cs].cmd = NAND_CMD_READSTART;
|
||||
}
|
||||
else
|
||||
{
|
||||
pRK28NC ->chip[0].addr = column;
|
||||
pRK28NC ->chip[master->cs].addr = column;
|
||||
}
|
||||
|
||||
rk2818_nand_wait_busy(mtd,READ_BUSY_COUNT);
|
||||
@@ -320,11 +373,11 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
|
||||
case NAND_CMD_PAGEPROG:
|
||||
pRK28NC ->FMCTL |= FMC_WP; //<2F><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
rk2818_nand_wait_busy(mtd,PROGRAM_BUSY_COUNT);
|
||||
|
||||
pRK28NC ->chip[0].cmd = NAND_CMD_STATUS;
|
||||
status = pRK28NC ->chip[0].data;
|
||||
pRK28NC ->chip[master->cs].cmd = NAND_CMD_STATUS;
|
||||
status = pRK28NC ->chip[master->cs].data;
|
||||
|
||||
if(status&0x1)
|
||||
ret = -1;
|
||||
@@ -336,21 +389,21 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
case NAND_CMD_ERASE1:
|
||||
pRK28NC ->FMCTL |= FMC_WP; //<2F><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
pRK28NC ->BCHCTL = 0x0;
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
if ( page_addr>=0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr>>8)&0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr>>16)&0xff;
|
||||
pRK28NC ->chip[master->cs].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr>>8)&0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr>>16)&0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAND_CMD_ERASE2:
|
||||
pRK28NC ->FMCTL |= FMC_WP; //<2F><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
rk2818_nand_wait_busy(mtd,ERASE_BUSY_COUNT);
|
||||
pRK28NC ->chip[0].cmd = NAND_CMD_STATUS;
|
||||
status = pRK28NC ->chip[0].data;
|
||||
pRK28NC ->chip[master->cs].cmd = NAND_CMD_STATUS;
|
||||
status = pRK28NC ->chip[master->cs].data;
|
||||
|
||||
if(status&0x1)
|
||||
ret = -1;
|
||||
@@ -361,35 +414,35 @@ static void rk2818_nand_cmdfunc(struct mtd_info *mtd, unsigned command,int colum
|
||||
|
||||
case NAND_CMD_SEQIN:
|
||||
pRK28NC ->FMCTL |= FMC_WP; //<2F><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
udelay(1);
|
||||
if ( column>= 0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = column;
|
||||
pRK28NC ->chip[master->cs].addr = column;
|
||||
if( mtd->writesize > 512)
|
||||
pRK28NC ->chip[0].addr = (column >> 8) & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (column >> 8) & 0xff;
|
||||
}
|
||||
if( page_addr>=0 )
|
||||
{
|
||||
pRK28NC ->chip[0].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr>>8)&0xff;
|
||||
pRK28NC ->chip[0].addr = (page_addr>>16)&0xff;
|
||||
pRK28NC ->chip[master->cs].addr = page_addr & 0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr>>8)&0xff;
|
||||
pRK28NC ->chip[master->cs].addr = (page_addr>>16)&0xff;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NAND_CMD_STATUS:
|
||||
pRK28NC ->BCHCTL = 0x0;
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
break;
|
||||
|
||||
case NAND_CMD_RESET:
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
break;
|
||||
|
||||
/* This applies to read commands */
|
||||
default:
|
||||
pRK28NC ->chip[0].cmd = command;
|
||||
pRK28NC ->chip[master->cs].cmd = command;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -453,15 +506,21 @@ int rk2818_nand_calculate_ecc(struct mtd_info *mtd,const uint8_t *dat,uint8_t *e
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
int i,chipnr;
|
||||
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
|
||||
rk2818_nand_wait_busy(mtd,READ_BUSY_COUNT);
|
||||
|
||||
pRK28NC->FLCTL |= FL_BYPASS; // dma mode
|
||||
|
||||
|
||||
for(i=0;i<mtd->writesize/0x400;i++)
|
||||
{
|
||||
pRK28NC ->BCHCTL = BCH_RST;
|
||||
@@ -471,7 +530,12 @@ int rk2818_nand_calculate_ecc(struct mtd_info *mtd,const uint8_t *dat,uint8_t *e
|
||||
|
||||
memcpy(buf+i*0x400,(u_char *)(pRK28NC->buf),0x400); // only use nandc sram0
|
||||
}
|
||||
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -481,11 +545,17 @@ void rk2818_nand_write_page(struct mtd_info *mtd,struct nand_chip *chip,const u
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
uint32_t i = 0;
|
||||
|
||||
uint32_t i = 0, chipnr;
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
pRK28NC->FLCTL |= FL_BYPASS; // dma mode
|
||||
|
||||
|
||||
for(i=0;i<mtd->writesize/0x400;i++)
|
||||
{
|
||||
memcpy((u_char *)(pRK28NC->buf),(buf+i*0x400),0x400); // only use nandc sram0
|
||||
@@ -498,8 +568,14 @@ void rk2818_nand_write_page(struct mtd_info *mtd,struct nand_chip *chip,const u
|
||||
}
|
||||
|
||||
pRK28NC ->chip[0].cmd = NAND_CMD_PAGEPROG;
|
||||
|
||||
|
||||
|
||||
rk2818_nand_wait_busy(mtd,PROGRAM_BUSY_COUNT);
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
return;
|
||||
|
||||
@@ -510,28 +586,43 @@ int rk2818_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page,
|
||||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
int i;
|
||||
int i,chipnr;
|
||||
|
||||
|
||||
if (sndcmd) {
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
||||
sndcmd = 0;
|
||||
}
|
||||
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
rk2818_nand_wait_busy(mtd,READ_BUSY_COUNT);
|
||||
|
||||
|
||||
|
||||
pRK28NC->FLCTL |= FL_BYPASS; // dma mode
|
||||
|
||||
|
||||
|
||||
|
||||
for(i=0;i<mtd->writesize/0x400;i++)
|
||||
{
|
||||
pRK28NC ->BCHCTL = BCH_RST;
|
||||
pRK28NC ->FLCTL = (0<<4)|FL_COR_EN|(0x1<<5)|FL_BYPASS|FL_START ;
|
||||
wait_op_done(mtd,TROP_US_DELAY,0);
|
||||
rk2818_nand_wait_bchdone(mtd,TROP_US_DELAY) ;
|
||||
// memcpy(buf+i*0x400,(u_char *)(pRK28NC->buf),0x400); // only use nandc sram0
|
||||
if(i==0)
|
||||
memcpy((u_char *)(chip->oob_poi+ chip->ops.ooboffs),(u_char *)(pRK28NC->spare),4);
|
||||
}
|
||||
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
|
||||
return sndcmd;
|
||||
}
|
||||
@@ -542,14 +633,21 @@ int rk2818_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint
|
||||
struct rk2818_nand_mtd *master = nand_chip->priv;
|
||||
pNANDC pRK28NC= (pNANDC)(master->regs);
|
||||
|
||||
|
||||
int i;
|
||||
int i,chipnr;
|
||||
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
chipnr = master->cs ;
|
||||
|
||||
rk2818_nand_select_chip(mtd,chipnr);
|
||||
|
||||
rk2818_nand_wait_busy(mtd,READ_BUSY_COUNT);
|
||||
|
||||
pRK28NC->FLCTL |= FL_BYPASS; // dma mode
|
||||
|
||||
|
||||
|
||||
for(i=0;i<mtd->writesize/0x400;i++)
|
||||
{
|
||||
pRK28NC ->BCHCTL = BCH_RST;
|
||||
@@ -560,10 +658,106 @@ int rk2818_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint
|
||||
if(i==0)
|
||||
memcpy((u_char *)(chip->oob_poi+ chip->ops.ooboffs),(u_char *)(pRK28NC->spare),4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rk2818_nand_select_chip(mtd,-1);
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk2818_nand_setrate(struct rk2818_nand_mtd *info)
|
||||
{
|
||||
pNANDC pRK28NC= (pNANDC)(info->regs);
|
||||
|
||||
unsigned long clkrate = clk_get_rate(info->clk);
|
||||
|
||||
u_char accesstime,rwpw,csrw,rwcs;
|
||||
|
||||
unsigned int ns=0,timingcfg;
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
//scan nand flash access time
|
||||
if ( info->accesstime ==0x00 )
|
||||
accesstime=50;
|
||||
else if ( info->accesstime==0x80)
|
||||
accesstime=25;
|
||||
else if ( info->accesstime==0x08)
|
||||
accesstime=20;
|
||||
else
|
||||
accesstime=60; //60ns
|
||||
|
||||
info->clk_rate = clkrate;
|
||||
clkrate /= 1000000; /* turn clock into MHz for ease of use */
|
||||
|
||||
if(clkrate>0 && clkrate<200)
|
||||
ns= 1000/clkrate; // ns
|
||||
else
|
||||
return -1;
|
||||
|
||||
timingcfg = (accesstime + ns -1)/ns;
|
||||
|
||||
timingcfg = (timingcfg>=3) ? (timingcfg-2) : timingcfg; //csrw+1, rwcs+1
|
||||
|
||||
rwpw = timingcfg-timingcfg/4;
|
||||
csrw = timingcfg/4;
|
||||
rwcs = (timingcfg/4 >=1)?(timingcfg/4):1;
|
||||
|
||||
mutex_lock(&rknand_mutex);
|
||||
|
||||
pRK28NC ->FMWAIT |= (rwcs<<FMW_RWCS_OFFSET)|(rwpw<<FMW_RWPW_OFFSET)|(csrw<<FMW_CSRW_OFFSET);
|
||||
|
||||
mutex_unlock(&rknand_mutex);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cpufreq driver support */
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
|
||||
static int rk2818_nand_cpufreq_transition(struct notifier_block *nb, unsigned long val, void *data)
|
||||
{
|
||||
struct rk2818_nand_mtd *info;
|
||||
unsigned long newclk;
|
||||
|
||||
info = container_of(nb, struct rk2818_nand_mtd, freq_transition);
|
||||
newclk = clk_get_rate(info->clk);
|
||||
|
||||
if (val == CPUFREQ_POSTCHANGE && newclk != info->clk_rate)
|
||||
{
|
||||
rk2818_nand_setrate(info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rk2818_nand_cpufreq_register(struct rk2818_nand_mtd *info)
|
||||
{
|
||||
info->freq_transition.notifier_call = rk2818_nand_cpufreq_transition;
|
||||
|
||||
return cpufreq_register_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
|
||||
}
|
||||
|
||||
static inline void rk2818_nand_cpufreq_deregister(struct rk2818_nand_mtd *info)
|
||||
{
|
||||
cpufreq_unregister_notifier(&info->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline int rk2818_nand_cpufreq_register(struct rk2818_nand_mtd *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rk2818_nand_cpufreq_deregister(struct rk2818_nand_mtd *info)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int rk2818_nand_probe(struct platform_device *pdev)
|
||||
{
|
||||
@@ -574,6 +768,7 @@ static int rk2818_nand_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
int err = 0;
|
||||
pNANDC pRK28NC;
|
||||
u_char maf_id,dev_id,ext_id3,ext_id4;
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
struct mtd_partition *partitions = NULL;
|
||||
@@ -638,10 +833,28 @@ static int rk2818_nand_probe(struct platform_device *pdev)
|
||||
this->ecc.mode = NAND_ECC_SOFT;
|
||||
}
|
||||
|
||||
|
||||
mutex_init(&rknand_mutex);
|
||||
|
||||
master->clk = clk_get(NULL, "nandc");
|
||||
|
||||
clk_enable(master->clk);
|
||||
|
||||
pRK28NC = (pNANDC)(master->regs);
|
||||
pRK28NC ->FMCTL = FMC_WP|FMC_FRDY|(0x1<<0);
|
||||
pRK28NC ->FMCTL = FMC_WP|FMC_FRDY;
|
||||
pRK28NC ->FMWAIT |= (1<<FMW_RWCS_OFFSET)|(4<<FMW_RWPW_OFFSET)|(1<<FMW_CSRW_OFFSET);
|
||||
pRK28NC ->BCHCTL = 0x1;
|
||||
|
||||
this->select_chip(mtd, 0);
|
||||
this->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
||||
maf_id = this->read_byte(mtd);
|
||||
dev_id = this->read_byte(mtd);
|
||||
ext_id3 = this->read_byte(mtd);
|
||||
ext_id4 = this->read_byte(mtd);
|
||||
|
||||
master->accesstime = ext_id4&0x88;
|
||||
|
||||
rk2818_nand_setrate(master);
|
||||
|
||||
/* Reset NAND */
|
||||
this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
||||
@@ -651,14 +864,28 @@ static int rk2818_nand_probe(struct platform_device *pdev)
|
||||
this->ecc.layout = &nand_hw_eccoob_16;
|
||||
}
|
||||
|
||||
// iomux flash cs1~cs7
|
||||
rk2818_mux_api_set(GPIOA5_FLASHCS1_SEL_NAME, IOMUXB_FLASH_CS1);
|
||||
rk2818_mux_api_set(GPIOA6_FLASHCS2_SEL_NAME, IOMUXB_FLASH_CS2);
|
||||
rk2818_mux_api_set(GPIOA7_FLASHCS3_SEL_NAME, IOMUXB_FLASH_CS3);
|
||||
rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL1_NAME, IOMUXA_FLASH_CS45);
|
||||
rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL_NAME, IOMUXA_FLASH_CS67);
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan(mtd, 1)) {
|
||||
if (nand_scan(mtd, 8)) { // rk2818 nandc support max 8 cs
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0,
|
||||
"RK2818 NAND: Unable to find any NAND device.\n");
|
||||
err = -ENXIO;
|
||||
goto outscan;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// rk281x dma mode bch must (1k data + 32 oob) bytes align , so cheat system writesize =1024,oobsize=32
|
||||
mtd->writesize = 1024;
|
||||
mtd->oobsize = 32;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
|
||||
if (num_partitions > 0) {
|
||||
@@ -678,6 +905,12 @@ static int rk2818_nand_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
|
||||
err =rk2818_nand_cpufreq_register(master);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR"rk2818 nand failed to init cpufreq support\n");
|
||||
goto outscan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
outres:
|
||||
@@ -695,8 +928,24 @@ static int rk2818_nand_remove(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
if(master == NULL)
|
||||
return 0;
|
||||
|
||||
rk2818_nand_cpufreq_deregister(master);
|
||||
|
||||
|
||||
nand_release(&master->mtd);
|
||||
iounmap(master->regs);
|
||||
|
||||
if(master->regs!=NULL){
|
||||
iounmap(master->regs);
|
||||
master->regs = NULL;
|
||||
}
|
||||
|
||||
if (master->clk != NULL && !IS_ERR(master->clk)) {
|
||||
clk_disable(master->clk);
|
||||
clk_put(master->clk);
|
||||
}
|
||||
|
||||
kfree(master);
|
||||
|
||||
return 0;
|
||||
@@ -756,6 +1005,26 @@ static void __exit rk2818_nand_exit(void)
|
||||
platform_driver_unregister(&rk2818_nand_driver);
|
||||
}
|
||||
|
||||
|
||||
// nandc dma cs mutex for dm9000 interface
|
||||
int rk2818_nand_status_mutex_trylock(void)
|
||||
{
|
||||
pNANDC pRK28NC= (pNANDC)RK2818_NANDC_BASE;
|
||||
if( mutex_trylock(&rknand_mutex))
|
||||
{
|
||||
pRK28NC->FMCTL &=0xffffff00; // release chip select
|
||||
return 1; // ready
|
||||
}
|
||||
else
|
||||
return 0; // busy
|
||||
}
|
||||
|
||||
void rk2818_nand_status_mutex_unlock(void)
|
||||
{
|
||||
mutex_unlock(&rknand_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(rk2818_nand_init);
|
||||
module_exit(rk2818_nand_exit);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
#include "dm9000.h"
|
||||
|
||||
@@ -104,6 +105,12 @@ typedef struct board_info {
|
||||
int debug_level;
|
||||
|
||||
enum dm9000_type type;
|
||||
|
||||
#ifdef CONFIG_DM9000_USE_NAND_CONTROL
|
||||
void *dev_id;
|
||||
struct work_struct dm9k_work;
|
||||
struct workqueue_struct *dm9000_wq;
|
||||
#endif
|
||||
|
||||
void (*inblk)(void __iomem *port, void *data, int length);
|
||||
void (*outblk)(void __iomem *port, void *data, int length);
|
||||
@@ -133,7 +140,6 @@ typedef struct board_info {
|
||||
} board_info_t;
|
||||
|
||||
/* debug code */
|
||||
#define DEBUG_LEVEL 4
|
||||
#define dm9000_dbg(db, lev, msg...) do { \
|
||||
if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \
|
||||
(lev) < db->debug_level) { \
|
||||
@@ -141,6 +147,14 @@ typedef struct board_info {
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_DM9000_USE_NAND_CONTROL
|
||||
extern int rk2818_nand_status_mutex_trylock(void);
|
||||
extern void rk2818_nand_status_mutex_unlock(void);
|
||||
#else
|
||||
static int rk2818_nand_status_mutex_trylock(void) {return 1;}
|
||||
static void rk2818_nand_status_mutex_unlock(void) {return;}
|
||||
#endif
|
||||
|
||||
static inline board_info_t *to_dm9000_board(struct net_device *dev)
|
||||
{
|
||||
return netdev_priv(dev);
|
||||
@@ -307,11 +321,16 @@ dm9000_read_locked(board_info_t *db, int reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int ret;
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
ret = ior(db, reg);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -363,21 +382,29 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
|
||||
}
|
||||
|
||||
mutex_lock(&db->addr_lock);
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
|
||||
iow(db, DM9000_EPAR, offset);
|
||||
iow(db, DM9000_EPCR, EPCR_ERPRR);
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
dm9000_wait_eeprom(db);
|
||||
|
||||
/* delay for at-least 150uS */
|
||||
msleep(1);
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
|
||||
iow(db, DM9000_EPCR, 0x0);
|
||||
|
||||
to[0] = ior(db, DM9000_EPDRL);
|
||||
@@ -385,6 +412,8 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
mutex_unlock(&db->addr_lock);
|
||||
}
|
||||
|
||||
@@ -400,22 +429,32 @@ dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
|
||||
return;
|
||||
|
||||
mutex_lock(&db->addr_lock);
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
iow(db, DM9000_EPAR, offset);
|
||||
iow(db, DM9000_EPDRH, data[1]);
|
||||
iow(db, DM9000_EPDRL, data[0]);
|
||||
iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
dm9000_wait_eeprom(db);
|
||||
|
||||
mdelay(1); /* wait at least 150uS to clear */
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
iow(db, DM9000_EPCR, 0);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
mutex_unlock(&db->addr_lock);
|
||||
}
|
||||
|
||||
@@ -480,9 +519,13 @@ static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
|
||||
if (dm->can_csum) {
|
||||
dm->rx_csum = data;
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(dm->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&dm->lock, flags);
|
||||
iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);
|
||||
spin_unlock_irqrestore(&dm->lock, flags);
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -680,9 +723,12 @@ dm9000_hash_table(struct net_device *dev)
|
||||
unsigned long flags;
|
||||
|
||||
dm9000_dbg(db, 1, "entering %s\n", __func__);
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
|
||||
for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
|
||||
iow(db, oft, dev->dev_addr[i]);
|
||||
|
||||
@@ -713,6 +759,8 @@ dm9000_hash_table(struct net_device *dev)
|
||||
|
||||
iow(db, DM9000_RCR, rcr);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -776,6 +824,10 @@ static void dm9000_timeout(struct net_device *dev)
|
||||
|
||||
/* Save previous register address */
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
netif_stop_queue(dev);
|
||||
@@ -788,6 +840,8 @@ static void dm9000_timeout(struct net_device *dev)
|
||||
/* Restore previous register address */
|
||||
writeb(reg_save, db->io_addr);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
}
|
||||
|
||||
static void dm9000_send_packet(struct net_device *dev,
|
||||
@@ -830,8 +884,12 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (!rk2818_nand_status_mutex_trylock()) {
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
|
||||
/* Move data to DM9000 TX RAM */
|
||||
writeb(DM9000_MWCMD, db->io_addr);
|
||||
|
||||
@@ -850,6 +908,8 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
/* free this SKB */
|
||||
dev_kfree_skb(skb);
|
||||
@@ -998,19 +1058,24 @@ dm9000_rx(struct net_device *dev)
|
||||
} while (rxbyte & DM9000_PKT_RDY);
|
||||
}
|
||||
|
||||
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
|
||||
#ifdef CONFIG_DM9000_USE_NAND_CONTROL
|
||||
static void dm9000_interrupt_work(struct work_struct *work)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
board_info_t *db = netdev_priv(dev);
|
||||
board_info_t *db = container_of(work, board_info_t, dm9k_work);
|
||||
struct net_device *dev = db->dev_id;
|
||||
int int_status;
|
||||
unsigned long flags;
|
||||
u8 reg_save;
|
||||
|
||||
dm9000_dbg(db, 3, "entering %s\n", __func__);
|
||||
|
||||
|
||||
//printk("entering %s\n", __FUNCTION__);
|
||||
|
||||
/* A real interrupt coming */
|
||||
|
||||
/* holders of db->lock must always block IRQs */
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
/* Save previous register address */
|
||||
@@ -1048,9 +1113,81 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
|
||||
writeb(reg_save, db->io_addr);
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
enable_irq(dev->irq);
|
||||
|
||||
}
|
||||
|
||||
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
board_info_t *db = netdev_priv(dev);
|
||||
|
||||
//printk("enter : %s\n", __FUNCTION__);
|
||||
|
||||
db->dev_id = dev_id;
|
||||
disable_irq_nosync(irq);
|
||||
queue_work(db->dm9000_wq, &(db->dm9k_work));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#else
|
||||
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = dev_id;
|
||||
board_info_t *db = netdev_priv(dev);
|
||||
int int_status;
|
||||
unsigned long flags;
|
||||
u8 reg_save;
|
||||
|
||||
dm9000_dbg(db, 3, "entering %s\n", __func__);
|
||||
|
||||
/* A real interrupt coming */
|
||||
|
||||
/* holders of db->lock must always block IRQs */
|
||||
spin_lock_irqsave(&db->lock, flags);
|
||||
|
||||
/* Save previous register address */
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
/* Disable all interrupts */
|
||||
iow(db, DM9000_IMR, IMR_PAR);
|
||||
|
||||
/* Got DM9000 interrupt status */
|
||||
int_status = ior(db, DM9000_ISR); /* Got ISR */
|
||||
iow(db, DM9000_ISR, int_status); /* Clear ISR status */
|
||||
|
||||
if (netif_msg_intr(db))
|
||||
dev_dbg(db->dev, "interrupt status %02x\n", int_status);
|
||||
|
||||
/* Received the coming packet */
|
||||
if (int_status & ISR_PRS)
|
||||
dm9000_rx(dev);
|
||||
|
||||
/* Trnasmit Interrupt check */
|
||||
if (int_status & ISR_PTS)
|
||||
dm9000_tx_done(dev, db);
|
||||
|
||||
if (db->type != TYPE_DM9000E) {
|
||||
if (int_status & ISR_LNKCHNG) {
|
||||
/* fire a link-change request */
|
||||
schedule_delayed_work(&db->phy_poll, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-enable interrupt mask */
|
||||
iow(db, DM9000_IMR, db->imr_all);
|
||||
|
||||
/* Restore previous register address */
|
||||
writeb(reg_save, db->io_addr);
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/*
|
||||
@@ -1074,6 +1211,11 @@ dm9000_open(struct net_device *dev)
|
||||
board_info_t *db = netdev_priv(dev);
|
||||
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
|
||||
|
||||
#ifdef CONFIG_DM9000_USE_NAND_CONTROL
|
||||
db->dm9000_wq = create_workqueue("dm9000 wq");
|
||||
INIT_WORK(&(db->dm9k_work), dm9000_interrupt_work);
|
||||
#endif
|
||||
|
||||
if (netif_msg_ifup(db))
|
||||
dev_dbg(db->dev, "enabling %s\n", dev->name);
|
||||
|
||||
@@ -1128,8 +1270,11 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
|
||||
|
||||
mutex_lock(&db->addr_lock);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
|
||||
/* Save previous register address */
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
@@ -1140,10 +1285,16 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
|
||||
|
||||
writeb(reg_save, db->io_addr);
|
||||
spin_unlock_irqrestore(&db->lock,flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
dm9000_msleep(db, 1); /* Wait read complete */
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
|
||||
@@ -1154,6 +1305,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
|
||||
/* restore the previous address */
|
||||
writeb(reg_save, db->io_addr);
|
||||
spin_unlock_irqrestore(&db->lock,flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
mutex_unlock(&db->addr_lock);
|
||||
|
||||
@@ -1175,8 +1328,11 @@ dm9000_phy_write(struct net_device *dev,
|
||||
dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
|
||||
mutex_lock(&db->addr_lock);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
|
||||
/* Save previous register address */
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
@@ -1191,10 +1347,16 @@ dm9000_phy_write(struct net_device *dev,
|
||||
|
||||
writeb(reg_save, db->io_addr);
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
|
||||
dm9000_msleep(db, 1); /* Wait write complete */
|
||||
|
||||
while(!rk2818_nand_status_mutex_trylock())
|
||||
dev_dbg(db->dev, "fun:%s, nand busy\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&db->lock,flags);
|
||||
|
||||
reg_save = readb(db->io_addr);
|
||||
|
||||
iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
|
||||
@@ -1203,6 +1365,8 @@ dm9000_phy_write(struct net_device *dev,
|
||||
writeb(reg_save, db->io_addr);
|
||||
|
||||
spin_unlock_irqrestore(&db->lock, flags);
|
||||
|
||||
rk2818_nand_status_mutex_unlock();
|
||||
mutex_unlock(&db->addr_lock);
|
||||
}
|
||||
|
||||
@@ -1240,6 +1404,10 @@ dm9000_stop(struct net_device *ndev)
|
||||
|
||||
dm9000_shutdown(ndev);
|
||||
|
||||
#ifdef CONFIG_DM9000_USE_NAND_CONTROL
|
||||
destroy_workqueue(db->dm9000_wq);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1290,8 +1458,6 @@ dm9000_probe(struct platform_device *pdev)
|
||||
db->dev = &pdev->dev;
|
||||
db->ndev = ndev;
|
||||
|
||||
//db->debug_level = 5;//add by liuyx@20100511
|
||||
|
||||
spin_lock_init(&db->lock);
|
||||
mutex_init(&db->addr_lock);
|
||||
|
||||
@@ -1350,6 +1516,7 @@ dm9000_probe(struct platform_device *pdev)
|
||||
#if 0
|
||||
ndev->irq = db->irq_res->start;
|
||||
#else//modify by liuyx@20100510
|
||||
rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL1_NAME, IOMUXA_GPIO1_A12);
|
||||
ndev->irq = gpio_to_irq(db->irq_res->start);
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user