]> git.sur5r.net Git - u-boot/blob - drivers/reset/stm32-reset.c
arm64: a37xx: pinctrl: Correct mpp definitions
[u-boot] / drivers / reset / stm32-reset.c
1 /*
2  * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
3  * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <reset-uclass.h>
12 #include <asm/io.h>
13
14 /* reset clear offset for STM32MP RCC */
15 #define RCC_CL 0x4
16
17 enum rcc_type {
18         RCC_STM32 = 0,
19         RCC_STM32MP,
20 };
21
22 struct stm32_reset_priv {
23         fdt_addr_t base;
24 };
25
26 static int stm32_reset_request(struct reset_ctl *reset_ctl)
27 {
28         return 0;
29 }
30
31 static int stm32_reset_free(struct reset_ctl *reset_ctl)
32 {
33         return 0;
34 }
35
36 static int stm32_reset_assert(struct reset_ctl *reset_ctl)
37 {
38         struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
39         int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
40         int offset = reset_ctl->id % BITS_PER_LONG;
41         debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
42               reset_ctl->id, bank, offset);
43
44         if (dev_get_driver_data(reset_ctl->dev) == RCC_STM32MP)
45                 /* reset assert is done in rcc set register */
46                 writel(BIT(offset), priv->base + bank);
47         else
48                 setbits_le32(priv->base + bank, BIT(offset));
49
50         return 0;
51 }
52
53 static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
54 {
55         struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
56         int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
57         int offset = reset_ctl->id % BITS_PER_LONG;
58         debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
59               reset_ctl->id, bank, offset);
60
61         if (dev_get_driver_data(reset_ctl->dev) == RCC_STM32MP)
62                 /* reset deassert is done in rcc clr register */
63                 writel(BIT(offset), priv->base + bank + RCC_CL);
64         else
65                 clrbits_le32(priv->base + bank, BIT(offset));
66
67         return 0;
68 }
69
70 static const struct reset_ops stm32_reset_ops = {
71         .request        = stm32_reset_request,
72         .free           = stm32_reset_free,
73         .rst_assert     = stm32_reset_assert,
74         .rst_deassert   = stm32_reset_deassert,
75 };
76
77 static int stm32_reset_probe(struct udevice *dev)
78 {
79         struct stm32_reset_priv *priv = dev_get_priv(dev);
80
81         priv->base = dev_read_addr(dev);
82         if (priv->base == FDT_ADDR_T_NONE) {
83                 /* for MFD, get address of parent */
84                 priv->base = dev_read_addr(dev->parent);
85                 if (priv->base == FDT_ADDR_T_NONE)
86                         return -EINVAL;
87         }
88
89         return 0;
90 }
91
92 static const struct udevice_id stm32_reset_ids[] = {
93         { .compatible = "st,stm32mp1-rcc-rst", .data = RCC_STM32MP },
94         { }
95 };
96
97 U_BOOT_DRIVER(stm32_rcc_reset) = {
98         .name                   = "stm32_rcc_reset",
99         .id                     = UCLASS_RESET,
100         .of_match               = stm32_reset_ids,
101         .probe                  = stm32_reset_probe,
102         .priv_auto_alloc_size   = sizeof(struct stm32_reset_priv),
103         .ops                    = &stm32_reset_ops,
104 };