blob: 1723cf49d873df333b64bb2cdcef42f6fe36d1b5 [file] [log] [blame]
developere5e687d2023-08-08 16:05:33 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
8#include <linux/io.h>
9#include <linux/err.h>
10#include <linux/types.h>
11#include <linux/device.h>
12#include <linux/platform_device.h>
13
14#include "hwspinlock.h"
15
16#define SEMA_ID (BIT(CORE_AP))
17
18static void __iomem *base;
19
20static inline u32 hwspinlock_read(u32 reg)
21{
22 return readl(base + reg);
23}
24
25static inline void hwspinlock_write(u32 reg, u32 val)
26{
27 writel(val, base + reg);
28}
29
30static inline u32 __mtk_tops_hwspinlock_get_reg(enum hwspinlock_group grp, u32 slot)
31{
32 if (unlikely(slot >= HWSPINLOCK_SLOT_MAX || grp >= __HWSPINLOCK_GROUP_MAX))
33 return 0;
34
35 if (grp == HWSPINLOCK_GROUP_TOP)
36 return HWSPINLOCK_TOP_BASE + slot * 4;
37 else
38 return HWSPINLOCK_CLUST_BASE + slot * 4;
39}
40
41/*
42 * try take TOPS HW spinlock
43 * return 1 on success
44 * return 0 on failure
45 */
46int mtk_tops_hwspin_try_lock(enum hwspinlock_group grp, u32 slot)
47{
48 u32 reg = __mtk_tops_hwspinlock_get_reg(grp, slot);
49
50 WARN_ON(!reg);
51
52 hwspinlock_write(reg, SEMA_ID);
53
54 return hwspinlock_read(reg) == SEMA_ID ? 1 : 0;
55}
56
57void mtk_tops_hwspin_lock(enum hwspinlock_group grp, u32 slot)
58{
59 u32 reg = __mtk_tops_hwspinlock_get_reg(grp, slot);
60
61 WARN_ON(!reg);
62
63 do {
64 hwspinlock_write(reg, SEMA_ID);
65 } while (hwspinlock_read(reg) != SEMA_ID);
66}
67
68void mtk_tops_hwspin_unlock(enum hwspinlock_group grp, u32 slot)
69{
70 u32 reg = __mtk_tops_hwspinlock_get_reg(grp, slot);
71
72 WARN_ON(!reg);
73
74 if (hwspinlock_read(reg) == SEMA_ID)
75 hwspinlock_write(reg, SEMA_ID);
76}
77
78int mtk_tops_hwspinlock_init(struct platform_device *pdev)
79{
80 struct resource *res;
81
82 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tops-base");
83 if (!res)
84 return -ENXIO;
85
86 base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
87 if (!base)
88 return -ENOMEM;
89
90 return 0;
91}