blob: 74afb4aec22b8812e951aecb399c22e5c94903e9 [file] [log] [blame]
Benjamin Gaignard77611122018-11-27 13:49:52 +01001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
6#include <common.h>
7#include <clk.h>
8#include <dm.h>
9#include <hwspinlock.h>
Simon Glass9bc15642020-02-03 07:36:16 -070010#include <malloc.h>
Benjamin Gaignard77611122018-11-27 13:49:52 +010011#include <asm/io.h>
12
13#define STM32_MUTEX_COREID BIT(8)
14#define STM32_MUTEX_LOCK_BIT BIT(31)
15#define STM32_MUTEX_NUM_LOCKS 32
16
17struct stm32mp1_hws_priv {
18 fdt_addr_t base;
19};
20
21static int stm32mp1_lock(struct udevice *dev, int index)
22{
23 struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
24 u32 status;
25
26 if (index >= STM32_MUTEX_NUM_LOCKS)
27 return -EINVAL;
28
29 status = readl(priv->base + index * sizeof(u32));
30 if (status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
31 return -EBUSY;
32
33 writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID,
34 priv->base + index * sizeof(u32));
35
36 status = readl(priv->base + index * sizeof(u32));
37 if (status != (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
38 return -EINVAL;
39
40 return 0;
41}
42
43static int stm32mp1_unlock(struct udevice *dev, int index)
44{
45 struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
46
47 if (index >= STM32_MUTEX_NUM_LOCKS)
48 return -EINVAL;
49
50 writel(STM32_MUTEX_COREID, priv->base + index * sizeof(u32));
51
52 return 0;
53}
54
55static int stm32mp1_hwspinlock_probe(struct udevice *dev)
56{
57 struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
58 struct clk clk;
59 int ret;
60
61 priv->base = dev_read_addr(dev);
62 if (priv->base == FDT_ADDR_T_NONE)
63 return -EINVAL;
64
65 ret = clk_get_by_index(dev, 0, &clk);
66 if (ret)
67 return ret;
68
69 ret = clk_enable(&clk);
70 if (ret)
71 clk_free(&clk);
72
73 return ret;
74}
75
76static const struct hwspinlock_ops stm32mp1_hwspinlock_ops = {
77 .lock = stm32mp1_lock,
78 .unlock = stm32mp1_unlock,
79};
80
81static const struct udevice_id stm32mp1_hwspinlock_ids[] = {
82 { .compatible = "st,stm32-hwspinlock" },
83 {}
84};
85
86U_BOOT_DRIVER(hwspinlock_stm32mp1) = {
87 .name = "hwspinlock_stm32mp1",
88 .id = UCLASS_HWSPINLOCK,
89 .of_match = stm32mp1_hwspinlock_ids,
90 .ops = &stm32mp1_hwspinlock_ops,
91 .probe = stm32mp1_hwspinlock_probe,
92 .priv_auto_alloc_size = sizeof(struct stm32mp1_hws_priv),
93};