Path: blob/master/arch/x86/platform/olpc/olpc_dt.c
10821 views
/*1* OLPC-specific OFW device tree support code.2*3* Paul Mackerras August 1996.4* Copyright (C) 1996-2005 Paul Mackerras.5*6* Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.7* {engebret|bergner}@us.ibm.com8*9* Adapted for sparc by David S. Miller [email protected]10* Adapted for x86/OLPC by Andres Salomon <[email protected]>11*12* This program is free software; you can redistribute it and/or13* modify it under the terms of the GNU General Public License14* as published by the Free Software Foundation; either version15* 2 of the License, or (at your option) any later version.16*/1718#include <linux/kernel.h>19#include <linux/bootmem.h>20#include <linux/of.h>21#include <linux/of_platform.h>22#include <linux/of_pdt.h>23#include <asm/olpc.h>24#include <asm/olpc_ofw.h>2526static phandle __init olpc_dt_getsibling(phandle node)27{28const void *args[] = { (void *)node };29void *res[] = { &node };3031if ((s32)node == -1)32return 0;3334if (olpc_ofw("peer", args, res) || (s32)node == -1)35return 0;3637return node;38}3940static phandle __init olpc_dt_getchild(phandle node)41{42const void *args[] = { (void *)node };43void *res[] = { &node };4445if ((s32)node == -1)46return 0;4748if (olpc_ofw("child", args, res) || (s32)node == -1) {49pr_err("PROM: %s: fetching child failed!\n", __func__);50return 0;51}5253return node;54}5556static int __init olpc_dt_getproplen(phandle node, const char *prop)57{58const void *args[] = { (void *)node, prop };59int len;60void *res[] = { &len };6162if ((s32)node == -1)63return -1;6465if (olpc_ofw("getproplen", args, res)) {66pr_err("PROM: %s: getproplen failed!\n", __func__);67return -1;68}6970return len;71}7273static int __init olpc_dt_getproperty(phandle node, const char *prop,74char *buf, int bufsize)75{76int plen;7778plen = olpc_dt_getproplen(node, prop);79if (plen > bufsize || plen < 1) {80return -1;81} else {82const void *args[] = { (void *)node, prop, buf, (void *)plen };83void *res[] = { &plen };8485if (olpc_ofw("getprop", args, res)) {86pr_err("PROM: %s: getprop failed!\n", __func__);87return -1;88}89}9091return plen;92}9394static int __init olpc_dt_nextprop(phandle node, char *prev, char *buf)95{96const void *args[] = { (void *)node, prev, buf };97int success;98void *res[] = { &success };99100buf[0] = '\0';101102if ((s32)node == -1)103return -1;104105if (olpc_ofw("nextprop", args, res) || success != 1)106return -1;107108return 0;109}110111static int __init olpc_dt_pkg2path(phandle node, char *buf,112const int buflen, int *len)113{114const void *args[] = { (void *)node, buf, (void *)buflen };115void *res[] = { len };116117if ((s32)node == -1)118return -1;119120if (olpc_ofw("package-to-path", args, res) || *len < 1)121return -1;122123return 0;124}125126static unsigned int prom_early_allocated __initdata;127128void * __init prom_early_alloc(unsigned long size)129{130static u8 *mem;131static size_t free_mem;132void *res;133134if (free_mem < size) {135const size_t chunk_size = max(PAGE_SIZE, size);136137/*138* To mimimize the number of allocations, grab at least139* PAGE_SIZE of memory (that's an arbitrary choice that's140* fast enough on the platforms we care about while minimizing141* wasted bootmem) and hand off chunks of it to callers.142*/143res = alloc_bootmem(chunk_size);144BUG_ON(!res);145prom_early_allocated += chunk_size;146memset(res, 0, chunk_size);147free_mem = chunk_size;148mem = res;149}150151/* allocate from the local cache */152free_mem -= size;153res = mem;154mem += size;155return res;156}157158static struct of_pdt_ops prom_olpc_ops __initdata = {159.nextprop = olpc_dt_nextprop,160.getproplen = olpc_dt_getproplen,161.getproperty = olpc_dt_getproperty,162.getchild = olpc_dt_getchild,163.getsibling = olpc_dt_getsibling,164.pkg2path = olpc_dt_pkg2path,165};166167void __init olpc_dt_build_devicetree(void)168{169phandle root;170171if (!olpc_ofw_is_installed())172return;173174root = olpc_dt_getsibling(0);175if (!root) {176pr_err("PROM: unable to get root node from OFW!\n");177return;178}179of_pdt_build_devicetree(root, &prom_olpc_ops);180181pr_info("PROM DT: Built device tree with %u bytes of memory.\n",182prom_early_allocated);183}184185/* A list of DT node/bus matches that we want to expose as platform devices */186static struct of_device_id __initdata of_ids[] = {187{ .compatible = "olpc,xo1-battery" },188{ .compatible = "olpc,xo1-dcon" },189{ .compatible = "olpc,xo1-rtc" },190{},191};192193static int __init olpc_create_platform_devices(void)194{195if (machine_is_olpc())196return of_platform_bus_probe(NULL, of_ids, NULL);197else198return 0;199}200device_initcall(olpc_create_platform_devices);201202203