Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 177256
b: refs/heads/master
c: 621dd24
h: refs/heads/master
v: v3
  • Loading branch information
Michael Hennerich authored and Mike Frysinger committed Dec 15, 2009
1 parent 91288f6 commit 9512814
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 46fe23ac39a0cdc4272946c1e3f9ff4fd5765a5b
refs/heads/master: 621dd2474399237ca556a54037c3b8557e80d021
5 changes: 5 additions & 0 deletions trunk/arch/blackfin/include/asm/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ struct gpio_port_t {
};
#endif

#ifdef BFIN_SPECIAL_GPIO_BANKS
void bfin_special_gpio_free(unsigned gpio);
int bfin_special_gpio_request(unsigned gpio, const char *label);
#endif

#ifdef CONFIG_PM

unsigned int bfin_pm_standby_setup(void);
Expand Down
97 changes: 97 additions & 0 deletions trunk/arch/blackfin/kernel/bfin_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ u8 pmux_offset[][16] = {
};
# endif

#elif defined(BF538_FAMILY)
static unsigned short * const port_fer[] = {
(unsigned short *) PORTCIO_FER,
(unsigned short *) PORTDIO_FER,
(unsigned short *) PORTEIO_FER,
};
#endif

static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
Expand Down Expand Up @@ -163,6 +169,27 @@ static int cmp_label(unsigned short ident, const char *label)

static void port_setup(unsigned gpio, unsigned short usage)
{
#if defined(BF538_FAMILY)
/*
* BF538/9 Port C,D and E are special.
* Inverted PORT_FER polarity on CDE and no PORF_FER on F
* Regular PORT F GPIOs are handled here, CDE are exclusively
* managed by GPIOLIB
*/

if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
return;

gpio -= MAX_BLACKFIN_GPIOS;

if (usage == GPIO_USAGE)
*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
else
*port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
SSYNC();
return;
#endif

if (check_gpio(gpio))
return;

Expand Down Expand Up @@ -981,6 +1008,76 @@ void bfin_gpio_free(unsigned gpio)
}
EXPORT_SYMBOL(bfin_gpio_free);

#ifdef BFIN_SPECIAL_GPIO_BANKS
static unsigned short reserved_special_gpio_map[gpio_bank(MAX_RESOURCES)];

int bfin_special_gpio_request(unsigned gpio, const char *label)
{
unsigned long flags;

local_irq_save_hw(flags);

/*
* Allow that the identical GPIO can
* be requested from the same driver twice
* Do nothing and return -
*/

if (cmp_label(gpio, label) == 0) {
local_irq_restore_hw(flags);
return 0;
}

if (unlikely(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
local_irq_restore_hw(flags);
printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
gpio, get_label(gpio));

return -EBUSY;
}
if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
local_irq_restore_hw(flags);
printk(KERN_ERR
"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
gpio, get_label(gpio));

return -EBUSY;
}

reserved_special_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
reserved_peri_map[gpio_bank(gpio)] |= gpio_bit(gpio);

set_label(gpio, label);
local_irq_restore_hw(flags);
port_setup(gpio, GPIO_USAGE);

return 0;
}
EXPORT_SYMBOL(bfin_special_gpio_request);

void bfin_special_gpio_free(unsigned gpio)
{
unsigned long flags;

might_sleep();

local_irq_save_hw(flags);

if (unlikely(!(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
gpio_error(gpio);
local_irq_restore_hw(flags);
return;
}

reserved_special_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
reserved_peri_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
set_label(gpio, "free");
local_irq_restore_hw(flags);
}
EXPORT_SYMBOL(bfin_special_gpio_free);
#endif


int bfin_gpio_irq_request(unsigned gpio, const char *label)
{
unsigned long flags;
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/blackfin/mach-bf538/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
#

obj-y := ints-priority.o dma.o
obj-$(CONFIG_GPIOLIB) += ext-gpio.o
123 changes: 123 additions & 0 deletions trunk/arch/blackfin/mach-bf538/ext-gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
*
* Copyright 2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/

#include <linux/module.h>
#include <linux/err.h>
#include <asm/blackfin.h>
#include <asm/gpio.h>
#include <asm/portmux.h>

#define DEFINE_REG(reg, off) \
static inline u16 read_##reg(void __iomem *port) \
{ return bfin_read16(port + off); } \
static inline void write_##reg(void __iomem *port, u16 v) \
{ bfin_write16(port + off, v); }

DEFINE_REG(PORTIO, 0x00)
DEFINE_REG(PORTIO_CLEAR, 0x10)
DEFINE_REG(PORTIO_SET, 0x20)
DEFINE_REG(PORTIO_DIR, 0x40)
DEFINE_REG(PORTIO_INEN, 0x50)

static void __iomem *gpio_chip_to_mmr(struct gpio_chip *chip)
{
switch (chip->base) {
default: /* not really needed, but keeps gcc happy */
case GPIO_PC0: return (void __iomem *)PORTCIO;
case GPIO_PD0: return (void __iomem *)PORTDIO;
case GPIO_PE0: return (void __iomem *)PORTEIO;
}
}

static int bf538_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
void __iomem *port = gpio_chip_to_mmr(chip);
return !!(read_PORTIO(port) & (1u << gpio));
}

static void bf538_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
{
void __iomem *port = gpio_chip_to_mmr(chip);
if (value)
write_PORTIO_SET(port, (1u << gpio));
else
write_PORTIO_CLEAR(port, (1u << gpio));
}

static int bf538_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
void __iomem *port = gpio_chip_to_mmr(chip);
write_PORTIO_DIR(port, read_PORTIO_DIR(port) & ~(1u << gpio));
write_PORTIO_INEN(port, read_PORTIO_INEN(port) | (1u << gpio));
return 0;
}

static int bf538_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
{
void __iomem *port = gpio_chip_to_mmr(chip);
write_PORTIO_INEN(port, read_PORTIO_INEN(port) & ~(1u << gpio));
bf538_gpio_set_value(port, gpio, value);
write_PORTIO_DIR(port, read_PORTIO_DIR(port) | (1u << gpio));
return 0;
}

static int bf538_gpio_request(struct gpio_chip *chip, unsigned gpio)
{
return bfin_special_gpio_request(chip->base + gpio, chip->label);
}

static void bf538_gpio_free(struct gpio_chip *chip, unsigned gpio)
{
return bfin_special_gpio_free(chip->base + gpio);
}

/* We don't set the irq fields as these banks cannot generate interrupts */

static struct gpio_chip bf538_portc_chip = {
.label = "GPIO-PC",
.direction_input = bf538_gpio_direction_input,
.get = bf538_gpio_get_value,
.direction_output = bf538_gpio_direction_output,
.set = bf538_gpio_set_value,
.request = bf538_gpio_request,
.free = bf538_gpio_free,
.base = GPIO_PC0,
.ngpio = GPIO_PC9 - GPIO_PC0 + 1,
};

static struct gpio_chip bf538_portd_chip = {
.label = "GPIO-PD",
.direction_input = bf538_gpio_direction_input,
.get = bf538_gpio_get_value,
.direction_output = bf538_gpio_direction_output,
.set = bf538_gpio_set_value,
.request = bf538_gpio_request,
.free = bf538_gpio_free,
.base = GPIO_PD0,
.ngpio = GPIO_PD13 - GPIO_PD0 + 1,
};

static struct gpio_chip bf538_porte_chip = {
.label = "GPIO-PE",
.direction_input = bf538_gpio_direction_input,
.get = bf538_gpio_get_value,
.direction_output = bf538_gpio_direction_output,
.set = bf538_gpio_set_value,
.request = bf538_gpio_request,
.free = bf538_gpio_free,
.base = GPIO_PE0,
.ngpio = GPIO_PE15 - GPIO_PE0 + 1,
};

static int __init bf538_extgpio_setup(void)
{
return gpiochip_add(&bf538_portc_chip) |
gpiochip_add(&bf538_portd_chip) |
gpiochip_add(&bf538_porte_chip);
}
arch_initcall(bf538_extgpio_setup);
42 changes: 21 additions & 21 deletions trunk/arch/blackfin/mach-bf538/include/mach/defBF539.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,31 +468,31 @@
/* General-Purpose Ports (0xFFC01500 - 0xFFC015FF) */

/* GPIO Port C Register Names */
#define GPIO_C_CNFG 0xFFC01500 /* GPIO Pin Port C Configuration Register */
#define GPIO_C_D 0xFFC01510 /* GPIO Pin Port C Data Register */
#define GPIO_C_C 0xFFC01520 /* Clear GPIO Pin Port C Register */
#define GPIO_C_S 0xFFC01530 /* Set GPIO Pin Port C Register */
#define GPIO_C_T 0xFFC01540 /* Toggle GPIO Pin Port C Register */
#define GPIO_C_DIR 0xFFC01550 /* GPIO Pin Port C Direction Register */
#define GPIO_C_INEN 0xFFC01560 /* GPIO Pin Port C Input Enable Register */
#define PORTCIO_FER 0xFFC01500 /* GPIO Pin Port C Configuration Register */
#define PORTCIO 0xFFC01510 /* GPIO Pin Port C Data Register */
#define PORTCIO_CLEAR 0xFFC01520 /* Clear GPIO Pin Port C Register */
#define PORTCIO_SET 0xFFC01530 /* Set GPIO Pin Port C Register */
#define PORTCIO_TOGGLE 0xFFC01540 /* Toggle GPIO Pin Port C Register */
#define PORTCIO_DIR 0xFFC01550 /* GPIO Pin Port C Direction Register */
#define PORTCIO_INEN 0xFFC01560 /* GPIO Pin Port C Input Enable Register */

/* GPIO Port D Register Names */
#define GPIO_D_CNFG 0xFFC01504 /* GPIO Pin Port D Configuration Register */
#define GPIO_D_D 0xFFC01514 /* GPIO Pin Port D Data Register */
#define GPIO_D_C 0xFFC01524 /* Clear GPIO Pin Port D Register */
#define GPIO_D_S 0xFFC01534 /* Set GPIO Pin Port D Register */
#define GPIO_D_T 0xFFC01544 /* Toggle GPIO Pin Port D Register */
#define GPIO_D_DIR 0xFFC01554 /* GPIO Pin Port D Direction Register */
#define GPIO_D_INEN 0xFFC01564 /* GPIO Pin Port D Input Enable Register */
#define PORTDIO_FER 0xFFC01504 /* GPIO Pin Port D Configuration Register */
#define PORTDIO 0xFFC01514 /* GPIO Pin Port D Data Register */
#define PORTDIO_CLEAR 0xFFC01524 /* Clear GPIO Pin Port D Register */
#define PORTDIO_SET 0xFFC01534 /* Set GPIO Pin Port D Register */
#define PORTDIO_TOGGLE 0xFFC01544 /* Toggle GPIO Pin Port D Register */
#define PORTDIO_DIR 0xFFC01554 /* GPIO Pin Port D Direction Register */
#define PORTDIO_INEN 0xFFC01564 /* GPIO Pin Port D Input Enable Register */

/* GPIO Port E Register Names */
#define GPIO_E_CNFG 0xFFC01508 /* GPIO Pin Port E Configuration Register */
#define GPIO_E_D 0xFFC01518 /* GPIO Pin Port E Data Register */
#define GPIO_E_C 0xFFC01528 /* Clear GPIO Pin Port E Register */
#define GPIO_E_S 0xFFC01538 /* Set GPIO Pin Port E Register */
#define GPIO_E_T 0xFFC01548 /* Toggle GPIO Pin Port E Register */
#define GPIO_E_DIR 0xFFC01558 /* GPIO Pin Port E Direction Register */
#define GPIO_E_INEN 0xFFC01568 /* GPIO Pin Port E Input Enable Register */
#define PORTEIO_FER 0xFFC01508 /* GPIO Pin Port E Configuration Register */
#define PORTEIO 0xFFC01518 /* GPIO Pin Port E Data Register */
#define PORTEIO_CLEAR 0xFFC01528 /* Clear GPIO Pin Port E Register */
#define PORTEIO_SET 0xFFC01538 /* Set GPIO Pin Port E Register */
#define PORTEIO_TOGGLE 0xFFC01548 /* Toggle GPIO Pin Port E Register */
#define PORTEIO_DIR 0xFFC01558 /* GPIO Pin Port E Direction Register */
#define PORTEIO_INEN 0xFFC01568 /* GPIO Pin Port E Input Enable Register */

/* DMA Controller 1 Traffic Control Registers (0xFFC01B00 - 0xFFC01BFF) */

Expand Down
7 changes: 2 additions & 5 deletions trunk/arch/blackfin/mach-bf538/include/mach/gpio.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
/*
* Copyright (C) 2008 Analog Devices Inc.
* Copyright (C) 2008-2009 Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/


#ifndef _MACH_GPIO_H_
#define _MACH_GPIO_H_

/* FIXME:
* For now only support PORTF GPIOs.
* PORT C,D and E are for peripheral usage only
*/
#define MAX_BLACKFIN_GPIOS 16
#define BFIN_SPECIAL_GPIO_BANKS 3

#define GPIO_PF0 0 /* PF */
#define GPIO_PF1 1
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/blackfin/mach-bf538/include/mach/portmux.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#ifndef _MACH_PORTMUX_H_
#define _MACH_PORTMUX_H_

#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
#define MAX_RESOURCES 64

#define P_TMR2 (P_DONTCARE)
#define P_TMR1 (P_DONTCARE)
Expand Down
30 changes: 30 additions & 0 deletions trunk/arch/blackfin/mach-common/dpmc_modes.S
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,21 @@ ENTRY(_do_hibernate)
PM_SYS_PUSH(EBIU_FCTL)
#endif

#ifdef PORTCIO_FER
PM_SYS_PUSH16(PORTCIO_DIR)
PM_SYS_PUSH16(PORTCIO_INEN)
PM_SYS_PUSH16(PORTCIO)
PM_SYS_PUSH16(PORTCIO_FER)
PM_SYS_PUSH16(PORTDIO_DIR)
PM_SYS_PUSH16(PORTDIO_INEN)
PM_SYS_PUSH16(PORTDIO)
PM_SYS_PUSH16(PORTDIO_FER)
PM_SYS_PUSH16(PORTEIO_DIR)
PM_SYS_PUSH16(PORTEIO_INEN)
PM_SYS_PUSH16(PORTEIO)
PM_SYS_PUSH16(PORTEIO_FER)
#endif

PM_SYS_PUSH16(SYSCR)

/* Save Core MMRs */
Expand Down Expand Up @@ -716,6 +731,21 @@ ENTRY(_do_hibernate)
P0.L = lo(PLL_CTL);
PM_SYS_POP16(SYSCR)

#ifdef PORTCIO_FER
PM_SYS_POP16(PORTEIO_FER)
PM_SYS_POP16(PORTEIO)
PM_SYS_POP16(PORTEIO_INEN)
PM_SYS_POP16(PORTEIO_DIR)
PM_SYS_POP16(PORTDIO_FER)
PM_SYS_POP16(PORTDIO)
PM_SYS_POP16(PORTDIO_INEN)
PM_SYS_POP16(PORTDIO_DIR)
PM_SYS_POP16(PORTCIO_FER)
PM_SYS_POP16(PORTCIO)
PM_SYS_POP16(PORTCIO_INEN)
PM_SYS_POP16(PORTCIO_DIR)
#endif

#ifdef EBIU_FCTL
PM_SYS_POP(EBIU_FCTL)
PM_SYS_POP(EBIU_MODE)
Expand Down

0 comments on commit 9512814

Please sign in to comment.