xref: /netbsd-src/sys/arch/mips/cavium/dev/octeon_fpa.c (revision 22b89011545e2886df72f766e05152c9d44b5fe2)
1*22b89011Ssimonb /*	$NetBSD: octeon_fpa.c,v 1.10 2021/03/24 08:10:14 simonb Exp $	*/
2f693c922Shikaru 
3f693c922Shikaru /*
4f693c922Shikaru  * Copyright (c) 2007 Internet Initiative Japan, Inc.
5f693c922Shikaru  * All rights reserved.
6f693c922Shikaru  *
7f693c922Shikaru  * Redistribution and use in source and binary forms, with or without
8f693c922Shikaru  * modification, are permitted provided that the following conditions
9f693c922Shikaru  * are met:
10f693c922Shikaru  * 1. Redistributions of source code must retain the above copyright
11f693c922Shikaru  *    notice, this list of conditions and the following disclaimer.
12f693c922Shikaru  * 2. Redistributions in binary form must reproduce the above copyright
13f693c922Shikaru  *    notice, this list of conditions and the following disclaimer in the
14f693c922Shikaru  *    documentation and/or other materials provided with the distribution.
15f693c922Shikaru  *
16f693c922Shikaru  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17f693c922Shikaru  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18f693c922Shikaru  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19f693c922Shikaru  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20f693c922Shikaru  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21f693c922Shikaru  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22f693c922Shikaru  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23f693c922Shikaru  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24f693c922Shikaru  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25f693c922Shikaru  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26f693c922Shikaru  * SUCH DAMAGE.
27f693c922Shikaru  */
28f693c922Shikaru 
29f693c922Shikaru #undef	FPADEBUG
30f693c922Shikaru 
31f693c922Shikaru #include <sys/cdefs.h>
32*22b89011Ssimonb __KERNEL_RCSID(0, "$NetBSD: octeon_fpa.c,v 1.10 2021/03/24 08:10:14 simonb Exp $");
33f693c922Shikaru 
34f693c922Shikaru #include <sys/param.h>
35f693c922Shikaru #include <sys/systm.h>
36f693c922Shikaru #include <sys/types.h>
3746d1333eSthorpej #include <sys/kmem.h>
38f693c922Shikaru 
39f693c922Shikaru #include <sys/bus.h>
40f693c922Shikaru #include <machine/locore.h>
41f693c922Shikaru #include <machine/vmparam.h>
42f693c922Shikaru 
43f693c922Shikaru #include <mips/cavium/octeonvar.h>
44f693c922Shikaru #include <mips/cavium/include/iobusvar.h>
45f693c922Shikaru #include <mips/cavium/dev/octeon_fpareg.h>
46b9fcd28bSsimonb #include <mips/cavium/dev/octeon_fpavar.h>
47f693c922Shikaru 
48f693c922Shikaru #ifdef FPADEBUG
49f693c922Shikaru #define	DPRINTF(x)	printf x
50f693c922Shikaru #else
51f693c922Shikaru #define	DPRINTF(x)
52f693c922Shikaru #endif
53f693c922Shikaru 
54f693c922Shikaru #define	_DMA_NSEGS	1
55f693c922Shikaru #define	_DMA_BUFLEN	0x01000000
56f693c922Shikaru 
573f508e4dSsimonb struct octfpa_softc {
58f693c922Shikaru 	int			sc_initialized;
59f693c922Shikaru 
60f693c922Shikaru 	bus_space_tag_t		sc_regt;
61f693c922Shikaru 	bus_space_handle_t	sc_regh;
62f693c922Shikaru 
63f693c922Shikaru 	bus_space_tag_t		sc_opst;
64f693c922Shikaru 	bus_space_handle_t	sc_opsh;
65f693c922Shikaru 
66f693c922Shikaru 	bus_dma_tag_t		sc_dmat;
67f693c922Shikaru };
68f693c922Shikaru 
693f508e4dSsimonb void			octfpa_bootstrap(struct octeon_config *);
703f508e4dSsimonb void			octfpa_reset(void);
713f508e4dSsimonb void			octfpa_int_enable(struct octfpa_softc *, int);
723f508e4dSsimonb void			octfpa_buf_dma_alloc(struct octfpa_buf *);
73f693c922Shikaru 
743f508e4dSsimonb static void		octfpa_init(struct octfpa_softc *);
75f693c922Shikaru #ifdef notyet
763f508e4dSsimonb static uint64_t		octfpa_iobdma(struct octfpa_softc *, int, int);
77f693c922Shikaru #endif
78f693c922Shikaru 
793f508e4dSsimonb static struct octfpa_softc	octfpa_softc;
80f693c922Shikaru 
81f693c922Shikaru /* ---- global functions */
82f693c922Shikaru 
83f693c922Shikaru void
octfpa_bootstrap(struct octeon_config * mcp)843f508e4dSsimonb octfpa_bootstrap(struct octeon_config *mcp)
85f693c922Shikaru {
863f508e4dSsimonb 	struct octfpa_softc *sc = &octfpa_softc;
87f693c922Shikaru 
88f693c922Shikaru 	sc->sc_regt = &mcp->mc_iobus_bust;
89f693c922Shikaru 	sc->sc_opst = &mcp->mc_iobus_bust;
90f693c922Shikaru 	sc->sc_dmat = &mcp->mc_iobus_dmat;
91f693c922Shikaru 
923f508e4dSsimonb 	octfpa_init(sc);
93f693c922Shikaru }
94f693c922Shikaru 
95f693c922Shikaru void
octfpa_reset(void)963f508e4dSsimonb octfpa_reset(void)
97f693c922Shikaru {
98f693c922Shikaru 	/* XXX */
99f693c922Shikaru }
100f693c922Shikaru 
101f693c922Shikaru int
octfpa_buf_init(int poolno,size_t size,size_t nelems,struct octfpa_buf ** rfb)1023f508e4dSsimonb octfpa_buf_init(int poolno, size_t size, size_t nelems, struct octfpa_buf **rfb)
103f693c922Shikaru {
1043f508e4dSsimonb 	struct octfpa_softc *sc = &octfpa_softc;
1053f508e4dSsimonb 	struct octfpa_buf *fb;
106f693c922Shikaru 	int nsegs;
107f693c922Shikaru 	paddr_t paddr;
108f693c922Shikaru 
109f693c922Shikaru 	nsegs = 1/* XXX */;
11046d1333eSthorpej 	fb = kmem_zalloc(sizeof(*fb) + sizeof(*fb->fb_dma_segs) * nsegs,
11146d1333eSthorpej 	    KM_SLEEP);
112f693c922Shikaru 	fb->fb_poolno = poolno;
113f693c922Shikaru 	fb->fb_size = size;
114f693c922Shikaru 	fb->fb_nelems = nelems;
115f693c922Shikaru 	fb->fb_len = size * nelems;
116f693c922Shikaru 	fb->fb_dmat = sc->sc_dmat;
117f693c922Shikaru 	fb->fb_dma_segs = (void *)(fb + 1);
118f693c922Shikaru 	fb->fb_dma_nsegs = nsegs;
119f693c922Shikaru 
1203f508e4dSsimonb 	octfpa_buf_dma_alloc(fb);
121f693c922Shikaru 
122f693c922Shikaru 	for (paddr = fb->fb_paddr; paddr < fb->fb_paddr + fb->fb_len;
123f693c922Shikaru 	    paddr += fb->fb_size)
1243f508e4dSsimonb 		octfpa_buf_put_paddr(fb, paddr);
125f693c922Shikaru 
126f693c922Shikaru 	*rfb = fb;
127f693c922Shikaru 
128f693c922Shikaru 	return 0;
129f693c922Shikaru }
130f693c922Shikaru 
131f693c922Shikaru void *
octfpa_buf_get(struct octfpa_buf * fb)1323f508e4dSsimonb octfpa_buf_get(struct octfpa_buf *fb)
133f693c922Shikaru {
134f693c922Shikaru 	paddr_t paddr;
135f693c922Shikaru 	vaddr_t addr;
136f693c922Shikaru 
1373f508e4dSsimonb 	paddr = octfpa_buf_get_paddr(fb);
138f693c922Shikaru 	if (paddr == 0)
139f693c922Shikaru 		addr = 0;
140f693c922Shikaru 	else
141f693c922Shikaru 		addr = fb->fb_addr + (vaddr_t/* XXX */)(paddr - fb->fb_paddr);
142f693c922Shikaru 	return (void *)addr;
143f693c922Shikaru }
144f693c922Shikaru 
145f693c922Shikaru void
octfpa_buf_dma_alloc(struct octfpa_buf * fb)1463f508e4dSsimonb octfpa_buf_dma_alloc(struct octfpa_buf *fb)
147f693c922Shikaru {
148f693c922Shikaru 	int status;
149f693c922Shikaru 	int nsegs;
150f693c922Shikaru 	void *va;
151f693c922Shikaru 
152f693c922Shikaru 	status = bus_dmamap_create(fb->fb_dmat, fb->fb_len,
153f693c922Shikaru 	    fb->fb_len / PAGE_SIZE,	/* # of segments */
154f693c922Shikaru 	    fb->fb_len,			/* we don't use s/g for FPA buf */
155f693c922Shikaru 	    PAGE_SIZE,			/* OCTEON hates >PAGE_SIZE boundary */
156f693c922Shikaru 	    0, &fb->fb_dmah);
157f693c922Shikaru 	if (status != 0)
158f693c922Shikaru 		panic("%s failed", "bus_dmamap_create");
159f693c922Shikaru 
160f693c922Shikaru 	status = bus_dmamem_alloc(fb->fb_dmat, fb->fb_len, 128, 0,
161f693c922Shikaru 	    fb->fb_dma_segs, fb->fb_dma_nsegs, &nsegs, 0);
162f693c922Shikaru 	if (status != 0 || fb->fb_dma_nsegs != nsegs)
163f693c922Shikaru 		panic("%s failed", "bus_dmamem_alloc");
164f693c922Shikaru 
165f693c922Shikaru 	status = bus_dmamem_map(fb->fb_dmat, fb->fb_dma_segs, fb->fb_dma_nsegs,
166f693c922Shikaru 	    fb->fb_len, &va, 0);
167f693c922Shikaru 	if (status != 0)
168f693c922Shikaru 		panic("%s failed", "bus_dmamem_map");
169f693c922Shikaru 
170f693c922Shikaru 	status = bus_dmamap_load(fb->fb_dmat, fb->fb_dmah, va, fb->fb_len,
171f693c922Shikaru 	    NULL,		/* kernel */
172f693c922Shikaru 	    0);
173f693c922Shikaru 	if (status != 0)
174f693c922Shikaru 		panic("%s failed", "bus_dmamap_load");
175f693c922Shikaru 
176f693c922Shikaru 	fb->fb_addr = (vaddr_t)va;
177f693c922Shikaru 	fb->fb_paddr = fb->fb_dma_segs[0].ds_addr;
178f693c922Shikaru }
179f693c922Shikaru 
180f693c922Shikaru uint64_t
octfpa_query(int poolno)1813f508e4dSsimonb octfpa_query(int poolno)
182f693c922Shikaru {
1833f508e4dSsimonb 	struct octfpa_softc *sc = &octfpa_softc;
184f693c922Shikaru 
185f693c922Shikaru 	return bus_space_read_8(sc->sc_regt, sc->sc_regh,
186f693c922Shikaru 	    FPA_QUE0_AVAILABLE_OFFSET + sizeof(uint64_t) * poolno);
187f693c922Shikaru }
188f693c922Shikaru 
189f693c922Shikaru /* ---- local functions */
190f693c922Shikaru 
1913f508e4dSsimonb static inline void	octfpa_init_bus(struct octfpa_softc *);
1923f508e4dSsimonb static inline void	octfpa_init_bus_space(struct octfpa_softc *);
1933f508e4dSsimonb static inline void	octfpa_init_regs(struct octfpa_softc *);
194f693c922Shikaru 
195f693c922Shikaru void
octfpa_init(struct octfpa_softc * sc)1963f508e4dSsimonb octfpa_init(struct octfpa_softc *sc)
197f693c922Shikaru {
198f693c922Shikaru 	if (sc->sc_initialized != 0)
199f693c922Shikaru 		panic("%s: already initialized", __func__);
200f693c922Shikaru 	sc->sc_initialized = 1;
201f693c922Shikaru 
2023f508e4dSsimonb 	octfpa_init_bus(sc);
2033f508e4dSsimonb 	octfpa_init_regs(sc);
204f693c922Shikaru }
205f693c922Shikaru 
206f693c922Shikaru void
octfpa_init_bus(struct octfpa_softc * sc)2073f508e4dSsimonb octfpa_init_bus(struct octfpa_softc *sc)
208f693c922Shikaru {
209eb61b502Ssimonb 
2103f508e4dSsimonb 	octfpa_init_bus_space(sc);
211f693c922Shikaru }
212f693c922Shikaru 
213f693c922Shikaru void
octfpa_init_bus_space(struct octfpa_softc * sc)2143f508e4dSsimonb octfpa_init_bus_space(struct octfpa_softc *sc)
215f693c922Shikaru {
216f693c922Shikaru 	int status;
217f693c922Shikaru 
218f693c922Shikaru 	status = bus_space_map(sc->sc_regt, FPA_BASE, FPA_SIZE, 0, &sc->sc_regh);
219f693c922Shikaru 	if (status != 0)
220f693c922Shikaru 		panic("can't map %s space", "register");
221f693c922Shikaru 
222f693c922Shikaru 	status = bus_space_map(sc->sc_opst,
223f693c922Shikaru 	    0x0001180028000000ULL/* XXX */, 0x0200/* XXX */, 0, &sc->sc_opsh);
224f693c922Shikaru 	if (status != 0)
225f693c922Shikaru 		panic("can't map %s space", "operations");
226f693c922Shikaru }
227f693c922Shikaru 
228f693c922Shikaru void
octfpa_init_regs(struct octfpa_softc * sc)2293f508e4dSsimonb octfpa_init_regs(struct octfpa_softc *sc)
230f693c922Shikaru {
231f693c922Shikaru 
232f693c922Shikaru 	bus_space_write_8(sc->sc_regt, sc->sc_regh, FPA_CTL_STATUS_OFFSET,
233f693c922Shikaru 	    FPA_CTL_STATUS_ENB);
234f693c922Shikaru }
235f693c922Shikaru 
236f693c922Shikaru int
octfpa_available_fpa_pool(int * available,int pool_no)2373f508e4dSsimonb octfpa_available_fpa_pool(int *available, int pool_no) {
2383f508e4dSsimonb 	struct octfpa_softc *sc = &octfpa_softc;
239f693c922Shikaru 	size_t offset;
240f693c922Shikaru 	uint64_t tmp;
241f693c922Shikaru 
242f693c922Shikaru 	switch (pool_no) {
243f693c922Shikaru 	case OCTEON_POOL_NO_PKT:
244f693c922Shikaru 		offset = FPA_QUE0_AVAILABLE_OFFSET;
245f693c922Shikaru 		break;
246f693c922Shikaru 	case OCTEON_POOL_NO_WQE:
247f693c922Shikaru 		offset = FPA_QUE1_AVAILABLE_OFFSET;
248f693c922Shikaru 		break;
249f693c922Shikaru 	case OCTEON_POOL_NO_CMD:
250f693c922Shikaru 		offset = FPA_QUE2_AVAILABLE_OFFSET;
251f693c922Shikaru 		break;
252f693c922Shikaru 	case OCTEON_POOL_NO_SG:
253f693c922Shikaru 		offset = FPA_QUE3_AVAILABLE_OFFSET;
254f693c922Shikaru 		break;
255f693c922Shikaru 	case OCTEON_POOL_NO_XXX_4:
256f693c922Shikaru 		offset = FPA_QUE4_AVAILABLE_OFFSET;
257f693c922Shikaru 		break;
258f693c922Shikaru 	case OCTEON_POOL_NO_XXX_5:
259f693c922Shikaru 		offset = FPA_QUE5_AVAILABLE_OFFSET;
260f693c922Shikaru 		break;
261f693c922Shikaru 	case OCTEON_POOL_NO_XXX_6:
262f693c922Shikaru 		offset = FPA_QUE6_AVAILABLE_OFFSET;
263f693c922Shikaru 		break;
264f693c922Shikaru 	case OCTEON_POOL_NO_DUMP:
265f693c922Shikaru 		offset = FPA_QUE7_AVAILABLE_OFFSET;
266f693c922Shikaru 		break;
267f693c922Shikaru 	default:
268f693c922Shikaru 		return EINVAL;
269f693c922Shikaru 	}
270f693c922Shikaru 	tmp = bus_space_read_8(sc->sc_regt, sc->sc_regh, offset);
271f693c922Shikaru 	if (available) {
272f693c922Shikaru 		*available = (int)(tmp & FPA_QUEX_AVAILABLE_QUE_SIZ);
273f693c922Shikaru 	}
274f693c922Shikaru 
275f693c922Shikaru 	return 0;
276f693c922Shikaru }
277