1f8eb0235SEnrico Weigelt, metux IT consult // SPDX-License-Identifier: GPL-2.0+
2f8eb0235SEnrico Weigelt, metux IT consult
3f8eb0235SEnrico Weigelt, metux IT consult /*
4f8eb0235SEnrico Weigelt, metux IT consult * PC-Engines APUv2/APUv3 board platform driver
502abbda1SAndy Shevchenko * for GPIO buttons and LEDs
6f8eb0235SEnrico Weigelt, metux IT consult *
7f8eb0235SEnrico Weigelt, metux IT consult * Copyright (C) 2018 metux IT consult
8f8eb0235SEnrico Weigelt, metux IT consult * Author: Enrico Weigelt <info@metux.net>
9f8eb0235SEnrico Weigelt, metux IT consult */
10f8eb0235SEnrico Weigelt, metux IT consult
11f8eb0235SEnrico Weigelt, metux IT consult #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12f8eb0235SEnrico Weigelt, metux IT consult
13f8eb0235SEnrico Weigelt, metux IT consult #include <linux/dmi.h>
14f8eb0235SEnrico Weigelt, metux IT consult #include <linux/err.h>
15f8eb0235SEnrico Weigelt, metux IT consult #include <linux/kernel.h>
16f8eb0235SEnrico Weigelt, metux IT consult #include <linux/leds.h>
17f8eb0235SEnrico Weigelt, metux IT consult #include <linux/module.h>
18f8eb0235SEnrico Weigelt, metux IT consult #include <linux/platform_device.h>
19f8eb0235SEnrico Weigelt, metux IT consult #include <linux/gpio_keys.h>
20f8eb0235SEnrico Weigelt, metux IT consult #include <linux/gpio/machine.h>
21f8eb0235SEnrico Weigelt, metux IT consult #include <linux/input.h>
22f8eb0235SEnrico Weigelt, metux IT consult #include <linux/platform_data/gpio/gpio-amd-fch.h>
23f8eb0235SEnrico Weigelt, metux IT consult
24f8eb0235SEnrico Weigelt, metux IT consult /*
25f8eb0235SEnrico Weigelt, metux IT consult * NOTE: this driver only supports APUv2/3 - not APUv1, as this one
2602abbda1SAndy Shevchenko * has completely different register layouts.
27f8eb0235SEnrico Weigelt, metux IT consult */
28f8eb0235SEnrico Weigelt, metux IT consult
2902abbda1SAndy Shevchenko /* Register mappings */
30f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_REG_LED1 AMD_FCH_GPIO_REG_GPIO57
31f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_REG_LED2 AMD_FCH_GPIO_REG_GPIO58
32f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_REG_LED3 AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
33f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_REG_MODESW AMD_FCH_GPIO_REG_GPIO32_GE1
34f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_REG_SIMSWAP AMD_FCH_GPIO_REG_GPIO33_GE2
35fce55cc8SEd Wildgoose #define APU2_GPIO_REG_MPCIE2 AMD_FCH_GPIO_REG_GPIO55_DEVSLP0
366a0694b6SFlorian Eckert #define APU2_GPIO_REG_MPCIE3 AMD_FCH_GPIO_REG_GPIO51
37f8eb0235SEnrico Weigelt, metux IT consult
3802abbda1SAndy Shevchenko /* Order in which the GPIO lines are defined in the register list */
39f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_LINE_LED1 0
40f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_LINE_LED2 1
41f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_LINE_LED3 2
42f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_LINE_MODESW 3
43f8eb0235SEnrico Weigelt, metux IT consult #define APU2_GPIO_LINE_SIMSWAP 4
446a0694b6SFlorian Eckert #define APU2_GPIO_LINE_MPCIE2 5
456a0694b6SFlorian Eckert #define APU2_GPIO_LINE_MPCIE3 6
46f8eb0235SEnrico Weigelt, metux IT consult
4702abbda1SAndy Shevchenko /* GPIO device */
48f8eb0235SEnrico Weigelt, metux IT consult
49f8eb0235SEnrico Weigelt, metux IT consult static int apu2_gpio_regs[] = {
50f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED1] = APU2_GPIO_REG_LED1,
51f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED2] = APU2_GPIO_REG_LED2,
52f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED3] = APU2_GPIO_REG_LED3,
53f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_MODESW] = APU2_GPIO_REG_MODESW,
54f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_SIMSWAP] = APU2_GPIO_REG_SIMSWAP,
556a0694b6SFlorian Eckert [APU2_GPIO_LINE_MPCIE2] = APU2_GPIO_REG_MPCIE2,
566a0694b6SFlorian Eckert [APU2_GPIO_LINE_MPCIE3] = APU2_GPIO_REG_MPCIE3,
57f8eb0235SEnrico Weigelt, metux IT consult };
58f8eb0235SEnrico Weigelt, metux IT consult
59f8eb0235SEnrico Weigelt, metux IT consult static const char * const apu2_gpio_names[] = {
60f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED1] = "front-led1",
61f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED2] = "front-led2",
62f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_LED3] = "front-led3",
63f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_MODESW] = "front-button",
64f8eb0235SEnrico Weigelt, metux IT consult [APU2_GPIO_LINE_SIMSWAP] = "simswap",
656a0694b6SFlorian Eckert [APU2_GPIO_LINE_MPCIE2] = "mpcie2_reset",
666a0694b6SFlorian Eckert [APU2_GPIO_LINE_MPCIE3] = "mpcie3_reset",
67f8eb0235SEnrico Weigelt, metux IT consult };
68f8eb0235SEnrico Weigelt, metux IT consult
69f8eb0235SEnrico Weigelt, metux IT consult static const struct amd_fch_gpio_pdata board_apu2 = {
70f8eb0235SEnrico Weigelt, metux IT consult .gpio_num = ARRAY_SIZE(apu2_gpio_regs),
71f8eb0235SEnrico Weigelt, metux IT consult .gpio_reg = apu2_gpio_regs,
72f8eb0235SEnrico Weigelt, metux IT consult .gpio_names = apu2_gpio_names,
73f8eb0235SEnrico Weigelt, metux IT consult };
74f8eb0235SEnrico Weigelt, metux IT consult
7502abbda1SAndy Shevchenko /* GPIO LEDs device */
76f8eb0235SEnrico Weigelt, metux IT consult
77f8eb0235SEnrico Weigelt, metux IT consult static const struct gpio_led apu2_leds[] = {
78f8eb0235SEnrico Weigelt, metux IT consult { .name = "apu:green:1" },
79f8eb0235SEnrico Weigelt, metux IT consult { .name = "apu:green:2" },
805037d4ddSEnrico Weigelt { .name = "apu:green:3" },
81f8eb0235SEnrico Weigelt, metux IT consult };
82f8eb0235SEnrico Weigelt, metux IT consult
83f8eb0235SEnrico Weigelt, metux IT consult static const struct gpio_led_platform_data apu2_leds_pdata = {
84f8eb0235SEnrico Weigelt, metux IT consult .num_leds = ARRAY_SIZE(apu2_leds),
85f8eb0235SEnrico Weigelt, metux IT consult .leds = apu2_leds,
86f8eb0235SEnrico Weigelt, metux IT consult };
87f8eb0235SEnrico Weigelt, metux IT consult
8884f669b4SYueHaibing static struct gpiod_lookup_table gpios_led_table = {
89f8eb0235SEnrico Weigelt, metux IT consult .dev_id = "leds-gpio",
90f8eb0235SEnrico Weigelt, metux IT consult .table = {
91f8eb0235SEnrico Weigelt, metux IT consult GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED1,
92f8eb0235SEnrico Weigelt, metux IT consult NULL, 0, GPIO_ACTIVE_LOW),
93f8eb0235SEnrico Weigelt, metux IT consult GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED2,
94f8eb0235SEnrico Weigelt, metux IT consult NULL, 1, GPIO_ACTIVE_LOW),
95f8eb0235SEnrico Weigelt, metux IT consult GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
96f8eb0235SEnrico Weigelt, metux IT consult NULL, 2, GPIO_ACTIVE_LOW),
97*9d7b132eSHans de Goede {} /* Terminating entry */
98f8eb0235SEnrico Weigelt, metux IT consult }
99f8eb0235SEnrico Weigelt, metux IT consult };
100f8eb0235SEnrico Weigelt, metux IT consult
10102abbda1SAndy Shevchenko /* GPIO keyboard device */
102f8eb0235SEnrico Weigelt, metux IT consult
103f8eb0235SEnrico Weigelt, metux IT consult static struct gpio_keys_button apu2_keys_buttons[] = {
104f8eb0235SEnrico Weigelt, metux IT consult {
105f14312a9SEnrico Weigelt .code = KEY_RESTART,
106f8eb0235SEnrico Weigelt, metux IT consult .active_low = 1,
107f8eb0235SEnrico Weigelt, metux IT consult .desc = "front button",
108f8eb0235SEnrico Weigelt, metux IT consult .type = EV_KEY,
109f8eb0235SEnrico Weigelt, metux IT consult .debounce_interval = 10,
110f8eb0235SEnrico Weigelt, metux IT consult .value = 1,
111f8eb0235SEnrico Weigelt, metux IT consult },
112f8eb0235SEnrico Weigelt, metux IT consult };
113f8eb0235SEnrico Weigelt, metux IT consult
114f8eb0235SEnrico Weigelt, metux IT consult static const struct gpio_keys_platform_data apu2_keys_pdata = {
115f8eb0235SEnrico Weigelt, metux IT consult .buttons = apu2_keys_buttons,
116f8eb0235SEnrico Weigelt, metux IT consult .nbuttons = ARRAY_SIZE(apu2_keys_buttons),
117f8eb0235SEnrico Weigelt, metux IT consult .poll_interval = 100,
118f8eb0235SEnrico Weigelt, metux IT consult .rep = 0,
119f8eb0235SEnrico Weigelt, metux IT consult .name = "apu2-keys",
120f8eb0235SEnrico Weigelt, metux IT consult };
121f8eb0235SEnrico Weigelt, metux IT consult
12284f669b4SYueHaibing static struct gpiod_lookup_table gpios_key_table = {
123f8eb0235SEnrico Weigelt, metux IT consult .dev_id = "gpio-keys-polled",
124f8eb0235SEnrico Weigelt, metux IT consult .table = {
125f8eb0235SEnrico Weigelt, metux IT consult GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW,
126f8eb0235SEnrico Weigelt, metux IT consult NULL, 0, GPIO_ACTIVE_LOW),
127*9d7b132eSHans de Goede {} /* Terminating entry */
128f8eb0235SEnrico Weigelt, metux IT consult }
129f8eb0235SEnrico Weigelt, metux IT consult };
130f8eb0235SEnrico Weigelt, metux IT consult
13102abbda1SAndy Shevchenko /* Board setup */
132f8eb0235SEnrico Weigelt, metux IT consult
13302abbda1SAndy Shevchenko /* Note: matching works on string prefix, so "apu2" must come before "apu" */
134f8eb0235SEnrico Weigelt, metux IT consult static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
135f8eb0235SEnrico Weigelt, metux IT consult
13602abbda1SAndy Shevchenko /* APU2 w/ legacy BIOS < 4.0.8 */
137f8eb0235SEnrico Weigelt, metux IT consult {
138f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu2",
139f8eb0235SEnrico Weigelt, metux IT consult .matches = {
140f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
141f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "APU2")
142f8eb0235SEnrico Weigelt, metux IT consult },
143f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
144f8eb0235SEnrico Weigelt, metux IT consult },
14502abbda1SAndy Shevchenko /* APU2 w/ legacy BIOS >= 4.0.8 */
146f8eb0235SEnrico Weigelt, metux IT consult {
147f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu2",
148f8eb0235SEnrico Weigelt, metux IT consult .matches = {
149f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
150f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "apu2")
151f8eb0235SEnrico Weigelt, metux IT consult },
152f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
153f8eb0235SEnrico Weigelt, metux IT consult },
15402abbda1SAndy Shevchenko /* APU2 w/ mainline BIOS */
155f8eb0235SEnrico Weigelt, metux IT consult {
156f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu2",
157f8eb0235SEnrico Weigelt, metux IT consult .matches = {
158f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
159f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2")
160f8eb0235SEnrico Weigelt, metux IT consult },
161f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
162f8eb0235SEnrico Weigelt, metux IT consult },
163f8eb0235SEnrico Weigelt, metux IT consult
16402abbda1SAndy Shevchenko /* APU3 w/ legacy BIOS < 4.0.8 */
165f8eb0235SEnrico Weigelt, metux IT consult {
166f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu3",
167f8eb0235SEnrico Weigelt, metux IT consult .matches = {
168f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
169f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "APU3")
170f8eb0235SEnrico Weigelt, metux IT consult },
171f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
172f8eb0235SEnrico Weigelt, metux IT consult },
17302abbda1SAndy Shevchenko /* APU3 w/ legacy BIOS >= 4.0.8 */
174f8eb0235SEnrico Weigelt, metux IT consult {
175f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu3",
176f8eb0235SEnrico Weigelt, metux IT consult .matches = {
177f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
178f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "apu3")
179f8eb0235SEnrico Weigelt, metux IT consult },
180f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
181f8eb0235SEnrico Weigelt, metux IT consult },
18202abbda1SAndy Shevchenko /* APU3 w/ mainline BIOS */
183f8eb0235SEnrico Weigelt, metux IT consult {
184f8eb0235SEnrico Weigelt, metux IT consult .ident = "apu3",
185f8eb0235SEnrico Weigelt, metux IT consult .matches = {
186f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
187f8eb0235SEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3")
188f8eb0235SEnrico Weigelt, metux IT consult },
189f8eb0235SEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
190f8eb0235SEnrico Weigelt, metux IT consult },
19102abbda1SAndy Shevchenko /* APU4 w/ legacy BIOS < 4.0.8 */
1923d00da1dSEnrico Weigelt, metux IT consult {
1933d00da1dSEnrico Weigelt, metux IT consult .ident = "apu4",
1943d00da1dSEnrico Weigelt, metux IT consult .matches = {
1953d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
1963d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "APU4")
1973d00da1dSEnrico Weigelt, metux IT consult },
1983d00da1dSEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
1993d00da1dSEnrico Weigelt, metux IT consult },
20002abbda1SAndy Shevchenko /* APU4 w/ legacy BIOS >= 4.0.8 */
2013d00da1dSEnrico Weigelt, metux IT consult {
2023d00da1dSEnrico Weigelt, metux IT consult .ident = "apu4",
2033d00da1dSEnrico Weigelt, metux IT consult .matches = {
2043d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
2053d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "apu4")
2063d00da1dSEnrico Weigelt, metux IT consult },
2073d00da1dSEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
2083d00da1dSEnrico Weigelt, metux IT consult },
20902abbda1SAndy Shevchenko /* APU4 w/ mainline BIOS */
2103d00da1dSEnrico Weigelt, metux IT consult {
2113d00da1dSEnrico Weigelt, metux IT consult .ident = "apu4",
2123d00da1dSEnrico Weigelt, metux IT consult .matches = {
2133d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
2143d00da1dSEnrico Weigelt, metux IT consult DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu4")
2153d00da1dSEnrico Weigelt, metux IT consult },
2163d00da1dSEnrico Weigelt, metux IT consult .driver_data = (void *)&board_apu2,
2173d00da1dSEnrico Weigelt, metux IT consult },
218f8eb0235SEnrico Weigelt, metux IT consult {}
219f8eb0235SEnrico Weigelt, metux IT consult };
220f8eb0235SEnrico Weigelt, metux IT consult
221f8eb0235SEnrico Weigelt, metux IT consult static struct platform_device *apu_gpio_pdev;
222f8eb0235SEnrico Weigelt, metux IT consult static struct platform_device *apu_leds_pdev;
223f8eb0235SEnrico Weigelt, metux IT consult static struct platform_device *apu_keys_pdev;
224f8eb0235SEnrico Weigelt, metux IT consult
apu_create_pdev(const char * name,const void * pdata,size_t sz)225f8eb0235SEnrico Weigelt, metux IT consult static struct platform_device * __init apu_create_pdev(
226f8eb0235SEnrico Weigelt, metux IT consult const char *name,
227f8eb0235SEnrico Weigelt, metux IT consult const void *pdata,
228f8eb0235SEnrico Weigelt, metux IT consult size_t sz)
229f8eb0235SEnrico Weigelt, metux IT consult {
230f8eb0235SEnrico Weigelt, metux IT consult struct platform_device *pdev;
231f8eb0235SEnrico Weigelt, metux IT consult
232f8eb0235SEnrico Weigelt, metux IT consult pdev = platform_device_register_resndata(NULL,
233f8eb0235SEnrico Weigelt, metux IT consult name,
234f8eb0235SEnrico Weigelt, metux IT consult PLATFORM_DEVID_NONE,
235f8eb0235SEnrico Weigelt, metux IT consult NULL,
236f8eb0235SEnrico Weigelt, metux IT consult 0,
237f8eb0235SEnrico Weigelt, metux IT consult pdata,
238f8eb0235SEnrico Weigelt, metux IT consult sz);
239f8eb0235SEnrico Weigelt, metux IT consult
240f8eb0235SEnrico Weigelt, metux IT consult if (IS_ERR(pdev))
241f8eb0235SEnrico Weigelt, metux IT consult pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
242f8eb0235SEnrico Weigelt, metux IT consult
243f8eb0235SEnrico Weigelt, metux IT consult return pdev;
244f8eb0235SEnrico Weigelt, metux IT consult }
245f8eb0235SEnrico Weigelt, metux IT consult
apu_board_init(void)246f8eb0235SEnrico Weigelt, metux IT consult static int __init apu_board_init(void)
247f8eb0235SEnrico Weigelt, metux IT consult {
248f8eb0235SEnrico Weigelt, metux IT consult const struct dmi_system_id *id;
249f8eb0235SEnrico Weigelt, metux IT consult
250f8eb0235SEnrico Weigelt, metux IT consult id = dmi_first_match(apu_gpio_dmi_table);
251f8eb0235SEnrico Weigelt, metux IT consult if (!id) {
25202abbda1SAndy Shevchenko pr_err("failed to detect APU board via DMI\n");
253f8eb0235SEnrico Weigelt, metux IT consult return -ENODEV;
254f8eb0235SEnrico Weigelt, metux IT consult }
255f8eb0235SEnrico Weigelt, metux IT consult
256f8eb0235SEnrico Weigelt, metux IT consult gpiod_add_lookup_table(&gpios_led_table);
257f8eb0235SEnrico Weigelt, metux IT consult gpiod_add_lookup_table(&gpios_key_table);
258f8eb0235SEnrico Weigelt, metux IT consult
259f8eb0235SEnrico Weigelt, metux IT consult apu_gpio_pdev = apu_create_pdev(
260f8eb0235SEnrico Weigelt, metux IT consult AMD_FCH_GPIO_DRIVER_NAME,
261f8eb0235SEnrico Weigelt, metux IT consult id->driver_data,
262f8eb0235SEnrico Weigelt, metux IT consult sizeof(struct amd_fch_gpio_pdata));
263f8eb0235SEnrico Weigelt, metux IT consult
264f8eb0235SEnrico Weigelt, metux IT consult apu_leds_pdev = apu_create_pdev(
265f8eb0235SEnrico Weigelt, metux IT consult "leds-gpio",
266f8eb0235SEnrico Weigelt, metux IT consult &apu2_leds_pdata,
267f8eb0235SEnrico Weigelt, metux IT consult sizeof(apu2_leds_pdata));
268f8eb0235SEnrico Weigelt, metux IT consult
269f8eb0235SEnrico Weigelt, metux IT consult apu_keys_pdev = apu_create_pdev(
270f8eb0235SEnrico Weigelt, metux IT consult "gpio-keys-polled",
271f8eb0235SEnrico Weigelt, metux IT consult &apu2_keys_pdata,
272f8eb0235SEnrico Weigelt, metux IT consult sizeof(apu2_keys_pdata));
273f8eb0235SEnrico Weigelt, metux IT consult
274f8eb0235SEnrico Weigelt, metux IT consult return 0;
275f8eb0235SEnrico Weigelt, metux IT consult }
276f8eb0235SEnrico Weigelt, metux IT consult
apu_board_exit(void)277f8eb0235SEnrico Weigelt, metux IT consult static void __exit apu_board_exit(void)
278f8eb0235SEnrico Weigelt, metux IT consult {
279f8eb0235SEnrico Weigelt, metux IT consult gpiod_remove_lookup_table(&gpios_led_table);
280f8eb0235SEnrico Weigelt, metux IT consult gpiod_remove_lookup_table(&gpios_key_table);
281f8eb0235SEnrico Weigelt, metux IT consult
282f8eb0235SEnrico Weigelt, metux IT consult platform_device_unregister(apu_keys_pdev);
283f8eb0235SEnrico Weigelt, metux IT consult platform_device_unregister(apu_leds_pdev);
284f8eb0235SEnrico Weigelt, metux IT consult platform_device_unregister(apu_gpio_pdev);
285f8eb0235SEnrico Weigelt, metux IT consult }
286f8eb0235SEnrico Weigelt, metux IT consult
287f8eb0235SEnrico Weigelt, metux IT consult module_init(apu_board_init);
288f8eb0235SEnrico Weigelt, metux IT consult module_exit(apu_board_exit);
289f8eb0235SEnrico Weigelt, metux IT consult
290f8eb0235SEnrico Weigelt, metux IT consult MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
29102abbda1SAndy Shevchenko MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LEDs/keys driver");
292f8eb0235SEnrico Weigelt, metux IT consult MODULE_LICENSE("GPL");
293f8eb0235SEnrico Weigelt, metux IT consult MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
294edbfe83dSJean Delvare MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME " platform:leds-gpio platform:gpio_keys_polled");
295