in keyboard/applespi.c [1648:1832]
static int applespi_probe(struct spi_device *spi)
{
struct applespi_data *applespi;
acpi_handle spi_handle = ACPI_HANDLE(&spi->dev);
acpi_status acpi_sts;
int sts, i;
unsigned long long gpe, usb_status;
/* check if the USB interface is present and enabled already */
acpi_sts = acpi_evaluate_integer(spi_handle, "UIST", NULL, &usb_status);
if (ACPI_SUCCESS(acpi_sts) && usb_status) {
/* let the USB driver take over instead */
dev_info(&spi->dev, "USB interface already enabled\n");
return -ENODEV;
}
/* allocate driver data */
applespi = devm_kzalloc(&spi->dev, sizeof(*applespi), GFP_KERNEL);
if (!applespi)
return -ENOMEM;
applespi->spi = spi;
INIT_WORK(&applespi->work, applespi_worker);
/* store the driver data */
spi_set_drvdata(spi, applespi);
/* create our buffers */
applespi->tx_buffer = devm_kmalloc(&spi->dev, APPLESPI_PACKET_SIZE,
GFP_KERNEL);
applespi->tx_status = devm_kmalloc(&spi->dev, APPLESPI_STATUS_SIZE,
GFP_KERNEL);
applespi->rx_buffer = devm_kmalloc(&spi->dev, APPLESPI_PACKET_SIZE,
GFP_KERNEL);
applespi->msg_buf = devm_kmalloc_array(&spi->dev, MAX_PKTS_PER_MSG,
APPLESPI_PACKET_SIZE,
GFP_KERNEL);
if (!applespi->tx_buffer || !applespi->tx_status ||
!applespi->rx_buffer || !applespi->msg_buf)
return -ENOMEM;
/* set up our spi messages */
applespi_setup_read_txfrs(applespi);
applespi_setup_write_txfrs(applespi);
/* cache ACPI method handles */
acpi_sts = acpi_get_handle(spi_handle, "SIEN", &applespi->sien);
if (ACPI_FAILURE(acpi_sts)) {
dev_err(&applespi->spi->dev,
"Failed to get SIEN ACPI method handle: %s\n",
acpi_format_exception(acpi_sts));
return -ENODEV;
}
acpi_sts = acpi_get_handle(spi_handle, "SIST", &applespi->sist);
if (ACPI_FAILURE(acpi_sts)) {
dev_err(&applespi->spi->dev,
"Failed to get SIST ACPI method handle: %s\n",
acpi_format_exception(acpi_sts));
return -ENODEV;
}
/* switch on the SPI interface */
sts = applespi_setup_spi(applespi);
if (sts)
return sts;
sts = applespi_enable_spi(applespi);
if (sts)
return sts;
/* setup the keyboard input dev */
applespi->keyboard_input_dev = devm_input_allocate_device(&spi->dev);
if (!applespi->keyboard_input_dev)
return -ENOMEM;
applespi->keyboard_input_dev->name = "Apple SPI Keyboard";
applespi->keyboard_input_dev->phys = "applespi/input0";
applespi->keyboard_input_dev->dev.parent = &spi->dev;
applespi->keyboard_input_dev->id.bustype = BUS_SPI;
applespi->keyboard_input_dev->evbit[0] =
BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) | BIT_MASK(EV_REP);
applespi->keyboard_input_dev->ledbit[0] = BIT_MASK(LED_CAPSL);
input_set_drvdata(applespi->keyboard_input_dev, applespi);
applespi->keyboard_input_dev->event = applespi_event;
for (i = 0; i < ARRAY_SIZE(applespi_scancodes); i++)
if (applespi_scancodes[i])
input_set_capability(applespi->keyboard_input_dev,
EV_KEY, applespi_scancodes[i]);
for (i = 0; i < ARRAY_SIZE(applespi_controlcodes); i++)
if (applespi_controlcodes[i])
input_set_capability(applespi->keyboard_input_dev,
EV_KEY, applespi_controlcodes[i]);
for (i = 0; i < ARRAY_SIZE(applespi_fn_codes); i++)
if (applespi_fn_codes[i].to)
input_set_capability(applespi->keyboard_input_dev,
EV_KEY, applespi_fn_codes[i].to);
input_set_capability(applespi->keyboard_input_dev, EV_KEY, KEY_FN);
sts = input_register_device(applespi->keyboard_input_dev);
if (sts) {
dev_err(&applespi->spi->dev,
"Unable to register keyboard input device (%d)\n", sts);
return -ENODEV;
}
/*
* The applespi device doesn't send interrupts normally (as is described
* in its DSDT), but rather seems to use ACPI GPEs.
*/
acpi_sts = acpi_evaluate_integer(spi_handle, "_GPE", NULL, &gpe);
if (ACPI_FAILURE(acpi_sts)) {
dev_err(&applespi->spi->dev,
"Failed to obtain GPE for SPI slave device: %s\n",
acpi_format_exception(acpi_sts));
return -ENODEV;
}
applespi->gpe = (int)gpe;
acpi_sts = acpi_install_gpe_handler(NULL, applespi->gpe,
ACPI_GPE_LEVEL_TRIGGERED,
applespi_notify, applespi);
if (ACPI_FAILURE(acpi_sts)) {
dev_err(&applespi->spi->dev,
"Failed to install GPE handler for GPE %d: %s\n",
applespi->gpe, acpi_format_exception(acpi_sts));
return -ENODEV;
}
applespi->suspended = false;
acpi_sts = acpi_enable_gpe(NULL, applespi->gpe);
if (ACPI_FAILURE(acpi_sts)) {
dev_err(&applespi->spi->dev,
"Failed to enable GPE handler for GPE %d: %s\n",
applespi->gpe, acpi_format_exception(acpi_sts));
acpi_remove_gpe_handler(NULL, applespi->gpe, applespi_notify);
return -ENODEV;
}
/* trigger touchpad setup */
applespi_init(applespi, false);
/*
* By default this device is not enabled for wakeup; but USB keyboards
* generally are, so the expectation is that by default the keyboard
* will wake the system.
*/
device_wakeup_enable(&spi->dev);
/* set up keyboard-backlight */
sts = applespi_get_saved_bl_level(applespi);
if (sts >= 0)
applespi_set_bl_level(&applespi->backlight_info, sts);
applespi->backlight_info.name = "spi::kbd_backlight";
applespi->backlight_info.default_trigger = "kbd-backlight";
applespi->backlight_info.brightness_set = applespi_set_bl_level;
sts = devm_led_classdev_register(&spi->dev, &applespi->backlight_info);
if (sts)
dev_warn(&applespi->spi->dev,
"Unable to register keyboard backlight class dev (%d)\n",
sts);
/* set up debugfs entries for touchpad dimensions logging */
applespi->debugfs_root = debugfs_create_dir("applespi", NULL);
debugfs_create_bool("enable_tp_dim", 0600, applespi->debugfs_root,
&applespi->debug_tp_dim);
debugfs_create_file("tp_dim", 0400, applespi->debugfs_root, applespi,
&applespi_tp_dim_fops);
return 0;
}