1/***********************license start***************
2 *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3 *  reserved.
4 *
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions are
8 *  met:
9 *
10 *      * Redistributions of source code must retain the above copyright
11 *        notice, this list of conditions and the following disclaimer.
12 *
13 *      * Redistributions in binary form must reproduce the above
14 *        copyright notice, this list of conditions and the following
15 *        disclaimer in the documentation and/or other materials provided
16 *        with the distribution.
17 *
18 *      * Neither the name of Cavium Networks nor the names of
19 *        its contributors may be used to endorse or promote products
20 *        derived from this software without specific prior written
21 *        permission.
22 *
23 *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32 *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39/*
40 *    This product includes software developed by the University of
41 *    California, Berkeley and its contributors."
42 */
43
44/* $FreeBSD$ */
45
46#ifndef __OCTEON_PCMAP_REGS_H__
47#define __OCTEON_PCMAP_REGS_H__
48
49#ifndef LOCORE
50
51/*
52 * Utility inlines & macros
53 */
54
55#if defined(__mips_n64)
56#define	oct_write64(a, v)	(*(volatile uint64_t *)(a) = (uint64_t)(v))
57#define	oct_write8_x8(a, v)	(*(volatile uint8_t *)(a) = (uint8_t)(v))
58
59#define	OCT_READ(n, t)							\
60static inline t oct_read ## n(uintptr_t a)				\
61{									\
62	volatile t *p = (volatile t *)a;				\
63	return (*p);							\
64}
65
66OCT_READ(8, uint8_t);
67OCT_READ(16, uint16_t);
68OCT_READ(32, uint32_t);
69OCT_READ(64, uint64_t);
70
71#elif defined(__mips_n32) || defined(__mips_o32)
72#if defined(__mips_n32)
73static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
74{
75    __asm __volatile (
76	    ".set push\n"
77            ".set mips64\n"
78            "sd     %0, 0(%1)\n"
79            ".set pop\n"
80            :
81	    : "r"(val64), "r"(csr_addr));
82}
83
84static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
85{
86    __asm __volatile (
87	    ".set push\n"
88            ".set mips64\n"
89            "sb    %0, 0(%1)\n"
90            ".set pop\n"
91            :
92	    : "r"(val8), "r"(csr_addr));
93}
94
95#define	OCT_READ(n, t, insn)						\
96static inline t oct_read ## n(uint64_t a)				\
97{									\
98    uint64_t tmp;							\
99									\
100    __asm __volatile (							\
101	".set push\n"							\
102        ".set mips64\n"							\
103        insn "\t%0, 0(%1)\n"						\
104        ".set pop\n"							\
105        : "=r"(tmp)							\
106        : "r"(a));							\
107    return ((t)tmp);							\
108}
109
110OCT_READ(8, uint8_t, "lb");
111OCT_READ(16, uint16_t, "lh");
112OCT_READ(32, uint32_t, "lw");
113OCT_READ(64, uint64_t, "ld");
114#else
115
116/*
117 * XXX
118 * Add o32 variants that load the address into a register and the result out
119 * of a register properly, and simply disable interrupts before and after and
120 * hope that we don't need to refill or modify the TLB to access the address.
121 * I'd be a lot happier if csr_addr were a physical address and we mapped it
122 * into XKPHYS here so that we could guarantee that interrupts were the only
123 * kind of exception we needed to worry about.
124 *
125 * Also, some of this inline assembly is needlessly verbose.  Oh, well.
126 */
127static inline void oct_write64 (uint64_t csr_addr, uint64_t val64)
128{
129	uint32_t csr_addrh = csr_addr >> 32;
130	uint32_t csr_addrl = csr_addr;
131	uint32_t valh = val64 >> 32;
132	uint32_t vall = val64;
133	uint32_t tmp1;
134	uint32_t tmp2;
135	uint32_t tmp3;
136	register_t sr;
137
138	sr = intr_disable();
139
140	__asm __volatile (
141	    ".set push\n"
142            ".set mips64\n"
143	    ".set noreorder\n"
144	    ".set noat\n"
145	    "dsll   %0, %3, 32\n"
146	    "dsll   %1, %5, 32\n"
147	    "dsll   %2, %4, 32\n"
148	    "dsrl   %2, %2, 32\n"
149	    "or     %0, %0, %2\n"
150	    "dsll   %2, %6, 32\n"
151	    "dsrl   %2, %2, 32\n"
152	    "or     %1, %1, %2\n"
153	    "sd     %0, 0(%1)\n"
154            ".set pop\n"
155	    : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
156	    : "r" (valh), "r" (vall), "r" (csr_addrh), "r" (csr_addrl));
157
158	intr_restore(sr);
159}
160
161static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8)
162{
163	uint32_t csr_addrh = csr_addr >> 32;
164	uint32_t csr_addrl = csr_addr;
165	uint32_t tmp1;
166	uint32_t tmp2;
167	register_t sr;
168
169	sr = intr_disable();
170
171	__asm __volatile (
172	    ".set push\n"
173            ".set mips64\n"
174	    ".set noreorder\n"
175	    ".set noat\n"
176	    "dsll   %0, %3, 32\n"
177	    "dsll   %1, %4, 32\n"
178	    "dsrl   %1, %1, 32\n"
179	    "or     %0, %0, %1\n"
180	    "sb     %2, 0(%0)\n"
181            ".set pop\n"
182	    : "=&r" (tmp1), "=&r" (tmp2)
183	    : "r" (val8), "r" (csr_addrh), "r" (csr_addrl));
184
185	intr_restore(sr);
186}
187
188#define	OCT_READ(n, t, insn)						\
189static inline t oct_read ## n(uint64_t csr_addr)			\
190{									\
191	uint32_t csr_addrh = csr_addr >> 32;				\
192	uint32_t csr_addrl = csr_addr;					\
193	uint32_t tmp1, tmp2;						\
194	register_t sr;							\
195									\
196	sr = intr_disable();						\
197									\
198	__asm __volatile (						\
199	    ".set push\n"						\
200            ".set mips64\n"						\
201	    ".set noreorder\n"						\
202	    ".set noat\n"						\
203	    "dsll   %1, %2, 32\n"					\
204	    "dsll   %0, %3, 32\n"					\
205	    "dsrl   %0, %0, 32\n"					\
206	    "or     %1, %1, %0\n"					\
207	    "lb     %1, 0(%1)\n"					\
208	    ".set pop\n"						\
209	    : "=&r" (tmp1), "=&r" (tmp2)				\
210	    : "r" (csr_addrh), "r" (csr_addrl));			\
211									\
212	intr_restore(sr);						\
213									\
214	return ((t)tmp2);						\
215}
216
217OCT_READ(8, uint8_t, "lb");
218OCT_READ(16, uint16_t, "lh");
219OCT_READ(32, uint32_t, "lw");
220
221static inline uint64_t oct_read64 (uint64_t csr_addr)
222{
223	uint32_t csr_addrh = csr_addr >> 32;
224	uint32_t csr_addrl = csr_addr;
225	uint32_t valh;
226	uint32_t vall;
227	register_t sr;
228
229	sr = intr_disable();
230
231	__asm __volatile (
232	    ".set push\n"
233            ".set mips64\n"
234	    ".set noreorder\n"
235	    ".set noat\n"
236	    "dsll   %0, %2, 32\n"
237	    "dsll   %1, %3, 32\n"
238	    "dsrl   %1, %1, 32\n"
239	    "or     %0, %0, %1\n"
240	    "ld     %1, 0(%0)\n"
241	    "dsrl   %0, %1, 32\n"
242	    "dsll   %1, %1, 32\n"
243	    "dsrl   %1, %1, 32\n"
244	    ".set pop\n"
245	    : "=&r" (valh), "=&r" (vall)
246	    : "r" (csr_addrh), "r" (csr_addrl));
247
248	intr_restore(sr);
249
250	return ((uint64_t)valh << 32) | vall;
251}
252#endif
253
254#endif
255
256#define	oct_write64_int64(a, v)	(oct_write64(a, (int64_t)(v)))
257
258/*
259 * Most write bus transactions are actually 64-bit on Octeon.
260 */
261static inline void oct_write8 (uint64_t csr_addr, uint8_t val8)
262{
263    oct_write64(csr_addr, (uint64_t) val8);
264}
265
266static inline void oct_write16 (uint64_t csr_addr, uint16_t val16)
267{
268    oct_write64(csr_addr, (uint64_t) val16);
269}
270
271static inline void oct_write32 (uint64_t csr_addr, uint32_t val32)
272{
273    oct_write64(csr_addr, (uint64_t) val32);
274}
275
276#define	oct_readint32(a)	((int32_t)oct_read32((a)))
277
278/*
279 * octeon_machdep.c
280 *
281 * Direct to Board Support level.
282 */
283extern void octeon_led_write_char(int char_position, char val);
284extern void octeon_led_write_hexchar(int char_position, char hexval);
285extern void octeon_led_write_hex(uint32_t wl);
286extern void octeon_led_write_string(const char *str);
287extern void octeon_reset(void);
288extern void octeon_led_write_char0(char val);
289extern void octeon_led_run_wheel(int *pos, int led_position);
290extern void octeon_debug_symbol(void);
291extern void octeon_ciu_reset(void);
292extern int octeon_is_simulation(void);
293#endif	/* LOCORE */
294
295/*
296 * EBT3000 LED Unit
297 */
298#define  OCTEON_CHAR_LED_BASE_ADDR	(0x1d020000 | (0x1ffffffffull << 31))
299
300#endif /* !OCTEON_PCMAP_REGS_H__ */
301