Skip to content

Instantly share code, notes, and snippets.

@arno01
Last active January 28, 2020 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arno01/ba69b5956f6bb996fd7232bbe009f2de to your computer and use it in GitHub Desktop.
Save arno01/ba69b5956f6bb996fd7232bbe009f2de to your computer and use it in GitHub Desktop.
  • roadrunner2/macbook12-spi-driver is at commit 3b58c7b3b2e814abd5347372d842328c88801f76 (HEAD -> touchbar-driver-hid-driver, origin/touchbar-driver-hid-driver, origin/HEAD)
  • torvalds/linux is at commit b0be0eff1a5ab77d588b76bd8b1c92d5d17b3f73 (HEAD -> master, origin/master, origin/HEAD)
[user@personal linux]$ diff -Nur ~/git/macbook12-spi-driver/applespi.c ~/git/linux/drivers/input/keyboard/applespi.c | xclip -selection clipboard
--- /home/user/git/macbook12-spi-driver/applespi.c	2020-01-28 13:15:41.561000000 +0100
+++ /home/user/git/linux/drivers/input/keyboard/applespi.c	2020-01-28 13:07:22.311000000 +0100
@@ -48,15 +48,12 @@
 #include <linux/efi.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
-#include <linux/jiffies.h>
-#include <linux/ktime.h>
 #include <linux/leds.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/spi/spi.h>
-#include <linux/version.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 
 #include <asm/barrier.h>
 #include <asm/unaligned.h>
@@ -65,14 +62,6 @@
 #include "applespi.h"
 #include "applespi_trace.h"
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
-#define PRE_SPI_PROPERTIES
-#endif
-
-#ifdef PRE_SPI_PROPERTIES
-#include <linux/notifier.h>
-#endif
-
 #define APPLESPI_PACKET_SIZE	256
 #define APPLESPI_STATUS_SIZE	4
 
@@ -355,13 +344,6 @@
 };
 
 struct spi_settings {
-#ifdef PRE_SPI_PROPERTIES
-	u64	spi_sclk_period;	/* period in ns */
-	u64	spi_word_size;		/* in number of bits */
-	u64	spi_bit_order;		/* 1 = MSB_FIRST, 0 = LSB_FIRST */
-	u64	spi_spo;		/* clock polarity: 0 = low, 1 = high */
-	u64	spi_sph;		/* clock phase: 0 = first, 1 = second */
-#endif
 	u64	spi_cs_delay;		/* cs-to-clk delay in us */
 	u64	reset_a2r_usec;		/* active-to-receive delay? */
 	u64	reset_rec_usec;		/* ? (cur val: 10) */
@@ -418,7 +400,7 @@
 	unsigned int			cmd_msg_cntr;
 	/* lock to protect the above parameters and flags below */
 	spinlock_t			cmd_msg_lock;
-	ktime_t				cmd_msg_queued;
+	bool				cmd_msg_queued;
 	enum applespi_evt_type		cmd_evt_type;
 
 	struct led_classdev		backlight_info;
@@ -429,13 +411,7 @@
 	bool				read_active;
 	bool				write_active;
 
-	struct applespi_complete_info {
-		void				(*complete)(void *context);
-		struct applespi_data		*applespi;
-	}				spi_complete[2];
-	bool				cancel_spi;
-
-	wait_queue_head_t		tp_info_complete;
+	struct work_struct		work;
 	struct touchpad_info_protocol	rcvd_tp_info;
 
 	struct dentry			*debugfs_root;
@@ -617,61 +593,13 @@
 	spi_message_add_tail(st_t, msg);
 }
 
-static bool applespi_async_outstanding(struct applespi_data *applespi)
-{
-	return applespi->spi_complete[0].complete ||
-	       applespi->spi_complete[1].complete;
-}
-
-static void applespi_async_complete(void *context)
-{
-	struct applespi_complete_info *info = context;
-	struct applespi_data *applespi = info->applespi;
-	unsigned long flags;
-
-	info->complete(applespi);
-
-	spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
-
-	info->complete = NULL;
-
-	if (applespi->cancel_spi && !applespi_async_outstanding(applespi))
-		wake_up_all(&applespi->drain_complete);
-
-	spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
-}
-
 static int applespi_async(struct applespi_data *applespi,
 			  struct spi_message *message, void (*complete)(void *))
 {
-	struct applespi_complete_info *info;
-	int sts;
-
-	if (applespi->cancel_spi) {
-		if (!applespi_async_outstanding(applespi))
-			wake_up_all(&applespi->drain_complete);
-		return -ESHUTDOWN;
-	}
-
-	/*
-	 * There can only be at most 2 spi requests in flight, one for "reads"
-	 * and one for "writes".
-	 */
-	if (!applespi->spi_complete[0].complete)
-		info = &applespi->spi_complete[0];
-	else
-		info = &applespi->spi_complete[1];
-	info->complete = complete;
-	info->applespi = applespi;
-
-	message->complete = applespi_async_complete;
-	message->context = info;
+	message->complete = complete;
+	message->context = applespi;
 
-	sts = spi_async(applespi->spi, message);
-	if (sts)
-		info->complete = NULL;
-
-	return sts;
+	return spi_async(applespi->spi, message);
 }
 
 static inline bool applespi_check_write_status(struct applespi_data *applespi,
@@ -694,114 +622,6 @@
 	return true;
 }
 
-#ifdef PRE_SPI_PROPERTIES
-
-struct appleacpi_spi_registration_info {
-	struct class_interface	cif;
-	struct acpi_device	*adev;
-	struct spi_device	*spi;
-	struct spi_master	*spi_master;
-	struct delayed_work	work;
-	struct notifier_block	slave_notifier;
-};
-
-struct applespi_acpi_map_entry {
-	char *name;
-	size_t field_offset;
-};
-
-static const struct applespi_acpi_map_entry applespi_spi_settings_map[] = {
-	{ "spiSclkPeriod", offsetof(struct spi_settings, spi_sclk_period) },
-	{ "spiWordSize",   offsetof(struct spi_settings, spi_word_size) },
-	{ "spiBitOrder",   offsetof(struct spi_settings, spi_bit_order) },
-	{ "spiSPO",        offsetof(struct spi_settings, spi_spo) },
-	{ "spiSPH",        offsetof(struct spi_settings, spi_sph) },
-	{ "spiCSDelay",    offsetof(struct spi_settings, spi_cs_delay) },
-	{ "resetA2RUsec",  offsetof(struct spi_settings, reset_a2r_usec) },
-	{ "resetRecUsec",  offsetof(struct spi_settings, reset_rec_usec) },
-};
-
-static u8 *acpi_dsm_uuid = "a0b5b7c6-1318-441c-b0c9-fe695eaf949b";
-
-static int applespi_find_settings_field(const char *name)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(applespi_spi_settings_map); i++) {
-		if (strcmp(applespi_spi_settings_map[i].name, name) == 0)
-			return applespi_spi_settings_map[i].field_offset;
-	}
-
-	return -1;
-}
-
-static int applespi_get_spi_settings(acpi_handle handle,
-				     struct spi_settings *settings)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
-	guid_t guid, *uuid = &guid;
-#else
-	u8 uuid[16];
-#endif
-	union acpi_object *spi_info;
-	union acpi_object name;
-	union acpi_object value;
-	int i;
-	int field_off;
-	u64 *field;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
-	guid_parse(acpi_dsm_uuid, uuid);
-#else
-	acpi_str_to_uuid(acpi_dsm_uuid, uuid);
-#endif
-
-	spi_info = acpi_evaluate_dsm(handle, uuid, 1, 1, NULL);
-	if (!spi_info) {
-		pr_err("Failed to get SPI info from _DSM method\n");
-		return -ENODEV;
-	}
-	if (spi_info->type != ACPI_TYPE_PACKAGE) {
-		pr_err("Unexpected data returned from SPI _DSM method: type=%d\n",
-		       spi_info->type);
-		ACPI_FREE(spi_info);
-		return -ENODEV;
-	}
-
-	/*
-	 * The data is stored in pairs of items, first a string containing
-	 * the name of the item, followed by an 8-byte buffer containing the
-	 * value in little-endian.
-	 */
-	for (i = 0; i < spi_info->package.count - 1; i += 2) {
-		name = spi_info->package.elements[i];
-		value = spi_info->package.elements[i + 1];
-
-		if (!(name.type == ACPI_TYPE_STRING &&
-		      value.type == ACPI_TYPE_BUFFER &&
-		      value.buffer.length == 8)) {
-			pr_warn("Unexpected data returned from SPI _DSM method: name.type=%d, value.type=%d\n",
-				name.type, value.type);
-			continue;
-		}
-
-		field_off = applespi_find_settings_field(name.string.pointer);
-		if (field_off < 0) {
-			pr_debug("Skipping unknown SPI setting '%s'\n",
-				 name.string.pointer);
-			continue;
-		}
-
-		field = (u64 *)((char *)settings + field_off);
-		*field = le64_to_cpu(*((__le64 *)value.buffer.pointer));
-	}
-	ACPI_FREE(spi_info);
-
-	return 0;
-}
-
-#else
-
 static int applespi_get_spi_settings(struct applespi_data *applespi)
 {
 	struct acpi_device *adev = ACPI_COMPANION(&applespi->spi->dev);
@@ -834,27 +654,16 @@
 	return 0;
 }
 
-#endif
-
-static int applespi_setup_spi(struct applespi_data *applespi
-#ifdef PRE_SPI_PROPERTIES
-			      , acpi_handle spi_handle
-#endif
-			      )
+static int applespi_setup_spi(struct applespi_data *applespi)
 {
 	int sts;
 
-#ifdef PRE_SPI_PROPERTIES
-	sts = applespi_get_spi_settings(spi_handle, &applespi->spi_settings);
-#else
 	sts = applespi_get_spi_settings(applespi);
-#endif
 	if (sts)
 		return sts;
 
 	spin_lock_init(&applespi->cmd_msg_lock);
 	init_waitqueue_head(&applespi->drain_complete);
-	init_waitqueue_head(&applespi->tp_info_complete);
 
 	return 0;
 }
@@ -907,7 +716,7 @@
 		wake_up_all(&applespi->drain_complete);
 
 	if (is_write_msg) {
-		applespi->cmd_msg_queued = 0;
+		applespi->cmd_msg_queued = false;
 		applespi_send_cmd_msg(applespi);
 	}
 
@@ -949,16 +758,8 @@
 		return 0;
 
 	/* check whether send is in progress */
-	if (applespi->cmd_msg_queued) {
-		if (ktime_ms_delta(ktime_get(), applespi->cmd_msg_queued) < 1000)
-			return 0;
-
-		dev_warn(&applespi->spi->dev, "Command %d timed out\n",
-			 applespi->cmd_evt_type);
-
-		applespi->cmd_msg_queued = 0;
-		applespi->write_active = false;
-	}
+	if (applespi->cmd_msg_queued)
+		return 0;
 
 	/* set up packet */
 	memset(packet, 0, APPLESPI_PACKET_SIZE);
@@ -1055,7 +856,7 @@
 		return sts;
 	}
 
-	applespi->cmd_msg_queued = ktime_get();
+	applespi->cmd_msg_queued = true;
 	applespi->write_active = true;
 
 	return 0;
@@ -1214,7 +1015,7 @@
 	const struct applespi_tp_info *tp_info = &applespi->tp_info;
 	int i, n;
 
-	/* touchpad_input_dev is set async in probe */
+	/* touchpad_input_dev is set async in worker */
 	input = smp_load_acquire(&applespi->touchpad_input_dev);
 	if (!input)
 		return;	/* touchpad isn't initialized yet */
@@ -1468,15 +1269,15 @@
 
 	/* finger touch area */
 	input_set_abs_params(touchpad_input_dev, ABS_MT_TOUCH_MAJOR,
-			     0, 2048, 0, 0);
+			     0, 5000, 0, 0);
 	input_set_abs_params(touchpad_input_dev, ABS_MT_TOUCH_MINOR,
-			     0, 2048, 0, 0);
+			     0, 5000, 0, 0);
 
 	/* finger approach area */
 	input_set_abs_params(touchpad_input_dev, ABS_MT_WIDTH_MAJOR,
-			     0, 2048, 0, 0);
+			     0, 5000, 0, 0);
 	input_set_abs_params(touchpad_input_dev, ABS_MT_WIDTH_MINOR,
-			     0, 2048, 0, 0);
+			     0, 5000, 0, 0);
 
 	/* finger orientation */
 	input_set_abs_params(touchpad_input_dev, ABS_MT_ORIENTATION,
@@ -1518,14 +1319,26 @@
 	return 0;
 }
 
+static void applespi_worker(struct work_struct *work)
+{
+	struct applespi_data *applespi =
+		container_of(work, struct applespi_data, work);
+
+	applespi_register_touchpad_device(applespi, &applespi->rcvd_tp_info);
+}
+
 static void applespi_handle_cmd_response(struct applespi_data *applespi,
 					 struct spi_packet *packet,
 					 struct message *message)
 {
 	if (packet->device == PACKET_DEV_INFO &&
 	    le16_to_cpu(message->type) == 0x1020) {
+		/*
+		 * We're not allowed to sleep here, but registering an input
+		 * device can sleep.
+		 */
 		applespi->rcvd_tp_info = message->tp_info;
-		wake_up_all(&applespi->tp_info_complete);
+		schedule_work(&applespi->work);
 		return;
 	}
 
@@ -1813,7 +1626,6 @@
 	struct applespi_data *applespi;
 	acpi_handle spi_handle = ACPI_HANDLE(&spi->dev);
 	acpi_status acpi_sts;
-	unsigned long flags;
 	int sts, i;
 	unsigned long long gpe, usb_status;
 
@@ -1832,6 +1644,8 @@
 
 	applespi->spi = spi;
 
+	INIT_WORK(&applespi->work, applespi_worker);
+
 	/* store the driver data */
 	spi_set_drvdata(spi, applespi);
 
@@ -1872,11 +1686,7 @@
 	}
 
 	/* switch on the SPI interface */
-	sts = applespi_setup_spi(applespi
-#ifdef PRE_SPI_PROPERTIES
-				 , spi_handle
-#endif
-				 );
+	sts = applespi_setup_spi(applespi);
 	if (sts)
 		return sts;
 
@@ -1963,22 +1773,6 @@
 	/* trigger touchpad setup */
 	applespi_init(applespi, false);
 
-	/* set up the touchpad as a separate input device */
-	sts = wait_event_timeout(applespi->tp_info_complete,
-				 applespi->rcvd_tp_info.model_no,
-				 msecs_to_jiffies(3000));
-	if (!sts) {
-		dev_err(&applespi->spi->dev,
-			"Timed out waiting for device info\n");
-		sts = -ETIMEDOUT;
-		goto cancel_spi;
-	}
-
-	sts = applespi_register_touchpad_device(applespi,
-						&applespi->rcvd_tp_info);
-	if (sts)
-		goto cancel_spi;
-
 	/*
 	 * By default this device is not enabled for wakeup; but USB keyboards
 	 * generally are, so the expectation is that by default the keyboard
@@ -2011,19 +1805,6 @@
 			    &applespi_tp_dim_fops);
 
 	return 0;
-
-cancel_spi:
-	acpi_disable_gpe(NULL, applespi->gpe);
-	acpi_remove_gpe_handler(NULL, applespi->gpe, applespi_notify);
-
-	spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
-	applespi->cancel_spi = true;
-	wait_event_lock_irq(applespi->drain_complete,
-			    !applespi_async_outstanding(applespi),
-			    applespi->cmd_msg_lock);
-	spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
-
-	return sts;
 }
 
 static void applespi_drain_writes(struct applespi_data *applespi)
@@ -2033,10 +1814,8 @@
 	spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
 
 	applespi->drain = true;
-	wait_event_lock_irq_timeout(applespi->drain_complete,
-				    !applespi->write_active,
-				    applespi->cmd_msg_lock,
-				    msecs_to_jiffies(3000));
+	wait_event_lock_irq(applespi->drain_complete, !applespi->write_active,
+			    applespi->cmd_msg_lock);
 
 	spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);
 }
@@ -2047,10 +1826,8 @@
 
 	spin_lock_irqsave(&applespi->cmd_msg_lock, flags);
 
-	wait_event_lock_irq_timeout(applespi->drain_complete,
-				    !applespi->read_active,
-				    applespi->cmd_msg_lock,
-				    msecs_to_jiffies(3000));
+	wait_event_lock_irq(applespi->drain_complete, !applespi->read_active,
+			    applespi->cmd_msg_lock);
 
 	applespi->suspended = true;
 
@@ -2131,7 +1908,7 @@
 	applespi->drain = false;
 	applespi->have_cl_led_on = false;
 	applespi->have_bl_level = 0;
-	applespi->cmd_msg_queued = 0;
+	applespi->cmd_msg_queued = false;
 	applespi->read_active = false;
 	applespi->write_active = false;
 
@@ -2177,406 +1954,8 @@
 	.shutdown	= applespi_shutdown,
 };
 
-#ifdef PRE_SPI_PROPERTIES
-
-#define SPI_DEV_CHIP_SEL	0	/* from DSDT UBUF */
-
-/*
- * All the following code is to deal with the fact that the _CRS method for
- * the SPI device in the DSDT returns an empty resource, and the real info is
- * available from the _DSM method. So we need to hook into the ACPI device
- * registration and create and register the SPI device ourselves.
- *
- * All of this can be removed and replaced with
- * module_spi_driver(applespi_driver)
- * when the core adds support for this sort of setup.
- */
-
-/*
- * Configure the spi device with the info from the _DSM method.
- */
-static int appleacpi_config_spi_dev(struct spi_device *spi,
-				    struct acpi_device *adev)
-{
-	struct spi_settings settings;
-	int ret;
-
-	ret = applespi_get_spi_settings(acpi_device_handle(adev), &settings);
-	if (ret)
-		return ret;
-
-	spi->max_speed_hz = 1000000000 / settings.spi_sclk_period;
-	spi->chip_select = SPI_DEV_CHIP_SEL;
-	spi->bits_per_word = settings.spi_word_size;
-
-	spi->mode =
-		(settings.spi_spo * SPI_CPOL) |
-		(settings.spi_sph * SPI_CPHA) |
-		(settings.spi_bit_order == 0 ? SPI_LSB_FIRST : 0);
-
-	spi->irq = -1;		/* uses GPE */
-
-	spi->dev.platform_data = NULL;
-	spi->controller_data = NULL;
-	spi->controller_state = NULL;
-
-	pr_debug("spi-config: max_speed_hz=%d, chip_select=%d, bits_per_word=%d, mode=%x, irq=%d\n",
-		 spi->max_speed_hz, spi->chip_select, spi->bits_per_word,
-		 spi->mode, spi->irq);
-
-	return 0;
-}
-
-static int appleacpi_is_device_registered(struct device *dev, void *data)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	struct spi_master *spi_master = data;
-
-	if (spi->master == spi_master && spi->chip_select == SPI_DEV_CHIP_SEL)
-		return -EBUSY;
-	return 0;
-}
-
-/*
- * Unregister all physical devices devices associated with the acpi device,
- * so that the new SPI device becomes the first physical device for it.
- * Otherwise we don't get properly registered as the driver for the spi
- * device.
- */
-static void appleacpi_unregister_phys_devs(struct acpi_device *adev)
-{
-	struct acpi_device_physical_node *entry;
-	struct device *dev;
-
-	while (true) {
-		mutex_lock(&adev->physical_node_lock);
-
-		if (list_empty(&adev->physical_node_list)) {
-			mutex_unlock(&adev->physical_node_lock);
-			break;
-		}
-
-		entry = list_first_entry(&adev->physical_node_list,
-					 struct acpi_device_physical_node,
-					 node);
-		dev = get_device(entry->dev);
-
-		mutex_unlock(&adev->physical_node_lock);
-
-		platform_device_unregister(to_platform_device(dev));
-		put_device(dev);
-	}
-}
-
-/*
- * Create the spi device for the keyboard and touchpad and register it with
- * the master spi device.
- */
-static int appleacpi_register_spi_device(struct spi_master *spi_master,
-					 struct acpi_device *adev)
-{
-	struct appleacpi_spi_registration_info *reg_info;
-	struct spi_device *spi;
-	int ret;
-
-	reg_info = acpi_driver_data(adev);
-
-	/* check if an spi device is already registered */
-	ret = bus_for_each_dev(&spi_bus_type, NULL, spi_master,
-			       appleacpi_is_device_registered);
-	if (ret == -EBUSY) {
-		pr_info("Spi Device already registered - patched DSDT?\n");
-		ret = 0;
-		goto release_master;
-	} else if (ret) {
-		pr_err("Error checking for spi device registered: %d\n", ret);
-		goto release_master;
-	}
-
-	/* none is; check if acpi device is there */
-	if (acpi_bus_get_status(adev) || !adev->status.present) {
-		pr_info("ACPI device is not present\n");
-		ret = 0;
-		goto release_master;
-	}
-
-	/*
-	 * acpi device is there.
-	 *
-	 * First unregister any physical devices already associated with this
-	 * acpi device (done by acpi_generic_device_attach).
-	 */
-	appleacpi_unregister_phys_devs(adev);
-
-	/* create spi device */
-	spi = spi_alloc_device(spi_master);
-	if (!spi) {
-		pr_err("Failed to allocate spi device\n");
-		ret = -ENOMEM;
-		goto release_master;
-	}
-
-	ret = appleacpi_config_spi_dev(spi, adev);
-	if (ret)
-		goto free_spi;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
-	acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
-			  sizeof(spi->modalias));
-#else
-	strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
-#endif
-
-	adev->power.flags.ignore_parent = true;
-
-	ACPI_COMPANION_SET(&spi->dev, adev);
-	acpi_device_set_enumerated(adev);
-
-	/* add spi device */
-	ret = spi_add_device(spi);
-	if (ret) {
-		adev->power.flags.ignore_parent = false;
-		pr_err("Failed to add spi device: %d\n", ret);
-		goto free_spi;
-	}
-
-	reg_info->spi = spi;
-
-	pr_info("Added spi device %s\n", dev_name(&spi->dev));
-
-	goto release_master;
-
-free_spi:
-	spi_dev_put(spi);
-release_master:
-	spi_master_put(spi_master);
-	reg_info->spi_master = NULL;
-
-	return ret;
-}
-
-static void appleacpi_dev_registration_worker(struct work_struct *work)
-{
-	struct appleacpi_spi_registration_info *info =
-		container_of(work, struct appleacpi_spi_registration_info,
-			     work.work);
-
-	if (info->spi_master && !info->spi_master->running) {
-		pr_debug_ratelimited("spi-master device is not running yet\n");
-		schedule_delayed_work(&info->work, usecs_to_jiffies(100));
-		return;
-	}
-
-	appleacpi_register_spi_device(info->spi_master, info->adev);
-}
-
-/*
- * Callback for whenever a new master spi device is added.
- */
-static int appleacpi_spi_master_added(struct device *dev,
-				      struct class_interface *cif)
-{
-	struct spi_master *spi_master =
-		container_of(dev, struct spi_master, dev);
-	struct appleacpi_spi_registration_info *info =
-		container_of(cif, struct appleacpi_spi_registration_info, cif);
-	struct acpi_device *master_adev = spi_master->dev.parent ?
-		ACPI_COMPANION(spi_master->dev.parent) : NULL;
-
-	pr_debug("New spi-master device %s (%s) with bus-number %d was added\n",
-		 dev_name(&spi_master->dev),
-		 master_adev ? acpi_device_hid(master_adev) : "-no-acpi-dev-",
-		 spi_master->bus_num);
-
-	if (master_adev != info->adev->parent)
-		return 0;
-
-	pr_info("Got spi-master device for device %s\n",
-		acpi_device_hid(info->adev));
-
-	/*
-	 * mutexes are held here, preventing unregistering of physical devices,
-	 * so need to do the actual registration in a worker.
-	 */
-	info->spi_master = spi_master_get(spi_master);
-	schedule_delayed_work(&info->work, usecs_to_jiffies(100));
-
-	return 0;
-}
-
-/*
- * Callback for whenever a slave spi device is added or removed.
- */
-static int appleacpi_spi_slave_changed(struct notifier_block *nb,
-				       unsigned long action, void *data)
-{
-	struct appleacpi_spi_registration_info *info =
-		container_of(nb, struct appleacpi_spi_registration_info,
-			     slave_notifier);
-	struct spi_device *spi = data;
-
-	pr_debug("SPI slave device changed: action=%lu, dev=%s\n",
-		 action, dev_name(&spi->dev));
-
-	switch (action) {
-	case BUS_NOTIFY_DEL_DEVICE:
-		if (spi == info->spi) {
-			info->spi = NULL;
-			return NOTIFY_OK;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-/*
- * spi_master_class is not exported, so this is an ugly hack to get it anyway.
- */
-static struct class *appleacpi_get_spi_master_class(void)
-{
-	struct spi_master *spi_master;
-	struct device dummy;
-	struct class *cls = NULL;
-
-	memset(&dummy, 0, sizeof(dummy));
-
-	spi_master = spi_alloc_master(&dummy, 0);
-	if (spi_master) {
-		cls = spi_master->dev.class;
-		spi_master_put(spi_master);
-	}
-
-	return cls;
-}
-
-static int appleacpi_probe(struct acpi_device *adev)
-{
-	struct appleacpi_spi_registration_info *reg_info;
-	int ret;
-
-	pr_debug("Probing acpi-device %s: bus-id='%s', adr=%lu, uid='%s'\n",
-		 acpi_device_hid(adev), acpi_device_bid(adev),
-		 acpi_device_adr(adev), acpi_device_uid(adev));
-
-	ret = spi_register_driver(&applespi_driver);
-	if (ret) {
-		pr_err("Failed to register spi-driver: %d\n", ret);
-		return ret;
-	}
-
-	/*
-	 * Ideally we would just call spi_register_board_info() here,
-	 * but that function is not exported. Additionally, we need to
-	 * perform some extra work during device creation, such as
-	 * unregistering physical devices. So instead we have do the
-	 * registration ourselves. For that we see if our spi-master
-	 * has been registered already, and if not jump through some
-	 * hoops to make sure we are notified when it does.
-	 */
-
-	reg_info = kzalloc(sizeof(*reg_info), GFP_KERNEL);
-	if (!reg_info) {
-		ret = -ENOMEM;
-		goto unregister_driver;
-	}
-
-	reg_info->adev = adev;
-	INIT_DELAYED_WORK(&reg_info->work, appleacpi_dev_registration_worker);
-
-	adev->driver_data = reg_info;
-
-	/*
-	 * Set up listening for spi slave removals so we can properly
-	 * handle them.
-	 */
-	reg_info->slave_notifier.notifier_call =
-		appleacpi_spi_slave_changed;
-	ret = bus_register_notifier(&spi_bus_type,
-				    &reg_info->slave_notifier);
-	if (ret) {
-		pr_err("Failed to register notifier for spi slaves: %d\n", ret);
-		goto free_reg_info;
-	}
-
-	/*
-	 * Listen for additions of spi-master devices so we can register our spi
-	 * device when the relevant master is added.  Note that our callback
-	 * gets called immediately for all existing master devices, so this
-	 * takes care of registration when the master already exists too.
-	 */
-	reg_info->cif.class = appleacpi_get_spi_master_class();
-	reg_info->cif.add_dev = appleacpi_spi_master_added;
-
-	ret = class_interface_register(&reg_info->cif);
-	if (ret) {
-		pr_err("Failed to register watcher for spi-master: %d\n", ret);
-		goto unregister_notifier;
-	}
-
-	if (!reg_info->spi_master) {
-		pr_info("No spi-master device found for device %s - waiting for it to be registered\n",
-			acpi_device_hid(adev));
-	}
-
-	pr_info("acpi-device probe done: %s\n", acpi_device_hid(adev));
-
-	return 0;
-
-unregister_notifier:
-	bus_unregister_notifier(&spi_bus_type, &reg_info->slave_notifier);
-free_reg_info:
-	adev->driver_data = NULL;
-	kfree(reg_info);
-unregister_driver:
-	spi_unregister_driver(&applespi_driver);
-	return ret;
-}
-
-static int appleacpi_remove(struct acpi_device *adev)
-{
-	struct appleacpi_spi_registration_info *reg_info;
-
-	reg_info = acpi_driver_data(adev);
-	if (reg_info) {
-		class_interface_unregister(&reg_info->cif);
-		bus_unregister_notifier(&spi_bus_type,
-					&reg_info->slave_notifier);
-		cancel_delayed_work_sync(&reg_info->work);
-		if (reg_info->spi)
-			spi_unregister_device(reg_info->spi);
-		kfree(reg_info);
-	}
-
-	spi_unregister_driver(&applespi_driver);
-
-	pr_info("acpi-device remove done: %s\n", acpi_device_hid(adev));
-
-	return 0;
-}
-
-static struct acpi_driver appleacpi_driver = {
-	.name		= "appleacpi",
-	.class		= "topcase", /* ? */
-	.owner		= THIS_MODULE,
-	.ids		= applespi_acpi_match,
-	.ops		= {
-		.add		= appleacpi_probe,
-		.remove		= appleacpi_remove,
-	},
-};
-
-module_acpi_driver(appleacpi_driver)
-
-#else
-
 module_spi_driver(applespi_driver)
 
-#endif
-
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MacBook(Pro) SPI Keyboard/Touchpad driver");
 MODULE_AUTHOR("Federico Lorenzi");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment