1d4f3e350SEd Wildgoose /* 2d4f3e350SEd Wildgoose * System Specific setup for PCEngines ALIX. 3d4f3e350SEd Wildgoose * At the moment this means setup of GPIO control of LEDs 4d4f3e350SEd Wildgoose * on Alix.2/3/6 boards. 5d4f3e350SEd Wildgoose * 6d4f3e350SEd Wildgoose * 7d4f3e350SEd Wildgoose * Copyright (C) 2008 Constantin Baranov <const@mimas.ru> 8d4f3e350SEd Wildgoose * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com> 9d4f3e350SEd Wildgoose * 10d4f3e350SEd Wildgoose * TODO: There are large similarities with leds-net5501.c 11d4f3e350SEd Wildgoose * by Alessandro Zummo <a.zummo@towertech.it> 12d4f3e350SEd Wildgoose * In the future leds-net5501.c should be migrated over to platform 13d4f3e350SEd Wildgoose * 14d4f3e350SEd Wildgoose * This program is free software; you can redistribute it and/or modify 15d4f3e350SEd Wildgoose * it under the terms of the GNU General Public License version 2 16d4f3e350SEd Wildgoose * as published by the Free Software Foundation. 17d4f3e350SEd Wildgoose */ 18d4f3e350SEd Wildgoose 19d4f3e350SEd Wildgoose #include <linux/kernel.h> 20d4f3e350SEd Wildgoose #include <linux/init.h> 21d4f3e350SEd Wildgoose #include <linux/io.h> 22d4f3e350SEd Wildgoose #include <linux/string.h> 23d4f3e350SEd Wildgoose #include <linux/module.h> 24d4f3e350SEd Wildgoose #include <linux/leds.h> 25d4f3e350SEd Wildgoose #include <linux/platform_device.h> 26d4f3e350SEd Wildgoose #include <linux/gpio.h> 27d4f3e350SEd Wildgoose 28d4f3e350SEd Wildgoose #include <asm/geode.h> 29d4f3e350SEd Wildgoose 30*476bc001SRusty Russell static bool force = 0; 31d4f3e350SEd Wildgoose module_param(force, bool, 0444); 32d4f3e350SEd Wildgoose /* FIXME: Award bios is not automatically detected as Alix platform */ 33d4f3e350SEd Wildgoose MODULE_PARM_DESC(force, "Force detection as ALIX.2/ALIX.3 platform"); 34d4f3e350SEd Wildgoose 35d4f3e350SEd Wildgoose static struct gpio_led alix_leds[] = { 36d4f3e350SEd Wildgoose { 37d4f3e350SEd Wildgoose .name = "alix:1", 38d4f3e350SEd Wildgoose .gpio = 6, 39d4f3e350SEd Wildgoose .default_trigger = "default-on", 40d4f3e350SEd Wildgoose .active_low = 1, 41d4f3e350SEd Wildgoose }, 42d4f3e350SEd Wildgoose { 43d4f3e350SEd Wildgoose .name = "alix:2", 44d4f3e350SEd Wildgoose .gpio = 25, 45d4f3e350SEd Wildgoose .default_trigger = "default-off", 46d4f3e350SEd Wildgoose .active_low = 1, 47d4f3e350SEd Wildgoose }, 48d4f3e350SEd Wildgoose { 49d4f3e350SEd Wildgoose .name = "alix:3", 50d4f3e350SEd Wildgoose .gpio = 27, 51d4f3e350SEd Wildgoose .default_trigger = "default-off", 52d4f3e350SEd Wildgoose .active_low = 1, 53d4f3e350SEd Wildgoose }, 54d4f3e350SEd Wildgoose }; 55d4f3e350SEd Wildgoose 56d4f3e350SEd Wildgoose static struct gpio_led_platform_data alix_leds_data = { 57d4f3e350SEd Wildgoose .num_leds = ARRAY_SIZE(alix_leds), 58d4f3e350SEd Wildgoose .leds = alix_leds, 59d4f3e350SEd Wildgoose }; 60d4f3e350SEd Wildgoose 61d4f3e350SEd Wildgoose static struct platform_device alix_leds_dev = { 62d4f3e350SEd Wildgoose .name = "leds-gpio", 63d4f3e350SEd Wildgoose .id = -1, 64d4f3e350SEd Wildgoose .dev.platform_data = &alix_leds_data, 65d4f3e350SEd Wildgoose }; 66d4f3e350SEd Wildgoose 67d4f3e350SEd Wildgoose static void __init register_alix(void) 68d4f3e350SEd Wildgoose { 69d4f3e350SEd Wildgoose /* Setup LED control through leds-gpio driver */ 70d4f3e350SEd Wildgoose platform_device_register(&alix_leds_dev); 71d4f3e350SEd Wildgoose } 72d4f3e350SEd Wildgoose 73d4f3e350SEd Wildgoose static int __init alix_present(unsigned long bios_phys, 74d4f3e350SEd Wildgoose const char *alix_sig, 75d4f3e350SEd Wildgoose size_t alix_sig_len) 76d4f3e350SEd Wildgoose { 77d4f3e350SEd Wildgoose const size_t bios_len = 0x00010000; 78d4f3e350SEd Wildgoose const char *bios_virt; 79d4f3e350SEd Wildgoose const char *scan_end; 80d4f3e350SEd Wildgoose const char *p; 81d4f3e350SEd Wildgoose char name[64]; 82d4f3e350SEd Wildgoose 83d4f3e350SEd Wildgoose if (force) { 84d4f3e350SEd Wildgoose printk(KERN_NOTICE "%s: forced to skip BIOS test, " 85d4f3e350SEd Wildgoose "assume system is ALIX.2/ALIX.3\n", 86d4f3e350SEd Wildgoose KBUILD_MODNAME); 87d4f3e350SEd Wildgoose return 1; 88d4f3e350SEd Wildgoose } 89d4f3e350SEd Wildgoose 90d4f3e350SEd Wildgoose bios_virt = phys_to_virt(bios_phys); 91d4f3e350SEd Wildgoose scan_end = bios_virt + bios_len - (alix_sig_len + 2); 92d4f3e350SEd Wildgoose for (p = bios_virt; p < scan_end; p++) { 93d4f3e350SEd Wildgoose const char *tail; 94d4f3e350SEd Wildgoose char *a; 95d4f3e350SEd Wildgoose 96d4f3e350SEd Wildgoose if (memcmp(p, alix_sig, alix_sig_len) != 0) 97d4f3e350SEd Wildgoose continue; 98d4f3e350SEd Wildgoose 99d4f3e350SEd Wildgoose memcpy(name, p, sizeof(name)); 100d4f3e350SEd Wildgoose 101d4f3e350SEd Wildgoose /* remove the first \0 character from string */ 102d4f3e350SEd Wildgoose a = strchr(name, '\0'); 103d4f3e350SEd Wildgoose if (a) 104d4f3e350SEd Wildgoose *a = ' '; 105d4f3e350SEd Wildgoose 106d4f3e350SEd Wildgoose /* cut the string at a newline */ 107d4f3e350SEd Wildgoose a = strchr(name, '\r'); 108d4f3e350SEd Wildgoose if (a) 109d4f3e350SEd Wildgoose *a = '\0'; 110d4f3e350SEd Wildgoose 111d4f3e350SEd Wildgoose tail = p + alix_sig_len; 112d4f3e350SEd Wildgoose if ((tail[0] == '2' || tail[0] == '3')) { 113d4f3e350SEd Wildgoose printk(KERN_INFO 114d4f3e350SEd Wildgoose "%s: system is recognized as \"%s\"\n", 115d4f3e350SEd Wildgoose KBUILD_MODNAME, name); 116d4f3e350SEd Wildgoose return 1; 117d4f3e350SEd Wildgoose } 118d4f3e350SEd Wildgoose } 119d4f3e350SEd Wildgoose 120d4f3e350SEd Wildgoose return 0; 121d4f3e350SEd Wildgoose } 122d4f3e350SEd Wildgoose 123d4f3e350SEd Wildgoose static int __init alix_init(void) 124d4f3e350SEd Wildgoose { 125d4f3e350SEd Wildgoose const char tinybios_sig[] = "PC Engines ALIX."; 126d4f3e350SEd Wildgoose const char coreboot_sig[] = "PC Engines\0ALIX."; 127d4f3e350SEd Wildgoose 128d4f3e350SEd Wildgoose if (!is_geode()) 129d4f3e350SEd Wildgoose return 0; 130d4f3e350SEd Wildgoose 131d4f3e350SEd Wildgoose if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) || 132d4f3e350SEd Wildgoose alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1)) 133d4f3e350SEd Wildgoose register_alix(); 134d4f3e350SEd Wildgoose 135d4f3e350SEd Wildgoose return 0; 136d4f3e350SEd Wildgoose } 137d4f3e350SEd Wildgoose 138d4f3e350SEd Wildgoose module_init(alix_init); 139d4f3e350SEd Wildgoose 140d4f3e350SEd Wildgoose MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>"); 141d4f3e350SEd Wildgoose MODULE_DESCRIPTION("PCEngines ALIX System Setup"); 142d4f3e350SEd Wildgoose MODULE_LICENSE("GPL"); 143