android13/u-boot/drivers/rknand/rknand.c

239 lines
4.6 KiB
C
Raw Normal View History

2024-06-22 08:45:49 -04:00
/*
* Copyright (C) (C) Copyright 2016-2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/vendor.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/root.h>
#include "rknand.h"
struct blk_desc *rknand_get_blk_desc(struct rknand_dev *ndev)
{
struct blk_desc *desc;
struct udevice *dev;
device_find_first_child(ndev->dev, &dev);
if (!dev)
return NULL;
desc = dev_get_uclass_platdata(dev);
return desc;
}
ulong rknand_bread(struct udevice *udev, lbaint_t start,
lbaint_t blkcnt, void *dst)
{
struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
struct rknand_dev *ndev = dev_get_priv(udev->parent);
int err;
if (blkcnt == 0)
return 0;
if ((start + blkcnt) > block_dev->lba)
return 0;
if (ndev->read == NULL)
return 0;
err = ndev->read(0, (u32)start, (u32)blkcnt, dst);
if (err)
return err;
return blkcnt;
}
ulong rknand_bwrite(struct udevice *udev, lbaint_t start,
lbaint_t blkcnt, const void *src)
{
struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
struct rknand_dev *ndev = dev_get_priv(udev->parent);
int err;
if (blkcnt == 0)
return 0;
if ((start + blkcnt) > block_dev->lba)
return 0;
if (ndev->write == NULL)
return 0;
err = ndev->write(0, (u32)start, (u32)blkcnt, src);
if (err)
return err;
return blkcnt;
}
ulong rknand_berase(struct udevice *udev, lbaint_t start,
lbaint_t blkcnt)
{
struct blk_desc *block_dev = dev_get_uclass_platdata(udev);
struct rknand_dev *ndev = dev_get_priv(udev->parent);
int err;
if (blkcnt == 0)
return 0;
if ((start + blkcnt) > block_dev->lba)
return 0;
if (ndev->erase == NULL)
return 0;
err = ndev->erase(0, (u32)start, (u32)blkcnt);
if (err)
return err;
return blkcnt;
}
int rkftl_nand_vendor_read(struct blk_desc *dev_desc,
u32 index,
u32 n_sec,
void *p_data)
{
int ret;
ret = ftl_vendor_read(index, n_sec, p_data);
if (!ret)
return n_sec;
else
return -EIO;
}
int rkftl_nand_vendor_write(struct blk_desc *dev_desc,
u32 index,
u32 n_sec,
void *p_data)
{
int ret;
ret = ftl_vendor_write(index, n_sec, p_data);
if (!ret)
return n_sec;
else
return -EIO;
}
int rknand_scan_namespace(void)
{
struct uclass *uc;
struct udevice *dev;
int ret;
ret = uclass_get(UCLASS_RKNAND, &uc);
if (ret)
return ret;
uclass_foreach_dev(dev, uc) {
debug("%s %d %p\n", __func__, __LINE__, dev);
ret = device_probe(dev);
if (ret)
return ret;
}
return 0;
}
static int rknand_blk_bind(struct udevice *udev)
{
struct udevice *bdev;
int ret;
ret = blk_create_devicef(udev, "rknand_blk", "blk",
IF_TYPE_RKNAND,
0, 512, 0, &bdev);
if (ret) {
debug("Cannot create block device\n");
return ret;
}
return 0;
}
static int rknand_blk_probe(struct udevice *udev)
{
struct rknand_dev *ndev = dev_get_priv(udev->parent);
struct blk_desc *desc = dev_get_uclass_platdata(udev);
debug("%s %d %p ndev = %p %p\n", __func__, __LINE__,
udev, ndev, udev->parent);
ndev->dev = udev;
desc->if_type = IF_TYPE_RKNAND;
desc->lba = ndev->density;
desc->log2blksz = 9;
desc->blksz = 512;
desc->bdev = udev;
desc->devnum = 0;
sprintf(desc->vendor, "0x%.4x", 0x2207);
memcpy(desc->product, "rknand", sizeof("rknand"));
memcpy(desc->revision, "V1.00", sizeof("V1.00"));
part_init(desc);
return 0;
}
static int rockchip_nand_probe(struct udevice *udev)
{
int ret;
struct rknand_dev *ndev = dev_get_priv(udev);
ndev->ioaddr = dev_read_addr_ptr(udev);
ret = rk_ftl_init(ndev->ioaddr);
if (!ret) {
ndev->density = ftl_get_density(0);
ndev->read = ftl_read;
ndev->write = ftl_write;
ndev->erase = ftl_discard;
#ifndef CONFIG_SPL_BUILD
#ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
flash_vendor_dev_ops_register(rkftl_nand_vendor_read,
rkftl_nand_vendor_write);
#endif
#endif
}
return ret;
}
static const struct blk_ops rknand_blk_ops = {
.read = rknand_bread,
.write = rknand_bwrite,
.erase = rknand_berase,
};
static const struct udevice_id rockchip_nand_ids[] = {
{ .compatible = "rockchip,rk-nandc" },
{ }
};
U_BOOT_DRIVER(rknand_blk) = {
.name = "rknand_blk",
.id = UCLASS_BLK,
.ops = &rknand_blk_ops,
.probe = rknand_blk_probe,
};
UCLASS_DRIVER(rknand) = {
.id = UCLASS_RKNAND,
.name = "rknand",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.per_device_auto_alloc_size = sizeof(struct rknand_uclass_priv),
};
U_BOOT_DRIVER(rknand) = {
.name = "rknand",
.id = UCLASS_RKNAND,
.of_match = rockchip_nand_ids,
.bind = rknand_blk_bind,
.probe = rockchip_nand_probe,
.priv_auto_alloc_size = sizeof(struct rknand_dev),
};