Hello Stefan, > -----Original Message----- > From: Stefan Binding <sbinding@xxxxxxxxxxxxxxxxxxxxx> > Sent: Friday, April 28, 2023 7:38 PM > To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@xxxxxxx>; > broonie@xxxxxxxxxx; tudor.ambarus@xxxxxxxxxx; pratyush@xxxxxxxxxx; > michael@xxxxxxxx; miquel.raynal@xxxxxxxxxxx; richard@xxxxxx; > vigneshr@xxxxxx > Cc: git (AMD-Xilinx) <git@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; linux- > kernel@xxxxxxxxxxxxxxx; linux-mtd@xxxxxxxxxxxxxxxxxxx; > nicolas.ferre@xxxxxxxxxxxxx; alexandre.belloni@xxxxxxxxxxx; > claudiu.beznea@xxxxxxxxxxxxx; Simek, Michal <michal.simek@xxxxxxx>; > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; amitrkcian2002@xxxxxxxxx; > patches@xxxxxxxxxxxxxxxxxxxxx; vitalyr@xxxxxxxxxxxxxxxxxxxxx > 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@xxxxxxxxxxxxxxxxxxxxx> > >> Sent: Tuesday, April 25, 2023 5:50 PM > >> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@xxxxxxx>; > >> broonie@xxxxxxxxxx; tudor.ambarus@xxxxxxxxxx; pratyush@xxxxxxxxxx; > >> michael@xxxxxxxx; miquel.raynal@xxxxxxxxxxx; richard@xxxxxx; > >> vigneshr@xxxxxx > >> Cc: git (AMD-Xilinx) <git@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; linux- > >> kernel@xxxxxxxxxxxxxxx; linux-mtd@xxxxxxxxxxxxxxxxxxx; > >> nicolas.ferre@xxxxxxxxxxxxx; alexandre.belloni@xxxxxxxxxxx; > >> claudiu.beznea@xxxxxxxxxxxxx; Simek, Michal > <michal.simek@xxxxxxx>; > >> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; amitrkcian2002@xxxxxxxxx; > >> patches@xxxxxxxxxxxxxxxxxxxxx; vitalyr@xxxxxxxxxxxxxxxxxxxxx > >> 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@xxxxxxxxxxxxxxxxxxxxx> > >>>> Sent: Wednesday, April 12, 2023 8:33 PM > >>>> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@xxxxxxx>; > >>>> broonie@xxxxxxxxxx; tudor.ambarus@xxxxxxxxxx; pratyush@xxxxxxxxxx; > >>>> michael@xxxxxxxx; miquel.raynal@xxxxxxxxxxx; richard@xxxxxx; > >>>> vigneshr@xxxxxx > >>>> Cc: git (AMD-Xilinx) <git@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; > >>>> linux- kernel@xxxxxxxxxxxxxxx; linux-mtd@xxxxxxxxxxxxxxxxxxx; > >>>> nicolas.ferre@xxxxxxxxxxxxx; alexandre.belloni@xxxxxxxxxxx; > >>>> claudiu.beznea@xxxxxxxxxxxxx; Simek, Michal > >> <michal.simek@xxxxxxx>; > >>>> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; amitrkcian2002@xxxxxxxxx; > >>>> patches@xxxxxxxxxxxxxxxxxxxxx; vitalyr@xxxxxxxxxxxxxxxxxxxxx > >>>> 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@xxxxxxxxxxxxxxxxxxxxx> > >>>>>> Sent: Thursday, April 6, 2023 7:14 PM > >>>>>> To: Mahapatra, Amit Kumar <amit.kumar-mahapatra@xxxxxxx>; > >>>>>> broonie@xxxxxxxxxx; tudor.ambarus@xxxxxxxxxx; > >>>>>> pratyush@xxxxxxxxxx; michael@xxxxxxxx; > miquel.raynal@xxxxxxxxxxx; > >>>>>> richard@xxxxxx; vigneshr@xxxxxx > >>>>>> Cc: git (AMD-Xilinx) <git@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; > >>>>>> linux- kernel@xxxxxxxxxxxxxxx; linux-mtd@xxxxxxxxxxxxxxxxxxx; > >>>>>> nicolas.ferre@xxxxxxxxxxxxx; alexandre.belloni@xxxxxxxxxxx; > >>>>>> claudiu.beznea@xxxxxxxxxxxxx; Simek, Michal > >>>> <michal.simek@xxxxxxx>; > >>>>>> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; amitrkcian2002@xxxxxxxxx; > >>>>>> patches@xxxxxxxxxxxxxxxxxxxxx; vitalyr@xxxxxxxxxxxxxxxxxxxxx > >>>>>> 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@xxxxxxx> > >>>>>>> Sent: Thursday, April 6, 2023 7:54 AM > >>>>>>> To: broonie@xxxxxxxxxx; tudor.ambarus@xxxxxxxxxx; > >>>>>>> pratyush@xxxxxxxxxx; michael@xxxxxxxx; > >>>>>>> miquel.raynal@xxxxxxxxxxx; richard@xxxxxx; vigneshr@xxxxxx > >>>>>>> Cc: git@xxxxxxx; sbinding@xxxxxxxxxxxxxxxxxxxxx; linux- > >>>>>>> spi@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; linux- > >>>>>>> mtd@xxxxxxxxxxxxxxxxxxx; nicolas.ferre@xxxxxxxxxxxxx; > >>>>>>> alexandre.belloni@xxxxxxxxxxx; claudiu.beznea@xxxxxxxxxxxxx; > >>>>>>> michal.simek@xxxxxxx; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; > >>>>>>> amitrkcian2002@xxxxxxxxx; Amit Kumar Mahapatra <amit.kumar- > >>>>>>> mahapatra@xxxxxxx> > >>>>>>> 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/303feb3cc06ac0665d0ee9c14149 > 4 > > 1200e60e8a3 patch but it is failing with the current patch series ? > > I retested with the latest master kernel > https://github.com/torvalds/linux/commit/33afd4b76393627477e878b3b195 > d606e585d816 > 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. Thank you for the confirmation. > > > > > 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 a lot for the dmesg log. Here the __ffs() is creating the issue. __ffs() behavior is undefined if no set bits exist in spi->cs_index_mask , as a result random value (i.e, 64) is assigned to cs_num. I think this could be fixed by replacing __ffs() with ffs() calls. To confirm the same could you please apply the attached patch on top of this patch series and re-test. If it works fine, then for sanity kindly rerun by removing the printk lines. Thanks, Amit > > > > > Thanks, > > Amit > >>>> Thanks, > >>>> > >>>> Stefan > >>>> > >>>>>> Thanks, > >>>>>> Stefan Binding > >>>>>> > >>>>>>> Signed-off-by: Amit Kumar Mahapatra <amit.kumar- > >>>>>> mahapatra@xxxxxxx> > >>>>>>> --- > >>>>>>> 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
Attachment:
0001-spi-cs-gpio-call-trace-fix.patch
Description: 0001-spi-cs-gpio-call-trace-fix.patch