0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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
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
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" },
0103 { 0xb1f, 7, "net5501" },
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;
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);