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