Hi,

I've been running voyage 0.9.5 & kernel 3.14.12 on PCEngines APU board for a long time
without any problem.
Last week I got my first APU-2 board and I migrated my system to it.
I experienced system freezings at the end of the boot process some times, and many
kernel (3.14.12) crashes during the reboot and halt,

---
[ 352.370331] INFO: rcu_sched self-detected stall on CPU { 3} (t=60000 jiffies g=6765 c=6764 q=3054)
[  352.379509] sending NMI to all CPUs:
[  352.383105] NMI backtrace for cpu 3
[ 352.386626] CPU: 3 PID: 5664 Comm: postdrop Not tainted 3.14.12-iGetech #1
[  352.393571] Hardware name: PC Engines apu2/apu2, BIOS 88a4f96 03/07/2016
[ 352.400298] task: ffff8800d81020d0 ti: ffff8800d819c000 task.ti: ffff8800d819c000 [ 352.407807] RIP: 0010:[<ffffffff811d863b>] [<ffffffff811d863b>] delay_tsc+0xf/0x4b
[  352.415532] RSP: 0018:ffff88011ed83ae0  EFLAGS: 00000807
...

I updated my voyage 0.9.5 to kernel 4.1.6 version. Now there is NO crashes during reboot and halt
but I still have freezings at the end of the boot process few times.

Is it going to help migrating to voyage 0.10.0? does anyone have long experience using APU-2 and
any version of voyage linux and kernel?

PD: I'm running on a mSATA drive.

BTW: I've created a patch for the kernel 4.1.6 to use the 3 front LEDs on top of a GPIO driver (also included) for the front LEDs and the front PUSH BUTTON, which replaces the existing LED driver in the 4.1.6 that, I think, only
works for the 3 LEDs.


--
Jordi Ferrer
Cap Àrea I+D+i
Mòbil:  634 631 625  |  Ext. 2005
iGetech Innova SL  |  C/Bòsnia, 6-8  |  17800 - Olot, Girona
Tel. (+34) 972 264 667  |  http://www.igetech.com

--- config-4.1.6	2016-09-30 16:11:43.365420541 +0200
+++ config-4.1.6-gpio-leds-apu2	2016-09-30 16:17:00.717407464 +0200
@@ -2652,6 +2652,7 @@
 # CONFIG_GPIO_IT8761E is not set
 # CONFIG_GPIO_LYNXPOINT is not set
 CONFIG_GPIO_FCH=y
+CONFIG_GPIO_APU2=y
 # CONFIG_GPIO_SCH is not set
 # CONFIG_GPIO_SCH311X is not set
 # CONFIG_GPIO_VX855 is not set
@@ -4178,7 +4179,7 @@
 # CONFIG_LEDS_BLINKM is not set
 # CONFIG_LEDS_PM8941_WLED is not set
 CONFIG_LEDS_APU=y
-CONFIG_LEDS_APU2=m
+CONFIG_LEDS_APU2=y
 
 #
 # LED Triggers
diff -Naur linux-source-4.1.6-voyage/drivers/gpio/Kconfig linux-source-4.1.6-iGetech/drivers/gpio/Kconfig
--- linux-source-4.1.6-voyage/drivers/gpio/Kconfig	2015-11-02 08:48:44.000000000 +0100
+++ linux-source-4.1.6-iGetech/drivers/gpio/Kconfig	2016-09-28 18:21:54.374434660 +0200
@@ -256,6 +256,18 @@
 	  use them with care. For instance, PC Engines APU board users
 	  should only use GPIO 187 (in), 189 (out), 190 (out), 191 (out).
 
+config GPIO_APU2
+	tristate "PC Engines APU2 AMD FCH GPIO"
+	depends on PCI && X86
+	default m
+	help
+	  GPIO interface for PC Engines APU2 AMD FCH Controller.
+	  Available GPIOs are 32, 57-59.
+
+	  Part of GPIOs is usually occupied by BIOS for it's internal needs, so
+	  use them with care. For instance, PC Engines APU2 board users
+	  should only use GPIO 32 (in), 57 (out), 58 (out), 59 (out).
+
 config GPIO_MM_LANTIQ
 	bool "Lantiq Memory mapped GPIOs"
 	depends on LANTIQ && SOC_XWAY
diff -Naur linux-source-4.1.6-voyage/drivers/gpio/Makefile linux-source-4.1.6-iGetech/drivers/gpio/Makefile
--- linux-source-4.1.6-voyage/drivers/gpio/Makefile	2015-11-02 08:48:44.000000000 +0100
+++ linux-source-4.1.6-iGetech/drivers/gpio/Makefile	2016-09-28 18:23:24.707435453 +0200
@@ -33,6 +33,7 @@
 obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_FCH)		+= gpio-fch.o
+obj-$(CONFIG_GPIO_APU2)		+= gpio-apu2.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
 obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
diff -Naur linux-source-4.1.6-voyage/drivers/gpio/gpio-apu2.c linux-source-4.1.6-iGetech/drivers/gpio/gpio-apu2.c
--- linux-source-4.1.6-voyage/drivers/gpio/gpio-apu2.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-source-4.1.6-iGetech/drivers/gpio/gpio-apu2.c	2016-09-28 18:20:51.334434106 +0200
@@ -0,0 +1,253 @@
+/*
+ *  gpio-apu2.c - AMD FCH GPIO support for PC-Engines APU2 board
+ *
+ *  Copyright (c) 2015  Carsten Spiess <fli4l at carsten-spiess.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/version.h>
+
+#define DEVNAME                 "gpio-apu2"
+
+#define FCH_ACPI_MMIO_BASE      0xFED80000
+#define FCH_GPIO_BASE           (FCH_ACPI_MMIO_BASE + 0x1500)
+#define FCH_GPIO_SIZE           0x300
+
+#define APU2_NUM_GPIO           4
+
+#define GPIO_BIT_DIR            23
+#define GPIO_BIT_WRITE          22
+#define GPIO_BIT_READ           16
+
+/* internal variables */
+static struct pci_dev *gpio_apu2_pci;
+static DEFINE_SPINLOCK ( gpio_lock);
+
+/* the watchdog platform device */
+static struct platform_device *gpio_apu2_platform_device;
+
+static const struct pci_device_id gpio_apu2_pci_tbl[] ={
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID, PCI_ANY_ID},
+	{ 0, } /* End of list */
+};
+MODULE_DEVICE_TABLE ( pci, gpio_apu2_pci_tbl);
+
+/* EGPIO89=GPIO32, AGPIO68=GPIO57, AGPIO69=GPIO58, AGPIO70=GPIO59 */
+static u8 gpio_offset[APU2_NUM_GPIO] = {89, 68, 69, 70};
+
+static void __iomem *gpio_addr[APU2_NUM_GPIO] = {NULL, NULL, NULL, NULL};
+
+static int gpio_apu2_get_dir (struct gpio_chip *chip, unsigned offset)
+{
+	u32 val;
+
+	val = ~ioread32 (gpio_addr[offset]);
+
+	return (val >> GPIO_BIT_DIR) & 1;
+}
+
+static int gpio_apu2_dir_in (struct gpio_chip *gc, unsigned offset)
+{
+	u32 val;
+
+	spin_lock_bh (&gpio_lock);
+
+	val = ioread32 (gpio_addr[offset]);
+	val &= ~BIT(GPIO_BIT_DIR);
+	iowrite32 (val, gpio_addr[offset]);
+
+	spin_unlock_bh (&gpio_lock);
+
+	return 0;
+}
+
+static int gpio_apu2_dir_out (struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	u32 val;
+
+	spin_lock_bh (&gpio_lock);
+
+	val = ioread32 (gpio_addr[offset]);
+	val |= BIT(GPIO_BIT_DIR);
+	iowrite32 (val, gpio_addr[offset]);
+
+	spin_unlock_bh (&gpio_lock);
+
+	return 0;
+}
+
+static int gpio_apu2_get_data (struct gpio_chip *chip, unsigned offset)
+{
+	u32 val;
+
+	val = ioread32 (gpio_addr[offset]);
+
+	return (val >> GPIO_BIT_READ) & 1;
+}
+
+static void gpio_apu2_set_data (struct gpio_chip *chip, unsigned offset, int value)
+{
+	u32 val;
+
+	spin_lock_bh (&gpio_lock);
+
+	val = ioread32 (gpio_addr[offset]);
+
+	if (value)
+		val |= BIT(GPIO_BIT_WRITE);
+	else
+		val &= ~BIT(GPIO_BIT_WRITE);
+
+	iowrite32 (val, gpio_addr[offset]);
+
+	spin_unlock_bh (&gpio_lock);
+}
+
+static struct gpio_chip gpio_apu2_chip = {
+	.label = DEVNAME,
+	.owner = THIS_MODULE,
+	.base = -1,
+	.ngpio = APU2_NUM_GPIO,
+	.get_direction = gpio_apu2_get_dir,
+	.direction_input = gpio_apu2_dir_in,
+	.direction_output = gpio_apu2_dir_out,
+	.get = gpio_apu2_get_data,
+	.set = gpio_apu2_set_data,
+};
+
+/*
+ *
+ */
+static int gpio_apu2_probe (struct platform_device *dev)
+{
+	int ret = 0;
+	int i;
+	struct pci_dev *pci_dev = NULL;
+	u32 pmval;
+
+	/* Match the PCI device */
+	for_each_pci_dev (pci_dev) {
+		if (pci_match_id (gpio_apu2_pci_tbl, pci_dev) != NULL) {
+			gpio_apu2_pci = pci_dev;
+			break;
+		}
+	}
+
+	if (!gpio_apu2_pci)
+		return -ENODEV;
+
+	pr_info ("PCI Revision ID: 0x%x\n", gpio_apu2_pci->revision);
+
+	/* Determine type of southbridge chipset */
+	if (gpio_apu2_pci->revision < 0x40) {
+		return -EACCES;
+	}
+
+	/* Request memory region for GPIO's */
+	if (!devm_request_mem_region (&dev->dev, FCH_GPIO_BASE,
+		FCH_GPIO_SIZE, DEVNAME)){
+		pr_err ("request GPIO mem region failed\n");
+		return -ENXIO;
+	}
+
+	/* Map IO's for GPIO's */
+	for (i = 0; i < APU2_NUM_GPIO; i++) {
+		gpio_addr[i] = devm_ioremap (&dev->dev,
+			FCH_GPIO_BASE + (gpio_offset[i] * sizeof (u32)), sizeof (u32));
+		if (!gpio_addr[i]) {
+			pr_err ("map GPIO%d address failed\n", gpio_offset[i]);
+			return -ENXIO;
+		}
+	}
+
+	gpio_apu2_chip.dev = &dev->dev;
+	ret = gpiochip_add (&gpio_apu2_chip);
+	if (ret) {
+		pr_err ("adding gpiochip failed\n");
+	}
+
+	return ret;
+}
+
+static int gpio_apu2_remove (struct platform_device *dev)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+	int ret;
+	ret = gpiochip_remove (&gpio_apu2_chip);
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) */
+	gpiochip_remove (&gpio_apu2_chip);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) */
+	return 0;
+}
+
+static struct platform_driver gpio_apu2_driver = {
+	.probe = gpio_apu2_probe,
+	.remove = gpio_apu2_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DEVNAME
+	}
+};
+
+static int __init gpio_apu2_init (void)
+{
+	int err;
+
+	pr_info ("load APU2 GPIO driver module\n");
+
+	err = platform_driver_register (&gpio_apu2_driver);
+	if (err)
+		goto exit;
+
+	gpio_apu2_platform_device = platform_device_register_simple (DEVNAME, -1, NULL, 0);
+	if (IS_ERR(gpio_apu2_platform_device)) {
+		err = PTR_ERR(gpio_apu2_platform_device);
+		goto exit_driver;
+	}
+
+	pr_info ("APU2 GPIO driver module loaded\n");
+	return 0;
+
+exit_driver:
+	platform_driver_unregister (&gpio_apu2_driver);
+exit:
+	return err;
+}
+
+static void __exit gpio_apu2_exit (void)
+{
+	platform_device_unregister (gpio_apu2_platform_device);
+	platform_driver_unregister (&gpio_apu2_driver);
+	pr_info ("APU2 GPIO driver module unloaded\n");
+}
+
+MODULE_AUTHOR ("Carsten Spiess <fli4l at carsten-spiess.de>");
+MODULE_DESCRIPTION("GPIO driver for AMD FCH on PC-Engines APU2");
+MODULE_LICENSE("GPL");
+
+module_init (gpio_apu2_init);
+module_exit (gpio_apu2_exit);
diff -Naur linux-source-4.1.6-voyage/drivers/leds/Kconfig linux-source-4.1.6-iGetech/drivers/leds/Kconfig
--- linux-source-4.1.6-voyage/drivers/leds/Kconfig	2016-06-01 12:55:11.000000000 +0200
+++ linux-source-4.1.6-iGetech/drivers/leds/Kconfig	2016-09-28 18:26:24.576437032 +0200
@@ -547,10 +547,16 @@
 	  (GPIO_FCH & LEDS_GPIO) to actually use the LEDs
 
 config LEDS_APU2
-	tristate "LED Support for the PC Engines APU2 series LEDs"
+	bool "PC Engines APU2 GPIO-based LED Driver"
 	depends on LEDS_CLASS
-	help
-	  This option enables support for the PCEngines APU programmable LEDs.
+	depends on GPIOLIB
+	select GPIO_APU2
+	select LEDS_GPIO
+	---help---
+	  This option sets up LEDs using GPIO control on PC Engines APU2 board.
+
+	  Note: You must still enable the drivers for GPIO and LED support
+	  (GPIO_APU2 & LEDS_GPIO) to actually use the LEDs
 
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
diff -Naur linux-source-4.1.6-voyage/drivers/leds/leds-apu2.c linux-source-4.1.6-iGetech/drivers/leds/leds-apu2.c
--- linux-source-4.1.6-voyage/drivers/leds/leds-apu2.c	2016-06-01 12:55:11.000000000 +0200
+++ linux-source-4.1.6-iGetech/drivers/leds/leds-apu2.c	2016-09-28 18:21:10.802434277 +0200
@@ -1,201 +1,139 @@
 /*
- * LEDs driver for PCEngines apu2
+ * Set up PC Engines APU2 board front LEDs using GPIOLIB and GPIO-APU2
+ * drivers. This driver is based on the leds-apu.
  *
- * Copyright (C) 2016 Christian Herzog <dad...@daduke.org>, based on
- * Petr Leibman's leds-alix
- * Based on leds-wrap.c
+ * Copyright (C) 2016 Jordi Ferrer Plana <jfer...@igetech.com>
  *
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU General Public License 2 as published
+ * by the Free Software Foundation.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-#include <asm/io.h>
 #include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/dmi.h>
+
+/* Module Information */
+#define APU2_MODULE_NAME		"leds-apu2"
+#define APU2_MODULE_VER			"0.1"
+#define APU2_DRIVER_NAME		(APU2_MODULE_NAME " (v" APU2_MODULE_VER ")")
 
-#define DRVNAME		"apu2-led"
-
-#define FCH_ACPI_MMIO_BASE      0xFED80000
-#define FCH_GPIO_BASE           (FCH_ACPI_MMIO_BASE + 0x1500)
-#define FCH_GPIO_SIZE           0x300
-#define GPIO_BIT_WRITE          22
-static DEFINE_SPINLOCK ( gpio_lock);
-
-#define APU2_NUM_GPIO            4
-static u8 gpio_offset[APU2_NUM_GPIO] = {89, 68, 69, 70};
-
-static void __iomem *gpio_addr[APU2_NUM_GPIO] = {NULL, NULL, NULL, NULL};
-
-static struct platform_device *pdev;
-
-static void apu2_led_set_1(struct led_classdev *led_cdev, enum led_brightness value) {
-	u32 val;
-
-	spin_lock_bh (&gpio_lock);
-
-	val = ioread32 (gpio_addr[1]);
-
-	if (value)
-		val &= ~BIT(GPIO_BIT_WRITE);
-	else
-		val |= BIT(GPIO_BIT_WRITE);
-
-	iowrite32 (val, gpio_addr[1]);
-
-	spin_unlock_bh (&gpio_lock);
-}
-
-static void apu2_led_set_2(struct led_classdev *led_cdev, enum led_brightness value) {
-	u32 val;
-
-	spin_lock_bh (&gpio_lock);
-
-	val = ioread32 (gpio_addr[2]);
-
-	if (value)
-		val &= ~BIT(GPIO_BIT_WRITE);
-	else
-		val |= BIT(GPIO_BIT_WRITE);
-
-	iowrite32 (val, gpio_addr[2]);
-
-	spin_unlock_bh (&gpio_lock);
-}
-
-static void apu2_led_set_3(struct led_classdev *led_cdev, enum led_brightness value) {
-	u32 val;
-
-	spin_lock_bh (&gpio_lock);
-
-	val = ioread32 (gpio_addr[3]);
-
-	if (value)
-		val &= ~BIT(GPIO_BIT_WRITE);
-	else
-		val |= BIT(GPIO_BIT_WRITE);
-
-	iowrite32 (val, gpio_addr[3]);
-
-	spin_unlock_bh (&gpio_lock);
-}
+static struct gpio_keys_button apu2_gpio_buttons[] = {
+	{
+		.code			= KEY_RESTART,
+		.gpio			= 508,
+		.active_low		= 1,
+		.desc			= "Reset button",
+		.type			= EV_KEY,
+		.wakeup			= 0,
+		.debounce_interval	= 100,
+		.can_disable		= 0,
+	}
+};
+static struct gpio_keys_platform_data apu2_buttons_data = {
+	.buttons			= apu2_gpio_buttons,
+	.nbuttons			= ARRAY_SIZE(apu2_gpio_buttons),
+	.poll_interval			= 20,
+};
 
-static struct led_classdev apu2_led_1 = {
-	.name		= "apu2:1",
-	.brightness_set	= apu2_led_set_1,
+static struct platform_device apu2_buttons_dev = {
+	.name				= "gpio-keys-polled",
+	.id				= 1,
+	.dev = {
+		.platform_data		= &apu2_buttons_data,
+	}
 };
 
-static struct led_classdev apu2_led_2 = {
-	.name		= "apu2:2",
-	.brightness_set	= apu2_led_set_2,
+static struct gpio_led apu2_leds[] = {
+	{
+		.name = "apu2:1",
+		.gpio = 509,
+		.default_trigger = "default-on",
+		.active_low = 1,
+	},
+	{
+		.name = "apu2:2",
+		.gpio = 510,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+	{
+		.name = "apu2:3",
+		.gpio = 511,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
 };
 
-static struct led_classdev apu2_led_3 = {
-	.name		= "apu2:3",
-	.brightness_set	= apu2_led_set_3,
+static struct gpio_led_platform_data apu2_leds_data = {
+	.num_leds = ARRAY_SIZE(apu2_leds),
+	.leds = apu2_leds,
 };
 
-#ifdef CONFIG_PM
-static int apu2_led_suspend(struct platform_device *dev,
-		pm_message_t state)
-{
-	led_classdev_suspend(&apu2_led_1);
-	led_classdev_suspend(&apu2_led_2);
-	led_classdev_suspend(&apu2_led_3);
-	return 0;
-}
+static struct platform_device apu2_leds_dev = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev.platform_data = &apu2_leds_data,
+};
 
-static int apu2_led_resume(struct platform_device *dev)
-{
-	led_classdev_resume(&apu2_led_1);
-	led_classdev_resume(&apu2_led_2);
-	led_classdev_resume(&apu2_led_3);
-	return 0;
-}
-#else
-#define apu2_led_suspend NULL
-#define apu2_led_resume NULL
-#endif
+static struct __initdata platform_device *apu2_devs[] = {
+	&apu2_buttons_dev,
+	&apu2_leds_dev,
+};
 
-static int apu2_led_probe(struct platform_device *pdev)
+static void __init register_apu2(void)
 {
-	int ret;
-
-	ret = led_classdev_register(&pdev->dev, &apu2_led_1);
-	if (ret == 0)
-	{
-		ret = led_classdev_register(&pdev->dev, &apu2_led_2);
-		if (ret >= 0)
-		{
-			ret = led_classdev_register(&pdev->dev, &apu2_led_3);
-			if (ret < 0)
-				led_classdev_unregister(&apu2_led_2);
-		}
-		if (ret < 0)
-			led_classdev_unregister(&apu2_led_1);
-	}
-	return ret;
+	/* Setup LED control through leds-gpio driver */
+	platform_add_devices(apu2_devs, ARRAY_SIZE(apu2_devs));
 }
 
-static int apu2_led_remove(struct platform_device *pdev)
+static bool __init apu2_present_dmi(void)
 {
-	led_classdev_unregister(&apu2_led_1);
-	led_classdev_unregister(&apu2_led_2);
-	led_classdev_unregister(&apu2_led_3);
-	
-	return 0;
-}
+	const char *vendor, *product;
 
-static struct platform_driver apu2_led_driver = {
-	.probe		= apu2_led_probe,
-	.remove		= apu2_led_remove,
-	.suspend	= apu2_led_suspend,
-	.resume		= apu2_led_resume,
-	.driver		= {
-	.name		= DRVNAME,
-	.owner		= THIS_MODULE,
-	},
-};
-
-static int __init apu2_led_init(void)
-{
-	int ret;
-	int i;
+	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+	if (!vendor || strcmp(vendor, "PC Engines"))
+		return false;
 
-	ret = platform_driver_register(&apu2_led_driver);
-	if (ret < 0)
-		goto out;
-
-	pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
-	if (IS_ERR(pdev)) {
-		ret = PTR_ERR(pdev);
-		platform_driver_unregister(&apu2_led_driver);
-		goto out;
-	}
+	product = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!product || (strcmp(product, "apu2")))
+		return false;
 
-	for (i = 0; i < APU2_NUM_GPIO; i++) {
-		gpio_addr[i] = ioremap ( FCH_GPIO_BASE + (gpio_offset[i] * sizeof (u32)), sizeof (u32));
-	}
+	printk(KERN_INFO "%s: System is recognized as \"%s %s\"\n",
+		APU2_DRIVER_NAME, vendor, product);
 
-out:
-	return ret;
+	return true;
 }
 
-static void __exit apu2_led_exit(void)
+static int __init apu2_init(void)
 {
-	platform_device_unregister(pdev);
-	platform_driver_unregister(&apu2_led_driver);
+	/* Check for APU2 board */
+	printk(KERN_INFO "Loading driver %s.\n", APU2_DRIVER_NAME);
+	if (apu2_present_dmi())
+		register_apu2();
+
+	return 0;
 }
 
-module_init(apu2_led_init);
-module_exit(apu2_led_exit);
+module_init(apu2_init);
 
-MODULE_AUTHOR("Christian Herzog");
-MODULE_DESCRIPTION("PCEngines apu2 LED driver");
+MODULE_AUTHOR("Jordi Ferrer Plana <jfer...@igetech.com>");
+MODULE_DESCRIPTION("PC Engines APU2 GPIO-based LED Driver");
 MODULE_LICENSE("GPL");
_______________________________________________
Voyage-linux mailing list
Voyage-linux@list.voyage.hk
http://list.voyage.hk/mailman/listinfo/voyage-linux

Reply via email to