blob: 9d4f361b25193be84b0908be197fbd344e65b05a [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 <dm.h>
10#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <malloc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020013#include <reset-uclass.h>
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020014#include <stm32_rcc.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020015#include <asm/io.h>
Patrick Delaunayecb23b52020-11-06 19:01:48 +010016#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Patrice Chotard5c121e12017-09-13 18:00:07 +020018
Patrick Delaunay42905732020-10-15 15:01:11 +020019/* offset of register without set/clear management */
20#define RCC_MP_GCR_OFFSET 0x10C
21
Patrick Delaunayb925d622018-03-12 10:46:14 +010022/* reset clear offset for STM32MP RCC */
23#define RCC_CL 0x4
24
Patrice Chotard5c121e12017-09-13 18:00:07 +020025struct stm32_reset_priv {
26 fdt_addr_t base;
27};
28
Patrice Chotard5c121e12017-09-13 18:00:07 +020029static int stm32_reset_assert(struct reset_ctl *reset_ctl)
30{
31 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Patrice Chotard48186972021-04-28 13:42:45 +020032 int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
33 int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
Patrick Delaunayecb23b52020-11-06 19:01:48 +010034
35 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
36 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020037
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020038 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020039 if (bank != RCC_MP_GCR_OFFSET)
40 /* reset assert is done in rcc set register */
41 writel(BIT(offset), priv->base + bank);
42 else
43 clrbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010044 else
45 setbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020046
47 return 0;
48}
49
50static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
51{
52 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
Patrice Chotard48186972021-04-28 13:42:45 +020053 int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4;
54 int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE);
Patrick Delaunayecb23b52020-11-06 19:01:48 +010055
56 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
57 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020058
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020059 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020060 if (bank != RCC_MP_GCR_OFFSET)
61 /* reset deassert is done in rcc clr register */
62 writel(BIT(offset), priv->base + bank + RCC_CL);
63 else
64 setbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010065 else
66 clrbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020067
68 return 0;
69}
70
71static const struct reset_ops stm32_reset_ops = {
Patrice Chotard5c121e12017-09-13 18:00:07 +020072 .rst_assert = stm32_reset_assert,
73 .rst_deassert = stm32_reset_deassert,
74};
75
76static int stm32_reset_probe(struct udevice *dev)
77{
78 struct stm32_reset_priv *priv = dev_get_priv(dev);
79
Patrick Delaunayb925d622018-03-12 10:46:14 +010080 priv->base = dev_read_addr(dev);
81 if (priv->base == FDT_ADDR_T_NONE) {
82 /* for MFD, get address of parent */
83 priv->base = dev_read_addr(dev->parent);
84 if (priv->base == FDT_ADDR_T_NONE)
85 return -EINVAL;
86 }
Patrice Chotard5c121e12017-09-13 18:00:07 +020087
88 return 0;
89}
90
91U_BOOT_DRIVER(stm32_rcc_reset) = {
92 .name = "stm32_rcc_reset",
93 .id = UCLASS_RESET,
Patrice Chotard5c121e12017-09-13 18:00:07 +020094 .probe = stm32_reset_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -070095 .priv_auto = sizeof(struct stm32_reset_priv),
Patrice Chotard5c121e12017-09-13 18:00:07 +020096 .ops = &stm32_reset_ops,
97};