summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/stm32/pinctrl-stm32.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/stm32/pinctrl-stm32.c')
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c198
1 files changed, 131 insertions, 67 deletions
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 7aecd0efde07..57a33fb0f2d7 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -44,6 +44,7 @@
#define STM32_GPIO_LCKR 0x1c
#define STM32_GPIO_AFRL 0x20
#define STM32_GPIO_AFRH 0x24
+#define STM32_GPIO_SECCFGR 0x30
/* custom bitfield to backup pin status */
#define STM32_GPIO_BKP_MODE_SHIFT 0
@@ -95,6 +96,7 @@ struct stm32_gpio_bank {
u32 bank_ioport_nr;
u32 pin_backup[STM32_GPIO_PINS_PER_BANK];
u8 irq_type[STM32_GPIO_PINS_PER_BANK];
+ bool secure_control;
};
struct stm32_pinctrl {
@@ -198,11 +200,7 @@ static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
if (!value)
offset += STM32_GPIO_PINS_PER_BANK;
- clk_enable(bank->clk);
-
writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR);
-
- clk_disable(bank->clk);
}
static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -226,25 +224,11 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset)
pinctrl_gpio_free(chip->base + offset);
}
-static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset)
-{
- struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
-
- return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
-}
-
static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
- int ret;
-
- clk_enable(bank->clk);
-
- ret = stm32_gpio_get_noclk(chip, offset);
- clk_disable(bank->clk);
-
- return ret;
+ return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
}
static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -302,6 +286,33 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
return ret;
}
+static int stm32_gpio_init_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+ struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
+ unsigned int i;
+ u32 sec;
+
+ /* All gpio are valid per default */
+ bitmap_fill(valid_mask, ngpios);
+
+ if (bank->secure_control) {
+ /* Tag secured pins as invalid */
+ sec = readl_relaxed(bank->base + STM32_GPIO_SECCFGR);
+
+ for (i = 0; i < ngpios; i++) {
+ if (sec & BIT(i)) {
+ clear_bit(i, valid_mask);
+ dev_dbg(pctl->dev, "No access to gpio %d - %d\n", bank->bank_nr, i);
+ }
+ }
+ }
+
+ return 0;
+}
+
static const struct gpio_chip stm32_gpio_template = {
.request = stm32_gpio_request,
.free = stm32_gpio_free,
@@ -312,6 +323,7 @@ static const struct gpio_chip stm32_gpio_template = {
.to_irq = stm32_gpio_to_irq,
.get_direction = stm32_gpio_get_direction,
.set_config = gpiochip_generic_config,
+ .init_valid_mask = stm32_gpio_init_valid_mask,
};
static void stm32_gpio_irq_trigger(struct irq_data *d)
@@ -324,7 +336,7 @@ static void stm32_gpio_irq_trigger(struct irq_data *d)
return;
/* If level interrupt type then retrig */
- level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq);
+ level = stm32_gpio_get(&bank->gpio_chip, d->hwirq);
if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) ||
(level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH))
irq_chip_retrigger_hierarchy(d);
@@ -366,7 +378,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
{
struct stm32_gpio_bank *bank = irq_data->domain->host_data;
struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent);
- unsigned long flags;
int ret;
ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq);
@@ -380,10 +391,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data)
return ret;
}
- flags = irqd_get_trigger_type(irq_data);
- if (flags & IRQ_TYPE_LEVEL_MASK)
- clk_enable(bank->clk);
-
return 0;
}
@@ -391,9 +398,6 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data)
{
struct stm32_gpio_bank *bank = irq_data->domain->host_data;
- if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK)
- clk_disable(bank->clk);
-
gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq);
}
@@ -534,7 +538,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin)
static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl,
u32 pin_num, u32 fnum)
{
- int i;
+ int i, k;
for (i = 0; i < pctl->npins; i++) {
const struct stm32_desc_pin *pin = pctl->pins + i;
@@ -543,7 +547,7 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl,
if (pin->pin.number != pin_num)
continue;
- while (func && func->name) {
+ for (k = 0; k < STM32_CONFIG_NUM; k++) {
if (func->num == fnum)
return true;
func++;
@@ -770,7 +774,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
unsigned long flags;
int err = 0;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
if (pctl->hwlock) {
@@ -799,7 +802,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return err;
}
@@ -812,7 +814,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
unsigned long flags;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
val = readl_relaxed(bank->base + alt_offset);
@@ -824,7 +825,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode,
*mode = val >> (pin * 2);
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
}
static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
@@ -868,12 +868,32 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
return stm32_pmx_set_mode(bank, pin, !input, 0);
}
+static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned int gpio)
+{
+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pinctrl_gpio_range *range;
+
+ range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio);
+ if (!range) {
+ dev_err(pctl->dev, "No gpio range defined.\n");
+ return -EINVAL;
+ }
+
+ if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) {
+ dev_warn(pctl->dev, "Can't access gpio %d\n", gpio);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
static const struct pinmux_ops stm32_pmx_ops = {
.get_functions_count = stm32_pmx_get_funcs_cnt,
.get_function_name = stm32_pmx_get_func_name,
.get_function_groups = stm32_pmx_get_func_groups,
.set_mux = stm32_pmx_set_mux,
.gpio_set_direction = stm32_pmx_gpio_set_direction,
+ .request = stm32_pmx_request,
.strict = true,
};
@@ -887,7 +907,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
u32 val;
int err = 0;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
if (pctl->hwlock) {
@@ -911,7 +930,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return err;
}
@@ -922,14 +940,12 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank,
unsigned long flags;
u32 val;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
val &= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return (val >> offset);
}
@@ -942,7 +958,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
u32 val;
int err = 0;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
if (pctl->hwlock) {
@@ -966,7 +981,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return err;
}
@@ -977,14 +991,12 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank,
unsigned long flags;
u32 val;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
val &= GENMASK(offset * 2 + 1, offset * 2);
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return (val >> (offset * 2));
}
@@ -997,7 +1009,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
u32 val;
int err = 0;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
if (pctl->hwlock) {
@@ -1021,7 +1032,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
unlock:
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return err;
}
@@ -1032,14 +1042,12 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
unsigned long flags;
u32 val;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
val &= GENMASK(offset * 2 + 1, offset * 2);
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return (val >> (offset * 2));
}
@@ -1050,7 +1058,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
unsigned long flags;
u32 val;
- clk_enable(bank->clk);
spin_lock_irqsave(&bank->lock, flags);
if (dir)
@@ -1061,7 +1068,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
BIT(offset));
spin_unlock_irqrestore(&bank->lock, flags);
- clk_disable(bank->clk);
return val;
}
@@ -1084,6 +1090,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
bank = gpiochip_get_data(range->gc);
offset = stm32_gpio_pin(pin);
+ if (!gpiochip_line_is_valid(range->gc, offset)) {
+ dev_warn(pctl->dev, "Can't access gpio %d\n", pin);
+ return -EACCES;
+ }
+
switch (param) {
case PIN_CONFIG_DRIVE_PUSH_PULL:
ret = stm32_pconf_set_driving(bank, offset, 0);
@@ -1163,10 +1174,27 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
+static struct stm32_desc_pin *
+stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl,
+ unsigned int pin_number)
+{
+ struct stm32_desc_pin *pins = pctl->pins;
+ int i;
+
+ for (i = 0; i < pctl->npins; i++) {
+ if (pins->pin.number == pin_number)
+ return pins;
+ pins++;
+ }
+ return NULL;
+}
+
static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned int pin)
{
+ struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct stm32_desc_pin *pin_desc;
struct pinctrl_gpio_range *range;
struct stm32_gpio_bank *bank;
int offset;
@@ -1186,6 +1214,11 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
bank = gpiochip_get_data(range->gc);
offset = stm32_gpio_pin(pin);
+ if (!gpiochip_line_is_valid(range->gc, offset)) {
+ seq_puts(s, "NO ACCESS");
+ return;
+ }
+
stm32_pmx_get_mode(bank, offset, &mode, &alt);
bias = stm32_pconf_get_bias(bank, offset);
@@ -1216,7 +1249,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
case 2:
drive = stm32_pconf_get_driving(bank, offset);
speed = stm32_pconf_get_speed(bank, offset);
- seq_printf(s, "%d - %s - %s - %s %s", alt,
+ pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin);
+ if (!pin_desc)
+ return;
+
+ seq_printf(s, "%d (%s) - %s - %s - %s %s", alt,
+ pin_desc->functions[alt + 1].name,
drive ? "open drain" : "push pull",
biasing[bias],
speeds[speed], "speed");
@@ -1256,9 +1294,9 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
if (IS_ERR(bank->base))
return PTR_ERR(bank->base);
- err = clk_prepare(bank->clk);
+ err = clk_prepare_enable(bank->clk);
if (err) {
- dev_err(dev, "failed to prepare clk (%d)\n", err);
+ dev_err(dev, "failed to prepare_enable clk (%d)\n", err);
return err;
}
@@ -1297,6 +1335,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
bank->gpio_chip.parent = dev;
bank->bank_nr = bank_nr;
bank->bank_ioport_nr = bank_ioport_nr;
+ bank->secure_control = pctl->match_data->secure_control;
spin_lock_init(&bank->lock);
/* create irq hierarchical domain */
@@ -1306,21 +1345,28 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
STM32_GPIO_IRQ_LINE, bank->fwnode,
&stm32_gpio_domain_ops, bank);
- if (!bank->domain)
- return -ENODEV;
+ if (!bank->domain) {
+ err = -ENODEV;
+ goto err_clk;
+ }
err = gpiochip_add_data(&bank->gpio_chip, bank);
if (err) {
dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr);
- return err;
+ goto err_clk;
}
dev_info(dev, "%s bank added\n", bank->gpio_chip.label);
return 0;
+
+err_clk:
+ clk_disable_unprepare(bank->clk);
+ return err;
}
-static struct irq_domain *stm32_pctrl_get_irq_domain(struct device_node *np)
+static struct irq_domain *stm32_pctrl_get_irq_domain(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct device_node *parent;
struct irq_domain *domain;
@@ -1424,7 +1470,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl,
if (pctl->pkg && !(pctl->pkg & p->pkg))
continue;
pins->pin = p->pin;
- pins->functions = p->functions;
+ memcpy((struct stm32_desc_pin *)pins->functions, p->functions,
+ STM32_CONFIG_NUM * sizeof(struct stm32_desc_function));
pins++;
nb_pins_available++;
}
@@ -1436,23 +1483,19 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl,
int stm32_pctl_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
+ const struct stm32_pinctrl_match_data *match_data;
struct fwnode_handle *child;
- const struct of_device_id *match;
struct device *dev = &pdev->dev;
struct stm32_pinctrl *pctl;
struct pinctrl_pin_desc *pins;
int i, ret, hwlock_id;
unsigned int banks;
- if (!np)
+ match_data = device_get_match_data(dev);
+ if (!match_data)
return -EINVAL;
- match = of_match_device(dev->driver->of_match_table, dev);
- if (!match || !match->data)
- return -EINVAL;
-
- if (!of_find_property(np, "pins-are-numbered", NULL)) {
+ if (!device_property_present(dev, "pins-are-numbered")) {
dev_err(dev, "only support pins-are-numbered format\n");
return -EINVAL;
}
@@ -1464,7 +1507,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pctl);
/* check for IRQ controller (may require deferred probe) */
- pctl->domain = stm32_pctrl_get_irq_domain(np);
+ pctl->domain = stm32_pctrl_get_irq_domain(pdev);
if (IS_ERR(pctl->domain))
return PTR_ERR(pctl->domain);
@@ -1480,10 +1523,10 @@ int stm32_pctl_probe(struct platform_device *pdev)
spin_lock_init(&pctl->irqmux_lock);
pctl->dev = dev;
- pctl->match_data = match->data;
+ pctl->match_data = match_data;
/* get optional package information */
- if (!of_property_read_u32(np, "st,package", &pctl->pkg))
+ if (!device_property_read_u32(dev, "st,package", &pctl->pkg))
dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg);
pctl->pins = devm_kcalloc(pctl->dev, pctl->match_data->npins,
@@ -1568,6 +1611,10 @@ int stm32_pctl_probe(struct platform_device *pdev)
ret = stm32_gpiolib_register_bank(pctl, child);
if (ret) {
fwnode_handle_put(child);
+
+ for (i = 0; i < pctl->nbanks; i++)
+ clk_disable_unprepare(pctl->banks[i].clk);
+
return ret;
}
@@ -1593,6 +1640,9 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
if (!range)
return 0;
+ if (!gpiochip_line_is_valid(range->gc, offset))
+ return 0;
+
pin_is_irq = gpiochip_line_is_irq(range->gc, offset);
if (!desc || (!pin_is_irq && !desc->gpio_owner))
@@ -1639,12 +1689,26 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs(
return 0;
}
+int __maybe_unused stm32_pinctrl_suspend(struct device *dev)
+{
+ struct stm32_pinctrl *pctl = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < pctl->nbanks; i++)
+ clk_disable(pctl->banks[i].clk);
+
+ return 0;
+}
+
int __maybe_unused stm32_pinctrl_resume(struct device *dev)
{
struct stm32_pinctrl *pctl = dev_get_drvdata(dev);
struct stm32_pinctrl_group *g = pctl->groups;
int i;
+ for (i = 0; i < pctl->nbanks; i++)
+ clk_enable(pctl->banks[i].clk);
+
for (i = 0; i < pctl->ngroups; i++, g++)
stm32_pinctrl_restore_gpio_regs(pctl, g->pin);