Skip to content

Commit

Permalink
arm64: phytium: UEFI mode acpi table support for qspi/spi driver
Browse files Browse the repository at this point in the history
Add acpi table support for qspi/spi driver, supporting
parsing of ACPI tables.

Signed-off-by: yuanxia <[email protected]>
Signed-off-by: Wang Hanmo <[email protected]>
Signed-off-by: Wang Yinfeng <[email protected]>
  • Loading branch information
yuanxia0927 committed May 21, 2024
1 parent 8970680 commit 4c414a4
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 25 deletions.
45 changes: 44 additions & 1 deletion drivers/mtd/mtdpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <linux/of.h>
#include <linux/of_platform.h>

#include <linux/acpi.h>
#include <linux/property.h>
#include "mtdcore.h"

/*
Expand Down Expand Up @@ -504,12 +506,14 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
static const char * const default_mtd_part_types[] = {
"cmdlinepart",
"ofpart",
"acpipart",
NULL
};

/* Check DT only when looking for subpartitions. */
static const char * const default_subpartition_types[] = {
"ofpart",
"acpipart",
NULL
};

Expand Down Expand Up @@ -573,6 +577,43 @@ static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat
return ret;
}

static int mtd_part_acpi_parse(struct mtd_info *master,
struct mtd_partitions *pparts)
{
struct mtd_part_parser *parser;
struct acpi_device *adev;
struct fwnode_handle *child;
const char *compat;
const char *fixed = "acpi-fixed-partitions";
int ret, err = 0;
int compare = 1;
struct device *dev = &master->dev;

if (!mtd_is_partition(master)) {
fwnode_property_read_string(dev->fwnode, "fixed", &compat);
if (compat)
compare = strcmp(compat, fixed);
}

//all child node
device_for_each_child_node(dev, child) {
if (compat && !compare) {
parser = mtd_part_parser_get(fixed);
if (!parser && !request_module("%s", fixed))
parser = mtd_part_parser_get(fixed);
if (parser) {
ret = mtd_part_do_parse(parser, master, pparts, NULL);
if (ret > 0)
return ret;
mtd_part_parser_put(parser);
if (ret < 0 && !err)
err = ret;
}
}
}
return err;
}

static int mtd_part_of_parse(struct mtd_info *master,
struct mtd_partitions *pparts)
{
Expand Down Expand Up @@ -678,7 +719,9 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
* should be used. It requires a bit different logic so it is
* handled in a separated function.
*/
if (!strcmp(*types, "ofpart")) {
if (!strcmp(*types, "acpipart")) {
ret = mtd_part_acpi_parse(master, &pparts);
} else if (!strcmp(*types, "ofpart")) {
ret = mtd_part_of_parse(master, &pparts);
} else {
pr_debug("%s: parsing partitions %s\n", master->name,
Expand Down
8 changes: 8 additions & 0 deletions drivers/mtd/parsers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ config MTD_OF_PARTS_LINKSYS_NS
two "firmware" partitions. Currently used firmware has to be detected
using CFE environment variable.

config MTD_ACPI_PARTS
tristate "ACPI partitioning parser"
depends on ACPI && (ARCH_PHYTIUM || COMPILE_TEST)
help
This provides an acpi partition parser, which is used to parse the
partition map described in ACPI table, as the children of the flash
memory struct.

config MTD_PARSER_IMAGETAG
tristate "Parser for BCM963XX Image Tag format partitions"
depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
Expand Down
2 changes: 2 additions & 0 deletions drivers/mtd/parsers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
ofpart-y += ofpart_core.o
ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o
obj-$(CONFIG_MTD_ACPI_PARTS) += acpipart.o
acpipart-y += acpipart_core.o
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o
Expand Down
143 changes: 143 additions & 0 deletions drivers/mtd/parsers/acpipart_core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Flash partitions described by the acpi table
*
* Author: Wang Hanmo <[email protected]>
*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/slab.h>
#include <linux/mtd/partitions.h>
#include <linux/property.h>
#include <linux/acpi.h>

static const struct acpi_device_id parse_acpipart_match_table[];

static int parse_acpi_fixed_partitions(struct mtd_info *master,
const struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
{
struct mtd_partition *parts;
struct acpi_device_id *acpi_id;
const char *partname;
int nr_parts, i, ret = 0;
struct acpi_device *adev;
struct fwnode_handle *child;
struct fwnode_handle *child_handle;
bool dedicated = true;
struct device *dev;

dev = &master->dev;
adev = ACPI_COMPANION(&master->dev);

if (!master->parent) {/*master*/
device_get_next_child_node(dev, child_handle);
if (!child_handle) {
pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n",
master->name, child_handle);
dedicated = false;
}
}

acpi_id = acpi_match_device(parse_acpipart_match_table, dev);
if (dedicated && !acpi_id)
return 0;

nr_parts = 0;
device_for_each_child_node(dev, child_handle) {
nr_parts++;
}

if (nr_parts == 0)
return 0;
parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
if (!parts)
return -ENOMEM;

i = 0;
device_for_each_child_node(dev, child_handle) {
u64 offset, length;
bool bool_match;

fwnode_property_read_u64(child_handle, "offset", &offset);
fwnode_property_read_u64(child_handle, "length", &length);
if (!offset && !length) {
if (dedicated) {
pr_debug("%s: acpipart partition %pOF (%pOF) missing reg property.\n",
master->name, child_handle,
dev->fwnode);
goto acpipart_fail;
} else {
nr_parts--;
continue;
}
}

parts[i].offset = offset;
parts[i].size = length;
parts[i].fwnode = child_handle;
if (!fwnode_property_read_string(child_handle, "label", &partname))
parts[i].name = partname;
bool_match = fwnode_property_read_bool(child_handle, "read-only");
if (bool_match)
parts[i].mask_flags |= MTD_WRITEABLE;
bool_match = fwnode_property_read_bool(child_handle, "lock");
if (bool_match)
parts[i].mask_flags |= MTD_POWERUP_LOCK;
bool_match = fwnode_property_read_bool(child_handle, "slc-mode");
if (bool_match)
parts[i].mask_flags |= MTD_SLC_ON_MLC_EMULATION;
i++;
}

if (!nr_parts)
goto acpipart_none;

*pparts = parts;
ret = nr_parts;
return ret;

acpipart_fail:
pr_err("%s: error parsing acpipart partition %pOF (%pOF)\n",
master->name, child_handle, dev->fwnode);
ret = -EINVAL;
acpipart_none:
kfree(parts);
return ret;
}

static const struct acpi_device_id parse_acpipart_match_table[] = {
/* Generic */
{ "acpi-fixed-partitions", 0 },
/* Customized */
{},
};

MODULE_DEVICE_TABLE(acpi, parse_acpipart_match_table);

static struct mtd_part_parser acpipart_parser = {
.parse_fn = parse_acpi_fixed_partitions,
.name = "acpi-fixed-partitions",
.acpi_match_table = ACPI_PTR(parse_acpipart_match_table),
};

static int __init acpipart_parser_init(void)
{
register_mtd_parser(&acpipart_parser);
return 0;
}

static void __exit acpipart_parser_exit(void)
{
deregister_mtd_parser(&acpipart_parser);
}

module_init(acpipart_parser_init);
module_exit(acpipart_parser_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parser for MTD partitioning information in acpi table");
MODULE_AUTHOR("wanghanmo <[email protected]>");
MODULE_ALIAS("acpi-fixed-partitions");
13 changes: 13 additions & 0 deletions drivers/mtd/spi-nor/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Copyright (C) 2014, Freescale Semiconductor, Inc.
*/

#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/delay.h>
Expand All @@ -17,6 +18,7 @@
#include <linux/mtd/spi-nor.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/property.h>
#include <linux/sched/task_stack.h>
#include <linux/sizes.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -3621,6 +3623,7 @@ static int spi_nor_probe(struct spi_mem *spimem)
struct spi_device *spi = spimem->spi;
struct flash_platform_data *data = dev_get_platdata(&spi->dev);
struct spi_nor *nor;
struct acpi_device *adev;
/*
* Enable all caps by default. The core will mask them after
* checking what's really supported using spi_mem_supports_op().
Expand All @@ -3636,6 +3639,10 @@ static int spi_nor_probe(struct spi_mem *spimem)
nor->spimem = spimem;
nor->dev = &spi->dev;
spi_nor_set_flash_node(nor, spi->dev.of_node);
adev = ACPI_COMPANION(nor->dev);
nor->mtd.dev.fwnode = spi->dev.fwnode;

device_property_read_string(&spi->dev, "_HID", &nor->mtd.name);

spi_mem_set_drvdata(spimem, nor);

Expand Down Expand Up @@ -3775,6 +3782,11 @@ static const struct of_device_id spi_nor_of_table[] = {
};
MODULE_DEVICE_TABLE(of, spi_nor_of_table);

static const struct acpi_device_id spi_nor_acpi_table[] = {
{"PHYT8009", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, spi_nor_acpi_table);
/*
* REVISIT: many of these chips have deep power-down modes, which
* should clearly be entered on suspend() to minimize power use.
Expand All @@ -3786,6 +3798,7 @@ static struct spi_mem_driver spi_nor_driver = {
.name = "spi-nor",
.of_match_table = spi_nor_of_table,
.dev_groups = spi_nor_sysfs_groups,
.acpi_match_table = spi_nor_acpi_table,
},
.id_table = spi_nor_dev_ids,
},
Expand Down
9 changes: 9 additions & 0 deletions drivers/spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,15 @@ config SPI_ORION
This enables using the SPI master controller on the Orion
and MVEBU chips.

config SPI_PCI1XXXX
tristate "PCI1XXXX SPI Bus support"
depends on PCI
help
Say "yes" to Enable the SPI Bus support for the PCI1xxxx card
This is a PCI to SPI Bus driver
This driver can be built as module. If so, the module will be
called as spi-pci1xxxx.

config SPI_PHYTIUM
tristate
depends on ARCH_PHYTIUM || COMPILE_TEST
Expand Down
1 change: 1 addition & 0 deletions drivers/spi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PCI1XXXX) += spi-pci1xxxx.o
obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium.o
obj-$(CONFIG_SPI_PHYTIUM_PLAT) += spi-phytium-plat.o
obj-$(CONFIG_SPI_PHYTIUM_PCI) += spi-phytium-pci.o
Expand Down
Loading

0 comments on commit 4c414a4

Please sign in to comment.