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
37int64_t	cn30xxfau_op_load(uint64_t);
38void	cn30xxfau_op_iobdma(int, uint64_t);
39void	cn30xxfau_op_store(uint64_t, int64_t);
40int64_t	cn30xxfau_op_load_paddr(int, int, int) __unused;
41void	cn30xxfau_op_iobdma_store_data(int, int, int, int, int);
42void	cn30xxfau_op_store_paddr(int, int, int64_t);
43
44
45/* ---- utilities */
46
47int64_t
48cn30xxfau_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
60void
61cn30xxfau_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
83int64_t
84cn30xxfau_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
99void
100cn30xxfau_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
112void
113cn30xxfau_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
119uint64_t
120cn30xxfau_op_save(struct cn30xxfau_desc *fd)
121{
122	octeon_synciobdma();
123	return octeon_cvmseg_read_8(fd->fd_scroff);
124}
125
126void
127cn30xxfau_op_restore(struct cn30xxfau_desc *fd, uint64_t backup)
128{
129	octeon_cvmseg_write_8(fd->fd_scroff, backup);
130}
131
132int64_t
133cn30xxfau_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
141int64_t
142cn30xxfau_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
150void
151cn30xxfau_op_add_8(struct cn30xxfau_desc *fd, int64_t v)
152{
153	cn30xxfau_op_store_paddr(0, fd->fd_regno, v);
154}
155
156void
157cn30xxfau_op_set_8(struct cn30xxfau_desc *fd, int64_t v)
158{
159	cn30xxfau_op_store_paddr(1, fd->fd_regno, v);
160}
161