summaryrefslogtreecommitdiffstats
path: root/arch/unicore32/kernel/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/unicore32/kernel/gpio.c')
-rw-r--r--arch/unicore32/kernel/gpio.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c
new file mode 100644
index 000000000000..cb12ec39552c
--- /dev/null
+++ b/arch/unicore32/kernel/gpio.c
@@ -0,0 +1,122 @@
+/*
+ * linux/arch/unicore32/kernel/gpio.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ * Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* in FPGA, no GPIO support */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_LEDS
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+
+static const struct gpio_led puv3_gpio_leds[] = {
+ { .name = "cpuhealth", .gpio = GPO_CPU_HEALTH, .active_low = 0,
+ .default_trigger = "heartbeat", },
+ { .name = "hdd_led", .gpio = GPO_HDD_LED, .active_low = 1,
+ .default_trigger = "ide-disk", },
+};
+
+static const struct gpio_led_platform_data puv3_gpio_led_data = {
+ .num_leds = ARRAY_SIZE(puv3_gpio_leds),
+ .leds = (void *) puv3_gpio_leds,
+};
+
+static struct platform_device puv3_gpio_gpio_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = (void *) &puv3_gpio_led_data,
+ }
+};
+
+static int __init puv3_gpio_leds_init(void)
+{
+ platform_device_register(&puv3_gpio_gpio_leds);
+ return 0;
+}
+
+device_initcall(puv3_gpio_leds_init);
+#endif
+
+static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ return readl(GPIO_GPLR) & GPIO_GPIO(offset);
+}
+
+static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (value)
+ writel(GPIO_GPIO(offset), GPIO_GPSR);
+ else
+ writel(GPIO_GPIO(offset), GPIO_GPCR);
+}
+
+static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ writel(readl(GPIO_GPDR) & ~GPIO_GPIO(offset), GPIO_GPDR);
+ local_irq_restore(flags);
+ return 0;
+}
+
+static int puv3_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ puv3_gpio_set(chip, offset, value);
+ writel(readl(GPIO_GPDR) | GPIO_GPIO(offset), GPIO_GPDR);
+ local_irq_restore(flags);
+ return 0;
+}
+
+static struct gpio_chip puv3_gpio_chip = {
+ .label = "gpio",
+ .direction_input = puv3_direction_input,
+ .direction_output = puv3_direction_output,
+ .set = puv3_gpio_set,
+ .get = puv3_gpio_get,
+ .base = 0,
+ .ngpio = GPIO_MAX + 1,
+};
+
+void __init puv3_init_gpio(void)
+{
+ writel(GPIO_DIR, GPIO_GPDR);
+#if defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919) \
+ || defined(CONFIG_PUV3_DB0913)
+ gpio_set_value(GPO_WIFI_EN, 1);
+ gpio_set_value(GPO_HDD_LED, 1);
+ gpio_set_value(GPO_VGA_EN, 1);
+ gpio_set_value(GPO_LCD_EN, 1);
+ gpio_set_value(GPO_CAM_PWR_EN, 0);
+ gpio_set_value(GPO_LCD_VCC_EN, 1);
+ gpio_set_value(GPO_SOFT_OFF, 1);
+ gpio_set_value(GPO_BT_EN, 1);
+ gpio_set_value(GPO_FAN_ON, 0);
+ gpio_set_value(GPO_SPKR, 0);
+ gpio_set_value(GPO_CPU_HEALTH, 1);
+ gpio_set_value(GPO_LAN_SEL, 1);
+/*
+ * DO NOT modify the GPO_SET_V1 and GPO_SET_V2 in kernel
+ * gpio_set_value(GPO_SET_V1, 1);
+ * gpio_set_value(GPO_SET_V2, 1);
+ */
+#endif
+ gpiochip_add(&puv3_gpio_chip);
+}