1 // SPDX-License-Identifier: GPL-2.0-only
3 * System Specific setup for PCEngines ALIX.
4 * At the moment this means setup of GPIO control of LEDs
5 * on Alix.2/3/6 boards.
7 * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
8 * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
9 * and Philip Prindeville <philipp@redfish-solutions.com>
11 * TODO: There are large similarities with leds-net5501.c
12 * by Alessandro Zummo <a.zummo@towertech.it>
13 * In the future leds-net5501.c should be migrated over to platform
16 #include <linux/kernel.h>
17 #include <linux/init.h>
19 #include <linux/string.h>
20 #include <linux/moduleparam.h>
21 #include <linux/dmi.h>
23 #include <asm/geode.h>
25 #include "geode-common.h"
27 #define BIOS_SIGNATURE_TINYBIOS 0xf0000
28 #define BIOS_SIGNATURE_COREBOOT 0x500
29 #define BIOS_REGION_SIZE 0x10000
32 * This driver is not modular, but to keep back compatibility
33 * with existing use cases, continuing with module_param is
34 * the easiest way forward.
36 static bool force
= 0;
37 module_param(force
, bool, 0444);
38 /* FIXME: Award bios is not automatically detected as Alix platform */
39 MODULE_PARM_DESC(force
, "Force detection as ALIX.2/ALIX.3 platform");
41 static const struct geode_led alix_leds
[] __initconst
= {
47 static void __init
register_alix(void)
49 geode_create_restart_key(24);
50 geode_create_leds("alix", alix_leds
, ARRAY_SIZE(alix_leds
));
53 static bool __init
alix_present(unsigned long bios_phys
,
57 const size_t bios_len
= BIOS_REGION_SIZE
;
58 const char *bios_virt
;
64 printk(KERN_NOTICE
"%s: forced to skip BIOS test, "
65 "assume system is ALIX.2/ALIX.3\n",
70 bios_virt
= phys_to_virt(bios_phys
);
71 scan_end
= bios_virt
+ bios_len
- (alix_sig_len
+ 2);
72 for (p
= bios_virt
; p
< scan_end
; p
++) {
76 if (memcmp(p
, alix_sig
, alix_sig_len
) != 0)
79 memcpy(name
, p
, sizeof(name
));
81 /* remove the first \0 character from string */
82 a
= strchr(name
, '\0');
86 /* cut the string at a newline */
87 a
= strchr(name
, '\r');
91 tail
= p
+ alix_sig_len
;
92 if ((tail
[0] == '2' || tail
[0] == '3' || tail
[0] == '6')) {
94 "%s: system is recognized as \"%s\"\n",
95 KBUILD_MODNAME
, name
);
103 static bool __init
alix_present_dmi(void)
105 const char *vendor
, *product
;
107 vendor
= dmi_get_system_info(DMI_SYS_VENDOR
);
108 if (!vendor
|| strcmp(vendor
, "PC Engines"))
111 product
= dmi_get_system_info(DMI_PRODUCT_NAME
);
112 if (!product
|| (strcmp(product
, "ALIX.2D") && strcmp(product
, "ALIX.6")))
115 printk(KERN_INFO
"%s: system is recognized as \"%s %s\"\n",
116 KBUILD_MODNAME
, vendor
, product
);
121 static int __init
alix_init(void)
123 const char tinybios_sig
[] = "PC Engines ALIX.";
124 const char coreboot_sig
[] = "PC Engines\0ALIX.";
129 if (alix_present(BIOS_SIGNATURE_TINYBIOS
, tinybios_sig
, sizeof(tinybios_sig
) - 1) ||
130 alix_present(BIOS_SIGNATURE_COREBOOT
, coreboot_sig
, sizeof(coreboot_sig
) - 1) ||
136 device_initcall(alix_init
);