14ffd4dfeSGrzegorz Bernacki /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 44ffd4dfeSGrzegorz Bernacki * Copyright (c) 2012 Semihalf. 54ffd4dfeSGrzegorz Bernacki * All rights reserved. 64ffd4dfeSGrzegorz Bernacki * 74ffd4dfeSGrzegorz Bernacki * Redistribution and use in source and binary forms, with or without 84ffd4dfeSGrzegorz Bernacki * modification, are permitted provided that the following conditions 94ffd4dfeSGrzegorz Bernacki * are met: 104ffd4dfeSGrzegorz Bernacki * 1. Redistributions of source code must retain the above copyright 114ffd4dfeSGrzegorz Bernacki * notice, this list of conditions and the following disclaimer. 124ffd4dfeSGrzegorz Bernacki * 2. Redistributions in binary form must reproduce the above copyright 134ffd4dfeSGrzegorz Bernacki * notice, this list of conditions and the following disclaimer in the 144ffd4dfeSGrzegorz Bernacki * documentation and/or other materials provided with the distribution. 154ffd4dfeSGrzegorz Bernacki * 164ffd4dfeSGrzegorz Bernacki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 174ffd4dfeSGrzegorz Bernacki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184ffd4dfeSGrzegorz Bernacki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194ffd4dfeSGrzegorz Bernacki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 204ffd4dfeSGrzegorz Bernacki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214ffd4dfeSGrzegorz Bernacki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224ffd4dfeSGrzegorz Bernacki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234ffd4dfeSGrzegorz Bernacki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244ffd4dfeSGrzegorz Bernacki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254ffd4dfeSGrzegorz Bernacki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264ffd4dfeSGrzegorz Bernacki * SUCH DAMAGE. 274ffd4dfeSGrzegorz Bernacki */ 284ffd4dfeSGrzegorz Bernacki 294ffd4dfeSGrzegorz Bernacki #include <sys/cdefs.h> 304ffd4dfeSGrzegorz Bernacki __FBSDID("$FreeBSD$"); 314ffd4dfeSGrzegorz Bernacki 324ffd4dfeSGrzegorz Bernacki #include <sys/param.h> 334ffd4dfeSGrzegorz Bernacki #include <sys/systm.h> 344ffd4dfeSGrzegorz Bernacki #include <sys/kernel.h> 35*4e462178SIan Lepore #include <sys/module.h> 364ffd4dfeSGrzegorz Bernacki #include <sys/slicer.h> 374ffd4dfeSGrzegorz Bernacki 384ffd4dfeSGrzegorz Bernacki #include <dev/fdt/fdt_common.h> 394874af73SMarius Strobl #include <dev/ofw/ofw_bus.h> 404874af73SMarius Strobl #include <dev/ofw/openfirm.h> 414ffd4dfeSGrzegorz Bernacki 424ffd4dfeSGrzegorz Bernacki #ifdef DEBUG 434ffd4dfeSGrzegorz Bernacki #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ 444ffd4dfeSGrzegorz Bernacki printf(fmt,##args); } while (0) 454ffd4dfeSGrzegorz Bernacki #else 464ffd4dfeSGrzegorz Bernacki #define debugf(fmt, args...) 474ffd4dfeSGrzegorz Bernacki #endif 484ffd4dfeSGrzegorz Bernacki 494874af73SMarius Strobl static int fdt_flash_fill_slices(device_t dev, const char *provider, 504874af73SMarius Strobl struct flash_slice *slices, int *slices_num); 514874af73SMarius Strobl static void fdt_slicer_init(void); 524874af73SMarius Strobl 534874af73SMarius Strobl static int 544874af73SMarius Strobl fdt_flash_fill_slices(device_t dev, const char *provider __unused, 554874af73SMarius Strobl struct flash_slice *slices, int *slices_num) 564ffd4dfeSGrzegorz Bernacki { 574ffd4dfeSGrzegorz Bernacki char *slice_name; 584ffd4dfeSGrzegorz Bernacki phandle_t dt_node, dt_child; 594ffd4dfeSGrzegorz Bernacki u_long base, size; 604ffd4dfeSGrzegorz Bernacki int i; 614ffd4dfeSGrzegorz Bernacki ssize_t name_len; 624ffd4dfeSGrzegorz Bernacki 634ffd4dfeSGrzegorz Bernacki /* 644ffd4dfeSGrzegorz Bernacki * We assume the caller provides buffer for FLASH_SLICES_MAX_NUM 654ffd4dfeSGrzegorz Bernacki * flash_slice structures. 664ffd4dfeSGrzegorz Bernacki */ 674ffd4dfeSGrzegorz Bernacki if (slices == NULL) { 684ffd4dfeSGrzegorz Bernacki *slices_num = 0; 694ffd4dfeSGrzegorz Bernacki return (ENOMEM); 704ffd4dfeSGrzegorz Bernacki } 714ffd4dfeSGrzegorz Bernacki 724ffd4dfeSGrzegorz Bernacki dt_node = ofw_bus_get_node(dev); 734ffd4dfeSGrzegorz Bernacki for (dt_child = OF_child(dt_node), i = 0; dt_child != 0; 744ffd4dfeSGrzegorz Bernacki dt_child = OF_peer(dt_child)) { 754ffd4dfeSGrzegorz Bernacki 764ffd4dfeSGrzegorz Bernacki if (i == FLASH_SLICES_MAX_NUM) { 774ffd4dfeSGrzegorz Bernacki debugf("not enough buffer for slice i=%d\n", i); 784ffd4dfeSGrzegorz Bernacki break; 794ffd4dfeSGrzegorz Bernacki } 804ffd4dfeSGrzegorz Bernacki 814ffd4dfeSGrzegorz Bernacki /* 824ffd4dfeSGrzegorz Bernacki * Retrieve start and size of the slice. 834ffd4dfeSGrzegorz Bernacki */ 844ffd4dfeSGrzegorz Bernacki if (fdt_regsize(dt_child, &base, &size) != 0) { 854ffd4dfeSGrzegorz Bernacki debugf("error during processing reg property, i=%d\n", 864ffd4dfeSGrzegorz Bernacki i); 874ffd4dfeSGrzegorz Bernacki continue; 884ffd4dfeSGrzegorz Bernacki } 894ffd4dfeSGrzegorz Bernacki 904ffd4dfeSGrzegorz Bernacki if (size == 0) { 914ffd4dfeSGrzegorz Bernacki debugf("slice i=%d with no size\n", i); 924ffd4dfeSGrzegorz Bernacki continue; 934ffd4dfeSGrzegorz Bernacki } 944ffd4dfeSGrzegorz Bernacki 954ffd4dfeSGrzegorz Bernacki /* 964ffd4dfeSGrzegorz Bernacki * Retrieve label. 974ffd4dfeSGrzegorz Bernacki */ 98217d17bcSOleksandr Tymoshenko name_len = OF_getprop_alloc(dt_child, "label", 994ffd4dfeSGrzegorz Bernacki (void **)&slice_name); 1004ffd4dfeSGrzegorz Bernacki if (name_len <= 0) { 1014ffd4dfeSGrzegorz Bernacki /* Use node name if no label defined */ 1024874af73SMarius Strobl name_len = OF_getprop_alloc(dt_child, "name", 103217d17bcSOleksandr Tymoshenko (void **)&slice_name); 1044ffd4dfeSGrzegorz Bernacki if (name_len <= 0) { 1054ffd4dfeSGrzegorz Bernacki debugf("slice i=%d with no name\n", i); 1064ffd4dfeSGrzegorz Bernacki slice_name = NULL; 1074ffd4dfeSGrzegorz Bernacki } 1084ffd4dfeSGrzegorz Bernacki } 1094ffd4dfeSGrzegorz Bernacki 1104ffd4dfeSGrzegorz Bernacki /* 1114ffd4dfeSGrzegorz Bernacki * Fill slice entry data. 1124ffd4dfeSGrzegorz Bernacki */ 1134ffd4dfeSGrzegorz Bernacki slices[i].base = base; 1144ffd4dfeSGrzegorz Bernacki slices[i].size = size; 1154ffd4dfeSGrzegorz Bernacki slices[i].label = slice_name; 1164ffd4dfeSGrzegorz Bernacki i++; 1174ffd4dfeSGrzegorz Bernacki } 1184ffd4dfeSGrzegorz Bernacki 1194ffd4dfeSGrzegorz Bernacki *slices_num = i; 1204ffd4dfeSGrzegorz Bernacki return (0); 1214ffd4dfeSGrzegorz Bernacki } 1224874af73SMarius Strobl 1234874af73SMarius Strobl static void 1244874af73SMarius Strobl fdt_slicer_init(void) 1254874af73SMarius Strobl { 1264874af73SMarius Strobl 1274874af73SMarius Strobl flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_NAND, 1284874af73SMarius Strobl FALSE); 1294874af73SMarius Strobl flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_CFI, 1304874af73SMarius Strobl FALSE); 1314874af73SMarius Strobl flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_SPI, 1324874af73SMarius Strobl FALSE); 1334874af73SMarius Strobl } 1344874af73SMarius Strobl 135*4e462178SIan Lepore static void 136*4e462178SIan Lepore fdt_slicer_cleanup(void) 137*4e462178SIan Lepore { 138*4e462178SIan Lepore 139*4e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_NAND, true); 140*4e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_CFI, true); 141*4e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_SPI, true); 142*4e462178SIan Lepore } 143*4e462178SIan Lepore 1444874af73SMarius Strobl /* 1454874af73SMarius Strobl * Must be initialized after GEOM classes (SI_SUB_DRIVERS/SI_ORDER_FIRST), 1464874af73SMarius Strobl * i. e. after g_init() is called, due to the use of the GEOM topology_lock 1474874af73SMarius Strobl * in flash_register_slicer(). However, must be before SI_SUB_CONFIGURE. 1484874af73SMarius Strobl */ 149*4e462178SIan Lepore SYSINIT(fdt_slicer, SI_SUB_DRIVERS, SI_ORDER_SECOND, fdt_slicer_init, NULL); 150*4e462178SIan Lepore SYSUNINIT(fdt_slicer, SI_SUB_DRIVERS, SI_ORDER_SECOND, fdt_slicer_cleanup, NULL); 151*4e462178SIan Lepore 152*4e462178SIan Lepore static int 153*4e462178SIan Lepore mod_handler(module_t mod, int type, void *data) 154*4e462178SIan Lepore { 155*4e462178SIan Lepore 156*4e462178SIan Lepore /* 157*4e462178SIan Lepore * Nothing to do here: the SYSINIT/SYSUNINIT defined above run 158*4e462178SIan Lepore * automatically at module load/unload time. 159*4e462178SIan Lepore */ 160*4e462178SIan Lepore return (0); 161*4e462178SIan Lepore } 162*4e462178SIan Lepore 163*4e462178SIan Lepore static moduledata_t fdt_slicer_mod = { 164*4e462178SIan Lepore "fdt_slicer", mod_handler, NULL 165*4e462178SIan Lepore }; 166*4e462178SIan Lepore 167*4e462178SIan Lepore DECLARE_MODULE(fdt_slicer, fdt_slicer_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 168*4e462178SIan Lepore MODULE_VERSION(fdt_slicer, 1); 169