summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/x86-android-tablets/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/x86-android-tablets/core.c')
-rw-r--r--drivers/platform/x86/x86-android-tablets/core.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c
index b55957bde034..f8221a15575b 100644
--- a/drivers/platform/x86/x86-android-tablets/core.c
+++ b/drivers/platform/x86/x86-android-tablets/core.c
@@ -141,9 +141,11 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
}
static int i2c_client_count;
+static int spi_dev_count;
static int pdev_count;
static int serdev_count;
static struct i2c_client **i2c_clients;
+static struct spi_device **spi_devs;
static struct platform_device **pdevs;
static struct serdev_device **serdevs;
static struct gpio_keys_button *buttons;
@@ -185,6 +187,46 @@ static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info
return 0;
}
+static __init int x86_instantiate_spi_dev(const struct x86_dev_info *dev_info, int idx)
+{
+ const struct x86_spi_dev_info *spi_dev_info = &dev_info->spi_dev_info[idx];
+ struct spi_board_info board_info = spi_dev_info->board_info;
+ struct spi_controller *controller;
+ struct acpi_device *adev;
+ acpi_handle handle;
+ acpi_status status;
+
+ board_info.irq = x86_acpi_irq_helper_get(&spi_dev_info->irq_data);
+ if (board_info.irq < 0)
+ return board_info.irq;
+
+ status = acpi_get_handle(NULL, spi_dev_info->ctrl_path, &handle);
+ if (ACPI_FAILURE(status)) {
+ pr_err("Error could not get %s handle\n", spi_dev_info->ctrl_path);
+ return -ENODEV;
+ }
+
+ adev = acpi_fetch_acpi_dev(handle);
+ if (!adev) {
+ pr_err("Error could not get adev for %s\n", spi_dev_info->ctrl_path);
+ return -ENODEV;
+ }
+
+ controller = acpi_spi_find_controller_by_adev(adev);
+ if (!controller) {
+ pr_err("Error could not get SPI controller for %s\n", spi_dev_info->ctrl_path);
+ return -ENODEV;
+ }
+
+ spi_devs[idx] = spi_new_device(controller, &board_info);
+ put_device(&controller->dev);
+ if (!spi_devs[idx])
+ return dev_err_probe(&controller->dev, -ENOMEM,
+ "creating SPI-device %d\n", idx);
+
+ return 0;
+}
+
static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
{
struct acpi_device *ctrl_adev, *serdev_adev;
@@ -263,6 +305,11 @@ static void x86_android_tablet_remove(struct platform_device *pdev)
kfree(pdevs);
kfree(buttons);
+ for (i = 0; i < spi_dev_count; i++)
+ spi_unregister_device(spi_devs[i]);
+
+ kfree(spi_devs);
+
for (i = 0; i < i2c_client_count; i++)
i2c_unregister_device(i2c_clients[i]);
@@ -333,6 +380,21 @@ static __init int x86_android_tablet_probe(struct platform_device *pdev)
}
}
+ spi_devs = kcalloc(dev_info->spi_dev_count, sizeof(*spi_devs), GFP_KERNEL);
+ if (!spi_devs) {
+ x86_android_tablet_remove(pdev);
+ return -ENOMEM;
+ }
+
+ spi_dev_count = dev_info->spi_dev_count;
+ for (i = 0; i < spi_dev_count; i++) {
+ ret = x86_instantiate_spi_dev(dev_info, i);
+ if (ret < 0) {
+ x86_android_tablet_remove(pdev);
+ return ret;
+ }
+ }
+
/* + 1 to make space for (optional) gpio_keys_button pdev */
pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL);
if (!pdevs) {