blob: 64a11cfcfc0a61329c0cf8e0e8d392505f4c7571 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Patrice Chotard23a06412017-09-13 18:00:07 +02002/*
Patrice Chotard3bc599c2017-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 Chotard23a06412017-09-13 18:00:07 +02005 */
6
7#include <common.h>
8#include <dm.h>
9#include <errno.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070011#include <malloc.h>
Patrice Chotard23a06412017-09-13 18:00:07 +020012#include <reset-uclass.h>
Patrick Delaunayd090cba2018-07-09 15:17:20 +020013#include <stm32_rcc.h>
Patrice Chotard23a06412017-09-13 18:00:07 +020014#include <asm/io.h>
Simon Glasscd93d622020-05-10 11:40:13 -060015#include <linux/bitops.h>
Patrice Chotard23a06412017-09-13 18:00:07 +020016
Patrick Delaunaya7519b32018-03-12 10:46:14 +010017/* reset clear offset for STM32MP RCC */
18#define RCC_CL 0x4
19
Patrice Chotard23a06412017-09-13 18:00:07 +020020struct stm32_reset_priv {
21 fdt_addr_t base;
22};
23
24static int stm32_reset_request(struct reset_ctl *reset_ctl)
25{
26 return 0;
27}
28
29static int stm32_reset_free(struct reset_ctl *reset_ctl)
30{
31 return 0;
32}
33
34static int stm32_reset_assert(struct reset_ctl *reset_ctl)
35{
36 struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev);
37 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
38 int offset = reset_ctl->id % BITS_PER_LONG;
39 debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
40 reset_ctl->id, bank, offset);
41
Patrick Delaunayd090cba2018-07-09 15:17:20 +020042 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunaya7519b32018-03-12 10:46:14 +010043 /* reset assert is done in rcc set register */
44 writel(BIT(offset), priv->base + bank);
45 else
46 setbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard23a06412017-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);
54 int bank = (reset_ctl->id / BITS_PER_LONG) * 4;
55 int offset = reset_ctl->id % BITS_PER_LONG;
56 debug("%s: reset id = %ld bank = %d offset = %d)\n", __func__,
57 reset_ctl->id, bank, offset);
58
Patrick Delaunayd090cba2018-07-09 15:17:20 +020059 if (dev_get_driver_data(reset_ctl->dev) == STM32MP1)
Patrick Delaunaya7519b32018-03-12 10:46:14 +010060 /* reset deassert is done in rcc clr register */
61 writel(BIT(offset), priv->base + bank + RCC_CL);
62 else
63 clrbits_le32(priv->base + bank, BIT(offset));
Patrice Chotard23a06412017-09-13 18:00:07 +020064
65 return 0;
66}
67
68static const struct reset_ops stm32_reset_ops = {
69 .request = stm32_reset_request,
Simon Glass94474b22020-02-03 07:35:52 -070070 .rfree = stm32_reset_free,
Patrice Chotard23a06412017-09-13 18:00:07 +020071 .rst_assert = stm32_reset_assert,
72 .rst_deassert = stm32_reset_deassert,
73};
74
75static int stm32_reset_probe(struct udevice *dev)
76{
77 struct stm32_reset_priv *priv = dev_get_priv(dev);
78
Patrick Delaunaya7519b32018-03-12 10:46:14 +010079 priv->base = dev_read_addr(dev);
80 if (priv->base == FDT_ADDR_T_NONE) {
81 /* for MFD, get address of parent */
82 priv->base = dev_read_addr(dev->parent);
83 if (priv->base == FDT_ADDR_T_NONE)
84 return -EINVAL;
85 }
Patrice Chotard23a06412017-09-13 18:00:07 +020086
87 return 0;
88}
89
90U_BOOT_DRIVER(stm32_rcc_reset) = {
91 .name = "stm32_rcc_reset",
92 .id = UCLASS_RESET,
Patrice Chotard23a06412017-09-13 18:00:07 +020093 .probe = stm32_reset_probe,
94 .priv_auto_alloc_size = sizeof(struct stm32_reset_priv),
95 .ops = &stm32_reset_ops,
96};