Our customer discovered a kernel freeze when trying to initialize the Keypad driver in Linux. Looking a bit closer in why it exactly freezes we could pinpoint a single register read during the drivers initialization: In imx_keypad_config the driver reads the Keypad Data Register (KPDR) on which line the system freezes.
static void imx_keypad_config(struct imx_keypad *keypad)
unsigned short reg_val;
* Include enabled rows in interrupt generation (KPCR[7:0])
* Configure keypad columns as open-drain (KPCR[15:8])
reg_val = readw(keypad->mmio_base + KPCR);
reg_val |= keypad->rows_en_mask & 0xff; /* rows */
reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */
writew(reg_val, keypad->mmio_base + KPCR);
/* Write 0's to KPDR[15:8] (Colums) */
reg_val = readw(keypad->mmio_base + KPDR);<FREEZE>
reg_val &= 0x00ff;
writew(reg_val, keypad->mmio_base + KPDR);
We can also verify that with a simple read using U-Boot.. Other register in the same block seem to work fine:
=> md.w 0x30320004 1
30320004: 0000 ..
=> md.w 0x30320002 1
30320002: 0002 ..
=> md.w 0x30320006 1
As far as I understand there should be no limitations on when this register is readable. It is only byte or half-word addressable, and md.w is addressing it using a half-word read, so this should be a valid register access.
This is reproducible on our Colibri iMX7 modules as well as on a NXP MCIMX7SABRE Rev. C (mask 2N09P). I did not found a related errata.