由于MT25QU01G是一款SPI NOR闪存,因此在U-Boot中的驱动程序将使用SPI总线来与它交互。下面是一个简单的MT25QU01G驱动程序示例,它使用U-Boot的SPI API来实现与闪存的通信:

#include <common.h>
#include <dm.h>
#include <spi.h>

#define MT25QU01G_CMD_READ 0x03
#define MT25QU01G_CMD_WRITE_ENABLE 0x06
#define MT25QU01G_CMD_WRITE_DISABLE 0x04
#define MT25QU01G_CMD_ERASE_SECTOR 0x20
#define MT25QU01G_CMD_ERASE_CHIP 0xC7
#define MT25QU01G_CMD_READ_STATUS 0x05
#define MT25QU01G_STATUS_BUSY (1 << 0)

struct mt25qu01g_spi_flash {
    struct spi_slave *spi;
};

static int mt25qu01g_spi_flash_read(struct udevice *dev, uint32_t addr, size_t size, void *dst)
{
    struct mt25qu01g_spi_flash *priv = dev_get_priv(dev);
    u8 cmd[4] = {MT25QU01G_CMD_READ, addr >> 16, addr >> 8, addr};
    struct spi_buf buf[2] = {
        { .tx_buf = cmd, .len = sizeof(cmd) },
        { .rx_buf = dst, .len = size }
    };
    struct spi_transfer xfer = {
        .tx_buf = cmd,
        .rx_buf = dst,
        .len = size,
        .bits_per_word = 8,
    };
    int ret;

    ret = spi_sync(priv->spi, &xfer, 1);
    if (ret)
        dev_err(dev, "read error %d\n", ret);

    return ret;
}

static int mt25qu01g_spi_flash_write(struct udevice *dev, uint32_t addr, size_t size, const void *src)
{
    struct mt25qu01g_spi_flash *priv = dev_get_priv(dev);
    u8 cmd[4] = {MT25QU01G_CMD_WRITE_ENABLE};
    u8 status;
    int ret;

    ret = spi_write(priv->spi, cmd, sizeof(cmd));
    if (ret)
        return ret;

    cmd[0] = MT25QU01G_CMD_READ_STATUS;
    do {
        ret = spi_xfer(priv->spi, cmd, cmd, sizeof(cmd));
        if (ret)
            return ret;
        status = cmd[1];
    } while (status & MT25QU01G_STATUS_BUSY);

    cmd[0] = MT25QU01G_CMD_WRITE;
    cmd[1] = addr >> 16;
    cmd[2] = addr >> 8;
    cmd[3] = addr;
    ret = spi_write_then_read(priv->spi, cmd, sizeof(cmd), src, size);
    if (ret)
        return ret;

    cmd[0] = MT25QU01G_CMD_WRITE_DISABLE;
    ret = spi_write(priv->spi, cmd, sizeof(cmd));
    if (ret)
        return ret;

    return 0;
}

static int mt25qu01g_spi_flash_erase(struct udevice *dev, uint32_t addr, size_t size)
{
    struct mt25qu01g_spi_flash *priv = dev_get_priv(dev);
    u8 cmd[4] = {MT25QU01G_CMD_WRITE_ENABLE};
    u8 status;
    int ret;

    ret = spi_write(priv->spi, cmd, sizeof(cmd));
    if (ret)
        return ret;

    cmd[0] = MT25QU01G_CMD_READ_STATUS;
    do {
        ret = spi_xfer(priv->spi, cmd, cmd, sizeof(cmd));
        if (ret)
            return ret;
        status = cmd[1];
    } while (status & MT25QU01G_STATUS_BUSY);

    if (size == MT25QU01G_SECTOR_SIZE) {
        cmd[0] = MT25QU01G_CMD_ERASE_SECTOR;
        cmd[1] = addr >> 16;
        cmd[2] = addr >> 8;
        cmd[3] = addr;
        ret = spi_write(priv->spi, cmd, sizeof(cmd));
        if (ret)
            return ret;
    } else if (size == MT25QU01G_FLASH_SIZE) {
        cmd[0] = MT25QU01G_CMD_ERASE_CHIP;
        ret = spi_write(priv->spi, cmd, sizeof(cmd));
        if (ret)
            return ret;
    } else {
        return -EINVAL;
    }

    cmd[0] = MT25QU01G_CMD_READ_STATUS;
    do {
        ret = spi_xfer(priv->spi, cmd, cmd, sizeof(cmd));
        if (ret)
            return ret;
        status = cmd[1];
    } while (status & MT25QU01G_STATUS_BUSY);

    return 0;
}

static int mt25qu01g_spi_flash_probe(struct udevice *dev)
{
    struct mt25qu01g_spi_flash *priv = dev_get_priv(dev);
    struct spi_slave *spi;
    int ret;

    ret = spi_get_slave(dev, &spi);
    if (ret)
        return ret;

    priv->spi = spi;

    return 0;
}

static const struct spi_flash_ops mt25qu01g_spi_flash_ops = {
    .read = mt25qu01g_spi_flash_read,
    .write = mt25qu01g_spi_flash_write,
    .erase = mt25qu01g_spi_flash_erase,
};

static const struct udevice_id mt25qu01g_spi_flash_ids[] = {
    { .compatible = "micron,mt25qu01g" },
    { }
};

U_BOOT_DRIVER(mt25qu01g_spi_flash) = {
    .name = "mt25qu01g_spi_flash",
    .id = UCLASS_SPI_FLASH,
    .of_match = mt25qu01g_spi_flash_ids,
    .probe = mt25qu01g_spi_flash_probe,
    .priv_auto_alloc_size = sizeof(struct mt25qu01g_spi_flash),
    .ops = &mt25qu01g_spi_flash_ops,
};

该驱动程序使用spi_xfer()函数来发送和接收数据,该函数由U-Boot的SPI API提供。该驱动程序还使用了MT25QU01G闪存器件的一些命令,如读取、写入、擦除和读取状态。此外,该驱动程序还实现了spi_flash_ops结构体中定义的read()write()erase()函数,以便U-Boot可以使用这些函数来读取、写入和擦除闪存。

最后,该驱动程序还定义了一个U-Boot设备驱动程序,以便它可以被U-Boot识别并加载到内存中。此设备驱动程序使用的设备ID是与MT25QU01G SPI NOR闪存器件兼容的。

写一个uboot下的MT25QU01G驱动

原文地址: https://www.cveoy.top/t/topic/ADZ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录