blob: 3c10cf14d85382212487126938fed4ee1bd1365d [file] [log] [blame]
developer1966afb2023-08-08 16:02:18 +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
developer5cca2e42023-08-24 17:39:15 +08008#include <linux/bitmap.h>
9#include <linux/bitops.h>
developer1966afb2023-08-08 16:02:18 +080010#include <linux/err.h>
11#include <linux/lockdep.h>
12#include <linux/spinlock.h>
13
14#include "pce/cls.h"
15#include "pce/internal.h"
16#include "pce/netsys.h"
17
18struct cls_hw {
developer5cca2e42023-08-24 17:39:15 +080019 struct cls_entry cls_tbl[FE_MEM_CLS_MAX_INDEX];
20 DECLARE_BITMAP(cls_used, FE_MEM_CLS_MAX_INDEX);
developer1966afb2023-08-08 16:02:18 +080021 spinlock_t lock;
22};
23
24struct cls_hw cls_hw;
25
26int mtk_pce_cls_enable(void)
27{
28 mtk_pce_netsys_setbits(GLO_MEM_CFG, GDM_CLS_EN);
29
30 return 0;
31}
32
33void mtk_pce_cls_disable(void)
34{
35 mtk_pce_netsys_clrbits(GLO_MEM_CFG, GDM_CLS_EN);
36}
37
38static void mtk_pce_cls_clean_up(void)
39{
40 struct fe_mem_msg msg = {
41 .cmd = FE_MEM_CMD_WRITE,
42 .type = FE_MEM_TYPE_CLS,
43 };
44 unsigned long flag;
45 int ret = 0;
46 u32 i = 0;
47
48 memset(&msg.raw, 0, sizeof(msg.raw));
49
50 spin_lock_irqsave(&cls_hw.lock, flag);
51
52 /* clean up cls table */
53 for (i = 0; i < FE_MEM_CLS_MAX_INDEX; i++) {
54 msg.index = i;
55 ret = mtk_pce_fe_mem_msg_send(&msg);
56 if (ret)
57 goto unlock;
58 }
59
60unlock:
61 spin_unlock_irqrestore(&cls_hw.lock, flag);
62}
63
64int mtk_pce_cls_init(struct platform_device *pdev)
65{
developer5cca2e42023-08-24 17:39:15 +080066 u32 i;
67
developer1966afb2023-08-08 16:02:18 +080068 spin_lock_init(&cls_hw.lock);
69
70 mtk_pce_cls_clean_up();
71
developer5cca2e42023-08-24 17:39:15 +080072 for (i = 0; i < FE_MEM_CLS_MAX_INDEX; i++)
73 cls_hw.cls_tbl[i].idx = i + 1;
74
developer1966afb2023-08-08 16:02:18 +080075 return 0;
76}
77
78void mtk_pce_cls_deinit(struct platform_device *pdev)
79{
80 mtk_pce_cls_clean_up();
81}
82
developer5cca2e42023-08-24 17:39:15 +080083int mtk_pce_cls_desc_read(struct cls_desc *cdesc, u32 idx)
developer1966afb2023-08-08 16:02:18 +080084{
85 struct fe_mem_msg msg;
86 int ret;
87
developer5cca2e42023-08-24 17:39:15 +080088 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
89 return -EINVAL;
developer1966afb2023-08-08 16:02:18 +080090
developer5cca2e42023-08-24 17:39:15 +080091 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CLS, idx);
developer1966afb2023-08-08 16:02:18 +080092
93 memset(&msg.raw, 0, sizeof(msg.raw));
94
95 ret = mtk_pce_fe_mem_msg_send(&msg);
96 if (ret)
97 return ret;
98
99 memcpy(cdesc, &msg.cdesc, sizeof(struct cls_desc));
100
101 return ret;
102}
103
developer5cca2e42023-08-24 17:39:15 +0800104int mtk_pce_cls_desc_write(struct cls_desc *cdesc, u32 idx)
developer1966afb2023-08-08 16:02:18 +0800105{
106 struct fe_mem_msg msg;
107
developer5cca2e42023-08-24 17:39:15 +0800108 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
109 return -EINVAL;
developer1966afb2023-08-08 16:02:18 +0800110
developer5cca2e42023-08-24 17:39:15 +0800111 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CLS, idx);
developer1966afb2023-08-08 16:02:18 +0800112
113 memset(&msg.raw, 0, sizeof(msg.raw));
114 memcpy(&msg.cdesc, cdesc, sizeof(struct cls_desc));
115
116 return mtk_pce_fe_mem_msg_send(&msg);
117}
118
developer5cca2e42023-08-24 17:39:15 +0800119int mtk_pce_cls_entry_write(struct cls_entry *cls)
developer1966afb2023-08-08 16:02:18 +0800120{
developer5cca2e42023-08-24 17:39:15 +0800121 if (unlikely(!cls))
developer1966afb2023-08-08 16:02:18 +0800122 return -EINVAL;
123
developer5cca2e42023-08-24 17:39:15 +0800124 return mtk_pce_cls_desc_write(&cls->cdesc, cls->idx);
developer1966afb2023-08-08 16:02:18 +0800125}
developer5cca2e42023-08-24 17:39:15 +0800126EXPORT_SYMBOL(mtk_pce_cls_entry_write);
developer1966afb2023-08-08 16:02:18 +0800127
developer5cca2e42023-08-24 17:39:15 +0800128struct cls_entry *mtk_pce_cls_entry_alloc(void)
developer1966afb2023-08-08 16:02:18 +0800129{
developer5cca2e42023-08-24 17:39:15 +0800130 struct cls_entry *cls;
developer1966afb2023-08-08 16:02:18 +0800131 unsigned long flag;
developer5cca2e42023-08-24 17:39:15 +0800132 u32 idx;
developer1966afb2023-08-08 16:02:18 +0800133
134 spin_lock_irqsave(&cls_hw.lock, flag);
135
developer5cca2e42023-08-24 17:39:15 +0800136 idx = find_first_zero_bit(cls_hw.cls_used, FE_MEM_CLS_MAX_INDEX);
137 if (idx == FE_MEM_CLS_MAX_INDEX) {
138 cls = ERR_PTR(-ENOMEM);
developer1966afb2023-08-08 16:02:18 +0800139 goto unlock;
140 }
141
developer5cca2e42023-08-24 17:39:15 +0800142 set_bit(idx, cls_hw.cls_used);
developer1966afb2023-08-08 16:02:18 +0800143
developer5cca2e42023-08-24 17:39:15 +0800144 cls = &cls_hw.cls_tbl[idx];
145
146 memset(&cls->cdesc, 0, sizeof(cls->cdesc));
developer1966afb2023-08-08 16:02:18 +0800147
148unlock:
149 spin_unlock_irqrestore(&cls_hw.lock, flag);
150
developer5cca2e42023-08-24 17:39:15 +0800151 return cls;
developer1966afb2023-08-08 16:02:18 +0800152}
developer5cca2e42023-08-24 17:39:15 +0800153EXPORT_SYMBOL(mtk_pce_cls_entry_alloc);
developer1966afb2023-08-08 16:02:18 +0800154
developer5cca2e42023-08-24 17:39:15 +0800155void mtk_pce_cls_entry_free(struct cls_entry *cls)
developer1966afb2023-08-08 16:02:18 +0800156{
developer1966afb2023-08-08 16:02:18 +0800157 unsigned long flag;
developer1966afb2023-08-08 16:02:18 +0800158
developer5cca2e42023-08-24 17:39:15 +0800159 if (!cls)
developer1966afb2023-08-08 16:02:18 +0800160 return;
161
developer1966afb2023-08-08 16:02:18 +0800162 spin_lock_irqsave(&cls_hw.lock, flag);
developer5cca2e42023-08-24 17:39:15 +0800163 clear_bit(cls->idx - 1, cls_hw.cls_used);
developer1966afb2023-08-08 16:02:18 +0800164 spin_unlock_irqrestore(&cls_hw.lock, flag);
165}
developer5cca2e42023-08-24 17:39:15 +0800166EXPORT_SYMBOL(mtk_pce_cls_entry_free);