Merge branch 'cleanups' into next

This commit is contained in:
Haavard Skinnemoen
2009-02-23 10:27:15 +01:00
33 changed files with 1258 additions and 635 deletions

View File

@@ -34,7 +34,8 @@ COBJS-y += hsdramc.o
COBJS-y += exception.o
COBJS-y += cache.o
COBJS-y += interrupts.o
COBJS-y += pio.o
COBJS-$(CONFIG_PORTMUX_PIO) += portmux-pio.o
COBJS-$(CONFIG_PORTMUX_GPIO) += portmux-gpio.o
SRCS := $(START-y:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))

View File

@@ -24,7 +24,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)lib$(SOC).a
COBJS := gpio.o clk.o
COBJS := portmux.o clk.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))

View File

@@ -25,6 +25,7 @@
#include <asm/arch/clk.h>
#include <asm/arch/memory-map.h>
#include <asm/arch/portmux.h>
#include "sm.h"
@@ -66,3 +67,27 @@ void clk_init(void)
sm_writel(PM_MCCTRL, SM_BIT(PLLSEL));
#endif
}
unsigned long __gclk_set_rate(unsigned int id, enum gclk_parent parent,
unsigned long rate, unsigned long parent_rate)
{
unsigned long divider;
if (rate == 0 || parent_rate == 0) {
sm_writel(PM_GCCTRL(id), 0);
return 0;
}
divider = (parent_rate + rate / 2) / rate;
if (divider <= 1) {
sm_writel(PM_GCCTRL(id), parent | SM_BIT(CEN));
rate = parent_rate;
} else {
divider = min(255, divider / 2 - 1);
sm_writel(PM_GCCTRL(id), parent | SM_BIT(CEN) | SM_BIT(DIVEN)
| SM_BF(DIV, divider));
rate = parent_rate / (2 * (divider + 1));
}
return rate;
}

View File

@@ -1,199 +0,0 @@
/*
* Copyright (C) 2006 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/chip-features.h>
#include <asm/arch/gpio.h>
#include <asm/arch/memory-map.h>
/*
* Lots of small functions here. We depend on --gc-sections getting
* rid of the ones we don't need.
*/
void gpio_enable_ebi(void)
{
#ifdef CONFIG_SYS_HSDRAMC
#ifndef CONFIG_SYS_SDRAM_16BIT
gpio_select_periph_A(GPIO_PIN_PE0, 0);
gpio_select_periph_A(GPIO_PIN_PE1, 0);
gpio_select_periph_A(GPIO_PIN_PE2, 0);
gpio_select_periph_A(GPIO_PIN_PE3, 0);
gpio_select_periph_A(GPIO_PIN_PE4, 0);
gpio_select_periph_A(GPIO_PIN_PE5, 0);
gpio_select_periph_A(GPIO_PIN_PE6, 0);
gpio_select_periph_A(GPIO_PIN_PE7, 0);
gpio_select_periph_A(GPIO_PIN_PE8, 0);
gpio_select_periph_A(GPIO_PIN_PE9, 0);
gpio_select_periph_A(GPIO_PIN_PE10, 0);
gpio_select_periph_A(GPIO_PIN_PE11, 0);
gpio_select_periph_A(GPIO_PIN_PE12, 0);
gpio_select_periph_A(GPIO_PIN_PE13, 0);
gpio_select_periph_A(GPIO_PIN_PE14, 0);
gpio_select_periph_A(GPIO_PIN_PE15, 0);
#endif
gpio_select_periph_A(GPIO_PIN_PE26, 0);
#endif
}
#ifdef AT32AP700x_CHIP_HAS_USART
void gpio_enable_usart0(void)
{
gpio_select_periph_B(GPIO_PIN_PA8, 0);
gpio_select_periph_B(GPIO_PIN_PA9, 0);
}
void gpio_enable_usart1(void)
{
gpio_select_periph_A(GPIO_PIN_PA17, 0);
gpio_select_periph_A(GPIO_PIN_PA18, 0);
}
void gpio_enable_usart2(void)
{
gpio_select_periph_B(GPIO_PIN_PB26, 0);
gpio_select_periph_B(GPIO_PIN_PB27, 0);
}
void gpio_enable_usart3(void)
{
gpio_select_periph_B(GPIO_PIN_PB17, 0);
gpio_select_periph_B(GPIO_PIN_PB18, 0);
}
#endif
#ifdef AT32AP700x_CHIP_HAS_MACB
void gpio_enable_macb0(void)
{
gpio_select_periph_A(GPIO_PIN_PC3, 0); /* TXD0 */
gpio_select_periph_A(GPIO_PIN_PC4, 0); /* TXD1 */
gpio_select_periph_A(GPIO_PIN_PC7, 0); /* TXEN */
gpio_select_periph_A(GPIO_PIN_PC8, 0); /* TXCK */
gpio_select_periph_A(GPIO_PIN_PC9, 0); /* RXD0 */
gpio_select_periph_A(GPIO_PIN_PC10, 0); /* RXD1 */
gpio_select_periph_A(GPIO_PIN_PC13, 0); /* RXER */
gpio_select_periph_A(GPIO_PIN_PC15, 0); /* RXDV */
gpio_select_periph_A(GPIO_PIN_PC16, 0); /* MDC */
gpio_select_periph_A(GPIO_PIN_PC17, 0); /* MDIO */
#if !defined(CONFIG_RMII)
gpio_select_periph_A(GPIO_PIN_PC0, 0); /* COL */
gpio_select_periph_A(GPIO_PIN_PC1, 0); /* CRS */
gpio_select_periph_A(GPIO_PIN_PC2, 0); /* TXER */
gpio_select_periph_A(GPIO_PIN_PC5, 0); /* TXD2 */
gpio_select_periph_A(GPIO_PIN_PC6, 0); /* TXD3 */
gpio_select_periph_A(GPIO_PIN_PC11, 0); /* RXD2 */
gpio_select_periph_A(GPIO_PIN_PC12, 0); /* RXD3 */
gpio_select_periph_A(GPIO_PIN_PC14, 0); /* RXCK */
gpio_select_periph_A(GPIO_PIN_PC18, 0); /* SPD */
#endif
}
void gpio_enable_macb1(void)
{
gpio_select_periph_B(GPIO_PIN_PD13, 0); /* TXD0 */
gpio_select_periph_B(GPIO_PIN_PD14, 0); /* TXD1 */
gpio_select_periph_B(GPIO_PIN_PD11, 0); /* TXEN */
gpio_select_periph_B(GPIO_PIN_PD12, 0); /* TXCK */
gpio_select_periph_B(GPIO_PIN_PD10, 0); /* RXD0 */
gpio_select_periph_B(GPIO_PIN_PD6, 0); /* RXD1 */
gpio_select_periph_B(GPIO_PIN_PD5, 0); /* RXER */
gpio_select_periph_B(GPIO_PIN_PD4, 0); /* RXDV */
gpio_select_periph_B(GPIO_PIN_PD3, 0); /* MDC */
gpio_select_periph_B(GPIO_PIN_PD2, 0); /* MDIO */
#if !defined(CONFIG_RMII)
gpio_select_periph_B(GPIO_PIN_PC19, 0); /* COL */
gpio_select_periph_B(GPIO_PIN_PC23, 0); /* CRS */
gpio_select_periph_B(GPIO_PIN_PC26, 0); /* TXER */
gpio_select_periph_B(GPIO_PIN_PC27, 0); /* TXD2 */
gpio_select_periph_B(GPIO_PIN_PC28, 0); /* TXD3 */
gpio_select_periph_B(GPIO_PIN_PC29, 0); /* RXD2 */
gpio_select_periph_B(GPIO_PIN_PC30, 0); /* RXD3 */
gpio_select_periph_B(GPIO_PIN_PC24, 0); /* RXCK */
gpio_select_periph_B(GPIO_PIN_PD15, 0); /* SPD */
#endif
}
#endif
#ifdef AT32AP700x_CHIP_HAS_MMCI
void gpio_enable_mmci(void)
{
gpio_select_periph_A(GPIO_PIN_PA10, 0); /* CLK */
gpio_select_periph_A(GPIO_PIN_PA11, 0); /* CMD */
gpio_select_periph_A(GPIO_PIN_PA12, 0); /* DATA0 */
gpio_select_periph_A(GPIO_PIN_PA13, 0); /* DATA1 */
gpio_select_periph_A(GPIO_PIN_PA14, 0); /* DATA2 */
gpio_select_periph_A(GPIO_PIN_PA15, 0); /* DATA3 */
}
#endif
#ifdef AT32AP700x_CHIP_HAS_SPI
void gpio_enable_spi0(unsigned long cs_mask)
{
gpio_select_periph_A(GPIO_PIN_PA0, 0); /* MISO */
gpio_select_periph_A(GPIO_PIN_PA1, 0); /* MOSI */
gpio_select_periph_A(GPIO_PIN_PA2, 0); /* SCK */
/* Set up NPCSx as GPIO outputs, initially high */
if (cs_mask & (1 << 0)) {
gpio_set_value(GPIO_PIN_PA3, 1);
gpio_select_pio(GPIO_PIN_PA3, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 1)) {
gpio_set_value(GPIO_PIN_PA4, 1);
gpio_select_pio(GPIO_PIN_PA4, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 2)) {
gpio_set_value(GPIO_PIN_PA5, 1);
gpio_select_pio(GPIO_PIN_PA5, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 3)) {
gpio_set_value(GPIO_PIN_PA20, 1);
gpio_select_pio(GPIO_PIN_PA20, GPIOF_OUTPUT);
}
}
void gpio_enable_spi1(unsigned long cs_mask)
{
gpio_select_periph_B(GPIO_PIN_PA0, 0); /* MISO */
gpio_select_periph_B(GPIO_PIN_PB1, 0); /* MOSI */
gpio_select_periph_B(GPIO_PIN_PB5, 0); /* SCK */
/* Set up NPCSx as GPIO outputs, initially high */
if (cs_mask & (1 << 0)) {
gpio_set_value(GPIO_PIN_PB2, 1);
gpio_select_pio(GPIO_PIN_PB2, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 1)) {
gpio_set_value(GPIO_PIN_PB3, 1);
gpio_select_pio(GPIO_PIN_PB3, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 2)) {
gpio_set_value(GPIO_PIN_PB4, 1);
gpio_select_pio(GPIO_PIN_PB4, GPIOF_OUTPUT);
}
if (cs_mask & (1 << 3)) {
gpio_set_value(GPIO_PIN_PA27, 1);
gpio_select_pio(GPIO_PIN_PA27, GPIOF_OUTPUT);
}
}
#endif

View File

@@ -0,0 +1,204 @@
/*
* Copyright (C) 2006, 2008 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/chip-features.h>
#include <asm/arch/memory-map.h>
#include <asm/arch/portmux.h>
/*
* Lots of small functions here. We depend on --gc-sections getting
* rid of the ones we don't need.
*/
void portmux_enable_ebi(unsigned int bus_width, unsigned int addr_width,
unsigned long flags, unsigned long drive_strength)
{
unsigned long porte_mask = 0;
if (bus_width > 16)
portmux_select_peripheral(PORTMUX_PORT_E, 0xffff,
PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
if (addr_width > 23)
porte_mask |= (((1 << (addr_width - 23)) - 1) & 7) << 16;
if (flags & PORTMUX_EBI_CS(2))
porte_mask |= 1 << 25;
if (flags & PORTMUX_EBI_CS(4))
porte_mask |= 1 << 21;
if (flags & PORTMUX_EBI_CS(5))
porte_mask |= 1 << 22;
if (flags & (PORTMUX_EBI_CF(0) | PORTMUX_EBI_CF(1)))
porte_mask |= (1 << 19) | (1 << 20) | (1 << 23);
portmux_select_peripheral(PORTMUX_PORT_E, porte_mask,
PORTMUX_FUNC_A, 0);
if (flags & PORTMUX_EBI_NWAIT)
portmux_select_peripheral(PORTMUX_PORT_E, 1 << 24,
PORTMUX_FUNC_A, PORTMUX_PULL_UP);
}
#ifdef AT32AP700x_CHIP_HAS_MACB
void portmux_enable_macb0(unsigned long flags, unsigned long drive_strength)
{
unsigned long portc_mask;
portc_mask = (1 << 3) /* TXD0 */
| (1 << 4) /* TXD1 */
| (1 << 7) /* TXEN */
| (1 << 8) /* TXCK */
| (1 << 9) /* RXD0 */
| (1 << 10) /* RXD1 */
| (1 << 13) /* RXER */
| (1 << 15) /* RXDV */
| (1 << 16) /* MDC */
| (1 << 17); /* MDIO */
if (flags & PORTMUX_MACB_MII)
portc_mask |= (1 << 0) /* COL */
| (1 << 1) /* CRS */
| (1 << 2) /* TXER */
| (1 << 5) /* TXD2 */
| (1 << 6) /* TXD3 */
| (1 << 11) /* RXD2 */
| (1 << 12) /* RXD3 */
| (1 << 14); /* RXCK */
if (flags & PORTMUX_MACB_SPEED)
portc_mask |= (1 << 18);/* SPD */
/* REVISIT: Some pins are probably pure outputs */
portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
}
void portmux_enable_macb1(unsigned long flags, unsigned long drive_strength)
{
unsigned long portc_mask = 0;
unsigned long portd_mask;
portd_mask = (1 << 13) /* TXD0 */
| (1 << 14) /* TXD1 */
| (1 << 11) /* TXEN */
| (1 << 12) /* TXCK */
| (1 << 10) /* RXD0 */
| (1 << 6) /* RXD1 */
| (1 << 5) /* RXER */
| (1 << 4) /* RXDV */
| (1 << 3) /* MDC */
| (1 << 2); /* MDIO */
if (flags & PORTMUX_MACB_MII)
portc_mask = (1 << 19) /* COL */
| (1 << 23) /* CRS */
| (1 << 26) /* TXER */
| (1 << 27) /* TXD2 */
| (1 << 28) /* TXD3 */
| (1 << 29) /* RXD2 */
| (1 << 30) /* RXD3 */
| (1 << 24); /* RXCK */
if (flags & PORTMUX_MACB_SPEED)
portd_mask |= (1 << 15);/* SPD */
/* REVISIT: Some pins are probably pure outputs */
portmux_select_peripheral(PORTMUX_PORT_D, portc_mask,
PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
portmux_select_peripheral(PORTMUX_PORT_C, portc_mask,
PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
}
#endif
#ifdef AT32AP700x_CHIP_HAS_MMCI
void portmux_enable_mmci(unsigned int slot, unsigned long flags,
unsigned long drive_strength)
{
unsigned long mask;
unsigned long portmux_flags = PORTMUX_PULL_UP;
/* First, the common CLK signal. It doesn't need a pull-up */
portmux_select_peripheral(PORTMUX_PORT_A, 1 << 10,
PORTMUX_FUNC_A, 0);
if (flags & PORTMUX_MMCI_EXT_PULLUP)
portmux_flags = 0;
/* Then, the per-slot signals */
switch (slot) {
case 0:
mask = (1 << 11) | (1 << 12); /* CMD and DATA0 */
if (flags & PORTMUX_MMCI_4BIT)
/* DATA1..DATA3 */
mask |= (1 << 13) | (1 << 14) | (1 << 15);
portmux_select_peripheral(PORTMUX_PORT_A, mask,
PORTMUX_FUNC_A, portmux_flags);
break;
case 1:
mask = (1 << 6) | (1 << 7); /* CMD and DATA0 */
if (flags & PORTMUX_MMCI_4BIT)
/* DATA1..DATA3 */
mask |= (1 << 8) | (1 << 9) | (1 << 10);
portmux_select_peripheral(PORTMUX_PORT_B, mask,
PORTMUX_FUNC_B, portmux_flags);
break;
}
}
#endif
#ifdef AT32AP700x_CHIP_HAS_SPI
void portmux_enable_spi0(unsigned long cs_mask, unsigned long drive_strength)
{
unsigned long pin_mask;
/* MOSI and SCK */
portmux_select_peripheral(PORTMUX_PORT_A, (1 << 1) | (1 << 2),
PORTMUX_FUNC_A, 0);
/* MISO may float */
portmux_select_peripheral(PORTMUX_PORT_A, 1 << 0,
PORTMUX_FUNC_A, PORTMUX_BUSKEEPER);
/* Set up NPCSx as GPIO outputs, initially high */
pin_mask = (cs_mask & 7) << 3;
if (cs_mask & (1 << 3))
pin_mask |= 1 << 20;
portmux_select_gpio(PORTMUX_PORT_A, pin_mask,
PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
}
void portmux_enable_spi1(unsigned long cs_mask, unsigned long drive_strength)
{
/* MOSI and SCK */
portmux_select_peripheral(PORTMUX_PORT_B, (1 << 1) | (1 << 5),
PORTMUX_FUNC_B, 0);
/* MISO may float */
portmux_select_peripheral(PORTMUX_PORT_B, 1 << 0,
PORTMUX_FUNC_B, PORTMUX_BUSKEEPER);
/* Set up NPCSx as GPIO outputs, initially high */
portmux_select_gpio(PORTMUX_PORT_B, (cs_mask & 7) << 2,
PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
portmux_select_gpio(PORTMUX_PORT_A, (cs_mask & 8) << (27 - 3),
PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH);
}
#endif

View File

@@ -65,9 +65,6 @@ int cpu_init(void)
sysreg_write(EVBA, (unsigned long)&_evba);
asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET));
if(gclk_init)
gclk_init();
return 0;
}

View File

@@ -1,116 +0,0 @@
/*
* Copyright (C) 2006 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/gpio.h>
#include <asm/arch/memory-map.h>
#include "pio2.h"
void gpio_select_periph_A(unsigned int pin, int use_pullup)
{
void *base = gpio_pin_to_addr(pin);
uint32_t mask = 1 << (pin & 0x1f);
if (!base)
panic("Invalid GPIO pin %u\n", pin);
pio2_writel(base, ASR, mask);
pio2_writel(base, PDR, mask);
if (use_pullup)
pio2_writel(base, PUER, mask);
else
pio2_writel(base, PUDR, mask);
}
void gpio_select_periph_B(unsigned int pin, int use_pullup)
{
void *base = gpio_pin_to_addr(pin);
uint32_t mask = 1 << (pin & 0x1f);
if (!base)
panic("Invalid GPIO pin %u\n", pin);
pio2_writel(base, BSR, mask);
pio2_writel(base, PDR, mask);
if (use_pullup)
pio2_writel(base, PUER, mask);
else
pio2_writel(base, PUDR, mask);
}
void gpio_select_pio(unsigned int pin, unsigned long gpiof_flags)
{
void *base = gpio_pin_to_addr(pin);
uint32_t mask = 1 << (pin & 0x1f);
if (!base)
panic("Invalid GPIO pin %u\n", pin);
if (gpiof_flags & GPIOF_OUTPUT) {
if (gpiof_flags & GPIOF_MULTIDRV)
pio2_writel(base, MDER, mask);
else
pio2_writel(base, MDDR, mask);
pio2_writel(base, PUDR, mask);
pio2_writel(base, OER, mask);
} else {
if (gpiof_flags & GPIOF_PULLUP)
pio2_writel(base, PUER, mask);
else
pio2_writel(base, PUDR, mask);
if (gpiof_flags & GPIOF_DEGLITCH)
pio2_writel(base, IFER, mask);
else
pio2_writel(base, IFDR, mask);
pio2_writel(base, ODR, mask);
}
pio2_writel(base, PER, mask);
}
void gpio_set_value(unsigned int pin, int value)
{
void *base = gpio_pin_to_addr(pin);
uint32_t mask = 1 << (pin & 0x1f);
if (!base)
panic("Invalid GPIO pin %u\n", pin);
if (value)
pio2_writel(base, SODR, mask);
else
pio2_writel(base, CODR, mask);
}
int gpio_get_value(unsigned int pin)
{
void *base = gpio_pin_to_addr(pin);
int value;
if (!base)
panic("Invalid GPIO pin %u\n", pin);
value = pio2_readl(base, PDSR);
return (value >> (pin & 0x1f)) & 1;
}

107
cpu/at32ap/portmux-gpio.c Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2008 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/memory-map.h>
#include <asm/arch/gpio.h>
void portmux_select_peripheral(void *port, unsigned long pin_mask,
enum portmux_function func, unsigned long flags)
{
/* Both pull-up and pull-down set means buskeeper */
if (flags & PORTMUX_PULL_DOWN)
gpio_writel(port, PDERS, pin_mask);
else
gpio_writel(port, PDERC, pin_mask);
if (flags & PORTMUX_PULL_UP)
gpio_writel(port, PUERS, pin_mask);
else
gpio_writel(port, PUERC, pin_mask);
/* Select drive strength */
if (flags & PORTMUX_DRIVE_LOW)
gpio_writel(port, ODCR0S, pin_mask);
else
gpio_writel(port, ODCR0C, pin_mask);
if (flags & PORTMUX_DRIVE_HIGH)
gpio_writel(port, ODCR1S, pin_mask);
else
gpio_writel(port, ODCR1C, pin_mask);
/* Select function */
if (func & PORTMUX_FUNC_B)
gpio_writel(port, PMR0S, pin_mask);
else
gpio_writel(port, PMR0C, pin_mask);
if (func & PORTMUX_FUNC_C)
gpio_writel(port, PMR1S, pin_mask);
else
gpio_writel(port, PMR1C, pin_mask);
/* Disable GPIO (i.e. enable peripheral) */
gpio_writel(port, GPERC, pin_mask);
}
void portmux_select_gpio(void *port, unsigned long pin_mask,
unsigned long flags)
{
/* Both pull-up and pull-down set means buskeeper */
if (flags & PORTMUX_PULL_DOWN)
gpio_writel(port, PDERS, pin_mask);
else
gpio_writel(port, PDERC, pin_mask);
if (flags & PORTMUX_PULL_UP)
gpio_writel(port, PUERS, pin_mask);
else
gpio_writel(port, PUERC, pin_mask);
/* Enable open-drain mode if requested */
if (flags & PORTMUX_OPEN_DRAIN)
gpio_writel(port, ODMERS, pin_mask);
else
gpio_writel(port, ODMERC, pin_mask);
/* Select drive strength */
if (flags & PORTMUX_DRIVE_LOW)
gpio_writel(port, ODCR0S, pin_mask);
else
gpio_writel(port, ODCR0C, pin_mask);
if (flags & PORTMUX_DRIVE_HIGH)
gpio_writel(port, ODCR1S, pin_mask);
else
gpio_writel(port, ODCR1C, pin_mask);
/* Select direction and initial pin state */
if (flags & PORTMUX_DIR_OUTPUT) {
if (flags & PORTMUX_INIT_HIGH)
gpio_writel(port, OVRS, pin_mask);
else
gpio_writel(port, OVRC, pin_mask);
gpio_writel(port, ODERS, pin_mask);
} else {
gpio_writel(port, ODERC, pin_mask);
}
/* Enable GPIO */
gpio_writel(port, GPERS, pin_mask);
}

92
cpu/at32ap/portmux-pio.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2006, 2008 Atmel Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/memory-map.h>
#include <asm/arch/gpio.h>
void portmux_select_peripheral(void *port, unsigned long pin_mask,
enum portmux_function func, unsigned long flags)
{
if (flags & PORTMUX_PULL_UP)
pio_writel(port, PUER, pin_mask);
else
pio_writel(port, PUDR, pin_mask);
switch (func) {
case PORTMUX_FUNC_A:
pio_writel(port, ASR, pin_mask);
break;
case PORTMUX_FUNC_B:
pio_writel(port, BSR, pin_mask);
break;
}
pio_writel(port, PDR, pin_mask);
}
void portmux_select_gpio(void *port, unsigned long pin_mask,
unsigned long flags)
{
if (flags & PORTMUX_PULL_UP)
pio_writel(port, PUER, pin_mask);
else
pio_writel(port, PUDR, pin_mask);
if (flags & PORTMUX_OPEN_DRAIN)
pio_writel(port, MDER, pin_mask);
else
pio_writel(port, MDDR, pin_mask);
if (flags & PORTMUX_DIR_OUTPUT) {
if (flags & PORTMUX_INIT_HIGH)
pio_writel(port, SODR, pin_mask);
else
pio_writel(port, CODR, pin_mask);
pio_writel(port, OER, pin_mask);
} else {
pio_writel(port, ODR, pin_mask);
}
pio_writel(port, PER, pin_mask);
}
void pio_set_output_value(unsigned int pin, int value)
{
void *port = pio_pin_to_port(pin);
if (!port)
panic("Invalid GPIO pin %u\n", pin);
__pio_set_output_value(port, pin & 0x1f, value);
}
int pio_get_input_value(unsigned int pin)
{
void *port = pio_pin_to_port(pin);
if (!port)
panic("Invalid GPIO pin %u\n", pin);
return __pio_get_input_value(port, pin & 0x1f);
}