openwrt的GPIO控制
为什么有些GPIO可以在/sys/class/gpio中控制,而有些不行呢?
先来看一看普通不需要C程序而是使用脚本的控制方法(Linux普遍适用):
First step is making GPIO available in Linux: echo "29" > /sys/class/gpio/export then you need to decide if it will be input or output, as we will use it as a switch so we need output echo "out" > /sys/class/gpio/gpio29/direction and last line turns GPIO on or off with 1 or 0: echo "1" > /sys/class/gpio/gpio29/value
ath79_gpio_function_disable这个函数的作用是?
/* Enable GPIO15 and GPIO16 and possibly GPIO26 and GPIO27 */ ath79_gpio_function_disable(AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN | AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN);
现象:当屏蔽掉上面两行之后,我的使用了GPIO15的程序就出错了!所以这个函数是使能某GPIO口的意思。
ath79_gpio_function_xxx在哪里定义?
ath79/gpio.c:159:void ath79_gpio_function_setup(u32 set, u32 clear) ath79/gpio.c:173:void ath79_gpio_function_enable(u32 mask) ath79/gpio.c:175: ath79_gpio_function_setup(mask, 0); ath79/gpio.c:178:void ath79_gpio_function_disable(u32 mask) ath79/gpio.c:180: ath79_gpio_function_setup(0, mask);
我们先看一下AR9331的数据手册,关于GPIO15和GPIO16:
当BIT(5),也就是AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN为1时,GPIO_15会作为以太网交换机的LED使用。而上面我们的函数是ath79_gpio_function_disable,意思就是不把这两个GPIO作为以太网交换机的LED使用,因而后面它可以被用作普通的GPIO口了!
上面这个寄存器的名字叫做GPIO_FUNCTION_1,其地址是0x18040028,reset值为0x00,因而开机的时候它都是GPIO口功能的。
这个寄存器的一小部分定义在openwrt1407/target/linux/ar71xx/image/lzma-loader/src/ar71xx_regs.h,摘抄其中相关的一些宏定义:
#define AR933X_GPIO_FUNC_SPDIF2TCK BIT(31) #define AR933X_GPIO_FUNC_SPDIF_EN BIT(30) #define AR933X_GPIO_FUNC_I2SO_22_18_EN BIT(29) #define AR933X_GPIO_FUNC_I2S_MCK_EN BIT(27) #define AR933X_GPIO_FUNC_I2SO_EN BIT(26) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL BIT(25) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL BIT(24) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT BIT(23) #define AR933X_GPIO_FUNC_SPI_EN BIT(18) #define AR933X_GPIO_FUNC_SPI_CS_EN2 BIT(14) #define AR933X_GPIO_FUNC_SPI_CS_EN1 BIT(13) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) #define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) #define AR933X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) #define AR933X_GPIO_FUNC_UART_EN BIT(1) #define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0)
经查找,在~../linux-3-10-49/arch/mips/dev-common.c中有一个对UART的IO口配置工作:
void __init ath79_register_uart(void) { struct clk *clk; clk = clk_get(NULL, "uart"); if (IS_ERR(clk)) panic("unable to get UART clock, err=%ld", PTR_ERR(clk)); if (soc_is_ar71xx()) ath79_gpio_function_enable(AR71XX_GPIO_FUNC_UART_EN); else if (soc_is_ar724x()) ath79_gpio_function_enable(AR724X_GPIO_FUNC_UART_EN); else if (soc_is_ar913x()) ath79_gpio_function_enable(AR913X_GPIO_FUNC_UART_EN); else if (soc_is_ar933x()) ath79_gpio_function_enable(AR933X_GPIO_FUNC_UART_EN); if (soc_is_ar71xx() || soc_is_ar724x() || soc_is_ar913x() || soc_is_ar934x() || soc_is_qca953x() || soc_is_qca955x()) { ath79_uart_data[0].uartclk = clk_get_rate(clk); platform_device_register(&ath79_uart_device); } else if (soc_is_ar933x()) { ar933x_uart_data.uartclk = clk_get_rate(clk); platform_device_register(&ar933x_uart_device); } else { BUG(); } }