1/*- 2 * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/kernel.h> 36 37#include <dev/fdt/fdt_common.h> 38#include <dev/ofw/openfirm.h> 39#include <dev/ofw/ofw_bus.h> 40#include <dev/ofw/ofw_bus_subr.h> 41 42#include <machine/bus.h> 43#include <machine/fdt.h> 44 45#include <arm/ti/ti_prcm.h> 46#include <arm/ti/ti_hwmods.h> 47 48struct hwmod { 49 const char *name; 50 int clock_id; 51}; 52 53struct hwmod ti_hwmods[] = { 54 {"i2c1", I2C1_CLK}, 55 {"i2c2", I2C2_CLK}, 56 {"i2c3", I2C3_CLK}, 57 {"i2c4", I2C4_CLK}, 58 {"i2c5", I2C5_CLK}, 59 60 {"gpio1", GPIO1_CLK}, 61 {"gpio2", GPIO2_CLK}, 62 {"gpio3", GPIO3_CLK}, 63 {"gpio4", GPIO4_CLK}, 64 {"gpio5", GPIO5_CLK}, 65 {"gpio6", GPIO6_CLK}, 66 {"gpio7", GPIO7_CLK}, 67 68 {"mmc1", MMC1_CLK}, 69 {"mmc2", MMC2_CLK}, 70 {"mmc3", MMC3_CLK}, 71 {"mmc4", MMC4_CLK}, 72 {"mmc5", MMC5_CLK}, 73 {"mmc6", MMC6_CLK}, 74 75 {"epwmss0", PWMSS0_CLK}, 76 {"epwmss1", PWMSS1_CLK}, 77 {"epwmss2", PWMSS2_CLK}, 78 79 {"spi0", SPI0_CLK}, 80 {"spi1", SPI1_CLK}, 81 82 {"timer1", TIMER1_CLK}, 83 {"timer2", TIMER2_CLK}, 84 {"timer3", TIMER3_CLK}, 85 {"timer4", TIMER4_CLK}, 86 {"timer5", TIMER5_CLK}, 87 {"timer6", TIMER6_CLK}, 88 {"timer7", TIMER7_CLK}, 89 90 {"uart1", UART1_CLK}, 91 {"uart2", UART2_CLK}, 92 {"uart3", UART3_CLK}, 93 {"uart4", UART4_CLK}, 94 {"uart5", UART5_CLK}, 95 {"uart6", UART6_CLK}, 96 {"uart7", UART7_CLK}, 97 98 {NULL, 0} 99}; 100 101clk_ident_t 102ti_hwmods_get_clock(device_t dev) 103{ 104 phandle_t node; 105 int len, l; 106 char *name; 107 char *buf; 108 int clk; 109 struct hwmod *hw; 110 111 if ((node = ofw_bus_get_node(dev)) == 0) 112 return (INVALID_CLK_IDENT); 113 114 if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0) 115 return (INVALID_CLK_IDENT); 116 117 buf = name; 118 119 clk = INVALID_CLK_IDENT; 120 while ((len > 0) && (clk == INVALID_CLK_IDENT)) { 121 for (hw = ti_hwmods; hw->name != NULL; ++hw) { 122 if (strcmp(hw->name, name) == 0) { 123 clk = hw->clock_id; 124 break; 125 } 126 } 127 128 /* Slide to the next sub-string. */ 129 l = strlen(name) + 1; 130 name += l; 131 len -= l; 132 } 133 134 if (len > 0) 135 device_printf(dev, "WARNING: more than one ti,hwmod \n"); 136 137 OF_prop_free(buf); 138 return (clk); 139} 140 141int ti_hwmods_contains(device_t dev, const char *hwmod) 142{ 143 phandle_t node; 144 int len, l; 145 char *name; 146 char *buf; 147 int result; 148 149 if ((node = ofw_bus_get_node(dev)) == 0) 150 return (0); 151 152 if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0) 153 return (0); 154 155 buf = name; 156 157 result = 0; 158 while (len > 0) { 159 if (strcmp(name, hwmod) == 0) { 160 result = 1; 161 break; 162 } 163 164 /* Slide to the next sub-string. */ 165 l = strlen(name) + 1; 166 name += l; 167 len -= l; 168 } 169 170 OF_prop_free(buf); 171 172 return (result); 173} 174 175int 176ti_hwmods_get_unit(device_t dev, const char *hwmod) 177{ 178 phandle_t node; 179 int l, len, hwmodlen, result; 180 char *name; 181 char *buf; 182 183 if ((node = ofw_bus_get_node(dev)) == 0) 184 return (0); 185 186 if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0) 187 return (0); 188 189 buf = name; 190 hwmodlen = strlen(hwmod); 191 result = 0; 192 while (len > 0) { 193 if (strncmp(name, hwmod, hwmodlen) == 0) { 194 result = (int)strtoul(name + hwmodlen, NULL, 10); 195 break; 196 } 197 /* Slide to the next sub-string. */ 198 l = strlen(name) + 1; 199 name += l; 200 len -= l; 201 } 202 203 OF_prop_free(buf); 204 return (result); 205} 206