2 * Copyright (c) 2016 Stanislav Galabov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. The name of the author may not be used to endorse or promote products
12 * derived from this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/kernel.h>
34 #include <sys/module.h>
36 #include <dev/fdt/fdt_common.h>
37 #include <dev/ofw/openfirm.h>
38 #include <dev/ofw/ofw_bus.h>
39 #include <dev/ofw/ofw_bus_subr.h>
41 #include <dev/fdt/fdt_pinctrl.h>
42 #include <mips/mediatek/mtk_sysctl.h>
43 #include <mips/mediatek/mtk_soc.h>
44 #include <mips/mediatek/mtk_pinctrl.h>
46 #include "fdt_pinctrl_if.h"
48 static const struct ofw_compat_data compat_data[] = {
49 { "ralink,rt2880-pinmux", 1 },
56 mtk_pinctrl_probe(device_t dev)
59 if (!ofw_bus_status_okay(dev))
62 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
65 device_set_desc(dev, "MTK Pin Controller");
71 mtk_pinctrl_attach(device_t dev)
74 if (device_get_unit(dev) != 0) {
75 device_printf(dev, "Only one pin control allowed\n");
80 device_printf(dev, "GPIO mode start: 0x%08x\n",
81 mtk_sysctl_get(SYSCTL_GPIOMODE));
83 fdt_pinctrl_register(dev, NULL);
84 fdt_pinctrl_configure_tree(dev);
87 device_printf(dev, "GPIO mode end : 0x%08x\n",
88 mtk_sysctl_get(SYSCTL_GPIOMODE));
94 mtk_pinctrl_process_entry(device_t dev, struct mtk_pin_group *table,
95 const char *group, char *func)
100 for (i = 0; table[i].name != NULL; i++) {
101 if (strcmp(table[i].name, group) == 0) {
110 for (j = 0; j < table[i].funcnum; j++) {
111 if (strcmp(table[i].functions[j].name, func) == 0) {
112 val = mtk_sysctl_get(table[i].sysc_reg);
113 val &= ~(table[i].mask << table[i].offset);
114 val |= (table[i].functions[j].value << table[i].offset);
115 mtk_sysctl_set(table[i].sysc_reg, val);
124 mtk_pinctrl_process_node(device_t dev, struct mtk_pin_group *table,
127 const char **group_list = NULL;
128 char *pin_function = NULL;
129 int ret, num_groups, i;
133 num_groups = ofw_bus_string_list_to_array(node, "ralink,group",
139 if (OF_getprop_alloc_multi(node, "ralink,function", sizeof(*pin_function),
140 (void **)&pin_function) == -1) {
145 for (i = 0; i < num_groups; i++) {
146 if ((ret = mtk_pinctrl_process_entry(dev, table, group_list[i],
152 OF_prop_free(group_list);
153 OF_prop_free(pin_function);
158 mtk_pinctrl_configure(device_t dev, phandle_t cfgxref)
160 struct mtk_pin_group *pintable;
161 phandle_t node, child;
165 node = OF_node_from_xref(cfgxref);
168 /* Now, get the system type, so we can get the proper GPIO mode array */
169 socid = mtk_soc_get_socid();
173 pintable = rt2880_pintable;
175 case MTK_SOC_RT3050: /* fallthrough */
178 pintable = rt3050_pintable;
181 pintable = rt3352_pintable;
183 case MTK_SOC_RT3662: /* fallthrough */
185 pintable = rt3883_pintable;
188 pintable = rt5350_pintable;
190 case MTK_SOC_MT7620A: /* fallthrough */
191 case MTK_SOC_MT7620N:
192 pintable = mt7620_pintable;
194 case MTK_SOC_MT7628: /* fallthrough */
196 pintable = mt7628_pintable;
199 pintable = mt7621_pintable;
207 * OpenWRT dts files have single child within the pinctrl nodes, which
208 * contains the 'ralink,group' and 'ralink,function' properties.
210 for (child = OF_child(node); child != 0 && child != -1;
211 child = OF_peer(child)) {
212 if ((ret = mtk_pinctrl_process_node(dev, pintable, child)) != 0)
220 static device_method_t mtk_pinctrl_methods[] = {
221 DEVMETHOD(device_probe, mtk_pinctrl_probe),
222 DEVMETHOD(device_attach, mtk_pinctrl_attach),
224 /* fdt_pinctrl interface */
225 DEVMETHOD(fdt_pinctrl_configure, mtk_pinctrl_configure),
230 static driver_t mtk_pinctrl_driver = {
235 static devclass_t mtk_pinctrl_devclass;
237 EARLY_DRIVER_MODULE(mtk_pinctrl, simplebus, mtk_pinctrl_driver,
238 mtk_pinctrl_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_EARLY);
240 MODULE_DEPEND(mtk_pinctrl, mtk_sysctl, 1, 1, 1);