1 /* $OpenBSD: ofw_power.c,v 1.1 2018/05/02 15:16:31 patrick Exp $ */ 2 /* 3 * Copyright (c) 2016 Mark Kettenis 4 * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/systm.h> 21 #include <sys/malloc.h> 22 23 #include <dev/ofw/openfirm.h> 24 #include <dev/ofw/ofw_power.h> 25 26 LIST_HEAD(, power_domain_device) power_domain_devices = 27 LIST_HEAD_INITIALIZER(power_domain_devices); 28 29 void 30 power_domain_register(struct power_domain_device *pd) 31 { 32 pd->pd_cells = OF_getpropint(pd->pd_node, "#power-domain-cells", 0); 33 pd->pd_phandle = OF_getpropint(pd->pd_node, "phandle", 0); 34 if (pd->pd_phandle == 0) 35 return; 36 37 LIST_INSERT_HEAD(&power_domain_devices, pd, pd_list); 38 } 39 40 void 41 power_domain_enable_cells(uint32_t *cells, int on) 42 { 43 struct power_domain_device *pd; 44 uint32_t phandle = cells[0]; 45 46 LIST_FOREACH(pd, &power_domain_devices, pd_list) { 47 if (pd->pd_phandle == phandle) 48 break; 49 } 50 51 if (pd && pd->pd_enable) 52 pd->pd_enable(pd->pd_cookie, &cells[1], on); 53 } 54 55 uint32_t * 56 power_domain_next_domain(uint32_t *cells) 57 { 58 uint32_t phandle = cells[0]; 59 int node, ncells; 60 61 node = OF_getnodebyphandle(phandle); 62 if (node == 0) 63 return NULL; 64 65 ncells = OF_getpropint(node, "#power-domain-cells", 0); 66 return cells + ncells + 1; 67 } 68 69 void 70 power_domain_do_enable_idx(int node, int idx, int on) 71 { 72 uint32_t *domains; 73 uint32_t *domain; 74 int len; 75 76 len = OF_getproplen(node, "power-domains"); 77 if (len <= 0) 78 return; 79 80 domains = malloc(len, M_TEMP, M_WAITOK); 81 OF_getpropintarray(node, "power-domains", domains, len); 82 83 domain = domains; 84 while (domain && domain < domains + (len / sizeof(uint32_t))) { 85 if (idx <= 0) 86 power_domain_enable_cells(domain, on); 87 if (idx == 0) 88 break; 89 domain = power_domain_next_domain(domain); 90 idx--; 91 } 92 93 free(domains, M_TEMP, len); 94 } 95 96 void 97 power_domain_enable(int node) 98 { 99 power_domain_do_enable_idx(node, 0, 1); 100 } 101 102 void 103 power_domain_disable(int node) 104 { 105 power_domain_do_enable_idx(node, 0, 0); 106 } 107