Commit c3e2a79c authored by Haavard Skinnemoen's avatar Haavard Skinnemoen

[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: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 68380b58
......@@ -11,6 +11,7 @@
#include <asm/io.h>
#include <asm/arch/at32ap7000.h>
#include <asm/arch/board.h>
#include <asm/arch/portmux.h>
#include <asm/arch/sm.h>
......@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = { \
.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) \
static struct clk devname##_##_name = { \
.name = #_name, \
......@@ -67,18 +71,6 @@ static struct clk devname##_##_name = { \
.index = _index, \
}
enum {
PIOA,
PIOB,
PIOC,
PIOD,
};
enum {
FUNC_A,
FUNC_B,
};
unsigned long at32ap7000_osc_rates[3] = {
[0] = 32768,
/* FIXME: these are ATSTK1002-specific */
......@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
static inline void configure_usart0_pins(void)
{
portmux_set_func(PIOA, 8, FUNC_B); /* RXD */
portmux_set_func(PIOA, 9, FUNC_B); /* TXD */
select_peripheral(PA(8), PERIPH_B, 0); /* RXD */
select_peripheral(PA(9), PERIPH_B, 0); /* TXD */
}
static inline void configure_usart1_pins(void)
{
portmux_set_func(PIOA, 17, FUNC_A); /* RXD */
portmux_set_func(PIOA, 18, FUNC_A); /* TXD */
select_peripheral(PA(17), PERIPH_A, 0); /* RXD */
select_peripheral(PA(18), PERIPH_A, 0); /* TXD */
}
static inline void configure_usart2_pins(void)
{
portmux_set_func(PIOB, 26, FUNC_B); /* RXD */
portmux_set_func(PIOB, 27, FUNC_B); /* TXD */
select_peripheral(PB(26), PERIPH_B, 0); /* RXD */
select_peripheral(PB(27), PERIPH_B, 0); /* TXD */
}
static inline void configure_usart3_pins(void)
{
portmux_set_func(PIOB, 18, FUNC_B); /* RXD */
portmux_set_func(PIOB, 17, FUNC_B); /* TXD */
select_peripheral(PB(18), PERIPH_B, 0); /* RXD */
select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
}
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:
pdev = &macb0_device;
portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */
portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */
portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */
portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */
portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */
portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */
portmux_set_func(PIOC, 13, FUNC_A); /* RXER */
portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */
portmux_set_func(PIOC, 16, FUNC_A); /* MDC */
portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */
select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */
select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */
select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */
select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */
select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */
select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
select_peripheral(PC(16), PERIPH_A, 0); /* MDC */
select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
if (!data->is_rmii) {
portmux_set_func(PIOC, 0, FUNC_A); /* COL */
portmux_set_func(PIOC, 1, FUNC_A); /* CRS */
portmux_set_func(PIOC, 2, FUNC_A); /* TXER */
portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */
portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */
portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */
portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */
portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */
portmux_set_func(PIOC, 18, FUNC_A); /* SPD */
select_peripheral(PC(0), PERIPH_A, 0); /* COL */
select_peripheral(PC(1), PERIPH_A, 0); /* CRS */
select_peripheral(PC(2), PERIPH_A, 0); /* TXER */
select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */
select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */
select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
select_peripheral(PC(18), PERIPH_A, 0); /* SPD */
}
break;
......@@ -714,12 +706,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
switch (id) {
case 0:
pdev = &spi0_device;
portmux_set_func(PIOA, 0, FUNC_A); /* MISO */
portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */
portmux_set_func(PIOA, 2, FUNC_A); /* SCK */
portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */
portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */
portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */
select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
break;
default:
......@@ -762,37 +754,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
switch (id) {
case 0:
pdev = &lcdc0_device;
portmux_set_func(PIOC, 19, FUNC_A); /* CC */
portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */
portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */
portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */
portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */
portmux_set_func(PIOC, 24, FUNC_A); /* MODE */
portmux_set_func(PIOC, 25, FUNC_A); /* PWR */
portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */
portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */
portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */
portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */
portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */
portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */
portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */
portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */
portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */
portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */
portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */
portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */
portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */
portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */
portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */
portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */
portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */
portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */
portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */
portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */
portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */
portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */
portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */
portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */
select_peripheral(PC(19), PERIPH_A, 0); /* CC */
select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */
select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */
select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */
select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */
select_peripheral(PC(24), PERIPH_A, 0); /* MODE */
select_peripheral(PC(25), PERIPH_A, 0); /* PWR */
select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */
select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */
select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */
select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */
select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */
select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */
select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */
select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */
select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */
select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */
select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */
select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */
select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */
select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */
select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */
select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */
select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
clk_set_parent(&lcdc0_pixclk, &pll0);
clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
......
......@@ -25,27 +25,98 @@ struct pio_device {
void __iomem *regs;
const struct platform_device *pdev;
struct clk *clk;
u32 alloc_mask;
u32 pinmux_mask;
char name[32];
};
static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
unsigned int function_id)
static struct pio_device *gpio_to_pio(unsigned int gpio)
{
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;
}
/* 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 (function_id)
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);
else
pio_writel(pio, ASR, 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)
......
/*
* 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__ */
......@@ -7,10 +7,20 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_AVR32_AT32_PORTMUX_H__
#define __ASM_AVR32_AT32_PORTMUX_H__
#ifndef __ASM_ARCH_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 */
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_AVR32_AT32_PORTMUX_H__ */
#endif /* __ASM_ARCH_PORTMUX_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment