brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · 3751ed3 Raw
231 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3/*4 * Cisco Meraki MX100 (Tinkerbell) board platform driver5 *6 * Based off of arch/x86/platform/meraki/tink.c from the7 * Meraki GPL release meraki-firmware-sources-r23-201506018 *9 * Format inspired by platform/x86/pcengines-apuv2.c10 *11 * Copyright (C) 2021 Chris Blake <chrisrblake93@gmail.com>12 */13 14#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt15 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 our186	 * 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-005US188	 */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");231