Message ID | 20240607151831.3858304-4-wsadowski@marvell.com |
---|---|
State | New |
Headers | show |
Series | Marvell HW overlay support for Cadence xSPI | expand |
On Fri, Jun 07, 2024 at 08:18:30AM -0700, Witold Sadowski wrote: > These changes enable reading the configurations from ACPI tables as > required for successful probing in an ACPI UEFI environment. In the > case of an ACPI-disabled or DTS-based environment, it will continue > to read configurations from DTS as before. This doesn't describe what the ACPI tables are supposed to look like or anything, it's hard to review this... > +#ifdef CONFIG_ACPI > +static bool cdns_xspi_supports_op(struct spi_mem *mem, > + const struct spi_mem_op *op) > +{ > + if (!acpi_dev_get_property(adev, "spi-tx-bus-width", ACPI_TYPE_INTEGER, > + &obj)) { > + if (!acpi_dev_get_property(adev, "spi-rx-bus-width", ACPI_TYPE_INTEGER, > + &obj)) { Why is this Cadence specific? > static int cdns_xspi_of_get_plat_data(struct platform_device *pdev) > { > - struct device_node *node_prop = pdev->dev.of_node; > + struct fwnode_handle *fwnode_child; > unsigned int cs; > > - for_each_available_child_of_node_scoped(node_prop, node_child) { > - if (of_property_read_u32(node_child, "reg", &cs)) { > + device_for_each_child_node(&pdev->dev, fwnode_child) { > + if (!fwnode_device_is_available(fwnode_child)) > + continue; > + > + if (fwnode_property_read_u32(fwnode_child, "reg", &cs)) { > dev_err(&pdev->dev, "Couldn't get memory chip select\n"); > + 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"); > + fwnode_handle_put(fwnode_child); > return -ENXIO; > } > } This is just a general refactoring to fwnode and could be split out. > @@ -814,19 +890,19 @@ static int cdns_xspi_probe(struct platform_device *pdev) > if (ret) > return -ENODEV; > > - cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, "io"); > + cdns_xspi->iobase = devm_platform_ioremap_resource(pdev, 0); > - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma"); > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > - cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux"); > + cdns_xspi->auxbase = devm_platform_ioremap_resource(pdev, 2); This causes us to ignore naming on resources, that's an ABI break for other systems.
Hi > > These changes enable reading the configurations from ACPI tables as > > required for successful probing in an ACPI UEFI environment. In the > > case of an ACPI-disabled or DTS-based environment, it will continue to > > read configurations from DTS as before. > > This doesn't describe what the ACPI tables are supposed to look like or > anything, it's hard to review this... There should be an example of ACPI table in commit message? > > > +#ifdef CONFIG_ACPI > > +static bool cdns_xspi_supports_op(struct spi_mem *mem, > > + const struct spi_mem_op *op) > > +{ > > > + if (!acpi_dev_get_property(adev, "spi-tx-bus-width", > ACPI_TYPE_INTEGER, > > + &obj)) { > > > + if (!acpi_dev_get_property(adev, "spi-rx-bus-width", > ACPI_TYPE_INTEGER, > > + &obj)) { > > Why is this Cadence specific? So that part should do to generic spi? I think right now it is not Supported to read tx/rx bus width from acpi. > > > static int cdns_xspi_of_get_plat_data(struct platform_device *pdev) > > { > > - struct device_node *node_prop = pdev->dev.of_node; > > + struct fwnode_handle *fwnode_child; > > unsigned int cs; > > > > - for_each_available_child_of_node_scoped(node_prop, node_child) { > > - if (of_property_read_u32(node_child, "reg", &cs)) { > > + device_for_each_child_node(&pdev->dev, fwnode_child) { > > + if (!fwnode_device_is_available(fwnode_child)) > > + continue; > > + > > + if (fwnode_property_read_u32(fwnode_child, "reg", &cs)) { > > dev_err(&pdev->dev, "Couldn't get memory chip > select\n"); > > + 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"); > > + fwnode_handle_put(fwnode_child); > > return -ENXIO; > > } > > } > > This is just a general refactoring to fwnode and could be split out. Ok. > > > @@ -814,19 +890,19 @@ static int cdns_xspi_probe(struct platform_device > *pdev) > > if (ret) > > return -ENODEV; > > > > - cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, > "io"); > > + cdns_xspi->iobase = devm_platform_ioremap_resource(pdev, 0); > > > - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma"); > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > > > - cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, > "aux"); > > + cdns_xspi->auxbase = devm_platform_ioremap_resource(pdev, 2); > > This causes us to ignore naming on resources, that's an ABI break for > other systems. In that case acpi tables are not able to find resource by name. Or at least I wasn't able to find a way to handle that in different way. Is there better solution for that part? Regards Witek
On Tue, Jun 11, 2024 at 09:57:09PM +0000, Witold Sadowski wrote: > > > These changes enable reading the configurations from ACPI tables as > > > required for successful probing in an ACPI UEFI environment. In the > > > case of an ACPI-disabled or DTS-based environment, it will continue to > > > read configurations from DTS as before. > > This doesn't describe what the ACPI tables are supposed to look like or > > anything, it's hard to review this... > There should be an example of ACPI table in commit message? No sign of one in the patch that got sent, nor in the cover letter. > > > +#ifdef CONFIG_ACPI > > > +static bool cdns_xspi_supports_op(struct spi_mem *mem, > > > + const struct spi_mem_op *op) > > > +{ > > > + if (!acpi_dev_get_property(adev, "spi-tx-bus-width", > > ACPI_TYPE_INTEGER, > > > + &obj)) { > > > + if (!acpi_dev_get_property(adev, "spi-rx-bus-width", > > ACPI_TYPE_INTEGER, > > > + &obj)) { > > Why is this Cadence specific? > So that part should do to generic spi? I think right now it is not > Supported to read tx/rx bus width from acpi. I think I meant to say Marvell there rather than Cadence. > > > - cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, > > "io"); > > > + cdns_xspi->iobase = devm_platform_ioremap_resource(pdev, 0); > > > > > - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma"); > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > > > > > - cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, > > "aux"); > > > + cdns_xspi->auxbase = devm_platform_ioremap_resource(pdev, 2); > > This causes us to ignore naming on resources, that's an ABI break for > > other systems. > In that case acpi tables are not able to find resource by name. Or at > least I wasn't able to find a way to handle that in different way. > Is there better solution for that part? Try by name and then fall back on numbers?
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 566db2591d34..36c6c25aaea0 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> @@ -652,6 +654,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) { @@ -675,6 +738,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, }; @@ -726,15 +792,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 fwnode_handle *fwnode_child; unsigned int cs; - for_each_available_child_of_node_scoped(node_prop, node_child) { - if (of_property_read_u32(node_child, "reg", &cs)) { + device_for_each_child_node(&pdev->dev, fwnode_child) { + if (!fwnode_device_is_available(fwnode_child)) + continue; + + if (fwnode_property_read_u32(fwnode_child, "reg", &cs)) { dev_err(&pdev->dev, "Couldn't get memory chip select\n"); + 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"); + fwnode_handle_put(fwnode_child); return -ENXIO; } } @@ -788,6 +859,11 @@ static int cdns_xspi_probe(struct platform_device *pdev) SPI_MODE_0 | SPI_MODE_3; drv_data = of_device_get_match_data(dev); + if (!drv_data) { + drv_data = acpi_device_get_match_data(dev); + if (!drv_data) + return -ENODEV; + } host->mem_ops = &cadence_xspi_mem_ops; host->dev.of_node = pdev->dev.of_node; @@ -814,19 +890,19 @@ static int cdns_xspi_probe(struct platform_device *pdev) if (ret) return -ENODEV; - cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, "io"); + cdns_xspi->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cdns_xspi->iobase)) { dev_err(dev, "Failed to remap controller base address\n"); return PTR_ERR(cdns_xspi->iobase); } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); cdns_xspi->sdmabase = devm_ioremap_resource(dev, res); if (IS_ERR(cdns_xspi->sdmabase)) return PTR_ERR(cdns_xspi->sdmabase); cdns_xspi->sdmasize = resource_size(res); - cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux"); + cdns_xspi->auxbase = devm_platform_ioremap_resource(pdev, 2); if (IS_ERR(cdns_xspi->auxbase)) { dev_err(dev, "Failed to remap AUX address\n"); return PTR_ERR(cdns_xspi->auxbase);