From: Alexandre Courbot <gnurou@gmail.com>
To: Linus Walleij <linus.walleij@linaro.org>
Cc: Rojhalat Ibrahim <imr@rtschenk.de>,
Grant Likely <grant.likely@linaro.org>,
"linux-gpio@vger.kernel.org" <linux-gpio@vger.kernel.org>,
Gerhard Sittig <gsi@denx.de>, Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH 2/2][v3] gpio-mpc8xxx: add mpc8xxx_gpio_set_multiple function
Date: Sun, 1 Jun 2014 18:39:04 +0900 [thread overview]
Message-ID: <CAAVeFu+RSCjeKB2p72cCoJD652iQ2RFx32MT3HafwaUurzVvtg@mail.gmail.com> (raw)
In-Reply-To: <CACRpkdbneBDv0HxmZr6puthzAx_h-f9FnjUuBWbPEMBu9B8v5g@mail.gmail.com>
On Thu, May 29, 2014 at 10:27 PM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> On Tue, May 27, 2014 at 1:14 PM, Rojhalat Ibrahim <imr@rtschenk.de> wrote:
>
>> Add a set_multiple function to the MPC8xxx GPIO chip driver and thereby allow
>> for actual performance improvements when setting multiple outputs
>> simultaneously. In my case the time needed to configure an FPGA goes down from
>> 48 s to 19 s.
>
> OK that's substantial. We cannot deny this. Performance is awesome.
>
>> Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de>
>> ---
>> This patch depends on my previous patch "gpiolib: allow simultaneous setting
>> of multiple GPIO outputs".
>>
>> Change log:
>> v3: - change commit message
>> v2: - add this patch (v1 included only changes to gpiolib)
>>
>> drivers/gpio/gpio-mpc8xxx.c | 28 ++++++++++++++++++++++++++++
>> 1 file changed, 28 insertions(+)
>>
>> diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
>> index d7d6d72..d226f5c 100644
>> --- a/drivers/gpio/gpio-mpc8xxx.c
>> +++ b/drivers/gpio/gpio-mpc8xxx.c
>> @@ -105,6 +105,33 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
>> spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
>> }
>>
>> +static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
>> + u32 *mask, u32 *bits)
>> +{
>> + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
>> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
>> + unsigned long flags;
>> + int i;
>> +
>> + spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
>> +
>> + for (i = 0; i < gc->ngpio; i++) {
>> + if (*mask == 0)
>> + break;
>> + if (*mask & (1 << i)) {
>> + if ((*bits >> i) & 1)
>
> Use
> #include <linux/bitops.h>
>
> if (*mask & BIT(i)) {
> if ((*bits & BIT(i))
>
> ....
>
>> + mpc8xxx_gc->data |= mpc8xxx_gpio2mask(i);
>> + else
>> + mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(i);
>
> But hey:
>
> #define MPC8XXX_GPIO_PINS 32
>
> static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
> {
> return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
> }
>
> So what is happening? Bits are swizzled: bit 0 becomes
> bit 31, bit 1 becomes bit 30 ... bit 31 becomes bit 0.
> I'm actually for having a function
>
> u32 swizzle(u32 foo) {}
>
> In the kernel doing exactly this, because I read somewhere
> that there are ultimax ways for doing this. Namely so
> (drivers/crypto/ux500/cryp/cryp_core.c):
>
> /**
> * swap_bits_in_byte - mirror the bits in a byte
> * @b: the byte to be mirrored
> *
> * The bits are swapped the following way:
> * Byte b include bits 0-7, nibble 1 (n1) include bits 0-3 and
> * nibble 2 (n2) bits 4-7.
> *
> * Nibble 1 (n1):
> * (The "old" (moved) bit is replaced with a zero)
> * 1. Move bit 6 and 7, 4 positions to the left.
> * 2. Move bit 3 and 5, 2 positions to the left.
> * 3. Move bit 1-4, 1 position to the left.
> *
> * Nibble 2 (n2):
> * 1. Move bit 0 and 1, 4 positions to the right.
> * 2. Move bit 2 and 4, 2 positions to the right.
> * 3. Move bit 3-6, 1 position to the right.
> *
> * Combine the two nibbles to a complete and swapped byte.
> */
>
> static inline u8 swap_bits_in_byte(u8 b)
> {
> #define R_SHIFT_4_MASK (0xc0) /* Bits 6 and 7, right shift 4 */
> #define R_SHIFT_2_MASK (0x28) /* (After right shift 4) Bits 3 and 5,
> right shift 2 */
> #define R_SHIFT_1_MASK (0x1e) /* (After right shift 2) Bits 1-4,
> right shift 1 */
> #define L_SHIFT_4_MASK (0x03) /* Bits 0 and 1, left shift 4 */
> #define L_SHIFT_2_MASK (0x14) /* (After left shift 4) Bits 2 and 4,
> left shift 2 */
> #define L_SHIFT_1_MASK (0x78) /* (After left shift 1) Bits 3-6,
> left shift 1 */
>
> u8 n1;
> u8 n2;
>
> /* Swap most significant nibble */
> /* Right shift 4, bits 6 and 7 */
> n1 = ((b & R_SHIFT_4_MASK) >> 4) | (b & ~(R_SHIFT_4_MASK >> 4));
> /* Right shift 2, bits 3 and 5 */
> n1 = ((n1 & R_SHIFT_2_MASK) >> 2) | (n1 & ~(R_SHIFT_2_MASK >> 2));
> /* Right shift 1, bits 1-4 */
> n1 = (n1 & R_SHIFT_1_MASK) >> 1;
>
> /* Swap least significant nibble */
> /* Left shift 4, bits 0 and 1 */
> n2 = ((b & L_SHIFT_4_MASK) << 4) | (b & ~(L_SHIFT_4_MASK << 4));
> /* Left shift 2, bits 2 and 4 */
> n2 = ((n2 & L_SHIFT_2_MASK) << 2) | (n2 & ~(L_SHIFT_2_MASK << 2));
> /* Left shift 1, bits 3-6 */
> n2 = (n2 & L_SHIFT_1_MASK) << 1;
>
> return n1 | n2;
> }
>
> This can be extended to 16 and 32 bits so if this happens on
> many places in the kernel then it should be moved to
> <linux/bitops.h> or similar.
>
>> + *mask &= ~(1 << i);
>
> *mask &= ~BIT(i);
Linus, just for my own education do you have anything against
__clear_bit(*mask, BIT(i))?
>
>> + }
>> + }
>> + out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
>
> Yours,
> Linus Walleij
prev parent reply other threads:[~2014-06-01 9:39 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-27 11:14 [PATCH 2/2][v3] gpio-mpc8xxx: add mpc8xxx_gpio_set_multiple function Rojhalat Ibrahim
2014-05-29 13:27 ` Linus Walleij
2014-06-01 9:39 ` Alexandre Courbot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAAVeFu+RSCjeKB2p72cCoJD652iQ2RFx32MT3HafwaUurzVvtg@mail.gmail.com \
--to=gnurou@gmail.com \
--cc=broonie@kernel.org \
--cc=grant.likely@linaro.org \
--cc=gsi@denx.de \
--cc=imr@rtschenk.de \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).