RE: [PATCH 1/2] regmap-irq: use mask and val rather than usingmask_buf_def

From: Kim, Milo
Date: Fri Jul 20 2012 - 03:08:22 EST


> On Thu, Jul 19, 2012 at 09:04:39AM +0000, Kim, Milo wrote:
> > Default mask value is used when updating irq registers.
> > Rather than using mask_buf_def[], use mask and value explicitly.
>
> Why? What is the problem you are seeing and what is the intended
> effect
> of this change?

There are two reasons for this patch.
One is for better understanding about masking and updated bits.
The other is related with supporting interrupt-unmasked device.

(a) 'mask_buf & val_buf' VS 'mask_buf_def & mask_buf'
In my opinion, the mask_buf_def[] is 'masking bit' and the mask_buf[] is the 'value' to be updated when the IRQ is enabled/disabled.
The mask_buf_def[] means which bit is updated - that is exactly *mask bit*.
The value of mask_buf_def[] is copied from mask_buf[] when regmap_add_irq_chip() is called.
And then mask_buf_def[] is fixed value.
On the other hand, the mask_buf[] is variable. The value is updated whenever the IRQ is enabled/disabled.
Which is better understandable terminology ? 'mask and value' or 'default mask and updated mask'
I think 'mask & value' is more clear.

(b) supporting interrupt-unmasked device
There is different interrupt concept from interrupt-masked device.
To enable the IRQ, the register bit should be 1.
To update this value, the bit of IRQ value should be separated from the mask bit.

< Example >
Let me assume that enabling the IRQ0 and IRQ1 ... (8 bits register based)

(Interrupt mask device)
IRQ7 | IRQ6 | IRQ5 | IRQ4 | IRQ3 | IRQ2 | IRQ1 | IRQ0
1 1 1 1 1 1 0 0
Mask = 0xFC
Value = 0xFC (same as mask bit)

(Interrupt unmask device)
IRQ7 | IRQ6 | IRQ5 | IRQ4 | IRQ3 | IRQ2 | IRQ1 | IRQ0
0 0 0 0 0 0 1 1
Mask = 0xFC
Value = 0x03 (different from mask bit)

Let's move to regmap_irq data structure with two types.

(Interrupt mask device)
static struct regmap_irq foo_irqs[] = {
[FOO_IRQ0] = {
.reg_offset = 0;
.mask = BIT(0), /* 0x01 */
},
[FOO_IRQ1] = {
.reg_offset = 0;
.mask = BIT(1), /* 0x02 */
},
};

Initial time irq_enable() irq_enable()
Value (regmap_add_irq_chip) with IRQ0 with IRQ1
_______________________________________________________________
mask_buf_def 0x03 0x03 0x03
mask_buf 0x03 0xFE 0xFD
updated bits 0000 0011 xxxx xxx0 xxxx xx0x
(IRQ0,1 disabled) (IRQ0 enabled) (IRQ1 enabled)

Result: Works well.
Only one bit is cleared when the IRQ is enabled.

(Interrupt unmask device)
Case 1)
static struct regmap_irq foo_irqs[] = {
[FOO_IRQ0] = {
.reg_offset = 0;
.mask = BIT(0), /* 0x01 */
},
[FOO_IRQ1] = {
.reg_offset = 0;
.mask = BIT(1), /* 0x02 */
},
};

Initial time irq_enable() irq_enable()
Value (regmap_add_irq_chip) with IRQ0 with IRQ1
_______________________________________________________________
mask_buf_def 0x03 0x03 0x03
mask_buf 0x03 0xFE 0xFD
updated bits 0000 0011 xxxx xxx0 xxxx xx0x
(IRQ0,1 enabled) (IRQ0 disabled) (IRQ1 disabled)

Result: Not working.
Each IRQ is disabled. Other bits can be enabled not intentionally.

Case 2) What if changing the 'mask' to inverted bit as following.
static struct regmap_irq foo_irqs[] = {
[FOO_IRQ0] = {
.reg_offset = 0;
.mask = ~BIT(0), /* 0xFE */
},
[FOO_IRQ1] = {
.reg_offset = 0;
.mask = ~BIT(1), /* 0xFD */
},
};

Initial time irq_enable() irq_enable()
Value (regmap_add_irq_chip) with IRQ0 with IRQ1
_______________________________________________________________
mask_buf_def 0xFF 0xFF 0xFF
mask_buf 0xFF 0x01 0x02
updated bits 1111 1111 0000 0001 0000 0010
(All IRQs are enabled) (IRQ0 enabled, (IRQ1 enabled,
others are but others are disabled)
disabled)

Result: Not working.
Other bits are cleared except flagged IRQ.
Only one IRQ exists. Others are ignored.

In both cases, it doesn't work with interrupt-unmasked-register scheme.
To fix this issue, two patches were sent.
The mask and value should be separated -- (1) and different bit operation is required -- (2).
(1) [PATCH 1/2] regmap-irq: use mask and val rather than using mask_buf_def
(2) [PATCH 2/2] regmap-irq: support different type of irq register

And then the result will be as following.

(Interrupt mask device)

Initial time irq_enable() irq_enable()
Value (regmap_add_irq_chip) with IRQ0 with IRQ1
_______________________________________________________________
mask_buf 0x03 0x03 0x03
val_buf - 0xFE 0xFD
updated bits 0000 0011 xxxx xxx0 xxxx xx0x
(IRQ0,1 disabled) (IRQ0 enabled) (IRQ1 enabled)

(Interrupt unmask device)

Initial time irq_enable() irq_enable()
Value (regmap_add_irq_chip) with IRQ0 with IRQ1
_______________________________________________________________
mask_buf 0x03 0x03 0x03
val_buf - 0x01 0x02
updated bits 1111 1100 xxxx xxx1 xxxx xx1x
(IRQ0,1 disabled) (IRQ0 enabled) (IRQ1 enabled)


I'm not sure there is another device which supports the interrupt-unmasked register.
As far as I know, LP8788 is the only device :-(

Thanks !

Best Regards,
Milo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/