platform.c revision 266301
1266301Sandrew/*-
2266301Sandrew * Copyright (c) 2005 Peter Grehan
3266301Sandrew * Copyright (c) 2009 Nathan Whitehorn
4266301Sandrew * All rights reserved.
5266301Sandrew *
6266301Sandrew * Redistribution and use in source and binary forms, with or without
7266301Sandrew * modification, are permitted provided that the following conditions
8266301Sandrew * are met:
9266301Sandrew * 1. Redistributions of source code must retain the above copyright
10266301Sandrew *    notice, this list of conditions and the following disclaimer.
11266301Sandrew * 2. Redistributions in binary form must reproduce the above copyright
12266301Sandrew *    notice, this list of conditions and the following disclaimer in the
13266301Sandrew *    documentation and/or other materials provided with the distribution.
14266301Sandrew *
15266301Sandrew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16266301Sandrew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17266301Sandrew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18266301Sandrew * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19266301Sandrew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20266301Sandrew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21266301Sandrew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22266301Sandrew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23266301Sandrew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24266301Sandrew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25266301Sandrew * SUCH DAMAGE.
26266301Sandrew *
27266301Sandrew */
28266301Sandrew
29266301Sandrew#include <sys/cdefs.h>
30266301Sandrew__FBSDID("$FreeBSD: head/sys/arm/arm/platform.c 266301 2014-05-17 11:27:36Z andrew $");
31266301Sandrew
32266301Sandrew/*
33266301Sandrew * Dispatch platform calls to the appropriate platform implementation
34266301Sandrew * through a previously registered kernel object.
35266301Sandrew */
36266301Sandrew
37266301Sandrew#define	_ARM32_BUS_DMA_PRIVATE
38266301Sandrew#include <sys/param.h>
39266301Sandrew#include <sys/bus.h>
40266301Sandrew#include <sys/kernel.h>
41266301Sandrew#include <sys/lock.h>
42266301Sandrew#include <sys/ktr.h>
43266301Sandrew#include <sys/mutex.h>
44266301Sandrew#include <sys/rman.h>
45266301Sandrew#include <sys/systm.h>
46266301Sandrew#include <sys/smp.h>
47266301Sandrew#include <sys/sysctl.h>
48266301Sandrew#include <sys/types.h>
49266301Sandrew
50266301Sandrew#include <vm/vm.h>
51266301Sandrew#include <vm/vm_page.h>
52266301Sandrew
53266301Sandrew#include <machine/bus_dma.h>
54266301Sandrew#include <machine/cpu.h>
55266301Sandrew#include <machine/intr.h>
56266301Sandrew#include <machine/md_var.h>
57266301Sandrew#include <machine/platform.h>
58266301Sandrew#include <machine/platformvar.h>
59266301Sandrew#include <machine/smp.h>
60266301Sandrew
61266301Sandrew#include "platform_if.h"
62266301Sandrew
63266301Sandrewstatic platform_def_t	*plat_def_impl;
64266301Sandrewstatic platform_t	plat_obj;
65266301Sandrewstatic struct kobj_ops	plat_kernel_kops;
66266301Sandrewstatic struct platform_kobj	plat_kernel_obj;
67266301Sandrew
68266301Sandrewstatic char plat_name[64] = "";
69266301SandrewSYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RDTUN, plat_name, 0,
70266301Sandrew    "Platform currently in use");
71266301Sandrew
72266301Sandrew/*
73266301Sandrew * Platform install routines. Highest priority wins, using the same
74266301Sandrew * algorithm as bus attachment.
75266301Sandrew */
76266301SandrewSET_DECLARE(platform_set, platform_def_t);
77266301Sandrew
78266301Sandrewvoid
79266301Sandrewplatform_probe_and_attach(void)
80266301Sandrew{
81266301Sandrew	platform_def_t	**platpp, *platp;
82266301Sandrew	int		prio, best_prio;
83266301Sandrew
84266301Sandrew	plat_obj = &plat_kernel_obj;
85266301Sandrew	best_prio = 0;
86266301Sandrew
87266301Sandrew	/*
88266301Sandrew	 * We are unable to use TUNABLE_STR as the read will happen
89266301Sandrew	 * well after this function has returned.
90266301Sandrew	 */
91266301Sandrew	TUNABLE_STR_FETCH("hw.platform", plat_name, sizeof(plat_name));
92266301Sandrew
93266301Sandrew	/*
94266301Sandrew	 * Try to locate the best platform kobj
95266301Sandrew	 */
96266301Sandrew	SET_FOREACH(platpp, platform_set) {
97266301Sandrew		platp = *platpp;
98266301Sandrew
99266301Sandrew		/*
100266301Sandrew		 * Take care of compiling the selected class, and
101266301Sandrew		 * then statically initialise the MMU object
102266301Sandrew		 */
103266301Sandrew		kobj_class_compile_static(platp, &plat_kernel_kops);
104266301Sandrew		kobj_init_static((kobj_t)plat_obj, platp);
105266301Sandrew
106266301Sandrew		plat_obj->cls = platp;
107266301Sandrew
108266301Sandrew		prio = PLATFORM_PROBE(plat_obj);
109266301Sandrew
110266301Sandrew		/* Check for errors */
111266301Sandrew		if (prio > 0)
112266301Sandrew			continue;
113266301Sandrew
114266301Sandrew		/*
115266301Sandrew		 * Check if this module was specifically requested through
116266301Sandrew		 * the loader tunable we provide.
117266301Sandrew		 */
118266301Sandrew		if (strcmp(platp->name,plat_name) == 0) {
119266301Sandrew			plat_def_impl = platp;
120266301Sandrew			break;
121266301Sandrew		}
122266301Sandrew
123266301Sandrew		/* Otherwise, see if it is better than our current best */
124266301Sandrew		if (plat_def_impl == NULL || prio > best_prio) {
125266301Sandrew			best_prio = prio;
126266301Sandrew			plat_def_impl = platp;
127266301Sandrew		}
128266301Sandrew
129266301Sandrew		/*
130266301Sandrew		 * We can't free the KOBJ, since it is static. Reset the ops
131266301Sandrew		 * member of this class so that we can come back later.
132266301Sandrew		 */
133266301Sandrew		platp->ops = NULL;
134266301Sandrew	}
135266301Sandrew
136266301Sandrew	if (plat_def_impl == NULL)
137266301Sandrew		panic("No platform module found!");
138266301Sandrew
139266301Sandrew	/*
140266301Sandrew	 * Recompile to make sure we ended with the
141266301Sandrew	 * correct one, and then attach.
142266301Sandrew	 */
143266301Sandrew
144266301Sandrew	kobj_class_compile_static(plat_def_impl, &plat_kernel_kops);
145266301Sandrew	kobj_init_static((kobj_t)plat_obj, plat_def_impl);
146266301Sandrew
147266301Sandrew	strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name));
148266301Sandrew
149266301Sandrew	PLATFORM_ATTACH(plat_obj);
150266301Sandrew}
151266301Sandrew
152266301Sandrewint
153266301Sandrewplatform_devmap_init(void)
154266301Sandrew{
155266301Sandrew
156266301Sandrew	return PLATFORM_DEVMAP_INIT(plat_obj);
157266301Sandrew}
158266301Sandrew
159266301Sandrewvm_offset_t
160266301Sandrewplatform_lastaddr(void)
161266301Sandrew{
162266301Sandrew
163266301Sandrew	return PLATFORM_LASTADDR(plat_obj);
164266301Sandrew}
165266301Sandrew
166266301Sandrewvoid
167266301Sandrewplatform_gpio_init(void)
168266301Sandrew{
169266301Sandrew
170266301Sandrew	PLATFORM_GPIO_INIT(plat_obj);
171266301Sandrew}
172266301Sandrew
173266301Sandrewvoid
174266301Sandrewplatform_late_init(void)
175266301Sandrew{
176266301Sandrew
177266301Sandrew	PLATFORM_LATE_INIT(plat_obj);
178266301Sandrew}
179266301Sandrew
180