summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/mpc85xx/mpc85xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/powerpc/mpc85xx/mpc85xx.c')
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c69
1 files changed, 66 insertions, 3 deletions
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index b75e301..de9c771 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -10,9 +10,6 @@
* 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.
- * 3. Neither the name of the author nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -64,6 +61,72 @@ ccsr_write4(uintptr_t addr, uint32_t val)
__asm __volatile("eieio; sync");
}
+static __inline int
+law_getmax(void)
+{
+ uint32_t ver;
+
+ ver = SVR_VER(mfspr(SPR_SVR));
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
+ return (12);
+ else
+ return (8);
+}
+
+#define _LAW_SR(trgt,size) (0x80000000 | (trgt << 20) | (ffsl(size) - 2))
+#define _LAW_BAR(addr) (addr >> 12)
+
+int
+law_enable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Bail if already programmed. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i)))
+ return (0);
+
+ /* Find an unused access window. */
+ for (i = 0; i < law_max; i++)
+ if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
+ break;
+
+ if (i == law_max)
+ return (ENOSPC);
+
+ ccsr_write4(OCP85XX_LAWBAR(i), bar);
+ ccsr_write4(OCP85XX_LAWSR(i), sr);
+ return (0);
+}
+
+int
+law_disable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Find and disable requested LAW. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
+ ccsr_write4(OCP85XX_LAWBAR(i), 0);
+ ccsr_write4(OCP85XX_LAWSR(i), 0);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
void
cpu_reset(void)
{
OpenPOWER on IntegriCloud