#ifdef BFIN_SPECIAL_GPIO_BANKS
void bfin_special_gpio_free(unsigned gpio);
int bfin_special_gpio_request(unsigned gpio, const char *label);
+# ifdef CONFIG_PM
+void bfin_special_gpio_pm_hibernate_restore(void);
+void bfin_special_gpio_pm_hibernate_suspend(void);
+# endif
#endif
#ifdef CONFIG_PM
#if defined(CONFIG_PM)
static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
+# ifdef BF538_FAMILY
+static unsigned short port_fer_saved[3];
+# endif
#endif
static void gpio_error(unsigned gpio)
{
int i, bank;
+#ifdef BF538_FAMILY
+ for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+ port_fer_saved[i] = *port_fer[i];
+#endif
+
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
}
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+ bfin_special_gpio_pm_hibernate_suspend();
+#endif
+
AWA_DUMMY_READ(maska);
}
{
int i, bank;
+#ifdef BF538_FAMILY
+ for (i = 0; i < ARRAY_SIZE(port_fer_saved); ++i)
+ *port_fer[i] = port_fer_saved[i];
+#endif
+
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
gpio_array[bank]->both = gpio_bank_saved[bank].both;
gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
}
+
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+ bfin_special_gpio_pm_hibernate_restore();
+#endif
+
AWA_DUMMY_READ(maska);
}
/*
* GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
*
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
gpiochip_add(&bf538_porte_chip);
}
arch_initcall(bf538_extgpio_setup);
+
+#ifdef CONFIG_PM
+static struct {
+ u16 data, dir, inen;
+} gpio_bank_saved[3];
+
+static void __iomem * const port_bases[3] = {
+ (void *)PORTCIO,
+ (void *)PORTDIO,
+ (void *)PORTEIO,
+};
+
+void bfin_special_gpio_pm_hibernate_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+ gpio_bank_saved[i].data = read_PORTIO(port_bases[i]);
+ gpio_bank_saved[i].inen = read_PORTIO_INEN(port_bases[i]);
+ gpio_bank_saved[i].dir = read_PORTIO_DIR(port_bases[i]);
+ }
+}
+
+void bfin_special_gpio_pm_hibernate_restore(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
+ write_PORTIO_INEN(port_bases[i], gpio_bank_saved[i].inen);
+ write_PORTIO_SET(port_bases[i],
+ gpio_bank_saved[i].data & gpio_bank_saved[i].dir);
+ write_PORTIO_DIR(port_bases[i], gpio_bank_saved[i].dir);
+ }
+}
+#endif
#define _MACH_GPIO_H_
#define MAX_BLACKFIN_GPIOS 16
+#ifdef CONFIG_GPIOLIB
+/* We only use the special logic with GPIOLIB devices */
#define BFIN_SPECIAL_GPIO_BANKS 3
+#endif
#define GPIO_PF0 0 /* PF */
#define GPIO_PF1 1
PM_PUSH_SYNC(9)
#endif
-#ifdef PORTCIO_FER
- /* 16bit loads can only be done with dregs */
- PM_SYS_PUSH16(0, PORTCIO_DIR)
- PM_SYS_PUSH16(1, PORTCIO_INEN)
- PM_SYS_PUSH16(2, PORTCIO)
- PM_SYS_PUSH16(3, PORTCIO_FER)
- PM_SYS_PUSH16(4, PORTDIO_DIR)
- PM_SYS_PUSH16(5, PORTDIO_INEN)
- PM_SYS_PUSH16(6, PORTDIO)
- PM_SYS_PUSH16(7, PORTDIO_FER)
- PM_PUSH_SYNC(7)
- PM_SYS_PUSH16(0, PORTEIO_DIR)
- PM_SYS_PUSH16(1, PORTEIO_INEN)
- PM_SYS_PUSH16(2, PORTEIO)
- PM_SYS_PUSH16(3, PORTEIO_FER)
- PM_PUSH_SYNC(3)
-#endif
-
/* Save Core MMRs */
I0.H = hi(COREMMR_BASE);
I0.L = lo(COREMMR_BASE);
FP.H = hi(SYSMMR_BASE);
FP.L = lo(SYSMMR_BASE);
-#ifdef PORTCIO_FER
- PM_POP_SYNC(3)
- PM_SYS_POP16(3, PORTEIO_FER)
- PM_SYS_POP16(2, PORTEIO)
- PM_SYS_POP16(1, PORTEIO_INEN)
- PM_SYS_POP16(0, PORTEIO_DIR)
- PM_POP_SYNC(7)
- PM_SYS_POP16(7, PORTDIO_FER)
- PM_SYS_POP16(6, PORTDIO)
- PM_SYS_POP16(5, PORTDIO_INEN)
- PM_SYS_POP16(4, PORTDIO_DIR)
- PM_SYS_POP16(3, PORTCIO_FER)
- PM_SYS_POP16(2, PORTCIO)
- PM_SYS_POP16(1, PORTCIO_INEN)
- PM_SYS_POP16(0, PORTCIO_DIR)
-#endif
-
#ifdef EBIU_FCTL
PM_POP_SYNC(12)
PM_SYS_POP(12, EBIU_FCTL)