allwinner awnand代码解读
时间: 2023-07-09 19:32:02 浏览: 138
Allwinner AW NAND是一种基于Allwinner芯片的NAND闪存控制器。它的主要功能是对NAND闪存进行读写操作,并提供错误校验和修复等功能。以下是对AW NAND代码的解读:
1. 主要数据结构
struct aw_nand_chip {
struct nand_chip nand;
void __iomem *io_base;
spinlock_t lock;
struct clk *clk;
struct reset_control *rst;
struct dma_chan *dma_chan;
dma_cookie_t cookie;
struct completion dma_complete;
bool dma_running;
struct list_head dma_list;
struct aw_nand_dma_desc dma_descs[AW_NAND_MAX_DESC];
};
其中,nand_chip结构体是Linux内核中NAND闪存驱动程序使用的通用数据结构,io_base是Allwinner AW NAND的寄存器地址空间,lock是用于同步访问控制器的自旋锁,clk是时钟控制器,rst是重置控制器,dma_chan是DMA通道,dma_complete是用于DMA传输完成的信号,dma_running表示DMA传输是否正在进行,dma_list是DMA描述符的链表,dma_descs是DMA描述符数组。
2. 主要函数
static int aw_nand_hw_init(struct aw_nand_chip *chip)
{
int ret;
/* Enable NAND clocks */
clk_prepare_enable(chip->clk);
/* Reset NAND controller */
reset_control_assert(chip->rst);
udelay(10);
reset_control_deassert(chip->rst);
/* Configure NAND controller */
aw_nand_set_ecc_mode(chip, NAND_ECC_HW_SYNDROME);
aw_nand_set_buswidth(chip, NAND_BUSWIDTH_8);
aw_nand_set_timing(chip, &aw_nand_timings[0]);
/* Initialize DMA channel */
ret = aw_nand_dma_init(chip);
if (ret)
return ret;
/* Initialize NAND chip */
ret = nand_scan(&chip->nand, 1);
if (ret)
return ret;
nand_set_controller_data(&chip->nand, chip);
/* Register NAND device */
ret = mtd_device_register(&chip->nand, NULL, 0);
if (ret)
return ret;
return 0;
}
这是Allwinner AW NAND控制器的硬件初始化函数,主要包括以下几个步骤:使能NAND时钟,重置控制器,配置控制器,初始化DMA通道,初始化NAND芯片,注册MTD设备。
static int aw_nand_dma_init(struct aw_nand_chip *chip)
{
int i;
chip->dma_chan = dma_request_chan(chip->nand.dev, "tx");
if (IS_ERR(chip->dma_chan))
return PTR_ERR(chip->dma_chan);
/* Prepare DMA descriptors */
for (i = 0; i < AW_NAND_MAX_DESC; i++) {
chip->dma_descs[i].desc = dmaengine_prep_slave_sg(chip->dma_chan,
chip->nand.data_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!chip->dma_descs[i].desc) {
dev_err(chip->nand.dev, "Failed to prepare DMA descriptor %d\n", i);
return -ENOMEM;
}
chip->dma_descs[i].desc->callback = aw_nand_dma_callback;
chip->dma_descs[i].desc->callback_param = chip;
chip->dma_descs[i].desc->retries = 0;
chip->dma_descs[i].desc->cookie = &chip->dma_descs[i].cookie;
chip->dma_descs[i].cookie = 0;
chip->dma_descs[i].busy = false;
list_add_tail(&chip->dma_descs[i].list, &chip->dma_list);
}
return 0;
}
这是AW NAND控制器的DMA初始化函数,主要包括以下几个步骤:请求DMA通道,准备DMA描述符,设置DMA回调函数和参数,将DMA描述符添加到链表中。
static void aw_nand_dma_callback(void *data)
{
struct aw_nand_chip *chip = data;
struct aw_nand_dma_desc *desc;
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
/* Find completed DMA descriptor */
list_for_each_entry(desc, &chip->dma_list, list) {
if (desc->busy && dma_async_is_tx_complete(chip->dma_chan, desc->cookie, NULL, NULL) == DMA_COMPLETE) {
desc->busy = false;
break;
}
}
/* Restart DMA transfer */
if (!list_empty(&chip->dma_list)) {
desc = list_entry(chip->dma_list.next, struct aw_nand_dma_desc, list);
if (!desc->busy) {
desc->busy = true;
dmaengine_submit(desc->desc);
chip->cookie = *desc->desc->cookie;
dma_async_issue_pending(chip->dma_chan);
chip->dma_running = true;
}
} else {
complete(&chip->dma_complete);
chip->dma_running = false;
}
spin_unlock_irqrestore(&chip->lock, flags);
}
这是AW NAND控制器的DMA回调函数,主要包括以下几个步骤:查找已完成的DMA描述符,重新启动DMA传输。
以上是对Allwinner AW NAND的代码解读,包括主要数据结构和主要函数。
阅读全文