mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
205 lines
3.8 KiB
C
205 lines
3.8 KiB
C
|
// SPDX-License-Identifier: GPL-2.0+
|
||
|
/*
|
||
|
*
|
||
|
* Driver interface derived from:
|
||
|
* /cmd/host.c
|
||
|
* Copyright (c) 2012, Google Inc.
|
||
|
*
|
||
|
* Copyright (C) 2023 Johan Jonker <jbx6244@gmail.com>
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <blk.h>
|
||
|
#include <command.h>
|
||
|
#include <dm.h>
|
||
|
#include <rkmtd.h>
|
||
|
#include <stdio.h>
|
||
|
#include <dm/device-internal.h>
|
||
|
#include <dm/uclass-internal.h>
|
||
|
|
||
|
static int do_rkmtd_bind(struct cmd_tbl *cmdtp, int flag, int argc,
|
||
|
char *const argv[])
|
||
|
{
|
||
|
struct udevice *dev;
|
||
|
const char *label;
|
||
|
int ret;
|
||
|
|
||
|
argc--;
|
||
|
argv++;
|
||
|
|
||
|
if (argc < 1)
|
||
|
return CMD_RET_USAGE;
|
||
|
|
||
|
if (argc > 1)
|
||
|
return CMD_RET_USAGE;
|
||
|
|
||
|
label = argv[0];
|
||
|
ret = rkmtd_create_attach_mtd(label, &dev);
|
||
|
if (ret) {
|
||
|
printf("Cannot create device / bind mtd\n");
|
||
|
return CMD_RET_FAILURE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static struct udevice *parse_rkmtd_label(const char *label)
|
||
|
{
|
||
|
struct udevice *dev;
|
||
|
|
||
|
dev = rkmtd_find_by_label(label);
|
||
|
if (!dev) {
|
||
|
int devnum;
|
||
|
char *ep;
|
||
|
|
||
|
devnum = hextoul(label, &ep);
|
||
|
if (*ep ||
|
||
|
uclass_find_device_by_seq(UCLASS_RKMTD, devnum, &dev)) {
|
||
|
printf("No such device '%s'\n", label);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dev;
|
||
|
}
|
||
|
|
||
|
static int do_rkmtd_unbind(struct cmd_tbl *cmdtp, int flag, int argc,
|
||
|
char *const argv[])
|
||
|
{
|
||
|
struct udevice *dev;
|
||
|
const char *label;
|
||
|
int ret;
|
||
|
|
||
|
if (argc < 2)
|
||
|
return CMD_RET_USAGE;
|
||
|
|
||
|
label = argv[1];
|
||
|
dev = parse_rkmtd_label(label);
|
||
|
if (!dev)
|
||
|
return CMD_RET_FAILURE;
|
||
|
|
||
|
ret = rkmtd_detach(dev);
|
||
|
if (ret) {
|
||
|
printf("Cannot detach mtd\n");
|
||
|
return CMD_RET_FAILURE;
|
||
|
}
|
||
|
|
||
|
ret = device_unbind(dev);
|
||
|
if (ret) {
|
||
|
printf("Cannot unbind device '%s'\n", dev->name);
|
||
|
return CMD_RET_FAILURE;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void show_rkmtd_dev(struct udevice *dev)
|
||
|
{
|
||
|
struct rkmtd_dev *plat = dev_get_plat(dev);
|
||
|
struct blk_desc *desc;
|
||
|
struct udevice *blk;
|
||
|
int ret;
|
||
|
|
||
|
printf("%3d ", dev_seq(dev));
|
||
|
|
||
|
ret = blk_get_from_parent(dev, &blk);
|
||
|
if (ret)
|
||
|
return;
|
||
|
|
||
|
desc = dev_get_uclass_plat(blk);
|
||
|
printf("%12lu %-15s\n", (unsigned long)desc->lba, plat->label);
|
||
|
}
|
||
|
|
||
|
static int do_rkmtd_info(struct cmd_tbl *cmdtp, int flag, int argc,
|
||
|
char *const argv[])
|
||
|
{
|
||
|
struct udevice *dev;
|
||
|
|
||
|
if (argc < 1)
|
||
|
return CMD_RET_USAGE;
|
||
|
|
||
|
dev = NULL;
|
||
|
if (argc >= 2) {
|
||
|
dev = parse_rkmtd_label(argv[1]);
|
||
|
if (!dev)
|
||
|
return CMD_RET_FAILURE;
|
||
|
}
|
||
|
|
||
|
printf("%3s %12s %-15s\n", "dev", "blocks", "label");
|
||
|
if (dev) {
|
||
|
show_rkmtd_dev(dev);
|
||
|
} else {
|
||
|
struct uclass *uc;
|
||
|
|
||
|
uclass_id_foreach_dev(UCLASS_RKMTD, dev, uc)
|
||
|
show_rkmtd_dev(dev);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int do_rkmtd_dev(struct cmd_tbl *cmdtp, int flag, int argc,
|
||
|
char *const argv[])
|
||
|
{
|
||
|
struct udevice *dev;
|
||
|
const char *label;
|
||
|
|
||
|
if (argc < 1 || argc > 3)
|
||
|
return CMD_RET_USAGE;
|
||
|
|
||
|
if (argc == 1) {
|
||
|
struct rkmtd_dev *plat;
|
||
|
|
||
|
dev = rkmtd_get_cur_dev();
|
||
|
if (!dev) {
|
||
|
printf("No current rkmtd device\n");
|
||
|
return CMD_RET_FAILURE;
|
||
|
}
|
||
|
plat = dev_get_plat(dev);
|
||
|
printf("Current rkmtd device: %d: %s\n", dev_seq(dev),
|
||
|
plat->label);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
label = argv[1];
|
||
|
dev = parse_rkmtd_label(argv[1]);
|
||
|
if (!dev)
|
||
|
return CMD_RET_FAILURE;
|
||
|
|
||
|
rkmtd_set_cur_dev(dev);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static struct cmd_tbl cmd_rkmtd_sub[] = {
|
||
|
U_BOOT_CMD_MKENT(bind, 4, 0, do_rkmtd_bind, "", ""),
|
||
|
U_BOOT_CMD_MKENT(unbind, 4, 0, do_rkmtd_unbind, "", ""),
|
||
|
U_BOOT_CMD_MKENT(info, 3, 0, do_rkmtd_info, "", ""),
|
||
|
U_BOOT_CMD_MKENT(dev, 0, 1, do_rkmtd_dev, "", ""),
|
||
|
};
|
||
|
|
||
|
static int do_rkmtd(struct cmd_tbl *cmdtp, int flag, int argc,
|
||
|
char *const argv[])
|
||
|
{
|
||
|
struct cmd_tbl *c;
|
||
|
|
||
|
argc--;
|
||
|
argv++;
|
||
|
|
||
|
c = find_cmd_tbl(argv[0], cmd_rkmtd_sub, ARRAY_SIZE(cmd_rkmtd_sub));
|
||
|
|
||
|
if (c)
|
||
|
return c->cmd(cmdtp, flag, argc, argv);
|
||
|
else
|
||
|
return CMD_RET_USAGE;
|
||
|
}
|
||
|
|
||
|
U_BOOT_CMD(
|
||
|
rkmtd, 8, 1, do_rkmtd,
|
||
|
"Rockchip MTD sub-system",
|
||
|
"bind <label> - bind RKMTD device\n"
|
||
|
"rkmtd unbind <label> - unbind RKMTD device\n"
|
||
|
"rkmtd info [<label>] - show all available RKMTD devices\n"
|
||
|
"rkmtd dev [<label>] - show or set current RKMTD device\n"
|
||
|
);
|