linux/arch/x86/platform/geode/net5501.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * System Specific setup for Soekris net5501
   4 * At the moment this means setup of GPIO control of LEDs and buttons
   5 * on net5501 boards.
   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
  15#include <linux/kernel.h>
  16#include <linux/init.h>
  17#include <linux/io.h>
  18#include <linux/string.h>
  19#include <linux/leds.h>
  20#include <linux/platform_device.h>
  21#include <linux/input.h>
  22#include <linux/gpio_keys.h>
  23#include <linux/gpio/machine.h>
  24
  25#include <asm/geode.h>
  26
  27#define BIOS_REGION_BASE                0xffff0000
  28#define BIOS_REGION_SIZE                0x00010000
  29
  30static struct gpio_keys_button net5501_gpio_buttons[] = {
  31        {
  32                .code = KEY_RESTART,
  33                .gpio = 24,
  34                .active_low = 1,
  35                .desc = "Reset button",
  36                .type = EV_KEY,
  37                .wakeup = 0,
  38                .debounce_interval = 100,
  39                .can_disable = 0,
  40        }
  41};
  42static struct gpio_keys_platform_data net5501_buttons_data = {
  43        .buttons = net5501_gpio_buttons,
  44        .nbuttons = ARRAY_SIZE(net5501_gpio_buttons),
  45        .poll_interval = 20,
  46};
  47
  48static struct platform_device net5501_buttons_dev = {
  49        .name = "gpio-keys-polled",
  50        .id = 1,
  51        .dev = {
  52                .platform_data = &net5501_buttons_data,
  53        }
  54};
  55
  56static struct gpio_led net5501_leds[] = {
  57        {
  58                .name = "net5501:1",
  59                .default_trigger = "default-on",
  60        },
  61};
  62
  63static struct gpio_led_platform_data net5501_leds_data = {
  64        .num_leds = ARRAY_SIZE(net5501_leds),
  65        .leds = net5501_leds,
  66};
  67
  68static struct gpiod_lookup_table net5501_leds_gpio_table = {
  69        .dev_id = "leds-gpio",
  70        .table = {
  71                /* The Geode GPIOs should be on the CS5535 companion chip */
  72                GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_HIGH),
  73                { }
  74        },
  75};
  76
  77static struct platform_device net5501_leds_dev = {
  78        .name = "leds-gpio",
  79        .id = -1,
  80        .dev.platform_data = &net5501_leds_data,
  81};
  82
  83static struct platform_device *net5501_devs[] __initdata = {
  84        &net5501_buttons_dev,
  85        &net5501_leds_dev,
  86};
  87
  88static void __init register_net5501(void)
  89{
  90        /* Setup LED control through leds-gpio driver */
  91        gpiod_add_lookup_table(&net5501_leds_gpio_table);
  92        platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs));
  93}
  94
  95struct net5501_board {
  96        u16     offset;
  97        u16     len;
  98        char    *sig;
  99};
 100
 101static struct net5501_board __initdata boards[] = {
 102        { 0xb7b, 7, "net5501" },        /* net5501 v1.33/1.33c */
 103        { 0xb1f, 7, "net5501" },        /* net5501 v1.32i */
 104};
 105
 106static bool __init net5501_present(void)
 107{
 108        int i;
 109        unsigned char *rombase, *bios;
 110        bool found = false;
 111
 112        rombase = ioremap(BIOS_REGION_BASE, BIOS_REGION_SIZE - 1);
 113        if (!rombase) {
 114                printk(KERN_ERR "%s: failed to get rombase\n", KBUILD_MODNAME);
 115                return found;
 116        }
 117
 118        bios = rombase + 0x20;  /* null terminated */
 119
 120        if (memcmp(bios, "comBIOS", 7))
 121                goto unmap;
 122
 123        for (i = 0; i < ARRAY_SIZE(boards); i++) {
 124                unsigned char *model = rombase + boards[i].offset;
 125
 126                if (!memcmp(model, boards[i].sig, boards[i].len)) {
 127                        printk(KERN_INFO "%s: system is recognized as \"%s\"\n",
 128                               KBUILD_MODNAME, model);
 129
 130                        found = true;
 131                        break;
 132                }
 133        }
 134
 135unmap:
 136        iounmap(rombase);
 137        return found;
 138}
 139
 140static int __init net5501_init(void)
 141{
 142        if (!is_geode())
 143                return 0;
 144
 145        if (!net5501_present())
 146                return 0;
 147
 148        register_net5501();
 149
 150        return 0;
 151}
 152device_initcall(net5501_init);
 153