1283276Sgonzo/*-
2283276Sgonzo * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
3283276Sgonzo * All rights reserved.
4283276Sgonzo *
5283276Sgonzo * Redistribution and use in source and binary forms, with or without
6283276Sgonzo * modification, are permitted provided that the following conditions
7283276Sgonzo * are met:
8283276Sgonzo * 1. Redistributions of source code must retain the above copyright
9283276Sgonzo *    notice, this list of conditions and the following disclaimer.
10283276Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11283276Sgonzo *    notice, this list of conditions and the following disclaimer in the
12283276Sgonzo *    documentation and/or other materials provided with the distribution.
13283276Sgonzo *
14283276Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15283276Sgonzo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16283276Sgonzo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17283276Sgonzo * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18283276Sgonzo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19283276Sgonzo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20283276Sgonzo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21283276Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22283276Sgonzo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23283276Sgonzo * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24283276Sgonzo * POSSIBILITY OF SUCH DAMAGE.
25283276Sgonzo *
26283276Sgonzo * $FreeBSD: releng/11.0/sys/arm/ti/ti_hwmods.c 299477 2016-05-11 18:20:02Z gonzo $
27283276Sgonzo */
28283276Sgonzo
29283276Sgonzo#include <sys/cdefs.h>
30283276Sgonzo__FBSDID("$FreeBSD: releng/11.0/sys/arm/ti/ti_hwmods.c 299477 2016-05-11 18:20:02Z gonzo $");
31283276Sgonzo
32283276Sgonzo#include <sys/param.h>
33283276Sgonzo#include <sys/systm.h>
34283276Sgonzo#include <sys/bus.h>
35283276Sgonzo#include <sys/kernel.h>
36283276Sgonzo
37283276Sgonzo#include <dev/fdt/fdt_common.h>
38283276Sgonzo#include <dev/ofw/openfirm.h>
39283276Sgonzo#include <dev/ofw/ofw_bus.h>
40283276Sgonzo#include <dev/ofw/ofw_bus_subr.h>
41283276Sgonzo
42283276Sgonzo#include <machine/bus.h>
43283276Sgonzo#include <machine/fdt.h>
44283276Sgonzo
45283276Sgonzo#include <arm/ti/ti_prcm.h>
46283276Sgonzo#include <arm/ti/ti_hwmods.h>
47283276Sgonzo
48283276Sgonzostruct hwmod {
49283276Sgonzo	const char	*name;
50283276Sgonzo	int		clock_id;
51283276Sgonzo};
52283276Sgonzo
53283276Sgonzostruct hwmod ti_hwmods[] = {
54283276Sgonzo	{"i2c1",	I2C1_CLK},
55283276Sgonzo	{"i2c2",	I2C2_CLK},
56283276Sgonzo	{"i2c3",	I2C3_CLK},
57283276Sgonzo	{"i2c4",	I2C4_CLK},
58283276Sgonzo	{"i2c5",	I2C5_CLK},
59283276Sgonzo
60283276Sgonzo	{"gpio1",	GPIO1_CLK},
61283276Sgonzo	{"gpio2",	GPIO2_CLK},
62283276Sgonzo	{"gpio3",	GPIO3_CLK},
63283276Sgonzo	{"gpio4",	GPIO4_CLK},
64283276Sgonzo	{"gpio5",	GPIO5_CLK},
65283276Sgonzo	{"gpio6",	GPIO6_CLK},
66283276Sgonzo	{"gpio7",	GPIO7_CLK},
67283276Sgonzo
68283276Sgonzo	{"mmc1",	MMC1_CLK},
69283276Sgonzo	{"mmc2",	MMC2_CLK},
70283276Sgonzo	{"mmc3",	MMC3_CLK},
71283276Sgonzo	{"mmc4",	MMC4_CLK},
72283276Sgonzo	{"mmc5",	MMC5_CLK},
73283276Sgonzo	{"mmc6",	MMC6_CLK},
74283276Sgonzo
75283276Sgonzo	{"epwmss0",	PWMSS0_CLK},
76283276Sgonzo	{"epwmss1",	PWMSS1_CLK},
77283276Sgonzo	{"epwmss2",	PWMSS2_CLK},
78283276Sgonzo
79297395Sloos	{"spi0",	SPI0_CLK},
80297395Sloos	{"spi1",	SPI1_CLK},
81297395Sloos
82283276Sgonzo	{"timer1",	TIMER1_CLK},
83283276Sgonzo	{"timer2",	TIMER2_CLK},
84283276Sgonzo	{"timer3",	TIMER3_CLK},
85283276Sgonzo	{"timer4",	TIMER4_CLK},
86283276Sgonzo	{"timer5",	TIMER5_CLK},
87283276Sgonzo	{"timer6",	TIMER6_CLK},
88283276Sgonzo	{"timer7",	TIMER7_CLK},
89283276Sgonzo
90283276Sgonzo	{"uart1",	UART1_CLK},
91283276Sgonzo	{"uart2",	UART2_CLK},
92283276Sgonzo	{"uart3",	UART3_CLK},
93283276Sgonzo	{"uart4",	UART4_CLK},
94283276Sgonzo	{"uart5",	UART5_CLK},
95283276Sgonzo	{"uart6",	UART6_CLK},
96283276Sgonzo	{"uart7",	UART7_CLK},
97283276Sgonzo
98283276Sgonzo	{NULL,		0}
99283276Sgonzo};
100283276Sgonzo
101283276Sgonzoclk_ident_t
102283276Sgonzoti_hwmods_get_clock(device_t dev)
103283276Sgonzo{
104283276Sgonzo	phandle_t node;
105283276Sgonzo	int len, l;
106283276Sgonzo	char *name;
107283276Sgonzo	char *buf;
108283276Sgonzo	int clk;
109283276Sgonzo	struct hwmod *hw;
110283276Sgonzo
111283276Sgonzo	if ((node = ofw_bus_get_node(dev)) == 0)
112283276Sgonzo		return (INVALID_CLK_IDENT);
113283276Sgonzo
114283276Sgonzo	if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0)
115283276Sgonzo		return (INVALID_CLK_IDENT);
116283276Sgonzo
117283276Sgonzo	buf = name;
118283276Sgonzo
119283276Sgonzo	clk = INVALID_CLK_IDENT;
120283276Sgonzo	while ((len > 0) && (clk == INVALID_CLK_IDENT)) {
121283276Sgonzo		for (hw = ti_hwmods; hw->name != NULL; ++hw) {
122283276Sgonzo			if (strcmp(hw->name, name) == 0) {
123283276Sgonzo				clk = hw->clock_id;
124283276Sgonzo				break;
125283276Sgonzo			}
126283276Sgonzo		}
127283276Sgonzo
128283276Sgonzo		/* Slide to the next sub-string. */
129283276Sgonzo		l = strlen(name) + 1;
130283276Sgonzo		name += l;
131283276Sgonzo		len -= l;
132283276Sgonzo	}
133283276Sgonzo
134283276Sgonzo	if (len > 0)
135286615Spfg		device_printf(dev, "WARNING: more than one ti,hwmod \n");
136283276Sgonzo
137299477Sgonzo	OF_prop_free(buf);
138283276Sgonzo	return (clk);
139283276Sgonzo}
140283276Sgonzo
141283276Sgonzoint ti_hwmods_contains(device_t dev, const char *hwmod)
142283276Sgonzo{
143283276Sgonzo	phandle_t node;
144283276Sgonzo	int len, l;
145283276Sgonzo	char *name;
146283276Sgonzo	char *buf;
147283276Sgonzo	int result;
148283276Sgonzo
149283276Sgonzo	if ((node = ofw_bus_get_node(dev)) == 0)
150283276Sgonzo		return (0);
151283276Sgonzo
152283276Sgonzo	if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0)
153283276Sgonzo		return (0);
154283276Sgonzo
155283276Sgonzo	buf = name;
156283276Sgonzo
157283276Sgonzo	result = 0;
158283276Sgonzo	while (len > 0) {
159283276Sgonzo		if (strcmp(name, hwmod) == 0) {
160283276Sgonzo			result = 1;
161283276Sgonzo			break;
162283276Sgonzo		}
163283276Sgonzo
164283276Sgonzo		/* Slide to the next sub-string. */
165283276Sgonzo		l = strlen(name) + 1;
166283276Sgonzo		name += l;
167283276Sgonzo		len -= l;
168283276Sgonzo	}
169283276Sgonzo
170299477Sgonzo	OF_prop_free(buf);
171283276Sgonzo
172283276Sgonzo	return (result);
173283276Sgonzo}
174286678Sian
175286678Sianint
176286678Sianti_hwmods_get_unit(device_t dev, const char *hwmod)
177286678Sian{
178286678Sian	phandle_t node;
179286678Sian	int l, len, hwmodlen, result;
180286678Sian	char *name;
181286678Sian	char *buf;
182286678Sian
183286678Sian	if ((node = ofw_bus_get_node(dev)) == 0)
184286678Sian		return (0);
185286678Sian
186286678Sian	if ((len = OF_getprop_alloc(node, "ti,hwmods", 1, (void**)&name)) <= 0)
187286678Sian		return (0);
188286678Sian
189286678Sian	buf = name;
190286678Sian	hwmodlen = strlen(hwmod);
191286678Sian	result = 0;
192286678Sian	while (len > 0) {
193286678Sian		if (strncmp(name, hwmod, hwmodlen) == 0) {
194286678Sian                        result = (int)strtoul(name + hwmodlen, NULL, 10);
195286678Sian			break;
196286678Sian		}
197286678Sian		/* Slide to the next sub-string. */
198286678Sian		l = strlen(name) + 1;
199286678Sian		name += l;
200286678Sian		len -= l;
201286678Sian	}
202286678Sian
203299477Sgonzo	OF_prop_free(buf);
204286678Sian	return (result);
205286678Sian}
206