原帖: https://whycan.cn/t_2393.html#p37627
我的A33 linux5.x 按 4# 的操作步奏,中断申请到了, 但是根本不触发。
arch/arm/boot/dts/sun8i-a23-a33.dtsi
pio: pinctrl@1c20800 {
/* compatible gets set in SoC specific dtsi file */
reg = <0x01c20800 0x400>;
....
key_pins: key_pins@0 {
pins = "PB5";
function = "gpio_in";
allwinner,drive = <0>;
allwinner,pull = <1>;
};
arch/arm/boot/dts/sun8i-a33.dtsi
keys{
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&key_pins>;
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
g-keys_up {
label = "GPIO KEY_UP";
linux,code = <103>; /* KEY_UP, see /usr/include/linux/input-event-codes.h */
// gpios = <&pio 1 5 1>; /* PA7 GPIO_ACTIVE_LOW */
interrupt-parent = <&pio>;
interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>;//PB0
};
/*status = "okay";*/
};
iio-hwmon {
compatible = "iio-hwmon";
io-channels = <&ths>;
};
根本不触发:
# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
18: 0 0 0 0 GICv2 29 Level arch_timer
19: 401 1735 205 225 GICv2 30 Level arch_timer
22: 0 0 0 0 GICv2 50 Level timer@1c20c00
23: 0 0 0 0 GICv2 82 Level 1c02000.dma-controller
25: 4072 0 0 0 GICv2 92 Level sunxi-mmc
26: 0 0 0 0 GICv2 103 Level musb-hdrc.1.auto
27: 0 0 0 0 GICv2 104 Level ehci_hcd:usb1
28: 0 0 0 0 GICv2 105 Level ohci_hcd:usb2
34: 1705 0 0 0 GICv2 32 Level ttyS0
56: 0 0 0 0 sunxi_pio_edge 5 Edge GPIO KEY_UP
60: 0 0 0 0 sunxi_pio_edge 9 Edge 1c0f000.mmc cd
IPI0: 0 0 0 0 CPU wakeup interrupts
IPI1: 0 0 0 0 Timer broadcast interrupts
IPI2: 749 723 125 1223 Rescheduling interrupts
IPI3: 1 12 22 43 Function call interrupts
IPI4: 0 0 0 0 CPU stop interrupts
IPI5: 0 0 0 0 IRQ work interrupts
IPI6: 0 0 0 0 completion interrupts
Err: 0
离线
https://github.com/torvalds/linux/blob/master/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
https://patchwork.kernel.org/patch/8572141/
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
index 00265f0..8b381d6 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
@@ -485,6 +485,7 @@ static const struct sunxi_pinctrl_desc sun8i_a33_pinctrl_data = {
.pins = sun8i_a33_pins,
.npins = ARRAY_SIZE(sun8i_a33_pins),
.irq_banks = 2,
+ .irq_bank_base = 1,
};
2016 的bug patch 也没有并入?
离线
https://lore.kernel.org/patchwork/patch/934382/
这里貌似有icenowy 关于 A33/V3s 外部IO中断的 patch
离线
PB4 用 sysfs 控制输出高低电平正常:
#PB4 = 32 + 4 = 36
echo 36 > /sys/class/gpio/export
#设置为输出
echo "out" > /sys/class/gpio/gpio36/direction
#PB4输出高电平
echo 1 > /sys/class/gpio/gpio36/value
#PB4输出低电平
echo 0 > /sys/class/gpio/gpio36/value
hello.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/input/touchscreen.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#define GPIO 36 //PG0
#define GPIO_INT_NAME "pb4_int"
#define GPIO_HIGH gpio_get_value(GPIO)
#define GPIO_LOW (gpio_get_value(GPIO) == 0)
MODULE_LICENSE("Dual BSD/GPL");
short int irq_any_gpio = 0;
int count =0;
enum { falling, rising } type;
static irqreturn_t r_irq_handler(int irq, void *dev_id)
{
count++;
printk("interrupt received (irq: %d)\n", irq);
if (irq == gpio_to_irq(GPIO))
{
type = GPIO_LOW ? falling : rising;
if(type == falling)
{
printk("gpio pin is low\n");
}
else
printk("gpio pin is high\n");
}
return IRQ_HANDLED;
}
void r_int_config(void) {
if (gpio_request(GPIO, GPIO_INT_NAME ))
{
printk("GPIO request failure: %s\n", GPIO_INT_NAME );
return;
}
if ( (irq_any_gpio = gpio_to_irq(GPIO)) < 0 ) {
printk("GPIO to IRQ mapping failure %s\n",GPIO_INT_NAME );
return;
}
printk(KERN_NOTICE "Mapped int %d\n", irq_any_gpio);
if (request_irq(irq_any_gpio,(irq_handler_t ) r_irq_handler, IRQF_TRIGGER_FALLING , GPIO_INT_NAME, NULL))
{
printk("Irq Request failure\n");
return;
}
return;
}
static void release_hello(void) {
free_irq(gpio_to_irq(GPIO), NULL);
gpio_free(GPIO);;
return;
}
static int init_hello(void)
{
printk("<1>Hello World\n");
r_int_config();
return 0;
}
module_init(init_hello); // Do some better naming
module_exit(release_hello);
Makefile
Makefile
#
# Makefile for kernel test
#
PWD := $(shell pwd)
KVERSION := $(shell uname -r)
KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/
MODULE_NAME = hello
obj-m := $(MODULE_NAME).o
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
编译指令:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make -C /home/ren/A33/mainline/linux/ M=${PWD} modules
安装模块:
insmod hello.ko
然后短路 PB4 & GND, 然而还是纹丝不动.
离线
https://github.com/torvalds/linux/blob/master/drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c
SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 4)), /* PB_EINT4 */
改为:
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PB_EINT4 */
也没有什么用, 向各路江湖豪杰求救!
离线
用 devmem 去读 PB_CFG0 寄存器
看是否处于中断复用?
查了一下, PB_CFG0 地址应该是 0x01C20824
insmod hello.ko 之前:
devmem 0x01C20824: 0x77477733
insmod hello.ko 之后:
devmem 0x01C20824: 0x77447733
看来这个PB4的复用应该没有错误, 只能检查别的问题了。
看来还是去 Icenowy 的仓库围观一下:
https://github.com/Icenowy/linux/commits/a33-cedrus-pr
离线
# insmod /mnt/udisk/hello.ko
[ 31.697182] hello: loading out-of-tree module taints kernel.
[ 31.703544] <1>Hello World
[ 31.706404] Mapped int 57
#
#
# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
18: 0 0 0 0 GICv2 29 Level arch_timer
19: 370 294 146 209 GICv2 30 Level arch_timer
22: 0 0 0 0 GICv2 50 Level timer@1c20c00
23: 0 0 0 0 GICv2 82 Level 1c02000.dma-controller
24: 1175 0 0 0 GICv2 92 Level sunxi-mmc
26: 0 0 0 0 GICv2 103 Level musb-hdrc.1.auto
27: 0 0 0 0 GICv2 104 Level ehci_hcd:usb1
28: 0 0 0 0 GICv2 105 Level ohci_hcd:usb2
34: 166 0 0 0 GICv2 32 Level ttyS0
42: 0 0 0 0 GICv2 72 Level 1f00000.rtc
57: 0 0 0 0 sunxi_pio_edge 4 Edge pb4_int
62: 0 0 0 0 sunxi_pio_edge 9 Edge 1c0f000.mmc cd
IPI0: 0 0 0 0 CPU wakeup interrupts
IPI1: 0 0 0 0 Timer broadcast interrupts
IPI2: 710 836 99 271 Rescheduling interrupts
IPI3: 4 23 44 41 Function call interrupts
IPI4: 0 0 0 0 CPU stop interrupts
IPI5: 0 0 0 0 IRQ work interrupts
IPI6: 0 0 0 0 completion interrupts
Err: 0
# [ 52.420296] interrupt received (irq: 57)
[ 52.424250] gpio pin is low
[ 52.427083] interrupt received (irq: 57)
[ 52.431010] gpio pin is low
[ 52.854042] interrupt received (irq: 57)
[ 52.857980] gpio pin is low
[ 52.860807] interrupt received (irq: 57)
[ 52.864733] gpio pin is low
[ 52.886404] interrupt received (irq: 57)
[ 52.890338] gpio pin is low
[ 52.897023] interrupt received (irq: 57)
[ 52.900955] gpio pin is low
[ 52.927779] interrupt received (irq: 57)
[ 52.931710] gpio pin is low
[ 53.154994] interrupt received (irq: 57)
[ 53.158927] gpio pin is high
[ 53.161838] interrupt received (irq: 57)
[ 53.165764] gpio pin is low
[ 53.168574] interrupt received (irq: 57)
[ 53.172500] gpio pin is low
[ 53.577491] interrupt received (irq: 57)
[ 53.581424] gpio pin is high
[ 53.584343] interrupt received (irq: 57)
[ 53.588270] gpio pin is high
#
# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
18: 0 0 0 0 GICv2 29 Level arch_timer
19: 512 351 156 209 GICv2 30 Level arch_timer
22: 0 0 0 0 GICv2 50 Level timer@1c20c00
23: 0 0 0 0 GICv2 82 Level 1c02000.dma-controller
24: 1579 0 0 0 GICv2 92 Level sunxi-mmc
26: 0 0 0 0 GICv2 103 Level musb-hdrc.1.auto
27: 0 0 0 0 GICv2 104 Level ehci_hcd:usb1
28: 0 0 0 0 GICv2 105 Level ohci_hcd:usb2
34: 207 0 0 0 GICv2 32 Level ttyS0
42: 0 0 0 0 GICv2 72 Level 1f00000.rtc
57: 12 0 0 0 sunxi_pio_edge 4 Edge pb4_int
62: 0 0 0 0 sunxi_pio_edge 9 Edge 1c0f000.mmc cd
IPI0: 0 0 0 0 CPU wakeup interrupts
IPI1: 0 0 0 0 Timer broadcast interrupts
IPI2: 710 897 100 271 Rescheduling interrupts
IPI3: 5 26 44 41 Function call interrupts
IPI4: 0 0 0 0 CPU stop interrupts
IPI5: 4 0 0 0 IRQ work interrupts
IPI6: 0 0 0 0 completion interrupts
Err: 0
#
试了一下 linux4.20 居然可以触发中断, 估计后面被改出问题了吧.
离线