Я уже лет 10 занимался написанием драйверов для линуха, так что некоторый опыт есть. И эти вот Ваши идеи:
если делать 76 раз asm("nop"), то получается точно выдержать интервал 400 нс.
и
на время передачи данных делает spin_lock_irqsave()
кажутся мне довольно странными...Главная задача программиста при написании драйвера - уменьшить временные задержки, вносимые драйвером в работу ОС. А Вы делаете всё, что бы нарушить нормальную работу ядра. Но тогда не стоит удивляться, что результаты получаются какие-то странные!
Я по этим двум пунктам выскажусь так:
Для организации задержек на фиксированный интервал времени в ядре есть набор вызовов:
ndelay(unsigned long nsecs)
udelay(unsigned long usecs)
mdelay(unsigned long msecs)
Я думаю, их вполне достаточно для Ваших целей.
Далее, по поводу блокировки прерываний с помощью spin_lock_irqsave() Эта функция может использоваться только в очень ограниченные периоды времени. Использовать её во время выполнения операций ввода/вывода довольно сомнительно. тем более, если данные передаются из/в userspace. А если нужной страницы из userspace в этот момент нет в оперативной памяти? Я настоятельно рекомендую убрать эти вызовы.