1228060Sbapt/*	$OpenBSD: cn30xxpko.c,v 1.9 2022/12/28 01:39:21 yasuoka Exp $	*/
2228060Sbapt
3228060Sbapt/*
4228060Sbapt * Copyright (c) 2007 Internet Initiative Japan, Inc.
5228060Sbapt * All rights reserved.
6228060Sbapt *
7228060Sbapt * Redistribution and use in source and binary forms, with or without
8228060Sbapt * modification, are permitted provided that the following conditions
9228060Sbapt * are met:
10228060Sbapt * 1. Redistributions of source code must retain the above copyright
11228060Sbapt *    notice, this list of conditions and the following disclaimer.
12228060Sbapt * 2. Redistributions in binary form must reproduce the above copyright
13228060Sbapt *    notice, this list of conditions and the following disclaimer in the
14228060Sbapt *    documentation and/or other materials provided with the distribution.
15228060Sbapt *
16228060Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17228060Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18228060Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19228060Sbapt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20228060Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21228060Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22228060Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23228060Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24228060Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25228060Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26228060Sbapt * SUCH DAMAGE.
27228060Sbapt */
28228060Sbapt
29228060Sbapt#include <sys/param.h>
30228060Sbapt#include <sys/systm.h>
31228060Sbapt#include <sys/malloc.h>
32228060Sbapt
33228060Sbapt#include <machine/octeonvar.h>
34228060Sbapt
35228060Sbapt#include <octeon/dev/cn30xxfaureg.h>
36228060Sbapt#include <octeon/dev/cn30xxfpavar.h>
37228060Sbapt#include <octeon/dev/cn30xxpkoreg.h>
38228060Sbapt#include <octeon/dev/cn30xxpkovar.h>
39228060Sbapt
40228060Sbaptstatic inline void	cn30xxpko_op_store(uint64_t, uint64_t);
41228060Sbapt
42228060Sbapt#define	_PKO_RD8(sc, off) \
43228060Sbapt	bus_space_read_8((sc)->sc_regt, (sc)->sc_regh, (off))
44228060Sbapt#define	_PKO_WR8(sc, off, v) \
45228060Sbapt	bus_space_write_8((sc)->sc_regt, (sc)->sc_regh, (off), (v))
46228060Sbapt
47228060Sbapt/* ----- gloal functions */
48228060Sbapt
49228060Sbapt/* XXX */
50228060Sbaptvoid
51228060Sbaptcn30xxpko_init(struct cn30xxpko_attach_args *aa,
52228060Sbapt    struct cn30xxpko_softc **rsc)
53228060Sbapt{
54228060Sbapt	struct cn30xxpko_softc *sc;
55228060Sbapt	int status;
56228060Sbapt
57228060Sbapt	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
58228060Sbapt	if (sc == NULL)
59228060Sbapt		panic("can't allocate memory: %s", __func__);
60228060Sbapt
61228060Sbapt	sc->sc_port = aa->aa_port;
62228060Sbapt	sc->sc_regt = aa->aa_regt;
63228060Sbapt	sc->sc_cmdptr = aa->aa_cmdptr;
64228060Sbapt	sc->sc_cmd_buf_pool = aa->aa_cmd_buf_pool;
65228060Sbapt	sc->sc_cmd_buf_size = aa->aa_cmd_buf_size;
66228060Sbapt
67228060Sbapt	status = bus_space_map(sc->sc_regt, PKO_BASE, PKO_SIZE, 0,
68228060Sbapt	    &sc->sc_regh);
69228060Sbapt	if (status != 0)
70		panic("can't map %s space", "pko register");
71
72	*rsc = sc;
73}
74
75int
76cn30xxpko_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
93void
94cn30xxpko_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
104void
105cn30xxpko_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
114int
115cn30xxpko_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
137int pko_queue_map_init[32];
138
139int
140cn30xxpko_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