]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/pinctrl/pinctrl-at91-pio4.c
Merge tag 'for-linus-20191129' of git://git.kernel.dk/linux-block
[linux.git] / drivers / pinctrl / pinctrl-at91-pio4.c
index d6de4d360cd4f8a4c5a61e4368d7b82b73a9cbed..694912409fd9efbcb0970b0f59b44b2755c692f3 100644 (file)
@@ -328,6 +328,33 @@ static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset)
        return !!(reg & BIT(pin->line));
 }
 
+static int atmel_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+                                  unsigned long *bits)
+{
+       struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
+       unsigned int bank;
+
+       bitmap_zero(bits, atmel_pioctrl->npins);
+
+       for (bank = 0; bank < atmel_pioctrl->nbanks; bank++) {
+               unsigned int word = bank;
+               unsigned int offset = 0;
+               unsigned int reg;
+
+#if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG
+               word = BIT_WORD(bank * ATMEL_PIO_NPINS_PER_BANK);
+               offset = bank * ATMEL_PIO_NPINS_PER_BANK % BITS_PER_LONG;
+#endif
+               if (!mask[word])
+                       continue;
+
+               reg = atmel_gpio_read(atmel_pioctrl, bank, ATMEL_PIO_PDSR);
+               bits[word] |= mask[word] & (reg << offset);
+       }
+
+       return 0;
+}
+
 static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
                                       int value)
 {
@@ -358,11 +385,46 @@ static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
                         BIT(pin->line));
 }
 
+static void atmel_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+                                   unsigned long *bits)
+{
+       struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
+       unsigned int bank;
+
+       for (bank = 0; bank < atmel_pioctrl->nbanks; bank++) {
+               unsigned int bitmask;
+               unsigned int word = bank;
+
+/*
+ * On a 64-bit platform, BITS_PER_LONG is 64 so it is necessary to iterate over
+ * two 32bit words to handle the whole  bitmask
+ */
+#if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG
+               word = BIT_WORD(bank * ATMEL_PIO_NPINS_PER_BANK);
+#endif
+               if (!mask[word])
+                       continue;
+
+               bitmask = mask[word] & bits[word];
+               atmel_gpio_write(atmel_pioctrl, bank, ATMEL_PIO_SODR, bitmask);
+
+               bitmask = mask[word] & ~bits[word];
+               atmel_gpio_write(atmel_pioctrl, bank, ATMEL_PIO_CODR, bitmask);
+
+#if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG
+               mask[word] >>= ATMEL_PIO_NPINS_PER_BANK;
+               bits[word] >>= ATMEL_PIO_NPINS_PER_BANK;
+#endif
+       }
+}
+
 static struct gpio_chip atmel_gpio_chip = {
        .direction_input        = atmel_gpio_direction_input,
        .get                    = atmel_gpio_get,
+       .get_multiple           = atmel_gpio_get_multiple,
        .direction_output       = atmel_gpio_direction_output,
        .set                    = atmel_gpio_set,
+       .set_multiple           = atmel_gpio_set_multiple,
        .to_irq                 = atmel_gpio_to_irq,
        .base                   = 0,
 };
@@ -955,8 +1017,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
        atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks;
        atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       atmel_pioctrl->reg_base = devm_ioremap_resource(dev, res);
+       atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(atmel_pioctrl->reg_base))
                return -EINVAL;