mpc85xx.c revision 209908
1169689Skan/*-
2169689Skan * Copyright (C) 2008 Semihalf, Rafal Jaworowski
3169689Skan * All rights reserved.
4169689Skan *
5169689Skan * Redistribution and use in source and binary forms, with or without
6169689Skan * modification, are permitted provided that the following conditions
7169689Skan * are met:
8169689Skan * 1. Redistributions of source code must retain the above copyright
9169689Skan *    notice, this list of conditions and the following disclaimer.
10169689Skan * 2. Redistributions in binary form must reproduce the above copyright
11169689Skan *    notice, this list of conditions and the following disclaimer in the
12169689Skan *    documentation and/or other materials provided with the distribution.
13169689Skan *
14169689Skan * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24169689Skan * SUCH DAMAGE.
25169689Skan */
26169689Skan
27169689Skan#include <sys/cdefs.h>
28169689Skan__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/mpc85xx.c 209908 2010-07-11 21:08:29Z raj $");
29169689Skan
30169689Skan#include <sys/param.h>
31169689Skan#include <sys/systm.h>
32169689Skan#include <sys/lock.h>
33169689Skan#include <sys/mutex.h>
34169689Skan#include <sys/rman.h>
35169689Skan
36169689Skan#include <vm/vm.h>
37169689Skan#include <vm/vm_param.h>
38169689Skan
39169689Skan#include <machine/cpu.h>
40169689Skan#include <machine/cpufunc.h>
41169689Skan#include <machine/spr.h>
42169689Skan
43169689Skan#include <powerpc/mpc85xx/mpc85xx.h>
44169689Skan
45169689Skan/*
46169689Skan * MPC85xx system specific routines
47169689Skan */
48169689Skan
49169689Skanuint32_t
50169689Skanccsr_read4(uintptr_t addr)
51169689Skan{
52169689Skan	volatile uint32_t *ptr = (void *)addr;
53169689Skan
54169689Skan	return (*ptr);
55169689Skan}
56169689Skan
57169689Skanvoid
58169689Skanccsr_write4(uintptr_t addr, uint32_t val)
59169689Skan{
60169689Skan	volatile uint32_t *ptr = (void *)addr;
61169689Skan
62169689Skan	*ptr = val;
63169689Skan	__asm __volatile("eieio; sync");
64169689Skan}
65169689Skan
66169689Skanint
67169689Skanlaw_getmax(void)
68169689Skan{
69169689Skan	uint32_t ver;
70169689Skan
71169689Skan	ver = SVR_VER(mfspr(SPR_SVR));
72169689Skan	if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
73169689Skan		return (12);
74169689Skan	else if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
75169689Skan		return (10);
76169689Skan	else
77169689Skan		return (8);
78169689Skan}
79169689Skan
80169689Skan#define	_LAW_SR(trgt,size)	(0x80000000 | (trgt << 20) | (ffsl(size) - 2))
81169689Skan#define	_LAW_BAR(addr)		(addr >> 12)
82169689Skan
83169689Skanint
84169689Skanlaw_enable(int trgt, u_long addr, u_long size)
85169689Skan{
86169689Skan	uint32_t bar, sr;
87169689Skan	int i, law_max;
88169689Skan
89169689Skan	law_max = law_getmax();
90169689Skan	bar = _LAW_BAR(addr);
91169689Skan	sr = _LAW_SR(trgt, size);
92169689Skan
93169689Skan	/* Bail if already programmed. */
94169689Skan	for (i = 0; i < law_max; i++)
95169689Skan		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
96169689Skan		    bar == ccsr_read4(OCP85XX_LAWBAR(i)))
97169689Skan			return (0);
98169689Skan
99169689Skan	/* Find an unused access window. */
100169689Skan	for (i = 0; i < law_max; i++)
101169689Skan		if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
102169689Skan			break;
103169689Skan
104169689Skan	if (i == law_max)
105169689Skan		return (ENOSPC);
106169689Skan
107169689Skan	ccsr_write4(OCP85XX_LAWBAR(i), bar);
108169689Skan	ccsr_write4(OCP85XX_LAWSR(i), sr);
109169689Skan	return (0);
110169689Skan}
111169689Skan
112169689Skanint
113169689Skanlaw_disable(int trgt, u_long addr, u_long size)
114169689Skan{
115169689Skan	uint32_t bar, sr;
116169689Skan	int i, law_max;
117169689Skan
118169689Skan	law_max = law_getmax();
119169689Skan	bar = _LAW_BAR(addr);
120169689Skan	sr = _LAW_SR(trgt, size);
121169689Skan
122169689Skan	/* Find and disable requested LAW. */
123169689Skan	for (i = 0; i < law_max; i++)
124169689Skan		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
125169689Skan		    bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
126169689Skan			ccsr_write4(OCP85XX_LAWBAR(i), 0);
127169689Skan			ccsr_write4(OCP85XX_LAWSR(i), 0);
128169689Skan			return (0);
129169689Skan		}
130169689Skan
131169689Skan	return (ENOENT);
132169689Skan}
133169689Skan
134169689Skanint
135169689Skanlaw_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
136169689Skan{
137169689Skan	u_long start;
138169689Skan	uint32_t ver;
139169689Skan	int trgt, rv;
140169689Skan
141169689Skan	ver = SVR_VER(mfspr(SPR_SVR));
142169689Skan
143169689Skan	start = rman_get_start(res) & 0xf000;
144169689Skan
145169689Skan	rv = 0;
146169689Skan	trgt = -1;
147169689Skan	switch (start) {
148169689Skan	case 0x8000:
149169689Skan		trgt = 0;
150169689Skan		break;
151169689Skan	case 0x9000:
152169689Skan		trgt = 1;
153169689Skan		break;
154169689Skan	case 0xa000:
155169689Skan		if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
156169689Skan			trgt = 2;
157169689Skan		else
158169689Skan			rv = EINVAL;
159169689Skan		break;
160169689Skan	default:
161169689Skan		rv = ENXIO;
162169689Skan	}
163169689Skan	*trgt_mem = *trgt_io = trgt;
164169689Skan	return (rv);
165169689Skan}
166169689Skan
167169689Skanvoid
168169689Skancpu_reset(void)
169169689Skan{
170169689Skan	uint32_t ver = SVR_VER(mfspr(SPR_SVR));
171169689Skan
172169689Skan	if (ver == SVR_MPC8572E || ver == SVR_MPC8572 ||
173169689Skan	    ver == SVR_MPC8548E || ver == SVR_MPC8548)
174169689Skan		/* Systems with dedicated reset register */
175169689Skan		ccsr_write4(OCP85XX_RSTCR, 2);
176169689Skan	else {
177169689Skan		/* Clear DBCR0, disables debug interrupts and events. */
178169689Skan		mtspr(SPR_DBCR0, 0);
179169689Skan		__asm __volatile("isync");
180169689Skan
181169689Skan		/* Enable Debug Interrupts in MSR. */
182169689Skan		mtmsr(mfmsr() | PSL_DE);
183169689Skan
184169689Skan		/* Enable debug interrupts and issue reset. */
185169689Skan		mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM |
186169689Skan		    DBCR0_RST_SYSTEM);
187169689Skan	}
188169689Skan
189169689Skan	printf("Reset failed...\n");
190169689Skan	while (1);
191169689Skan}
192169689Skan