[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220914122110.7246-1-pshete@nvidia.com>
Date: Wed, 14 Sep 2022 17:51:10 +0530
From: Prathamesh Shete <pshete@...dia.com>
To: <linus.walleij@...aro.org>, <bgolaszewski@...libre.com>,
<linux-gpio@...r.kernel.org>, <linux-tegra@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <jonathanh@...dia.com>,
<thierry.reding@...il.com>
CC: <smangipudi@...dia.com>, <pshete@...dia.com>,
<kyarlagadda@...dia.com>, Manish Bhardwaj <mbhardwaj@...dia.com>
Subject: [PATCH] gpio: tegra186: Check GPIO pin permission before access.
This change checks if we have the necessary permission to
access the GPIO. For devices that have support for virtualisation
we need to check both the TEGRA186_GPIO_VM_REG and the
TEGRA186_GPIO_SCR_REG registers. For device that do not have
virtualisation support for GPIOs we only need to check the
TEGRA186_GPIO_SCR_REG register.
Signed-off-by: Manish Bhardwaj <mbhardwaj@...dia.com>
Signed-off-by: Prathamesh Shete <pshete@...dia.com>
---
drivers/gpio/gpio-tegra186.c | 71 ++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 54d9fa7da9c1..e6fc3c9b1e9f 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -26,6 +26,22 @@
#define TEGRA186_GPIO_INT_ROUTE_MAPPING(p, x) (0x14 + (p) * 0x20 + (x) * 4)
+#define TEGRA186_GPIO_VM_REG 0x00
+#define TEGRA186_GPIO_VM_RW_MASK 0x03
+#define TEGRA186_GPIO_SCR_REG 0x04
+#define TEGRA186_GPIO_SCR_DIFF 0x08
+#define TEGRA186_GPIO_SCR_BASE_DIFF 0x40
+#define TEGRA186_GPIO_SCR_SEC_WEN BIT(28)
+#define TEGRA186_GPIO_SCR_SEC_REN BIT(27)
+#define TEGRA186_GPIO_SCR_SEC_G1W BIT(9)
+#define TEGRA186_GPIO_SCR_SEC_G1R BIT(1)
+#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \
+ TEGRA186_GPIO_SCR_SEC_REN | \
+ TEGRA186_GPIO_SCR_SEC_G1R | \
+ TEGRA186_GPIO_SCR_SEC_G1W)
+#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \
+ TEGRA186_GPIO_SCR_SEC_REN)
+
/* control registers */
#define TEGRA186_GPIO_ENABLE_CONFIG 0x00
#define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)
@@ -77,6 +93,7 @@ struct tegra_gpio_soc {
unsigned int num_irqs_per_bank;
const struct tegra186_pin_range *pin_ranges;
+ bool has_vm_support;
unsigned int num_pin_ranges;
const char *pinmux;
bool has_gte;
@@ -129,6 +146,45 @@ static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
return gpio->base + offset + pin * 0x20;
}
+static void __iomem *tegra186_gpio_get_secure_base(struct tegra_gpio *gpio,
+ unsigned int pin)
+{
+ const struct tegra_gpio_port *port;
+ unsigned int offset;
+
+ port = tegra186_gpio_get_port(gpio, &pin);
+ if (!port)
+ return NULL;
+
+ offset = port->bank * 0x1000 + port->port * TEGRA186_GPIO_SCR_BASE_DIFF;
+
+ return gpio->secure + offset + pin * TEGRA186_GPIO_SCR_DIFF;
+}
+
+static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, u32 pin)
+{
+ void __iomem *secure;
+ u32 val;
+
+ secure = tegra186_gpio_get_secure_base(gpio, pin);
+
+ if (gpio->soc->has_vm_support) {
+ val = readl(secure + TEGRA186_GPIO_VM_REG);
+ if ((val & TEGRA186_GPIO_VM_RW_MASK) != TEGRA186_GPIO_VM_RW_MASK)
+ return false;
+ }
+
+ val = __raw_readl(secure + TEGRA186_GPIO_SCR_REG);
+
+ if ((val & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0)
+ return true;
+
+ if ((val & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS)
+ return true;
+
+ return false;
+}
+
static int tegra186_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
@@ -136,6 +192,9 @@ static int tegra186_gpio_get_direction(struct gpio_chip *chip,
void __iomem *base;
u32 value;
+ if (!tegra186_gpio_is_accessible(gpio, offset))
+ return -EPERM;
+
base = tegra186_gpio_get_base(gpio, offset);
if (WARN_ON(base == NULL))
return -ENODEV;
@@ -154,6 +213,9 @@ static int tegra186_gpio_direction_input(struct gpio_chip *chip,
void __iomem *base;
u32 value;
+ if (!tegra186_gpio_is_accessible(gpio, offset))
+ return -EPERM;
+
base = tegra186_gpio_get_base(gpio, offset);
if (WARN_ON(base == NULL))
return -ENODEV;
@@ -177,6 +239,9 @@ static int tegra186_gpio_direction_output(struct gpio_chip *chip,
void __iomem *base;
u32 value;
+ if (!tegra186_gpio_is_accessible(gpio, offset))
+ return -EPERM;
+
/* configure output level first */
chip->set(chip, offset, level);
@@ -293,6 +358,10 @@ static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
void __iomem *base;
u32 value;
+ if (!tegra186_gpio_is_accessible(gpio, offset)){
+ pr_err("GPIO not accessible\n");
+ return;
+ }
base = tegra186_gpio_get_base(gpio, offset);
if (WARN_ON(base == NULL))
return;
@@ -1042,6 +1111,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = {
.num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges),
.pin_ranges = tegra194_main_pin_ranges,
.pinmux = "nvidia,tegra194-pinmux",
+ .has_vm_support = true,
};
#define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \
@@ -1067,6 +1137,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
.instance = 1,
.num_irqs_per_bank = 8,
.has_gte = true,
+ .has_vm_support = false,
};
#define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
--
2.17.1
Powered by blists - more mailing lists