^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * PC-Engines APUv2/APUv3 board platform driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * for GPIO buttons and LEDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2018 metux IT consult
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Enrico Weigelt <info@metux.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/gpio_keys.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/gpio/machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/platform_data/gpio/gpio-amd-fch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * NOTE: this driver only supports APUv2/3 - not APUv1, as this one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * has completely different register layouts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* Register mappings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define APU2_GPIO_REG_LED1 AMD_FCH_GPIO_REG_GPIO57
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define APU2_GPIO_REG_LED2 AMD_FCH_GPIO_REG_GPIO58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define APU2_GPIO_REG_LED3 AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define APU2_GPIO_REG_MODESW AMD_FCH_GPIO_REG_GPIO32_GE1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define APU2_GPIO_REG_SIMSWAP AMD_FCH_GPIO_REG_GPIO33_GE2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define APU2_GPIO_REG_MPCIE2 AMD_FCH_GPIO_REG_GPIO55_DEVSLP0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define APU2_GPIO_REG_MPCIE3 AMD_FCH_GPIO_REG_GPIO51
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Order in which the GPIO lines are defined in the register list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define APU2_GPIO_LINE_LED1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define APU2_GPIO_LINE_LED2 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define APU2_GPIO_LINE_LED3 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define APU2_GPIO_LINE_MODESW 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define APU2_GPIO_LINE_SIMSWAP 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define APU2_GPIO_LINE_MPCIE2 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define APU2_GPIO_LINE_MPCIE3 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* GPIO device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int apu2_gpio_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) [APU2_GPIO_LINE_LED1] = APU2_GPIO_REG_LED1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [APU2_GPIO_LINE_LED2] = APU2_GPIO_REG_LED2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) [APU2_GPIO_LINE_LED3] = APU2_GPIO_REG_LED3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [APU2_GPIO_LINE_MODESW] = APU2_GPIO_REG_MODESW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [APU2_GPIO_LINE_SIMSWAP] = APU2_GPIO_REG_SIMSWAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [APU2_GPIO_LINE_MPCIE2] = APU2_GPIO_REG_MPCIE2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) [APU2_GPIO_LINE_MPCIE3] = APU2_GPIO_REG_MPCIE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static const char * const apu2_gpio_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) [APU2_GPIO_LINE_LED1] = "front-led1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [APU2_GPIO_LINE_LED2] = "front-led2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) [APU2_GPIO_LINE_LED3] = "front-led3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) [APU2_GPIO_LINE_MODESW] = "front-button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) [APU2_GPIO_LINE_SIMSWAP] = "simswap",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) [APU2_GPIO_LINE_MPCIE2] = "mpcie2_reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) [APU2_GPIO_LINE_MPCIE3] = "mpcie3_reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct amd_fch_gpio_pdata board_apu2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .gpio_num = ARRAY_SIZE(apu2_gpio_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .gpio_reg = apu2_gpio_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .gpio_names = apu2_gpio_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* GPIO LEDs device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct gpio_led apu2_leds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { .name = "apu:green:1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { .name = "apu:green:2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { .name = "apu:green:3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const struct gpio_led_platform_data apu2_leds_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .num_leds = ARRAY_SIZE(apu2_leds),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .leds = apu2_leds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct gpiod_lookup_table gpios_led_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .dev_id = "leds-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) NULL, 0, GPIO_ACTIVE_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) NULL, 1, GPIO_ACTIVE_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) NULL, 2, GPIO_ACTIVE_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {} /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* GPIO keyboard device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct gpio_keys_button apu2_keys_buttons[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .code = KEY_RESTART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .active_low = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .desc = "front button",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .type = EV_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .debounce_interval = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .value = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct gpio_keys_platform_data apu2_keys_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .buttons = apu2_keys_buttons,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .nbuttons = ARRAY_SIZE(apu2_keys_buttons),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .poll_interval = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .rep = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .name = "apu2-keys",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct gpiod_lookup_table gpios_key_table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .dev_id = "gpio-keys-polled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .table = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) NULL, 0, GPIO_ACTIVE_LOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {} /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Board setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Note: matching works on string prefix, so "apu2" must come before "apu" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* APU2 w/ legacy BIOS < 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .ident = "apu2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) DMI_MATCH(DMI_BOARD_NAME, "APU2")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* APU2 w/ legacy BIOS >= 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .ident = "apu2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) DMI_MATCH(DMI_BOARD_NAME, "apu2")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* APU2 w/ mainline BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .ident = "apu2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu2")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* APU3 w/ legacy BIOS < 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .ident = "apu3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) DMI_MATCH(DMI_BOARD_NAME, "APU3")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* APU3 w/ legacy BIOS >= 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .ident = "apu3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) DMI_MATCH(DMI_BOARD_NAME, "apu3")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* APU3 w/ mainline BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .ident = "apu3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu3")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* APU4 w/ legacy BIOS < 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .ident = "apu4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) DMI_MATCH(DMI_BOARD_NAME, "APU4")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* APU4 w/ legacy BIOS >= 4.0.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .ident = "apu4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) DMI_MATCH(DMI_BOARD_NAME, "apu4")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* APU4 w/ mainline BIOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .ident = "apu4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu4")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .driver_data = (void *)&board_apu2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static struct platform_device *apu_gpio_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct platform_device *apu_leds_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static struct platform_device *apu_keys_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static struct platform_device * __init apu_create_pdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) const void *pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) size_t sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) pdev = platform_device_register_resndata(NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) PLATFORM_DEVID_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (IS_ERR(pdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int __init apu_board_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) const struct dmi_system_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) id = dmi_first_match(apu_gpio_dmi_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pr_err("failed to detect APU board via DMI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) gpiod_add_lookup_table(&gpios_led_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) gpiod_add_lookup_table(&gpios_key_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) apu_gpio_pdev = apu_create_pdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) AMD_FCH_GPIO_DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) id->driver_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) sizeof(struct amd_fch_gpio_pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) apu_leds_pdev = apu_create_pdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "leds-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) &apu2_leds_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sizeof(apu2_leds_pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) apu_keys_pdev = apu_create_pdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) "gpio-keys-polled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) &apu2_keys_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) sizeof(apu2_keys_pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static void __exit apu_board_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) gpiod_remove_lookup_table(&gpios_led_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) gpiod_remove_lookup_table(&gpios_key_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) platform_device_unregister(apu_keys_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) platform_device_unregister(apu_leds_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) platform_device_unregister(apu_gpio_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) module_init(apu_board_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) module_exit(apu_board_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LEDs/keys driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) MODULE_ALIAS("platform:pcengines-apuv2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME " platform:leds-gpio platform:gpio_keys_polled");