1235778Sgber/*-
2235778Sgber * Copyright (c) 2012 Semihalf.
3235778Sgber * All rights reserved.
4235778Sgber *
5235778Sgber * Redistribution and use in source and binary forms, with or without
6235778Sgber * modification, are permitted provided that the following conditions
7235778Sgber * are met:
8235778Sgber * 1. Redistributions of source code must retain the above copyright
9235778Sgber *    notice, this list of conditions and the following disclaimer.
10235778Sgber * 2. Redistributions in binary form must reproduce the above copyright
11235778Sgber *    notice, this list of conditions and the following disclaimer in the
12235778Sgber *    documentation and/or other materials provided with the distribution.
13235778Sgber *
14235778Sgber * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15235778Sgber * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16235778Sgber * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17235778Sgber * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18235778Sgber * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19235778Sgber * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20235778Sgber * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21235778Sgber * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22235778Sgber * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23235778Sgber * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24235778Sgber * SUCH DAMAGE.
25235778Sgber */
26235778Sgber
27235778Sgber#include <sys/cdefs.h>
28235778Sgber__FBSDID("$FreeBSD: releng/10.2/sys/dev/fdt/fdt_slicer.c 261077 2014-01-23 12:02:04Z loos $");
29235778Sgber
30235778Sgber#include <sys/param.h>
31235778Sgber#include <sys/systm.h>
32235778Sgber#include <sys/kernel.h>
33235778Sgber#include <sys/module.h>
34235778Sgber#include <sys/slicer.h>
35235778Sgber
36235778Sgber#include <dev/fdt/fdt_common.h>
37235778Sgber
38235778Sgber#ifdef DEBUG
39235778Sgber#define debugf(fmt, args...) do { printf("%s(): ", __func__);	\
40235778Sgber    printf(fmt,##args); } while (0)
41235778Sgber#else
42235778Sgber#define debugf(fmt, args...)
43235778Sgber#endif
44235778Sgber
45235778Sgberint
46235778Sgberflash_fill_slices(device_t dev, struct flash_slice *slices, int *slices_num)
47235778Sgber{
48235778Sgber	char *slice_name;
49235778Sgber	phandle_t dt_node, dt_child;
50235778Sgber	u_long base, size;
51235778Sgber	int i;
52235778Sgber	ssize_t name_len;
53235778Sgber
54235778Sgber	/*
55235778Sgber	 * We assume the caller provides buffer for FLASH_SLICES_MAX_NUM
56235778Sgber	 * flash_slice structures.
57235778Sgber	 */
58235778Sgber	if (slices == NULL) {
59235778Sgber		*slices_num = 0;
60235778Sgber		return (ENOMEM);
61235778Sgber	}
62235778Sgber
63235778Sgber	dt_node = ofw_bus_get_node(dev);
64235778Sgber	for (dt_child = OF_child(dt_node), i = 0; dt_child != 0;
65235778Sgber	    dt_child = OF_peer(dt_child)) {
66235778Sgber
67235778Sgber		if (i == FLASH_SLICES_MAX_NUM) {
68235778Sgber			debugf("not enough buffer for slice i=%d\n", i);
69235778Sgber			break;
70235778Sgber		}
71235778Sgber
72235778Sgber		/*
73235778Sgber		 * Retrieve start and size of the slice.
74235778Sgber		 */
75235778Sgber		if (fdt_regsize(dt_child, &base, &size) != 0) {
76235778Sgber			debugf("error during processing reg property, i=%d\n",
77235778Sgber			    i);
78235778Sgber			continue;
79235778Sgber		}
80235778Sgber
81235778Sgber		if (size == 0) {
82235778Sgber			debugf("slice i=%d with no size\n", i);
83235778Sgber			continue;
84235778Sgber		}
85235778Sgber
86235778Sgber		/*
87235778Sgber		 * Retrieve label.
88235778Sgber		 */
89235778Sgber		name_len = OF_getprop_alloc(dt_child, "label", sizeof(char),
90235778Sgber		    (void **)&slice_name);
91235778Sgber		if (name_len <= 0) {
92235778Sgber			/* Use node name if no label defined */
93235778Sgber			name_len = OF_getprop_alloc(dt_child, "name", sizeof(char),
94235778Sgber			    (void **)&slice_name);
95235778Sgber			if (name_len <= 0) {
96235778Sgber				debugf("slice i=%d with no name\n", i);
97235778Sgber				slice_name = NULL;
98235778Sgber			}
99235778Sgber		}
100235778Sgber
101235778Sgber		/*
102235778Sgber		 * Fill slice entry data.
103235778Sgber		 */
104235778Sgber		slices[i].base = base;
105235778Sgber		slices[i].size = size;
106235778Sgber		slices[i].label = slice_name;
107235778Sgber		i++;
108235778Sgber	}
109235778Sgber
110235778Sgber	*slices_num = i;
111235778Sgber	return (0);
112235778Sgber}
113