aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2012-11-30 06:37:53 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-30 06:37:53 -0500
commit64bee4d28c9e2296f4f12a6c4cc40d085c2c9534 (patch)
treebc1125d24e6fdc4934dba6a6c78c2de2e0d46b61 /drivers
parente29482e8487954c87dc7b4fdbc53574bf1d4cce2 (diff)
spi / ACPI: add ACPI enumeration support
ACPI 5 introduced SPISerialBus resource that allows us to enumerate and configure the SPI slave devices behind the SPI controller. This patch adds support for this to the SPI core. In addition we bind ACPI nodes to SPI devices. This makes it possible for the slave drivers to get the ACPI handle for further configuration. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 84c2861d6f4d..1ab05234729f 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -35,6 +35,8 @@
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/delay.h> 36#include <linux/delay.h>
37#include <linux/kthread.h> 37#include <linux/kthread.h>
38#include <linux/ioport.h>
39#include <linux/acpi.h>
38 40
39static void spidev_release(struct device *dev) 41static void spidev_release(struct device *dev)
40{ 42{
@@ -93,6 +95,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
93 if (of_driver_match_device(dev, drv)) 95 if (of_driver_match_device(dev, drv))
94 return 1; 96 return 1;
95 97
98 /* Then try ACPI */
99 if (acpi_driver_match_device(dev, drv))
100 return 1;
101
96 if (sdrv->id_table) 102 if (sdrv->id_table)
97 return !!spi_match_id(sdrv->id_table, spi); 103 return !!spi_match_id(sdrv->id_table, spi);
98 104
@@ -888,6 +894,100 @@ static void of_register_spi_devices(struct spi_master *master)
888static void of_register_spi_devices(struct spi_master *master) { } 894static void of_register_spi_devices(struct spi_master *master) { }
889#endif 895#endif
890 896
897#ifdef CONFIG_ACPI
898static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
899{
900 struct spi_device *spi = data;
901
902 if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
903 struct acpi_resource_spi_serialbus *sb;
904
905 sb = &ares->data.spi_serial_bus;
906 if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
907 spi->chip_select = sb->device_selection;
908 spi->max_speed_hz = sb->connection_speed;
909
910 if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
911 spi->mode |= SPI_CPHA;
912 if (sb->clock_polarity == ACPI_SPI_START_HIGH)
913 spi->mode |= SPI_CPOL;
914 if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH)
915 spi->mode |= SPI_CS_HIGH;
916 }
917 } else if (spi->irq < 0) {
918 struct resource r;
919
920 if (acpi_dev_resource_interrupt(ares, 0, &r))
921 spi->irq = r.start;
922 }
923
924 /* Always tell the ACPI core to skip this resource */
925 return 1;
926}
927
928static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
929 void *data, void **return_value)
930{
931 struct spi_master *master = data;
932 struct list_head resource_list;
933 struct acpi_device *adev;
934 struct spi_device *spi;
935 int ret;
936
937 if (acpi_bus_get_device(handle, &adev))
938 return AE_OK;
939 if (acpi_bus_get_status(adev) || !adev->status.present)
940 return AE_OK;
941
942 spi = spi_alloc_device(master);
943 if (!spi) {
944 dev_err(&master->dev, "failed to allocate SPI device for %s\n",
945 dev_name(&adev->dev));
946 return AE_NO_MEMORY;
947 }
948
949 ACPI_HANDLE_SET(&spi->dev, handle);
950 spi->irq = -1;
951
952 INIT_LIST_HEAD(&resource_list);
953 ret = acpi_dev_get_resources(adev, &resource_list,
954 acpi_spi_add_resource, spi);
955 acpi_dev_free_resource_list(&resource_list);
956
957 if (ret < 0 || !spi->max_speed_hz) {
958 spi_dev_put(spi);
959 return AE_OK;
960 }
961
962 strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
963 if (spi_add_device(spi)) {
964 dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
965 dev_name(&adev->dev));
966 spi_dev_put(spi);
967 }
968
969 return AE_OK;
970}
971
972static void acpi_register_spi_devices(struct spi_master *master)
973{
974 acpi_status status;
975 acpi_handle handle;
976
977 handle = ACPI_HANDLE(&master->dev);
978 if (!handle)
979 return;
980
981 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
982 acpi_spi_add_device, NULL,
983 master, NULL);
984 if (ACPI_FAILURE(status))
985 dev_warn(&master->dev, "failed to enumerate SPI slaves\n");
986}
987#else
988static inline void acpi_register_spi_devices(struct spi_master *master) {}
989#endif /* CONFIG_ACPI */
990
891static void spi_master_release(struct device *dev) 991static void spi_master_release(struct device *dev)
892{ 992{
893 struct spi_master *master; 993 struct spi_master *master;
@@ -1023,8 +1123,9 @@ int spi_register_master(struct spi_master *master)
1023 spi_match_master_to_boardinfo(master, &bi->board_info); 1123 spi_match_master_to_boardinfo(master, &bi->board_info);
1024 mutex_unlock(&board_lock); 1124 mutex_unlock(&board_lock);
1025 1125
1026 /* Register devices from the device tree */ 1126 /* Register devices from the device tree and ACPI */
1027 of_register_spi_devices(master); 1127 of_register_spi_devices(master);
1128 acpi_register_spi_devices(master);
1028done: 1129done:
1029 return status; 1130 return status;
1030} 1131}