1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
3 * Copyright 2008-2016 Freescale Semiconductor Inc.
10 #include "qman_priv.h"
11 #include <sys/ioctl.h>
12 #include <rte_branch_prediction.h>
14 /* Global variable containing revision id (even on non-control plane systems
15 * where CCSR isn't available).
18 u16 qm_channel_pool1
= QMAN_CHANNEL_POOL1
;
19 u16 qm_channel_caam
= QMAN_CHANNEL_CAAM
;
20 u16 qm_channel_pme
= QMAN_CHANNEL_PME
;
22 /* Ccsr map address to access ccsrbased register */
23 static void *qman_ccsr_map
;
24 /* The qman clock frequency */
27 static __thread
int qmfd
= -1;
28 static __thread
struct qm_portal_config qpcfg
;
29 static __thread
struct dpaa_ioctl_portal_map map
= {
30 .type
= dpaa_portal_qman
33 static int fsl_qman_portal_init(uint32_t index
, int is_shared
)
36 struct qman_portal
*portal
;
38 struct dpaa_ioctl_irq_map irq_map
;
40 /* Verify the thread's cpu-affinity */
41 ret
= pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t
),
44 error(0, ret
, "pthread_getaffinity_np()");
48 for (loop
= 0; loop
< CPU_SETSIZE
; loop
++)
49 if (CPU_ISSET(loop
, &cpuset
)) {
50 if (qpcfg
.cpu
!= -1) {
51 pr_err("Thread is not affine to 1 cpu\n");
56 if (qpcfg
.cpu
== -1) {
57 pr_err("Bug in getaffinity handling!\n");
61 /* Allocate and map a qman portal */
63 ret
= process_portal_map(&map
);
65 error(0, ret
, "process_portal_map()");
68 qpcfg
.channel
= map
.channel
;
69 qpcfg
.pools
= map
.pools
;
70 qpcfg
.index
= map
.index
;
72 /* Make the portal's cache-[enabled|inhibited] regions */
73 qpcfg
.addr_virt
[DPAA_PORTAL_CE
] = map
.addr
.cena
;
74 qpcfg
.addr_virt
[DPAA_PORTAL_CI
] = map
.addr
.cinh
;
76 qmfd
= open(QMAN_PORTAL_IRQ_PATH
, O_RDONLY
);
78 pr_err("QMan irq init failed\n");
79 process_portal_unmap(&map
.addr
);
83 qpcfg
.is_shared
= is_shared
;
87 portal
= qman_create_affine_portal(&qpcfg
, NULL
, 0);
89 pr_err("Qman portal initialisation failed (%d)\n",
91 process_portal_unmap(&map
.addr
);
95 irq_map
.type
= dpaa_portal_qman
;
96 irq_map
.portal_cinh
= map
.addr
.cinh
;
97 process_portal_irq_map(qmfd
, &irq_map
);
101 static int fsl_qman_portal_finish(void)
103 __maybe_unused
const struct qm_portal_config
*cfg
;
106 process_portal_irq_unmap(qmfd
);
108 cfg
= qman_destroy_affine_portal(NULL
);
109 DPAA_BUG_ON(cfg
!= &qpcfg
);
110 ret
= process_portal_unmap(&map
.addr
);
112 error(0, ret
, "process_portal_unmap()");
116 int qman_thread_fd(void)
121 int qman_thread_init(void)
123 /* Convert from contiguous/virtual cpu numbering to real cpu when
124 * calling into the code that is dependent on the device naming.
126 return fsl_qman_portal_init(QBMAN_ANY_PORTAL_IDX
, 0);
129 int qman_thread_finish(void)
131 return fsl_qman_portal_finish();
134 void qman_thread_irq(void)
136 qbman_invoke_irq(qpcfg
.irq
);
138 /* Now we need to uninhibit interrupts. This is the only code outside
139 * the regular portal driver that manipulates any portal register, so
140 * rather than breaking that encapsulation I am simply hard-coding the
141 * offset to the inhibit register here.
143 out_be32(qpcfg
.addr_virt
[DPAA_PORTAL_CI
] + 0x36C0, 0);
146 struct qman_portal
*fsl_qman_portal_create(void)
149 struct qman_portal
*res
;
151 struct qm_portal_config
*q_pcfg
;
153 struct dpaa_ioctl_irq_map irq_map
;
154 struct dpaa_ioctl_portal_map q_map
= {0};
157 q_pcfg
= kzalloc((sizeof(struct qm_portal_config
)), 0);
159 error(0, -1, "q_pcfg kzalloc failed");
163 /* Verify the thread's cpu-affinity */
164 ret
= pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t
),
167 error(0, ret
, "pthread_getaffinity_np()");
173 for (loop
= 0; loop
< CPU_SETSIZE
; loop
++)
174 if (CPU_ISSET(loop
, &cpuset
)) {
175 if (q_pcfg
->cpu
!= -1) {
176 pr_err("Thread is not affine to 1 cpu\n");
182 if (q_pcfg
->cpu
== -1) {
183 pr_err("Bug in getaffinity handling!\n");
188 /* Allocate and map a qman portal */
189 q_map
.type
= dpaa_portal_qman
;
190 q_map
.index
= QBMAN_ANY_PORTAL_IDX
;
191 ret
= process_portal_map(&q_map
);
193 error(0, ret
, "process_portal_map()");
197 q_pcfg
->channel
= q_map
.channel
;
198 q_pcfg
->pools
= q_map
.pools
;
199 q_pcfg
->index
= q_map
.index
;
201 /* Make the portal's cache-[enabled|inhibited] regions */
202 q_pcfg
->addr_virt
[DPAA_PORTAL_CE
] = q_map
.addr
.cena
;
203 q_pcfg
->addr_virt
[DPAA_PORTAL_CI
] = q_map
.addr
.cinh
;
205 q_fd
= open(QMAN_PORTAL_IRQ_PATH
, O_RDONLY
);
207 pr_err("QMan irq init failed\n");
213 res
= qman_create_affine_portal(q_pcfg
, NULL
, true);
215 pr_err("Qman portal initialisation failed (%d)\n",
220 irq_map
.type
= dpaa_portal_qman
;
221 irq_map
.portal_cinh
= q_map
.addr
.cinh
;
222 process_portal_irq_map(q_fd
, &irq_map
);
228 process_portal_unmap(&q_map
.addr
);
233 int fsl_qman_portal_destroy(struct qman_portal
*qp
)
235 const struct qm_portal_config
*cfg
;
236 struct dpaa_portal_map addr
;
239 cfg
= qman_destroy_affine_portal(qp
);
242 process_portal_irq_unmap(cfg
->irq
);
244 addr
.cena
= cfg
->addr_virt
[DPAA_PORTAL_CE
];
245 addr
.cinh
= cfg
->addr_virt
[DPAA_PORTAL_CI
];
247 ret
= process_portal_unmap(&addr
);
249 pr_err("process_portal_unmap() (%d)\n", ret
);
256 int qman_global_init(void)
258 const struct device_node
*dt_node
;
261 static int ccsr_map_fd
;
262 const uint32_t *qman_addr
;
272 /* Use the device-tree to determine IP revision until something better
275 dt_node
= of_find_compatible_node(NULL
, NULL
, "fsl,qman-portal");
277 pr_err("No qman portals available for any CPU\n");
280 if (of_device_is_compatible(dt_node
, "fsl,qman-portal-1.0") ||
281 of_device_is_compatible(dt_node
, "fsl,qman-portal-1.0.0"))
282 pr_err("QMan rev1.0 on P4080 rev1 is not supported!\n");
283 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-1.1") ||
284 of_device_is_compatible(dt_node
, "fsl,qman-portal-1.1.0"))
285 qman_ip_rev
= QMAN_REV11
;
286 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-1.2") ||
287 of_device_is_compatible(dt_node
, "fsl,qman-portal-1.2.0"))
288 qman_ip_rev
= QMAN_REV12
;
289 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-2.0") ||
290 of_device_is_compatible(dt_node
, "fsl,qman-portal-2.0.0"))
291 qman_ip_rev
= QMAN_REV20
;
292 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-3.0.0") ||
293 of_device_is_compatible(dt_node
, "fsl,qman-portal-3.0.1"))
294 qman_ip_rev
= QMAN_REV30
;
295 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-3.1.0") ||
296 of_device_is_compatible(dt_node
, "fsl,qman-portal-3.1.1") ||
297 of_device_is_compatible(dt_node
, "fsl,qman-portal-3.1.2") ||
298 of_device_is_compatible(dt_node
, "fsl,qman-portal-3.1.3"))
299 qman_ip_rev
= QMAN_REV31
;
300 else if (of_device_is_compatible(dt_node
, "fsl,qman-portal-3.2.0") ||
301 of_device_is_compatible(dt_node
, "fsl,qman-portal-3.2.1"))
302 qman_ip_rev
= QMAN_REV32
;
304 qman_ip_rev
= QMAN_REV11
;
307 pr_err("Unknown qman portal version\n");
310 if ((qman_ip_rev
& 0xFF00) >= QMAN_REV30
) {
311 qm_channel_pool1
= QMAN_CHANNEL_POOL1_REV3
;
312 qm_channel_caam
= QMAN_CHANNEL_CAAM_REV3
;
313 qm_channel_pme
= QMAN_CHANNEL_PME_REV3
;
316 dt_node
= of_find_compatible_node(NULL
, NULL
, "fsl,pool-channel-range");
318 pr_err("No qman pool channel range available\n");
321 chanid
= of_get_property(dt_node
, "fsl,pool-channel-range", &lenp
);
323 pr_err("Can not get pool-channel-range property\n");
328 dt_node
= of_find_compatible_node(NULL
, NULL
, "fsl,qman");
330 pr_err("No qman device node available\n");
333 qman_addr
= of_get_address(dt_node
, 0, ®s_size
, NULL
);
335 pr_err("of_get_address cannot return qman address\n");
338 phys_addr
= of_translate_address(dt_node
, qman_addr
);
340 pr_err("of_translate_address failed\n");
344 ccsr_map_fd
= open("/dev/mem", O_RDWR
);
345 if (unlikely(ccsr_map_fd
< 0)) {
346 pr_err("Can not open /dev/mem for qman ccsr map\n");
350 qman_ccsr_map
= mmap(NULL
, regs_size
, PROT_READ
| PROT_WRITE
,
351 MAP_SHARED
, ccsr_map_fd
, phys_addr
);
352 if (qman_ccsr_map
== MAP_FAILED
) {
353 pr_err("Can not map qman ccsr base\n");
357 clk
= of_get_property(dt_node
, "clock-frequency", NULL
);
359 pr_warn("Can't find Qman clock frequency\n");
361 qman_clk
= be32_to_cpu(*clk
);
363 #ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
364 return qman_setup_fq_lookup_table(CONFIG_FSL_QMAN_FQ_LOOKUP_MAX
);