1 /* $OpenBSD: cn30xxpko.c,v 1.9 2022/12/28 01:39:21 yasuoka Exp $ */
2
3 /*
4 * Copyright (c) 2007 Internet Initiative Japan, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32
33 #include <machine/octeonvar.h>
34
35 #include <octeon/dev/cn30xxfaureg.h>
36 #include <octeon/dev/cn30xxfpavar.h>
37 #include <octeon/dev/cn30xxpkoreg.h>
38 #include <octeon/dev/cn30xxpkovar.h>
39
40 static inline void cn30xxpko_op_store(uint64_t, uint64_t);
41
42 #define _PKO_RD8(sc, off) \
43 bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
44 #define _PKO_WR8(sc, off, v) \
45 bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
46
47 /* ----- gloal functions */
48
49 /* XXX */
50 void
cn30xxpko_init(struct cn30xxpko_attach_args * aa,struct cn30xxpko_softc ** rsc)51 cn30xxpko_init(struct cn30xxpko_attach_args *aa,
52 struct cn30xxpko_softc **rsc)
53 {
54 struct cn30xxpko_softc *sc;
55 int status;
56
57 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
58 if (sc == NULL)
59 panic("can't allocate memory: %s", __func__);
60
61 sc->sc_port = aa->aa_port;
62 sc->sc_regt = aa->aa_regt;
63 sc->sc_cmdptr = aa->aa_cmdptr;
64 sc->sc_cmd_buf_pool = aa->aa_cmd_buf_pool;
65 sc->sc_cmd_buf_size = aa->aa_cmd_buf_size;
66
67 status = bus_space_map(sc->sc_regt, PKO_BASE, PKO_SIZE, 0,
68 &sc->sc_regh);
69 if (status != 0)
70 panic("can't map %s space", "pko register");
71
72 *rsc = sc;
73 }
74
75 int
cn30xxpko_enable(struct cn30xxpko_softc * sc)76 cn30xxpko_enable(struct cn30xxpko_softc *sc)
77 {
78 uint64_t reg_flags;
79
80 reg_flags = _PKO_RD8(sc, PKO_REG_FLAGS_OFFSET);
81 /* PKO_REG_FLAGS_RESET=0 */
82 /* PKO_REG_FLAGS_STORE_BE=0 */
83 SET(reg_flags, PKO_REG_FLAGS_ENA_DWB);
84 SET(reg_flags, PKO_REG_FLAGS_ENA_PKO);
85 /* XXX */
86 mips_sync();
87 _PKO_WR8(sc, PKO_REG_FLAGS_OFFSET, reg_flags);
88
89 return 0;
90 }
91
92 #if 0
93 void
94 cn30xxpko_reset(cn30xxpko_softc *sc)
95 {
96 uint64_t reg_flags;
97
98 reg_flags = _PKO_RD8(sc, PKO_REG_FLAGS_OFFSET);
99 SET(reg_flags, PKO_REG_FLAGS_RESET);
100 _PKO_WR8(sc, PKO_REG_FLAGS_OFFSET, reg_flags);
101 }
102 #endif
103
104 void
cn30xxpko_config(struct cn30xxpko_softc * sc)105 cn30xxpko_config(struct cn30xxpko_softc *sc)
106 {
107 uint64_t reg_cmd_buf = 0;
108
109 SET(reg_cmd_buf, (sc->sc_cmd_buf_pool << 20) & PKO_REG_CMD_BUF_POOL);
110 SET(reg_cmd_buf, sc->sc_cmd_buf_size & PKO_REG_CMD_BUF_SIZE);
111 _PKO_WR8(sc, PKO_REG_CMD_BUF_OFFSET, reg_cmd_buf);
112 }
113
114 int
cn30xxpko_port_enable(struct cn30xxpko_softc * sc,int enable)115 cn30xxpko_port_enable(struct cn30xxpko_softc *sc, int enable)
116 {
117 uint64_t reg_read_idx;
118 uint64_t mem_queue_qos;
119
120 reg_read_idx = 0;
121 SET(reg_read_idx, sc->sc_port & PKO_REG_READ_IDX_IDX);
122
123 /* XXX assume one queue mapped one port */
124 /* Enable packet output by enabling all queues for this port */
125 mem_queue_qos = 0;
126 SET(mem_queue_qos, ((uint64_t)sc->sc_port << 7) & PKO_MEM_QUEUE_QOS_PID);
127 SET(mem_queue_qos, sc->sc_port & PKO_MEM_QUEUE_QOS_QID);
128 SET(mem_queue_qos, ((enable ? 0xffULL : 0x00ULL) << 53) &
129 PKO_MEM_QUEUE_QOS_QOS_MASK);
130
131 _PKO_WR8(sc, PKO_REG_READ_IDX_OFFSET, reg_read_idx);
132 _PKO_WR8(sc, PKO_MEM_QUEUE_QOS_OFFSET, mem_queue_qos);
133
134 return 0;
135 }
136
137 int pko_queue_map_init[32];
138
139 int
cn30xxpko_port_config(struct cn30xxpko_softc * sc)140 cn30xxpko_port_config(struct cn30xxpko_softc *sc)
141 {
142 paddr_t buf_ptr = 0;
143 uint64_t mem_queue_ptrs, val;
144 int i;
145
146 KASSERT(sc->sc_port < 32);
147
148 buf_ptr = cn30xxfpa_load(OCTEON_POOL_NO_CMD);
149 if (buf_ptr == 0)
150 return 1;
151
152 KASSERT(buf_ptr != 0);
153
154 if (sc->sc_port == 24) {
155 /* Set up PKO for AGL port. */
156 _PKO_WR8(sc, PKO_REG_READ_IDX_OFFSET, 1ULL << 8);
157 for (i = 0; i < 40; i++) {
158 val = _PKO_RD8(sc, PKO_MEM_PORT_PTRS_OFFSET);
159 if ((val & PKO_MEM_PORT_PTRS_PID_M) == 24) {
160 CLR(val, PKO_MEM_PORT_PTRS_EID_M);
161 SET(val, 10ULL << PKO_MEM_PORT_PTRS_EID_S);
162 CLR(val, PKO_MEM_PORT_PTRS_BP_PORT_M);
163 SET(val, 40ULL << PKO_MEM_PORT_PTRS_BP_PORT_S);
164 _PKO_WR8(sc, PKO_MEM_PORT_PTRS_OFFSET, val);
165 break;
166 }
167 }
168 }
169
170 /* assume one queue mapped one port */
171 mem_queue_ptrs = 0;
172 SET(mem_queue_ptrs, PKO_MEM_QUEUE_PTRS_TAIL);
173 SET(mem_queue_ptrs, ((uint64_t)0 << 13) & PKO_MEM_QUEUE_PTRS_IDX);
174 SET(mem_queue_ptrs, ((uint64_t)sc->sc_port << 7) & PKO_MEM_QUEUE_PTRS_PID);
175 SET(mem_queue_ptrs, sc->sc_port & PKO_MEM_QUEUE_PTRS_QID);
176 SET(mem_queue_ptrs, ((uint64_t)0xff << 53) & PKO_MEM_QUEUE_PTRS_QOS_MASK);
177 SET(mem_queue_ptrs, ((uint64_t)buf_ptr << 17) & PKO_MEM_QUEUE_PTRS_BUF_PTR);
178 mips_sync();
179 _PKO_WR8(sc, PKO_MEM_QUEUE_PTRS_OFFSET, mem_queue_ptrs);
180
181 /*
182 * Set initial command buffer address and index
183 * for queue.
184 */
185 sc->sc_cmdptr->cmdptr = (uint64_t)buf_ptr;
186 sc->sc_cmdptr->cmdptr_idx = 0;
187
188 pko_queue_map_init[sc->sc_port] = 1;
189
190 return 0;
191 }
192