162e8ccc3SEmmanuel Vadot /*-
262e8ccc3SEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause
362e8ccc3SEmmanuel Vadot *
462e8ccc3SEmmanuel Vadot * Copyright (c) 2017 Kyle Evans <kevans@FreeBSD.org>
562e8ccc3SEmmanuel Vadot *
662e8ccc3SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
762e8ccc3SEmmanuel Vadot * modification, are permitted provided that the following conditions
862e8ccc3SEmmanuel Vadot * are met:
962e8ccc3SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
1062e8ccc3SEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
1162e8ccc3SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
1262e8ccc3SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
1362e8ccc3SEmmanuel Vadot * documentation and/or other materials provided with the distribution.
1462e8ccc3SEmmanuel Vadot *
1562e8ccc3SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1662e8ccc3SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1762e8ccc3SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1862e8ccc3SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1962e8ccc3SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2062e8ccc3SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2162e8ccc3SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2262e8ccc3SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2362e8ccc3SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2462e8ccc3SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2562e8ccc3SEmmanuel Vadot * SUCH DAMAGE.
2662e8ccc3SEmmanuel Vadot */
2762e8ccc3SEmmanuel Vadot
2862e8ccc3SEmmanuel Vadot /*
2962e8ccc3SEmmanuel Vadot * This is a generic syscon driver, whose purpose is to provide access to
3062e8ccc3SEmmanuel Vadot * various unrelated bits packed in a single register space. It is usually used
3162e8ccc3SEmmanuel Vadot * as a fallback to more specific driver, but works well enough for simple
3262e8ccc3SEmmanuel Vadot * access.
3362e8ccc3SEmmanuel Vadot */
3462e8ccc3SEmmanuel Vadot
3562e8ccc3SEmmanuel Vadot #include <sys/cdefs.h>
3662e8ccc3SEmmanuel Vadot #include "opt_platform.h"
3762e8ccc3SEmmanuel Vadot
3862e8ccc3SEmmanuel Vadot #include <sys/param.h>
3962e8ccc3SEmmanuel Vadot #include <sys/systm.h>
4062e8ccc3SEmmanuel Vadot #include <sys/bus.h>
4162e8ccc3SEmmanuel Vadot #include <sys/kernel.h>
4262e8ccc3SEmmanuel Vadot #include <sys/kobj.h>
4362e8ccc3SEmmanuel Vadot #include <sys/lock.h>
4462e8ccc3SEmmanuel Vadot #include <sys/malloc.h>
4562e8ccc3SEmmanuel Vadot #include <sys/module.h>
4662e8ccc3SEmmanuel Vadot #include <sys/rman.h>
4762e8ccc3SEmmanuel Vadot #include <sys/sx.h>
4862e8ccc3SEmmanuel Vadot #include <sys/queue.h>
4962e8ccc3SEmmanuel Vadot
5062e8ccc3SEmmanuel Vadot #include <machine/bus.h>
5162e8ccc3SEmmanuel Vadot
5262e8ccc3SEmmanuel Vadot #ifdef FDT
5362e8ccc3SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
5462e8ccc3SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
5562e8ccc3SEmmanuel Vadot #endif
5662e8ccc3SEmmanuel Vadot
5762e8ccc3SEmmanuel Vadot #include "syscon_if.h"
5862e8ccc3SEmmanuel Vadot #include "syscon.h"
5962e8ccc3SEmmanuel Vadot
6062e8ccc3SEmmanuel Vadot /*
6162e8ccc3SEmmanuel Vadot * Syscon interface details
6262e8ccc3SEmmanuel Vadot */
6362e8ccc3SEmmanuel Vadot typedef TAILQ_HEAD(syscon_list, syscon) syscon_list_t;
6462e8ccc3SEmmanuel Vadot
6562e8ccc3SEmmanuel Vadot /*
6662e8ccc3SEmmanuel Vadot * Declarations
6762e8ccc3SEmmanuel Vadot */
6862e8ccc3SEmmanuel Vadot static int syscon_method_init(struct syscon *syscon);
6962e8ccc3SEmmanuel Vadot static int syscon_method_uninit(struct syscon *syscon);
7062e8ccc3SEmmanuel Vadot static uint32_t syscon_method_read_4(struct syscon *syscon, bus_size_t offset);
7162e8ccc3SEmmanuel Vadot static int syscon_method_write_4(struct syscon *syscon, bus_size_t offset,
7262e8ccc3SEmmanuel Vadot uint32_t val);
7362e8ccc3SEmmanuel Vadot static int syscon_method_modify_4(struct syscon *syscon, bus_size_t offset,
7462e8ccc3SEmmanuel Vadot uint32_t clear_bits, uint32_t set_bits);
7562e8ccc3SEmmanuel Vadot
7662e8ccc3SEmmanuel Vadot
7762e8ccc3SEmmanuel Vadot MALLOC_DEFINE(M_SYSCON, "syscon", "Syscon driver");
7862e8ccc3SEmmanuel Vadot
7962e8ccc3SEmmanuel Vadot static syscon_list_t syscon_list = TAILQ_HEAD_INITIALIZER(syscon_list);
8062e8ccc3SEmmanuel Vadot static struct sx syscon_topo_lock;
8162e8ccc3SEmmanuel Vadot SX_SYSINIT(syscon_topology, &syscon_topo_lock, "Syscon topology lock");
8262e8ccc3SEmmanuel Vadot
8362e8ccc3SEmmanuel Vadot /*
8462e8ccc3SEmmanuel Vadot * Syscon methods.
8562e8ccc3SEmmanuel Vadot */
8662e8ccc3SEmmanuel Vadot static syscon_method_t syscon_methods[] = {
8762e8ccc3SEmmanuel Vadot SYSCONMETHOD(syscon_init, syscon_method_init),
8862e8ccc3SEmmanuel Vadot SYSCONMETHOD(syscon_uninit, syscon_method_uninit),
8962e8ccc3SEmmanuel Vadot SYSCONMETHOD(syscon_read_4, syscon_method_read_4),
9062e8ccc3SEmmanuel Vadot SYSCONMETHOD(syscon_write_4, syscon_method_write_4),
9162e8ccc3SEmmanuel Vadot SYSCONMETHOD(syscon_modify_4, syscon_method_modify_4),
9262e8ccc3SEmmanuel Vadot
9362e8ccc3SEmmanuel Vadot SYSCONMETHOD_END
9462e8ccc3SEmmanuel Vadot };
9562e8ccc3SEmmanuel Vadot DEFINE_CLASS_0(syscon, syscon_class, syscon_methods, 0);
9662e8ccc3SEmmanuel Vadot
9762e8ccc3SEmmanuel Vadot #define SYSCON_TOPO_SLOCK() sx_slock(&syscon_topo_lock)
9862e8ccc3SEmmanuel Vadot #define SYSCON_TOPO_XLOCK() sx_xlock(&syscon_topo_lock)
9962e8ccc3SEmmanuel Vadot #define SYSCON_TOPO_UNLOCK() sx_unlock(&syscon_topo_lock)
10062e8ccc3SEmmanuel Vadot #define SYSCON_TOPO_ASSERT() sx_assert(&syscon_topo_lock, SA_LOCKED)
10162e8ccc3SEmmanuel Vadot #define SYSCON_TOPO_XASSERT() sx_assert(&syscon_topo_lock, SA_XLOCKED)
10262e8ccc3SEmmanuel Vadot
10362e8ccc3SEmmanuel Vadot /*
10462e8ccc3SEmmanuel Vadot * Default syscon methods for base class.
10562e8ccc3SEmmanuel Vadot */
10662e8ccc3SEmmanuel Vadot static int
syscon_method_init(struct syscon * syscon)10762e8ccc3SEmmanuel Vadot syscon_method_init(struct syscon *syscon)
10862e8ccc3SEmmanuel Vadot {
10962e8ccc3SEmmanuel Vadot
11062e8ccc3SEmmanuel Vadot return (0);
11162e8ccc3SEmmanuel Vadot };
11262e8ccc3SEmmanuel Vadot
11362e8ccc3SEmmanuel Vadot static int
syscon_method_uninit(struct syscon * syscon)11462e8ccc3SEmmanuel Vadot syscon_method_uninit(struct syscon *syscon)
11562e8ccc3SEmmanuel Vadot {
11662e8ccc3SEmmanuel Vadot
11762e8ccc3SEmmanuel Vadot return (0);
11862e8ccc3SEmmanuel Vadot };
11962e8ccc3SEmmanuel Vadot
12062e8ccc3SEmmanuel Vadot void *
syscon_get_softc(struct syscon * syscon)12162e8ccc3SEmmanuel Vadot syscon_get_softc(struct syscon *syscon)
12262e8ccc3SEmmanuel Vadot {
12362e8ccc3SEmmanuel Vadot
12462e8ccc3SEmmanuel Vadot return (syscon->softc);
12562e8ccc3SEmmanuel Vadot };
12662e8ccc3SEmmanuel Vadot
12762e8ccc3SEmmanuel Vadot static uint32_t
syscon_method_read_4(struct syscon * syscon,bus_size_t offset)12862e8ccc3SEmmanuel Vadot syscon_method_read_4(struct syscon *syscon, bus_size_t offset)
12962e8ccc3SEmmanuel Vadot {
13062e8ccc3SEmmanuel Vadot uint32_t val;
13162e8ccc3SEmmanuel Vadot
13262e8ccc3SEmmanuel Vadot SYSCON_DEVICE_LOCK(syscon->pdev);
13362e8ccc3SEmmanuel Vadot val = SYSCON_UNLOCKED_READ_4(syscon, offset);
13462e8ccc3SEmmanuel Vadot SYSCON_DEVICE_UNLOCK(syscon->pdev);
13562e8ccc3SEmmanuel Vadot return(val);
13662e8ccc3SEmmanuel Vadot }
13762e8ccc3SEmmanuel Vadot
13862e8ccc3SEmmanuel Vadot static int
syscon_method_write_4(struct syscon * syscon,bus_size_t offset,uint32_t val)13962e8ccc3SEmmanuel Vadot syscon_method_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
14062e8ccc3SEmmanuel Vadot {
14162e8ccc3SEmmanuel Vadot int rv;
14262e8ccc3SEmmanuel Vadot
14362e8ccc3SEmmanuel Vadot SYSCON_DEVICE_LOCK(syscon->pdev);
14462e8ccc3SEmmanuel Vadot rv = SYSCON_UNLOCKED_WRITE_4(syscon, offset, val);
14562e8ccc3SEmmanuel Vadot SYSCON_DEVICE_UNLOCK(syscon->pdev);
14662e8ccc3SEmmanuel Vadot return(rv);
14762e8ccc3SEmmanuel Vadot }
14862e8ccc3SEmmanuel Vadot
14962e8ccc3SEmmanuel Vadot static int
syscon_method_modify_4(struct syscon * syscon,bus_size_t offset,uint32_t clear_bits,uint32_t set_bits)15062e8ccc3SEmmanuel Vadot syscon_method_modify_4(struct syscon *syscon, bus_size_t offset,
15162e8ccc3SEmmanuel Vadot uint32_t clear_bits, uint32_t set_bits)
15262e8ccc3SEmmanuel Vadot {
15362e8ccc3SEmmanuel Vadot int rv;
15462e8ccc3SEmmanuel Vadot
15562e8ccc3SEmmanuel Vadot SYSCON_DEVICE_LOCK(syscon->pdev);
15662e8ccc3SEmmanuel Vadot rv = SYSCON_UNLOCKED_MODIFY_4(syscon, offset, clear_bits, set_bits);
15762e8ccc3SEmmanuel Vadot SYSCON_DEVICE_UNLOCK(syscon->pdev);
15862e8ccc3SEmmanuel Vadot return(rv);
15962e8ccc3SEmmanuel Vadot }
16062e8ccc3SEmmanuel Vadot /*
16162e8ccc3SEmmanuel Vadot * Create and initialize syscon object, but do not register it.
16262e8ccc3SEmmanuel Vadot */
16362e8ccc3SEmmanuel Vadot struct syscon *
syscon_create(device_t pdev,syscon_class_t syscon_class)16462e8ccc3SEmmanuel Vadot syscon_create(device_t pdev, syscon_class_t syscon_class)
16562e8ccc3SEmmanuel Vadot {
16662e8ccc3SEmmanuel Vadot struct syscon *syscon;
16762e8ccc3SEmmanuel Vadot
16862e8ccc3SEmmanuel Vadot /* Create object and initialize it. */
16962e8ccc3SEmmanuel Vadot syscon = malloc(sizeof(struct syscon), M_SYSCON,
17062e8ccc3SEmmanuel Vadot M_WAITOK | M_ZERO);
17162e8ccc3SEmmanuel Vadot kobj_init((kobj_t)syscon, (kobj_class_t)syscon_class);
17262e8ccc3SEmmanuel Vadot
17362e8ccc3SEmmanuel Vadot /* Allocate softc if required. */
17462e8ccc3SEmmanuel Vadot if (syscon_class->size > 0)
17562e8ccc3SEmmanuel Vadot syscon->softc = malloc(syscon_class->size, M_SYSCON,
17662e8ccc3SEmmanuel Vadot M_WAITOK | M_ZERO);
17762e8ccc3SEmmanuel Vadot
17862e8ccc3SEmmanuel Vadot /* Rest of init. */
17962e8ccc3SEmmanuel Vadot syscon->pdev = pdev;
18062e8ccc3SEmmanuel Vadot return (syscon);
18162e8ccc3SEmmanuel Vadot }
18262e8ccc3SEmmanuel Vadot
18362e8ccc3SEmmanuel Vadot /* Register syscon object. */
18462e8ccc3SEmmanuel Vadot struct syscon *
syscon_register(struct syscon * syscon)18562e8ccc3SEmmanuel Vadot syscon_register(struct syscon *syscon)
18662e8ccc3SEmmanuel Vadot {
18762e8ccc3SEmmanuel Vadot int rv;
18862e8ccc3SEmmanuel Vadot
18962e8ccc3SEmmanuel Vadot #ifdef FDT
19062e8ccc3SEmmanuel Vadot if (syscon->ofw_node <= 0)
19162e8ccc3SEmmanuel Vadot syscon->ofw_node = ofw_bus_get_node(syscon->pdev);
19262e8ccc3SEmmanuel Vadot if (syscon->ofw_node <= 0)
19362e8ccc3SEmmanuel Vadot return (NULL);
19462e8ccc3SEmmanuel Vadot #endif
19562e8ccc3SEmmanuel Vadot
19662e8ccc3SEmmanuel Vadot rv = SYSCON_INIT(syscon);
19762e8ccc3SEmmanuel Vadot if (rv != 0) {
19862e8ccc3SEmmanuel Vadot printf("SYSCON_INIT failed: %d\n", rv);
19962e8ccc3SEmmanuel Vadot return (NULL);
20062e8ccc3SEmmanuel Vadot }
20162e8ccc3SEmmanuel Vadot
20262e8ccc3SEmmanuel Vadot #ifdef FDT
20362e8ccc3SEmmanuel Vadot OF_device_register_xref(OF_xref_from_node(syscon->ofw_node),
20462e8ccc3SEmmanuel Vadot syscon->pdev);
20562e8ccc3SEmmanuel Vadot #endif
20662e8ccc3SEmmanuel Vadot SYSCON_TOPO_XLOCK();
20762e8ccc3SEmmanuel Vadot TAILQ_INSERT_TAIL(&syscon_list, syscon, syscon_link);
20862e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
20962e8ccc3SEmmanuel Vadot return (syscon);
21062e8ccc3SEmmanuel Vadot }
21162e8ccc3SEmmanuel Vadot
21262e8ccc3SEmmanuel Vadot int
syscon_unregister(struct syscon * syscon)21362e8ccc3SEmmanuel Vadot syscon_unregister(struct syscon *syscon)
21462e8ccc3SEmmanuel Vadot {
21562e8ccc3SEmmanuel Vadot
21662e8ccc3SEmmanuel Vadot SYSCON_TOPO_XLOCK();
21762e8ccc3SEmmanuel Vadot TAILQ_REMOVE(&syscon_list, syscon, syscon_link);
21862e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
21962e8ccc3SEmmanuel Vadot #ifdef FDT
22062e8ccc3SEmmanuel Vadot OF_device_register_xref(OF_xref_from_node(syscon->ofw_node), NULL);
22162e8ccc3SEmmanuel Vadot #endif
22262e8ccc3SEmmanuel Vadot return (SYSCON_UNINIT(syscon));
22362e8ccc3SEmmanuel Vadot }
22462e8ccc3SEmmanuel Vadot
22562e8ccc3SEmmanuel Vadot /**
22662e8ccc3SEmmanuel Vadot * Provider methods
22762e8ccc3SEmmanuel Vadot */
22862e8ccc3SEmmanuel Vadot #ifdef FDT
22962e8ccc3SEmmanuel Vadot static struct syscon *
syscon_find_by_ofw_node(phandle_t node)23062e8ccc3SEmmanuel Vadot syscon_find_by_ofw_node(phandle_t node)
23162e8ccc3SEmmanuel Vadot {
23262e8ccc3SEmmanuel Vadot struct syscon *entry;
23362e8ccc3SEmmanuel Vadot
23462e8ccc3SEmmanuel Vadot SYSCON_TOPO_ASSERT();
23562e8ccc3SEmmanuel Vadot
23662e8ccc3SEmmanuel Vadot TAILQ_FOREACH(entry, &syscon_list, syscon_link) {
23762e8ccc3SEmmanuel Vadot if (entry->ofw_node == node)
23862e8ccc3SEmmanuel Vadot return (entry);
23962e8ccc3SEmmanuel Vadot }
24062e8ccc3SEmmanuel Vadot
24162e8ccc3SEmmanuel Vadot return (NULL);
24262e8ccc3SEmmanuel Vadot }
24362e8ccc3SEmmanuel Vadot
24462e8ccc3SEmmanuel Vadot struct syscon *
syscon_create_ofw_node(device_t pdev,syscon_class_t syscon_class,phandle_t node)24562e8ccc3SEmmanuel Vadot syscon_create_ofw_node(device_t pdev, syscon_class_t syscon_class,
24662e8ccc3SEmmanuel Vadot phandle_t node)
24762e8ccc3SEmmanuel Vadot {
24862e8ccc3SEmmanuel Vadot struct syscon *syscon;
24962e8ccc3SEmmanuel Vadot
25062e8ccc3SEmmanuel Vadot syscon = syscon_create(pdev, syscon_class);
25162e8ccc3SEmmanuel Vadot if (syscon == NULL)
25262e8ccc3SEmmanuel Vadot return (NULL);
25362e8ccc3SEmmanuel Vadot syscon->ofw_node = node;
25462e8ccc3SEmmanuel Vadot if (syscon_register(syscon) == NULL)
25562e8ccc3SEmmanuel Vadot return (NULL);
25662e8ccc3SEmmanuel Vadot return (syscon);
25762e8ccc3SEmmanuel Vadot }
25862e8ccc3SEmmanuel Vadot
25962e8ccc3SEmmanuel Vadot phandle_t
syscon_get_ofw_node(struct syscon * syscon)26062e8ccc3SEmmanuel Vadot syscon_get_ofw_node(struct syscon *syscon)
26162e8ccc3SEmmanuel Vadot {
26262e8ccc3SEmmanuel Vadot
26362e8ccc3SEmmanuel Vadot return (syscon->ofw_node);
26462e8ccc3SEmmanuel Vadot }
26562e8ccc3SEmmanuel Vadot
26662e8ccc3SEmmanuel Vadot int
syscon_get_by_ofw_node(device_t cdev,phandle_t node,struct syscon ** syscon)26762e8ccc3SEmmanuel Vadot syscon_get_by_ofw_node(device_t cdev, phandle_t node, struct syscon **syscon)
26862e8ccc3SEmmanuel Vadot {
26962e8ccc3SEmmanuel Vadot
27062e8ccc3SEmmanuel Vadot SYSCON_TOPO_SLOCK();
27162e8ccc3SEmmanuel Vadot *syscon = syscon_find_by_ofw_node(node);
27262e8ccc3SEmmanuel Vadot if (*syscon == NULL) {
27362e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
27462e8ccc3SEmmanuel Vadot device_printf(cdev, "Failed to find syscon node\n");
27562e8ccc3SEmmanuel Vadot return (ENODEV);
27662e8ccc3SEmmanuel Vadot }
27762e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
27862e8ccc3SEmmanuel Vadot return (0);
27962e8ccc3SEmmanuel Vadot }
28062e8ccc3SEmmanuel Vadot
28162e8ccc3SEmmanuel Vadot int
syscon_get_by_ofw_property(device_t cdev,phandle_t cnode,char * name,struct syscon ** syscon)28262e8ccc3SEmmanuel Vadot syscon_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name,
28362e8ccc3SEmmanuel Vadot struct syscon **syscon)
28462e8ccc3SEmmanuel Vadot {
28562e8ccc3SEmmanuel Vadot pcell_t *cells;
28662e8ccc3SEmmanuel Vadot int ncells;
28762e8ccc3SEmmanuel Vadot
28862e8ccc3SEmmanuel Vadot if (cnode <= 0)
28962e8ccc3SEmmanuel Vadot cnode = ofw_bus_get_node(cdev);
29062e8ccc3SEmmanuel Vadot if (cnode <= 0) {
29162e8ccc3SEmmanuel Vadot device_printf(cdev,
29262e8ccc3SEmmanuel Vadot "%s called on not ofw based device\n", __func__);
29362e8ccc3SEmmanuel Vadot return (ENXIO);
29462e8ccc3SEmmanuel Vadot }
29562e8ccc3SEmmanuel Vadot ncells = OF_getencprop_alloc_multi(cnode, name, sizeof(pcell_t),
29662e8ccc3SEmmanuel Vadot (void **)&cells);
29762e8ccc3SEmmanuel Vadot if (ncells < 1)
29862e8ccc3SEmmanuel Vadot return (ENOENT);
29962e8ccc3SEmmanuel Vadot
30062e8ccc3SEmmanuel Vadot /* Translate to syscon node. */
30162e8ccc3SEmmanuel Vadot SYSCON_TOPO_SLOCK();
30262e8ccc3SEmmanuel Vadot *syscon = syscon_find_by_ofw_node(OF_node_from_xref(cells[0]));
30362e8ccc3SEmmanuel Vadot if (*syscon == NULL) {
30462e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
30562e8ccc3SEmmanuel Vadot device_printf(cdev, "Failed to find syscon node\n");
30662e8ccc3SEmmanuel Vadot OF_prop_free(cells);
30762e8ccc3SEmmanuel Vadot return (ENODEV);
30862e8ccc3SEmmanuel Vadot }
30962e8ccc3SEmmanuel Vadot SYSCON_TOPO_UNLOCK();
31062e8ccc3SEmmanuel Vadot OF_prop_free(cells);
31162e8ccc3SEmmanuel Vadot return (0);
31262e8ccc3SEmmanuel Vadot }
31362e8ccc3SEmmanuel Vadot #endif
314