[AVR32] Portmux API update

Rename portmux_set_func to at32_select_periph, add at32_select_gpio
and add flags parameter to specify the initial state of the pins.

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
This commit is contained in:
Haavard Skinnemoen 2006-12-04 13:46:52 +01:00
parent 68380b5813
commit c3e2a79c0b
4 changed files with 194 additions and 88 deletions

View file

@ -11,6 +11,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/at32ap7000.h>
#include <asm/arch/board.h> #include <asm/arch/board.h>
#include <asm/arch/portmux.h> #include <asm/arch/portmux.h>
#include <asm/arch/sm.h> #include <asm/arch/sm.h>
@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = { \
.num_resources = ARRAY_SIZE(_name##_id##_resource), \ .num_resources = ARRAY_SIZE(_name##_id##_resource), \
} }
#define select_peripheral(pin, periph, flags) \
at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
#define DEV_CLK(_name, devname, bus, _index) \ #define DEV_CLK(_name, devname, bus, _index) \
static struct clk devname##_##_name = { \ static struct clk devname##_##_name = { \
.name = #_name, \ .name = #_name, \
@ -67,18 +71,6 @@ static struct clk devname##_##_name = { \
.index = _index, \ .index = _index, \
} }
enum {
PIOA,
PIOB,
PIOC,
PIOD,
};
enum {
FUNC_A,
FUNC_B,
};
unsigned long at32ap7000_osc_rates[3] = { unsigned long at32ap7000_osc_rates[3] = {
[0] = 32768, [0] = 32768,
/* FIXME: these are ATSTK1002-specific */ /* FIXME: these are ATSTK1002-specific */
@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
static inline void configure_usart0_pins(void) static inline void configure_usart0_pins(void)
{ {
portmux_set_func(PIOA, 8, FUNC_B); /* RXD */ select_peripheral(PA(8), PERIPH_B, 0); /* RXD */
portmux_set_func(PIOA, 9, FUNC_B); /* TXD */ select_peripheral(PA(9), PERIPH_B, 0); /* TXD */
} }
static inline void configure_usart1_pins(void) static inline void configure_usart1_pins(void)
{ {
portmux_set_func(PIOA, 17, FUNC_A); /* RXD */ select_peripheral(PA(17), PERIPH_A, 0); /* RXD */
portmux_set_func(PIOA, 18, FUNC_A); /* TXD */ select_peripheral(PA(18), PERIPH_A, 0); /* TXD */
} }
static inline void configure_usart2_pins(void) static inline void configure_usart2_pins(void)
{ {
portmux_set_func(PIOB, 26, FUNC_B); /* RXD */ select_peripheral(PB(26), PERIPH_B, 0); /* RXD */
portmux_set_func(PIOB, 27, FUNC_B); /* TXD */ select_peripheral(PB(27), PERIPH_B, 0); /* TXD */
} }
static inline void configure_usart3_pins(void) static inline void configure_usart3_pins(void)
{ {
portmux_set_func(PIOB, 18, FUNC_B); /* RXD */ select_peripheral(PB(18), PERIPH_B, 0); /* RXD */
portmux_set_func(PIOB, 17, FUNC_B); /* TXD */ select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
} }
static struct platform_device *at32_usarts[4]; static struct platform_device *at32_usarts[4];
@ -663,27 +655,27 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
case 0: case 0:
pdev = &macb0_device; pdev = &macb0_device;
portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */ select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */
portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */ select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */
portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */ select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */
portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */ select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */
portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */ select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */
portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */ select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
portmux_set_func(PIOC, 13, FUNC_A); /* RXER */ select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */ select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
portmux_set_func(PIOC, 16, FUNC_A); /* MDC */ select_peripheral(PC(16), PERIPH_A, 0); /* MDC */
portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */ select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
if (!data->is_rmii) { if (!data->is_rmii) {
portmux_set_func(PIOC, 0, FUNC_A); /* COL */ select_peripheral(PC(0), PERIPH_A, 0); /* COL */
portmux_set_func(PIOC, 1, FUNC_A); /* CRS */ select_peripheral(PC(1), PERIPH_A, 0); /* CRS */
portmux_set_func(PIOC, 2, FUNC_A); /* TXER */ select_peripheral(PC(2), PERIPH_A, 0); /* TXER */
portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */ select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */
portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */ select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */
portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */ select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */ select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */ select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
portmux_set_func(PIOC, 18, FUNC_A); /* SPD */ select_peripheral(PC(18), PERIPH_A, 0); /* SPD */
} }
break; break;
@ -714,12 +706,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
switch (id) { switch (id) {
case 0: case 0:
pdev = &spi0_device; pdev = &spi0_device;
portmux_set_func(PIOA, 0, FUNC_A); /* MISO */ select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */ select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
portmux_set_func(PIOA, 2, FUNC_A); /* SCK */ select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */ select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */ select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */ select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
break; break;
default: default:
@ -762,37 +754,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
switch (id) { switch (id) {
case 0: case 0:
pdev = &lcdc0_device; pdev = &lcdc0_device;
portmux_set_func(PIOC, 19, FUNC_A); /* CC */ select_peripheral(PC(19), PERIPH_A, 0); /* CC */
portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */
portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */
portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */ select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */
portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */ select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */
portmux_set_func(PIOC, 24, FUNC_A); /* MODE */ select_peripheral(PC(24), PERIPH_A, 0); /* MODE */
portmux_set_func(PIOC, 25, FUNC_A); /* PWR */ select_peripheral(PC(25), PERIPH_A, 0); /* PWR */
portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */ select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */
portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */ select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */
portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */ select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */
portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */ select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */
portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */ select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */
portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */ select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */
portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */ select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */
portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */ select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */
portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */ select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */
portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */ select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */
portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */ select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */
portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */ select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */
portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */ select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */
portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */ select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */
portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */ select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */
portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */ select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */
portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */ select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */ select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */ select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */ select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */ select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */ select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */ select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
clk_set_parent(&lcdc0_pixclk, &pll0); clk_set_parent(&lcdc0_pixclk, &pll0);
clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));

View file

@ -25,27 +25,98 @@ struct pio_device {
void __iomem *regs; void __iomem *regs;
const struct platform_device *pdev; const struct platform_device *pdev;
struct clk *clk; struct clk *clk;
u32 alloc_mask; u32 pinmux_mask;
char name[32]; char name[32];
}; };
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, static struct pio_device *gpio_to_pio(unsigned int gpio)
unsigned int function_id)
{ {
struct pio_device *pio; struct pio_device *pio;
u32 mask = 1 << pin_id; unsigned int index;
BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); index = gpio >> 5;
if (index >= MAX_NR_PIO_DEVICES)
return NULL;
pio = &pio_dev[index];
if (!pio->regs)
return NULL;
pio = &pio_dev[portmux_id]; return pio;
}
if (function_id) /* Pin multiplexing API */
void __init at32_select_periph(unsigned int pin, unsigned int periph,
unsigned long flags)
{
struct pio_device *pio;
unsigned int pin_index = pin & 0x1f;
u32 mask = 1 << pin_index;
pio = gpio_to_pio(pin);
if (unlikely(!pio)) {
printk("pio: invalid pin %u\n", pin);
goto fail;
}
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
printk("%s: pin %u is busy\n", pio->name, pin_index);
goto fail;
}
pio_writel(pio, PUER, mask);
if (periph)
pio_writel(pio, BSR, mask); pio_writel(pio, BSR, mask);
else else
pio_writel(pio, ASR, mask); pio_writel(pio, ASR, mask);
pio_writel(pio, PDR, mask); pio_writel(pio, PDR, mask);
if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask);
return;
fail:
dump_stack();
}
void __init at32_select_gpio(unsigned int pin, unsigned long flags)
{
struct pio_device *pio;
unsigned int pin_index = pin & 0x1f;
u32 mask = 1 << pin_index;
pio = gpio_to_pio(pin);
if (unlikely(!pio)) {
printk("pio: invalid pin %u\n", pin);
goto fail;
}
if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
printk("%s: pin %u is busy\n", pio->name, pin_index);
goto fail;
}
pio_writel(pio, PUER, mask);
if (flags & AT32_GPIOF_HIGH)
pio_writel(pio, SODR, mask);
else
pio_writel(pio, CODR, mask);
if (flags & AT32_GPIOF_OUTPUT)
pio_writel(pio, OER, mask);
else
pio_writel(pio, ODR, mask);
pio_writel(pio, PER, mask);
if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask);
return;
fail:
dump_stack();
} }
static int __init pio_probe(struct platform_device *pdev) static int __init pio_probe(struct platform_device *pdev)

View file

@ -0,0 +1,33 @@
/*
* Pin definitions for AT32AP7000.
*
* Copyright (C) 2006 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_AT32AP7000_H__
#define __ASM_ARCH_AT32AP7000_H__
#define GPIO_PERIPH_A 0
#define GPIO_PERIPH_B 1
#define NR_GPIO_CONTROLLERS 4
/*
* Pin numbers identifying specific GPIO pins on the chip. They can
* also be converted to IRQ numbers by passing them through
* gpio_to_irq().
*/
#define GPIO_PIOA_BASE (0)
#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
#endif /* __ASM_ARCH_AT32AP7000_H__ */

View file

@ -7,10 +7,20 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef __ASM_AVR32_AT32_PORTMUX_H__ #ifndef __ASM_ARCH_PORTMUX_H__
#define __ASM_AVR32_AT32_PORTMUX_H__ #define __ASM_ARCH_PORTMUX_H__
void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, /*
unsigned int function_id); * Set up pin multiplexing, called from board init only.
*
* The following flags determine the initial state of the pin.
*/
#define AT32_GPIOF_PULLUP 0x00000001 /* Enable pull-up */
#define AT32_GPIOF_OUTPUT 0x00000002 /* Enable output driver */
#define AT32_GPIOF_HIGH 0x00000004 /* Set output high */
#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */ void at32_select_periph(unsigned int pin, unsigned int periph,
unsigned long flags);
void at32_select_gpio(unsigned int pin, unsigned long flags);
#endif /* __ASM_ARCH_PORTMUX_H__ */