Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * System Specific setup for Soekris net5501
0004  * At the moment this means setup of GPIO control of LEDs and buttons
0005  * on net5501 boards.
0006  *
0007  * Copyright (C) 2008-2009 Tower Technologies
0008  * Written by Alessandro Zummo <a.zummo@towertech.it>
0009  *
0010  * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
0011  * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
0012  *                and Philip Prindeville <philipp@redfish-solutions.com>
0013  */
0014 
0015 #include <linux/kernel.h>
0016 #include <linux/init.h>
0017 #include <linux/io.h>
0018 #include <linux/string.h>
0019 #include <linux/leds.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/input.h>
0022 #include <linux/gpio_keys.h>
0023 #include <linux/gpio/machine.h>
0024 
0025 #include <asm/geode.h>
0026 
0027 #define BIOS_REGION_BASE        0xffff0000
0028 #define BIOS_REGION_SIZE        0x00010000
0029 
0030 static struct gpio_keys_button net5501_gpio_buttons[] = {
0031     {
0032         .code = KEY_RESTART,
0033         .gpio = 24,
0034         .active_low = 1,
0035         .desc = "Reset button",
0036         .type = EV_KEY,
0037         .wakeup = 0,
0038         .debounce_interval = 100,
0039         .can_disable = 0,
0040     }
0041 };
0042 static struct gpio_keys_platform_data net5501_buttons_data = {
0043     .buttons = net5501_gpio_buttons,
0044     .nbuttons = ARRAY_SIZE(net5501_gpio_buttons),
0045     .poll_interval = 20,
0046 };
0047 
0048 static struct platform_device net5501_buttons_dev = {
0049     .name = "gpio-keys-polled",
0050     .id = 1,
0051     .dev = {
0052         .platform_data = &net5501_buttons_data,
0053     }
0054 };
0055 
0056 static struct gpio_led net5501_leds[] = {
0057     {
0058         .name = "net5501:1",
0059         .default_trigger = "default-on",
0060     },
0061 };
0062 
0063 static struct gpio_led_platform_data net5501_leds_data = {
0064     .num_leds = ARRAY_SIZE(net5501_leds),
0065     .leds = net5501_leds,
0066 };
0067 
0068 static struct gpiod_lookup_table net5501_leds_gpio_table = {
0069     .dev_id = "leds-gpio",
0070     .table = {
0071         /* The Geode GPIOs should be on the CS5535 companion chip */
0072         GPIO_LOOKUP_IDX("cs5535-gpio", 6, NULL, 0, GPIO_ACTIVE_HIGH),
0073         { }
0074     },
0075 };
0076 
0077 static struct platform_device net5501_leds_dev = {
0078     .name = "leds-gpio",
0079     .id = -1,
0080     .dev.platform_data = &net5501_leds_data,
0081 };
0082 
0083 static struct platform_device *net5501_devs[] __initdata = {
0084     &net5501_buttons_dev,
0085     &net5501_leds_dev,
0086 };
0087 
0088 static void __init register_net5501(void)
0089 {
0090     /* Setup LED control through leds-gpio driver */
0091     gpiod_add_lookup_table(&net5501_leds_gpio_table);
0092     platform_add_devices(net5501_devs, ARRAY_SIZE(net5501_devs));
0093 }
0094 
0095 struct net5501_board {
0096     u16 offset;
0097     u16 len;
0098     char    *sig;
0099 };
0100 
0101 static struct net5501_board __initdata boards[] = {
0102     { 0xb7b, 7, "net5501" },    /* net5501 v1.33/1.33c */
0103     { 0xb1f, 7, "net5501" },    /* net5501 v1.32i */
0104 };
0105 
0106 static bool __init net5501_present(void)
0107 {
0108     int i;
0109     unsigned char *rombase, *bios;
0110     bool found = false;
0111 
0112     rombase = ioremap(BIOS_REGION_BASE, BIOS_REGION_SIZE - 1);
0113     if (!rombase) {
0114         printk(KERN_ERR "%s: failed to get rombase\n", KBUILD_MODNAME);
0115         return found;
0116     }
0117 
0118     bios = rombase + 0x20;  /* null terminated */
0119 
0120     if (memcmp(bios, "comBIOS", 7))
0121         goto unmap;
0122 
0123     for (i = 0; i < ARRAY_SIZE(boards); i++) {
0124         unsigned char *model = rombase + boards[i].offset;
0125 
0126         if (!memcmp(model, boards[i].sig, boards[i].len)) {
0127             printk(KERN_INFO "%s: system is recognized as \"%s\"\n",
0128                    KBUILD_MODNAME, model);
0129 
0130             found = true;
0131             break;
0132         }
0133     }
0134 
0135 unmap:
0136     iounmap(rombase);
0137     return found;
0138 }
0139 
0140 static int __init net5501_init(void)
0141 {
0142     if (!is_geode())
0143         return 0;
0144 
0145     if (!net5501_present())
0146         return 0;
0147 
0148     register_net5501();
0149 
0150     return 0;
0151 }
0152 device_initcall(net5501_init);