From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
kernel/drivers/pinctrl/pinctrl-at91-pio4.c | 103 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 81 insertions(+), 22 deletions(-)
diff --git a/kernel/drivers/pinctrl/pinctrl-at91-pio4.c b/kernel/drivers/pinctrl/pinctrl-at91-pio4.c
index 9e2f373..578b387 100644
--- a/kernel/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/kernel/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -1,24 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for the Atmel PIO4 controller
*
* Copyright (C) 2015 Atmel,
* 2015 Ludovic Desroches <ludovic.desroches@atmel.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <dt-bindings/pinctrl/at91.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
-/* FIXME: needed for gpio_to_irq(), get rid of this */
-#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/init.h>
@@ -116,6 +106,8 @@
* @irq_domain: irq domain for the gpio controller.
* @irqs: table containing the hw irq number of the bank. The index of the
* table is the bank id.
+ * @pm_wakeup_sources: bitmap of wakeup sources (lines)
+ * @pm_suspend_backup: backup/restore register values on suspend/resume
* @dev: device entry for the Atmel PIO controller.
* @node: node of the Atmel PIO controller.
*/
@@ -264,6 +256,13 @@
.irq_set_wake = atmel_gpio_irq_set_wake,
};
+static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
+
+ return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
+}
+
static void atmel_gpio_irq_handler(struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
@@ -297,8 +296,9 @@
break;
for_each_set_bit(n, &isr, BITS_PER_LONG)
- generic_handle_irq(gpio_to_irq(bank *
- ATMEL_PIO_NPINS_PER_BANK + n));
+ generic_handle_irq(atmel_gpio_to_irq(
+ atmel_pioctrl->gpio_chip,
+ bank * ATMEL_PIO_NPINS_PER_BANK + n));
}
chained_irq_exit(chip, desc);
@@ -328,6 +328,33 @@
reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR);
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,
@@ -360,18 +387,46 @@
BIT(pin->line));
}
-static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+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;
- return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
+ 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,
};
@@ -869,8 +924,7 @@
static int __maybe_unused atmel_pctrl_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(dev);
int i, j;
/*
@@ -898,8 +952,7 @@
static int __maybe_unused atmel_pctrl_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
+ struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(dev);
int i, j;
for (i = 0; i < atmel_pioctrl->nbanks; i++) {
@@ -930,10 +983,17 @@
.nbanks = 4,
};
+static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = {
+ .nbanks = 5,
+};
+
static const struct of_device_id atmel_pctrl_of_match[] = {
{
.compatible = "atmel,sama5d2-pinctrl",
.data = &atmel_sama5d2_pioctrl_data,
+ }, {
+ .compatible = "microchip,sama7g5-pinctrl",
+ .data = µchip_sama7g5_pioctrl_data,
}, {
/* sentinel */
}
@@ -966,10 +1026,9 @@
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;
+ return PTR_ERR(atmel_pioctrl->reg_base);
atmel_pioctrl->clk = devm_clk_get(dev, NULL);
if (IS_ERR(atmel_pioctrl->clk)) {
--
Gitblit v1.6.2