⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpio.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/arch/arm/plat-omap/gpio.c * * Support functions for OMAP GPIO * * Copyright (C) 2003-2005 Nokia Corporation * Written by Juha Yrjölä <juha.yrjola@nokia.com> * * 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/init.h>#include <linux/module.h>#include <linux/interrupt.h>#include <linux/sysdev.h>#include <linux/err.h>#include <linux/clk.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/arch/irqs.h>#include <asm/arch/gpio.h>#include <asm/mach/irq.h>#include <asm/io.h>/* * OMAP1510 GPIO registers */#define OMAP1510_GPIO_BASE		(void __iomem *)0xfffce000#define OMAP1510_GPIO_DATA_INPUT	0x00#define OMAP1510_GPIO_DATA_OUTPUT	0x04#define OMAP1510_GPIO_DIR_CONTROL	0x08#define OMAP1510_GPIO_INT_CONTROL	0x0c#define OMAP1510_GPIO_INT_MASK		0x10#define OMAP1510_GPIO_INT_STATUS	0x14#define OMAP1510_GPIO_PIN_CONTROL	0x18#define OMAP1510_IH_GPIO_BASE		64/* * OMAP1610 specific GPIO registers */#define OMAP1610_GPIO1_BASE		(void __iomem *)0xfffbe400#define OMAP1610_GPIO2_BASE		(void __iomem *)0xfffbec00#define OMAP1610_GPIO3_BASE		(void __iomem *)0xfffbb400#define OMAP1610_GPIO4_BASE		(void __iomem *)0xfffbbc00#define OMAP1610_GPIO_REVISION		0x0000#define OMAP1610_GPIO_SYSCONFIG		0x0010#define OMAP1610_GPIO_SYSSTATUS		0x0014#define OMAP1610_GPIO_IRQSTATUS1	0x0018#define OMAP1610_GPIO_IRQENABLE1	0x001c#define OMAP1610_GPIO_WAKEUPENABLE	0x0028#define OMAP1610_GPIO_DATAIN		0x002c#define OMAP1610_GPIO_DATAOUT		0x0030#define OMAP1610_GPIO_DIRECTION		0x0034#define OMAP1610_GPIO_EDGE_CTRL1	0x0038#define OMAP1610_GPIO_EDGE_CTRL2	0x003c#define OMAP1610_GPIO_CLEAR_IRQENABLE1	0x009c#define OMAP1610_GPIO_CLEAR_WAKEUPENA	0x00a8#define OMAP1610_GPIO_CLEAR_DATAOUT	0x00b0#define OMAP1610_GPIO_SET_IRQENABLE1	0x00dc#define OMAP1610_GPIO_SET_WAKEUPENA	0x00e8#define OMAP1610_GPIO_SET_DATAOUT	0x00f0/* * OMAP730 specific GPIO registers */#define OMAP730_GPIO1_BASE		(void __iomem *)0xfffbc000#define OMAP730_GPIO2_BASE		(void __iomem *)0xfffbc800#define OMAP730_GPIO3_BASE		(void __iomem *)0xfffbd000#define OMAP730_GPIO4_BASE		(void __iomem *)0xfffbd800#define OMAP730_GPIO5_BASE		(void __iomem *)0xfffbe000#define OMAP730_GPIO6_BASE		(void __iomem *)0xfffbe800#define OMAP730_GPIO_DATA_INPUT		0x00#define OMAP730_GPIO_DATA_OUTPUT	0x04#define OMAP730_GPIO_DIR_CONTROL	0x08#define OMAP730_GPIO_INT_CONTROL	0x0c#define OMAP730_GPIO_INT_MASK		0x10#define OMAP730_GPIO_INT_STATUS		0x14/* * omap24xx specific GPIO registers */#define OMAP242X_GPIO1_BASE		(void __iomem *)0x48018000#define OMAP242X_GPIO2_BASE		(void __iomem *)0x4801a000#define OMAP242X_GPIO3_BASE		(void __iomem *)0x4801c000#define OMAP242X_GPIO4_BASE		(void __iomem *)0x4801e000#define OMAP243X_GPIO1_BASE		(void __iomem *)0x4900C000#define OMAP243X_GPIO2_BASE		(void __iomem *)0x4900E000#define OMAP243X_GPIO3_BASE		(void __iomem *)0x49010000#define OMAP243X_GPIO4_BASE		(void __iomem *)0x49012000#define OMAP243X_GPIO5_BASE		(void __iomem *)0x480B6000#define OMAP24XX_GPIO_REVISION		0x0000#define OMAP24XX_GPIO_SYSCONFIG		0x0010#define OMAP24XX_GPIO_SYSSTATUS		0x0014#define OMAP24XX_GPIO_IRQSTATUS1	0x0018#define OMAP24XX_GPIO_IRQSTATUS2	0x0028#define OMAP24XX_GPIO_IRQENABLE2	0x002c#define OMAP24XX_GPIO_IRQENABLE1	0x001c#define OMAP24XX_GPIO_CTRL		0x0030#define OMAP24XX_GPIO_OE		0x0034#define OMAP24XX_GPIO_DATAIN		0x0038#define OMAP24XX_GPIO_DATAOUT		0x003c#define OMAP24XX_GPIO_LEVELDETECT0	0x0040#define OMAP24XX_GPIO_LEVELDETECT1	0x0044#define OMAP24XX_GPIO_RISINGDETECT	0x0048#define OMAP24XX_GPIO_FALLINGDETECT	0x004c#define OMAP24XX_GPIO_CLEARIRQENABLE1	0x0060#define OMAP24XX_GPIO_SETIRQENABLE1	0x0064#define OMAP24XX_GPIO_CLEARWKUENA	0x0080#define OMAP24XX_GPIO_SETWKUENA		0x0084#define OMAP24XX_GPIO_CLEARDATAOUT	0x0090#define OMAP24XX_GPIO_SETDATAOUT	0x0094struct gpio_bank {	void __iomem *base;	u16 irq;	u16 virtual_irq_start;	int method;	u32 reserved_map;#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)	u32 suspend_wakeup;	u32 saved_wakeup;#endif#ifdef CONFIG_ARCH_OMAP24XX	u32 non_wakeup_gpios;	u32 enabled_non_wakeup_gpios;	u32 saved_datain;	u32 saved_fallingdetect;	u32 saved_risingdetect;#endif	spinlock_t lock;};#define METHOD_MPUIO		0#define METHOD_GPIO_1510	1#define METHOD_GPIO_1610	2#define METHOD_GPIO_730		3#define METHOD_GPIO_24XX	4#ifdef CONFIG_ARCH_OMAP16XXstatic struct gpio_bank gpio_bank_1610[5] = {	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,     METHOD_MPUIO},	{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,	    IH_GPIO_BASE,      METHOD_GPIO_1610 },	{ OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 },	{ OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 },	{ OMAP1610_GPIO4_BASE, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, METHOD_GPIO_1610 },};#endif#ifdef CONFIG_ARCH_OMAP15XXstatic struct gpio_bank gpio_bank_1510[2] = {	{ OMAP_MPUIO_BASE,    INT_MPUIO,      IH_MPUIO_BASE, METHOD_MPUIO },	{ OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE,  METHOD_GPIO_1510 }};#endif#ifdef CONFIG_ARCH_OMAP730static struct gpio_bank gpio_bank_730[7] = {	{ OMAP_MPUIO_BASE,     INT_730_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },	{ OMAP730_GPIO1_BASE,  INT_730_GPIO_BANK1,  IH_GPIO_BASE,	METHOD_GPIO_730 },	{ OMAP730_GPIO2_BASE,  INT_730_GPIO_BANK2,  IH_GPIO_BASE + 32,	METHOD_GPIO_730 },	{ OMAP730_GPIO3_BASE,  INT_730_GPIO_BANK3,  IH_GPIO_BASE + 64,	METHOD_GPIO_730 },	{ OMAP730_GPIO4_BASE,  INT_730_GPIO_BANK4,  IH_GPIO_BASE + 96,	METHOD_GPIO_730 },	{ OMAP730_GPIO5_BASE,  INT_730_GPIO_BANK5,  IH_GPIO_BASE + 128, METHOD_GPIO_730 },	{ OMAP730_GPIO6_BASE,  INT_730_GPIO_BANK6,  IH_GPIO_BASE + 160, METHOD_GPIO_730 },};#endif#ifdef CONFIG_ARCH_OMAP24XXstatic struct gpio_bank gpio_bank_242x[4] = {	{ OMAP242X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,	METHOD_GPIO_24XX },	{ OMAP242X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,	METHOD_GPIO_24XX },	{ OMAP242X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,	METHOD_GPIO_24XX },	{ OMAP242X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,	METHOD_GPIO_24XX },};static struct gpio_bank gpio_bank_243x[5] = {	{ OMAP243X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,	METHOD_GPIO_24XX },	{ OMAP243X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,	METHOD_GPIO_24XX },	{ OMAP243X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,	METHOD_GPIO_24XX },	{ OMAP243X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,	METHOD_GPIO_24XX },	{ OMAP243X_GPIO5_BASE, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_24XX },};#endifstatic struct gpio_bank *gpio_bank;static int gpio_bank_count;static inline struct gpio_bank *get_gpio_bank(int gpio){#ifdef CONFIG_ARCH_OMAP15XX	if (cpu_is_omap15xx()) {		if (OMAP_GPIO_IS_MPUIO(gpio))			return &gpio_bank[0];		return &gpio_bank[1];	}#endif#if defined(CONFIG_ARCH_OMAP16XX)	if (cpu_is_omap16xx()) {		if (OMAP_GPIO_IS_MPUIO(gpio))			return &gpio_bank[0];		return &gpio_bank[1 + (gpio >> 4)];	}#endif#ifdef CONFIG_ARCH_OMAP730	if (cpu_is_omap730()) {		if (OMAP_GPIO_IS_MPUIO(gpio))			return &gpio_bank[0];		return &gpio_bank[1 + (gpio >> 5)];	}#endif#ifdef CONFIG_ARCH_OMAP24XX	if (cpu_is_omap24xx())		return &gpio_bank[gpio >> 5];#endif}static inline int get_gpio_index(int gpio){#ifdef CONFIG_ARCH_OMAP730	if (cpu_is_omap730())		return gpio & 0x1f;#endif#ifdef CONFIG_ARCH_OMAP24XX	if (cpu_is_omap24xx())		return gpio & 0x1f;#endif	return gpio & 0x0f;}static inline int gpio_valid(int gpio){	if (gpio < 0)		return -1;#ifndef CONFIG_ARCH_OMAP24XX	if (OMAP_GPIO_IS_MPUIO(gpio)) {		if (gpio >= OMAP_MAX_GPIO_LINES + 16)			return -1;		return 0;	}#endif#ifdef CONFIG_ARCH_OMAP15XX	if (cpu_is_omap15xx() && gpio < 16)		return 0;#endif#if defined(CONFIG_ARCH_OMAP16XX)	if ((cpu_is_omap16xx()) && gpio < 64)		return 0;#endif#ifdef CONFIG_ARCH_OMAP730	if (cpu_is_omap730() && gpio < 192)		return 0;#endif#ifdef CONFIG_ARCH_OMAP24XX	if (cpu_is_omap24xx() && gpio < 128)		return 0;#endif	return -1;}static int check_gpio(int gpio){	if (unlikely(gpio_valid(gpio)) < 0) {		printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);		dump_stack();		return -1;	}	return 0;}static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input){	void __iomem *reg = bank->base;	u32 l;	switch (bank->method) {#ifdef CONFIG_ARCH_OMAP1	case METHOD_MPUIO:		reg += OMAP_MPUIO_IO_CNTL;		break;#endif#ifdef CONFIG_ARCH_OMAP15XX	case METHOD_GPIO_1510:		reg += OMAP1510_GPIO_DIR_CONTROL;		break;#endif#ifdef CONFIG_ARCH_OMAP16XX	case METHOD_GPIO_1610:		reg += OMAP1610_GPIO_DIRECTION;		break;#endif#ifdef CONFIG_ARCH_OMAP730	case METHOD_GPIO_730:		reg += OMAP730_GPIO_DIR_CONTROL;		break;#endif#ifdef CONFIG_ARCH_OMAP24XX	case METHOD_GPIO_24XX:		reg += OMAP24XX_GPIO_OE;		break;#endif	default:		WARN_ON(1);		return;	}	l = __raw_readl(reg);	if (is_input)		l |= 1 << gpio;	else		l &= ~(1 << gpio);	__raw_writel(l, reg);}void omap_set_gpio_direction(int gpio, int is_input){	struct gpio_bank *bank;	if (check_gpio(gpio) < 0)		return;	bank = get_gpio_bank(gpio);	spin_lock(&bank->lock);	_set_gpio_direction(bank, get_gpio_index(gpio), is_input);	spin_unlock(&bank->lock);}static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable){	void __iomem *reg = bank->base;	u32 l = 0;	switch (bank->method) {#ifdef CONFIG_ARCH_OMAP1	case METHOD_MPUIO:		reg += OMAP_MPUIO_OUTPUT;		l = __raw_readl(reg);		if (enable)			l |= 1 << gpio;		else			l &= ~(1 << gpio);		break;#endif#ifdef CONFIG_ARCH_OMAP15XX	case METHOD_GPIO_1510:		reg += OMAP1510_GPIO_DATA_OUTPUT;		l = __raw_readl(reg);		if (enable)			l |= 1 << gpio;		else			l &= ~(1 << gpio);		break;#endif#ifdef CONFIG_ARCH_OMAP16XX	case METHOD_GPIO_1610:		if (enable)			reg += OMAP1610_GPIO_SET_DATAOUT;		else			reg += OMAP1610_GPIO_CLEAR_DATAOUT;		l = 1 << gpio;		break;#endif#ifdef CONFIG_ARCH_OMAP730	case METHOD_GPIO_730:		reg += OMAP730_GPIO_DATA_OUTPUT;		l = __raw_readl(reg);		if (enable)			l |= 1 << gpio;		else			l &= ~(1 << gpio);		break;#endif#ifdef CONFIG_ARCH_OMAP24XX	case METHOD_GPIO_24XX:		if (enable)			reg += OMAP24XX_GPIO_SETDATAOUT;		else			reg += OMAP24XX_GPIO_CLEARDATAOUT;		l = 1 << gpio;		break;#endif	default:		WARN_ON(1);		return;	}	__raw_writel(l, reg);}void omap_set_gpio_dataout(int gpio, int enable){	struct gpio_bank *bank;	if (check_gpio(gpio) < 0)		return;	bank = get_gpio_bank(gpio);	spin_lock(&bank->lock);	_set_gpio_dataout(bank, get_gpio_index(gpio), enable);	spin_unlock(&bank->lock);}int omap_get_gpio_datain(int gpio){	struct gpio_bank *bank;	void __iomem *reg;	if (check_gpio(gpio) < 0)		return -EINVAL;	bank = get_gpio_bank(gpio);	reg = bank->base;	switch (bank->method) {#ifdef CONFIG_ARCH_OMAP1	case METHOD_MPUIO:		reg += OMAP_MPUIO_INPUT_LATCH;		break;#endif#ifdef CONFIG_ARCH_OMAP15XX	case METHOD_GPIO_1510:		reg += OMAP1510_GPIO_DATA_INPUT;		break;#endif#ifdef CONFIG_ARCH_OMAP16XX	case METHOD_GPIO_1610:		reg += OMAP1610_GPIO_DATAIN;		break;#endif#ifdef CONFIG_ARCH_OMAP730	case METHOD_GPIO_730:		reg += OMAP730_GPIO_DATA_INPUT;		break;#endif#ifdef CONFIG_ARCH_OMAP24XX	case METHOD_GPIO_24XX:		reg += OMAP24XX_GPIO_DATAIN;		break;#endif	default:		return -EINVAL;	}	return (__raw_readl(reg)			& (1 << get_gpio_index(gpio))) != 0;}#define MOD_REG_BIT(reg, bit_mask, set)	\do {	\	int l = __raw_readl(base + reg); \	if (set) l |= bit_mask; \	else l &= ~bit_mask; \	__raw_writel(l, base + reg); \} while(0)#ifdef CONFIG_ARCH_OMAP24XXstatic inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger){	void __iomem *base = bank->base;	u32 gpio_bit = 1 << gpio;	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,		trigger & __IRQT_LOWLVL);	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,		trigger & __IRQT_HIGHLVL);	MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,		trigger & __IRQT_RISEDGE);	MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,		trigger & __IRQT_FALEDGE);	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {		if (trigger != 0)			__raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA);		else			__raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA);	} else {		if (trigger != 0)			bank->enabled_non_wakeup_gpios |= gpio_bit;		else			bank->enabled_non_wakeup_gpios &= ~gpio_bit;	}	/* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level	 * triggering requested. */}#endifstatic int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger){	void __iomem *reg = bank->base;	u32 l = 0;	switch (bank->method) {#ifdef CONFIG_ARCH_OMAP1	case METHOD_MPUIO:		reg += OMAP_MPUIO_GPIO_INT_EDGE;		l = __raw_readl(reg);		if (trigger & __IRQT_RISEDGE)			l |= 1 << gpio;		else if (trigger & __IRQT_FALEDGE)			l &= ~(1 << gpio);		else			goto bad;		break;#endif#ifdef CONFIG_ARCH_OMAP15XX	case METHOD_GPIO_1510:		reg += OMAP1510_GPIO_INT_CONTROL;		l = __raw_readl(reg);		if (trigger & __IRQT_RISEDGE)			l |= 1 << gpio;		else if (trigger & __IRQT_FALEDGE)			l &= ~(1 << gpio);		else			goto bad;		break;#endif#ifdef CONFIG_ARCH_OMAP16XX	case METHOD_GPIO_1610:		if (gpio & 0x08)			reg += OMAP1610_GPIO_EDGE_CTRL2;		else			reg += OMAP1610_GPIO_EDGE_CTRL1;		gpio &= 0x07;		l = __raw_readl(reg);		l &= ~(3 << (gpio << 1));		if (trigger & __IRQT_RISEDGE)			l |= 2 << (gpio << 1);		if (trigger & __IRQT_FALEDGE)			l |= 1 << (gpio << 1);		if (trigger)			/* Enable wake-up during idle for dynamic tick */			__raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);		else			__raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);		break;#endif#ifdef CONFIG_ARCH_OMAP730	case METHOD_GPIO_730:		reg += OMAP730_GPIO_INT_CONTROL;		l = __raw_readl(reg);		if (trigger & __IRQT_RISEDGE)			l |= 1 << gpio;		else if (trigger & __IRQT_FALEDGE)			l &= ~(1 << gpio);		else			goto bad;		break;#endif#ifdef CONFIG_ARCH_OMAP24XX	case METHOD_GPIO_24XX:		set_24xx_gpio_triggering(bank, gpio, trigger);		break;#endif	default:		goto bad;	}	__raw_writel(l, reg);	return 0;bad:	return -EINVAL;}static int gpio_irq_type(unsigned irq, unsigned type){	struct gpio_bank *bank;	unsigned gpio;	int retval;	if (!cpu_is_omap24xx() && irq > IH_MPUIO_BASE)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -