1*a7702439Spatrick /* $OpenBSD: ofw_pinctrl.c,v 1.3 2020/06/06 16:59:43 patrick Exp $ */
204796313Skettenis /*
304796313Skettenis * Copyright (c) 2016 Mark Kettenis
404796313Skettenis *
504796313Skettenis * Permission to use, copy, modify, and distribute this software for any
604796313Skettenis * purpose with or without fee is hereby granted, provided that the above
704796313Skettenis * copyright notice and this permission notice appear in all copies.
804796313Skettenis *
904796313Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1004796313Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1104796313Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1204796313Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1304796313Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1404796313Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1504796313Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1604796313Skettenis */
1704796313Skettenis
1804796313Skettenis #include <sys/types.h>
1904796313Skettenis #include <sys/systm.h>
2004796313Skettenis #include <sys/malloc.h>
2104796313Skettenis
2204796313Skettenis #include <dev/ofw/openfirm.h>
2304796313Skettenis #include <dev/ofw/ofw_pinctrl.h>
2404796313Skettenis
2504796313Skettenis struct pinctrl {
2604796313Skettenis int pc_phandle;
2704796313Skettenis int (*pc_pinctrl)(uint32_t, void *);
2804796313Skettenis void *pc_cookie;
2904796313Skettenis
3004796313Skettenis LIST_ENTRY(pinctrl) pc_list;
3104796313Skettenis };
3204796313Skettenis
3304796313Skettenis void pinctrl_register_child(int, int (*)(uint32_t, void *), void *);
3404796313Skettenis
3504796313Skettenis LIST_HEAD(, pinctrl) pinctrls = LIST_HEAD_INITIALIZER(pinctrl);
3604796313Skettenis
3704796313Skettenis void
pinctrl_register(int node,int (* pinctrl)(uint32_t,void *),void * cookie)3804796313Skettenis pinctrl_register(int node, int (*pinctrl)(uint32_t, void *), void *cookie)
3904796313Skettenis {
4004796313Skettenis for (node = OF_child(node); node; node = OF_peer(node))
4104796313Skettenis pinctrl_register_child(node, pinctrl, cookie);
4204796313Skettenis }
4304796313Skettenis
4404796313Skettenis void
pinctrl_register_child(int node,int (* pinctrl)(uint32_t,void *),void * cookie)4504796313Skettenis pinctrl_register_child(int node, int (*pinctrl)(uint32_t, void *), void *cookie)
4604796313Skettenis {
4704796313Skettenis struct pinctrl *pc;
4804796313Skettenis uint32_t phandle;
4904796313Skettenis
5004796313Skettenis phandle = OF_getpropint(node, "phandle", 0);
5104796313Skettenis if (phandle) {
5204796313Skettenis pc = malloc(sizeof(struct pinctrl), M_DEVBUF, M_WAITOK);
5304796313Skettenis pc->pc_phandle = phandle;
5404796313Skettenis pc->pc_pinctrl = pinctrl;
5504796313Skettenis pc->pc_cookie = cookie;
5604796313Skettenis LIST_INSERT_HEAD(&pinctrls, pc, pc_list);
5704796313Skettenis }
5804796313Skettenis
5904796313Skettenis for (node = OF_child(node); node; node = OF_peer(node))
6004796313Skettenis pinctrl_register_child(node, pinctrl, cookie);
6104796313Skettenis }
6204796313Skettenis
6304796313Skettenis int
pinctrl_byphandle(uint32_t phandle)6404796313Skettenis pinctrl_byphandle(uint32_t phandle)
6504796313Skettenis {
6604796313Skettenis struct pinctrl *pc;
6704796313Skettenis
68*a7702439Spatrick if (phandle == 0)
69*a7702439Spatrick return -1;
70*a7702439Spatrick
7104796313Skettenis LIST_FOREACH(pc, &pinctrls, pc_list) {
7204796313Skettenis if (pc->pc_phandle == phandle)
7304796313Skettenis return pc->pc_pinctrl(pc->pc_phandle, pc->pc_cookie);
7404796313Skettenis }
7504796313Skettenis
7604796313Skettenis return -1;
7704796313Skettenis }
7804796313Skettenis
7904796313Skettenis int
pinctrl_byid(int node,int id)8004796313Skettenis pinctrl_byid(int node, int id)
8104796313Skettenis {
8204796313Skettenis char pinctrl[32];
8304796313Skettenis uint32_t *phandles;
8404796313Skettenis int len, i;
8504796313Skettenis
8604796313Skettenis snprintf(pinctrl, sizeof(pinctrl), "pinctrl-%d", id);
8704796313Skettenis len = OF_getproplen(node, pinctrl);
8804796313Skettenis if (len <= 0)
8904796313Skettenis return -1;
9004796313Skettenis
9104796313Skettenis phandles = malloc(len, M_TEMP, M_WAITOK);
9204796313Skettenis OF_getpropintarray(node, pinctrl, phandles, len);
9304796313Skettenis for (i = 0; i < len / sizeof(uint32_t); i++)
9404796313Skettenis pinctrl_byphandle(phandles[i]);
9504796313Skettenis free(phandles, M_TEMP, len);
9604796313Skettenis return 0;
9704796313Skettenis }
9804796313Skettenis
9904796313Skettenis int
pinctrl_byname(int node,const char * config)10004796313Skettenis pinctrl_byname(int node, const char *config)
10104796313Skettenis {
10250946bcbSkettenis int id;
10304796313Skettenis
10450946bcbSkettenis id = OF_getindex(node, config, "pinctrl-names");
10550946bcbSkettenis if (id < 0)
10604796313Skettenis return -1;
10704796313Skettenis
10804796313Skettenis return pinctrl_byid(node, id);
10904796313Skettenis }
110