[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <13cdb17d-5b2a-d35e-8005-1a414f165407@opensource.cirrus.com>
Date: Fri, 28 Apr 2023 15:08:27 +0100
From: Stefan Binding <sbinding@...nsource.cirrus.com>
To: "Mahapatra, Amit Kumar" <amit.kumar-mahapatra@....com>,
"broonie@...nel.org" <broonie@...nel.org>,
"tudor.ambarus@...aro.org" <tudor.ambarus@...aro.org>,
"pratyush@...nel.org" <pratyush@...nel.org>,
"michael@...le.cc" <michael@...le.cc>,
"miquel.raynal@...tlin.com" <miquel.raynal@...tlin.com>,
"richard@....at" <richard@....at>,
"vigneshr@...com" <vigneshr@...com>
CC: "git (AMD-Xilinx)" <git@....com>,
"linux-spi@...r.kernel.org" <linux-spi@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"linux-mtd@...ts.infradead.org" <linux-mtd@...ts.infradead.org>,
"nicolas.ferre@...rochip.com" <nicolas.ferre@...rochip.com>,
"alexandre.belloni@...tlin.com" <alexandre.belloni@...tlin.com>,
"claudiu.beznea@...rochip.com" <claudiu.beznea@...rochip.com>,
"Simek, Michal" <michal.simek@....com>,
"linux-arm-kernel@...ts.infradead.org"
<linux-arm-kernel@...ts.infradead.org>,
"amitrkcian2002@...il.com" <amitrkcian2002@...il.com>,
"patches@...nsource.cirrus.com" <patches@...nsource.cirrus.com>,
"vitalyr@...nsource.cirrus.com" <vitalyr@...nsource.cirrus.com>
Subject: Re: [PATCH V7 1/7] spi: Add stacked and parallel memories support in
SPI core
Hi,
On 27/04/2023 18:09, Mahapatra, Amit Kumar wrote:
> Hello Stefan,
>
>> -----Original Message-----
>> From: Stefan Binding <sbinding@...nsource.cirrus.com>
>> Sent: Tuesday, April 25, 2023 5:50 PM
>> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@....com>;
>> broonie@...nel.org; tudor.ambarus@...aro.org; pratyush@...nel.org;
>> michael@...le.cc; miquel.raynal@...tlin.com; richard@....at;
>> vigneshr@...com
>> Cc: git (AMD-Xilinx) <git@....com>; linux-spi@...r.kernel.org; linux-
>> kernel@...r.kernel.org; linux-mtd@...ts.infradead.org;
>> nicolas.ferre@...rochip.com; alexandre.belloni@...tlin.com;
>> claudiu.beznea@...rochip.com; Simek, Michal <michal.simek@....com>;
>> linux-arm-kernel@...ts.infradead.org; amitrkcian2002@...il.com;
>> patches@...nsource.cirrus.com; vitalyr@...nsource.cirrus.com
>> Subject: Re: [PATCH V7 1/7] spi: Add stacked and parallel memories support
>> in SPI core
>>
>> Hi,
>>
>> On 20/04/2023 10:04, Mahapatra, Amit Kumar wrote:
>>> Hello Stefan,
>>>
>>>> -----Original Message-----
>>>> From: Stefan Binding <sbinding@...nsource.cirrus.com>
>>>> Sent: Wednesday, April 12, 2023 8:33 PM
>>>> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@....com>;
>>>> broonie@...nel.org; tudor.ambarus@...aro.org; pratyush@...nel.org;
>>>> michael@...le.cc; miquel.raynal@...tlin.com; richard@....at;
>>>> vigneshr@...com
>>>> Cc: git (AMD-Xilinx) <git@....com>; linux-spi@...r.kernel.org; linux-
>>>> kernel@...r.kernel.org; linux-mtd@...ts.infradead.org;
>>>> nicolas.ferre@...rochip.com; alexandre.belloni@...tlin.com;
>>>> claudiu.beznea@...rochip.com; Simek, Michal
>> <michal.simek@....com>;
>>>> linux-arm-kernel@...ts.infradead.org; amitrkcian2002@...il.com;
>>>> patches@...nsource.cirrus.com; vitalyr@...nsource.cirrus.com
>>>> Subject: Re: [PATCH V7 1/7] spi: Add stacked and parallel memories
>>>> support in SPI core
>>>>
>>>> Hi,
>>>>
>>>> On 11/04/2023 10:07, Mahapatra, Amit Kumar wrote:
>>>>> Hello Stefan,
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Stefan Binding <sbinding@...nsource.cirrus.com>
>>>>>> Sent: Thursday, April 6, 2023 7:14 PM
>>>>>> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@....com>;
>>>>>> broonie@...nel.org; tudor.ambarus@...aro.org; pratyush@...nel.org;
>>>>>> michael@...le.cc; miquel.raynal@...tlin.com; richard@....at;
>>>>>> vigneshr@...com
>>>>>> Cc: git (AMD-Xilinx) <git@....com>; linux-spi@...r.kernel.org;
>>>>>> linux- kernel@...r.kernel.org; linux-mtd@...ts.infradead.org;
>>>>>> nicolas.ferre@...rochip.com; alexandre.belloni@...tlin.com;
>>>>>> claudiu.beznea@...rochip.com; Simek, Michal
>>>> <michal.simek@....com>;
>>>>>> linux-arm-kernel@...ts.infradead.org; amitrkcian2002@...il.com;
>>>>>> patches@...nsource.cirrus.com; vitalyr@...nsource.cirrus.com
>>>>>> Subject: RE: [PATCH V7 1/7] spi: Add stacked and parallel memories
>>>>>> support in SPI core
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Amit Kumar Mahapatra <amit.kumar-mahapatra@....com>
>>>>>>> Sent: Thursday, April 6, 2023 7:54 AM
>>>>>>> To: broonie@...nel.org; tudor.ambarus@...aro.org;
>>>>>>> pratyush@...nel.org; michael@...le.cc; miquel.raynal@...tlin.com;
>>>>>>> richard@....at; vigneshr@...com
>>>>>>> Cc: git@....com; sbinding@...nsource.cirrus.com; linux-
>>>>>>> spi@...r.kernel.org; linux-kernel@...r.kernel.org; linux-
>>>>>>> mtd@...ts.infradead.org; nicolas.ferre@...rochip.com;
>>>>>>> alexandre.belloni@...tlin.com; claudiu.beznea@...rochip.com;
>>>>>>> michal.simek@....com; linux-arm-kernel@...ts.infradead.org;
>>>>>>> amitrkcian2002@...il.com; Amit Kumar Mahapatra <amit.kumar-
>>>>>>> mahapatra@....com>
>>>>>>> Subject: [PATCH V7 1/7] spi: Add stacked and parallel memories
>>>>>> support
>>>>>>> in SPI core
>>>>>>>
>>>>>>> For supporting multiple CS the SPI device need to be aware of all
>>>>>> the CS
>>>>>>> values. So, the "chip_select" member in the spi_device structure
>>>>>>> is
>>>>>> now
>>>>>>> an
>>>>>>> array that holds all the CS values.
>>>>>>>
>>>>>>> spi_device structure now has a "cs_index_mask" member. This acts
>>>>>>> as
>>>>>> an
>>>>>>> index to the chip_select array. If nth bit of spi->cs_index_mask
>>>>>>> is
>>>>>> set
>>>>>>> then the driver would assert spi->chip_select[n].
>>>>>>>
>>>>>>> In parallel mode all the chip selects are asserted/de-asserted
>>>>>>> simultaneously and each byte of data is stored in both devices,
>>>>>>> the
>>>>>> even
>>>>>>> bits in one, the odd bits in the other. The split is automatically
>>>>>> handled
>>>>>>> by the GQSPI controller. The GQSPI controller supports a maximum
>>>>>>> of two flashes connected in parallel mode. A
>>>>>>> SPI_CONTROLLER_MULTI_CS flag bit is added in the spi
>>>>>>> controntroller flags, through
>>>>>>> ctlr->flags the spi
>>>>>> core
>>>>>>> will make sure that the controller is capable of handling multiple
>>>>>> chip
>>>>>>> selects at once.
>>>>>>>
>>>>>>> For supporting multiple CS via GPIO the cs_gpiod member of the
>>>>>>> spi_device structure is now an array that holds the gpio
>>>>>>> descriptor for each chipselect.
>>>>>>>
>>>>>>> Multi CS support using GPIO is not tested due to unavailability of
>>>>>>> necessary hardware setup.
>>>>>>>
>>>>>>> Multi CS configuration with one native CS and one GPIO CS is not
>>>>>>> supported as this configuration could not be tested due to
>>>>>>> unavailability of necessary hardware setup.
>>>>>> I've tested this chain on a released laptop (HP EliteBook 840 G9)
>>>>>> which uses SPI to interface to 2 amps, one amp uses a native CS and
>>>>>> the other uses a GPIO CS, and I noticed that when using this chain,
>>>>>> the second amp no longer works.
>>>>> Thank you for testing this patch series on GPIO CS setup. As I don't
>>>>> have a GPIO CS setup, is it possible for you debug the failure and
>>>>> share more details/logs where the problem is?
>>>>>
>>>>> Regards,
>>>>> Amit
>>>> We are willing and able to debug this failure and share the failure logs.
>>>> The first issue that I see is a kernel crash when trying to set the GPIO CS:
>>>>
>>>> [ 2.951658] general protection fault, probably for non-canonical
>>>> address
>>>> 0xdead000000000122: 0000 [#1] PREEMPT SMP NOPTI [ 2.951771] CPU:
>> 9
>>>> PID: 379 Comm: systemd-udevd Tainted: G A 6.3.0-rc3+ #30 [
>>>> 2.951826] Hardware name: HP /896D, BIOS U70 Ver. 89.33.02 10/29/2021
>>>> [ 2.951882] RIP: 0010:gpiod_set_value_cansleep+0x21/0xa0
>>>> [ 2.951941] Code: 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 48 85
>>>> ff
>>>> 74 3e 55 48 89 e5 41 55 41 89 f5 41 54 49 89 fc 48 81 ff 00 f0 ff ff
>>>> 77 2c <48> 8b 3f 48 85 ff 74 53 48 83 bf 68 03 00 00 00 74 34 44 89
>>>> ee 4c [ 2.952043]
>>>> RSP: 0018:ffffc008c0deb928 EFLAGS: 00010287 [ 2.952080] RAX:
>>>> 0000000000000001 RBX: ffffa0a489534c00 RCX:
>>>> 0000000000000000
>>>> [ 2.952124] RDX: dead000000000122 RSI: 0000000000000001 RDI:
>>>> dead000000000122
>>>> [ 2.952167] RBP: ffffc008c0deb938 R08: 0000000000000000 R09:
>>>> ffffc008c0deb868
>>>> [ 2.952211] R10: ffffffffffffffff R11: 00000000000000b0 R12:
>>>> dead000000000122
>>>> [ 2.952256] R13: 0000000000000001 R14: 0000000000000000 R15:
>>>> 0000000000000000
>>>> [ 2.952299] FS: 00007f7fa5b5b880(0000) GS:ffffa0a81f840000(0000)
>>>> knlGS:0000000000000000
>>>> [ 2.952369] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [
>>>> 2.952407] CR2: 000055d648427100 CR3: 000000010e960003 CR4:
>>>> 0000000000770ee0
>>>> [ 2.952451] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>>>> 0000000000000000
>>>> [ 2.952492] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7:
>>>> 0000000000000400
>>>> [ 2.952533] PKRU: 55555554
>>>> [ 2.952561] Call Trace:
>>>> [ 2.952579] <TASK>
>>>> [ 2.952598] spi_set_cs+0x257/0x4a0 [ 2.952630]
>>>> spi_setup+0x1a2/0x500 [ 2.952667] __spi_add_device+0x88/0x160 [
>>>> 2.952710] spi_add_device+0x60/0x90 [ 2.952738]
>>>> smi_spi_probe+0x178/0x370 [serial_multi_instantiate] [ 2.952792]
>>>> smi_probe+0xcf/0x110 [serial_multi_instantiate] [ 2.952854]
>>>> platform_probe+0x42/0xb0 [ 2.952885] really_probe+0x1b2/0x420 [
>>>> 2.952914] __driver_probe_device+0x7e/0x180 [ 2.952947]
>>>> driver_probe_device+0x23/0xa0 [ 2.952993]
>>>> __driver_attach+0xe4/0x1e0 [ 2.953021] ?
>>>> __pfx___driver_attach+0x10/0x10
>>>> [ 2.953061] bus_for_each_dev+0x7a/0xd0 [ 2.953088]
>>>> driver_attach+0x1e/0x30 [ 2.953123] bus_add_driver+0x11c/0x220 [
>>>> 2.953150] driver_register+0x64/0x130 [ 2.953174] ?
>>>> __pfx_init_module+0x10/0x10 [serial_multi_instantiate] [ 2.953221]
>>>> __platform_driver_register+0x1e/0x30
>>>> [ 2.953251] smi_driver_init+0x1c/0xff0 [serial_multi_instantiate]
>>>> [ 2.953310] do_one_initcall+0x46/0x220 [ 2.953339] ?
>>>> kmalloc_trace+0x2a/0xa0 [ 2.953375] do_init_module+0x52/0x220 [
>>>> 2.953411] load_module+0x223c/0x2460 [ 2.953450]
>>>> __do_sys_finit_module+0xc8/0x140 [ 2.953479] ?
>>>> __do_sys_finit_module+0xc8/0x140
>>>> [ 2.953510] __x64_sys_finit_module+0x18/0x20 [ 2.953538]
>>>> do_syscall_64+0x38/0x90 [ 2.953574]
>>>> entry_SYSCALL_64_after_hwframe+0x72/0xdc
>>>> [ 2.953606] RIP: 0033:0x7f7fa5d7476d [ 2.953639] Code: 00 c3 66
>>>> 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa
>>>> 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08
>>>> 0f
>>>> 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d f3 36 0d 00 f7 d8 64 89 01
>>>> 48 [ 2.953739] RSP: 002b:00007fff1f8dd3b8 EFLAGS: 00000246
>> ORIG_RAX:
>>>> 0000000000000139
>>>> [ 2.956833] RAX: ffffffffffffffda RBX: 000055d648654ab0 RCX:
>>>> 00007f7fa5d7476d
>>>> [ 2.959202] RDX: 0000000000000000 RSI: 00007f7fa5c54ded RDI:
>>>> 0000000000000006
>>>> [ 2.961542] RBP: 0000000000020000 R08: 0000000000000000 R09:
>>>> 0000000000000000
>>>> [ 2.964312] R10: 0000000000000006 R11: 0000000000000246 R12:
>>>> 00007f7fa5c54ded
>>>> [ 2.966694] R13: 0000000000000000 R14: 000055d6483f41a0 R15:
>>>> 000055d648654ab0
>>>> [ 2.967668] resource: resource sanity check: requesting [mem
>>>> 0x00000000fedc0000-0x00000000fedcffff], which spans more than pnp
>>>> 00:04 [mem 0xfedc0000-0xfedc7fff] [ 2.968998] </TASK> [
>>>> 2.971615] caller
>>>> igen6_probe+0x178/0x8e0 [igen6_edac] mapping multiple BARs [
>>>> 2.975014] Modules linked in: igen6_edac(+) fjes(-)
>>>> serial_multi_instantiate(+) int3403_thermal sch_fq_codel
>>>> int340x_thermal_zone int3400_thermal intel_hid acpi_thermal_rel
>>>> acpi_tad sparse_keymap acpi_pad mac_hid msr parport_pc ppdev lp
>>>> parport drm ramoops reed_solomon efi_pstore ip_tables x_tables
>>>> autofs4 spi_pxa2xx_platform dw_dmac dw_dmac_core nvme
>> intel_lpss_pci
>>>> intel_lpss crc32_pclmul thunderbolt i2c_i801 xhci_pci idma64
>>>> nvme_core i2c_smbus virt_dma xhci_pci_renesas video wmi
>>>> pinctrl_tigerlake [ 2.987901] ---[ end trace 0000000000000000 ]---
>> [ 3.157030] RIP:
>>>> 0010:gpiod_set_value_cansleep+0x21/0xa0
>>>> [ 3.159077] Code: 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 48 85
>>>> ff
>>>> 74 3e 55 48 89 e5 41 55 41 89 f5 41 54 49 89 fc 48 81 ff 00 f0 ff ff
>>>> 77 2c <48> 8b 3f 48 85 ff 74 53 48 83 bf 68 03 00 00 00 74 34 44 89
>>>> ee 4c [ 3.161461]
>>>> RSP: 0018:ffffc008c0deb928 EFLAGS: 00010287 [ 3.164005] RAX:
>>>> 0000000000000001 RBX: ffffa0a489534c00 RCX:
>>>> 0000000000000000
>>>> [ 3.166354] RDX: dead000000000122 RSI: 0000000000000001 RDI:
>>>> dead000000000122
>>>> [ 3.168499] RBP: ffffc008c0deb938 R08: 0000000000000000 R09:
>>>> ffffc008c0deb868
>>>> [ 3.170609] R10: ffffffffffffffff R11: 00000000000000b0 R12:
>>>> dead000000000122
>>>> [ 3.172893] R13: 0000000000000001 R14: 0000000000000000 R15:
>>>> 0000000000000000
>>>> [ 3.175335] FS: 00007f7fa5b5b880(0000) GS:ffffa0a81f840000(0000)
>>>> knlGS:0000000000000000
>>>> [ 3.180434] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [
>>>> 3.183356] CR2: 000055d648427100 CR3: 000000010e960003 CR4:
>>>> 0000000000770ee0
>>>> [ 3.185107] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>>>> 0000000000000000
>>>> [ 3.186840] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7:
>>>> 0000000000000400
>>>> [ 3.188647] PKRU: 55555554
>>> Thank you for sharing the logs.
>>> As per our analysis the spi->cs_gpiod[0] is getting messed up while
>>> setting it in __spi_add_device( ).
>>> Is it possible for you to do the following changes on top of this
>>> patch series & re-run your test.
>>>
>>> After applying this patch series, in drivers/spi/spi.c file replace
>>> the following code snippet in __spi_add_device( ) function defination.
>>>
>>> if (ctlr->cs_gpiods) {
>>> for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
>>> spi_set_csgpiod(spi, idx,
>>> ctlr->cs_gpiods[spi_get_chipselect(spi, idx)]); }
>>>
>>> with the below code snippet
>>>
>>> if (ctlr->cs_gpiods) {
>>> for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
>>> if (!(idx != 0 && !spi_get_chipselect(spi, idx)))
>>> spi_set_csgpiod(spi, idx, ctlr-
>>> cs_gpiods[spi_get_chipselect(spi, idx)]);
>>> }
>>> }
>>>
>>> then re-run your test.
>>>
>>> Regards,
>>> Amit
>> I'm still seeing a crash on probe:
>>
>> [ 3.265683] BUG: unable to handle page fault for address:
>> 00000000fffedfdd
>> [ 3.265744] #PF: supervisor read access in kernel mode [ 3.265781] #PF:
>> error_code(0x0000) - not-present page [ 3.265817] PGD 0 P4D 0
>> [ 3.265840] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 3.265865] CPU: 4 PID:
>> 385 Comm: systemd-udevd Tainted: G A 6.3.0-rc3+ #32 [ 3.265910]
>> Hardware name: HP /896D, BIOS U70 Ver. 89.33.02 10/29/2021 [ 3.265956]
>> RIP: 0010:gpiod_set_raw_value_commit+0x3d/0xf0
>> [ 3.266007] Code: 48 89 e5 41 55 44 0f b6 ee 41 54 53 48 8b 17 48 2b
>> 82 70 03 00 00 4c 8b a2 68 03 00 00 48 c1 f8 03 48 0f af c1 66 90 48 89
>> c6 <49> 8b 44 24 60 44 89 ea 4c 89 e7 ff d0 0f 1f 00 5b 41 5c 41 5d 5d
>> [ 3.266092] RSP: 0018:ffffaad780f6f620 EFLAGS: 00010a03 [ 3.266121]
>> RAX: 333330b6bdbad102 RBX: ffff9c8d4a5f6800 RCX:
>> cccccccccccccccd
>> [ 3.266156] RDX: ffff9c8d4a5f6d40 RSI: 333330b6bdbad102 RDI:
>> ffff9c8d4a5f6d40
>> [ 3.266192] RBP: ffffaad780f6f638 R08: 00000001018c3789 R09:
>> 0000000000000000
>> [ 3.266228] R10: ffff9c8c4009ee40 R11: 0000000000000000 R12:
>> 00000000fffedf7d
>> [ 3.266264] R13: 0000000000000000 R14: 0000000000000001 R15:
>> 0000000000000001
>> [ 3.266299] FS: 00007f98d04de880(0000) GS:ffff9c90df700000(0000)
>> knlGS:0000000000000000
>> [ 3.266358] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> [ 3.266388] CR2: 00000000fffedfdd CR3: 000000010b680003 CR4:
>> 0000000000770ee0
>> [ 3.266422] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>> 0000000000000000
>> [ 3.266457] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7:
>> 0000000000000400
>> [ 3.266490] PKRU: 55555554
>> [ 3.266513] Call Trace:
>> [ 3.266530] <TASK>
>> [ 3.266546] gpiod_set_value_nocheck+0x5b/0x70
>> [ 3.266583] gpiod_set_value_cansleep+0x3e/0xa0
>> [ 3.266609] spi_set_cs+0x257/0x4a0
>> [ 3.266634] spi_transfer_one_message+0x49/0x740
>> [ 3.266672] __spi_pump_transfer_message+0x29b/0x620
>> [ 3.266712] __spi_sync+0x26f/0x3b0
>> [ 3.266735] spi_write_then_read+0x157/0x210 [ 3.266771] ?
>> psi_group_change+0x175/0x3b0 [ 3.266802] regmap_spi_read+0xe/0x20
>> [ 3.266826] _regmap_raw_read+0xe1/0x210
>> [ 3.266861] _regmap_bus_read+0x3a/0x70
>> [ 3.266887] _regmap_read+0x66/0x140
>> [ 3.266918] regmap_read+0x3f/0x70
>> [ 3.266957] cs35l41_hda_probe+0x553/0xc10 [snd_hda_scodec_cs35l41]
>> [ 3.267027] cs35l41_hda_spi_probe+0x62/0x80
>> [snd_hda_scodec_cs35l41_spi] [ 3.267096] spi_probe+0x55/0x90
>> [ 3.267145] really_probe+0x1b2/0x420
>> [ 3.267184] __driver_probe_device+0x7e/0x180
>> [ 3.267227] driver_probe_device+0x23/0xa0
>> [ 3.267287] __driver_attach+0xe4/0x1e0 [ 3.267326] ?
>> __pfx___driver_attach+0x10/0x10
>> [ 3.267381] bus_for_each_dev+0x7a/0xd0
>> [ 3.267406] driver_attach+0x1e/0x30
>> [ 3.267437] bus_add_driver+0x11c/0x220
>> [ 3.267461] driver_register+0x64/0x130 [ 3.267483] ?
>> __pfx_init_module+0x10/0x10 [snd_hda_scodec_cs35l41_spi]
>> [ 3.267525] __spi_register_driver+0xa1/0xd0 [ 3.270712] ?
>> __pfx_init_module+0x10/0x10 [snd_hda_scodec_cs35l41_spi]
>> [ 3.273446] cs35l41_spi_driver_init+0x1c/0xff0
>> [snd_hda_scodec_cs35l41_spi]
>> [ 3.275119] do_one_initcall+0x46/0x220 [ 3.276828] ?
>> kmalloc_trace+0x2a/0xa0 [ 3.279290] do_init_module+0x52/0x220
>> [ 3.283593] load_module+0x223c/0x2460
>> [ 3.283602] __do_sys_finit_module+0xc8/0x140 [ 3.287883] ?
>> __do_sys_finit_module+0xc8/0x140
>> [ 3.287907] __x64_sys_finit_module+0x18/0x20
>> [ 3.293156] do_syscall_64+0x38/0x90
>> [ 3.298937] entry_SYSCALL_64_after_hwframe+0x72/0xdc
>> [ 3.298945] RIP: 0033:0x7f98d06f776d
>> [ 3.319574] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa
>> 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f
>> 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d f3 36 0d 00 f7 d8 64 89 01 48
>> [ 3.319579] RSP: 002b:00007ffd988f7a08 EFLAGS: 00000246 ORIG_RAX:
>> 0000000000000139
>> [ 3.319585] RAX: ffffffffffffffda RBX: 000055af06a7d030 RCX:
>> 00007f98d06f776d
>> [ 3.319589] RDX: 0000000000000000 RSI: 00007f98d05d7ded RDI:
>> 0000000000000013
>> [ 3.329520] RBP: 0000000000020000 R08: 0000000000000000 R09:
>> 0000000000000000
>> [ 3.329523] R10: 0000000000000013 R11: 0000000000000246 R12:
>> 00007f98d05d7ded
>> [ 3.329525] R13: 0000000000000000 R14: 000055af06cdd040 R15:
>> 000055af06a7d030
>> [ 3.329531] </TASK>
>> [ 3.329533] Modules linked in: snd_hda_intel(+) ttm snd_intel_dspcfg btusb
>> rapl snd_seq_midi snd_intel_sdw_acpi libarc4 intel_cstate binfmt_misc
>> uvcvideo(+) snd_seq_midi_event btrtl
>> snd_hda_scodec_cs35l41_spi(+) snd_hda_codec drm_display_helper
>> cdc_ncm(+) videobuf2_vmalloc snd_rawmidi btbcm uvc cdc_ether cec btintel
>> videobuf2_memops snd_hda_scodec_cs35l41_i2c snd_hda_core
>> videobuf2_v4l2 uas usbnet rc_core snd_hwdep btmtk
>> snd_hda_scodec_cs35l41 input_leds mii wmi_bmof videodev snd_seq
>> processor_thermal_device_pci bluetooth iwlwifi drm_kms_helper snd_pcm
>> snd_hda_cs_dsp_ctls processor_thermal_device mei_me
>> videobuf2_common snd_seq_device i2c_algo_bit cs_dsp
>> processor_thermal_rfim ecdh_generic usb_storage serio_raw mc
>> syscopyarea ecc processor_thermal_mbox ucsi_acpi snd_soc_cs35l41_lib
>> 8250_dw mei snd_timer cfg80211 sysfillrect typec_ucsi
>> processor_thermal_rapl igen6_edac sysimgblt intel_rapl_common typec snd
>> soundcore int3403_thermal int340x_thermal_zone serial_multi_instantiate
>> int3400_thermal intel_hid acpi_thermal_rel [ 3.338475] sparse_keymap
>> acpi_tad acpi_pad mac_hid sch_fq_codel msr parport_pc ppdev lp parport
>> drm ramoops reed_solomon efi_pstore ip_tables x_tables autofs4
>> spi_pxa2xx_platform dw_dmac dw_dmac_core intel_lpss_pci nvme
>> intel_lpss i2c_i801 idma64 crc32_pclmul thunderbolt i2c_smbus nvme_core
>> xhci_pci virt_dma xhci_pci_renesas video wmi pinctrl_tigerlake [ 3.338514]
>> CR2: 00000000fffedfdd [ 3.338517] ---[ end trace 0000000000000000 ]---
>> [ 3.504965] RIP: 0010:gpiod_set_raw_value_commit+0x3d/0xf0
>> [ 3.504973] Code: 48 89 e5 41 55 44 0f b6 ee 41 54 53 48 8b 17 48 2b
>> 82 70 03 00 00 4c 8b a2 68 03 00 00 48 c1 f8 03 48 0f af c1 66 90 48 89
>> c6 <49> 8b 44 24 60 44 89 ea 4c 89 e7 ff d0 0f 1f 00 5b 41 5c 41 5d 5d
>> [ 3.504975] RSP: 0018:ffffaad780f6f620 EFLAGS: 00010a03 [ 3.504978]
>> RAX: 333330b6bdbad102 RBX: ffff9c8d4a5f6800 RCX:
>> cccccccccccccccd
>> [ 3.504979] RDX: ffff9c8d4a5f6d40 RSI: 333330b6bdbad102 RDI:
>> ffff9c8d4a5f6d40
>> [ 3.504980] RBP: ffffaad780f6f638 R08: 00000001018c3789 R09:
>> 0000000000000000
>> [ 3.504982] R10: ffff9c8c4009ee40 R11: 0000000000000000 R12:
>> 00000000fffedf7d
>> [ 3.504983] R13: 0000000000000000 R14: 0000000000000001 R15:
>> 0000000000000001
>> [ 3.504984] FS: 00007f98d04de880(0000) GS:ffff9c90df700000(0000)
>> knlGS:0000000000000000
>> [ 3.504986] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> [ 3.504988] CR2: 00000000fffedfdd CR3: 000000010b680003 CR4:
>> 0000000000770ee0
>> [ 3.504989] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>> 0000000000000000
>> [ 3.504990] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7:
>> 0000000000000400
>> [ 3.504992] PKRU: 55555554
>>
>> Thanks,
>> Stefan
> Thanks for the logs.
>
> Could you please confirm that your test case was passing with
> https://github.com/torvalds/linux/commit/303feb3cc06ac0665d0ee9c1414941200e60e8a3 patch
> but it is failing with the current patch series ?
I retested with the latest master kernel
https://github.com/torvalds/linux/commit/33afd4b76393627477e878b3b195d606e585d816
and I could see it worked fine. I attached a dmesg log of this.
That particular commit id you posted does not work, due to a different
issue which was fixed in a later commit.
>
> Regarding the failure
> The logs suggest that we are trying to access an invalid pointer while
> calling the gpiod_set_value_cansleep( ) API.
> This could be possible if the cs_num is corrupted and we are trying to
> access an invalid spi->cs_gpiod[ ].
> To confirm the same could you please do the following changes in the
> code and re-test.
>
> After applying this patch series, in drivers/spi/spi.c file replace the
> following code snippet in __spi_add_device( ) function definition.
> if (ctlr->cs_gpiods) {
> for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
> spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[spi_get_chipselect(spi, idx)]);
> }
>
> with the below code snippet
>
> if (ctlr->cs_gpiods) {
> for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
> if (!(idx != 0 && !spi_get_chipselect(spi, idx))) {
> printk("%s( ) [%d] cs[%d] = [%d]\n", __func__, __LINE__, idx, spi_get_chipselect(spi, idx));
> spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[spi_get_chipselect(spi, idx)]);
> }
> }
> }
>
> And at the start of spi_set_cs( ) function in drivers/spi/spi.c file add
> the following print statements.
>
> printk("%s( ) [%d] spi->cs_index_mask == [%d]\n", __func__, __LINE__, spi->cs_index_mask);
> printk("%s( ) [%d] cs_num == [%d]\n", __func__, __LINE__, cs_num);
I've attached dmesg log of this. It no longer crashes when using the
prints (I am unsure why), but it still does not work.
For sanity, I retested these changes with the print lines commented out,
and the crash returned.
>
> Thanks,
> Amit
>>>> Thanks,
>>>>
>>>> Stefan
>>>>
>>>>>> Thanks,
>>>>>> Stefan Binding
>>>>>>
>>>>>>> Signed-off-by: Amit Kumar Mahapatra <amit.kumar-
>>>>>> mahapatra@....com>
>>>>>>> ---
>>>>>>> drivers/spi/spi.c | 226
>>>>>> ++++++++++++++++++++++++++++------------
>>>>>>> include/linux/spi/spi.h | 32 ++++--
>>>>>>> 2 files changed, 183 insertions(+), 75 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index
>>>>>>> 9036d7a50674..04d7322170c4 100644
>>>>>>> --- a/drivers/spi/spi.c
>>>>>>> +++ b/drivers/spi/spi.c
>>>>>>> @@ -612,10 +612,24 @@ static int spi_dev_check(struct device *dev,
>>>>>>> void *data) {
>>>>>>> struct spi_device *spi = to_spi_device(dev);
>>>>>>> struct spi_device *new_spi = data;
>>>>>>> + int idx, nw_idx;
>>>>>>>
>>>>>>> - if (spi->controller == new_spi->controller &&
>>>>>>> - spi_get_chipselect(spi, 0) == spi_get_chipselect(new_spi,
>>>>>> 0))
>>>>>>> - return -EBUSY;
>>>>>>> + if (spi->controller == new_spi->controller) {
>>>>>>> + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
>>>>>>> + for (nw_idx = 0; nw_idx < SPI_CS_CNT_MAX;
>>>>>>> nw_idx++) {
>>>>>>> + if ((idx != 0 &&
>>>>>> !spi_get_chipselect(spi,
>>>>>>> idx)) ||
>>>>>>> + (nw_idx != 0 &&
>>>>>>> !spi_get_chipselect(spi, nw_idx))) {
>>>>>>> + continue;
>>>>>>> + } else if (spi_get_chipselect(spi,
>>>>>> idx) ==
>>>>>>> + spi_get_chipselect(new_spi,
>>>>>> nw_idx))
>>>>>>> {
>>>>>>> + dev_err(dev,
>>>>>>> + "chipselect %d
>> already
>>>>>>> in use\n",
>>>>>>> +
>>>>>>> spi_get_chipselect(new_spi, nw_idx));
>>>>>>> + return -EBUSY;
>>>>>>> + }
>>>>>>> + }
>>>>>>> + }
>>>>>>> + }
>>>>>>> return 0;
>>>>>>> }
>>>>>>>
>>>>>>> @@ -629,7 +643,7 @@ static int __spi_add_device(struct spi_device
>>>>>>> *spi)
>>>>>>> {
>>>>>>> struct spi_controller *ctlr = spi->controller;
>>>>>>> struct device *dev = ctlr->dev.parent;
>>>>>>> - int status;
>>>>>>> + int status, idx;
>>>>>>>
>>>>>>> /*
>>>>>>> * We need to make sure there's no other device with this
>> @@
>>>>>>> -638,8
>>>>>>> +652,6 @@ static int __spi_add_device(struct spi_device
>>>>>>> *spi)
>>>>>>> */
>>>>>>> status = bus_for_each_dev(&spi_bus_type, NULL, spi,
>>>>>> spi_dev_check);
>>>>>>> if (status) {
>>>>>>> - dev_err(dev, "chipselect %d already in use\n",
>>>>>>> - spi_get_chipselect(spi, 0));
>>>>>>> return status;
>>>>>>> }
>>>>>>>
>>>>>>> @@ -649,8 +661,10 @@ static int __spi_add_device(struct spi_device
>>>>>>> *spi)
>>>>>>> return -ENODEV;
>>>>>>> }
>>>>>>>
>>>>>>> - if (ctlr->cs_gpiods)
>>>>>>> - spi_set_csgpiod(spi, 0, ctlr-
>>>>>>>> cs_gpiods[spi_get_chipselect(spi, 0)]);
>>>>>>> + if (ctlr->cs_gpiods) {
>>>>>>> + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
>>>>>>> + spi_set_csgpiod(spi, idx, ctlr-
>>>>>>>> cs_gpiods[spi_get_chipselect(spi, idx)]);
>>>>>>> + }
>>>>>>>
>>>>>>> /*
>>>>>>> * Drivers may modify this initial i/o setup, but will @@
>>>>>>> -690,13
>>>>>>> +704,15 @@ int spi_add_device(struct spi_device *spi) {
>>>>>>> struct spi_controller *ctlr = spi->controller;
>>>>>>> struct device *dev = ctlr->dev.parent;
>>>>>>> - int status;
>>>>>>> + int status, idx;
>>>>>>>
>>>>>>> - /* Chipselects are numbered 0..max; validate. */
>>>>>>> - if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) {
>>>>>>> - dev_err(dev, "cs%d >= max %d\n",
>>>>>>> spi_get_chipselect(spi, 0),
>>>>>>> - ctlr->num_chipselect);
>>>>>>> - return -EINVAL;
>>>>>>> + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
>>>>>>> + /* Chipselects are numbered 0..max; validate. */
>>>>>>> + if (spi_get_chipselect(spi, idx) >=
>>>>>> ctlr->num_chipselect) {
>>>>>>> + dev_err(dev, "cs%d >= max %d\n",
>>>>>>> spi_get_chipselect(spi, idx),
>>>>>>> + ctlr->num_chipselect);
>>>>>>> + return -EINVAL;
>>>>>>> + }
>>>>>>> }
>>>>>>>
>>>>>>> /* Set the bus ID string */
>>>>>>> @@ -713,12 +729,15 @@ static int spi_add_device_locked(struct
>>>>>>> spi_device *spi) {
>>>>>>> struct spi_controller *ctlr = spi->controller;
>>>>>>> struct device *dev = ctlr->dev.parent;
>>>>>>> + int idx;
>>>>>>>
>>>>>>> - /* Chipselects are numbered 0..max; validate. */
>>>>>>> - if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) {
>>>>>>> - dev_err(dev, "cs%d >= max %d\n",
>>>>>>> spi_get_chipselect(spi, 0),
>>>>>>> - ctlr->num_chipselect);
>>>>>>> - return -EINVAL;
>>>>>>> + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
>>>>>>> + /* Chipselects are numbered 0..max; validate. */
>>>>>>> + if (spi_get_chipselect(spi, idx) >=
>>>>>> ctlr->num_chipselect) {
>>>>>>> + dev_err(dev, "cs%d >= max %d\n",
>>>>>>> spi_get_chipselect(spi, idx),
>>>>>>> + ctlr->num_chipselect);
>>>>>>> + return -EINVAL;
>>>>>>> + }
>>>>>>> }
>>>>>>>
>>>>>>> /* Set the bus ID string */
>>>>>>> @@ -966,58 +985,118 @@ static void spi_res_release(struct
>>>>>>> spi_controller *ctlr, struct spi_message *mes static void
>>>>>>> spi_set_cs(struct spi_device *spi, bool enable, bool
>>>>>> force)
>>>>>>> {
>>>>>>> bool activate = enable;
>>>>>>> + u32 cs_num = __ffs(spi->cs_index_mask);
>>>>>>> + int idx;
>>>>>>>
>>>>>>> /*
>>>>>>> - * Avoid calling into the driver (or doing delays) if the chip
>>>>>> select
>>>>>>> - * isn't actually changing from the last time this was called.
>>>>>>> + * In parallel mode all the chip selects are
>>>>>> asserted/de-asserted
>>>>>>> + * at once
>>>>>>> */
>>>>>>> - if (!force && ((enable && spi->controller->last_cs ==
>>>>>>> spi_get_chipselect(spi, 0)) ||
>>>>>>> - (!enable && spi->controller->last_cs !=
>>>>>>> spi_get_chipselect(spi, 0))) &&
>>>>>>> - (spi->controller->last_cs_mode_high == (spi->mode &
>>>>>>> SPI_CS_HIGH)))
>>>>>>> - return;
>>>>>>> -
>>>>>>> - trace_spi_set_cs(spi, activate);
>>>>>>> -
>>>>>>> - spi->controller->last_cs = enable ? spi_get_chipselect(spi, 0)
>>>>>> : -1;
>>>>>>> - spi->controller->last_cs_mode_high = spi->mode &
>>>>>>> SPI_CS_HIGH;
>>>>>>> -
>>>>>>> - if ((spi_get_csgpiod(spi, 0) ||
>>>>>> !spi->controller->set_cs_timing)
>>>>>>> && !activate)
>>>>>>> - spi_delay_exec(&spi->cs_hold, NULL);
>>>>>>> -
>>>>>>> - if (spi->mode & SPI_CS_HIGH)
>>>>>>> - enable = !enable;
>>>>>>> + if ((spi->cs_index_mask & SPI_PARALLEL_CS_MASK) ==
>>>>>>> SPI_PARALLEL_CS_MASK) {
>>>>>>> + spi->controller->last_cs_mode_high = spi->mode &
>>>>>>> SPI_CS_HIGH;
>>>>>>> +
>>>>>>> + if ((spi_get_csgpiod(spi, 0) || !spi->controller-
>>>>>>>> set_cs_timing) && !activate)
>>>>>>> + spi_delay_exec(&spi->cs_hold, NULL);
>>>>>>> +
>>>>>>> + if (spi->mode & SPI_CS_HIGH)
>>>>>>> + enable = !enable;
>>>>>>> +
>>>>>>> + if (spi_get_csgpiod(spi, 0) && spi_get_csgpiod(spi,
>>>>>> 1)) {
>>>>>>> + if (!(spi->mode & SPI_NO_CS)) {
>>>>>>> + /*
>>>>>>> + * Historically ACPI has no means of
>>>>>> the
>>>>>>> GPIO polarity and
>>>>>>> + * thus the SPISerialBus() resource
>>>>>>> defines it on the per-chip
>>>>>>> + * basis. In order to avoid a chain of
>>>>>>> negations, the GPIO
>>>>>>> + * polarity is considered being Active
>>>>>>> High. Even for the cases
>>>>>>> + * when _DSD() is involved (in the
>>>>>>> updated versions of ACPI)
>>>>>>> + * the GPIO CS polarity must be
>>>>>> defined
>>>>>>> Active High to avoid
>>>>>>> + * ambiguity. That's why we use
>>>>>> enable,
>>>>>>> that takes SPI_CS_HIGH
>>>>>>> + * into account.
>>>>>>> + */
>>>>>>> + if (has_acpi_companion(&spi->dev)) {
>>>>>>> + for (idx = 0; idx <
>>>>>>> SPI_CS_CNT_MAX; idx++)
>>>>>>> +
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx),
>>>>>>> +
>>>>>>> !enable);
>>>>>>> + } else {
>>>>>>> + for (idx = 0; idx <
>>>>>>> SPI_CS_CNT_MAX; idx++)
>>>>>>> + /* Polarity handled by
>>>>>>> GPIO library */
>>>>>>> +
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, idx),
>>>>>>> +
>>>>>>> activate);
>>>>>>> + }
>>>>>>> + }
>>>>>>> + /* Some SPI masters need both GPIO CS &
>>>>>>> slave_select */
>>>>>>> + if ((spi->controller->flags &
>>>>>>> SPI_MASTER_GPIO_SS) &&
>>>>>>> + spi->controller->set_cs)
>>>>>>> + spi->controller->set_cs(spi, !enable);
>>>>>>> + } else if (spi->controller->set_cs) {
>>>>>>> + spi->controller->set_cs(spi, !enable);
>>>>>>> + }
>>>>>>>
>>>>>>> - if (spi_get_csgpiod(spi, 0)) {
>>>>>>> - if (!(spi->mode & SPI_NO_CS)) {
>>>>>>> - /*
>>>>>>> - * Historically ACPI has no means of the GPIO
>>>>>>> polarity and
>>>>>>> - * thus the SPISerialBus() resource defines it
>>>>>> on
>>>>>>> the per-chip
>>>>>>> - * basis. In order to avoid a chain of
>>>>>> negations,
>>>>>>> the GPIO
>>>>>>> - * polarity is considered being Active High.
>>>>>> Even
>>>>>>> for the cases
>>>>>>> - * when _DSD() is involved (in the updated
>>>>>>> versions of ACPI)
>>>>>>> - * the GPIO CS polarity must be defined Active
>>>>>>> High to avoid
>>>>>>> - * ambiguity. That's why we use enable, that
>>>>>>> takes SPI_CS_HIGH
>>>>>>> - * into account.
>>>>>>> - */
>>>>>>> - if (has_acpi_companion(&spi->dev))
>>>>>>> -
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), !enable);
>>>>>>> + if (spi_get_csgpiod(spi, 0) || spi_get_csgpiod(spi, 1)
>>>>>> ||
>>>>>>> + !spi->controller->set_cs_timing) {
>>>>>>> + if (activate)
>>>>>>> + spi_delay_exec(&spi->cs_setup,
>> NULL);
>>>>>>> else
>>>>>>> - /* Polarity handled by GPIO library */
>>>>>>> -
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), activate);
>>>>>>> + spi_delay_exec(&spi->cs_inactive,
>>>>>>> NULL);
>>>>>>> }
>>>>>>> - /* Some SPI masters need both GPIO CS & slave_select
>>>>>>> */
>>>>>>> - if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
>>>>>>> - spi->controller->set_cs)
>>>>>>> + } else {
>>>>>>> + /*
>>>>>>> + * Avoid calling into the driver (or doing delays) if
>>>>>> the
>>>>>>> chip select
>>>>>>> + * isn't actually changing from the last time this was
>>>>>>> called.
>>>>>>> + */
>>>>>>> + if (!force && ((enable && spi->controller->last_cs ==
>>>>>>> + spi_get_chipselect(spi, cs_num)) ||
>>>>>>> + (!enable && spi->controller->last_cs
>>>>>> !=
>>>>>>> + spi_get_chipselect(spi, cs_num))) &&
>>>>>>> + (spi->controller->last_cs_mode_high ==
>>>>>>> + (spi->mode & SPI_CS_HIGH)))
>>>>>>> + return;
>>>>>>> +
>>>>>>> + trace_spi_set_cs(spi, activate);
>>>>>>> +
>>>>>>> + spi->controller->last_cs = enable ?
>>>>>>> spi_get_chipselect(spi, cs_num) : -1;
>>>>>>> + spi->controller->last_cs_mode_high = spi->mode &
>>>>>>> SPI_CS_HIGH;
>>>>>>> +
>>>>>>> + if ((spi_get_csgpiod(spi, cs_num) || !spi->controller-
>>>>>>>> set_cs_timing) && !activate)
>>>>>>> + spi_delay_exec(&spi->cs_hold, NULL);
>>>>>>> +
>>>>>>> + if (spi->mode & SPI_CS_HIGH)
>>>>>>> + enable = !enable;
>>>>>>> +
>>>>>>> + if (spi_get_csgpiod(spi, cs_num)) {
>>>>>>> + if (!(spi->mode & SPI_NO_CS)) {
>>>>>>> + /*
>>>>>>> + * Historically ACPI has no means of
>>>>>> the
>>>>>>> GPIO polarity and
>>>>>>> + * thus the SPISerialBus() resource
>>>>>>> defines it on the per-chip
>>>>>>> + * basis. In order to avoid a chain of
>>>>>>> negations, the GPIO
>>>>>>> + * polarity is considered being Active
>>>>>>> High. Even for the cases
>>>>>>> + * when _DSD() is involved (in the
>>>>>>> updated versions of ACPI)
>>>>>>> + * the GPIO CS polarity must be
>>>>>> defined
>>>>>>> Active High to avoid
>>>>>>> + * ambiguity. That's why we use
>>>>>> enable,
>>>>>>> that takes SPI_CS_HIGH
>>>>>>> + * into account.
>>>>>>> + */
>>>>>>> + if (has_acpi_companion(&spi->dev))
>>>>>>> +
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, cs_num),
>>>>>>> +
>>>>>>> !enable);
>>>>>>> + else
>>>>>>> + /* Polarity handled by GPIO
>>>>>>> library */
>>>>>>> +
>>>>>>> gpiod_set_value_cansleep(spi_get_csgpiod(spi, cs_num),
>>>>>>> +
>>>>>>> activate);
>>>>>>> + }
>>>>>>> + /* Some SPI masters need both GPIO CS &
>>>>>>> slave_select */
>>>>>>> + if ((spi->controller->flags &
>>>>>>> SPI_MASTER_GPIO_SS) &&
>>>>>>> + spi->controller->set_cs)
>>>>>>> + spi->controller->set_cs(spi, !enable);
>>>>>>> + } else if (spi->controller->set_cs) {
>>>>>>> spi->controller->set_cs(spi, !enable);
>>>>>>> - } else if (spi->controller->set_cs) {
>>>>>>> - spi->controller->set_cs(spi, !enable);
>>>>>>> - }
>>>>>>> + }
>>>>>>>
>>>>>>> - if (spi_get_csgpiod(spi, 0) ||
>>>>>> !spi->controller->set_cs_timing) {
>>>>>>> - if (activate)
>>>>>>> - spi_delay_exec(&spi->cs_setup, NULL);
>>>>>>> - else
>>>>>>> - spi_delay_exec(&spi->cs_inactive, NULL);
>>>>>>> + if (spi_get_csgpiod(spi, cs_num) || !spi->controller-
>>>>>>>> set_cs_timing) {
>>>>>>> + if (activate)
>>>>>>> + spi_delay_exec(&spi->cs_setup,
>> NULL);
>>>>>>> + else
>>>>>>> + spi_delay_exec(&spi->cs_inactive,
>>>>>>> NULL);
>>>>>>> + }
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> @@ -2246,8 +2325,8 @@ static void of_spi_parse_dt_cs_delay(struct
>>>>>>> device_node *nc, static int of_spi_parse_dt(struct spi_controller
>>>>>>> *ctlr, struct
>>>>>> spi_device
>>>>>>> *spi,
>>>>>>> struct device_node *nc)
>>>>>>> {
>>>>>>> - u32 value;
>>>>>>> - int rc;
>>>>>>> + u32 value, cs[SPI_CS_CNT_MAX] = {0};
>>>>>>> + int rc, idx;
>>>>>>>
>>>>>>> /* Mode (clock phase/polarity/etc.) */
>>>>>>> if (of_property_read_bool(nc, "spi-cpha")) @@ -2320,13
>>>>>>> +2399,21
>>>>>> @@
>>>>>>> static int of_spi_parse_dt(struct spi_controller *ctlr, struct
>>>>>>> spi_device *spi,
>>>>>>> }
>>>>>>>
>>>>>>> /* Device address */
>>>>>>> - rc = of_property_read_u32(nc, "reg", &value);
>>>>>>> - if (rc) {
>>>>>>> + rc = of_property_read_variable_u32_array(nc, "reg", &cs[0],
>> 1,
>>>>>>> + SPI_CS_CNT_MAX);
>>>>>>> + if (rc < 0 || rc > ctlr->num_chipselect) {
>>>>>>> dev_err(&ctlr->dev, "%pOF has no valid 'reg' property
>>>>>> (%d)\n",
>>>>>>> nc, rc);
>>>>>>> return rc;
>>>>>>> + } else if ((of_property_read_bool(nc, "parallel-memories"))
>> &&
>>>>>>> + (!(ctlr->flags & SPI_CONTROLLER_MULTI_CS))) {
>>>>>>> + dev_err(&ctlr->dev, "SPI controller doesn't support
>>>>>> multi
>>>>>>> CS\n");
>>>>>>> + return -EINVAL;
>>>>>>> }
>>>>>>> - spi_set_chipselect(spi, 0, value);
>>>>>>> + for (idx = 0; idx < rc; idx++)
>>>>>>> + spi_set_chipselect(spi, idx, cs[idx]);
>>>>>>> + /* By default set the spi->cs_index_mask as 1 */
>>>>>>> + spi->cs_index_mask = 0x01;
>>>>>>>
>>>>>>> /* Device speed */
>>>>>>> if (!of_property_read_u32(nc, "spi-max-frequency", &value))
>> @@
>>>>>>> -3907,7 +3994,8 @@ static int __spi_validate(struct spi_device
>>>>>>> *spi, struct spi_message *message)
>>>>>>> * cs_change is set for each transfer.
>>>>>>> */
>>>>>>> if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits &
>>>>>>> SPI_CS_WORD) ||
>>>>>>> - spi_get_csgpiod(spi, 0))) {
>>>>>>> + spi_get_csgpiod(spi, 0) ||
>>>>>>> + spi_get_csgpiod(spi, 1))) {
>>>>>>> size_t maxsize;
>>>>>>> int ret;
>>>>>>>
>>>>>>> diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
>>>>>>> index 873ced6ae4ca..6453b246e0af 100644
>>>>>>> --- a/include/linux/spi/spi.h
>>>>>>> +++ b/include/linux/spi/spi.h
>>>>>>> @@ -19,6 +19,11 @@
>>>>>>> #include <linux/acpi.h>
>>>>>>> #include <linux/u64_stats_sync.h>
>>>>>>>
>>>>>>> +/* Max no. of CS supported per spi device */ #define
>>>>>>> +SPI_CS_CNT_MAX
>>>>>>> +2
>>>>>>> +
>>>>>>> +/* chip select mask */
>>>>>>> +#define SPI_PARALLEL_CS_MASK (BIT(0) | BIT(1))
>>>>>>> struct dma_chan;
>>>>>>> struct software_node;
>>>>>>> struct ptp_system_timestamp;
>>>>>>> @@ -166,6 +171,7 @@ extern void
>>>>>>> spi_transfer_cs_change_delay_exec(struct spi_message *msg,
>>>>>>> * deasserted. If @cs_change_delay is used from
>> @spi_transfer,
>>>>>>> then the
>>>>>>> * two delays will be added up.
>>>>>>> * @pcpu_statistics: statistics for the spi_device
>>>>>>> + * @cs_index_mask: Bit mask of the active chipselect(s) in the
>>>>>>> chipselect array
>>>>>>> *
>>>>>>> * A @spi_device is used to interchange data between an SPI slave
>>>>>>> * (usually a discrete chip) and CPU memory.
>>>>>>> @@ -181,7 +187,7 @@ struct spi_device {
>>>>>>> struct spi_controller *controller;
>>>>>>> struct spi_controller *master; /* Compatibility layer
>>>>>> */
>>>>>>> u32 max_speed_hz;
>>>>>>> - u8 chip_select;
>>>>>>> + u8 chip_select[SPI_CS_CNT_MAX];
>>>>>>> u8 bits_per_word;
>>>>>>> bool rt;
>>>>>>> #define SPI_NO_TX BIT(31) /* No transmit wire */
>>>>>>> @@ -202,7 +208,7 @@ struct spi_device {
>>>>>>> void *controller_data;
>>>>>>> char modalias[SPI_NAME_SIZE];
>>>>>>> const char *driver_override;
>>>>>>> - struct gpio_desc *cs_gpiod; /* Chip select gpio
>>>>>> desc
>>>>>>> */
>>>>>>> + struct gpio_desc *cs_gpiod[SPI_CS_CNT_MAX]; /*
>>>>>> Chip
>>>>>>> select gpio desc */
>>>>>>> struct spi_delay word_delay; /* Inter-word delay */
>>>>>>> /* CS delays */
>>>>>>> struct spi_delay cs_setup;
>>>>>>> @@ -212,6 +218,13 @@ struct spi_device {
>>>>>>> /* The statistics */
>>>>>>> struct spi_statistics __percpu *pcpu_statistics;
>>>>>>>
>>>>>>> + /* Bit mask of the chipselect(s) that the driver need to use
>>>>>> from
>>>>>>> + * the chipselect array.When the controller is capable to
>>>>>> handle
>>>>>>> + * multiple chip selects & memories are connected in parallel
>>>>>>> + * then more than one bit need to be set in cs_index_mask.
>>>>>>> + */
>>>>>>> + u32 cs_index_mask : SPI_CS_CNT_MAX;
>>>>>>> +
>>>>>>> /*
>>>>>>> * likely need more hooks for more protocol options affecting
>> how
>>>>>>> * the controller talks to each chip, like:
>>>>>>> @@ -268,22 +281,22 @@ static inline void *spi_get_drvdata(const
>>>>>>> struct spi_device *spi)
>>>>>>>
>>>>>>> static inline u8 spi_get_chipselect(const struct spi_device
>>>>>>> *spi,
>>>>>> u8 idx)
>>>>>>> {
>>>>>>> - return spi->chip_select;
>>>>>>> + return spi->chip_select[idx];
>>>>>>> }
>>>>>>>
>>>>>>> static inline void spi_set_chipselect(struct spi_device *spi,
>>>>>>> u8
>>>>>> idx, u8
>>>>>>> chipselect)
>>>>>>> {
>>>>>>> - spi->chip_select = chipselect;
>>>>>>> + spi->chip_select[idx] = chipselect;
>>>>>>> }
>>>>>>>
>>>>>>> static inline struct gpio_desc *spi_get_csgpiod(const struct
>>>>>> spi_device
>>>>>>> *spi, u8 idx)
>>>>>>> {
>>>>>>> - return spi->cs_gpiod;
>>>>>>> + return spi->cs_gpiod[idx];
>>>>>>> }
>>>>>>>
>>>>>>> static inline void spi_set_csgpiod(struct spi_device *spi, u8
>>>>>>> idx,
>>>>>> struct
>>>>>>> gpio_desc *csgpiod)
>>>>>>> {
>>>>>>> - spi->cs_gpiod = csgpiod;
>>>>>>> + spi->cs_gpiod[idx] = csgpiod;
>>>>>>> }
>>>>>>>
>>>>>>> /**
>>>>>>> @@ -388,6 +401,8 @@ extern struct spi_device
>>>>>>> *spi_new_ancillary_device(struct spi_device *spi, u8 ch
>>>>>>> * @bus_lock_spinlock: spinlock for SPI bus locking
>>>>>>> * @bus_lock_mutex: mutex for exclusion of multiple callers
>>>>>>> * @bus_lock_flag: indicates that the SPI bus is locked for
>>>>>> exclusive use
>>>>>>> + * @multi_cs_cap: indicates that the SPI Controller can
>>>>>> assert/de-assert
>>>>>>> + * more than one chip select at once.
>>>>>>> * @setup: updates the device mode and clocking records used by a
>>>>>>> * device's SPI controller; protocol code may call this. This
>>>>>>> * must fail if an unrecognized or unsupported mode is
>> requested.
>>>>>>> @@ -554,6 +569,11 @@ struct spi_controller {
>>>>>>> #define SPI_CONTROLLER_MUST_TX BIT(4) /* Requires tx
>>>>>>> */
>>>>>>>
>>>>>>> #define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must
>>>>>> select
>>>>>>> slave */
>>>>>>> + /*
>>>>>>> + * The spi-controller has multi chip select capability and can
>>>>>>> + * assert/de-assert more than one chip select at once.
>>>>>>> + */
>>>>>>> +#define SPI_CONTROLLER_MULTI_CS BIT(6)
>>>>>>>
>>>>>>> /* Flag indicating if the allocation of this struct is devres-
>>>>>>> managed */
>>>>>>> bool devm_allocated;
>>>>>>> --
>>>>>>> 2.17.1
View attachment "dmesg_patch_chain_with_changes.log" of type "text/plain" (142879 bytes)
View attachment "gitdiff_patch_chain_with_changes.diff" of type "text/plain" (1314 bytes)
View attachment "dmesg_master_kernel_6.3.0.log" of type "text/plain" (110278 bytes)
Powered by blists - more mailing lists