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.c | 217 ++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 162 insertions(+), 55 deletions(-)
diff --git a/kernel/drivers/pinctrl/pinctrl-at91.c b/kernel/drivers/pinctrl/pinctrl-at91.c
index fad0e13..9015486 100644
--- a/kernel/drivers/pinctrl/pinctrl-at91.c
+++ b/kernel/drivers/pinctrl/pinctrl-at91.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* at91 pinctrl driver based on at91 pinmux core
*
* Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * Under GPLv2 only
*/
#include <linux/clk.h>
@@ -16,7 +15,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
@@ -59,11 +58,14 @@
#define OUTPUT (1 << 7)
#define OUTPUT_VAL_SHIFT 8
#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT)
+#define SLEWRATE_SHIFT 9
+#define SLEWRATE_MASK 0x1
+#define SLEWRATE (SLEWRATE_MASK << SLEWRATE_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
-/**
+/*
* These defines will translated the dt binding settings to our internal
* settings. They are not necessarily the same value as the register setting.
* The actual drive strength current of low, medium and high must be looked up
@@ -72,10 +74,22 @@
* DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive
* strength when there is no dt config for it.
*/
-#define DRIVE_STRENGTH_DEFAULT (0 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_LOW (1 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_MED (2 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_HI (3 << DRIVE_STRENGTH_SHIFT)
+enum drive_strength_bit {
+ DRIVE_STRENGTH_BIT_DEF,
+ DRIVE_STRENGTH_BIT_LOW,
+ DRIVE_STRENGTH_BIT_MED,
+ DRIVE_STRENGTH_BIT_HI,
+};
+
+#define DRIVE_STRENGTH_BIT_MSK(name) (DRIVE_STRENGTH_BIT_##name << \
+ DRIVE_STRENGTH_SHIFT)
+
+enum slewrate_bit {
+ SLEWRATE_BIT_ENA,
+ SLEWRATE_BIT_DIS,
+};
+
+#define SLEWRATE_BIT_MSK(name) (SLEWRATE_BIT_##name << SLEWRATE_SHIFT)
/**
* struct at91_pmx_func - describes AT91 pinmux functions
@@ -147,6 +161,10 @@
* @set_pulldown: enable/disable pulldown
* @get_schmitt_trig: get schmitt trigger status
* @disable_schmitt_trig: disable schmitt trigger
+ * @get_drivestrength: get driver strength
+ * @set_drivestrength: set driver strength
+ * @get_slewrate: get slew rate
+ * @set_slewrate: set slew rate
* @irq_type: return irq type
*/
struct at91_pinctrl_mux_ops {
@@ -166,6 +184,8 @@
unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
void (*set_drivestrength)(void __iomem *pio, unsigned pin,
u32 strength);
+ unsigned (*get_slewrate)(void __iomem *pio, unsigned pin);
+ void (*set_slewrate)(void __iomem *pio, unsigned pin, u32 slewrate);
/* irq */
int (*irq_type)(struct irq_data *d, unsigned type);
};
@@ -263,8 +283,8 @@
*/
grp = at91_pinctrl_find_group_by_name(info, np->name);
if (!grp) {
- dev_err(info->dev, "unable to find group for node %s\n",
- np->name);
+ dev_err(info->dev, "unable to find group for node %pOFn\n",
+ np);
return -EINVAL;
}
@@ -551,7 +571,7 @@
/* SAMA5 strength is 1:1 with our defines,
* except 0 is equivalent to low per datasheet */
if (!tmp)
- tmp = DRIVE_STRENGTH_LOW;
+ tmp = DRIVE_STRENGTH_BIT_MSK(LOW);
return tmp;
}
@@ -564,9 +584,30 @@
/* strength is inverse in SAM9x5s hardware with the pinctrl defines
* hardware: 0 = hi, 1 = med, 2 = low, 3 = rsvd */
- tmp = DRIVE_STRENGTH_HI - tmp;
+ tmp = DRIVE_STRENGTH_BIT_MSK(HI) - tmp;
return tmp;
+}
+
+static unsigned at91_mux_sam9x60_get_drivestrength(void __iomem *pio,
+ unsigned pin)
+{
+ unsigned tmp = readl_relaxed(pio + SAM9X60_PIO_DRIVER1);
+
+ if (tmp & BIT(pin))
+ return DRIVE_STRENGTH_BIT_HI;
+
+ return DRIVE_STRENGTH_BIT_LOW;
+}
+
+static unsigned at91_mux_sam9x60_get_slewrate(void __iomem *pio, unsigned pin)
+{
+ unsigned tmp = readl_relaxed(pio + SAM9X60_PIO_SLEWR);
+
+ if ((tmp & BIT(pin)))
+ return SLEWRATE_BIT_ENA;
+
+ return SLEWRATE_BIT_DIS;
}
static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength)
@@ -600,10 +641,49 @@
/* strength is inverse on SAM9x5s with our defines
* 0 = hi, 1 = med, 2 = low, 3 = rsvd */
- setting = DRIVE_STRENGTH_HI - setting;
+ setting = DRIVE_STRENGTH_BIT_MSK(HI) - setting;
set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin,
setting);
+}
+
+static void at91_mux_sam9x60_set_drivestrength(void __iomem *pio, unsigned pin,
+ u32 setting)
+{
+ unsigned int tmp;
+
+ if (setting <= DRIVE_STRENGTH_BIT_DEF ||
+ setting == DRIVE_STRENGTH_BIT_MED ||
+ setting > DRIVE_STRENGTH_BIT_HI)
+ return;
+
+ tmp = readl_relaxed(pio + SAM9X60_PIO_DRIVER1);
+
+ /* Strength is 0: low, 1: hi */
+ if (setting == DRIVE_STRENGTH_BIT_LOW)
+ tmp &= ~BIT(pin);
+ else
+ tmp |= BIT(pin);
+
+ writel_relaxed(tmp, pio + SAM9X60_PIO_DRIVER1);
+}
+
+static void at91_mux_sam9x60_set_slewrate(void __iomem *pio, unsigned pin,
+ u32 setting)
+{
+ unsigned int tmp;
+
+ if (setting < SLEWRATE_BIT_ENA || setting > SLEWRATE_BIT_DIS)
+ return;
+
+ tmp = readl_relaxed(pio + SAM9X60_PIO_SLEWR);
+
+ if (setting == SLEWRATE_BIT_DIS)
+ tmp &= ~BIT(pin);
+ else
+ tmp |= BIT(pin);
+
+ writel_relaxed(tmp, pio + SAM9X60_PIO_SLEWR);
}
static struct at91_pinctrl_mux_ops at91rm9200_ops = {
@@ -631,6 +711,27 @@
.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
.get_drivestrength = at91_mux_sam9x5_get_drivestrength,
.set_drivestrength = at91_mux_sam9x5_set_drivestrength,
+ .irq_type = alt_gpio_irq_type,
+};
+
+static const struct at91_pinctrl_mux_ops sam9x60_ops = {
+ .get_periph = at91_mux_pio3_get_periph,
+ .mux_A_periph = at91_mux_pio3_set_A_periph,
+ .mux_B_periph = at91_mux_pio3_set_B_periph,
+ .mux_C_periph = at91_mux_pio3_set_C_periph,
+ .mux_D_periph = at91_mux_pio3_set_D_periph,
+ .get_deglitch = at91_mux_pio3_get_deglitch,
+ .set_deglitch = at91_mux_pio3_set_deglitch,
+ .get_debounce = at91_mux_pio3_get_debounce,
+ .set_debounce = at91_mux_pio3_set_debounce,
+ .get_pulldown = at91_mux_pio3_get_pulldown,
+ .set_pulldown = at91_mux_pio3_set_pulldown,
+ .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+ .get_drivestrength = at91_mux_sam9x60_get_drivestrength,
+ .set_drivestrength = at91_mux_sam9x60_set_drivestrength,
+ .get_slewrate = at91_mux_sam9x60_get_slewrate,
+ .set_slewrate = at91_mux_sam9x60_set_slewrate,
.irq_type = alt_gpio_irq_type,
};
@@ -893,6 +994,8 @@
if (info->ops->get_drivestrength)
*config |= (info->ops->get_drivestrength(pio, pin)
<< DRIVE_STRENGTH_SHIFT);
+ if (info->ops->get_slewrate)
+ *config |= (info->ops->get_slewrate(pio, pin) << SLEWRATE_SHIFT);
if (at91_mux_get_output(pio, pin, &out))
*config |= OUTPUT | (out << OUTPUT_VAL_SHIFT);
@@ -944,6 +1047,9 @@
info->ops->set_drivestrength(pio, pin,
(config & DRIVE_STRENGTH)
>> DRIVE_STRENGTH_SHIFT);
+ if (info->ops->set_slewrate)
+ info->ops->set_slewrate(pio, pin,
+ (config & SLEWRATE) >> SLEWRATE_SHIFT);
} /* for each config */
@@ -959,11 +1065,11 @@
} \
} while (0)
-#define DBG_SHOW_FLAG_MASKED(mask,flag) do { \
+#define DBG_SHOW_FLAG_MASKED(mask, flag, name) do { \
if ((config & mask) == flag) { \
if (num_conf) \
seq_puts(s, "|"); \
- seq_puts(s, #flag); \
+ seq_puts(s, #name); \
num_conf++; \
} \
} while (0)
@@ -981,9 +1087,13 @@
DBG_SHOW_FLAG(PULL_DOWN);
DBG_SHOW_FLAG(DIS_SCHMIT);
DBG_SHOW_FLAG(DEGLITCH);
- DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_LOW);
- DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_MED);
- DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_HI);
+ DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_BIT_MSK(LOW),
+ DRIVE_STRENGTH_LOW);
+ DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_BIT_MSK(MED),
+ DRIVE_STRENGTH_MED);
+ DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_BIT_MSK(HI),
+ DRIVE_STRENGTH_HI);
+ DBG_SHOW_FLAG(SLEWRATE);
DBG_SHOW_FLAG(DEBOUNCE);
if (config & DEBOUNCE) {
val = config >> DEBOUNCE_VAL_SHIFT;
@@ -1071,7 +1181,7 @@
const __be32 *list;
int i, j;
- dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+ dev_dbg(info->dev, "group(%d): %pOFn\n", index, np);
/* Initialise group */
grp->name = np->name;
@@ -1122,7 +1232,7 @@
static u32 grp_index;
u32 i = 0;
- dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+ dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np);
func = &info->functions[index];
@@ -1155,6 +1265,7 @@
{ .compatible = "atmel,sama5d3-pinctrl", .data = &sama5d3_ops },
{ .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
{ .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
+ { .compatible = "microchip,sam9x60-pinctrl", .data = &sam9x60_ops },
{ /* sentinel */ }
};
@@ -1306,7 +1417,10 @@
u32 osr;
osr = readl_relaxed(pio + PIO_OSR);
- return !(osr & mask);
+ if (osr & mask)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
}
static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -1375,14 +1489,11 @@
int i;
struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
void __iomem *pio = at91_gpio->regbase;
+ const char *gpio_label;
- for (i = 0; i < chip->ngpio; i++) {
+ for_each_requested_gpio(chip, i, gpio_label) {
unsigned mask = pin_to_mask(i);
- const char *gpio_label;
- gpio_label = gpiochip_is_requested(chip, i);
- if (!gpio_label)
- continue;
mode = at91_gpio->ops->get_periph(pio, mask);
seq_printf(s, "[%s] GPIO%s%d: ",
gpio_label, chip->label, i);
@@ -1487,7 +1598,7 @@
return 0;
case IRQ_TYPE_NONE:
default:
- pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
+ pr_warn("AT91: No type for GPIO irq offset %d\n", d->irq);
return -EINVAL;
}
@@ -1615,9 +1726,11 @@
struct at91_gpio_chip *prev = NULL;
struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
struct irq_chip *gpio_irqchip;
- int ret, i;
+ struct gpio_irq_chip *girq;
+ int i;
- gpio_irqchip = devm_kzalloc(&pdev->dev, sizeof(*gpio_irqchip), GFP_KERNEL);
+ gpio_irqchip = devm_kzalloc(&pdev->dev, sizeof(*gpio_irqchip),
+ GFP_KERNEL);
if (!gpio_irqchip)
return -ENOMEM;
@@ -1639,33 +1752,30 @@
* handler will perform the actual work of handling the parent
* interrupt.
*/
- ret = gpiochip_irqchip_add(&at91_gpio->chip,
- gpio_irqchip,
- 0,
- handle_edge_irq,
- IRQ_TYPE_NONE);
- if (ret) {
- dev_err(&pdev->dev, "at91_gpio.%d: Couldn't add irqchip to gpiochip.\n",
- at91_gpio->pioc_idx);
- return ret;
- }
+ girq = &at91_gpio->chip.irq;
+ girq->chip = gpio_irqchip;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_edge_irq;
- /* The top level handler handles one bank of GPIOs, except
+ /*
+ * The top level handler handles one bank of GPIOs, except
* on some SoC it can handle up to three...
* We only set up the handler for the first of the list.
*/
gpiochip_prev = irq_get_handler_data(at91_gpio->pioc_virq);
if (!gpiochip_prev) {
- /* Then register the chain on the parent IRQ */
- gpiochip_set_chained_irqchip(&at91_gpio->chip,
- gpio_irqchip,
- at91_gpio->pioc_virq,
- gpio_irq_handler);
+ girq->parent_handler = gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(&pdev->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = at91_gpio->pioc_virq;
return 0;
}
prev = gpiochip_get_data(gpiochip_prev);
-
/* we can only have 2 banks before */
for (i = 0; i < 2; i++) {
if (prev->next) {
@@ -1697,13 +1807,13 @@
static const struct of_device_id at91_gpio_of_match[] = {
{ .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
{ .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
+ { .compatible = "microchip,sam9x60-gpio", .data = &sam9x60_ops },
{ /* sentinel */ }
};
static int at91_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct resource *res;
struct at91_gpio_chip *at91_chip = NULL;
struct gpio_chip *chip;
struct pinctrl_gpio_range *range;
@@ -1731,8 +1841,7 @@
goto err;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- at91_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
+ at91_chip->regbase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(at91_chip->regbase)) {
ret = PTR_ERR(at91_chip->regbase);
goto err;
@@ -1794,6 +1903,10 @@
range->npins = chip->ngpio;
range->gc = chip;
+ ret = at91_gpio_of_irq_setup(pdev, at91_chip);
+ if (ret)
+ goto gpiochip_add_err;
+
ret = gpiochip_add_data(chip, at91_chip);
if (ret)
goto gpiochip_add_err;
@@ -1801,16 +1914,10 @@
gpio_chips[alias_idx] = at91_chip;
gpio_banks = max(gpio_banks, alias_idx + 1);
- ret = at91_gpio_of_irq_setup(pdev, at91_chip);
- if (ret)
- goto irq_setup_err;
-
dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
return 0;
-irq_setup_err:
- gpiochip_remove(chip);
gpiochip_add_err:
clk_enable_err:
clk_disable_unprepare(at91_chip->clock);
--
Gitblit v1.6.2