mpc85xx.c revision 267654
1238106Sdes/*-
2238106Sdes * Copyright (C) 2008 Semihalf, Rafal Jaworowski
3238106Sdes * All rights reserved.
4238106Sdes *
5238106Sdes * Redistribution and use in source and binary forms, with or without
6238106Sdes * modification, are permitted provided that the following conditions
7238106Sdes * are met:
8238106Sdes * 1. Redistributions of source code must retain the above copyright
9238106Sdes *    notice, this list of conditions and the following disclaimer.
10238106Sdes * 2. Redistributions in binary form must reproduce the above copyright
11238106Sdes *    notice, this list of conditions and the following disclaimer in the
12238106Sdes *    documentation and/or other materials provided with the distribution.
13238106Sdes *
14238106Sdes * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17238106Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18238106Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19238106Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20238106Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21238106Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22238106Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23238106Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24269257Sdes * SUCH DAMAGE.
25269257Sdes */
26269257Sdes
27269257Sdes#include <sys/cdefs.h>
28269257Sdes__FBSDID("$FreeBSD: releng/9.3/sys/powerpc/mpc85xx/mpc85xx.c 222428 2011-05-28 19:14:16Z marcel $");
29269257Sdes
30269257Sdes#include <sys/param.h>
31269257Sdes#include <sys/systm.h>
32269257Sdes#include <sys/lock.h>
33269257Sdes#include <sys/mutex.h>
34238106Sdes#include <sys/rman.h>
35238106Sdes
36238106Sdes#include <vm/vm.h>
37238106Sdes#include <vm/vm_param.h>
38238106Sdes
39238106Sdes#include <machine/cpu.h>
40238106Sdes#include <machine/cpufunc.h>
41238106Sdes#include <machine/spr.h>
42238106Sdes
43238106Sdes#include <powerpc/mpc85xx/mpc85xx.h>
44238106Sdes
45238106Sdes/*
46269257Sdes * MPC85xx system specific routines
47238106Sdes */
48238106Sdes
49238106Sdesuint32_t
50238106Sdesccsr_read4(uintptr_t addr)
51238106Sdes{
52238106Sdes	volatile uint32_t *ptr = (void *)addr;
53238106Sdes
54238106Sdes	return (*ptr);
55238106Sdes}
56238106Sdes
57238106Sdesvoid
58238106Sdesccsr_write4(uintptr_t addr, uint32_t val)
59238106Sdes{
60238106Sdes	volatile uint32_t *ptr = (void *)addr;
61238106Sdes
62238106Sdes	*ptr = val;
63238106Sdes	__asm __volatile("eieio; sync");
64269257Sdes}
65269257Sdes
66269257Sdesint
67269257Sdeslaw_getmax(void)
68238106Sdes{
69238106Sdes	uint32_t ver;
70238106Sdes
71238106Sdes	ver = SVR_VER(mfspr(SPR_SVR));
72238106Sdes	if (ver == SVR_MPC8555E || ver == SVR_MPC8555)
73238106Sdes		return (8);
74269257Sdes	if (ver == SVR_MPC8548E || ver == SVR_MPC8548 ||
75269257Sdes	    ver == SVR_MPC8533E || ver == SVR_MPC8533)
76238106Sdes		return (10);
77238106Sdes
78238106Sdes	return (12);
79238106Sdes}
80238106Sdes
81238106Sdes#define	_LAW_SR(trgt,size)	(0x80000000 | (trgt << 20) | (ffsl(size) - 2))
82238106Sdes#define	_LAW_BAR(addr)		(addr >> 12)
83238106Sdes
84238106Sdesint
85238106Sdeslaw_enable(int trgt, u_long addr, u_long size)
86238106Sdes{
87238106Sdes	uint32_t bar, sr;
88238106Sdes	int i, law_max;
89238106Sdes
90238106Sdes	law_max = law_getmax();
91238106Sdes	bar = _LAW_BAR(addr);
92238106Sdes	sr = _LAW_SR(trgt, size);
93238106Sdes
94238106Sdes	/* Bail if already programmed. */
95238106Sdes	for (i = 0; i < law_max; i++)
96238106Sdes		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
97238106Sdes		    bar == ccsr_read4(OCP85XX_LAWBAR(i)))
98238106Sdes			return (0);
99238106Sdes
100238106Sdes	/* Find an unused access window. */
101238106Sdes	for (i = 0; i < law_max; i++)
102238106Sdes		if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
103238106Sdes			break;
104238106Sdes
105238106Sdes	if (i == law_max)
106238106Sdes		return (ENOSPC);
107238106Sdes
108238106Sdes	ccsr_write4(OCP85XX_LAWBAR(i), bar);
109238106Sdes	ccsr_write4(OCP85XX_LAWSR(i), sr);
110238106Sdes	return (0);
111238106Sdes}
112238106Sdes
113238106Sdesint
114238106Sdeslaw_disable(int trgt, u_long addr, u_long size)
115238106Sdes{
116238106Sdes	uint32_t bar, sr;
117238106Sdes	int i, law_max;
118238106Sdes
119238106Sdes	law_max = law_getmax();
120238106Sdes	bar = _LAW_BAR(addr);
121238106Sdes	sr = _LAW_SR(trgt, size);
122238106Sdes
123238106Sdes	/* Find and disable requested LAW. */
124238106Sdes	for (i = 0; i < law_max; i++)
125238106Sdes		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
126238106Sdes		    bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
127238106Sdes			ccsr_write4(OCP85XX_LAWBAR(i), 0);
128238106Sdes			ccsr_write4(OCP85XX_LAWSR(i), 0);
129238106Sdes			return (0);
130238106Sdes		}
131238106Sdes
132238106Sdes	return (ENOENT);
133238106Sdes}
134238106Sdes
135238106Sdesint
136269257Sdeslaw_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
137269257Sdes{
138269257Sdes	u_long start;
139269257Sdes	uint32_t ver;
140269257Sdes	int trgt, rv;
141269257Sdes
142269257Sdes	ver = SVR_VER(mfspr(SPR_SVR));
143269257Sdes
144269257Sdes	start = rman_get_start(res) & 0xf000;
145269257Sdes
146269257Sdes	rv = 0;
147269257Sdes	trgt = -1;
148269257Sdes	switch (start) {
149269257Sdes	case 0x8000:
150269257Sdes		trgt = 0;
151269257Sdes		break;
152269257Sdes	case 0x9000:
153269257Sdes		trgt = 1;
154269257Sdes		break;
155269257Sdes	case 0xa000:
156269257Sdes		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
157269257Sdes			trgt = 3;
158269257Sdes		else
159269257Sdes			trgt = 2;
160269257Sdes		break;
161269257Sdes	case 0xb000:
162269257Sdes		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
163269257Sdes			rv = EINVAL;
164269257Sdes		else
165269257Sdes			trgt = 3;
166269257Sdes		break;
167269257Sdes	default:
168269257Sdes		rv = ENXIO;
169269257Sdes	}
170269257Sdes	*trgt_mem = *trgt_io = trgt;
171269257Sdes	return (rv);
172269257Sdes}
173269257Sdes
174269257Sdes