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