diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev --- a/sys/arm64/conf/std.dev +++ b/sys/arm64/conf/std.dev @@ -65,6 +65,7 @@ device phy device hwreset device nvmem +device powerdom device regulator device syscon diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -2714,6 +2714,8 @@ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sata/host/sathw.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" +dev/powerdom/powerdom.c optional powerdom +dev/powerdom/powerdom_if.m optional powerdom dev/ppbus/if_plip.c optional plip dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt diff --git a/sys/dev/powerdom/powerdom.h b/sys/dev/powerdom/powerdom.h new file mode 100644 --- /dev/null +++ b/sys/dev/powerdom/powerdom.h @@ -0,0 +1,70 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2016 Michal Meloun + * All rights reserved. + * + * Copyright (c) 2022 Kyle Evans + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef DEV_EXTRES_POWERDOM_POWERDOM_H +#define DEV_EXTRES_POWERDOM_POWERDOM_H + +#include "opt_platform.h" +#include +#ifdef FDT +#include +#endif + +typedef struct powerdom *powerdom_t; + +/* + * Provider interface + */ +#ifdef FDT +void powerdom_register_ofw_provider(device_t provider_dev); +void powerdom_unregister_ofw_provider(device_t provider_dev); +#endif + +/* + * Consumer interface + */ +int powerdom_get_by_id(device_t consumer_dev, device_t provider_dev, + intptr_t id, powerdom_t *pd); +void powerdom_release(powerdom_t pd); + +int powerdom_enable(powerdom_t pd); +int powerdom_disable(powerdom_t pd); +int powerdom_is_enabled(powerdom_t pd, bool *value); + +#ifdef FDT +int powerdom_get_by_ofw_name(device_t consumer_dev, phandle_t node, char *name, + powerdom_t *pd); +int powerdom_get_by_ofw_idx(device_t consumer_dev, phandle_t node, int idx, + powerdom_t *pd); +int powerdom_enable_all(device_t consumer_dev); +#endif + +#endif /* DEV_EXTRES_POWERDOM_POWERDOM_H */ diff --git a/sys/dev/powerdom/powerdom.c b/sys/dev/powerdom/powerdom.c new file mode 100644 --- /dev/null +++ b/sys/dev/powerdom/powerdom.c @@ -0,0 +1,198 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2016 Michal Meloun + * All rights reserved. + * + * Copyright (c) 2022 Kyle Evans + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_platform.h" +#include +#include +#include +#include +#include +#include + +#ifdef FDT +#include +#include +#endif + +#include + +#include "powerdom_if.h" + +struct powerdom { + device_t consumer_dev; /* consumer device */ + device_t provider_dev; /* provider device */ + intptr_t pd_id; /* power domain id */ +}; + +MALLOC_DEFINE(M_POWERDOM, "powerdom", "Power domain framework"); + +int +powerdom_enable(powerdom_t pd) +{ + + return (POWERDOM_ENABLE(pd->provider_dev, pd->pd_id)); +} + +int +powerdom_disable(powerdom_t pd) +{ + + return (POWERDOM_DISABLE(pd->provider_dev, pd->pd_id)); +} + +int +powerdom_is_enabled(powerdom_t pd, bool *value) +{ + + return (POWERDOM_IS_ENABLED(pd->provider_dev, pd->pd_id, value)); +} + +void +powerdom_release(powerdom_t pd) +{ + + free(pd, M_POWERDOM); +} + +int +powerdom_get_by_id(device_t consumer_dev, device_t provider_dev, intptr_t id, + powerdom_t *pd_out) +{ + powerdom_t pd; + + /* Create handle */ + pd = malloc(sizeof(struct powerdom), M_POWERDOM, + M_WAITOK | M_ZERO); + pd->consumer_dev = consumer_dev; + pd->provider_dev = provider_dev; + pd->pd_id = id; + *pd_out = pd; + return (0); +} + +#ifdef FDT +int +powerdom_default_ofw_map(device_t provider_dev, phandle_t xref, int ncells, + pcell_t *cells, intptr_t *id) +{ + if (ncells == 0) + *id = 1; + else if (ncells == 1) + *id = cells[0]; + else + return (ERANGE); + + return (0); +} + +int +powerdom_get_by_ofw_idx(device_t consumer_dev, phandle_t cnode, int idx, + powerdom_t *pd) +{ + phandle_t xnode; + pcell_t *cells; + device_t pddev; + int ncells, rv; + intptr_t id; + + if (cnode <= 0) + cnode = ofw_bus_get_node(consumer_dev); + if (cnode <= 0) { + device_printf(consumer_dev, + "%s called on not ofw based device\n", __func__); + return (ENXIO); + } + + rv = ofw_bus_parse_xref_list_alloc(cnode, "power-domains", + "#power-domain-cells", + idx, &xnode, &ncells, &cells); + if (rv != 0) + return (rv); + + /* Tranlate provider to device */ + pddev = OF_device_from_xref(xnode); + if (pddev == NULL) { + OF_prop_free(cells); + return (ENODEV); + } + /* Map power domain to number */ + rv = POWERDOM_MAP(pddev, xnode, ncells, cells, &id); + OF_prop_free(cells); + if (rv != 0) + return (rv); + + return (powerdom_get_by_id(consumer_dev, pddev, id, pd)); +} + +int +powerdom_get_by_ofw_name(device_t consumer_dev, phandle_t cnode, char *name, + powerdom_t *pd) +{ + int rv, idx; + + if (cnode <= 0) + cnode = ofw_bus_get_node(consumer_dev); + if (cnode <= 0) { + device_printf(consumer_dev, + "%s called on not ofw based device\n", __func__); + return (ENXIO); + } + rv = ofw_bus_find_string_index(cnode, "power-domain-names", name, &idx); + if (rv != 0) + return (rv); + return (powerdom_get_by_ofw_idx(consumer_dev, cnode, idx, pd)); +} + +void +powerdom_register_ofw_provider(device_t provider_dev) +{ + phandle_t xref, node; + + node = ofw_bus_get_node(provider_dev); + if (node <= 0) + panic("%s called on not ofw based device.\n", __func__); + + xref = OF_xref_from_node(node); + OF_device_register_xref(xref, provider_dev); +} + +void +powerdom_unregister_ofw_provider(device_t provider_dev) +{ +#ifdef notyet + phandle_t xref; + + xref = OF_xref_from_device(provider_dev); + /* https://reviews.freebsd.org/D22945 */ + OF_device_unregister_xref(xref, provider_dev); +#endif +} +#endif diff --git a/sys/dev/powerdom/powerdom_if.m b/sys/dev/powerdom/powerdom_if.m new file mode 100644 --- /dev/null +++ b/sys/dev/powerdom/powerdom_if.m @@ -0,0 +1,86 @@ +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright 2016 Michal Meloun +# All rights reserved. +# +# Copyright (c) 2022 Kyle Evans +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +#include "opt_platform.h" + +#ifdef FDT +#include +#include +#endif + +INTERFACE powerdom; + +#ifdef FDT +HEADER { +int powerdom_default_ofw_map(device_t , phandle_t, int, pcell_t *, intptr_t *); +} + +# +# map fdt property cells to power domain id +# Returns 0 on success or a standard errno value. +# +METHOD int map { + device_t provider_dev; + phandle_t xref; + int ncells; + pcell_t *cells; + intptr_t *id; +} DEFAULT powerdom_default_ofw_map; +#endif + +# +# Get actual status of given power domain. +# Returns 0 on success or a standard errno value. +# +METHOD int is_enabled { + device_t provider_dev; + intptr_t id; + bool *value; +}; + +# +# Enable the given power domain. +# Returns 0 on success or a standard errno value. +# +METHOD int enable { + device_t provider_dev; + intptr_t id; +}; + +# +# Disable the given power domain. +# Returns 0 on success or a standard errno value. +# +METHOD int disable { + device_t provider_dev; + intptr_t id; +};