📄 gpio.c
字号:
/* * arch/arm/mach-pnx4008/gpio.c * * PNX4008 GPIO driver * * Author: Dmitry Chigirev <source@mvista.com> * * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips: * Copyright (c) 2005 Koninklijke Philips Electronics N.V. * * 2005 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/module.h>#include <asm/semaphore.h>#include <asm/io.h>#include <asm/arch/platform.h>#include <asm/arch/gpio.h>/* register definitions */#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE)#define PIO_INP_STATE (0x00U)#define PIO_OUTP_SET (0x04U)#define PIO_OUTP_CLR (0x08U)#define PIO_OUTP_STATE (0x0CU)#define PIO_DRV_SET (0x10U)#define PIO_DRV_CLR (0x14U)#define PIO_DRV_STATE (0x18U)#define PIO_SDINP_STATE (0x1CU)#define PIO_SDOUTP_SET (0x20U)#define PIO_SDOUTP_CLR (0x24U)#define PIO_MUX_SET (0x28U)#define PIO_MUX_CLR (0x2CU)#define PIO_MUX_STATE (0x30U)static inline void gpio_lock(void){ local_irq_disable();}static inline void gpio_unlock(void){ local_irq_enable();}/* Inline functions */static inline int gpio_read_bit(u32 reg, int gpio){ u32 bit, val; int ret = -EFAULT; if (gpio < 0) goto out; bit = GPIO_BIT(gpio); if (bit) { val = __raw_readl(PIO_VA_BASE + reg); ret = (val & bit) ? 1 : 0; }out: return ret;}static inline int gpio_set_bit(u32 reg, int gpio){ u32 bit, val; int ret = -EFAULT; if (gpio < 0) goto out; bit = GPIO_BIT(gpio); if (bit) { val = __raw_readl(PIO_VA_BASE + reg); val |= bit; __raw_writel(val, PIO_VA_BASE + reg); ret = 0; }out: return ret;}/* Very simple access control, bitmap for allocated/free */static unsigned long access_map[4];#define INP_INDEX 0#define OUTP_INDEX 1#define GPIO_INDEX 2#define MUX_INDEX 3/*GPIO to Input Mapping */static short gpio_to_inp_map[32] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 24, -1};/*GPIO to Mux Mapping */static short gpio_to_mux_map[32] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 4, 5, -1};/*Output to Mux Mapping */static short outp_to_mux_map[32] = { -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};int pnx4008_gpio_register_pin(unsigned short pin){ unsigned long bit = GPIO_BIT(pin); int ret = -EBUSY; /* Already in use */ gpio_lock(); if (GPIO_ISBID(pin)) { if (access_map[GPIO_INDEX] & bit) goto out; access_map[GPIO_INDEX] |= bit; } else if (GPIO_ISRAM(pin)) { if (access_map[GPIO_INDEX] & bit) goto out; access_map[GPIO_INDEX] |= bit; } else if (GPIO_ISMUX(pin)) { if (access_map[MUX_INDEX] & bit) goto out; access_map[MUX_INDEX] |= bit; } else if (GPIO_ISOUT(pin)) { if (access_map[OUTP_INDEX] & bit) goto out; access_map[OUTP_INDEX] |= bit; } else if (GPIO_ISIN(pin)) { if (access_map[INP_INDEX] & bit) goto out; access_map[INP_INDEX] |= bit; } else goto out; ret = 0;out: gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_register_pin);int pnx4008_gpio_unregister_pin(unsigned short pin){ unsigned long bit = GPIO_BIT(pin); int ret = -EFAULT; /* Not registered */ gpio_lock(); if (GPIO_ISBID(pin)) { if (~access_map[GPIO_INDEX] & bit) goto out; access_map[GPIO_INDEX] &= ~bit; } else if (GPIO_ISRAM(pin)) { if (~access_map[GPIO_INDEX] & bit) goto out; access_map[GPIO_INDEX] &= ~bit; } else if (GPIO_ISMUX(pin)) { if (~access_map[MUX_INDEX] & bit) goto out; access_map[MUX_INDEX] &= ~bit; } else if (GPIO_ISOUT(pin)) { if (~access_map[OUTP_INDEX] & bit) goto out; access_map[OUTP_INDEX] &= ~bit; } else if (GPIO_ISIN(pin)) { if (~access_map[INP_INDEX] & bit) goto out; access_map[INP_INDEX] &= ~bit; } else goto out; ret = 0;out: gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);unsigned long pnx4008_gpio_read_pin(unsigned short pin){ unsigned long ret = -EFAULT; int gpio = GPIO_BIT_MASK(pin); gpio_lock(); if (GPIO_ISOUT(pin)) { ret = gpio_read_bit(PIO_OUTP_STATE, gpio); } else if (GPIO_ISRAM(pin)) { if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) { ret = gpio_read_bit(PIO_SDINP_STATE, gpio); } } else if (GPIO_ISBID(pin)) { ret = gpio_read_bit(PIO_DRV_STATE, gpio); if (ret > 0) ret = gpio_read_bit(PIO_OUTP_STATE, gpio); else if (ret == 0) ret = gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]); } else if (GPIO_ISIN(pin)) { ret = gpio_read_bit(PIO_INP_STATE, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin);/* Write Value to output */int pnx4008_gpio_write_pin(unsigned short pin, int output){ int gpio = GPIO_BIT_MASK(pin); int ret = -EFAULT; gpio_lock(); if (GPIO_ISOUT(pin)) { printk( "writing '%x' to '%x'\n", gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR ); ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio); } else if (GPIO_ISRAM(pin)) { if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) ret = gpio_set_bit(output ? PIO_SDOUTP_SET : PIO_SDOUTP_CLR, gpio); } else if (GPIO_ISBID(pin)) { if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_write_pin);/* Value = 1 : Set GPIO pin as output *//* Value = 0 : Set GPIO pin as input */int pnx4008_gpio_set_pin_direction(unsigned short pin, int output){ int gpio = GPIO_BIT_MASK(pin); int ret = -EFAULT; gpio_lock(); if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/int pnx4008_gpio_read_pin_direction(unsigned short pin){ int gpio = GPIO_BIT_MASK(pin); int ret = -EFAULT; gpio_lock(); if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { ret = gpio_read_bit(PIO_DRV_STATE, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);/* Value = 1 : Set pin to muxed function *//* Value = 0 : Set pin as GPIO */int pnx4008_gpio_set_pin_mux(unsigned short pin, int output){ int gpio = GPIO_BIT_MASK(pin); int ret = -EFAULT; gpio_lock(); if (GPIO_ISBID(pin)) { ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio_to_mux_map[gpio]); } else if (GPIO_ISOUT(pin)) { ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, outp_to_mux_map[gpio]); } else if (GPIO_ISMUX(pin)) { ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/int pnx4008_gpio_read_pin_mux(unsigned short pin){ int gpio = GPIO_BIT_MASK(pin); int ret = -EFAULT; gpio_lock(); if (GPIO_ISBID(pin)) { ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]); } else if (GPIO_ISOUT(pin)) { ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]); } else if (GPIO_ISMUX(pin)) { ret = gpio_read_bit(PIO_MUX_STATE, gpio); } gpio_unlock(); return ret;}EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -