blob: daa2e47ebbe04e6629101128c99836ce7b2d4103 [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
30static int stm32_reset_request(struct reset_ctl *reset_ctl)
31{
32 return 0;
33}
34
35static int stm32_reset_free(struct reset_ctl *reset_ctl)
36{
37 return 0;
38}
39
40static int stm32_reset_assert(struct reset_ctl *reset_ctl)
41{
42 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
43 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
44 int offset = reset_ctl->id % BITS_PER_LONG;
Patrick Delaunayecb23b52020-11-06 19:01:48 +010045
46 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
47 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020048
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020049 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020050 if (bank != RCC_MP_GCR_OFFSET)
51 /* reset assert is done in rcc set register */
52 writel(BIT(offset), priv->base + bank);
53 else
54 clrbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010055 else
56 setbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020057
58 return 0;
59}
60
61static int stm32_reset_deassert(struct reset_ctl *reset_ctl)
62{
63 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
64 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
65 int offset = reset_ctl->id % BITS_PER_LONG;
Patrick Delaunayecb23b52020-11-06 19:01:48 +010066
67 dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n",
68 reset_ctl->id, bank, offset);
Patrice Chotard5c121e12017-09-13 18:00:07 +020069
Patrick Delaunayb139a5b2018-07-09 15:17:20 +020070 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunay42905732020-10-15 15:01:11 +020071 if (bank != RCC_MP_GCR_OFFSET)
72 /* reset deassert is done in rcc clr register */
73 writel(BIT(offset), priv->base + bank + RCC_CL);
74 else
75 setbits_le32(priv->base + bank, BIT(offset));
Patrick Delaunayb925d622018-03-12 10:46:14 +010076 else
77 clrbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard5c121e12017-09-13 18:00:07 +020078
79 return 0;
80}
81
82static const struct reset_ops stm32_reset_ops = {
83 .request = stm32_reset_request,
Simon Glass1928cd42020-02-03 07:35:52 -070084 .rfree = stm32_reset_free,
Patrice Chotard5c121e12017-09-13 18:00:07 +020085 .rst_assert = stm32_reset_assert,
86 .rst_deassert = stm32_reset_deassert,
87};
88
89static int stm32_reset_probe(struct udevice *dev)
90{
91 struct stm32_reset_priv *priv = dev_get_priv(dev);
92
Patrick Delaunayb925d622018-03-12 10:46:14 +010093 priv->base = dev_read_addr(dev);
94 if (priv->base == FDT_ADDR_T_NONE) {
95 /* for MFD, get address of parent */
96 priv->base = dev_read_addr(dev->parent);
97 if (priv->base == FDT_ADDR_T_NONE)
98 return -EINVAL;
99 }
Patrice Chotard5c121e12017-09-13 18:00:07 +0200100
101 return 0;
102}
103
104U_BOOT_DRIVER(stm32_rcc_reset) = {
105 .name = "stm32_rcc_reset",
106 .id = UCLASS_RESET,
Patrice Chotard5c121e12017-09-13 18:00:07 +0200107 .probe = stm32_reset_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700108 .priv_auto = sizeof(struct stm32_reset_priv),
Patrice Chotard5c121e12017-09-13 18:00:07 +0200109 .ops = &stm32_reset_ops,
110};