1209906Sraj/*-
2209906Sraj * Copyright (c) 2009-2010 The FreeBSD Foundation
3209906Sraj * All rights reserved.
4209906Sraj *
5209906Sraj * This software was developed by Semihalf under sponsorship from
6209906Sraj * the FreeBSD Foundation.
7209906Sraj *
8209906Sraj * Redistribution and use in source and binary forms, with or without
9209906Sraj * modification, are permitted provided that the following conditions
10209906Sraj * are met:
11209906Sraj * 1. Redistributions of source code must retain the above copyright
12209906Sraj *    notice, this list of conditions and the following disclaimer.
13209906Sraj * 2. Redistributions in binary form must reproduce the above copyright
14209906Sraj *    notice, this list of conditions and the following disclaimer in the
15209906Sraj *    documentation and/or other materials provided with the distribution.
16209906Sraj *
17209906Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18209906Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19209906Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20209906Sraj * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21209906Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22209906Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23209906Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24209906Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25209906Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26209906Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27209906Sraj * SUCH DAMAGE.
28209906Sraj */
29209906Sraj
30209906Sraj#include <sys/cdefs.h>
31209906Sraj__FBSDID("$FreeBSD$");
32209906Sraj
33209906Sraj#include <sys/param.h>
34209906Sraj#include <sys/systm.h>
35209906Sraj#include <sys/kernel.h>
36209906Sraj#include <sys/module.h>
37209906Sraj#include <sys/bus.h>
38209906Sraj
39209906Sraj#include <machine/intr_machdep.h>
40209906Sraj
41209906Sraj#include <dev/ofw/ofw_bus.h>
42209906Sraj#include <dev/ofw/ofw_bus_subr.h>
43209906Sraj#include <dev/ofw/openfirm.h>
44209906Sraj
45209906Sraj#include "ofw_bus_if.h"
46209906Sraj#include "fdt_common.h"
47209906Sraj
48209906Srajstatic void
49209906Srajfdt_fixup_busfreq(phandle_t root)
50209906Sraj{
51209906Sraj	phandle_t sb, cpus, child;
52209906Sraj	pcell_t freq;
53209906Sraj
54209906Sraj	/*
55209906Sraj	 * Do a strict check so as to skip non-SOC nodes, which also claim
56209906Sraj	 * simple-bus compatibility such as eLBC etc.
57209906Sraj	 */
58209906Sraj	if ((sb = fdt_find_compatible(root, "simple-bus", 1)) == 0)
59209906Sraj		return;
60209906Sraj
61209906Sraj	/*
62209906Sraj	 * This fixup uses /cpus/ bus-frequency prop value to set simple-bus
63209906Sraj	 * bus-frequency property.
64209906Sraj	 */
65209906Sraj	if ((cpus = OF_finddevice("/cpus")) == 0)
66209906Sraj		return;
67209906Sraj
68209906Sraj	if ((child = OF_child(cpus)) == 0)
69209906Sraj		return;
70209906Sraj
71209906Sraj	if (OF_getprop(child, "bus-frequency", (void *)&freq,
72209906Sraj	    sizeof(freq)) <= 0)
73209906Sraj		return;
74209906Sraj
75209906Sraj	OF_setprop(sb, "bus-frequency", (void *)&freq, sizeof(freq));
76209906Sraj}
77209906Sraj
78209906Srajstruct fdt_fixup_entry fdt_fixup_table[] = {
79209906Sraj	{ "fsl,MPC8572DS", &fdt_fixup_busfreq },
80209906Sraj	{ "MPC8555CDS", &fdt_fixup_busfreq },
81209906Sraj	{ NULL, NULL }
82209906Sraj};
83209906Sraj
84209906Srajstatic int
85209906Srajfdt_pic_decode_iic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
86209906Sraj    int *pol)
87209906Sraj{
88209906Sraj	if (!fdt_is_compatible(node, "chrp,iic"))
89209906Sraj		return (ENXIO);
90209906Sraj
91209906Sraj	*interrupt = intr[0];
92209906Sraj
93209906Sraj	switch (intr[1]) {
94209906Sraj	case 0:
95209906Sraj		/* Active L level */
96209906Sraj		*trig = INTR_TRIGGER_LEVEL;
97209906Sraj		*pol = INTR_POLARITY_LOW;
98209906Sraj		break;
99209906Sraj	case 1:
100209906Sraj		/* Active H level */
101209906Sraj		*trig = INTR_TRIGGER_LEVEL;
102209906Sraj		*pol = INTR_POLARITY_HIGH;
103209906Sraj		break;
104209906Sraj	case 2:
105209906Sraj		/* H to L edge */
106209906Sraj		*trig = INTR_TRIGGER_EDGE;
107209906Sraj		*pol = INTR_POLARITY_LOW;
108209906Sraj		break;
109209906Sraj	case 3:
110209906Sraj		/* L to H edge */
111209906Sraj		*trig = INTR_TRIGGER_EDGE;
112209906Sraj		*pol = INTR_POLARITY_HIGH;
113209906Sraj		break;
114209906Sraj	default:
115209906Sraj		*trig = INTR_TRIGGER_CONFORM;
116209906Sraj		*pol = INTR_POLARITY_CONFORM;
117209906Sraj	}
118209906Sraj	return (0);
119209906Sraj}
120209906Sraj
121209906Srajstatic int
122209906Srajfdt_pic_decode_openpic(phandle_t node, pcell_t *intr, int *interrupt,
123209906Sraj    int *trig, int *pol)
124209906Sraj{
125209906Sraj
126209906Sraj	if (!fdt_is_compatible(node, "chrp,open-pic"))
127209906Sraj		return (ENXIO);
128209906Sraj
129209906Sraj	/*
130209906Sraj	 * XXX The interrupt number read out from the MPC85XX device tree is
131209906Sraj	 * already offset by 16 to reflect the 'internal' IRQ range shift on
132209906Sraj	 * the OpenPIC.
133209906Sraj	 */
134209906Sraj	*interrupt = intr[0];
135209906Sraj
136209906Sraj	switch (intr[1]) {
137209906Sraj	case 0:
138209906Sraj		/* L to H edge */
139209906Sraj		*trig = INTR_TRIGGER_EDGE;
140209906Sraj		*pol = INTR_POLARITY_HIGH;
141209906Sraj		break;
142209906Sraj	case 1:
143209906Sraj		/* Active L level */
144209906Sraj		*trig = INTR_TRIGGER_LEVEL;
145209906Sraj		*pol = INTR_POLARITY_LOW;
146209906Sraj		break;
147209906Sraj	case 2:
148209906Sraj		/* Active H level */
149209906Sraj		*trig = INTR_TRIGGER_LEVEL;
150209906Sraj		*pol = INTR_POLARITY_HIGH;
151209906Sraj		break;
152209906Sraj	case 3:
153209906Sraj		/* H to L edge */
154209906Sraj		*trig = INTR_TRIGGER_EDGE;
155209906Sraj		*pol = INTR_POLARITY_LOW;
156209906Sraj		break;
157209906Sraj	default:
158209906Sraj		*trig = INTR_TRIGGER_CONFORM;
159209906Sraj		*pol = INTR_POLARITY_CONFORM;
160209906Sraj	}
161209906Sraj	return (0);
162209906Sraj}
163209906Sraj
164209906Srajfdt_pic_decode_t fdt_pic_table[] = {
165209906Sraj	&fdt_pic_decode_iic,
166209906Sraj	&fdt_pic_decode_openpic,
167209906Sraj	NULL
168209906Sraj};
169