Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mtd: rawnand: Add Phytium NAND flash controller support
Browse files Browse the repository at this point in the history
This patch implements a device driver of NAND flash controller
for both Phytium PCIe chipset and SoCs. Since interrupt flags
depends on the bus implementation, e.g., PCI vs platform,
we extract the interrupt register function from NFC driver core.

Signed-off-by: Zhu Mingshuai <[email protected]>
Signed-off-by: Zhou Yulin <[email protected]>
Signed-off-by: Chen Baozi <[email protected]>
Signed-off-by: Wang Yinfeng <[email protected]>
Signed-off-by: Hu Yeqing <[email protected]>
Hu Yeqing authored and MingcongBai committed May 29, 2024
1 parent 70ad6fc commit 9264883
Showing 7 changed files with 2,891 additions and 0 deletions.
42 changes: 42 additions & 0 deletions Documentation/devicetree/bindings/mtd/phytium,nfc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mtd/phytium,nfc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Phytium Nand Flash controller

maintainers:
- Chen Baozi <[email protected]>

properties:
compatible:
const: phytium,nfc

reg:
maxItems: 1

interrupts:
maxItems: 1

nand-ecc-strength:
const: 8

nand-ecc-step-size:
const: 512

allOf:
- $ref: "nand-controller.yaml#"

required:
- compatible
- reg
- interrupts

examples:
- |
nand0: nand@28002000 {
compatible = "phytium,nfc";
reg = <0x0 0x28002000 0x0 0x1000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
};
19 changes: 19 additions & 0 deletions drivers/mtd/nand/raw/Kconfig
Original file line number Diff line number Diff line change
@@ -150,6 +150,25 @@ config MTD_NAND_ORION
No board specific support is done by this driver, each board
must advertise a platform_device for the driver to attach.

config MTD_NAND_PHYTIUM
tristate

config MTD_NAND_PHYTIUM_PCI
tristate "Support Phytium NAND controller as a PCI device"
select MTD_NAND_PHYTIUM
depends on PCI
help
Enable the driver for NAND flash controller of Phytium Px210 chipset,
using the Phytium NAND controller core.

config MTD_NAND_PHYTIUM_PLAT
tristate "Support Phytium NAND controller as a platform device"
select MTD_NAND_PHYTIUM
depends on ARCH_PHYTIUM
help
Enable the driver for NAND flash controller of Phytium CPU chipset,
using the Phytium NAND controller core.

config MTD_NAND_MARVELL
tristate "Marvell EBU NAND controller"
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
3 changes: 3 additions & 0 deletions drivers/mtd/nand/raw/Makefile
Original file line number Diff line number Diff line change
@@ -57,6 +57,9 @@ obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o
obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o
obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o
obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o
obj-$(CONFIG_MTD_NAND_PHYTIUM) += phytium_nand.o
obj-$(CONFIG_MTD_NAND_PHYTIUM_PCI) += phytium_nand_pci.o
obj-$(CONFIG_MTD_NAND_PHYTIUM_PLAT) += phytium_nand_plat.o

nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
nand-objs += nand_onfi.o
2,090 changes: 2,090 additions & 0 deletions drivers/mtd/nand/raw/phytium_nand.c

Large diffs are not rendered by default.

449 changes: 449 additions & 0 deletions drivers/mtd/nand/raw/phytium_nand.h

Large diffs are not rendered by default.

150 changes: 150 additions & 0 deletions drivers/mtd/nand/raw/phytium_nand_pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// SPDX-License-Identifier: GPL-2.0
/*
* PCI driver for Phytium NAND flash controller
*
* Copyright (C) 2021-2023, Phytium Technology Co., Ltd.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/device.h>

#include "phytium_nand.h"

#define DRV_NAME "phytium_nand_pci"

static struct mtd_partition partition_info[] = {
{
.name = "Flash partition 1",
.offset = 0x0000000,
.size = 0x4000000 },
{
.name = "Flash partition 2",
.offset = 0x4000000,
.size = 0x8000000 },
{
.name = "Flash partition 3",
.offset = 0x8000000,
.size = 0x10000000 },
{
.name = "Flash partition 4",
.offset = 0x10000000,
.size = 0x12000000 },
{
.name = "Flash partition 5",
.offset = 0x12000000,
.size = 0x14000000 },
};

static struct phytium_nfc_caps x100_nfc_caps = {
.hw_ver = 1,
.int_mask_bits = 13,
.max_cs_nb = 2,
.max_rb_nb = 1,
.legacy_of_bindings = true,
.ecc_strength = 4,
.ecc_step_size = 512,
.nr_parts = 5,
.parts = partition_info,
};

static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
{
struct phytium_nfc *nfc;
int ret;

ret = pcim_enable_device(pdev);
if (ret)
return ret;

ret = pcim_iomap_regions(pdev, 0x1, pci_name(pdev));
if (ret) {
dev_err(&pdev->dev, "I/O memory remapping failed\n");
return ret;
}

pci_set_master(pdev);
pci_try_set_mwi(pdev);

nfc = devm_kzalloc(&pdev->dev, sizeof(struct phytium_nfc),
GFP_KERNEL);
if (!nfc)
return -ENOMEM;

nfc->dev = &pdev->dev;
nfc->regs = pcim_iomap_table(pdev)[0];
nfc->irq = pdev->irq;
nfc->caps = &x100_nfc_caps;

ret = devm_request_irq(nfc->dev, nfc->irq, phytium_nfc_isr,
IRQF_SHARED, "phytium-nfc-pci", nfc);
if (ret) {
dev_err(nfc->dev, "Failed to register NFC interrupt.\n");
return ret;
}

ret = phytium_nand_init(nfc);
if (ret)
return ret;

pci_set_drvdata(pdev, nfc);

return ret;
}

static void phytium_pci_remove(struct pci_dev *pdev)
{
struct phytium_nfc *nfc = pci_get_drvdata(pdev);
int ret;

ret = phytium_nand_remove(nfc);
if (ret)
dev_warn(&pdev->dev, "can't remove device properly: %d\n", ret);
}

static int __maybe_unused phytium_nfc_prepare(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
struct phytium_nfc *nfc = pci_get_drvdata(pci);
int ret;

ret = phytium_nand_prepare(nfc);

return 0;
}

static int __maybe_unused phytium_nfc_resume(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
struct phytium_nfc *nfc = pci_get_drvdata(pci);
int ret;

ret = phytium_nand_resume(nfc);

return ret;
}

static const struct dev_pm_ops phytium_pci_dev_pm_ops = {
.prepare = phytium_nfc_prepare,
.resume = phytium_nfc_resume,
};

static const struct pci_device_id phytium_pci_id_table[] = {
{ PCI_VDEVICE(PHYTIUM, 0xdc29) },
{ }
};
MODULE_DEVICE_TABLE(pci, phytium_pci_id_table);

static struct pci_driver phytium_pci_driver = {
.name = DRV_NAME,
.id_table = phytium_pci_id_table,
.probe = phytium_pci_probe,
.remove = phytium_pci_remove,
.driver = {
.pm = &phytium_pci_dev_pm_ops,
},
};
module_pci_driver(phytium_pci_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCI driver for Phytium NAND controller");
MODULE_AUTHOR("Zhu Mingshuai <zhumingshuai@phytium.com.cn>");
138 changes: 138 additions & 0 deletions drivers/mtd/nand/raw/phytium_nand_plat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Core driver for Phytium NAND flash controller
*
* Copyright (C) 2020-2023, Phytium Technology Co., Ltd.
*/

#include <linux/module.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/acpi.h>
#include <linux/acpi_dma.h>

#include "phytium_nand.h"

#define DRV_NAME "phytium_nand_plat"

static int phytium_nfc_plat_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *r;
struct phytium_nfc *nfc;
unsigned int ecc_strength;
unsigned int ecc_step_size;
int ret;

nfc = devm_kzalloc(&pdev->dev, sizeof(struct phytium_nfc),
GFP_KERNEL);
if (!nfc)
return -ENOMEM;

nfc->dev = dev;

r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
nfc->regs = devm_ioremap_resource(dev, r);
if (IS_ERR(nfc->regs))
return PTR_ERR(nfc->regs);

dev_info(nfc->dev, "NFC register address :%p, phy address:%llx\n",
nfc->regs, r->start);

nfc->irq = platform_get_irq(pdev, 0);
if (nfc->irq < 0) {
dev_err(dev, "failed to retrieve irq\n");
return nfc->irq;
}

ret = devm_request_irq(dev, nfc->irq, phytium_nfc_isr, 0,
"phytium-nfc-plat", nfc);
if (ret) {
dev_err(nfc->dev, "Failed to register NFC interrupt.\n");
return ret;
}

nfc->caps = devm_kzalloc(dev, sizeof(struct phytium_nfc_caps), GFP_KERNEL);
if (!nfc->caps)
return -ENOMEM;

/* Currently hard-coded parameters */
nfc->caps->hw_ver = 2;
nfc->caps->int_mask_bits = 17;
nfc->caps->max_cs_nb = 4;
nfc->caps->max_rb_nb = 4;
nfc->caps->nr_parts = 0;
nfc->caps->parts = NULL;

device_property_read_u32(&pdev->dev, "nand-ecc-strength", &ecc_strength);
nfc->caps->ecc_strength = ecc_strength ? ecc_strength : 8;

device_property_read_u32(&pdev->dev, "nand-ecc-step-size", &ecc_step_size);
nfc->caps->ecc_step_size = ecc_step_size ? ecc_step_size : 512;

ret = phytium_nand_init(nfc);
if (ret)
return ret;

platform_set_drvdata(pdev, nfc);

return ret;
}

static int phytium_nfc_plat_remove(struct platform_device *pdev)
{
struct phytium_nfc *nfc = platform_get_drvdata(pdev);

return phytium_nand_remove(nfc);
}

static int __maybe_unused phytium_nfc_plat_prepare(struct device *dev)
{
struct phytium_nfc *nfc = dev_get_drvdata(dev);

return phytium_nand_prepare(nfc);
}

static int __maybe_unused phytium_nfc_plat_resume(struct device *dev)
{
struct phytium_nfc *nfc = dev_get_drvdata(dev);
int ret;

ret = phytium_nand_resume(nfc);

return ret;
}

static const struct dev_pm_ops phytium_dev_pm_ops = {
.prepare = phytium_nfc_plat_prepare,
.resume = phytium_nfc_plat_resume,
};

#ifdef CONFIG_OF
static const struct of_device_id phytium_nfc_of_ids[] = {
{ .compatible = "phytium,nfc", },
{ }
};
MODULE_DEVICE_TABLE(of, phytium_nfc_of_ids);
#endif

static struct platform_driver phytium_nfc_plat_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = phytium_nfc_of_ids,
.pm = &phytium_dev_pm_ops,
},
.probe = phytium_nfc_plat_probe,
.remove = phytium_nfc_plat_remove,
};
module_platform_driver(phytium_nfc_plat_driver)

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Phytium NAND controller Platform driver");
MODULE_AUTHOR("Zhu Mingshuai <zhumingshuai@phytium.com.cn>");

0 comments on commit 9264883

Please sign in to comment.