1 /* $NetBSD: octeon_fau.c,v 1.4 2020/06/23 05:14:18 simonb 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 REGENTS 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 REGENTS 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/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: octeon_fau.c,v 1.4 2020/06/23 05:14:18 simonb Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <mips/locore.h> 35 #include <mips/cavium/octeonvar.h> 36 #include <mips/cavium/dev/octeon_faureg.h> 37 #include <mips/cavium/dev/octeon_fauvar.h> 38 39 static inline int64_t octfau_op_load(uint64_t); 40 static inline void octfau_op_iobdma(int, uint64_t); 41 static inline void octfau_op_store(uint64_t, int64_t); 42 static inline int64_t octfau_op_load_paddr(int, int, int); 43 static inline void octfau_op_iobdma_store_data(int, int, int, int, int); 44 static inline void octfau_op_store_paddr(int, int, int64_t); 45 46 47 /* ---- utilities */ 48 49 static inline int64_t 50 octfau_op_load(uint64_t args) 51 { 52 paddr_t addr = OCTEON_ADDR_IO_DID(FAU_MAJOR_DID, FAU_SUB_DID) | 53 __SHIFTIN(args, OCTEON_ADDR_OFFSET); 54 55 return octeon_xkphys_read_8(addr); 56 } 57 58 static inline void 59 octfau_op_store(uint64_t args, int64_t value) 60 { 61 paddr_t addr = OCTEON_ADDR_IO_DID(FAU_MAJOR_DID, FAU_SUB_DID) | 62 __SHIFTIN(args, OCTEON_ADDR_OFFSET); 63 64 octeon_xkphys_write_8(addr, value); 65 } 66 67 /* ---- operation primitives */ 68 69 /* 70 * Fetch-and-Add Operations 71 */ 72 73 /* Load Operations */ 74 75 /* Load Physical Address for FAU Operations */ 76 77 static inline int64_t 78 octfau_op_load_paddr(int incval, int tagwait, int reg) 79 { 80 uint64_t args = 81 __SHIFTIN(incval, POW_LOAD_INCVAL) | 82 __SHIFTIN(tagwait, POW_LOAD_TAGWAIT) | 83 __SHIFTIN(reg, POW_LOAD_REG); 84 85 return octfau_op_load(args); 86 } 87 88 /* Store Operations */ 89 90 /* Store Physical Address for FAU Operations */ 91 92 static inline void 93 octfau_op_store_paddr(int noadd, int reg, int64_t value) 94 { 95 uint64_t args = POW_STORE_NOADD | __SHIFTIN(reg, POW_STORE_REG); 96 97 octfau_op_store(args, value); 98 } 99 100 /* ---- API */ 101 102 void 103 octfau_op_init(struct octfau_desc *fd, size_t scroff, size_t regno) 104 { 105 106 fd->fd_scroff = scroff; 107 fd->fd_regno = regno; 108 } 109 110 uint64_t 111 octfau_op_save(struct octfau_desc *fd) 112 { 113 114 OCTEON_SYNCIOBDMA/* XXX */; 115 return octeon_cvmseg_read_8(fd->fd_scroff); 116 } 117 118 void 119 octfau_op_restore(struct octfau_desc *fd, uint64_t backup) 120 { 121 122 octeon_cvmseg_write_8(fd->fd_scroff, backup); 123 } 124 125 int64_t 126 octfau_op_inc_8(struct octfau_desc *fd, int64_t v) 127 { 128 129 octfau_op_iobdma_store_data(fd->fd_scroff, v, 0, OCT_FAU_OP_SIZE_64/* XXX */, 130 fd->fd_regno); 131 OCTEON_SYNCIOBDMA/* XXX */; 132 return octeon_cvmseg_read_8(fd->fd_scroff)/* XXX */; 133 } 134 135 int64_t 136 octfau_op_incwait_8(struct octfau_desc *fd, int v) 137 { 138 139 octfau_op_iobdma_store_data(fd->fd_scroff, v, 1, OCT_FAU_OP_SIZE_64/* XXX */, 140 fd->fd_regno); 141 /* XXX */ 142 OCTEON_SYNCIOBDMA/* XXX */; 143 /* XXX */ 144 return octeon_cvmseg_read_8(fd->fd_scroff)/* XXX */; 145 } 146 147 void 148 octfau_op_add_8(struct octfau_desc *fd, int64_t v) 149 { 150 151 octfau_op_store_paddr(0, fd->fd_regno, v); 152 } 153 154 void 155 octfau_op_set_8(struct octfau_desc *fd, int64_t v) 156 { 157 158 octfau_op_store_paddr(1, fd->fd_regno, v); 159 } 160