Message ID | 20240418011353.1764672-5-wsadowski@marvell.com |
---|---|
State | New |
Headers | show |
Series | Marvell HW overlay support for Cadence xSPI | expand |
On 18/04/2024 03:13, Witold Sadowski wrote: > From: Piyush Malgujar <pmalgujar@marvell.com> > > These changes enables to read the configs from ACPI tables as required > for successful probing in ACPI uefi environment. > In case of ACPI disabled/dts based environment, it will continue to > read configs from dts as before > ... > } > @@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device *pdev) > return 0; > } > > +#ifdef CONFIG_ACPI > +static const struct acpi_device_id cdns_xspi_acpi_match[] = { > + { > + .id = "cdns,xspi-nor", > + .driver_data = (kernel_ulong_t) &cdns_driver_data, > + }, > + { > + .id = "mrvl,xspi-nor", > + .driver_data = (kernel_ulong_t) &mrvl_driver_data, UEFI provides compatibles for ACPI? I think that's first such format in the kernel. Best regards, Krzysztof
> On 18/04/2024 03:13, Witold Sadowski wrote: > > From: Piyush Malgujar <pmalgujar@marvell.com> > > > > These changes enables to read the configs from ACPI tables as required > > for successful probing in ACPI uefi environment. > > In case of ACPI disabled/dts based environment, it will continue to > > read configs from dts as before > > > > ... > > > } > > @@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device > *pdev) > > return 0; > > } > > > > +#ifdef CONFIG_ACPI > > +static const struct acpi_device_id cdns_xspi_acpi_match[] = { > > + { > > + .id = "cdns,xspi-nor", > > + .driver_data = (kernel_ulong_t) &cdns_driver_data, > > + }, > > + { > > + .id = "mrvl,xspi-nor", > > + .driver_data = (kernel_ulong_t) &mrvl_driver_data, > > UEFI provides compatibles for ACPI? I think that's first such format in > the kernel. Yes, that code is not doing what was expected. Current usage scenario in ACPI mode is: xSPI block with HID PRP0001, and additional compatible package set to correct compatible string With that approach only issue(in ACPI mode) is with matching device with data field from of_device_id. It looks like there are functions to match that when DTB is used, but in ACPI mode it fails. I believe solution is to traverse dev->driver->of_match_table manually To match device name with correct compatible data structure. That will be included in next patchset. > > Best regards, > Krzysztof Regards Witek
On 29/04/2024 16:30, Witold Sadowski wrote: >>> >>> +#ifdef CONFIG_ACPI >>> +static const struct acpi_device_id cdns_xspi_acpi_match[] = { >>> + { >>> + .id = "cdns,xspi-nor", >>> + .driver_data = (kernel_ulong_t) &cdns_driver_data, >>> + }, >>> + { >>> + .id = "mrvl,xspi-nor", >>> + .driver_data = (kernel_ulong_t) &mrvl_driver_data, >> >> UEFI provides compatibles for ACPI? I think that's first such format in >> the kernel. > > Yes, that code is not doing what was expected. > Current usage scenario in ACPI mode is: > xSPI block with HID PRP0001, and additional compatible package set to > correct compatible string > With that approach only issue(in ACPI mode) is with matching device > with data field from of_device_id. It looks like there are functions > to match that when DTB is used, but in ACPI mode it fails. > I believe solution is to traverse dev->driver->of_match_table manually > To match device name with correct compatible data structure. > That will be included in next patchset. PRP0001 should be handled by regular of_device_id table, of course assuming your kernel has build-in CONFIG_OF. Best regards, Krzysztof
> On 29/04/2024 16:30, Witold Sadowski wrote: > >>> > >>> +#ifdef CONFIG_ACPI > >>> +static const struct acpi_device_id cdns_xspi_acpi_match[] = { > >>> + { > >>> + .id = "cdns,xspi-nor", > >>> + .driver_data = (kernel_ulong_t) &cdns_driver_data, > >>> + }, > >>> + { > >>> + .id = "mrvl,xspi-nor", > >>> + .driver_data = (kernel_ulong_t) &mrvl_driver_data, > >> > >> UEFI provides compatibles for ACPI? I think that's first such format > >> in the kernel. > > > > Yes, that code is not doing what was expected. > > Current usage scenario in ACPI mode is: > > xSPI block with HID PRP0001, and additional compatible package set to > > correct compatible string With that approach only issue(in ACPI mode) > > is with matching device with data field from of_device_id. It looks > > like there are functions to match that when DTB is used, but in ACPI > > mode it fails. > > I believe solution is to traverse dev->driver->of_match_table manually > > To match device name with correct compatible data structure. > > That will be included in next patchset. > > PRP0001 should be handled by regular of_device_id table, of course > assuming your kernel has build-in CONFIG_OF. And it is correctly matched by id, but functions to retrieve data fails. I'm referring to of_device_get_match_data - there is no of node in ACPI case. I have come up with solution, as I wasn't able to find similar function that will work with ACPI and dtb on the same time: static const void * cdns_xspi_get_data(struct device *dev) { const struct of_device_id *matches = dev->driver->of_match_table; for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { if (device_is_compatible(dev, matches->compatible)) return matches->data; } return NULL; } Is there a better way to handle that? > > Best regards, > Krzysztof
On Wed, May 08, 2024 at 08:04:49AM +0000, Witold Sadowski wrote: > > I have come up with solution, as I wasn't able to find similar function that > will work with ACPI and dtb on the same time: The usual thing would just be to try both an ACPI match and an OF match.
> On Wed, May 08, 2024 at 08:04:49AM +0000, Witold Sadowski wrote: > > > > > I have come up with solution, as I wasn't able to find similar > > function that will work with ACPI and dtb on the same time: > > The usual thing would just be to try both an ACPI match and an OF match. Ok, thanks. I thought it can be done in single step.
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 5d36f9177f3c..e4ebfad8a1cb 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -2,6 +2,7 @@ // Cadence XSPI flash controller driver // Copyright (C) 2020-21 Cadence +#include <linux/acpi.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/err.h> @@ -14,6 +15,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> #include <linux/bitfield.h> @@ -700,6 +702,67 @@ static int cdns_xspi_mem_op(struct cdns_xspi_dev *cdns_xspi, (dir != SPI_MEM_NO_DATA)); } +#ifdef CONFIG_ACPI +static bool cdns_xspi_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct spi_device *spi = mem->spi; + const union acpi_object *obj; + struct acpi_device *adev; + + adev = ACPI_COMPANION(&spi->dev); + + if (!acpi_dev_get_property(adev, "spi-tx-bus-width", ACPI_TYPE_INTEGER, + &obj)) { + switch (obj->integer.value) { + case 1: + break; + case 2: + spi->mode |= SPI_TX_DUAL; + break; + case 4: + spi->mode |= SPI_TX_QUAD; + break; + case 8: + spi->mode |= SPI_TX_OCTAL; + break; + default: + dev_warn(&spi->dev, + "spi-tx-bus-width %lld not supported\n", + obj->integer.value); + break; + } + } + + if (!acpi_dev_get_property(adev, "spi-rx-bus-width", ACPI_TYPE_INTEGER, + &obj)) { + switch (obj->integer.value) { + case 1: + break; + case 2: + spi->mode |= SPI_RX_DUAL; + break; + case 4: + spi->mode |= SPI_RX_QUAD; + break; + case 8: + spi->mode |= SPI_RX_OCTAL; + break; + default: + dev_warn(&spi->dev, + "spi-rx-bus-width %lld not supported\n", + obj->integer.value); + break; + } + } + + if (!spi_mem_default_supports_op(mem, op)) + return false; + + return true; +} +#endif + static int cdns_xspi_mem_op_execute(struct spi_mem *mem, const struct spi_mem_op *op) { @@ -723,6 +786,9 @@ static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op * } static const struct spi_controller_mem_ops cadence_xspi_mem_ops = { +#ifdef CONFIG_ACPI + .supports_op = cdns_xspi_supports_op, +#endif .exec_op = cdns_xspi_mem_op_execute, .adjust_op_size = cdns_xspi_adjust_mem_op_size, }; @@ -774,21 +840,20 @@ static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev) static int cdns_xspi_of_get_plat_data(struct platform_device *pdev) { - struct device_node *node_prop = pdev->dev.of_node; - struct device_node *node_child; + struct fwnode_handle *fwnode_child; unsigned int cs; - for_each_child_of_node(node_prop, node_child) { - if (!of_device_is_available(node_child)) + device_for_each_child_node(&pdev->dev, fwnode_child) { + if (!fwnode_device_is_available(fwnode_child)) continue; - if (of_property_read_u32(node_child, "reg", &cs)) { + if (fwnode_property_read_u32(fwnode_child, "reg", &cs)) { dev_err(&pdev->dev, "Couldn't get memory chip select\n"); - of_node_put(node_child); + fwnode_handle_put(fwnode_child); return -ENXIO; } else if (cs >= CDNS_XSPI_MAX_BANKS) { dev_err(&pdev->dev, "reg (cs) parameter value too large\n"); - of_node_put(node_child); + fwnode_handle_put(fwnode_child); return -ENXIO; } } @@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_ACPI +static const struct acpi_device_id cdns_xspi_acpi_match[] = { + { + .id = "cdns,xspi-nor", + .driver_data = (kernel_ulong_t) &cdns_driver_data, + }, + { + .id = "mrvl,xspi-nor", + .driver_data = (kernel_ulong_t) &mrvl_driver_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, cdns_xspi_acpi_match); +#endif + static const struct of_device_id cdns_xspi_of_match[] = { { .compatible = "cdns,xspi-nor", @@ -942,6 +1022,9 @@ static struct platform_driver cdns_xspi_platform_driver = { .driver = { .name = CDNS_XSPI_NAME, .of_match_table = cdns_xspi_of_match, +#ifdef CONFIG_ACPI + .acpi_match_table = cdns_xspi_acpi_match, +#endif }, };