blob: 0bbde29810b44f859d6ba6f9c4c4a945df4de2cb [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
Patrice Chotard5d9950d2020-12-02 18:47:30 +01004 * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
Patrice Chotard5c121e12017-09-13 18:00:07 +02005 */
6
Patrick Delaunayecb23b52020-11-06 19:01:48 +01007#define LOG_CATEGORY UCLASS_RESET
8
Patrice Chotard5c121e12017-09-13 18:00:07 +02009#include <common.h>
10#include <dm.h>
11#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <malloc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020014#include <reset-uclass.h>
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020015#include <stm32_rcc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020016#include <asm/io.h>
Patrick Delaunayecb23b52020-11-06 19:01:48 +010017#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020019
Patrick Delaunay42905732020-10-15 15:01:11 +020020/* offset of register without set/clear management */
21#define RCC_MP_GCR_OFFSET 0x10C
22
Patrick Delaunayb925d622018-03-12 10:46:14 +010023/* reset clear offset for STM32MP RCC */
24#define RCC_CL 0x4
25
Patrice Chotard5c121e12017-09-13 18:00:07 +020026struct stm32_reset_priv {
27 fdt_addr_t base;
28};
29
Patrice Chotard5c121e12017-09-13 18:00:07 +020030static int stm32_reset_assert(struct reset_ctl *reset_ctl)
31{
32 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Patrice Chotard48186972021-04-28 13:42:45 +020033 int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
34 int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
Patrick Delaunayecb23b52020-11-06 19:01:48 +010035
36 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
37 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020038
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020039 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020040 if (bank != RCC_MP_GCR_OFFSET)
41 /* reset assert is done in rcc set register */
42 writel(BIT(offset), priv->base + bank);
43 else
44 clrbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010045 else
46 setbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020047
48 return 0;
49}
50
51static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
52{
53 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Patrice Chotard48186972021-04-28 13:42:45 +020054 int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
55 int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
Patrick Delaunayecb23b52020-11-06 19:01:48 +010056
57 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
58 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020059
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020060 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020061 if (bank != RCC_MP_GCR_OFFSET)
62 /* reset deassert is done in rcc clr register */
63 writel(BIT(offset), priv->base + bank + RCC_CL);
64 else
65 setbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010066 else
67 clrbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020068
69 return 0;
70}
71
72static const struct reset_ops stm32_reset_ops = {
Patrice Chotard5c121e12017-09-13 18:00:07 +020073 .rst_assert = stm32_reset_assert,
74 .rst_deassert = stm32_reset_deassert,
75};
76
77static int stm32_reset_probe(struct udevice *dev)
78{
79 struct stm32_reset_priv *priv = dev_get_priv(dev);
80
Patrick Delaunayb925d622018-03-12 10:46:14 +010081 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 }
Patrice Chotard5c121e12017-09-13 18:00:07 +020088
89 return 0;
90}
91
92U_BOOT_DRIVER(stm32_rcc_reset) = {
93 .name = "stm32_rcc_reset",
94 .id = UCLASS_RESET,
Patrice Chotard5c121e12017-09-13 18:00:07 +020095 .probe = stm32_reset_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -070096 .priv_auto = sizeof(struct stm32_reset_priv),
Patrice Chotard5c121e12017-09-13 18:00:07 +020097 .ops = &stm32_reset_ops,
98};