blob: 5dda522a4eb7fedab2238a4312a9e235812915c1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Patrice Chotard5c121e12017-09-13 18:00:07 +02002/*
Patrice Chotard789ee0e2017-10-23 09:53:58 +02003 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
4 * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
Patrice Chotard5c121e12017-09-13 18:00:07 +02005 */
6
7#include <common.h>
8#include <dm.h>
9#include <errno.h>
Simon Glass9bc15642020-02-03 07:36:16 -070010#include <malloc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020011#include <reset-uclass.h>
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020012#include <stm32_rcc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020013#include <asm/io.h>
14
Patrick Delaunayb925d622018-03-12 10:46:14 +010015/* reset clear offset for STM32MP RCC */
16#define RCC_CL 0x4
17
Patrice Chotard5c121e12017-09-13 18:00:07 +020018struct stm32_reset_priv {
19 fdt_addr_t base;
20};
21
22static int stm32_reset_request(struct reset_ctl *reset_ctl)
23{
24 return 0;
25}
26
27static int stm32_reset_free(struct reset_ctl *reset_ctl)
28{
29 return 0;
30}
31
32static int stm32_reset_assert(struct reset_ctl *reset_ctl)
33{
34 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
35 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
36 int offset = reset_ctl->id % BITS_PER_LONG;
37 debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
38 reset_ctl->id, bank, offset);
39
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020040 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunayb925d622018-03-12 10:46:14 +010041 /* reset assert is done in rcc set register */
42 writel(BIT(offset), priv->base + bank);
43 else
44 setbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020045
46 return 0;
47}
48
49static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
50{
51 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
52 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
53 int offset = reset_ctl->id % BITS_PER_LONG;
54 debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
55 reset_ctl->id, bank, offset);
56
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020057 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunayb925d622018-03-12 10:46:14 +010058 /* reset deassert is done in rcc clr register */
59 writel(BIT(offset), priv->base + bank + RCC_CL);
60 else
61 clrbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020062
63 return 0;
64}
65
66static const struct reset_ops stm32_reset_ops = {
67 .request = stm32_reset_request,
Simon Glass1928cd42020-02-03 07:35:52 -070068 .rfree = stm32_reset_free,
Patrice Chotard5c121e12017-09-13 18:00:07 +020069 .rst_assert = stm32_reset_assert,
70 .rst_deassert = stm32_reset_deassert,
71};
72
73static int stm32_reset_probe(struct udevice *dev)
74{
75 struct stm32_reset_priv *priv = dev_get_priv(dev);
76
Patrick Delaunayb925d622018-03-12 10:46:14 +010077 priv->base = dev_read_addr(dev);
78 if (priv->base == FDT_ADDR_T_NONE) {
79 /* for MFD, get address of parent */
80 priv->base = dev_read_addr(dev->parent);
81 if (priv->base == FDT_ADDR_T_NONE)
82 return -EINVAL;
83 }
Patrice Chotard5c121e12017-09-13 18:00:07 +020084
85 return 0;
86}
87
88U_BOOT_DRIVER(stm32_rcc_reset) = {
89 .name = "stm32_rcc_reset",
90 .id = UCLASS_RESET,
Patrice Chotard5c121e12017-09-13 18:00:07 +020091 .probe = stm32_reset_probe,
92 .priv_auto_alloc_size = sizeof(struct stm32_reset_priv),
93 .ops = &stm32_reset_ops,
94};