ofw_regulator.c revision 1.2
1/* $OpenBSD: ofw_regulator.c,v 1.2 2017/11/18 13:48:50 kettenis Exp $ */ 2/* 3 * Copyright (c) 2016 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/types.h> 19#include <sys/systm.h> 20#include <sys/malloc.h> 21 22#include <dev/ofw/openfirm.h> 23#include <dev/ofw/ofw_gpio.h> 24#include <dev/ofw/ofw_pinctrl.h> 25#include <dev/ofw/ofw_regulator.h> 26 27LIST_HEAD(, regulator_device) regulator_devices = 28 LIST_HEAD_INITIALIZER(regulator_devices); 29 30void 31regulator_register(struct regulator_device *rd) 32{ 33 rd->rd_phandle = OF_getpropint(rd->rd_node, "phandle", 0); 34 if (rd->rd_phandle == 0) 35 return; 36 37 LIST_INSERT_HEAD(®ulator_devices, rd, rd_list); 38} 39 40int 41regulator_set(uint32_t phandle, int enable) 42{ 43 uint32_t *gpio; 44 uint32_t startup_delay; 45 int active; 46 int node; 47 int len; 48 49 node = OF_getnodebyphandle(phandle); 50 if (node == 0) 51 return -1; 52 53 if (!OF_is_compatible(node, "regulator-fixed")) 54 return -1; 55 56 pinctrl_byname(node, "default"); 57 58 if (OF_getproplen(node, "enable-active-high") == 0) 59 active = 1; 60 else 61 active = 0; 62 63 /* The "gpio" property is optional. */ 64 len = OF_getproplen(node, "gpio"); 65 if (len < 0) 66 return 0; 67 68 gpio = malloc(len, M_TEMP, M_WAITOK); 69 OF_getpropintarray(node, "gpio", gpio, len); 70 gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT); 71 if (enable) 72 gpio_controller_set_pin(gpio, active); 73 else 74 gpio_controller_set_pin(gpio, !active); 75 free(gpio, M_TEMP, len); 76 77 startup_delay = OF_getpropint(node, "startup-delay-us", 0); 78 if (enable && startup_delay > 0) 79 delay(startup_delay); 80 81 return 0; 82} 83 84int 85regulator_enable(uint32_t phandle) 86{ 87 return regulator_set(phandle, 1); 88} 89 90int 91regulator_disable(uint32_t phandle) 92{ 93 return regulator_set(phandle, 0); 94} 95 96uint32_t 97regulator_get_voltage(uint32_t phandle) 98{ 99 struct regulator_device *rd; 100 int node; 101 102 LIST_FOREACH(rd, ®ulator_devices, rd_list) { 103 if (rd->rd_phandle == phandle) 104 break; 105 } 106 107 if (rd && rd->rd_get_voltage) 108 return rd->rd_get_voltage(rd->rd_cookie); 109 110 node = OF_getnodebyphandle(phandle); 111 if (node == 0) 112 return 0; 113 114 if (OF_is_compatible(node, "regulator-fixed")) 115 return OF_getpropint(node, "regulator-min-voltage", 0); 116 117 return 0; 118} 119 120int 121regulator_set_voltage(uint32_t phandle, uint32_t voltage) 122{ 123 struct regulator_device *rd; 124 125 LIST_FOREACH(rd, ®ulator_devices, rd_list) { 126 if (rd->rd_phandle == phandle) 127 break; 128 } 129 130 if (rd && rd->rd_set_voltage) 131 return rd->rd_set_voltage(rd->rd_cookie, voltage); 132 133 return -1; 134} 135