xref: /dpdk/drivers/bus/dpaa/base/qbman/bman_driver.c (revision e9fd4b87f08d4da01ea9bde075f02e702b65a784)
1d81734caSHemant Agrawal /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2f09ede6cSShreyansh Jain  *
3f09ede6cSShreyansh Jain  * Copyright 2008-2016 Freescale Semiconductor Inc.
4d81734caSHemant Agrawal  * Copyright 2017 NXP
5f09ede6cSShreyansh Jain  *
6f09ede6cSShreyansh Jain  */
7f09ede6cSShreyansh Jain 
8f09ede6cSShreyansh Jain #include <rte_branch_prediction.h>
9f09ede6cSShreyansh Jain 
10f09ede6cSShreyansh Jain #include <fsl_usd.h>
11f09ede6cSShreyansh Jain #include <process.h>
12f09ede6cSShreyansh Jain #include "bman_priv.h"
13f09ede6cSShreyansh Jain #include <sys/ioctl.h>
14*e9fd4b87SNatanael Copa #include <err.h>
15f09ede6cSShreyansh Jain 
16f09ede6cSShreyansh Jain /*
17f09ede6cSShreyansh Jain  * Global variables of the max portal/pool number this bman version supported
18f09ede6cSShreyansh Jain  */
197d9c4dfaSHemant Agrawal static u16 bman_ip_rev;
20f09ede6cSShreyansh Jain u16 bman_pool_max;
217d9c4dfaSHemant Agrawal static void *bman_ccsr_map;
22f09ede6cSShreyansh Jain 
23f09ede6cSShreyansh Jain /*****************/
24f09ede6cSShreyansh Jain /* Portal driver */
25f09ede6cSShreyansh Jain /*****************/
26f09ede6cSShreyansh Jain 
278e253882SHemant Agrawal static __thread int bmfd = -1;
28f09ede6cSShreyansh Jain static __thread struct bm_portal_config pcfg;
29f09ede6cSShreyansh Jain static __thread struct dpaa_ioctl_portal_map map = {
30f09ede6cSShreyansh Jain 	.type = dpaa_portal_bman
31f09ede6cSShreyansh Jain };
32f09ede6cSShreyansh Jain 
fsl_bman_portal_init(uint32_t idx,int is_shared)33f09ede6cSShreyansh Jain static int fsl_bman_portal_init(uint32_t idx, int is_shared)
34f09ede6cSShreyansh Jain {
35f09ede6cSShreyansh Jain 	cpu_set_t cpuset;
36f38f61e9SShreyansh Jain 	struct bman_portal *portal;
37f09ede6cSShreyansh Jain 	int loop, ret;
38f09ede6cSShreyansh Jain 	struct dpaa_ioctl_irq_map irq_map;
39f09ede6cSShreyansh Jain 
40f09ede6cSShreyansh Jain 	/* Verify the thread's cpu-affinity */
41f09ede6cSShreyansh Jain 	ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
42f09ede6cSShreyansh Jain 				     &cpuset);
43f09ede6cSShreyansh Jain 	if (ret) {
44*e9fd4b87SNatanael Copa 		errno = ret;
45*e9fd4b87SNatanael Copa 		err(0, "pthread_getaffinity_np()");
46f09ede6cSShreyansh Jain 		return ret;
47f09ede6cSShreyansh Jain 	}
48f09ede6cSShreyansh Jain 	pcfg.cpu = -1;
49f09ede6cSShreyansh Jain 	for (loop = 0; loop < CPU_SETSIZE; loop++)
50f09ede6cSShreyansh Jain 		if (CPU_ISSET(loop, &cpuset)) {
51f09ede6cSShreyansh Jain 			if (pcfg.cpu != -1) {
52f09ede6cSShreyansh Jain 				pr_err("Thread is not affine to 1 cpu");
53f09ede6cSShreyansh Jain 				return -EINVAL;
54f09ede6cSShreyansh Jain 			}
55f09ede6cSShreyansh Jain 			pcfg.cpu = loop;
56f09ede6cSShreyansh Jain 		}
57f09ede6cSShreyansh Jain 	if (pcfg.cpu == -1) {
58f09ede6cSShreyansh Jain 		pr_err("Bug in getaffinity handling!");
59f09ede6cSShreyansh Jain 		return -EINVAL;
60f09ede6cSShreyansh Jain 	}
61f09ede6cSShreyansh Jain 	/* Allocate and map a bman portal */
62f09ede6cSShreyansh Jain 	map.index = idx;
63f09ede6cSShreyansh Jain 	ret = process_portal_map(&map);
64f09ede6cSShreyansh Jain 	if (ret) {
65*e9fd4b87SNatanael Copa 		errno = ret;
66*e9fd4b87SNatanael Copa 		err(0, "process_portal_map()");
67f09ede6cSShreyansh Jain 		return ret;
68f09ede6cSShreyansh Jain 	}
69f09ede6cSShreyansh Jain 	/* Make the portal's cache-[enabled|inhibited] regions */
70f09ede6cSShreyansh Jain 	pcfg.addr_virt[DPAA_PORTAL_CE] = map.addr.cena;
71f09ede6cSShreyansh Jain 	pcfg.addr_virt[DPAA_PORTAL_CI] = map.addr.cinh;
72f09ede6cSShreyansh Jain 	pcfg.is_shared = is_shared;
73f09ede6cSShreyansh Jain 	pcfg.index = map.index;
74f09ede6cSShreyansh Jain 	bman_depletion_fill(&pcfg.mask);
75f09ede6cSShreyansh Jain 
768e253882SHemant Agrawal 	bmfd = open(BMAN_PORTAL_IRQ_PATH, O_RDONLY);
778e253882SHemant Agrawal 	if (bmfd == -1) {
78f09ede6cSShreyansh Jain 		pr_err("BMan irq init failed");
79f09ede6cSShreyansh Jain 		process_portal_unmap(&map.addr);
80f09ede6cSShreyansh Jain 		return -EBUSY;
81f09ede6cSShreyansh Jain 	}
82f09ede6cSShreyansh Jain 	/* Use the IRQ FD as a unique IRQ number */
838e253882SHemant Agrawal 	pcfg.irq = bmfd;
84f09ede6cSShreyansh Jain 
85f38f61e9SShreyansh Jain 	portal = bman_create_affine_portal(&pcfg);
86f38f61e9SShreyansh Jain 	if (!portal) {
87f38f61e9SShreyansh Jain 		pr_err("Bman portal initialisation failed (%d)",
88f38f61e9SShreyansh Jain 		       pcfg.cpu);
89f38f61e9SShreyansh Jain 		process_portal_unmap(&map.addr);
90f38f61e9SShreyansh Jain 		return -EBUSY;
91f38f61e9SShreyansh Jain 	}
92f38f61e9SShreyansh Jain 
93f09ede6cSShreyansh Jain 	/* Set the IRQ number */
94f09ede6cSShreyansh Jain 	irq_map.type = dpaa_portal_bman;
95f09ede6cSShreyansh Jain 	irq_map.portal_cinh = map.addr.cinh;
968e253882SHemant Agrawal 	process_portal_irq_map(bmfd, &irq_map);
97f09ede6cSShreyansh Jain 	return 0;
98f09ede6cSShreyansh Jain }
99f09ede6cSShreyansh Jain 
fsl_bman_portal_finish(void)100f09ede6cSShreyansh Jain static int fsl_bman_portal_finish(void)
101f09ede6cSShreyansh Jain {
102f38f61e9SShreyansh Jain 	__maybe_unused const struct bm_portal_config *cfg;
103f09ede6cSShreyansh Jain 	int ret;
104f09ede6cSShreyansh Jain 
1058e253882SHemant Agrawal 	process_portal_irq_unmap(bmfd);
106f09ede6cSShreyansh Jain 
107f38f61e9SShreyansh Jain 	cfg = bman_destroy_affine_portal();
108f38f61e9SShreyansh Jain 	DPAA_BUG_ON(cfg != &pcfg);
109f09ede6cSShreyansh Jain 	ret = process_portal_unmap(&map.addr);
110*e9fd4b87SNatanael Copa 	if (ret) {
111*e9fd4b87SNatanael Copa 		errno = ret;
112*e9fd4b87SNatanael Copa 		err(0, "process_portal_unmap()");
113*e9fd4b87SNatanael Copa 	}
114f09ede6cSShreyansh Jain 	return ret;
115f09ede6cSShreyansh Jain }
116f09ede6cSShreyansh Jain 
bman_thread_fd(void)1178e253882SHemant Agrawal int bman_thread_fd(void)
1188e253882SHemant Agrawal {
1198e253882SHemant Agrawal 	return bmfd;
1208e253882SHemant Agrawal }
1218e253882SHemant Agrawal 
bman_thread_init(void)122f09ede6cSShreyansh Jain int bman_thread_init(void)
123f09ede6cSShreyansh Jain {
124f09ede6cSShreyansh Jain 	/* Convert from contiguous/virtual cpu numbering to real cpu when
125f09ede6cSShreyansh Jain 	 * calling into the code that is dependent on the device naming.
126f09ede6cSShreyansh Jain 	 */
127f09ede6cSShreyansh Jain 	return fsl_bman_portal_init(QBMAN_ANY_PORTAL_IDX, 0);
128f09ede6cSShreyansh Jain }
129f09ede6cSShreyansh Jain 
bman_thread_finish(void)130f09ede6cSShreyansh Jain int bman_thread_finish(void)
131f09ede6cSShreyansh Jain {
132f09ede6cSShreyansh Jain 	return fsl_bman_portal_finish();
133f09ede6cSShreyansh Jain }
134f09ede6cSShreyansh Jain 
bman_thread_irq(void)135f09ede6cSShreyansh Jain void bman_thread_irq(void)
136f09ede6cSShreyansh Jain {
137f09ede6cSShreyansh Jain 	qbman_invoke_irq(pcfg.irq);
138f09ede6cSShreyansh Jain 	/* Now we need to uninhibit interrupts. This is the only code outside
139f09ede6cSShreyansh Jain 	 * the regular portal driver that manipulates any portal register, so
140f09ede6cSShreyansh Jain 	 * rather than breaking that encapsulation I am simply hard-coding the
141f09ede6cSShreyansh Jain 	 * offset to the inhibit register here.
142f09ede6cSShreyansh Jain 	 */
143f09ede6cSShreyansh Jain 	out_be32(pcfg.addr_virt[DPAA_PORTAL_CI] + 0xe0c, 0);
144f09ede6cSShreyansh Jain }
145f09ede6cSShreyansh Jain 
bman_init_ccsr(const struct device_node * node)146f09ede6cSShreyansh Jain int bman_init_ccsr(const struct device_node *node)
147f09ede6cSShreyansh Jain {
148f09ede6cSShreyansh Jain 	static int ccsr_map_fd;
149f09ede6cSShreyansh Jain 	uint64_t phys_addr;
150f09ede6cSShreyansh Jain 	const uint32_t *bman_addr;
151f09ede6cSShreyansh Jain 	uint64_t regs_size;
152f09ede6cSShreyansh Jain 
153f09ede6cSShreyansh Jain 	bman_addr = of_get_address(node, 0, &regs_size, NULL);
154f09ede6cSShreyansh Jain 	if (!bman_addr) {
155f09ede6cSShreyansh Jain 		pr_err("of_get_address cannot return BMan address");
156f09ede6cSShreyansh Jain 		return -EINVAL;
157f09ede6cSShreyansh Jain 	}
158f09ede6cSShreyansh Jain 	phys_addr = of_translate_address(node, bman_addr);
159f09ede6cSShreyansh Jain 	if (!phys_addr) {
160f09ede6cSShreyansh Jain 		pr_err("of_translate_address failed");
161f09ede6cSShreyansh Jain 		return -EINVAL;
162f09ede6cSShreyansh Jain 	}
163f09ede6cSShreyansh Jain 
164f09ede6cSShreyansh Jain 	ccsr_map_fd = open(BMAN_CCSR_MAP, O_RDWR);
165f09ede6cSShreyansh Jain 	if (unlikely(ccsr_map_fd < 0)) {
166f09ede6cSShreyansh Jain 		pr_err("Can not open /dev/mem for BMan CCSR map");
167f09ede6cSShreyansh Jain 		return ccsr_map_fd;
168f09ede6cSShreyansh Jain 	}
169f09ede6cSShreyansh Jain 
170f09ede6cSShreyansh Jain 	bman_ccsr_map = mmap(NULL, regs_size, PROT_READ |
171f09ede6cSShreyansh Jain 			     PROT_WRITE, MAP_SHARED, ccsr_map_fd, phys_addr);
172f09ede6cSShreyansh Jain 	if (bman_ccsr_map == MAP_FAILED) {
173f09ede6cSShreyansh Jain 		pr_err("Can not map BMan CCSR base Bman: "
1740e5607e4SHemant Agrawal 		       "0x%x Phys: 0x%" PRIx64 " size 0x%" PRIu64,
175f09ede6cSShreyansh Jain 		       *bman_addr, phys_addr, regs_size);
176f09ede6cSShreyansh Jain 		return -EINVAL;
177f09ede6cSShreyansh Jain 	}
178f09ede6cSShreyansh Jain 
179f09ede6cSShreyansh Jain 	return 0;
180f09ede6cSShreyansh Jain }
181f09ede6cSShreyansh Jain 
bman_global_init(void)182f09ede6cSShreyansh Jain int bman_global_init(void)
183f09ede6cSShreyansh Jain {
184f09ede6cSShreyansh Jain 	const struct device_node *dt_node;
185f09ede6cSShreyansh Jain 	static int done;
186f09ede6cSShreyansh Jain 
187f09ede6cSShreyansh Jain 	if (done)
188f09ede6cSShreyansh Jain 		return -EBUSY;
189f09ede6cSShreyansh Jain 	/* Use the device-tree to determine IP revision until something better
190f09ede6cSShreyansh Jain 	 * is devised.
191f09ede6cSShreyansh Jain 	 */
192f09ede6cSShreyansh Jain 	dt_node = of_find_compatible_node(NULL, NULL, "fsl,bman-portal");
193f09ede6cSShreyansh Jain 	if (!dt_node) {
194f09ede6cSShreyansh Jain 		pr_err("No bman portals available for any CPU\n");
195f09ede6cSShreyansh Jain 		return -ENODEV;
196f09ede6cSShreyansh Jain 	}
197f09ede6cSShreyansh Jain 	if (of_device_is_compatible(dt_node, "fsl,bman-portal-1.0") ||
198f09ede6cSShreyansh Jain 	    of_device_is_compatible(dt_node, "fsl,bman-portal-1.0.0")) {
199f09ede6cSShreyansh Jain 		bman_ip_rev = BMAN_REV10;
200f09ede6cSShreyansh Jain 		bman_pool_max = 64;
201f09ede6cSShreyansh Jain 	} else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.0") ||
202f09ede6cSShreyansh Jain 		of_device_is_compatible(dt_node, "fsl,bman-portal-2.0.8")) {
203f09ede6cSShreyansh Jain 		bman_ip_rev = BMAN_REV20;
204f09ede6cSShreyansh Jain 		bman_pool_max = 8;
205f09ede6cSShreyansh Jain 	} else if (of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.0") ||
206f09ede6cSShreyansh Jain 		of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.1") ||
207f09ede6cSShreyansh Jain 		of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.2") ||
208f09ede6cSShreyansh Jain 		of_device_is_compatible(dt_node, "fsl,bman-portal-2.1.3")) {
209f09ede6cSShreyansh Jain 		bman_ip_rev = BMAN_REV21;
210f09ede6cSShreyansh Jain 		bman_pool_max = 64;
211f09ede6cSShreyansh Jain 	} else {
212f09ede6cSShreyansh Jain 		pr_warn("unknown BMan version in portal node,default "
213f09ede6cSShreyansh Jain 			"to rev1.0");
214f09ede6cSShreyansh Jain 		bman_ip_rev = BMAN_REV10;
215f09ede6cSShreyansh Jain 		bman_pool_max = 64;
216f09ede6cSShreyansh Jain 	}
217f09ede6cSShreyansh Jain 
218f09ede6cSShreyansh Jain 	if (!bman_ip_rev) {
219f09ede6cSShreyansh Jain 		pr_err("Unknown bman portal version\n");
220f09ede6cSShreyansh Jain 		return -ENODEV;
221f09ede6cSShreyansh Jain 	}
222f09ede6cSShreyansh Jain 	{
223f09ede6cSShreyansh Jain 		const struct device_node *dn = of_find_compatible_node(NULL,
224f09ede6cSShreyansh Jain 							NULL, "fsl,bman");
225f09ede6cSShreyansh Jain 		if (!dn)
226f09ede6cSShreyansh Jain 			pr_err("No bman device node available");
227f09ede6cSShreyansh Jain 
228f09ede6cSShreyansh Jain 		if (bman_init_ccsr(dn))
229f09ede6cSShreyansh Jain 			pr_err("BMan CCSR map failed.");
230f09ede6cSShreyansh Jain 	}
231f09ede6cSShreyansh Jain 
232f09ede6cSShreyansh Jain 	done = 1;
233f09ede6cSShreyansh Jain 	return 0;
234f09ede6cSShreyansh Jain }
235f09ede6cSShreyansh Jain 
236f09ede6cSShreyansh Jain #define BMAN_POOL_CONTENT(n) (0x0600 + ((n) * 0x04))
bm_pool_free_buffers(u32 bpid)237f09ede6cSShreyansh Jain u32 bm_pool_free_buffers(u32 bpid)
238f09ede6cSShreyansh Jain {
239f09ede6cSShreyansh Jain 	return in_be32(bman_ccsr_map + BMAN_POOL_CONTENT(bpid));
240f09ede6cSShreyansh Jain }
241f09ede6cSShreyansh Jain 
__generate_thresh(u32 val,int roundup)242f09ede6cSShreyansh Jain static u32 __generate_thresh(u32 val, int roundup)
243f09ede6cSShreyansh Jain {
244f09ede6cSShreyansh Jain 	u32 e = 0;      /* co-efficient, exponent */
245f09ede6cSShreyansh Jain 	int oddbit = 0;
246f09ede6cSShreyansh Jain 
247f09ede6cSShreyansh Jain 	while (val > 0xff) {
248f09ede6cSShreyansh Jain 		oddbit = val & 1;
249f09ede6cSShreyansh Jain 		val >>= 1;
250f09ede6cSShreyansh Jain 		e++;
251f09ede6cSShreyansh Jain 		if (roundup && oddbit)
252f09ede6cSShreyansh Jain 			val++;
253f09ede6cSShreyansh Jain 	}
254f09ede6cSShreyansh Jain 	DPAA_ASSERT(e < 0x10);
255f09ede6cSShreyansh Jain 	return (val | (e << 8));
256f09ede6cSShreyansh Jain }
257f09ede6cSShreyansh Jain 
258f09ede6cSShreyansh Jain #define POOL_SWDET(n)       (0x0000 + ((n) * 0x04))
259f09ede6cSShreyansh Jain #define POOL_HWDET(n)       (0x0100 + ((n) * 0x04))
260f09ede6cSShreyansh Jain #define POOL_SWDXT(n)       (0x0200 + ((n) * 0x04))
261f09ede6cSShreyansh Jain #define POOL_HWDXT(n)       (0x0300 + ((n) * 0x04))
bm_pool_set(u32 bpid,const u32 * thresholds)262f09ede6cSShreyansh Jain int bm_pool_set(u32 bpid, const u32 *thresholds)
263f09ede6cSShreyansh Jain {
264f09ede6cSShreyansh Jain 	if (!bman_ccsr_map)
265f09ede6cSShreyansh Jain 		return -ENODEV;
266f09ede6cSShreyansh Jain 	if (bpid >= bman_pool_max)
267f09ede6cSShreyansh Jain 		return -EINVAL;
268f09ede6cSShreyansh Jain 	out_be32(bman_ccsr_map + POOL_SWDET(bpid),
269f09ede6cSShreyansh Jain 		 __generate_thresh(thresholds[0], 0));
270f09ede6cSShreyansh Jain 	out_be32(bman_ccsr_map + POOL_SWDXT(bpid),
271f09ede6cSShreyansh Jain 		 __generate_thresh(thresholds[1], 1));
272f09ede6cSShreyansh Jain 	out_be32(bman_ccsr_map + POOL_HWDET(bpid),
273f09ede6cSShreyansh Jain 		 __generate_thresh(thresholds[2], 0));
274f09ede6cSShreyansh Jain 	out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
275f09ede6cSShreyansh Jain 		 __generate_thresh(thresholds[3], 1));
276f09ede6cSShreyansh Jain 	return 0;
277f09ede6cSShreyansh Jain }
278f09ede6cSShreyansh Jain 
279f09ede6cSShreyansh Jain #define BMAN_LOW_DEFAULT_THRESH		0x40
280f09ede6cSShreyansh Jain #define BMAN_HIGH_DEFAULT_THRESH		0x80
bm_pool_set_hw_threshold(u32 bpid,const u32 low_thresh,const u32 high_thresh)281f09ede6cSShreyansh Jain int bm_pool_set_hw_threshold(u32 bpid, const u32 low_thresh,
282f09ede6cSShreyansh Jain 			     const u32 high_thresh)
283f09ede6cSShreyansh Jain {
284f09ede6cSShreyansh Jain 	if (!bman_ccsr_map)
285f09ede6cSShreyansh Jain 		return -ENODEV;
286f09ede6cSShreyansh Jain 	if (bpid >= bman_pool_max)
287f09ede6cSShreyansh Jain 		return -EINVAL;
288f09ede6cSShreyansh Jain 	if (low_thresh && high_thresh) {
289f09ede6cSShreyansh Jain 		out_be32(bman_ccsr_map + POOL_HWDET(bpid),
290f09ede6cSShreyansh Jain 			 __generate_thresh(low_thresh, 0));
291f09ede6cSShreyansh Jain 		out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
292f09ede6cSShreyansh Jain 			 __generate_thresh(high_thresh, 1));
293f09ede6cSShreyansh Jain 	} else {
294f09ede6cSShreyansh Jain 		out_be32(bman_ccsr_map + POOL_HWDET(bpid),
295f09ede6cSShreyansh Jain 			 __generate_thresh(BMAN_LOW_DEFAULT_THRESH, 0));
296f09ede6cSShreyansh Jain 		out_be32(bman_ccsr_map + POOL_HWDXT(bpid),
297f09ede6cSShreyansh Jain 			 __generate_thresh(BMAN_HIGH_DEFAULT_THRESH, 1));
298f09ede6cSShreyansh Jain 	}
299f09ede6cSShreyansh Jain 	return 0;
300f09ede6cSShreyansh Jain }
301