Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3e2a79c authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

[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
Loading
Loading
Loading
Loading
+68 −76
Original line number Diff line number Diff line
@@ -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));
+78 −7
Original line number Diff line number Diff line
@@ -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)
+33 −0
Original line number Diff line number Diff line
/*
 * 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__ */
+15 −5
Original line number Diff line number Diff line
@@ -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__ */