mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
mtd: spi-nor: core: Support misc devices
Calling ioctl PCIE_DMA_GET_FLASH_INFO to get spi nor id. Change-Id: I1ecfdd527f18c0c323fba9673546c167032d1726 Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
@@ -24,6 +24,13 @@ config MTD_SPI_NOR_USE_4K_SECTORS
|
||||
Please note that some tools/drivers/filesystems may not work with
|
||||
4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
|
||||
|
||||
config MTD_SPI_NOR_MISC
|
||||
bool "Support SPI NOR misc device"
|
||||
default n
|
||||
help
|
||||
Support obtaining flash information through the ioctl interface
|
||||
of the misc device.
|
||||
|
||||
source "drivers/mtd/spi-nor/controllers/Kconfig"
|
||||
|
||||
endif # MTD_SPI_NOR
|
||||
|
||||
@@ -21,9 +21,17 @@
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <linux/mtd/spi-nor.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
#include <uapi/linux/spi_nor_misc.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct spi_nor_misc_dev {
|
||||
struct miscdevice dev;
|
||||
struct spi_nor *nor;
|
||||
};
|
||||
|
||||
/* Define max times to check status register before we give up. */
|
||||
|
||||
/*
|
||||
@@ -3462,6 +3470,78 @@ static int spi_nor_create_write_dirmap(struct spi_nor *nor)
|
||||
return PTR_ERR_OR_ZERO(nor->dirmap.wdesc);
|
||||
}
|
||||
|
||||
static int spi_nor_misc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct miscdevice *miscdev = file->private_data;
|
||||
struct spi_nor_misc_dev *nor_dev;
|
||||
|
||||
nor_dev = container_of(miscdev, struct spi_nor_misc_dev, dev);
|
||||
file->private_data = nor_dev->nor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long spi_nor_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct spi_nor *nor = (struct spi_nor *)file->private_data;
|
||||
struct nor_flash_user_info info;
|
||||
void __user *uarg = (void __user *)arg;
|
||||
int i, ret;
|
||||
|
||||
switch (cmd) {
|
||||
case NOR_GET_FLASH_INFO:
|
||||
for (i = 0; i < SPI_NOR_MAX_ID_LEN; i++)
|
||||
info.id[i] = nor->info->id[i];
|
||||
|
||||
ret = copy_to_user(uarg, &info, sizeof(info));
|
||||
if (ret) {
|
||||
dev_err(nor->dev, "failed to get elbi data\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations spi_nor_misc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = spi_nor_misc_open,
|
||||
.unlocked_ioctl = spi_nor_misc_ioctl,
|
||||
};
|
||||
|
||||
static int spi_nor_add_misc(struct spi_nor *nor)
|
||||
{
|
||||
int ret;
|
||||
struct spi_nor_misc_dev *nor_dev;
|
||||
char name[24];
|
||||
|
||||
nor_dev = devm_kzalloc(nor->dev, sizeof(struct spi_nor_misc_dev),
|
||||
GFP_KERNEL);
|
||||
if (!nor_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
nor_dev->dev.minor = MISC_DYNAMIC_MINOR;
|
||||
snprintf(name, sizeof(name), "%s%s", "nor_misc_", dev_name(nor->dev));
|
||||
nor_dev->dev.name = devm_kstrdup(nor->dev, name, GFP_KERNEL);
|
||||
nor_dev->dev.fops = &spi_nor_misc_ops;
|
||||
nor_dev->dev.parent = nor->dev;
|
||||
|
||||
ret = misc_register(&nor_dev->dev);
|
||||
if (ret) {
|
||||
dev_err(nor->dev, "failed to register misc device.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
nor_dev->nor = nor;
|
||||
nor->misc_dev = &nor_dev->dev;
|
||||
|
||||
dev_info(nor->dev, "register misc device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_nor_probe(struct spi_mem *spimem)
|
||||
{
|
||||
struct spi_device *spi = spimem->spi;
|
||||
@@ -3531,6 +3611,9 @@ static int spi_nor_probe(struct spi_mem *spimem)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MTD_SPI_NOR_MISC))
|
||||
spi_nor_add_misc(nor);
|
||||
|
||||
return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
|
||||
data ? data->nr_parts : 0);
|
||||
}
|
||||
@@ -3541,6 +3624,9 @@ static int spi_nor_remove(struct spi_mem *spimem)
|
||||
|
||||
spi_nor_restore(nor);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MTD_SPI_NOR_MISC) && nor->misc_dev)
|
||||
misc_deregister(nor->misc_dev);
|
||||
|
||||
/* Clean up MTD stuff. */
|
||||
return mtd_device_unregister(&nor->mtd);
|
||||
}
|
||||
|
||||
@@ -388,6 +388,7 @@ struct spi_nor {
|
||||
struct spi_mem_dirmap_desc *wdesc;
|
||||
} dirmap;
|
||||
|
||||
struct miscdevice *misc_dev;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
|
||||
20
include/uapi/linux/spi_nor_misc.h
Normal file
20
include/uapi/linux/spi_nor_misc.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI__SPI_NOR_MISC_H__
|
||||
#define _UAPI__SPI_NOR_MISC_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define SPI_NOR_MAX_ID_LEN 6
|
||||
|
||||
struct nor_flash_user_info {
|
||||
__u8 id[SPI_NOR_MAX_ID_LEN];
|
||||
};
|
||||
|
||||
#define NOR_BASE 'P'
|
||||
#define NOR_GET_FLASH_INFO _IOR(NOR_BASE, 0, struct nor_flash_user_info)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user