HI, Samuel
If udelay is not accurate, then I think this is a big issue, can we first make sure udelay is accurate? How did you get the 18us when you only delay for 5us? By measuring the GPIO using a scope? Such as Before udelay 5us, we set a GPIO from high to low, then do the delay, then set the GPIO from low to high,now we can get the actual delay it goes from scope. Keep in mind that we need to disable IRQ when doing this test.
The udelay based on CPU loop, there is a global variable called loops_per_jiffies, every time CPU freq changelooping variable need to be updated. I think udelay should be accurate, otherwise, there shoul be big issue in kernel.
Can you please try to make sure udelay is accurate first? Try what I describe upper, disable IRQ, pull down/up a GPIO and using scope to measure the GPIO, then read the time from scope to see whether the interval of the GPIO status change is same as the delay time we set.
If udelay is accurate enough, then we can go on your case.