The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/mediatek/mtk_pinctrl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016 Stanislav Galabov
    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  *    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.
   13  *
   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
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bus.h>
   34 #include <sys/module.h>
   35 
   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>
   40 
   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>
   45 
   46 #include "fdt_pinctrl_if.h"
   47 
   48 static const struct ofw_compat_data compat_data[] = {
   49         { "ralink,rt2880-pinmux",       1 },
   50 
   51         /* Sentinel */
   52         { NULL,                         0 }
   53 };
   54 
   55 static int
   56 mtk_pinctrl_probe(device_t dev)
   57 {
   58 
   59         if (!ofw_bus_status_okay(dev))
   60                 return (ENXIO);
   61 
   62         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
   63                 return (ENXIO);
   64 
   65         device_set_desc(dev, "MTK Pin Controller");
   66 
   67         return (0);
   68 }
   69 
   70 static int
   71 mtk_pinctrl_attach(device_t dev)
   72 {
   73 
   74         if (device_get_unit(dev) != 0) {
   75                 device_printf(dev, "Only one pin control allowed\n");
   76                 return (ENXIO);
   77         }
   78 
   79         if (bootverbose)
   80                 device_printf(dev, "GPIO mode start: 0x%08x\n",
   81                     mtk_sysctl_get(SYSCTL_GPIOMODE));
   82 
   83         fdt_pinctrl_register(dev, NULL);
   84         fdt_pinctrl_configure_tree(dev);
   85 
   86         if (bootverbose)
   87                 device_printf(dev, "GPIO mode end  : 0x%08x\n",
   88                     mtk_sysctl_get(SYSCTL_GPIOMODE));
   89 
   90         return (0);
   91 }
   92 
   93 static int
   94 mtk_pinctrl_process_entry(device_t dev, struct mtk_pin_group *table,
   95     const char *group, char *func)
   96 {
   97         uint32_t val;
   98         int found = 0, i, j;
   99 
  100         for (i = 0; table[i].name != NULL; i++) {
  101                 if (strcmp(table[i].name, group) == 0) {
  102                         found = 1;
  103                         break;
  104                 }
  105         }
  106 
  107         if (!found)
  108                 return (ENOENT);
  109 
  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);
  116                         return (0);
  117                 }
  118         }
  119 
  120         return (ENOENT);
  121 }
  122 
  123 static int
  124 mtk_pinctrl_process_node(device_t dev, struct mtk_pin_group *table,
  125     phandle_t node)
  126 {
  127         const char **group_list = NULL;
  128         char *pin_function = NULL;
  129         int ret, num_groups, i;
  130 
  131         ret = 0;
  132 
  133         num_groups = ofw_bus_string_list_to_array(node, "ralink,group",
  134             &group_list);
  135 
  136         if (num_groups <= 0)
  137                 return (ENOENT);
  138 
  139         if (OF_getprop_alloc_multi(node, "ralink,function", sizeof(*pin_function),
  140                              (void **)&pin_function) == -1) {
  141                 ret = ENOENT;
  142                 goto out;
  143         }
  144 
  145         for (i = 0; i < num_groups; i++) {
  146                 if ((ret = mtk_pinctrl_process_entry(dev, table, group_list[i],
  147                     pin_function)) != 0)
  148                         goto out;
  149         }
  150 
  151 out:
  152         OF_prop_free(group_list);
  153         OF_prop_free(pin_function);
  154         return (ret);
  155 }
  156 
  157 static int
  158 mtk_pinctrl_configure(device_t dev, phandle_t cfgxref)
  159 {
  160         struct mtk_pin_group *pintable;
  161         phandle_t node, child;
  162         uint32_t socid;
  163         int ret;
  164 
  165         node = OF_node_from_xref(cfgxref);
  166         ret = 0;
  167 
  168         /* Now, get the system type, so we can get the proper GPIO mode array */
  169         socid = mtk_soc_get_socid();
  170 
  171         switch (socid) {
  172         case MTK_SOC_RT2880:
  173                 pintable = rt2880_pintable;
  174                 break;
  175         case MTK_SOC_RT3050: /* fallthrough */
  176         case MTK_SOC_RT3052:
  177         case MTK_SOC_RT3350:
  178                 pintable = rt3050_pintable;
  179                 break;
  180         case MTK_SOC_RT3352:
  181                 pintable = rt3352_pintable;
  182                 break;
  183         case MTK_SOC_RT3662: /* fallthrough */
  184         case MTK_SOC_RT3883:
  185                 pintable = rt3883_pintable;
  186                 break;
  187         case MTK_SOC_RT5350:
  188                 pintable = rt5350_pintable;
  189                 break;
  190         case MTK_SOC_MT7620A: /* fallthrough */
  191         case MTK_SOC_MT7620N:
  192                 pintable = mt7620_pintable;
  193                 break;
  194         case MTK_SOC_MT7628: /* fallthrough */
  195         case MTK_SOC_MT7688:
  196                 pintable = mt7628_pintable;
  197                 break;
  198         case MTK_SOC_MT7621:
  199                 pintable = mt7621_pintable;
  200                 break;
  201         default:
  202                 ret = ENOENT;
  203                 goto out;
  204         }
  205 
  206         /*
  207          * OpenWRT dts files have single child within the pinctrl nodes, which
  208          * contains the 'ralink,group' and 'ralink,function' properties.
  209          */ 
  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)
  213                         return (ret);
  214         }
  215 
  216 out:
  217         return (ret);
  218 }
  219 
  220 static device_method_t mtk_pinctrl_methods[] = {
  221         DEVMETHOD(device_probe,                 mtk_pinctrl_probe),
  222         DEVMETHOD(device_attach,                mtk_pinctrl_attach),
  223 
  224         /* fdt_pinctrl interface */
  225         DEVMETHOD(fdt_pinctrl_configure,        mtk_pinctrl_configure),
  226 
  227         DEVMETHOD_END
  228 };
  229 
  230 static driver_t mtk_pinctrl_driver = {
  231         "pinctrl",
  232         mtk_pinctrl_methods,
  233         0,
  234 };
  235 static devclass_t mtk_pinctrl_devclass;
  236 
  237 EARLY_DRIVER_MODULE(mtk_pinctrl, simplebus, mtk_pinctrl_driver,
  238     mtk_pinctrl_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_EARLY);
  239 
  240 MODULE_DEPEND(mtk_pinctrl, mtk_sysctl, 1, 1, 1);

Cache object: ec306e04a5b5f0780e9d6fe8505e608f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.