14ffd4dfeSGrzegorz Bernacki /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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/param.h> 304ffd4dfeSGrzegorz Bernacki #include <sys/systm.h> 314ffd4dfeSGrzegorz Bernacki #include <sys/kernel.h> 324e462178SIan Lepore #include <sys/module.h> 334ffd4dfeSGrzegorz Bernacki #include <sys/slicer.h> 344ffd4dfeSGrzegorz Bernacki 354ffd4dfeSGrzegorz Bernacki #include <dev/fdt/fdt_common.h> 364874af73SMarius Strobl #include <dev/ofw/ofw_bus.h> 374874af73SMarius Strobl #include <dev/ofw/openfirm.h> 384ffd4dfeSGrzegorz Bernacki 394ffd4dfeSGrzegorz Bernacki #ifdef DEBUG 404ffd4dfeSGrzegorz Bernacki #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ 414ffd4dfeSGrzegorz Bernacki printf(fmt,##args); } while (0) 424ffd4dfeSGrzegorz Bernacki #else 434ffd4dfeSGrzegorz Bernacki #define debugf(fmt, args...) 444ffd4dfeSGrzegorz Bernacki #endif 454ffd4dfeSGrzegorz Bernacki 46db58d718SIan Lepore static int fill_slices(device_t dev, const char *provider, 474874af73SMarius Strobl struct flash_slice *slices, int *slices_num); 484874af73SMarius Strobl static void fdt_slicer_init(void); 494874af73SMarius Strobl 504874af73SMarius Strobl static int 51a6bcabcdSIan Lepore fill_slices_from_node(phandle_t node, struct flash_slice *slices, int *count) 524ffd4dfeSGrzegorz Bernacki { 53a6bcabcdSIan Lepore char *label; 54a6bcabcdSIan Lepore phandle_t child; 554ffd4dfeSGrzegorz Bernacki u_long base, size; 56a6bcabcdSIan Lepore int flags, i; 57db58d718SIan Lepore ssize_t nmlen; 584ffd4dfeSGrzegorz Bernacki 59db58d718SIan Lepore i = 0; 60db58d718SIan Lepore for (child = OF_child(node); child != 0; child = OF_peer(child)) { 61a6bcabcdSIan Lepore flags = FLASH_SLICES_FLAG_NONE; 624ffd4dfeSGrzegorz Bernacki 6385f55a2aSIan Lepore /* Nodes with a compatible property are not slices. */ 6485f55a2aSIan Lepore if (OF_hasprop(child, "compatible")) 6585f55a2aSIan Lepore continue; 6685f55a2aSIan Lepore 674ffd4dfeSGrzegorz Bernacki if (i == FLASH_SLICES_MAX_NUM) { 684ffd4dfeSGrzegorz Bernacki debugf("not enough buffer for slice i=%d\n", i); 694ffd4dfeSGrzegorz Bernacki break; 704ffd4dfeSGrzegorz Bernacki } 714ffd4dfeSGrzegorz Bernacki 72db58d718SIan Lepore /* Retrieve start and size of the slice. */ 73db58d718SIan Lepore if (fdt_regsize(child, &base, &size) != 0) { 744ffd4dfeSGrzegorz Bernacki debugf("error during processing reg property, i=%d\n", 754ffd4dfeSGrzegorz Bernacki i); 764ffd4dfeSGrzegorz Bernacki continue; 774ffd4dfeSGrzegorz Bernacki } 784ffd4dfeSGrzegorz Bernacki 794ffd4dfeSGrzegorz Bernacki if (size == 0) { 804ffd4dfeSGrzegorz Bernacki debugf("slice i=%d with no size\n", i); 814ffd4dfeSGrzegorz Bernacki continue; 824ffd4dfeSGrzegorz Bernacki } 834ffd4dfeSGrzegorz Bernacki 84db58d718SIan Lepore /* Retrieve label. */ 85a6bcabcdSIan Lepore nmlen = OF_getprop_alloc(child, "label", (void **)&label); 86db58d718SIan Lepore if (nmlen <= 0) { 874ffd4dfeSGrzegorz Bernacki /* Use node name if no label defined */ 88a6bcabcdSIan Lepore nmlen = OF_getprop_alloc(child, "name", (void **)&label); 89db58d718SIan Lepore if (nmlen <= 0) { 904ffd4dfeSGrzegorz Bernacki debugf("slice i=%d with no name\n", i); 91a6bcabcdSIan Lepore label = NULL; 924ffd4dfeSGrzegorz Bernacki } 934ffd4dfeSGrzegorz Bernacki } 944ffd4dfeSGrzegorz Bernacki 95a6bcabcdSIan Lepore if (OF_hasprop(child, "read-only")) 96a6bcabcdSIan Lepore flags |= FLASH_SLICES_FLAG_RO; 97a6bcabcdSIan Lepore 98db58d718SIan Lepore /* Fill slice entry data. */ 994ffd4dfeSGrzegorz Bernacki slices[i].base = base; 1004ffd4dfeSGrzegorz Bernacki slices[i].size = size; 101a6bcabcdSIan Lepore slices[i].label = label; 102a6bcabcdSIan Lepore slices[i].flags = flags; 1034ffd4dfeSGrzegorz Bernacki i++; 1044ffd4dfeSGrzegorz Bernacki } 1054ffd4dfeSGrzegorz Bernacki 106a6bcabcdSIan Lepore *count = i; 1074ffd4dfeSGrzegorz Bernacki return (0); 1084ffd4dfeSGrzegorz Bernacki } 1094874af73SMarius Strobl 110a6bcabcdSIan Lepore static int 111a6bcabcdSIan Lepore fill_slices(device_t dev, const char *provider __unused, 112a6bcabcdSIan Lepore struct flash_slice *slices, int *slices_num) 113a6bcabcdSIan Lepore { 114a6bcabcdSIan Lepore phandle_t child, node; 115a6bcabcdSIan Lepore 116a6bcabcdSIan Lepore /* 117a6bcabcdSIan Lepore * We assume the caller provides buffer for FLASH_SLICES_MAX_NUM 118a6bcabcdSIan Lepore * flash_slice structures. 119a6bcabcdSIan Lepore */ 120a6bcabcdSIan Lepore if (slices == NULL) { 121a6bcabcdSIan Lepore *slices_num = 0; 122a6bcabcdSIan Lepore return (ENOMEM); 123a6bcabcdSIan Lepore } 124a6bcabcdSIan Lepore 125a6bcabcdSIan Lepore node = ofw_bus_get_node(dev); 126a6bcabcdSIan Lepore 127a6bcabcdSIan Lepore /* 128a6bcabcdSIan Lepore * If there is a child node whose compatible is "fixed-partitions" then 129a6bcabcdSIan Lepore * we have new-style data where all partitions are the children of that 130a6bcabcdSIan Lepore * node. Otherwise we have old-style data where all the children of the 131a6bcabcdSIan Lepore * device node are the partitions. 132a6bcabcdSIan Lepore */ 133a6bcabcdSIan Lepore child = fdt_find_compatible(node, "fixed-partitions", false); 134a6bcabcdSIan Lepore if (child == 0) 135a6bcabcdSIan Lepore return fill_slices_from_node(node, slices, slices_num); 136a6bcabcdSIan Lepore else 137a6bcabcdSIan Lepore return fill_slices_from_node(child, slices, slices_num); 138a6bcabcdSIan Lepore } 139a6bcabcdSIan Lepore 1404874af73SMarius Strobl static void 1414874af73SMarius Strobl fdt_slicer_init(void) 1424874af73SMarius Strobl { 1434874af73SMarius Strobl 144db58d718SIan Lepore flash_register_slicer(fill_slices, FLASH_SLICES_TYPE_NAND, false); 145db58d718SIan Lepore flash_register_slicer(fill_slices, FLASH_SLICES_TYPE_CFI, false); 146db58d718SIan Lepore flash_register_slicer(fill_slices, FLASH_SLICES_TYPE_SPI, false); 1474874af73SMarius Strobl } 1484874af73SMarius Strobl 1494e462178SIan Lepore static void 1504e462178SIan Lepore fdt_slicer_cleanup(void) 1514e462178SIan Lepore { 1524e462178SIan Lepore 1534e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_NAND, true); 1544e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_CFI, true); 1554e462178SIan Lepore flash_register_slicer(NULL, FLASH_SLICES_TYPE_SPI, true); 1564e462178SIan Lepore } 1574e462178SIan Lepore 1584874af73SMarius Strobl /* 1590ddc94d6SKyle Evans * Must be initialized after GEOM classes (SI_SUB_DRIVERS/SI_ORDER_SECOND), 1604874af73SMarius Strobl * i. e. after g_init() is called, due to the use of the GEOM topology_lock 1614874af73SMarius Strobl * in flash_register_slicer(). However, must be before SI_SUB_CONFIGURE. 1624874af73SMarius Strobl */ 1630ddc94d6SKyle Evans SYSINIT(fdt_slicer, SI_SUB_DRIVERS, SI_ORDER_THIRD, fdt_slicer_init, NULL); 1640ddc94d6SKyle Evans SYSUNINIT(fdt_slicer, SI_SUB_DRIVERS, SI_ORDER_THIRD, fdt_slicer_cleanup, NULL); 1654e462178SIan Lepore 1664e462178SIan Lepore static int 1674e462178SIan Lepore mod_handler(module_t mod, int type, void *data) 1684e462178SIan Lepore { 1694e462178SIan Lepore 1704e462178SIan Lepore /* 1714e462178SIan Lepore * Nothing to do here: the SYSINIT/SYSUNINIT defined above run 1724e462178SIan Lepore * automatically at module load/unload time. 1734e462178SIan Lepore */ 1744e462178SIan Lepore return (0); 1754e462178SIan Lepore } 1764e462178SIan Lepore 1774e462178SIan Lepore static moduledata_t fdt_slicer_mod = { 1784e462178SIan Lepore "fdt_slicer", mod_handler, NULL 1794e462178SIan Lepore }; 1804e462178SIan Lepore 1810ddc94d6SKyle Evans DECLARE_MODULE(fdt_slicer, fdt_slicer_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 182*2352336aSMark Johnston MODULE_DEPEND(fdt_slicer, geom_flashmap, 0, 0, 0); 1834e462178SIan Lepore MODULE_VERSION(fdt_slicer, 1); 184