2020-02-28 15:24:07

by John Garry

[permalink] [raw]
Subject: [PATCH RFC 0/3] spi/HiSilicon v3xx: Support dual and quad mode through DMI quirks

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/[email protected]/
[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


2020-02-28 15:24:21

by John Garry

[permalink] [raw]
Subject: [PATCH RFC 3/3] 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 <[email protected]>
---
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 <[email protected]>");
--
2.17.1

2020-02-28 15:24:29

by John Garry

[permalink] [raw]
Subject: [PATCH RFC 1/3] 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 <[email protected]>
---
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

2020-02-28 16:21:26

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH RFC 3/3] spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits

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 :/


Attachments:
(No filename) (429.00 B)
signature.asc (499.00 B)
Download all attachments

2020-02-28 17:18:46

by John Garry

[permalink] [raw]
Subject: Re: [PATCH RFC 3/3] spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits

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/
>

2020-02-28 18:26:01

by Mark Brown

[permalink] [raw]
Subject: Applied "spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits" to the spi tree

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 <[email protected]>
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 <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mark Brown <[email protected]>
---
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 <[email protected]>");
--
2.20.1

2020-02-28 18:27:03

by Mark Brown

[permalink] [raw]
Subject: Applied "spi: Allow SPI controller override device buswidth" to the spi tree

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 <[email protected]>
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 <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mark Brown <[email protected]>
---
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

2020-03-01 10:05:10

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

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 <[email protected]>
> ---
> 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

2020-03-02 09:31:30

by John Garry

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

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 <[email protected]>
>> ---
>>   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/
> .

2020-03-02 12:23:51

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

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.


Attachments:
(No filename) (189.00 B)
signature.asc (499.00 B)
Download all attachments

2020-03-02 16:13:55

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

Hi John,

Thanks for your patch!

On Fri, Feb 28, 2020 at 4:23 PM John Garry <[email protected]> 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 <[email protected]>

> --- 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 -- [email protected]

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

2020-03-02 16:34:53

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

On Mon, Mar 02, 2020 at 05:12:05PM +0100, Geert Uytterhoeven wrote:
> On Fri, Feb 28, 2020 at 4:23 PM John Garry <[email protected]> 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 :/


Attachments:
(No filename) (672.00 B)
signature.asc (499.00 B)
Download all attachments

2020-03-02 18:52:01

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

Hi John,

On Fri, Feb 28, 2020 at 4:23 PM John Garry <[email protected]> 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 -- [email protected]

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

2020-03-03 09:53:23

by John Garry

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth


Hi Geert,

>
> On Fri, Feb 28, 2020 at 4:23 PM John Garry <[email protected]> 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

2020-03-03 13:06:46

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH RFC 1/3] spi: Allow SPI controller override device buswidth

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.


Attachments:
(No filename) (384.00 B)
signature.asc (495.00 B)
Download all attachments