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