mtd: spinand: toshiba: Support for new Kioxia Serial NAND
[oweals/u-boot.git] / drivers / hwspinlock / stm32_hwspinlock.c
1 // 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>
10 #include <malloc.h>
11 #include <asm/io.h>
12 #include <linux/bitops.h>
13
14 #define STM32_MUTEX_COREID      BIT(8)
15 #define STM32_MUTEX_LOCK_BIT    BIT(31)
16 #define STM32_MUTEX_NUM_LOCKS   32
17
18 struct stm32mp1_hws_priv {
19         fdt_addr_t base;
20 };
21
22 static int stm32mp1_lock(struct udevice *dev, int index)
23 {
24         struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
25         u32 status;
26
27         if (index >= STM32_MUTEX_NUM_LOCKS)
28                 return -EINVAL;
29
30         status = readl(priv->base + index * sizeof(u32));
31         if (status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
32                 return -EBUSY;
33
34         writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID,
35                priv->base + index * sizeof(u32));
36
37         status = readl(priv->base + index * sizeof(u32));
38         if (status != (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
39                 return -EINVAL;
40
41         return 0;
42 }
43
44 static int stm32mp1_unlock(struct udevice *dev, int index)
45 {
46         struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
47
48         if (index >= STM32_MUTEX_NUM_LOCKS)
49                 return -EINVAL;
50
51         writel(STM32_MUTEX_COREID, priv->base + index * sizeof(u32));
52
53         return 0;
54 }
55
56 static int stm32mp1_hwspinlock_probe(struct udevice *dev)
57 {
58         struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
59         struct clk clk;
60         int ret;
61
62         priv->base = dev_read_addr(dev);
63         if (priv->base == FDT_ADDR_T_NONE)
64                 return -EINVAL;
65
66         ret = clk_get_by_index(dev, 0, &clk);
67         if (ret)
68                 return ret;
69
70         ret = clk_enable(&clk);
71         if (ret)
72                 clk_free(&clk);
73
74         return ret;
75 }
76
77 static const struct hwspinlock_ops stm32mp1_hwspinlock_ops = {
78         .lock = stm32mp1_lock,
79         .unlock = stm32mp1_unlock,
80 };
81
82 static const struct udevice_id stm32mp1_hwspinlock_ids[] = {
83         { .compatible = "st,stm32-hwspinlock" },
84         {}
85 };
86
87 U_BOOT_DRIVER(hwspinlock_stm32mp1) = {
88         .name = "hwspinlock_stm32mp1",
89         .id = UCLASS_HWSPINLOCK,
90         .of_match = stm32mp1_hwspinlock_ids,
91         .ops = &stm32mp1_hwspinlock_ops,
92         .probe = stm32mp1_hwspinlock_probe,
93         .priv_auto_alloc_size = sizeof(struct stm32mp1_hws_priv),
94 };