diff options
-rw-r--r-- | arch/blackfin/include/asm/gpio.h | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 22 | ||||
-rw-r--r-- | arch/blackfin/mach-bf538/ext-gpio.c | 37 | ||||
-rw-r--r-- | arch/blackfin/mach-bf538/include/mach/gpio.h | 3 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc_modes.S | 35 |
5 files changed, 65 insertions, 36 deletions
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index d061620..5a25856 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -119,6 +119,10 @@ struct gpio_port_t { #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 diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index bcf8cf6..16d7ebf 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -118,6 +118,9 @@ static struct str_ident { #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) @@ -604,6 +607,11 @@ void bfin_gpio_pm_hibernate_suspend(void) { 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); @@ -625,6 +633,10 @@ void bfin_gpio_pm_hibernate_suspend(void) 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); } @@ -632,6 +644,11 @@ void bfin_gpio_pm_hibernate_restore(void) { 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); @@ -653,6 +670,11 @@ void bfin_gpio_pm_hibernate_restore(void) 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); } diff --git a/arch/blackfin/mach-bf538/ext-gpio.c b/arch/blackfin/mach-bf538/ext-gpio.c index 180b125..471a9b1 100644 --- a/arch/blackfin/mach-bf538/ext-gpio.c +++ b/arch/blackfin/mach-bf538/ext-gpio.c @@ -1,7 +1,7 @@ /* * 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. */ @@ -121,3 +121,38 @@ static int __init bf538_extgpio_setup(void) 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 diff --git a/arch/blackfin/mach-bf538/include/mach/gpio.h b/arch/blackfin/mach-bf538/include/mach/gpio.h index 8a5beee..3561c7d 100644 --- a/arch/blackfin/mach-bf538/include/mach/gpio.h +++ b/arch/blackfin/mach-bf538/include/mach/gpio.h @@ -8,7 +8,10 @@ #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 diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S index 1a1c092..fa0df0a 100644 --- a/arch/blackfin/mach-common/dpmc_modes.S +++ b/arch/blackfin/mach-common/dpmc_modes.S @@ -459,24 +459,6 @@ ENTRY(_do_hibernate) 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); @@ -777,23 +759,6 @@ ENTRY(_do_hibernate) 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) |