1 /* $OpenBSD: cn30xxfau.c,v 1.7 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
32 #include <machine/octeonvar.h>
33
34 #include <octeon/dev/cn30xxfaureg.h>
35 #include <octeon/dev/cn30xxfauvar.h>
36
37 int64_t cn30xxfau_op_load(uint64_t);
38 void cn30xxfau_op_iobdma(int, uint64_t);
39 void cn30xxfau_op_store(uint64_t, int64_t);
40 int64_t cn30xxfau_op_load_paddr(int, int, int) __unused;
41 void cn30xxfau_op_iobdma_store_data(int, int, int, int, int);
42 void cn30xxfau_op_store_paddr(int, int, int64_t);
43
44
45 /* ---- utilities */
46
47 int64_t
cn30xxfau_op_load(uint64_t args)48 cn30xxfau_op_load(uint64_t args)
49 {
50 paddr_t addr;
51
52 addr =
53 ((uint64_t)1 << 48) |
54 ((uint64_t)(CN30XXFAU_MAJORDID & 0x1f) << 43) |
55 ((uint64_t)(CN30XXFAU_SUBDID & 0x7) << 40) |
56 ((uint64_t)(args & 0xfffffffffULL) << 0);
57 return octeon_xkphys_read_8(addr);
58 }
59
60 void
cn30xxfau_op_store(uint64_t args,int64_t value)61 cn30xxfau_op_store(uint64_t args, int64_t value)
62 {
63 paddr_t addr;
64
65 addr =
66 ((uint64_t)1 << 48) |
67 ((uint64_t)(CN30XXFAU_MAJORDID & 0x1f) << 43) |
68 ((uint64_t)(CN30XXFAU_SUBDID & 0x7) << 40) |
69 ((uint64_t)(args & 0xfffffffffULL) << 0);
70 octeon_xkphys_write_8(addr, value);
71 }
72
73 /* ---- operation primitives */
74
75 /*
76 * 3.4 Fetch-and-Add Operations
77 */
78
79 /* 3.4.1 Load Operations */
80
81 /* Load Physical Address for FAU Operations */
82
83 int64_t
cn30xxfau_op_load_paddr(int incval,int tagwait,int reg)84 cn30xxfau_op_load_paddr(int incval, int tagwait, int reg)
85 {
86 uint64_t args;
87
88 args =
89 ((uint64_t)(incval & 0x3fffff) << 14) |
90 ((uint64_t)(tagwait & 0x1) << 13) |
91 ((uint64_t)(reg & 0x7ff) << 0);
92 return cn30xxfau_op_load(args);
93 }
94
95 /* 3.4.3 Store Operations */
96
97 /* Store Physical Address for FAU Operations */
98
99 void
cn30xxfau_op_store_paddr(int noadd,int reg,int64_t value)100 cn30xxfau_op_store_paddr(int noadd, int reg, int64_t value)
101 {
102 uint64_t args;
103
104 args =
105 ((uint64_t)(noadd & 0x1) << 13) |
106 ((uint64_t)(reg & 0x7ff) << 0);
107 cn30xxfau_op_store(args, value);
108 }
109
110 /* ---- API */
111
112 void
cn30xxfau_op_init(struct cn30xxfau_desc * fd,size_t scroff,size_t regno)113 cn30xxfau_op_init(struct cn30xxfau_desc *fd, size_t scroff, size_t regno)
114 {
115 fd->fd_scroff = scroff;
116 fd->fd_regno = regno;
117 }
118
119 uint64_t
cn30xxfau_op_save(struct cn30xxfau_desc * fd)120 cn30xxfau_op_save(struct cn30xxfau_desc *fd)
121 {
122 octeon_synciobdma();
123 return octeon_cvmseg_read_8(fd->fd_scroff);
124 }
125
126 void
cn30xxfau_op_restore(struct cn30xxfau_desc * fd,uint64_t backup)127 cn30xxfau_op_restore(struct cn30xxfau_desc *fd, uint64_t backup)
128 {
129 octeon_cvmseg_write_8(fd->fd_scroff, backup);
130 }
131
132 int64_t
cn30xxfau_op_inc_8(struct cn30xxfau_desc * fd,int64_t v)133 cn30xxfau_op_inc_8(struct cn30xxfau_desc *fd, int64_t v)
134 {
135 cn30xxfau_op_iobdma_store_data(fd->fd_scroff, v, 0, OCT_FAU_OP_SIZE_64/* XXX */,
136 fd->fd_regno);
137 octeon_synciobdma();
138 return octeon_cvmseg_read_8(fd->fd_scroff)/* XXX */;
139 }
140
141 int64_t
cn30xxfau_op_incwait_8(struct cn30xxfau_desc * fd,int v)142 cn30xxfau_op_incwait_8(struct cn30xxfau_desc *fd, int v)
143 {
144 cn30xxfau_op_iobdma_store_data(fd->fd_scroff, v, 1, OCT_FAU_OP_SIZE_64/* XXX */,
145 fd->fd_regno);
146 octeon_synciobdma();
147 return octeon_cvmseg_read_8(fd->fd_scroff)/* XXX */;
148 }
149
150 void
cn30xxfau_op_add_8(struct cn30xxfau_desc * fd,int64_t v)151 cn30xxfau_op_add_8(struct cn30xxfau_desc *fd, int64_t v)
152 {
153 cn30xxfau_op_store_paddr(0, fd->fd_regno, v);
154 }
155
156 void
cn30xxfau_op_set_8(struct cn30xxfau_desc * fd,int64_t v)157 cn30xxfau_op_set_8(struct cn30xxfau_desc *fd, int64_t v)
158 {
159 cn30xxfau_op_store_paddr(1, fd->fd_regno, v);
160 }
161