Skip to content

Commit a0a9071

Browse files
westeribroonie
authored andcommitted
spi: Let drivers translate ACPI DeviceSelection to suitable Linux chip select
In Windows it is up to the SPI host controller driver to handle the ACPI DeviceSelection as it likes. The SPI core does not take any part in it. This is different in Linux because we always expect to have chip select in range of 0 .. master->num_chipselect - 1. In order to support this in Linux we need a way to allow the driver to translate between ACPI DeviceSelection field and Linux chip select number so provide a new optional hook ->fw_translate_cs() that can be used by a driver to handle translation and call this hook if set during SPI slave ACPI enumeration. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 92e963f commit a0a9071

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

drivers/spi/spi.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1581,13 +1581,30 @@ static void of_register_spi_devices(struct spi_master *master) { }
15811581
static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
15821582
{
15831583
struct spi_device *spi = data;
1584+
struct spi_master *master = spi->master;
15841585

15851586
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
15861587
struct acpi_resource_spi_serialbus *sb;
15871588

15881589
sb = &ares->data.spi_serial_bus;
15891590
if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
1590-
spi->chip_select = sb->device_selection;
1591+
/*
1592+
* ACPI DeviceSelection numbering is handled by the
1593+
* host controller driver in Windows and can vary
1594+
* from driver to driver. In Linux we always expect
1595+
* 0 .. max - 1 so we need to ask the driver to
1596+
* translate between the two schemes.
1597+
*/
1598+
if (master->fw_translate_cs) {
1599+
int cs = master->fw_translate_cs(master,
1600+
sb->device_selection);
1601+
if (cs < 0)
1602+
return cs;
1603+
spi->chip_select = cs;
1604+
} else {
1605+
spi->chip_select = sb->device_selection;
1606+
}
1607+
15911608
spi->max_speed_hz = sb->connection_speed;
15921609

15931610
if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)

include/linux/spi/spi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
369369
* @dma_rx: DMA receive channel
370370
* @dummy_rx: dummy receive buffer for full-duplex devices
371371
* @dummy_tx: dummy transmit buffer for full-duplex devices
372+
* @fw_translate_cs: If the boot firmware uses different numbering scheme
373+
* what Linux expects, this optional hook can be used to translate
374+
* between the two.
372375
*
373376
* Each SPI master controller can communicate with one or more @spi_device
374377
* children. These make a small bus, sharing MOSI, MISO and SCK signals
@@ -537,6 +540,8 @@ struct spi_master {
537540
/* dummy data for full duplex devices */
538541
void *dummy_rx;
539542
void *dummy_tx;
543+
544+
int (*fw_translate_cs)(struct spi_master *master, unsigned cs);
540545
};
541546

542547
static inline void *spi_master_get_devdata(struct spi_master *master)

0 commit comments

Comments
 (0)