summaryrefslogtreecommitdiff
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /arch/blackfin/kernel
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/Makefile3
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c159
2 files changed, 143 insertions, 19 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 703dc7c..735f24e 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
- fixed_code.o reboot.o bfin_dma.o \
+ fixed_code.o reboot.o bfin_gpio.o bfin_dma.o \
exception.o dumpstack.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
@@ -16,7 +16,6 @@ else
obj-y += time.o
endif
-obj-$(CONFIG_GPIO_ADI) += bfin_gpio.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index a017359..ed978f1 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -11,8 +11,11 @@
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/gpio.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
#include <linux/irq.h>
+#include <asm/irq_handler.h>
#if ANOMALY_05000311 || ANOMALY_05000323
enum {
@@ -55,6 +58,19 @@ static struct gpio_port_t * const gpio_array[] = {
(struct gpio_port_t *) FIO0_FLAG_D,
(struct gpio_port_t *) FIO1_FLAG_D,
(struct gpio_port_t *) FIO2_FLAG_D,
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ (struct gpio_port_t *)PORTA_FER,
+ (struct gpio_port_t *)PORTB_FER,
+ (struct gpio_port_t *)PORTC_FER,
+ (struct gpio_port_t *)PORTD_FER,
+ (struct gpio_port_t *)PORTE_FER,
+ (struct gpio_port_t *)PORTF_FER,
+ (struct gpio_port_t *)PORTG_FER,
+# if defined(CONFIG_BF54x)
+ (struct gpio_port_t *)PORTH_FER,
+ (struct gpio_port_t *)PORTI_FER,
+ (struct gpio_port_t *)PORTJ_FER,
+# endif
#else
# error no gpio arrays defined
#endif
@@ -153,6 +169,12 @@ DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM);
inline int check_gpio(unsigned gpio)
{
+#if defined(CONFIG_BF54x)
+ if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
+ || gpio == GPIO_PH14 || gpio == GPIO_PH15
+ || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
+ return -EINVAL;
+#endif
if (gpio >= MAX_BLACKFIN_GPIOS)
return -EINVAL;
return 0;
@@ -190,6 +212,12 @@ static void port_setup(unsigned gpio, unsigned short usage)
else
*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
SSYNC();
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ if (usage == GPIO_USAGE)
+ gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+ SSYNC();
#endif
}
@@ -227,7 +255,7 @@ static int portmux_group_check(unsigned short per)
u16 ident = P_IDENT(per);
u16 function = P_FUNCT2MUX(per);
s8 offset = port_mux[ident];
- u16 m, pmux, pfunc, mask;
+ u16 m, pmux, pfunc;
if (offset < 0)
return 0;
@@ -242,12 +270,10 @@ static int portmux_group_check(unsigned short per)
continue;
if (offset == 1)
- mask = 3;
+ pfunc = (pmux >> offset) & 3;
else
- mask = 1;
-
- pfunc = (pmux >> offset) & mask;
- if (pfunc != (function & mask)) {
+ pfunc = (pmux >> offset) & 1;
+ if (pfunc != function) {
pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n",
ident, function, m, pfunc);
return -EINVAL;
@@ -262,21 +288,43 @@ static void portmux_setup(unsigned short per)
u16 ident = P_IDENT(per);
u16 function = P_FUNCT2MUX(per);
s8 offset = port_mux[ident];
- u16 pmux, mask;
+ u16 pmux;
if (offset == -1)
return;
pmux = bfin_read_PORT_MUX();
- if (offset == 1)
- mask = 3;
+ if (offset != 1)
+ pmux &= ~(1 << offset);
else
- mask = 1;
+ pmux &= ~(3 << 1);
+ pmux |= (function << offset);
+ bfin_write_PORT_MUX(pmux);
+}
+#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+inline void portmux_setup(unsigned short per)
+{
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
+ u32 pmux;
- pmux &= ~(mask << offset);
- pmux |= ((function & mask) << offset);
+ pmux = gpio_array[gpio_bank(ident)]->port_mux;
- bfin_write_PORT_MUX(pmux);
+ pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
+ pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
+
+ gpio_array[gpio_bank(ident)]->port_mux = pmux;
+}
+
+inline u16 get_portmux(unsigned short per)
+{
+ u16 ident = P_IDENT(per);
+ u32 pmux = gpio_array[gpio_bank(ident)]->port_mux;
+ return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
+}
+static int portmux_group_check(unsigned short per)
+{
+ return 0;
}
#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
static int portmux_group_check(unsigned short per)
@@ -331,6 +379,7 @@ static int portmux_group_check(unsigned short per)
}
#endif
+#if !(defined(CONFIG_BF54x) || defined(CONFIG_BF60x))
/***********************************************************
*
* FUNCTIONS: Blackfin General Purpose Ports Access Functions
@@ -523,7 +572,7 @@ static const unsigned int sic_iwr_irqs[] = {
*************************************************************
* MODIFICATION HISTORY :
**************************************************************/
-int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
+int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
{
unsigned long flags;
@@ -542,7 +591,7 @@ int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl)
return 0;
}
-int bfin_gpio_pm_standby_ctrl(unsigned ctrl)
+int bfin_pm_standby_ctrl(unsigned ctrl)
{
u16 bank, mask, i;
@@ -633,6 +682,53 @@ void bfin_gpio_pm_hibernate_restore(void)
#endif
+#else /* CONFIG_BF54x || CONFIG_BF60x */
+#ifdef CONFIG_PM
+
+int bfin_pm_standby_ctrl(unsigned ctrl)
+{
+ return 0;
+}
+
+void bfin_gpio_pm_hibernate_suspend(void)
+{
+ int i, bank;
+
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+ bank = gpio_bank(i);
+
+ gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
+ gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
+ gpio_bank_saved[bank].data = gpio_array[bank]->data;
+ gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
+ gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
+ }
+}
+
+void bfin_gpio_pm_hibernate_restore(void)
+{
+ int i, bank;
+
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+ bank = gpio_bank(i);
+
+ gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
+ gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
+ gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
+ gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+ & gpio_bank_saved[bank].dir;
+ gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
+ }
+}
+#endif
+
+unsigned short get_gpio_dir(unsigned gpio)
+{
+ return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
+}
+EXPORT_SYMBOL(get_gpio_dir);
+
+#endif /* CONFIG_BF54x || CONFIG_BF60x */
/***********************************************************
*
@@ -689,7 +785,11 @@ int peripheral_request(unsigned short per, const char *label)
* be requested and used by several drivers
*/
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
+#else
if (!(per & P_MAYSHARE)) {
+#endif
/*
* Allow that the identical pin function can
* be requested from the same driver twice
@@ -838,9 +938,12 @@ int bfin_gpio_request(unsigned gpio, const char *label)
if (unlikely(is_reserved(gpio_irq, gpio, 1))) {
printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
" (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
- } else { /* Reset POLAR setting when acquiring a gpio for the first time */
+ }
+#if !(defined(CONFIG_BF54x) || defined(CONFIG_BF60x))
+ else { /* Reset POLAR setting when acquiring a gpio for the first time */
set_gpio_polar(gpio, 0);
}
+#endif
reserve(gpio, gpio);
set_label(gpio, label);
@@ -1009,7 +1112,11 @@ void bfin_gpio_irq_free(unsigned gpio)
static inline void __bfin_gpio_direction_input(unsigned gpio)
{
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
+#else
gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
+#endif
gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
}
@@ -1033,7 +1140,17 @@ EXPORT_SYMBOL(bfin_gpio_direction_input);
void bfin_gpio_irq_prepare(unsigned gpio)
{
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ unsigned long flags;
+#endif
+
port_setup(gpio, GPIO_USAGE);
+
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ flags = hard_local_irq_save();
+ __bfin_gpio_direction_input(gpio);
+ hard_local_irq_restore(flags);
+#endif
}
void bfin_gpio_set_value(unsigned gpio, int arg)
@@ -1058,7 +1175,11 @@ int bfin_gpio_direction_output(unsigned gpio, int value)
gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
gpio_set_value(gpio, value);
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
+#else
gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
+#endif
AWA_DUMMY_READ(dir);
hard_local_irq_restore(flags);
@@ -1069,6 +1190,9 @@ EXPORT_SYMBOL(bfin_gpio_direction_output);
int bfin_gpio_get_value(unsigned gpio)
{
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
+ return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
+#else
unsigned long flags;
if (unlikely(get_gpio_edge(gpio))) {
@@ -1081,6 +1205,7 @@ int bfin_gpio_get_value(unsigned gpio)
return ret;
} else
return get_gpio_data(gpio);
+#endif
}
EXPORT_SYMBOL(bfin_gpio_get_value);