cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

led.c (3062B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Driver for controlling LEDs for cameras connected to the Intel atomisp2
      4 * The main purpose of this driver is to turn off LEDs which are on at boot.
      5 *
      6 * Copyright (C) 2020 Hans de Goede <hdegoede@redhat.com>
      7 */
      8
      9#include <linux/dmi.h>
     10#include <linux/gpio/consumer.h>
     11#include <linux/gpio/machine.h>
     12#include <linux/leds.h>
     13#include <linux/module.h>
     14#include <linux/mod_devicetable.h>
     15#include <linux/platform_device.h>
     16#include <linux/workqueue.h>
     17
     18/* This must be leds-gpio as the leds-gpio driver binds to the name */
     19#define DEV_NAME		"leds-gpio"
     20
     21static const struct gpio_led atomisp2_leds[] = {
     22	{
     23		.name = "atomisp2::camera",
     24		.default_state  = LEDS_GPIO_DEFSTATE_OFF,
     25	},
     26};
     27
     28static const struct gpio_led_platform_data atomisp2_leds_pdata = {
     29	.num_leds	= ARRAY_SIZE(atomisp2_leds),
     30	.leds		= atomisp2_leds,
     31};
     32
     33static struct gpiod_lookup_table asus_t100ta_lookup = {
     34	.dev_id = DEV_NAME,
     35	.table = {
     36		GPIO_LOOKUP_IDX("INT33FC:02", 8, NULL, 0, GPIO_ACTIVE_HIGH),
     37		{ }
     38	}
     39};
     40
     41static struct gpiod_lookup_table asus_t100chi_lookup = {
     42	.dev_id = DEV_NAME,
     43	.table = {
     44		GPIO_LOOKUP_IDX("INT33FC:01", 24, NULL, 0, GPIO_ACTIVE_HIGH),
     45		{ }
     46	}
     47};
     48
     49static const struct dmi_system_id atomisp2_led_systems[] __initconst = {
     50	{
     51		.matches = {
     52			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
     53			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
     54		},
     55		.driver_data = &asus_t100ta_lookup,
     56	},
     57	{
     58		.matches = {
     59			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
     60			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"),
     61		},
     62		.driver_data = &asus_t100ta_lookup,
     63	},
     64	{
     65		.matches = {
     66			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
     67			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"),
     68		},
     69		.driver_data = &asus_t100chi_lookup,
     70	},
     71	{} /* Terminating entry */
     72};
     73MODULE_DEVICE_TABLE(dmi, atomisp2_led_systems);
     74
     75static struct gpiod_lookup_table *gpio_lookup;
     76static struct platform_device *pdev;
     77
     78static int __init atomisp2_led_init(void)
     79{
     80	const struct dmi_system_id *system;
     81
     82	system = dmi_first_match(atomisp2_led_systems);
     83	if (!system)
     84		return -ENODEV;
     85
     86	gpio_lookup = system->driver_data;
     87	gpiod_add_lookup_table(gpio_lookup);
     88
     89	pdev = platform_device_register_resndata(NULL,
     90						 DEV_NAME, PLATFORM_DEVID_NONE,
     91						 NULL, 0, &atomisp2_leds_pdata,
     92						 sizeof(atomisp2_leds_pdata));
     93	if (IS_ERR(pdev))
     94		gpiod_remove_lookup_table(gpio_lookup);
     95
     96	return PTR_ERR_OR_ZERO(pdev);
     97}
     98
     99static void __exit atomisp2_led_cleanup(void)
    100{
    101	platform_device_unregister(pdev);
    102	gpiod_remove_lookup_table(gpio_lookup);
    103}
    104
    105module_init(atomisp2_led_init);
    106module_exit(atomisp2_led_cleanup);
    107
    108/*
    109 * The ACPI INIT method from Asus WMI's code on the T100TA and T200TA turns the
    110 * LED on (without the WMI interface allowing further control over the LED).
    111 * Ensure we are loaded after asus-nb-wmi so that we turn the LED off again.
    112 */
    113MODULE_SOFTDEP("pre: asus_nb_wmi");
    114MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com");
    115MODULE_DESCRIPTION("Intel atomisp2 camera LED driver");
    116MODULE_LICENSE("GPL");