xref: /openbsd-src/sys/dev/ofw/ofw_pinctrl.c (revision a77024392229412bd0851d9586f3ce1e52321555)
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