|
44 | 44 | #define STM32_GPIO_AFRL 0x20
|
45 | 45 | #define STM32_GPIO_AFRH 0x24
|
46 | 46 |
|
| 47 | +/* custom bitfield to backup pin status */ |
| 48 | +#define STM32_GPIO_BKP_MODE_SHIFT 0 |
| 49 | +#define STM32_GPIO_BKP_MODE_MASK GENMASK(1, 0) |
| 50 | +#define STM32_GPIO_BKP_ALT_SHIFT 2 |
| 51 | +#define STM32_GPIO_BKP_ALT_MASK GENMASK(5, 2) |
| 52 | +#define STM32_GPIO_BKP_SPEED_SHIFT 6 |
| 53 | +#define STM32_GPIO_BKP_SPEED_MASK GENMASK(7, 6) |
| 54 | +#define STM32_GPIO_BKP_PUPD_SHIFT 8 |
| 55 | +#define STM32_GPIO_BKP_PUPD_MASK GENMASK(9, 8) |
| 56 | +#define STM32_GPIO_BKP_TYPE 10 |
| 57 | +#define STM32_GPIO_BKP_VAL 11 |
| 58 | + |
47 | 59 | #define STM32_GPIO_PINS_PER_BANK 16
|
48 | 60 | #define STM32_GPIO_IRQ_LINE 16
|
49 | 61 |
|
@@ -79,6 +91,7 @@ struct stm32_gpio_bank {
|
79 | 91 | struct irq_domain *domain;
|
80 | 92 | u32 bank_nr;
|
81 | 93 | u32 bank_ioport_nr;
|
| 94 | + u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; |
82 | 95 | };
|
83 | 96 |
|
84 | 97 | struct stm32_pinctrl {
|
@@ -133,11 +146,50 @@ static inline u32 stm32_gpio_get_alt(u32 function)
|
133 | 146 | return 0;
|
134 | 147 | }
|
135 | 148 |
|
| 149 | +static void stm32_gpio_backup_value(struct stm32_gpio_bank *bank, |
| 150 | + u32 offset, u32 value) |
| 151 | +{ |
| 152 | + bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_VAL); |
| 153 | + bank->pin_backup[offset] |= value << STM32_GPIO_BKP_VAL; |
| 154 | +} |
| 155 | + |
| 156 | +static void stm32_gpio_backup_mode(struct stm32_gpio_bank *bank, u32 offset, |
| 157 | + u32 mode, u32 alt) |
| 158 | +{ |
| 159 | + bank->pin_backup[offset] &= ~(STM32_GPIO_BKP_MODE_MASK | |
| 160 | + STM32_GPIO_BKP_ALT_MASK); |
| 161 | + bank->pin_backup[offset] |= mode << STM32_GPIO_BKP_MODE_SHIFT; |
| 162 | + bank->pin_backup[offset] |= alt << STM32_GPIO_BKP_ALT_SHIFT; |
| 163 | +} |
| 164 | + |
| 165 | +static void stm32_gpio_backup_driving(struct stm32_gpio_bank *bank, u32 offset, |
| 166 | + u32 drive) |
| 167 | +{ |
| 168 | + bank->pin_backup[offset] &= ~BIT(STM32_GPIO_BKP_TYPE); |
| 169 | + bank->pin_backup[offset] |= drive << STM32_GPIO_BKP_TYPE; |
| 170 | +} |
| 171 | + |
| 172 | +static void stm32_gpio_backup_speed(struct stm32_gpio_bank *bank, u32 offset, |
| 173 | + u32 speed) |
| 174 | +{ |
| 175 | + bank->pin_backup[offset] &= ~STM32_GPIO_BKP_SPEED_MASK; |
| 176 | + bank->pin_backup[offset] |= speed << STM32_GPIO_BKP_SPEED_SHIFT; |
| 177 | +} |
| 178 | + |
| 179 | +static void stm32_gpio_backup_bias(struct stm32_gpio_bank *bank, u32 offset, |
| 180 | + u32 bias) |
| 181 | +{ |
| 182 | + bank->pin_backup[offset] &= ~STM32_GPIO_BKP_PUPD_MASK; |
| 183 | + bank->pin_backup[offset] |= bias << STM32_GPIO_BKP_PUPD_SHIFT; |
| 184 | +} |
| 185 | + |
136 | 186 | /* GPIO functions */
|
137 | 187 |
|
138 | 188 | static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
|
139 | 189 | unsigned offset, int value)
|
140 | 190 | {
|
| 191 | + stm32_gpio_backup_value(bank, offset, value); |
| 192 | + |
141 | 193 | if (!value)
|
142 | 194 | offset += STM32_GPIO_PINS_PER_BANK;
|
143 | 195 |
|
@@ -620,6 +672,8 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
|
620 | 672 | if (pctl->hwlock)
|
621 | 673 | hwspin_unlock(pctl->hwlock);
|
622 | 674 |
|
| 675 | + stm32_gpio_backup_mode(bank, pin, mode, alt); |
| 676 | + |
623 | 677 | unlock:
|
624 | 678 | spin_unlock_irqrestore(&bank->lock, flags);
|
625 | 679 | clk_disable(bank->clk);
|
@@ -732,6 +786,8 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
|
732 | 786 | if (pctl->hwlock)
|
733 | 787 | hwspin_unlock(pctl->hwlock);
|
734 | 788 |
|
| 789 | + stm32_gpio_backup_driving(bank, offset, drive); |
| 790 | + |
735 | 791 | unlock:
|
736 | 792 | spin_unlock_irqrestore(&bank->lock, flags);
|
737 | 793 | clk_disable(bank->clk);
|
@@ -784,6 +840,8 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
|
784 | 840 | if (pctl->hwlock)
|
785 | 841 | hwspin_unlock(pctl->hwlock);
|
786 | 842 |
|
| 843 | + stm32_gpio_backup_speed(bank, offset, speed); |
| 844 | + |
787 | 845 | unlock:
|
788 | 846 | spin_unlock_irqrestore(&bank->lock, flags);
|
789 | 847 | clk_disable(bank->clk);
|
@@ -836,6 +894,8 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
|
836 | 894 | if (pctl->hwlock)
|
837 | 895 | hwspin_unlock(pctl->hwlock);
|
838 | 896 |
|
| 897 | + stm32_gpio_backup_bias(bank, offset, bias); |
| 898 | + |
839 | 899 | unlock:
|
840 | 900 | spin_unlock_irqrestore(&bank->lock, flags);
|
841 | 901 | clk_disable(bank->clk);
|
@@ -1369,3 +1429,75 @@ int stm32_pctl_probe(struct platform_device *pdev)
|
1369 | 1429 |
|
1370 | 1430 | return 0;
|
1371 | 1431 | }
|
| 1432 | + |
| 1433 | +static int __maybe_unused stm32_pinctrl_restore_gpio_regs( |
| 1434 | + struct stm32_pinctrl *pctl, u32 pin) |
| 1435 | +{ |
| 1436 | + const struct pin_desc *desc = pin_desc_get(pctl->pctl_dev, pin); |
| 1437 | + u32 val, alt, mode, offset = stm32_gpio_pin(pin); |
| 1438 | + struct pinctrl_gpio_range *range; |
| 1439 | + struct stm32_gpio_bank *bank; |
| 1440 | + bool pin_is_irq; |
| 1441 | + int ret; |
| 1442 | + |
| 1443 | + range = pinctrl_find_gpio_range_from_pin(pctl->pctl_dev, pin); |
| 1444 | + if (!range) |
| 1445 | + return 0; |
| 1446 | + |
| 1447 | + pin_is_irq = gpiochip_line_is_irq(range->gc, offset); |
| 1448 | + |
| 1449 | + if (!desc || (!pin_is_irq && !desc->gpio_owner)) |
| 1450 | + return 0; |
| 1451 | + |
| 1452 | + bank = gpiochip_get_data(range->gc); |
| 1453 | + |
| 1454 | + alt = bank->pin_backup[offset] & STM32_GPIO_BKP_ALT_MASK; |
| 1455 | + alt >>= STM32_GPIO_BKP_ALT_SHIFT; |
| 1456 | + mode = bank->pin_backup[offset] & STM32_GPIO_BKP_MODE_MASK; |
| 1457 | + mode >>= STM32_GPIO_BKP_MODE_SHIFT; |
| 1458 | + |
| 1459 | + ret = stm32_pmx_set_mode(bank, offset, mode, alt); |
| 1460 | + if (ret) |
| 1461 | + return ret; |
| 1462 | + |
| 1463 | + if (mode == 1) { |
| 1464 | + val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_VAL); |
| 1465 | + val = val >> STM32_GPIO_BKP_VAL; |
| 1466 | + __stm32_gpio_set(bank, offset, val); |
| 1467 | + } |
| 1468 | + |
| 1469 | + val = bank->pin_backup[offset] & BIT(STM32_GPIO_BKP_TYPE); |
| 1470 | + val >>= STM32_GPIO_BKP_TYPE; |
| 1471 | + ret = stm32_pconf_set_driving(bank, offset, val); |
| 1472 | + if (ret) |
| 1473 | + return ret; |
| 1474 | + |
| 1475 | + val = bank->pin_backup[offset] & STM32_GPIO_BKP_SPEED_MASK; |
| 1476 | + val >>= STM32_GPIO_BKP_SPEED_SHIFT; |
| 1477 | + ret = stm32_pconf_set_speed(bank, offset, val); |
| 1478 | + if (ret) |
| 1479 | + return ret; |
| 1480 | + |
| 1481 | + val = bank->pin_backup[offset] & STM32_GPIO_BKP_PUPD_MASK; |
| 1482 | + val >>= STM32_GPIO_BKP_PUPD_SHIFT; |
| 1483 | + ret = stm32_pconf_set_bias(bank, offset, val); |
| 1484 | + if (ret) |
| 1485 | + return ret; |
| 1486 | + |
| 1487 | + if (pin_is_irq) |
| 1488 | + regmap_field_write(pctl->irqmux[offset], bank->bank_ioport_nr); |
| 1489 | + |
| 1490 | + return 0; |
| 1491 | +} |
| 1492 | + |
| 1493 | +int __maybe_unused stm32_pinctrl_resume(struct device *dev) |
| 1494 | +{ |
| 1495 | + struct stm32_pinctrl *pctl = dev_get_drvdata(dev); |
| 1496 | + struct stm32_pinctrl_group *g = pctl->groups; |
| 1497 | + int i; |
| 1498 | + |
| 1499 | + for (i = g->pin; i < g->pin + pctl->ngroups; i++) |
| 1500 | + stm32_pinctrl_restore_gpio_regs(pctl, i); |
| 1501 | + |
| 1502 | + return 0; |
| 1503 | +} |
0 commit comments