Messages in this thread | | | From | "Kim, Milo" <> | Subject | RE: [PATCH 1/2] regmap-irq: use mask and val rather than using mask_buf_def | Date | Fri, 20 Jul 2012 07:08:15 +0000 |
| |
> 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
| |