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

meraki-mx100.c (5555B)


      1// SPDX-License-Identifier: GPL-2.0+
      2
      3/*
      4 * Cisco Meraki MX100 (Tinkerbell) board platform driver
      5 *
      6 * Based off of arch/x86/platform/meraki/tink.c from the
      7 * Meraki GPL release meraki-firmware-sources-r23-20150601
      8 *
      9 * Format inspired by platform/x86/pcengines-apuv2.c
     10 *
     11 * Copyright (C) 2021 Chris Blake <chrisrblake93@gmail.com>
     12 */
     13
     14#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
     15
     16#include <linux/dmi.h>
     17#include <linux/err.h>
     18#include <linux/gpio_keys.h>
     19#include <linux/gpio/machine.h>
     20#include <linux/input.h>
     21#include <linux/io.h>
     22#include <linux/kernel.h>
     23#include <linux/leds.h>
     24#include <linux/module.h>
     25#include <linux/platform_device.h>
     26
     27#define TINK_GPIO_DRIVER_NAME "gpio_ich"
     28
     29/* LEDs */
     30static const struct gpio_led tink_leds[] = {
     31	{
     32		.name = "mx100:green:internet",
     33		.default_trigger = "default-on",
     34	},
     35	{
     36		.name = "mx100:green:lan2",
     37	},
     38	{
     39		.name = "mx100:green:lan3",
     40	},
     41	{
     42		.name = "mx100:green:lan4",
     43	},
     44	{
     45		.name = "mx100:green:lan5",
     46	},
     47	{
     48		.name = "mx100:green:lan6",
     49	},
     50	{
     51		.name = "mx100:green:lan7",
     52	},
     53	{
     54		.name = "mx100:green:lan8",
     55	},
     56	{
     57		.name = "mx100:green:lan9",
     58	},
     59	{
     60		.name = "mx100:green:lan10",
     61	},
     62	{
     63		.name = "mx100:green:lan11",
     64	},
     65	{
     66		.name = "mx100:green:ha",
     67	},
     68	{
     69		.name = "mx100:orange:ha",
     70	},
     71	{
     72		.name = "mx100:green:usb",
     73	},
     74	{
     75		.name = "mx100:orange:usb",
     76	},
     77};
     78
     79static const struct gpio_led_platform_data tink_leds_pdata = {
     80	.num_leds	= ARRAY_SIZE(tink_leds),
     81	.leds		= tink_leds,
     82};
     83
     84static struct gpiod_lookup_table tink_leds_table = {
     85	.dev_id = "leds-gpio",
     86	.table = {
     87		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11,
     88				NULL, 0, GPIO_ACTIVE_LOW),
     89		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18,
     90				NULL, 1, GPIO_ACTIVE_HIGH),
     91		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20,
     92				NULL, 2, GPIO_ACTIVE_HIGH),
     93		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22,
     94				NULL, 3, GPIO_ACTIVE_HIGH),
     95		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23,
     96				NULL, 4, GPIO_ACTIVE_HIGH),
     97		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32,
     98				NULL, 5, GPIO_ACTIVE_HIGH),
     99		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34,
    100				NULL, 6, GPIO_ACTIVE_HIGH),
    101		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35,
    102				NULL, 7, GPIO_ACTIVE_HIGH),
    103		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36,
    104				NULL, 8, GPIO_ACTIVE_HIGH),
    105		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37,
    106				NULL, 9, GPIO_ACTIVE_HIGH),
    107		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48,
    108				NULL, 10, GPIO_ACTIVE_HIGH),
    109		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16,
    110				NULL, 11, GPIO_ACTIVE_LOW),
    111		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7,
    112				NULL, 12, GPIO_ACTIVE_LOW),
    113		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21,
    114				NULL, 13, GPIO_ACTIVE_LOW),
    115		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19,
    116				NULL, 14, GPIO_ACTIVE_LOW),
    117		{} /* Terminating entry */
    118	}
    119};
    120
    121/* Reset Button */
    122static struct gpio_keys_button tink_buttons[] = {
    123	{
    124		.desc			= "Reset",
    125		.type			= EV_KEY,
    126		.code			= KEY_RESTART,
    127		.active_low             = 1,
    128		.debounce_interval      = 100,
    129	},
    130};
    131
    132static const struct gpio_keys_platform_data tink_buttons_pdata = {
    133	.buttons	= tink_buttons,
    134	.nbuttons	= ARRAY_SIZE(tink_buttons),
    135	.poll_interval  = 20,
    136	.rep		= 0,
    137	.name		= "mx100-keys",
    138};
    139
    140static struct gpiod_lookup_table tink_keys_table = {
    141	.dev_id = "gpio-keys-polled",
    142	.table = {
    143		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60,
    144				NULL, 0, GPIO_ACTIVE_LOW),
    145		{} /* Terminating entry */
    146	}
    147};
    148
    149/* Board setup */
    150static const struct dmi_system_id tink_systems[] __initconst = {
    151	{
    152		.matches = {
    153			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Cisco"),
    154			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MX100-HW"),
    155		},
    156	},
    157	{} /* Terminating entry */
    158};
    159MODULE_DEVICE_TABLE(dmi, tink_systems);
    160
    161static struct platform_device *tink_leds_pdev;
    162static struct platform_device *tink_keys_pdev;
    163
    164static struct platform_device * __init tink_create_dev(
    165	const char *name, const void *pdata, size_t sz)
    166{
    167	struct platform_device *pdev;
    168
    169	pdev = platform_device_register_data(NULL,
    170		name, PLATFORM_DEVID_NONE, pdata, sz);
    171	if (IS_ERR(pdev))
    172		pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
    173
    174	return pdev;
    175}
    176
    177static int __init tink_board_init(void)
    178{
    179	int ret;
    180
    181	if (!dmi_first_match(tink_systems))
    182		return -ENODEV;
    183
    184	/*
    185	 * We need to make sure that GPIO60 isn't set to native mode as is default since it's our
    186	 * Reset Button. To do this, write to GPIO_USE_SEL2 to have GPIO60 set to GPIO mode.
    187	 * This is documented on page 1609 of the PCH datasheet, order number 327879-005US
    188	 */
    189	outl(inl(0x530) | BIT(28), 0x530);
    190
    191	gpiod_add_lookup_table(&tink_leds_table);
    192	gpiod_add_lookup_table(&tink_keys_table);
    193
    194	tink_leds_pdev = tink_create_dev("leds-gpio",
    195		&tink_leds_pdata, sizeof(tink_leds_pdata));
    196	if (IS_ERR(tink_leds_pdev)) {
    197		ret = PTR_ERR(tink_leds_pdev);
    198		goto err;
    199	}
    200
    201	tink_keys_pdev = tink_create_dev("gpio-keys-polled",
    202		&tink_buttons_pdata, sizeof(tink_buttons_pdata));
    203	if (IS_ERR(tink_keys_pdev)) {
    204		ret = PTR_ERR(tink_keys_pdev);
    205		platform_device_unregister(tink_leds_pdev);
    206		goto err;
    207	}
    208
    209	return 0;
    210
    211err:
    212	gpiod_remove_lookup_table(&tink_keys_table);
    213	gpiod_remove_lookup_table(&tink_leds_table);
    214	return ret;
    215}
    216module_init(tink_board_init);
    217
    218static void __exit tink_board_exit(void)
    219{
    220	platform_device_unregister(tink_keys_pdev);
    221	platform_device_unregister(tink_leds_pdev);
    222	gpiod_remove_lookup_table(&tink_keys_table);
    223	gpiod_remove_lookup_table(&tink_leds_table);
    224}
    225module_exit(tink_board_exit);
    226
    227MODULE_AUTHOR("Chris Blake <chrisrblake93@gmail.com>");
    228MODULE_DESCRIPTION("Cisco Meraki MX100 Platform Driver");
    229MODULE_LICENSE("GPL");
    230MODULE_ALIAS("platform:meraki-mx100");