| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | /* * Atmel PIO2 Port Multiplexer support * * Copyright (C) 2004-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. */#include <linux/clk.h>#include <linux/debugfs.h>#include <linux/export.h>#include <linux/fs.h>#include <linux/platform_device.h>#include <linux/irq.h>#include <asm/gpio.h>#include <asm/io.h>#include <mach/portmux.h>#include "pio.h"#define MAX_NR_PIO_DEVICES		8struct pio_device {	struct gpio_chip chip;	void __iomem *regs;	const struct platform_device *pdev;	struct clk *clk;	u32 pinmux_mask;	char name[8];};static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];static struct pio_device *gpio_to_pio(unsigned int gpio){	struct pio_device *pio;	unsigned int index;	index = gpio >> 5;	if (index >= MAX_NR_PIO_DEVICES)		return NULL;	pio = &pio_dev[index];	if (!pio->regs)		return NULL;	return pio;}/* Pin multiplexing API */static DEFINE_SPINLOCK(pio_lock);void __init at32_select_periph(unsigned int port, u32 pin_mask,			       unsigned int periph, unsigned long flags){	struct pio_device *pio;	/* assign and verify pio */	pio = gpio_to_pio(port);	if (unlikely(!pio)) {		printk(KERN_WARNING "pio: invalid port %u\n", port);		goto fail;	}	/* Test if any of the requested pins is already muxed */	spin_lock(&pio_lock);	if (unlikely(pio->pinmux_mask & pin_mask)) {		printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n",		       pio->name, pin_mask, pio->pinmux_mask & pin_mask);		spin_unlock(&pio_lock);		goto fail;	}	pio->pinmux_mask |= pin_mask;	/* enable pull ups */	pio_writel(pio, PUER, pin_mask);	/* select either peripheral A or B */	if (periph)		pio_writel(pio, BSR, pin_mask);	else		pio_writel(pio, ASR, pin_mask);	/* enable peripheral control */	pio_writel(pio, PDR, pin_mask);	/* Disable pull ups if not requested. */	if (!(flags & AT32_GPIOF_PULLUP))		pio_writel(pio, PUDR, pin_mask);	spin_unlock(&pio_lock);	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;	}	if (flags & AT32_GPIOF_OUTPUT) {		if (flags & AT32_GPIOF_HIGH)			pio_writel(pio, SODR, mask);		else			pio_writel(pio, CODR, mask);		if (flags & AT32_GPIOF_MULTIDRV)			pio_writel(pio, MDER, mask);		else			pio_writel(pio, MDDR, mask);		pio_writel(pio, PUDR, mask);		pio_writel(pio, OER, mask);	} else {		if (flags & AT32_GPIOF_PULLUP)			pio_writel(pio, PUER, mask);		else			pio_writel(pio, PUDR, mask);		if (flags & AT32_GPIOF_DEGLITCH)			pio_writel(pio, IFER, mask);		else			pio_writel(pio, IFDR, mask);		pio_writel(pio, ODR, mask);	}	pio_writel(pio, PER, mask);	return;fail:	dump_stack();}/* * Undo a previous pin reservation. Will not affect the hardware * configuration. */void at32_deselect_pin(unsigned int pin){	struct pio_device *pio;	unsigned int pin_index = pin & 0x1f;	pio = gpio_to_pio(pin);	if (unlikely(!pio)) {
 |