aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-30 06:38:51 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-30 06:38:51 -0500
commitd9ba1025a46d368bc00a2981cb2b2a918e9209b7 (patch)
treec0451a56f972b01e16c776b572a23b4371ce5c5d
parentad063fbbdda6247c4653b708bf011986e8ab7ec8 (diff)
parent64bee4d28c9e2296f4f12a6c4cc40d085c2c9534 (diff)
Merge branch 'acpi-enumeration'
* acpi-enumeration: spi / ACPI: add ACPI enumeration support gpio / ACPI: add ACPI support
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpiolib-acpi.c54
-rw-r--r--drivers/spi/spi.c103
-rw-r--r--include/linux/acpi_gpio.h19
5 files changed, 180 insertions, 1 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 47150f5ded0..f16557690cf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -49,6 +49,10 @@ config OF_GPIO
49 def_bool y 49 def_bool y
50 depends on OF 50 depends on OF
51 51
52config GPIO_ACPI
53 def_bool y
54 depends on ACPI
55
52config DEBUG_GPIO 56config DEBUG_GPIO
53 bool "Debug GPIO calls" 57 bool "Debug GPIO calls"
54 depends on DEBUG_KERNEL 58 depends on DEBUG_KERNEL
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9aeed670732..420dbaca05f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
4 4
5obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o 5obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
6obj-$(CONFIG_OF_GPIO) += gpiolib-of.o 6obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
7obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
7 8
8# Device drivers. Generally keep list sorted alphabetically 9# Device drivers. Generally keep list sorted alphabetically
9obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o 10obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
new file mode 100644
index 00000000000..cbad6e908d3
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -0,0 +1,54 @@
1/*
2 * ACPI helpers for GPIO API
3 *
4 * Copyright (C) 2012, Intel Corporation
5 * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
6 * Mika Westerberg <mika.westerberg@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/errno.h>
14#include <linux/gpio.h>
15#include <linux/export.h>
16#include <linux/acpi_gpio.h>
17#include <linux/acpi.h>
18
19static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
20{
21 if (!gc->dev)
22 return false;
23
24 return ACPI_HANDLE(gc->dev) == data;
25}
26
27/**
28 * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
29 * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
30 * @pin: ACPI GPIO pin number (0-based, controller-relative)
31 *
32 * Returns GPIO number to use with Linux generic GPIO API, or errno error value
33 */
34
35int acpi_get_gpio(char *path, int pin)
36{
37 struct gpio_chip *chip;
38 acpi_handle handle;
39 acpi_status status;
40
41 status = acpi_get_handle(NULL, path, &handle);
42 if (ACPI_FAILURE(status))
43 return -ENODEV;
44
45 chip = gpiochip_find(handle, acpi_gpiochip_find);
46 if (!chip)
47 return -ENODEV;
48
49 if (!gpio_is_valid(chip->base + pin))
50 return -EINVAL;
51
52 return chip->base + pin;
53}
54EXPORT_SYMBOL_GPL(acpi_get_gpio);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 84c2861d6f4..1ab05234729 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}
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
new file mode 100644
index 00000000000..91615a389b6
--- /dev/null
+++ b/include/linux/acpi_gpio.h
@@ -0,0 +1,19 @@
1#ifndef _LINUX_ACPI_GPIO_H_
2#define _LINUX_ACPI_GPIO_H_
3
4#include <linux/errno.h>
5
6#ifdef CONFIG_GPIO_ACPI
7
8int acpi_get_gpio(char *path, int pin);
9
10#else /* CONFIG_GPIO_ACPI */
11
12static inline int acpi_get_gpio(char *path, int pin)
13{
14 return -ENODEV;
15}
16
17#endif /* CONFIG_GPIO_ACPI */
18
19#endif /* _LINUX_ACPI_GPIO_H_ */