linux/arch/x86/platform/geode/net5501.c
<<
>>
Prefs
   1/*
   2 * System Specific setup for Soekris net5501
   3 * At the moment this means setup of GPIO control of LEDs and buttons
   4 * on net5501 boards.
   5 *
   6 *
   7 * Copyright (C) 2008-2009 Tower Technologies
   8 * Written by Alessandro Zummo <a.zummo@towertech.it>
   9 *
  10 * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
  11 * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
  12 *                and Philip Prindeville <philipp@redfish-solutions.com>
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License version 2
  16 * as published by the Free Software Foundation.
  17 */
  18
  19#include <linux/kernel.h>
  20#include <linux/init.h>
  21#include <linux/io.h>
  22#include <linux/string.h>
  23#include <linux/leds.h>
  24#include <linux/platform_device.h>
  25#include <linux/gpio.h>
  26#include <linux/input.h>
  27#include <linux/gpio_keys.h>
  28
  29#include <asm/geode.h>
  30
  31#define BIOS_REGION_BASE                0xffff0000
  32#define BIOS_REGION_SIZE                0x00010000
  33
  34static struct gpio_keys_button net5501_gpio_buttons[] = {
  35        {
  36                .code = KEY_RESTART,
  37                .gpio = 24,
  38                .active_low = 1,
  39                .desc = "Reset button",
  40                .type = EV_KEY,
  41                .wakeup = 0,
  42                .debounce_interval = 100,
  43                .can_disable = 0,
  44        }
  45};
  46static struct gpio_keys_platform_data net5501_buttons_data = {
  47        .buttons = net5501_gpio_buttons,
  48        .nbuttons = ARRAY_SIZE(net5501_gpio_buttons),
  49        .poll_interval = 20,
  50};
  51
  52static struct platform_device net5501_buttons_dev = {
  53        .name = "gpio-keys-polled",
  54        .id = 1,
  55        .dev = {
  56                .platform_data = &net5501_buttons_data,
  57        }
  58};
  59
  60static struct gpio_led net5501_leds[] = {
  61        {
  62                .name = "net5501:1",
  63                .gpio = 6,
  64                .default_trigger = "default-on",
  65                .active_low = 0,
  66        },
  67};
  68
  69static struct gpio_led_platform_data net5501_leds_data = {
  70        .num_leds = ARRAY_SIZE(net5501_leds),
  71        .leds = net5501_leds,
  72};
  73
  74static struct platform_device net5501_leds_dev = {
  75        .name = "leds-gpio",
  76        .id = -1,
  77        .dev.platform_data = &net5501_leds_data,
  78};
  79
  80static struct platform_device *net5501_devs[] __initdata = {
  81        &net5501_buttons_dev,
  82        &net5501_leds_dev,
  83};
  84
  85static void __init register_net5501(void)
  86{
  87        /* Setup LED control through leds-gpio driver */
  88        platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs));
  89}
  90
  91struct net5501_board {
  92        u16     offset;
  93        u16     len;
  94        char    *sig;
  95};
  96
  97static struct net5501_board __initdata boards[] = {
  98        { 0xb7b, 7, "net5501" },        /* net5501 v1.33/1.33c */
  99        { 0xb1f, 7, "net5501" },        /* net5501 v1.32i */
 100};
 101
 102static bool __init net5501_present(void)
 103{
 104        int i;
 105        unsigned char *rombase, *bios;
 106        bool found = false;
 107
 108        rombase = ioremap(BIOS_REGION_BASE, BIOS_REGION_SIZE - 1);
 109        if (!rombase) {
 110                printk(KERN_ERR "%s: failed to get rombase\n", KBUILD_MODNAME);
 111                return found;
 112        }
 113
 114        bios = rombase + 0x20;  /* null terminated */
 115
 116        if (memcmp(bios, "comBIOS", 7))
 117                goto unmap;
 118
 119        for (i = 0; i < ARRAY_SIZE(boards); i++) {
 120                unsigned char *model = rombase + boards[i].offset;
 121
 122                if (!memcmp(model, boards[i].sig, boards[i].len)) {
 123                        printk(KERN_INFO "%s: system is recognized as \"%s\"\n",
 124                               KBUILD_MODNAME, model);
 125
 126                        found = true;
 127                        break;
 128                }
 129        }
 130
 131unmap:
 132        iounmap(rombase);
 133        return found;
 134}
 135
 136static int __init net5501_init(void)
 137{
 138        if (!is_geode())
 139                return 0;
 140
 141        if (!net5501_present())
 142                return 0;
 143
 144        register_net5501();
 145
 146        return 0;
 147}
 148device_initcall(net5501_init);
 149