summaryrefslogtreecommitdiffstats
path: root/sys/mips/nlm/hal/mmio.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/mips/nlm/hal/mmio.h')
-rw-r--r--sys/mips/nlm/hal/mmio.h338
1 files changed, 338 insertions, 0 deletions
diff --git a/sys/mips/nlm/hal/mmio.h b/sys/mips/nlm/hal/mmio.h
new file mode 100644
index 0000000..a19a867
--- /dev/null
+++ b/sys/mips/nlm/hal/mmio.h
@@ -0,0 +1,338 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ * NETLOGIC_BSD */
+
+#ifndef __NLM_NLMIO_H__
+#define __NLM_NLMIO_H__
+
+#if !defined(__mips_n32) && !defined(__mips_n64)
+/*
+ * For o32 compilation, we have to disable interrupts and enable KX bit to
+ * access 64 bit addresses or data.
+ *
+ * We need to disable interrupts because we save just the lower 32 bits of
+ * registers in interrupt handling. So if we get hit by an interrupt while
+ * using the upper 32 bits of a register, we lose.
+ */
+static __inline__ uint32_t nlm_enable_kx(void)
+{
+ uint32_t sr;
+
+ __asm__ __volatile__(
+ "mfc0 %0, $12 \n\t" /* read status reg */
+ "move $8, %0 \n\t"
+ "ori $8, $8, 0x81 \n\t" /* set KX, and IE */
+ "xori $8, $8, 0x1 \n\t" /* flip IE */
+ "mtc0 $8, $12 \n\t" /* update status reg */
+ : "=r"(sr)
+ : : "$8");
+
+ return (sr);
+}
+
+static __inline__ void nlm_restore_kx(uint32_t sr)
+{
+ __asm__ __volatile__("mtc0 %0, $12" : : "r"(sr));
+}
+#endif
+
+static __inline__ uint32_t
+nlm_load_word(volatile uint32_t *addr)
+{
+ return (*addr);
+}
+
+static __inline__ void
+nlm_store_word(volatile uint32_t *addr, uint32_t val)
+{
+ *addr = val;
+}
+
+#if defined(__mips_n64) || defined(__mips_n32)
+static __inline__ uint64_t
+nlm_load_dword(volatile uint64_t *addr)
+{
+ return (*addr);
+}
+
+static __inline__ void
+nlm_store_dword(volatile uint64_t *addr, uint64_t val)
+{
+ *addr = val;
+}
+
+#else /* o32 */
+static __inline__ uint64_t
+nlm_load_dword(volatile uint64_t *addr)
+{
+ uint32_t valhi, vallo, sr;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "ld $8, 0(%2) \n\t"
+ "dsra32 %0, $8, 0 \n\t"
+ "sll %1, $8, 0 \n\t"
+ ".set pop \n"
+ : "=r"(valhi), "=r"(vallo)
+ : "r"(addr)
+ : "$8" );
+ nlm_restore_kx(sr);
+
+ return (((uint64_t)valhi << 32) | vallo);
+}
+
+static __inline__ void
+nlm_store_dword(volatile uint64_t *addr, uint64_t val)
+{
+ uint32_t valhi, vallo, sr;
+
+ valhi = val >> 32;
+ vallo = val & 0xffffffff;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "dsll32 $8, %1, 0 \n\t"
+ "dsll32 $9, %2, 0 \n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0 \n\t" /* sign extend */
+ "or $9, $9, $8 \n\t"
+ "sd $9, 0(%0) \n\t"
+ ".set pop \n"
+ : : "r"(addr), "r"(valhi), "r"(vallo)
+ : "$8", "$9", "memory");
+ nlm_restore_kx(sr);
+}
+#endif
+
+#if defined(__mips_n64)
+static __inline__ uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr;
+
+ return (*p);
+}
+
+static __inline__ void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr;
+
+ *p = val;
+}
+
+static __inline__ uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr;
+
+ return (*p);
+}
+
+static __inline__ void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr;
+
+ *p = val;
+}
+
+#elif defined(__mips_n32)
+
+static __inline__ uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ uint32_t val;
+
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "lw %0, 0(%1) \n\t"
+ ".set pop \n"
+ : "=r"(val)
+ : "r"(addr));
+
+ return (val);
+}
+
+static __inline__ void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "sw %0, 0(%1) \n\t"
+ ".set pop \n"
+ : : "r"(val), "r"(addr)
+ : "memory");
+}
+
+static __inline__ uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ uint64_t val;
+
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "ld %0, 0(%1) \n\t"
+ ".set pop \n"
+ : "=r"(val)
+ : "r"(addr));
+ return (val);
+}
+
+static __inline__ void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "sd %0, 0(%1) \n\t"
+ ".set pop \n"
+ : : "r"(val), "r"(addr)
+ : "memory");
+}
+
+#else /* o32 */
+static __inline__ uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ uint32_t val, addrhi, addrlo, sr;
+
+ addrhi = addr >> 32;
+ addrlo = addr & 0xffffffff;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "dsll32 $8, %1, 0 \n\t"
+ "dsll32 $9, %2, 0 \n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0 \n\t" /* sign extend */
+ "or $9, $9, $8 \n\t"
+ "lw %0, 0($9) \n\t"
+ ".set pop \n"
+ : "=r"(val)
+ : "r"(addrhi), "r"(addrlo)
+ : "$8", "$9");
+ nlm_restore_kx(sr);
+
+ return (val);
+
+}
+
+static __inline__ void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ uint32_t addrhi, addrlo, sr;
+
+ addrhi = addr >> 32;
+ addrlo = addr & 0xffffffff;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "dsll32 $8, %1, 0 \n\t"
+ "dsll32 $9, %2, 0 \n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0 \n\t" /* sign extend */
+ "or $9, $9, $8 \n\t"
+ "sw %0, 0($9) \n\t"
+ ".set pop \n"
+ :: "r"(val), "r"(addrhi), "r"(addrlo)
+ : "$8", "$9", "memory");
+ nlm_restore_kx(sr);
+}
+
+static __inline__ uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ uint32_t addrh, addrl, sr;
+ uint32_t valh, vall;
+
+ addrh = addr >> 32;
+ addrl = addr & 0xffffffff;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "dsll32 $8, %2, 0 \n\t"
+ "dsll32 $9, %3, 0 \n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0 \n\t" /* sign extend */
+ "or $9, $9, $8 \n\t"
+ "ld $8, 0($9) \n\t"
+ "dsra32 %0, $8, 0 \n\t"
+ "sll %1, $8, 0 \n\t"
+ ".set pop \n"
+ : "=r"(valh), "=r"(vall)
+ : "r"(addrh), "r"(addrl)
+ : "$8", "$9");
+ nlm_restore_kx(sr);
+
+ return (((uint64_t)valh << 32) | vall);
+}
+
+static __inline__ void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ uint32_t addrh, addrl, sr;
+ uint32_t valh, vall;
+
+ addrh = addr >> 32;
+ addrl = addr & 0xffffffff;
+ valh = val >> 32;
+ vall = val & 0xffffffff;
+
+ sr = nlm_enable_kx();
+ __asm__ __volatile__(
+ ".set push \n\t"
+ ".set mips64 \n\t"
+ "dsll32 $8, %2, 0 \n\t"
+ "dsll32 $9, %3, 0 \n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0 \n\t" /* sign extend */
+ "or $9, $9, $8 \n\t"
+ "dsll32 $8, %0, 0 \n\t"
+ "dsll32 $10, %1, 0 \n\t" /* get rid of the */
+ "dsrl32 $10, $10, 0 \n\t" /* sign extend */
+ "or $8, $8, $10 \n\t"
+ "sd $8, 0($9) \n\t"
+ ".set pop \n"
+ : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
+ : "$8", "$9", "memory");
+ nlm_restore_kx(sr);
+}
+
+#endif /* __mips_n64 */
+
+#endif
OpenPOWER on IntegriCloud