Jump to content

gpio PA19 hardware interrupts


Ohms

Recommended Posts

Recently i have been experimenting with interrupts on orange pi zero plus2-H3 trying to capture data-ready pulses from an external adc on gpio PA19.  The aim is to synchronize spi-read-data transactions with the incoming adc data-ready signal. First I tried to get it to work on legacy kernel 3.4 by adding the following section in to /boot/script.fex and compile the .fex file to .bin file using fex2bin:
 

[gpio_para]
gpio_used = 1
gpio_num = 6
....
gpio_pin_6 = port:PA19<0><default><default><1>

This configured the pin properly as i had tested on other pins with some leds and it works. The driver code for capturing the interrupt was based on an example i found at https://github.com/tomxue/Kernel_GPIO_interrupt/blob/master/m_test.c and is as follows:
 

...

#define GPIO_PIN 19
#define GPIO_PIN_DESC "GPIO PA19 interrupt test"

static irqreturn_t r_irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
   unsigned long flags;
  
   local_irq_save(flags);
   printk("Interrupt [%d] on device [%s] was triggered!!\n", irq, (char *) dev_id);
   local_irq_restore(flags);
 
   return IRQ_HANDLED;
}

void config_interrupt (void) {
   int err;
   int gpio_irq;

   err = setup_pinmux();
   if (err < 0) {
      printk("GPIO setup pinmux failure: %s\n", GPIO_PIN_DESC);
      return;
   }

   if (gpio_request(GPIO_PIN, GPIO_PIN_DESC)) {
      printk("GPIO request failure: %s\n", GPIO_PIN_DESC);
      return;
   }

   if (gpio_direction_input(GPIO_PIN)) {
      printk("GPIO set direction input failure %s\n", GPIO_PIN_DESC);
      return;
   }
 
   if ( (gpio_irq = gpio_to_irq(GPIO_PIN)) < 0 ) {
      printk("GPIO to IRQ mapping failure %s\n", GPIO_PIN_DESC);
      return;
   }

   printk(KERN_NOTICE "Mapped int %d\n", gpio_irq);
 
   if (request_irq(gpio_irq,
                   (irq_handler_t ) r_irq_handler,
                   IRQF_TRIGGER_RISING,   // IRQF_TRIGGER_LOW,
                   GPIO_PIN_DESC,
                   GPIO_PIN_DEVICE_DESC)) {
      printk("Irq Request failure\n");
      return;
   }
  
   return;
}


Unfortunately i could only get it to work if i replace IRQF_TRIGGER_RISING with IRQF_TRIGGER_LOW. This was tested by issuing dmesg to obtain the irq number and then cat /proc/interrupts to monitor interrupt events on the allocated irq. At first, this gave me the impression that interrupts in the kernel are polling the pin instead of actual hardware triggering. Based on the data sheets of  the sunxi H3 chipset (http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf, page 74) PA19 is interrupt capable by the setting the pinmux to PA_EINT19, function code 0x6. So i decided to do low level configuration of the pinmux by adding the following section to the module and test accordingly:
 

/**
 * Low level configuration of GPIO pin mode
 */
#ifdef KERNEL_34
#define IOMEM(x) ((void __force __iomem *)(x))
#ifndef IO_ADDRESS
#define IO_ADDRESS(x) ((x) + 0xf0000000)
#endif
#ifndef __io_address
#define __io_address(n) IOMEM(IO_ADDRESS(n))
#endif


// IO memory map base address, discovered by searching through Armbian sources
#define SUNXI_IOMEM(n) (0xf0000000 + (n))
#define PIO_BASE SUNXI_IOMEM(0x01C20800)

// gpio banks of the ALLWINNER H3
#define GPIO_BANK_A 0
//#define GPIO_BANK_B 1        // not a valid bank on H3
#define GPIO_BANK_C 2
#define GPIO_BANK_D 3
#define GPIO_BANK_E 4
#define GPIO_BANK_F 5
#define GPIO_BANK_G 6

// PORT configuration registers
#define Pn_CFG0_REG(n)        (PIO_BASE + (n*0x24) + (0x00))    // 32bits[0..31] see data sheet
#define Pn_CFG1_REG(n)        (PIO_BASE + (n*0x24) + (0x04))
#define Pn_CFG2_REG(n)        (PIO_BASE + (n*0x24) + (0x08))
#define Pn_CFG3_REG(n)        (PIO_BASE + (n*0x24) + (0x0c))

#define PA_DAT                (PIO_BASE + 0x10)
#define PA_PULL               (PIO_BASE + 0x1C)

#define PA_EINT_CFG_REG(n)    (PIO_BASE + 0x200 + (4*n))
#define PA_EINT_CTL_REG       (PIO_BASE + 0x210)
#define PA_EINT_STATUS_REG    (PIO_BASE + 0x214)
#define PA_EINT_DEB_REG       (PIO_BASE + 0x218)

#define readb(addr)        (*((volatile unsigned char  *)(addr)))
#define readw(addr)        (*((volatile unsigned short *)(addr)))
#define readl(addr)        (*((volatile unsigned long  *)(addr)))
#define writeb(v, addr)    (*((volatile unsigned char  *)(addr)) = (unsigned char)(v))
#define writew(v, addr)    (*((volatile unsigned short *)(addr)) = (unsigned short)(v))
#define writel(v, addr)    (*((volatile unsigned long  *)(addr)) = (unsigned long)(v))
#endif


#ifdef KERNEL_34
static int setup_pinmux(void) {
    int cfg;
    int shift;
    unsigned int val = 0x6 ;    // function 0x6  = PA_EINT mode
    unsigned int reg, mask;

    //writel(0x00711112, Pn_CFG2_REG(GPIO_BANK_A));  // default register value
    
    void __iomem *base = __io_address(0x01c28000);
    printk("GPIO: base                     = 0x%lx, %s \n", (long unsigned int)base, GPIO_PIN_DESC);
    printk("GPIO: PIO_BASE                 = 0x%lx, %s \n", (long unsigned int)PIO_BASE, GPIO_PIN_DESC);

    // display CFG registers of GPIO_BANK_A
    printk("GPIO: Pn_CFG0_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG0_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG1_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG1_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG2_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG2_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG3_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG3_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    //
    printk("GPIO: PA_DAT             = 0x%.8lx, %s \n", readl(PA_DAT),            GPIO_PIN_DESC);
    printk("GPIO: PA_PULL            = 0x%.8lx, %s \n", readl(PA_PULL),            GPIO_PIN_DESC);
    printk("GPIO: PA_EINT_STATUS     = 0x%.8lx, %s \n", readl(PA_EINT_STATUS_REG), GPIO_PIN_DESC);
    printk("GPIO: PA_EINT_DEB_REG    = 0x%.8lx, %s \n", readl(PA_EINT_DEB_REG),    GPIO_PIN_DESC);
    printk("GPIO: PA_EINT_CFG_REG(0) = 0x%.8lx, %s \n", readl(PA_EINT_CFG_REG(0)),GPIO_PIN_DESC);
    printk("GPIO: PA_EINT_CTL_REG    = 0x%.8lx, %s \n", readl(PA_EINT_CTL_REG),    GPIO_PIN_DESC);

    printk("GPIO: writing to registers, %s \n", GPIO_PIN_DESC);

    //set PA19_SELECT to PA_EIN19
    // PAn_SELECT(GPIO_BANK_A, 19, 0x6);
    // bank  = (19*4)/32 = 2 = PA_CFG2
    // shift = (19*4)-(bank*32)/4
    cfg = (GPIO_PIN * 4) / 32;
    shift = ((GPIO_PIN * 4) - (cfg * 32)) ;
    mask = ~(0x0000000f << shift);
    val = val << shift;
    printk("GPIO: cfg=%d, shift=%d, mask=0x%.8lx,  %s \n", cfg, shift, mask, GPIO_PIN_DESC);
    switch (cfg){
    case 0:
        reg = readl(Pn_CFG0_REG(GPIO_BANK_A));
        reg &= mask;
        reg |= val;
        writel(reg, Pn_CFG0_REG(GPIO_BANK_A));
        break;
    case 1:
        reg = readl(Pn_CFG1_REG(GPIO_BANK_A));
        reg &= mask;
        reg |= val;
        writel(reg, Pn_CFG1_REG(GPIO_BANK_A));
        break;
    case 2:
        reg = readl(Pn_CFG2_REG(GPIO_BANK_A));
        reg &= mask;
        reg |= val;
        writel(reg, Pn_CFG2_REG(GPIO_BANK_A));
        break;
    case 3:
        reg = readl(Pn_CFG3_REG(GPIO_BANK_A));
        reg &= mask;
        reg |= val;
        writel(reg, Pn_CFG3_REG(GPIO_BANK_A));
        break;
    }
    printk("GPIO: Pn_CFG0_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG0_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG1_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG1_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG2_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG2_REG(GPIO_BANK_A)), GPIO_PIN_DESC);
    printk("GPIO: Pn_CFG3_REG(GPIO_BANK_A) = 0x%.8lx, %s \n", readl(Pn_CFG3_REG(GPIO_BANK_A)), GPIO_PIN_DESC);

the    // enable interrupt on PA19
    reg = readl(PA_EINT_CTL_REG);
    reg |= 1 << GPIO_PIN;
    writel(reg, PA_EINT_CTL_REG);
    printk("GPIO: PA_EINT_CTL_REG    = 0x%.8lx, %s \n", readl(PA_EINT_CTL_REG),    GPIO_PIN_DESC);
    printk("GPIO: PA_EINT_STATUS     = 0x%.8lx, %s \n", readl(PA_EINT_STATUS_REG), GPIO_PIN_DESC);

   return 0;
}
#endif


I could see in the dmesg printouts that the PA19-pin was configured properly but still i could only get interrupts to work if i use IRQF_TRIGGER_LOW.

After some reading on the Internet and instability issues with WiFi i decided to go with the latest mainline development kernel which uses device trees.  Executing the kernel module with low-level register programming on the mainline kernel resulted in Kernel-oops and segmentation faults. 
I modified /boot/dtb/sun8i-h3-orangepi-zeroplus.dts based on an example i found at http://geek-mag.com/posts/265668/ as follows and tested using the pulse-counter module presented at the same site:

 

/dts-v1/;
/ {
    interrupt-parent = <0x1>;
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    model = "Xunlong Orange Pi Zero Plus";
    compatible = "xunlong,orangepi-zeroplus", "allwinner,sun8i-h3";

    sst: pulse_counter {
       compatible = "gpio-pulse-counter";
       pi_irq_counter@0 {
          label = "sst_PA19_pulse_counter";
          pinctrl-names = "default";
          pinctrl-0 = <&ext_counter_PA19>;

          /* bank: 0, pin 19, function 6 */
          gpios = <&pio 0 19 6>;

          /* interrupt properties may be omitted if used gpios property */
          interrupt-parent = <&pio>;
          interrupt-names = "counter-edge-rising";
          interrupts = <19 0>; /* PA19 / EINT19 / rising edge*/
      };
   };

....

   pio: pinctrl@01c20800 {
         reg = <0x1c20800 0x400>;
         interrupts = <0x0 0xb 0x4 0x0 0x11 0x4>;
         clocks = <0x2 0x36 0x3 0x5>;
         clock-names = "apb", "hosc", "losc";
         gpio-controller;
         #gpio-cells = <0x3>;
         interrupt-controller;
         #interrupt-cells = <0x3>;
         compatible = "allwinner,sun8i-h3-pinctrl";
         linux,phandle = <0xd>;
         phandle = <0xd>;

....

         ext_counter_PA19: sst_pins@0 {
              allwinner,pins = "PA19";
              allwinner,function = "gpio_in";
              drive = <0>;
              pull = <1>;
        };
   };
};




Still the same issues, I could only get interrupts if i set IRQF_TRIGGER_LOW. After three weeks of reading, digging and diving on the Internet i had decided to test  gpio-PA19 using a switch connected with a pull-up resistor to 3.3v. pressing the switch will result in grounding PA19 and hence a rising edge pulse will be generated when the switch is released. To my surprise i got rising edge interrupts to work. Now y thaughts are shifting towards hardware issues so i grabbed a scope and function generator to monitor the activities on the gpio-pin PA19.
 
Here are some of my findings:

  1. Picture 1: adc_drdy_pulse_width.jpeg, pulse width 1us, frequency 2KHz - 128Khz depending on sampling frequency setup, no-interrupts detected
  2. Picture 2: adc-pulse-frequency.jpeg
  3. Picture 3: function-generator-pulse-50percent-duty.jpeg, frequency 50Hz, interrupts visible if i increase generator voltage to 4.3 volts. It seems that the gpio input load reduces the function-generator voltage from 3.3V to 2.7V and hence logic level voltages are not detected correctly.
  4.  

 

Conclusions:

interrupt activity detection is lowered as the frequency increases
@10KHz no more interrupts visible
@1% pulse duty cycle of 400Hz no more interrupts visible

Questions:
1) How do i activate hardware irq sampling on PA19 in mainline kernel?
2) How do i set irq-pin sampling debounce to 24MHz on mainline kernel?
3) Can the kernel handle high speed irq's

4) Why does are irqs not triggering when i increase the pulse frequency or lower pwm duty.

5) How can i do low level register programming in mainline kernel? 

 

Any help would be appreciated 

 

adc_drdy_pulse_width.jpeg

adc-pulse-frequency.jpeg

board-setup.jpeg

function-generator-pulse-50percent-duty.jpeg

irq_pulses-working.jpeg

push_button_switch.jpeg

Link to comment
Share on other sites

Here is a follow up on the latest changes:



cat /proc/interrupts shows 0 at pi_irq_counter, irq 64

           CPU0       CPU1       CPU2       CPU3       
...
 64:          0          0          0          0  sunxi_pio_edge  19 Edge      pi_irq_counter
...

sudo cat /sys/kernel/debug/gpio shows:

 

gpiochip0: GPIOs 0-223, parent: platform/1c20800.pinctrl, 1c20800.pinctrl:
 gpio-3   (                    |sst:red:led         ) out lo    
 gpio-9   (                    |reset               ) out hi    
 gpio-17  (                    |orangepi:red:status ) out lo    
 gpio-19  (                    |pi_irq_counter      ) in  lo IRQ
 gpio-102 (                    |usb1-vbus           ) out hi    
 gpio-107 (                    |sst:blue:led        ) out lo    
 gpio-166 (                    |cd                  ) in  hi    
 gpio-204 (                    |usb0_id_det         ) in  lo IRQ

Which suggests that gpio-19 was correctly set as an irq pin:

 

So i went back and tested with function generator by changing frequency and pulse widths and measuring the number of pulses /sec using the following script:

prevCount=0; 
while true;
do 
  count=`cat /proc/interrupts| grep --color=never 64:|sed "s/^[     ]*64:[  ]*\([0-9]*\)[   ].*$/\1/"`; 
  echo $count,$((count-prevCount));
  prevCount=$count;
  sleep 1;
done

here are the results:

 

dat1.txt: Pulse frequency increase from 50Hz to 8KHz are correct, errors start to occur above 8KHz 

dat2.txt: Changed pulse duty cycle from 50% to 1%, frequency 450Hz, errors start to occur below 2% pwm duty cycle

 

What do i need to change in order to capture the ADC pulses which have a pulse width of 1us? 

 

any help please!!!

 

 

 

 

 

Link to comment
Share on other sites

When I understand correctly, the interrupts you are sending have a rather short duration, i.e. within a microsecond.

 

It could be that the interrupt is polled by the Allwinner and/or kernel. Are you using the right clock source, I read somewhere that there is also a higher precision clock. Not sure how to set that up, hopefully someone in this forum can help you with that.

 

Another issue could be the input-debouncer, that is mainly useful when you attach a key/switch to the GPIO pin not with fast hardware. When this is set to a long value, it may average your interrupt signal away. I've played a bit with this debouncer (via gpio include file) , but got errors trying to set it directly on a GPIO pin.

Link to comment
Share on other sites

Yes the interrupts are short if the processor is polling, but this is quite normal for hardware trigger circuits. I looked up the datasheets and it seems that there are 2 frequency modes for input debounce but i have no idea how to set them. I have tried input-debounce = <1>; in the device tree but it makes no difference. Further i see no reference to a higher precision clock. It seems that the H3 is not suitable for this kind of design???

Link to comment
Share on other sites

Thanks for the link. But when i try to do low level programming of the registers on mainline kernel, using the code presented in my first post, I get a segmentation fault.  

Do you know how to obtain the base address of the registers on mainline kernel?

 

For legacy kernel 3.4 it is IO_ADDRESS(x) ((x) + 0xf0000000). 

 


 

Link to comment
Share on other sites

Gentlemen Thank you very much.

Both solutions work in a similar way by getting the base address from /dev/mem.

By writing 1 to the PA_EINT_DEB_REG which sets HSOSC24MHz on for the debounce filter i managed to get PA19 interrupts working.

# Read PA_EINT_CTL_REG
sudo devmem2 0x01c20a10
/dev/mem opened.
Memory mapped at address 0xb6f87000.
Value at address 0x1C20A10 (0xb6f87a10): 0x80000

#which indicates that PA19 is set to external interrupts (OK)

# Enable HSOSC by writing a 1 to PA_EINT_DEB_REG
sudo devmem2 0x01c20a18 w 1
/dev/mem opened.
Memory mapped at address 0xb6f38000.
Value at address 0x1C20A18 (0xb6f38a18): 0x1
Written 0x1; readback 0x1

I can go as high as 130Khz (which is more than sufficient in my case) after that jitter becomes a problem . 

 

138874405,130857
139005379,130974
139136288,130909
Link to comment
Share on other sites

Looking at the pinctrl driver code, input debouncing should be controllable from DT - by setting the "input-debounce" property of the pin controller.

Optional properties:
  - input-debounce: Array of debouncing periods in microseconds. One period per
    irq bank found in the controller. 0 if no setup required.

So for H3 it would be an array of 2 values. I guess devmem2 can be used to verify that debounce source and prescaler are set by this property.

Link to comment
Share on other sites

I have tried the to place input-debounce = <1 0>;  In multiple places in the device tree, as i do not understand exactly were to place it.

I just can not get it to work like this what am i doing wrong?

 

/dts-v1/;
/ {

...    
    counters {
                compatible =  "allwinner,sun8i-h3-pinctrl", "gpio-pulse-counter";
                pi_irq_counter@0 {
                        label = "sst_PA19_pulse_counter";
                        pinctrl-names = "default";
                        pinctrl-0 = <&ext_counter_PA19>;
                        /* CON3, pin 12: PH2 - pin 226 (Multi6 function: EINT2) */
                        /* bank: 226 / 32 = 7, pin into the bank 226 % 32 = 2 */
                        gpios = <&pio 0 19 6>;
                        /* interrupt properties may be omitted if used gpios property */
                        interrupt-parent = <&pio>;
                        interrupt-names = "counter-edge-rising";
                        interrupts = <0 19 0>; /* PA19 / EINT19 / rising edge*/
                        input-debounce = <0x1 0x0>;
                };
        };
        pio: pinctrl@01c20800 {
                        reg = <0x1c20800 0x400>;
                        interrupts = <0x0 0xb 0x4 0x0 0x11 0x4>;
                        clocks = <0x2 0x36 0x3 0x5>;
                        clock-names = "apb", "hosc", "losc";
                        gpio-controller;
                        #gpio-cells = <0x3>;
                        interrupt-controller;
                        #interrupt-cells = <0x3>;
                        compatible = "allwinner,sun8i-h3-pinctrl";
                        linux,phandle = <0xd>;
                        phandle = <0xd>;
                        input-debounce = <0x1 0x0>;
....

                       ext_counter_PA19: sst_pins@0 {
                                allwinner,pins = "PA19";
                                allwinner,function = "gpio_in";
                                allwinner,input-debounce = <1 1>;
                                allwinner,drive = <0>;
                                allwinner,pull = <1>;
                        };
        };
.....

};


 

Link to comment
Share on other sites

When i read the PA_EINT_DEB_REG using devmem2 i get the following:

 

sudo devmem2 0x01c20a18
/dev/mem opened.
Memory mapped at address 0xb6fa5000.
Value at address 0x1C20A18 (0xb6fa5a18): 0x51

 

Does this mean that the te debounce register is set to the correct oscilator 24MHZ but somthing else has written to the DEB_CLK_PRE_SCALE?


 

Link to comment
Share on other sites

57 minutes ago, Ohms said:

I have tried the to place input-debounce = <1 0>;  In multiple places in the device tree, as i do not understand exactly were to place it.

It should be in the pinctrl@01c20800 node

 

53 minutes ago, Ohms said:

Does this mean that the te debounce register is set to the correct oscilator 24MHZ but somthing else has written to the DEB_CLK_PRE_SCALE?

Setting input-debounce affects both the oscillator and prescaler bits, so it's not "something else" but the pinctrl driver: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/pinctrl/sunxi/pinctrl-sunxi.c#n1176

Link to comment
Share on other sites

I have done some tests with the input-debounce devicetree settings under the pinctrl on H5 (nanopi, kernel Linux nplus2 4.14.12-sunxi64). I discovered the following behaviour:

  • when I set the input-debounce to <0x1 0x3 0x4>, I read back the following with devmem2:
    • Value at address 0x1C20A18 (0xffff90bf6a18): 0x51, debounce on prescale=2^5, using HOSC timer
    • Value at address 0x1C20A38 (0xffffbc512a38): 0x61, debounce on prescale=2^6, using HOSC timer
    • Value at address 0x1C20A58 (0xffff9cbb4a58): 0x71, debounce on prescale=2^7, using HOSC timer

However, I would really like to enable the HOSC timer without any debounce. So I rewrote the setup_debounce kernel code to run in user-space (see attached), and analysed what is going on. The figure below shows the value written to the debounce register with increasing input-debounce value in the device tree. It appears that the HOSC timer is only used for input-debounce 1 upto 9 with written register values 0x51, 0x61, and 0x71. For input-debounce 10 upto 40 the register is set to 0, and after that it is gradually increased using the LOSC timer upto register value 0x70.
test.thumb.png.04282d5fa4ccee347f80d66e221b427c.png
This behavior is probably not what was intended with this code. And it would be great if all debounce registry settings (7 values for HOSC timer plus 7 values for LOSC timer) can all be used from the device tree input-debounce field. I propose to change the behavior for the first 40 values to the following:

  • input-debouce 0: keep default value
  • input-debouce 1..5: use HOSC with value 0, writing 0x1 to debounce register
  • input-debouce 6..10: use HOSC with value 1, writing 0x11 to debounce register
  • input-debouce 11..15..: use HOSC with value 2, writing 0x21 to debounce register
  • input-debouce 16..20: use HOSC with value 3, writing 0x31 to debounce register
  • input-debouce 21..25: use HOSC with value 4, writing 0x41 to debounce register
  • input-debouce 26..30: use HOSC with value 5, writing 0x51 to debounce register
  • input-debouce 31..35: use HOSC with value 6, writing 0x61 to debounce register
  • input-debouce 36..40: use HOSC with value 7, writing 0x71 to debounce register

This could be easily done using something like below instead of the hosc_freq&hosc_div code:
if (debounce<=40) {
  writel(((debounce-1)/5)<<4+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base));

  continue;

}

 

pinctr-sunxi-test.c

Link to comment
Share on other sites

A small update. The proposed fix removes low frequenty timer with prescaling 2^0. Probably better to mainly change the first 9 register values, so low frequenty timer stays mostly the same as before.

 

if (debounce<=16) {
  writel(((debounce/2-1))<<4+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base));

  continue;

}

Link to comment
Share on other sites

I just updated my test program with the patch to verify its workings, the main change is:

        if (debounce<=16) {

             writel((((debounce-1)/2)<<4)+1,sunxi_irq_debounce_reg_from_bank(i,pctl->desc->irq_bank_base));
            continue;
        }


Here is a further zoomed plot of the previous test program, showing the devicetree input-debounce for a pinctrl bank on x-axis versus the calculated debounce register entry.
test-zoomed.png.b85dd1cc035344fbc99cb977d4cdb740.png
Here is the plot for the new test program (see attached source), showing the devicetree input-debounce for the pinctrl bank on x-axis versus the calculated debounce register entry. One can clearly see that we now cover all debounce register values.

test2.png.7376f61988fd3ce3b3d877f3861f3060.png

 

pinctr-sunxi-test2.c

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines