As discussed during the original HiSilicon v3xx SPI driver upstreaming, currently there is no method for the ACPI SPI Serial Bus Connection Resource Descriptor to define the data buswidth [0], [1]. So we can look to get the ACPI spec updated for this, and I have submitted a proposal for a new feature here: https://bugzilla.tianocore.org/show_bug.cgi?id=2557 However I am not sure how successful that will be. In the meantime, as an alternate approach, this RFC proposes to allow the SPI controller driver override the device buswidth. In this example, the driver uses DMI quirks to discover the host machine and set the buswidth override accordingly when the machine is known to support dual or quad mode of operation. I also have included a fix for dual and quad modes in the driver. Comments welcome. thanks. [0] https://lore.kernel.org/linux-mtd/20200109212842.GK3702-GFdadSzt00ze9xe1eoZjHA@public.gmane.org/ [1] https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf, 19.6.126 John Garry (3): spi: Allow SPI controller override device buswidth spi: HiSilicon v3xx: Properly set CMD_CONFIG for Dual/Quad modes spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits drivers/spi/spi-hisi-sfc-v3xx.c | 99 ++++++++++++++++++++++++++++++++- drivers/spi/spi.c | 4 +- include/linux/spi/spi.h | 3 + 3 files changed, 104 insertions(+), 2 deletions(-) -- 2.17.1
Currently ACPI firmware description for a SPI device does not have any method to describe the data buswidth on the board. So even through the controller and device may support higher modes than standard SPI, it cannot be assumed that the board does - as such, that device is limited to standard SPI in such a circumstance. As a workaround, allow the controller driver supply buswidth override bits, which are used inform the core code that the controller driver knows the buswidth supported on that board for that device. A host controller driver might know this info from DMI tables, for example. Signed-off-by: John Garry <john.garry@huawei.com> --- drivers/spi/spi.c | 4 +++- include/linux/spi/spi.h | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 38b4c78df506..292f26807b41 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -510,6 +510,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; spi->cs_gpio = -ENOENT; + spi->mode = ctlr->buswidth_override_bits; spin_lock_init(&spi->statistics.lock); @@ -2181,9 +2182,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, return AE_NO_MEMORY; } + ACPI_COMPANION_SET(&spi->dev, adev); spi->max_speed_hz = lookup.max_speed_hz; - spi->mode = lookup.mode; + spi->mode |= lookup.mode; spi->irq = lookup.irq; spi->bits_per_word = lookup.bits_per_word; spi->chip_select = lookup.chip_select; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6d16ba01ff5a..600e3793303e 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -481,6 +481,9 @@ struct spi_controller { /* spi_device.mode flags understood by this controller driver */ u32 mode_bits; + /* spi_device.mode flags override flags for this controller */ + u32 buswidth_override_bits; + /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; #define SPI_BPW_MASK(bits) BIT((bits) - 1) -- 2.17.1
The CMD_CONFIG register memory interface type field is not set configured for Dual and Quad modes, so set appropriately. This was not detected previously as we only ever operated in standard SPI mode. Signed-off-by: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> --- drivers/spi/spi-hisi-sfc-v3xx.c | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 4cf8fc80a7b7..45d906110ed1 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -17,6 +17,12 @@ #define HISI_SFC_V3XX_VERSION (0x1f8) #define HISI_SFC_V3XX_CMD_CFG (0x300) +#define HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT (1 << 17) +#define HISI_SFC_V3XX_CMD_CFG_DUAL_IO (2 << 17) +#define HISI_SFC_V3XX_CMD_CFG_FULL_DIO (3 << 17) +#define HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT (5 << 17) +#define HISI_SFC_V3XX_CMD_CFG_QUAD_IO (6 << 17) +#define HISI_SFC_V3XX_CMD_CFG_FULL_QIO (7 << 17) #define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9 #define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8) #define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7) @@ -161,6 +167,43 @@ static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host, if (op->addr.nbytes) config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK; + switch (op->data.buswidth) { + case 0 ... 1: + break; + case 2: + if (op->addr.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT; + } else if (op->addr.buswidth == 2) { + if (op->cmd.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IO; + } else if (op->cmd.buswidth == 2) { + config |= HISI_SFC_V3XX_CMD_CFG_FULL_DIO; + } else { + return -EIO; + } + } else { + return -EIO; + } + break; + case 4: + if (op->addr.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT; + } else if (op->addr.buswidth == 4) { + if (op->cmd.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IO; + } else if (op->cmd.buswidth == 4) { + config |= HISI_SFC_V3XX_CMD_CFG_FULL_QIO; + } else { + return -EIO; + } + } else { + return -EIO; + } + break; + default: + return -EOPNOTSUPP; + } + if (op->data.dir != SPI_MEM_NO_DATA) { config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK; -- 2.17.1
The Huawei D06 board (and variants) can support Quad mode of operation. Since we have no current method in ACPI SPI bus device resource description to describe this information, use DMI to detect the board, and set the controller buswidth override bits. Signed-off-by: John Garry <john.garry@huawei.com> --- drivers/spi/spi-hisi-sfc-v3xx.c | 56 ++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 45d906110ed1..e3b57252d075 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -7,6 +7,7 @@ #include <linux/acpi.h> #include <linux/bitops.h> +#include <linux/dmi.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -250,6 +251,44 @@ static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = { .exec_op = hisi_sfc_v3xx_exec_op, }; +static int hisi_sfc_v3xx_buswidth_override_bits; + +/* + * ACPI FW does not allow us to currently set the device buswidth, so quirk it + * depending on the board. + */ +static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d) +{ + hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD; + + return 0; +} + +static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[] = { + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "D06"), + }, + }, + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"), + }, + }, + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"), + }, + }, + {} +}; + static int hisi_sfc_v3xx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -265,6 +304,8 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; + ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits; + host = spi_controller_get_devdata(ctlr); host->dev = dev; @@ -320,7 +361,20 @@ static struct platform_driver hisi_sfc_v3xx_spi_driver = { .probe = hisi_sfc_v3xx_probe, }; -module_platform_driver(hisi_sfc_v3xx_spi_driver); +static int __init hisi_sfc_v3xx_spi_init(void) +{ + dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table); + + return platform_driver_register(&hisi_sfc_v3xx_spi_driver); +} + +static void __exit hisi_sfc_v3xx_spi_exit(void) +{ + platform_driver_unregister(&hisi_sfc_v3xx_spi_driver); +} + +module_init(hisi_sfc_v3xx_spi_init); +module_exit(hisi_sfc_v3xx_spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Garry <john.garry@huawei.com>"); -- 2.17.1
[-- Attachment #1: Type: text/plain, Size: 429 bytes --] On Fri, Feb 28, 2020 at 11:18:51PM +0800, John Garry wrote: > The Huawei D06 board (and variants) can support Quad mode of operation. > > Since we have no current method in ACPI SPI bus device resource description > to describe this information, use DMI to detect the board, and set the > controller buswidth override bits. Hopefully this is something that the ACPI people will be looking to address going forwards :/ [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --]
On 28/02/2020 16:20, Mark Brown wrote: > On Fri, Feb 28, 2020 at 11:18:51PM +0800, John Garry wrote: >> The Huawei D06 board (and variants) can support Quad mode of operation. >> >> Since we have no current method in ACPI SPI bus device resource description >> to describe this information, use DMI to detect the board, and set the >> controller buswidth override bits. > > Hopefully this is something that the ACPI people will be looking to > address going forwards :/ > Yeah, well I did mention the bugzilla [0] I raised for this in the cover letter; but I think that the new process workflows to raise feature requests in this way still needs to be formalized, so this may be blocked for now [1]. And unfortunately I can't actively participate in relevant standards WGs either, so if anyone else would like to assist, then that would great... BTW, I think that it might also be good to request a generic jedec-compatible SPI NOR part ACPI HID/CID here also. Thanks, John [0] https://bugzilla.tianocore.org/show_bug.cgi?id=2557 [1] https://edk2.groups.io/g/devel/message/53420 > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ >
The patch spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 34e608b023e96f51b31274435b49c8ae61e2389f Mon Sep 17 00:00:00 2001 From: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Date: Fri, 28 Feb 2020 23:18:51 +0800 Subject: [PATCH] spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits The Huawei D06 board (and variants) can support Quad mode of operation. Since we have no current method in ACPI SPI bus device resource description to describe this information, use DMI to detect the board, and set the controller buswidth override bits. Signed-off-by: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Link: https://lore.kernel.org/r/1582903131-160033-4-git-send-email-john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> --- drivers/spi/spi-hisi-sfc-v3xx.c | 56 ++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 45d906110ed1..e3b57252d075 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -7,6 +7,7 @@ #include <linux/acpi.h> #include <linux/bitops.h> +#include <linux/dmi.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -250,6 +251,44 @@ static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = { .exec_op = hisi_sfc_v3xx_exec_op, }; +static int hisi_sfc_v3xx_buswidth_override_bits; + +/* + * ACPI FW does not allow us to currently set the device buswidth, so quirk it + * depending on the board. + */ +static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d) +{ + hisi_sfc_v3xx_buswidth_override_bits = SPI_RX_QUAD | SPI_TX_QUAD; + + return 0; +} + +static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[] = { + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "D06"), + }, + }, + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 2280 V2"), + }, + }, + { + .callback = hisi_sfc_v3xx_dmi_quirk, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Huawei"), + DMI_MATCH(DMI_PRODUCT_NAME, "TaiShan 200 (Model 2280)"), + }, + }, + {} +}; + static int hisi_sfc_v3xx_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -265,6 +304,8 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; + ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits; + host = spi_controller_get_devdata(ctlr); host->dev = dev; @@ -320,7 +361,20 @@ static struct platform_driver hisi_sfc_v3xx_spi_driver = { .probe = hisi_sfc_v3xx_probe, }; -module_platform_driver(hisi_sfc_v3xx_spi_driver); +static int __init hisi_sfc_v3xx_spi_init(void) +{ + dmi_check_system(hisi_sfc_v3xx_dmi_quirk_table); + + return platform_driver_register(&hisi_sfc_v3xx_spi_driver); +} + +static void __exit hisi_sfc_v3xx_spi_exit(void) +{ + platform_driver_unregister(&hisi_sfc_v3xx_spi_driver); +} + +module_init(hisi_sfc_v3xx_spi_init); +module_exit(hisi_sfc_v3xx_spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>"); -- 2.20.1
The patch spi: HiSilicon v3xx: Properly set CMD_CONFIG for Dual/Quad modes has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 8fe21d6b347247227c349c9b2f7c462fae362af4 Mon Sep 17 00:00:00 2001 From: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Date: Fri, 28 Feb 2020 23:18:50 +0800 Subject: [PATCH] spi: HiSilicon v3xx: Properly set CMD_CONFIG for Dual/Quad modes The CMD_CONFIG register memory interface type field is not set configured for Dual and Quad modes, so set appropriately. This was not detected previously as we only ever operated in standard SPI mode. Signed-off-by: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Link: https://lore.kernel.org/r/1582903131-160033-3-git-send-email-john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> --- drivers/spi/spi-hisi-sfc-v3xx.c | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 4cf8fc80a7b7..45d906110ed1 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -17,6 +17,12 @@ #define HISI_SFC_V3XX_VERSION (0x1f8) #define HISI_SFC_V3XX_CMD_CFG (0x300) +#define HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT (1 << 17) +#define HISI_SFC_V3XX_CMD_CFG_DUAL_IO (2 << 17) +#define HISI_SFC_V3XX_CMD_CFG_FULL_DIO (3 << 17) +#define HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT (5 << 17) +#define HISI_SFC_V3XX_CMD_CFG_QUAD_IO (6 << 17) +#define HISI_SFC_V3XX_CMD_CFG_FULL_QIO (7 << 17) #define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9 #define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8) #define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7) @@ -161,6 +167,43 @@ static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host, if (op->addr.nbytes) config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK; + switch (op->data.buswidth) { + case 0 ... 1: + break; + case 2: + if (op->addr.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IN_DUAL_OUT; + } else if (op->addr.buswidth == 2) { + if (op->cmd.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_DUAL_IO; + } else if (op->cmd.buswidth == 2) { + config |= HISI_SFC_V3XX_CMD_CFG_FULL_DIO; + } else { + return -EIO; + } + } else { + return -EIO; + } + break; + case 4: + if (op->addr.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IN_QUAD_OUT; + } else if (op->addr.buswidth == 4) { + if (op->cmd.buswidth <= 1) { + config |= HISI_SFC_V3XX_CMD_CFG_QUAD_IO; + } else if (op->cmd.buswidth == 4) { + config |= HISI_SFC_V3XX_CMD_CFG_FULL_QIO; + } else { + return -EIO; + } + } else { + return -EIO; + } + break; + default: + return -EOPNOTSUPP; + } + if (op->data.dir != SPI_MEM_NO_DATA) { config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK; -- 2.20.1
The patch spi: Allow SPI controller override device buswidth has been applied to the spi tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From ea23578611dce2eeaf31dcfe12cd7130cf3d1411 Mon Sep 17 00:00:00 2001 From: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Date: Fri, 28 Feb 2020 23:18:49 +0800 Subject: [PATCH] spi: Allow SPI controller override device buswidth Currently ACPI firmware description for a SPI device does not have any method to describe the data buswidth on the board. So even through the controller and device may support higher modes than standard SPI, it cannot be assumed that the board does - as such, that device is limited to standard SPI in such a circumstance. As a workaround, allow the controller driver supply buswidth override bits, which are used inform the core code that the controller driver knows the buswidth supported on that board for that device. A host controller driver might know this info from DMI tables, for example. Signed-off-by: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> Link: https://lore.kernel.org/r/1582903131-160033-2-git-send-email-john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> --- drivers/spi/spi.c | 4 +++- include/linux/spi/spi.h | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 38b4c78df506..292f26807b41 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -510,6 +510,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) spi->dev.bus = &spi_bus_type; spi->dev.release = spidev_release; spi->cs_gpio = -ENOENT; + spi->mode = ctlr->buswidth_override_bits; spin_lock_init(&spi->statistics.lock); @@ -2181,9 +2182,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, return AE_NO_MEMORY; } + ACPI_COMPANION_SET(&spi->dev, adev); spi->max_speed_hz = lookup.max_speed_hz; - spi->mode = lookup.mode; + spi->mode |= lookup.mode; spi->irq = lookup.irq; spi->bits_per_word = lookup.bits_per_word; spi->chip_select = lookup.chip_select; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6d16ba01ff5a..600e3793303e 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -481,6 +481,9 @@ struct spi_controller { /* spi_device.mode flags understood by this controller driver */ u32 mode_bits; + /* spi_device.mode flags override flags for this controller */ + u32 buswidth_override_bits; + /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; #define SPI_BPW_MASK(bits) BIT((bits) - 1) -- 2.20.1
Hello! On 28.02.2020 18:18, John Garry wrote: > Currently ACPI firmware description for a SPI device does not have any > method to describe the data buswidth on the board. > > So even through the controller and device may support higher modes than ^^^^^^^ Though? > standard SPI, it cannot be assumed that the board does - as such, that > device is limited to standard SPI in such a circumstance. > > As a workaround, allow the controller driver supply buswidth override bits, > which are used inform the core code that the controller driver knows the > buswidth supported on that board for that device. > > A host controller driver might know this info from DMI tables, for example. > > Signed-off-by: John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> > --- > drivers/spi/spi.c | 4 +++- > include/linux/spi/spi.h | 3 +++ > 2 files changed, 6 insertions(+), 1 deletion(-) > > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index 38b4c78df506..292f26807b41 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -510,6 +510,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) > spi->dev.bus = &spi_bus_type; > spi->dev.release = spidev_release; > spi->cs_gpio = -ENOENT; > + spi->mode = ctlr->buswidth_override_bits; > > spin_lock_init(&spi->statistics.lock); > > @@ -2181,9 +2182,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, > return AE_NO_MEMORY; > } > > + What for? > ACPI_COMPANION_SET(&spi->dev, adev); > spi->max_speed_hz = lookup.max_speed_hz; > - spi->mode = lookup.mode; > + spi->mode |= lookup.mode; > spi->irq = lookup.irq; > spi->bits_per_word = lookup.bits_per_word; > spi->chip_select = lookup.chip_select; [...] MBR, Sergei
On 01/03/2020 10:04, Sergei Shtylyov wrote: > Hello! > Hi Sergei, > On 28.02.2020 18:18, John Garry wrote: > >> Currently ACPI firmware description for a SPI device does not have any >> method to describe the data buswidth on the board. >> >> So even through the controller and device may support higher modes than > ^^^^^^^ > Though? > right >> standard SPI, it cannot be assumed that the board does - as such, that >> device is limited to standard SPI in such a circumstance. >> >> As a workaround, allow the controller driver supply buswidth override >> bits, >> which are used inform the core code that the controller driver knows the >> buswidth supported on that board for that device. >> >> A host controller driver might know this info from DMI tables, for >> example. >> >> Signed-off-by: John Garry <john.garry@huawei.com> >> --- >> drivers/spi/spi.c | 4 +++- >> include/linux/spi/spi.h | 3 +++ >> 2 files changed, 6 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c >> index 38b4c78df506..292f26807b41 100644 >> --- a/drivers/spi/spi.c >> +++ b/drivers/spi/spi.c >> @@ -510,6 +510,7 @@ struct spi_device *spi_alloc_device(struct >> spi_controller *ctlr) >> spi->dev.bus = &spi_bus_type; >> spi->dev.release = spidev_release; >> spi->cs_gpio = -ENOENT; >> + spi->mode = ctlr->buswidth_override_bits; >> spin_lock_init(&spi->statistics.lock); >> @@ -2181,9 +2182,10 @@ static acpi_status >> acpi_register_spi_device(struct spi_controller *ctlr, >> return AE_NO_MEMORY; >> } >> + > > What for? slipped through the net > >> ACPI_COMPANION_SET(&spi->dev, adev); >> spi->max_speed_hz = lookup.max_speed_hz; >> - spi->mode = lookup.mode; >> + spi->mode |= lookup.mode; >> spi->irq = lookup.irq; >> spi->bits_per_word = lookup.bits_per_word; >> spi->chip_select = lookup.chip_select; > [...] TBH, I did not think that this series would be applied since I tagged it as RFC, hence the typos which would have been caught. Indeed, this also exposes an issue with enabling quad SPI for a spansion SPI NOR part, which I need to debug now in the SPI NOR driver. Hi Mark, Do you want me to do anything about the above superfluous newline? Thanks, John > > MBR, Sergei > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > .
[-- Attachment #1: Type: text/plain, Size: 184 bytes --] On Mon, Mar 02, 2020 at 09:30:08AM +0000, John Garry wrote: > Do you want me to do anything about the above superfluous newline? Whatever you prefer, I don't really care either way. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --]
Hi John, Thanks for your patch! On Fri, Feb 28, 2020 at 4:23 PM John Garry <john.garry@huawei.com> wrote: > Currently ACPI firmware description for a SPI device does not have any > method to describe the data buswidth on the board. > > So even through the controller and device may support higher modes than > standard SPI, it cannot be assumed that the board does - as such, that > device is limited to standard SPI in such a circumstance. Indeed. > As a workaround, allow the controller driver supply buswidth override bits, > which are used inform the core code that the controller driver knows the > buswidth supported on that board for that device. I feel this is a bit dangerous, and might bite us one day. > A host controller driver might know this info from DMI tables, for example. Can't acpi_register_spi_device() obtain that info from DMI tables, to avoid contaminating the generic code? > Signed-off-by: John Garry <john.garry@huawei.com> > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -510,6 +510,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) > spi->dev.bus = &spi_bus_type; > spi->dev.release = spidev_release; > spi->cs_gpio = -ENOENT; > + spi->mode = ctlr->buswidth_override_bits; This could just be moved to acpi_register_spi_device(), right? > > spin_lock_init(&spi->statistics.lock); > > @@ -2181,9 +2182,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, > return AE_NO_MEMORY; > } > > + > ACPI_COMPANION_SET(&spi->dev, adev); > spi->max_speed_hz = lookup.max_speed_hz; > - spi->mode = lookup.mode; > + spi->mode |= lookup.mode; > spi->irq = lookup.irq; > spi->bits_per_word = lookup.bits_per_word; > spi->chip_select = lookup.chip_select; > diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h > index 6d16ba01ff5a..600e3793303e 100644 > --- a/include/linux/spi/spi.h > +++ b/include/linux/spi/spi.h > @@ -481,6 +481,9 @@ struct spi_controller { > /* spi_device.mode flags understood by this controller driver */ > u32 mode_bits; > > + /* spi_device.mode flags override flags for this controller */ > + u32 buswidth_override_bits; And I'd be happy if we could avoid adding this here ;-) > + > /* bitmask of supported bits_per_word for transfers */ > u32 bits_per_word_mask; > #define SPI_BPW_MASK(bits) BIT((bits) - 1) Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
[-- Attachment #1: Type: text/plain, Size: 657 bytes --] On Mon, Mar 02, 2020 at 05:12:05PM +0100, Geert Uytterhoeven wrote: > On Fri, Feb 28, 2020 at 4:23 PM John Garry <john.garry@huawei.com> wrote: > > A host controller driver might know this info from DMI tables, for example. > Can't acpi_register_spi_device() obtain that info from DMI tables, > to avoid contaminating the generic code? The DMI tables are going to boil down to per board quirks which we *could* put in the core but you end up with a lot of them and chances are that at some point we'll end up with device specific quirks which don't fit so well in the core. Handling stuff in the drivers is fairly idiomatic. Much ACPI, so standards :/ [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --]
Hi John,
On Fri, Feb 28, 2020 at 4:23 PM John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
> Currently ACPI firmware description for a SPI device does not have any
> method to describe the data buswidth on the board.
>
> So even through the controller and device may support higher modes than
> standard SPI, it cannot be assumed that the board does - as such, that
> device is limited to standard SPI in such a circumstance.
>
> As a workaround, allow the controller driver supply buswidth override bits,
> which are used inform the core code that the controller driver knows the
> buswidth supported on that board for that device.
Just wondering: can't the controller just override this (e.g. in the .setuup()
callback) without having to touch the generic code?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Hi Geert,
>
> On Fri, Feb 28, 2020 at 4:23 PM John Garry <john.garry-hv44wF8Li93QT0dZR+AlfA@public.gmane.org> wrote:
>> Currently ACPI firmware description for a SPI device does not have any
>> method to describe the data buswidth on the board.
>>
>> So even through the controller and device may support higher modes than
>> standard SPI, it cannot be assumed that the board does - as such, that
>> device is limited to standard SPI in such a circumstance.
>>
>> As a workaround, allow the controller driver supply buswidth override bits,
>> which are used inform the core code that the controller driver knows the
>> buswidth supported on that board for that device.
>
> Just wondering: can't the controller just override this (e.g. in the .setuup()
> callback) without having to touch the generic code?
I think that this is a good idea.
However, where we call .setup() in spi_setup() looks a little too late -
at the point we call .setup(), most of the work on vetting/fixing the
mode bits is complete. And I would not want the SPI controller driver
just to disregard this work and overwrite the bits (in this way).
And if we wanted to move the .setup callback earlier, then I would be
worried here with 2 things:
1. Some SPI controller drivers may rely on spi->mode being set finally
when .setup() is called
2. We may need to undo the work of .setup() if we later error in
spi_setup(), like for invalid mode bits
However, maybe another callback could be introduced, .early_setup().
Thanks,
John
[-- Attachment #1: Type: text/plain, Size: 376 bytes --] On Tue, Mar 03, 2020 at 09:42:45AM +0000, John Garry wrote: > However, maybe another callback could be introduced, .early_setup(). One thing I like about the explicit core code is that it makes it much easier to see which drivers are doing the worrying thing, with just overwriting things in a callback everything is very freeform and you have to audit things individually. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 484 bytes --]