xref: /netbsd/sys/arch/arm/imx/imx23_pinctrl.c (revision beecddb6)
1*beecddb6Sthorpej /* $Id: imx23_pinctrl.c,v 1.6 2021/08/07 16:18:44 thorpej Exp $ */
25224f277Smatt 
35224f277Smatt /*
45224f277Smatt * Copyright (c) 2013 The NetBSD Foundation, Inc.
55224f277Smatt * All rights reserved.
65224f277Smatt *
75224f277Smatt * This code is derived from software contributed to The NetBSD Foundation
85224f277Smatt * by Petri Laakso.
95224f277Smatt *
105224f277Smatt * Redistribution and use in source and binary forms, with or without
115224f277Smatt * modification, are permitted provided that the following conditions
125224f277Smatt * are met:
135224f277Smatt * 1. Redistributions of source code must retain the above copyright
145224f277Smatt *    notice, this list of conditions and the following disclaimer.
155224f277Smatt * 2. Redistributions in binary form must reproduce the above copyright
165224f277Smatt *    notice, this list of conditions and the following disclaimer in the
175224f277Smatt *    documentation and/or other materials provided with the distribution.
185224f277Smatt *
195224f277Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
205224f277Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
215224f277Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
225224f277Smatt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
235224f277Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
245224f277Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
255224f277Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
265224f277Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275224f277Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
285224f277Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
295224f277Smatt * POSSIBILITY OF SUCH DAMAGE.
305224f277Smatt */
315224f277Smatt 
325224f277Smatt #include <sys/param.h>
335224f277Smatt #include <sys/types.h>
345224f277Smatt #include <sys/bus.h>
355224f277Smatt #include <sys/cdefs.h>
365224f277Smatt #include <sys/device.h>
375224f277Smatt #include <sys/errno.h>
385224f277Smatt #include <sys/gpio.h>
395224f277Smatt 
405224f277Smatt #include <dev/gpio/gpiovar.h>
415224f277Smatt 
425224f277Smatt #include <arm/imx/imx23_pinctrlreg.h>
435224f277Smatt #include <arm/imx/imx23_pinctrlvar.h>
445224f277Smatt #include <arm/imx/imx23var.h>
455224f277Smatt 
465224f277Smatt #define GPIO_PINS 96
475224f277Smatt 
48aa56c0c1Sskrll typedef struct imx23_pinctrl_softc {
495224f277Smatt 	device_t sc_dev;
505224f277Smatt 	bus_space_tag_t sc_iot;
515224f277Smatt 	bus_space_handle_t sc_hdl;
525224f277Smatt 	struct gpio_chipset_tag gc;
535224f277Smatt 	gpio_pin_t pins[GPIO_PINS];
54aa56c0c1Sskrll } *imx23_pinctrl_softc_t;
555224f277Smatt 
56aa56c0c1Sskrll static int	imx23_pinctrl_match(device_t, cfdata_t, void *);
57aa56c0c1Sskrll static void	imx23_pinctrl_attach(device_t, device_t, void *);
58aa56c0c1Sskrll static int	imx23_pinctrl_activate(device_t, enum devact);
595224f277Smatt 
605224f277Smatt #if notyet
61aa56c0c1Sskrll static void     imx23_pinctrl_reset(struct imx23_pinctrl_softc *);
625224f277Smatt #endif
63aa56c0c1Sskrll static void     imx23_pinctrl_init(struct imx23_pinctrl_softc *);
645224f277Smatt 
65aa56c0c1Sskrll static	int	imx23_pinctrl_gp_gc_open(void *, device_t);
66aa56c0c1Sskrll static	void	imx23_pinctrl_gp_gc_close(void *, device_t);
67aa56c0c1Sskrll static	int	imx23_pinctrl_gp_pin_read(void *, int);
68aa56c0c1Sskrll static	void	imx23_pinctrl_gp_pin_write(void *, int, int);
69aa56c0c1Sskrll static	void	imx23_pinctrl_gp_pin_ctl(void *, int, int);
705224f277Smatt 
71aa56c0c1Sskrll static imx23_pinctrl_softc_t _sc = NULL;
725224f277Smatt 
73aa56c0c1Sskrll CFATTACH_DECL3_NEW(imx23_pinctrl,
74aa56c0c1Sskrll         sizeof(struct imx23_pinctrl_softc),
75aa56c0c1Sskrll         imx23_pinctrl_match,
76aa56c0c1Sskrll         imx23_pinctrl_attach,
775224f277Smatt         NULL,
78aa56c0c1Sskrll         imx23_pinctrl_activate,
795224f277Smatt         NULL,
805224f277Smatt         NULL,
815224f277Smatt         0
825224f277Smatt );
835224f277Smatt 
845224f277Smatt #define GPIO_PIN_CAP (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INOUT | \
855224f277Smatt 		GPIO_PIN_PULLUP | GPIO_PIN_SET)
865224f277Smatt 
875224f277Smatt /*
885224f277Smatt  * Supported capabilities for each GPIO pin.
895224f277Smatt  */
905224f277Smatt const static int pin_caps[GPIO_PINS] = {
915224f277Smatt 	/*
925224f277Smatt 	 * HW_PINCTRL_MUXSEL0
935224f277Smatt 	 */
945224f277Smatt 	/* PIN 0 */
955224f277Smatt 	GPIO_PIN_CAP,
965224f277Smatt 	/* PIN 1 */
975224f277Smatt 	GPIO_PIN_CAP,
985224f277Smatt 	/* PIN 2 */
995224f277Smatt 	GPIO_PIN_CAP,
1005224f277Smatt 	/* PIN 3 */
1015224f277Smatt 	GPIO_PIN_CAP,
1025224f277Smatt 	/* PIN 4 */
1035224f277Smatt 	GPIO_PIN_CAP,
1045224f277Smatt 	/* PIN 5 */
1055224f277Smatt 	GPIO_PIN_CAP,
1065224f277Smatt 	/* PIN 6 */
1075224f277Smatt 	GPIO_PIN_CAP,
1085224f277Smatt 	/* PIN 7 */
1095224f277Smatt 	GPIO_PIN_CAP,
1105224f277Smatt 	/* PIN 8 */
1115224f277Smatt 	GPIO_PIN_CAP,
1125224f277Smatt 	/* PIN 9 */
1135224f277Smatt 	GPIO_PIN_CAP,
1145224f277Smatt 	/* PIN 10 */
1155224f277Smatt 	GPIO_PIN_CAP,
1165224f277Smatt 	/* PIN 11 */
1175224f277Smatt 	GPIO_PIN_CAP,
1185224f277Smatt 	/* PIN 12 */
1195224f277Smatt 	GPIO_PIN_CAP,
1205224f277Smatt 	/* PIN 13 */
1215224f277Smatt 	GPIO_PIN_CAP,
1225224f277Smatt 	/* PIN 14 */
1235224f277Smatt 	GPIO_PIN_CAP,
1245224f277Smatt 	/* PIN 15 */
1255224f277Smatt 	GPIO_PIN_CAP,
1265224f277Smatt 	/*
1275224f277Smatt 	 * HW_PINCTRL_MUXSEL1
1285224f277Smatt 	 */
1295224f277Smatt 	/* PIN 16 */
1305224f277Smatt 	GPIO_PIN_CAP,
1315224f277Smatt 	/* PIN 17 */
1325224f277Smatt 	0,		/* Reserved for powering OLinuXino MAXI/MINI USB hub. */
1335224f277Smatt 	/* PIN 18 */
1345224f277Smatt 	GPIO_PIN_CAP,
1355224f277Smatt 	/* PIN 19 */
1365224f277Smatt 	GPIO_PIN_CAP,
1375224f277Smatt 	/* PIN 20 */
1385224f277Smatt 	GPIO_PIN_CAP,
1395224f277Smatt 	/* PIN 21 */
1405224f277Smatt 	GPIO_PIN_CAP,
1415224f277Smatt 	/* PIN 22 */
1425224f277Smatt 	GPIO_PIN_CAP,
1435224f277Smatt 	/* PIN 23 */
1445224f277Smatt 	GPIO_PIN_CAP,
1455224f277Smatt 	/* PIN 24 */
1465224f277Smatt 	GPIO_PIN_CAP,
1475224f277Smatt 	/* PIN 25 */
1485224f277Smatt 	GPIO_PIN_CAP,
1495224f277Smatt 	/* PIN 26 */
1505224f277Smatt 	GPIO_PIN_CAP,
1515224f277Smatt 	/* PIN 27 */
1525224f277Smatt 	GPIO_PIN_CAP,
1535224f277Smatt 	/* PIN 28 */
1545224f277Smatt 	GPIO_PIN_CAP,
1555224f277Smatt 	/* PIN 29 */
1565224f277Smatt 	GPIO_PIN_CAP,
1575224f277Smatt 	/* PIN 30 */
1585224f277Smatt 	GPIO_PIN_CAP,
1595224f277Smatt 	/* PIN 31 */
1605224f277Smatt 	GPIO_PIN_CAP,
1615224f277Smatt 	/*
1625224f277Smatt 	 * HW_PINCTRL_MUXSEL2
1635224f277Smatt 	 */
1645224f277Smatt 	/* PIN 32 */
1655224f277Smatt 	GPIO_PIN_CAP,
1665224f277Smatt 	/* PIN 33 */
1675224f277Smatt 	GPIO_PIN_CAP,
1685224f277Smatt 	/* PIN 34 */
1695224f277Smatt 	GPIO_PIN_CAP,
1705224f277Smatt 	/* PIN 35 */
1715224f277Smatt 	GPIO_PIN_CAP,
1725224f277Smatt 	/* PIN 36 */
1735224f277Smatt 	GPIO_PIN_CAP,
1745224f277Smatt 	/* PIN 37 */
1755224f277Smatt 	GPIO_PIN_CAP,
1765224f277Smatt 	/* PIN 38 */
1775224f277Smatt 	GPIO_PIN_CAP,
1785224f277Smatt 	/* PIN 39 */
1795224f277Smatt 	GPIO_PIN_CAP,
1805224f277Smatt 	/* PIN 40 */
1815224f277Smatt 	GPIO_PIN_CAP,
1825224f277Smatt 	/* PIN 41 */
1835224f277Smatt 	GPIO_PIN_CAP,
1845224f277Smatt 	/* PIN 42 */
1855224f277Smatt 	GPIO_PIN_CAP,
1865224f277Smatt 	/* PIN 43 */
1875224f277Smatt 	GPIO_PIN_CAP,
1885224f277Smatt 	/* PIN 44 */
1895224f277Smatt 	GPIO_PIN_CAP,
1905224f277Smatt 	/* PIN 45 */
1915224f277Smatt 	GPIO_PIN_CAP,
1925224f277Smatt 	/* PIN 46 */
1935224f277Smatt 	GPIO_PIN_CAP,
1945224f277Smatt 	/* PIN 47 */
1955224f277Smatt 	GPIO_PIN_CAP,
1965224f277Smatt 	/*
1975224f277Smatt 	 * HW_PINCTRL_MUXSEL3
1985224f277Smatt 	 */
1995224f277Smatt 	/* PIN 48 */
2005224f277Smatt 	GPIO_PIN_CAP,
2015224f277Smatt 	/* PIN 49 */
2025224f277Smatt 	GPIO_PIN_CAP,
2035224f277Smatt 	/* PIN 50 */
2045224f277Smatt 	GPIO_PIN_CAP,
2055224f277Smatt 	/* PIN 51 */
2065224f277Smatt 	GPIO_PIN_CAP,
2075224f277Smatt 	/* PIN 52 */
2085224f277Smatt 	GPIO_PIN_CAP,
2095224f277Smatt 	/* PIN 53 */
2105224f277Smatt 	GPIO_PIN_CAP,
2115224f277Smatt 	/* PIN 54 */
2125224f277Smatt 	GPIO_PIN_CAP,
2135224f277Smatt 	/* PIN 55 */
2145224f277Smatt 	GPIO_PIN_CAP,
2155224f277Smatt 	/* PIN 56 */
2165224f277Smatt 	GPIO_PIN_CAP,
2175224f277Smatt 	/* PIN 57 */
2185224f277Smatt 	GPIO_PIN_CAP,
2195224f277Smatt 	/* PIN 58 */
2205224f277Smatt 	GPIO_PIN_CAP,
2215224f277Smatt 	/* PIN 59 */
2225224f277Smatt 	GPIO_PIN_CAP,
2235224f277Smatt 	/* PIN 60 */
2245224f277Smatt 	GPIO_PIN_CAP,
2255224f277Smatt 	/* PIN 61 */
2265224f277Smatt 	GPIO_PIN_CAP,
2275224f277Smatt 	/* PIN 62 */
2285224f277Smatt 	GPIO_PIN_CAP,
2295224f277Smatt 	/* PIN 63 */
2305224f277Smatt 	0,		/* Reserved. */
2315224f277Smatt 	/*
2325224f277Smatt 	 * HW_PINCTRL_MUXSEL4
2335224f277Smatt 	 */
2345224f277Smatt 	/* PIN 64 */
2355224f277Smatt 	GPIO_PIN_CAP,
2365224f277Smatt 	/* PIN 65 */
2375224f277Smatt 	GPIO_PIN_CAP,
2385224f277Smatt 	/* PIN 66 */
2395224f277Smatt 	GPIO_PIN_CAP,
2405224f277Smatt 	/* PIN 67 */
2415224f277Smatt 	GPIO_PIN_CAP,
2425224f277Smatt 	/* PIN 68 */
2435224f277Smatt 	GPIO_PIN_CAP,
2445224f277Smatt 	/* PIN 69 */
2455224f277Smatt 	GPIO_PIN_CAP,
2465224f277Smatt 	/* PIN 70 */
2475224f277Smatt 	GPIO_PIN_CAP,
2485224f277Smatt 	/* PIN 71 */
2495224f277Smatt 	GPIO_PIN_CAP,
2505224f277Smatt 	/* PIN 72 */
2515224f277Smatt 	GPIO_PIN_CAP,
2525224f277Smatt 	/* PIN 73 */
2535224f277Smatt 	0,		/* From this on reserved for EMI (DRAM) pins. */
2545224f277Smatt 	/* PIN 74 */
2555224f277Smatt 	0,
2565224f277Smatt 	/* PIN 75 */
2575224f277Smatt 	0,
2585224f277Smatt 	/* PIN 76 */
2595224f277Smatt 	0,
2605224f277Smatt 	/* PIN 77 */
2615224f277Smatt 	0,
2625224f277Smatt 	/* PIN 78 */
2635224f277Smatt 	0,
2645224f277Smatt 	/* PIN 79 */
2655224f277Smatt 	0,
2665224f277Smatt 	/*
2675224f277Smatt 	 * HW_PINCTRL_MUXSEL5
2685224f277Smatt 	 */
2695224f277Smatt 	/* PIN 80 */
2705224f277Smatt 	0,
2715224f277Smatt 	/* PIN 81 */
2725224f277Smatt 	0,
2735224f277Smatt 	/* PIN 82 */
2745224f277Smatt 	0,
2755224f277Smatt 	/* PIN 83 */
2765224f277Smatt 	0,
2775224f277Smatt 	/* PIN 84 */
2785224f277Smatt 	0,
2795224f277Smatt 	/* PIN 85 */
2805224f277Smatt 	0,
2815224f277Smatt 	/* PIN 86 */
2825224f277Smatt 	0,
2835224f277Smatt 	/* PIN 87 */
2845224f277Smatt 	0,
2855224f277Smatt 	/* PIN 88 */
2865224f277Smatt 	0,
2875224f277Smatt 	/* PIN 89 */
2885224f277Smatt 	0,
2895224f277Smatt 	/* PIN 90 */
2905224f277Smatt 	0,
2915224f277Smatt 	/* PIN 91 */
2925224f277Smatt 	0,
2935224f277Smatt 	/* PIN 92 */
2945224f277Smatt 	0,
2955224f277Smatt 	/* PIN 93 */
2965224f277Smatt 	0,
2975224f277Smatt 	/* PIN 94 */
2985224f277Smatt 	0,
2995224f277Smatt 	/* PIN 95 */
3005224f277Smatt 	0
3015224f277Smatt };
3025224f277Smatt 
3035224f277Smatt #define PINCTRL_RD(sc, reg)						\
3045224f277Smatt 	bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
3055224f277Smatt #define PINCTRL_WR(sc, reg, val)					\
3065224f277Smatt 	bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
3075224f277Smatt 
3085224f277Smatt /*
3095224f277Smatt  * Macros to map pin numbers to registers and bit fields.
3105224f277Smatt  */
3115224f277Smatt #define MUXSEL_REG_SIZE	0x10
3125224f277Smatt #define PIN2MUXSEL_REG(pin)						\
3135224f277Smatt 	((pin / 16) * MUXSEL_REG_SIZE + HW_PINCTRL_MUXSEL0)
3145224f277Smatt #define PIN2MUXSEL_SET_REG(pin)						\
3155224f277Smatt 	((pin / 16) * MUXSEL_REG_SIZE + HW_PINCTRL_MUXSEL0_SET)
3165224f277Smatt #define PIN2MUXSEL_CLR_REG(pin)						\
3175224f277Smatt 	((pin / 16) * MUXSEL_REG_SIZE + HW_PINCTRL_MUXSEL0_CLR)
3185224f277Smatt #define PIN2MUXSEL_MASK(pin)	(3<<(pin % 16 * 2))
3195224f277Smatt 
3205224f277Smatt #define DRIVE_REG_SIZE	0x10
3215224f277Smatt #define PIN2DRIVE_REG(pin)						\
3225224f277Smatt 	((pin / 8) * DRIVE_REG_SIZE + HW_PINCTRL_DRIVE0)
3235224f277Smatt #define PIN2DRIVE_SET_REG(pin)						\
3245224f277Smatt 	((pin / 8) * DRIVE_REG_SIZE + HW_PINCTRL_DRIVE0_SET)
3255224f277Smatt #define PIN2DRIVE_CLR_REG(pin)						\
3265224f277Smatt 	((pin / 8) * DRIVE_REG_SIZE + HW_PINCTRL_DRIVE0_CLR)
3275224f277Smatt #define PIN2DRIVE_MASK(pin)	(3<<(pin % 8 * 4))
3285224f277Smatt 
3295224f277Smatt #define PULL_REG_SIZE	0x10
3305224f277Smatt #define PIN2PULL_REG(pin)						\
3315224f277Smatt 	((pin / 32) * PULL_REG_SIZE + HW_PINCTRL_PULL0)
3325224f277Smatt #define PIN2PULL_SET_REG(pin)						\
3335224f277Smatt 	((pin / 32) * PULL_REG_SIZE + HW_PINCTRL_PULL0_SET)
3345224f277Smatt #define PIN2PULL_CLR_REG(pin)						\
3355224f277Smatt 	((pin / 32) * PULL_REG_SIZE + HW_PINCTRL_PULL0_CLR)
3365224f277Smatt #define PIN2PULL_MASK(pin)	(1<<(pin % 32))
3375224f277Smatt 
3385224f277Smatt #define DOUT_REG_SIZE	0x10
3395224f277Smatt #define PIN2DOUT_REG(pin)						\
3405224f277Smatt 	((pin / 32) * DOUT_REG_SIZE + HW_PINCTRL_DOUT0)
3415224f277Smatt #define PIN2DOUT_SET_REG(pin)						\
3425224f277Smatt 	((pin / 32) * DOUT_REG_SIZE + HW_PINCTRL_DOUT0_SET)
3435224f277Smatt #define PIN2DOUT_CLR_REG(pin)						\
3445224f277Smatt 	((pin / 32) * DOUT_REG_SIZE + HW_PINCTRL_DOUT0_CLR)
3455224f277Smatt #define PIN2DOUT_MASK(pin)	(1<<(pin % 32))
3465224f277Smatt 
3475224f277Smatt #define DIN_REG_SIZE	0x10
3485224f277Smatt #define PIN2DIN_REG(pin)	((pin / 32) * DIN_REG_SIZE + HW_PINCTRL_DIN0)
3495224f277Smatt #define PIN2DIN_MASK(pin)	(1<<(pin % 32))
3505224f277Smatt 
3515224f277Smatt #define DOE_REG_SIZE	0x10
3525224f277Smatt #define PIN2DOE_REG(pin)						\
3535224f277Smatt 	((pin / 32) * DOE_REG_SIZE + HW_PINCTRL_DOE0)
3545224f277Smatt #define PIN2DOE_SET_REG(pin)						\
3555224f277Smatt 	((pin / 32) * DOE_REG_SIZE + HW_PINCTRL_DOE0_SET)
3565224f277Smatt #define PIN2DOE_CLR_REG(pin)						\
3575224f277Smatt 	((pin / 32) * DOE_REG_SIZE + HW_PINCTRL_DOE0_CLR)
3585224f277Smatt #define PIN2DOE_MASK(pin)	(1<<(pin % 32))
3595224f277Smatt 
3605224f277Smatt #define DRIVE_STRENGTH_4MA	0
3615224f277Smatt #define DRIVE_STRENGTH_8MA	1
3625224f277Smatt #define DRIVE_STRENGTH_12MA	2
3635224f277Smatt 
3645224f277Smatt #define MUXEL_GPIO_MODE	3
3655224f277Smatt 
3665224f277Smatt #define PINCTRL_SOFT_RST_LOOP 455 /* At least 1 us ... */
3675224f277Smatt 
3685224f277Smatt static int
imx23_pinctrl_match(device_t parent,cfdata_t match,void * aux)369aa56c0c1Sskrll imx23_pinctrl_match(device_t parent, cfdata_t match, void *aux)
3705224f277Smatt {
3715224f277Smatt 	struct apb_attach_args *aa = aux;
3725224f277Smatt 
3735224f277Smatt 	if ((aa->aa_addr == HW_PINCTRL_BASE) &&
3745224f277Smatt 	    (aa->aa_size == HW_PINCTRL_SIZE))
3755224f277Smatt 		return 1;
3765224f277Smatt 
3775224f277Smatt 	return 0;
3785224f277Smatt }
3795224f277Smatt 
3805224f277Smatt static void
imx23_pinctrl_attach(device_t parent,device_t self,void * aux)381aa56c0c1Sskrll imx23_pinctrl_attach(device_t parent, device_t self, void *aux)
3825224f277Smatt {
383aa56c0c1Sskrll 	struct imx23_pinctrl_softc *sc = device_private(self);
3845224f277Smatt 	struct apb_attach_args *aa = aux;
385aa56c0c1Sskrll 	static int imx23_pinctrl_attached = 0;
3865224f277Smatt 
3875224f277Smatt 	sc->sc_dev = self;
3885224f277Smatt 	sc->sc_iot = aa->aa_iot;
3895224f277Smatt 
390aa56c0c1Sskrll 	if (imx23_pinctrl_attached) {
3915224f277Smatt 		aprint_error_dev(sc->sc_dev, "already attached\n");
3925224f277Smatt 		return;
3935224f277Smatt 	}
3945224f277Smatt 
3955224f277Smatt 	if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0,
396aa56c0c1Sskrll 	    &sc->sc_hdl)) {
3975224f277Smatt 		aprint_error_dev(sc->sc_dev, "Unable to map bus space\n");
3985224f277Smatt 		return;
3995224f277Smatt 	}
4005224f277Smatt 
4015224f277Smatt #if notyet
402aa56c0c1Sskrll 	imx23_pinctrl_reset(sc);
4035224f277Smatt #endif
4045224f277Smatt 
405aa56c0c1Sskrll 	imx23_pinctrl_init(sc);
4065224f277Smatt 
4075224f277Smatt 	aprint_normal(": PIN MUX & GPIO\n");
4085224f277Smatt 
4095224f277Smatt 	/* Set pin capabilities. */
4105224f277Smatt 	int i;
4115224f277Smatt 	for(i = 0; i < GPIO_PINS; i++) {
4125224f277Smatt 		sc->pins[i].pin_caps = pin_caps[i];
4135224f277Smatt 	}
4145224f277Smatt 
415aa56c0c1Sskrll 	imx23_pinctrl_attached = 1;
4165224f277Smatt 
4175224f277Smatt 	sc->gc.gp_cookie = sc;
418aa56c0c1Sskrll 	sc->gc.gp_gc_open = imx23_pinctrl_gp_gc_open;
419aa56c0c1Sskrll 	sc->gc.gp_gc_close = imx23_pinctrl_gp_gc_close;
420aa56c0c1Sskrll 	sc->gc.gp_pin_read = imx23_pinctrl_gp_pin_read;
421aa56c0c1Sskrll 	sc->gc.gp_pin_write = imx23_pinctrl_gp_pin_write;
422aa56c0c1Sskrll 	sc->gc.gp_pin_ctl = imx23_pinctrl_gp_pin_ctl;
4235224f277Smatt 
4245224f277Smatt 	struct gpiobus_attach_args gpiobus_aa;
4255224f277Smatt 	gpiobus_aa.gba_gc = &sc->gc;
4265224f277Smatt 	gpiobus_aa.gba_npins = GPIO_PINS;
4275224f277Smatt 	gpiobus_aa.gba_pins = sc->pins;
4285224f277Smatt 
429*beecddb6Sthorpej 	config_found(self, &gpiobus_aa, gpiobus_print, CFARGS_NONE);
4305224f277Smatt 
4315224f277Smatt 	return;
4325224f277Smatt }
4335224f277Smatt 
4345224f277Smatt static int
imx23_pinctrl_activate(device_t self,enum devact act)435aa56c0c1Sskrll imx23_pinctrl_activate(device_t self, enum devact act)
4365224f277Smatt {
4375224f277Smatt 
4385224f277Smatt 	return EOPNOTSUPP;
4395224f277Smatt }
4405224f277Smatt 
4415224f277Smatt static void
imx23_pinctrl_init(struct imx23_pinctrl_softc * sc)442aa56c0c1Sskrll imx23_pinctrl_init(struct imx23_pinctrl_softc *sc)
4435224f277Smatt {
4445224f277Smatt 	_sc = sc;
4455224f277Smatt 	return;
4465224f277Smatt }
4475224f277Smatt 
4485224f277Smatt #if notyet
4495224f277Smatt /*
4505224f277Smatt  * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
4515224f277Smatt  */
4525224f277Smatt static void
imx23_pinctrl_reset(struct imx23_pinctrl_softc * sc)453aa56c0c1Sskrll imx23_pinctrl_reset(struct imx23_pinctrl_softc *sc)
4545224f277Smatt {
4555224f277Smatt         unsigned int loop;
4565224f277Smatt 
4575224f277Smatt         /* Prepare for soft-reset by making sure that SFTRST is not currently
4585224f277Smatt          * asserted. Also clear CLKGATE so we can wait for its assertion below.
4595224f277Smatt          */
4605224f277Smatt         PINCTRL_WR(sc, HW_PINCTRL_CTRL_CLR, HW_PINCTRL_CTRL_SFTRST);
4615224f277Smatt 
4625224f277Smatt         /* Wait at least a microsecond for SFTRST to deassert. */
4635224f277Smatt         loop = 0;
4645224f277Smatt         while ((PINCTRL_RD(sc, HW_PINCTRL_CTRL) & HW_PINCTRL_CTRL_SFTRST) ||
4655224f277Smatt             (loop < PINCTRL_SOFT_RST_LOOP))
4665224f277Smatt                 loop++;
4675224f277Smatt 
4685224f277Smatt         /* Clear CLKGATE so we can wait for its assertion below. */
4695224f277Smatt         PINCTRL_WR(sc, HW_PINCTRL_CTRL_CLR, HW_PINCTRL_CTRL_CLKGATE);
4705224f277Smatt 
4715224f277Smatt         /* Soft-reset the block. */
4725224f277Smatt         PINCTRL_WR(sc, HW_PINCTRL_CTRL_SET, HW_PINCTRL_CTRL_SFTRST);
4735224f277Smatt 
4745224f277Smatt         /* Wait until clock is in the gated state. */
4755224f277Smatt         while (!(PINCTRL_RD(sc, HW_PINCTRL_CTRL) & HW_PINCTRL_CTRL_CLKGATE));
4765224f277Smatt 
4775224f277Smatt         /* Bring block out of reset. */
4785224f277Smatt         PINCTRL_WR(sc, HW_PINCTRL_CTRL_CLR, HW_PINCTRL_CTRL_SFTRST);
4795224f277Smatt 
4805224f277Smatt         loop = 0;
4815224f277Smatt         while ((PINCTRL_RD(sc, HW_PINCTRL_CTRL) & HW_PINCTRL_CTRL_SFTRST) ||
4825224f277Smatt             (loop < PINCTRL_SOFT_RST_LOOP))
4835224f277Smatt                 loop++;
4845224f277Smatt 
4855224f277Smatt         PINCTRL_WR(sc, HW_PINCTRL_CTRL_CLR, HW_PINCTRL_CTRL_CLKGATE);
4865224f277Smatt 
4875224f277Smatt         /* Wait until clock is in the NON-gated state. */
4885224f277Smatt         while (PINCTRL_RD(sc, HW_PINCTRL_CTRL) & HW_PINCTRL_CTRL_CLKGATE);
4895224f277Smatt 
4905224f277Smatt         return;
4915224f277Smatt }
4925224f277Smatt #endif
4935224f277Smatt 
4945224f277Smatt /*
4955224f277Smatt  * Enable external USB transceiver/HUB.
4965224f277Smatt  *
4975224f277Smatt  * PIN18/LCD_D17/USB_EN controls reset line of external USB chip on MINI and
4985224f277Smatt  * MAXI boards. We configure this pin to logic 1.
4995224f277Smatt  */
5005224f277Smatt void
imx23_pinctrl_en_usb(void)501aa56c0c1Sskrll imx23_pinctrl_en_usb(void)
5025224f277Smatt {
503aa56c0c1Sskrll 	struct imx23_pinctrl_softc *sc = _sc;
5045224f277Smatt 
5055224f277Smatt         if (sc == NULL) {
506aa56c0c1Sskrll                 aprint_error("imx23_pinctrl is not initialized");
5075224f277Smatt                 return;
5085224f277Smatt         }
5095224f277Smatt 
510aa56c0c1Sskrll 	imx23_pinctrl_gp_pin_ctl(sc, 17, GPIO_PIN_OUTPUT);
5115224f277Smatt 	delay(1000);
512aa56c0c1Sskrll 	imx23_pinctrl_gp_pin_write(sc, 17, 1);
5135224f277Smatt 
5145224f277Smatt 	return;
5155224f277Smatt }
5165224f277Smatt 
5175224f277Smatt static	int
imx23_pinctrl_gp_gc_open(void * cookie,device_t dev)518aa56c0c1Sskrll imx23_pinctrl_gp_gc_open(void *cookie, device_t dev)
5195224f277Smatt {
5205224f277Smatt 	return 0;
5215224f277Smatt }
5225224f277Smatt 
5235224f277Smatt static	void
imx23_pinctrl_gp_gc_close(void * cookie,device_t dev)524aa56c0c1Sskrll imx23_pinctrl_gp_gc_close(void *cookie, device_t dev)
5255224f277Smatt {
5265224f277Smatt 	return;
5275224f277Smatt }
5285224f277Smatt 
5295224f277Smatt static	int
imx23_pinctrl_gp_pin_read(void * cookie,int pin)530aa56c0c1Sskrll imx23_pinctrl_gp_pin_read(void *cookie, int pin)
5315224f277Smatt {
5325224f277Smatt 	int value;
533aa56c0c1Sskrll 	imx23_pinctrl_softc_t sc = (imx23_pinctrl_softc_t) cookie;
5345224f277Smatt 
5355224f277Smatt 	if (PINCTRL_RD(sc, PIN2DIN_REG(pin)) & PIN2DIN_MASK(pin))
5365224f277Smatt 		value = 1;
5375224f277Smatt 	else
5385224f277Smatt 		value = 0;
5395224f277Smatt 
5405224f277Smatt 	return value;
5415224f277Smatt }
5425224f277Smatt 
5435224f277Smatt static	void
imx23_pinctrl_gp_pin_write(void * cookie,int pin,int value)544aa56c0c1Sskrll imx23_pinctrl_gp_pin_write(void *cookie, int pin, int value)
5455224f277Smatt {
546aa56c0c1Sskrll 	imx23_pinctrl_softc_t sc = (imx23_pinctrl_softc_t) cookie;
5475224f277Smatt 
5485224f277Smatt 	if (value)
5495224f277Smatt 		PINCTRL_WR(sc, PIN2DOUT_SET_REG(pin), PIN2DOUT_MASK(pin));
5505224f277Smatt 	else
5515224f277Smatt 		PINCTRL_WR(sc, PIN2DOUT_CLR_REG(pin), PIN2DOUT_MASK(pin));
5525224f277Smatt 
5535224f277Smatt 	return;
5545224f277Smatt }
5555224f277Smatt 
5565224f277Smatt /*
5575224f277Smatt  * Configure pin as requested in flags.
5585224f277Smatt  */
5595224f277Smatt static	void
imx23_pinctrl_gp_pin_ctl(void * cookie,int pin,int flags)560aa56c0c1Sskrll imx23_pinctrl_gp_pin_ctl(void *cookie, int pin, int flags)
5615224f277Smatt {
562aa56c0c1Sskrll 	imx23_pinctrl_softc_t sc = (imx23_pinctrl_softc_t) cookie;
5635224f277Smatt 	uint32_t tmpr;
5645224f277Smatt 
5655224f277Smatt 	/* Enable GPIO pin. */
5665224f277Smatt 	tmpr = PINCTRL_RD(sc, PIN2MUXSEL_REG(pin));
5675224f277Smatt 	tmpr &= ~PIN2MUXSEL_MASK(pin);
5685224f277Smatt 	tmpr |= __SHIFTIN(MUXEL_GPIO_MODE, PIN2MUXSEL_MASK(pin));
5695224f277Smatt 	PINCTRL_WR(sc, PIN2MUXSEL_REG(pin), tmpr);
5705224f277Smatt 
5715224f277Smatt 	/* Configure pin drive strength. */
5725224f277Smatt 	tmpr = PINCTRL_RD(sc, PIN2DRIVE_REG(pin));
5735224f277Smatt 	tmpr &= ~PIN2DRIVE_MASK(pin);
5745224f277Smatt 	tmpr |= __SHIFTIN(DRIVE_STRENGTH_4MA, PIN2DRIVE_MASK(pin));
5755224f277Smatt 	PINCTRL_WR(sc, PIN2DRIVE_REG(pin), tmpr);
5765224f277Smatt 
5775224f277Smatt 	if ((flags & (GPIO_PIN_OUTPUT | GPIO_PIN_INOUT))) {
5785224f277Smatt 		/* Configure pullup resistor or gate keeper. */
5795224f277Smatt 		if (flags & GPIO_PIN_PULLUP)
5805224f277Smatt 			PINCTRL_WR(sc, PIN2PULL_SET_REG(pin),
5815224f277Smatt 				PIN2PULL_MASK(pin));
5825224f277Smatt 		else
5835224f277Smatt 			PINCTRL_WR(sc, PIN2PULL_CLR_REG(pin),
5845224f277Smatt 				PIN2PULL_MASK(pin));
5855224f277Smatt 
5865224f277Smatt 		/* Set initial pin value to logic zero. */
5875224f277Smatt 		PINCTRL_WR(sc, PIN2DOUT_CLR_REG(pin), PIN2DOUT_MASK(pin));
5885224f277Smatt 
5895224f277Smatt 		/* Enable pin output. */
5905224f277Smatt 		PINCTRL_WR(sc, PIN2DOE_SET_REG(pin), PIN2DOE_MASK(pin));
5915224f277Smatt 	}
5925224f277Smatt 
5935224f277Smatt 	if (flags & GPIO_PIN_INPUT) {
5945224f277Smatt 		/* Disable pin output. */
5955224f277Smatt 		PINCTRL_WR(sc, PIN2DOE_CLR_REG(pin), PIN2DOE_MASK(pin));
5965224f277Smatt 
5975224f277Smatt 		/* Configure pullup resistor or gate keeper. */
5985224f277Smatt 		if (flags & GPIO_PIN_PULLUP)
5995224f277Smatt 			PINCTRL_WR(sc, PIN2PULL_SET_REG(pin),
6005224f277Smatt 				PIN2PULL_MASK(pin));
6015224f277Smatt 		else
6025224f277Smatt 			PINCTRL_WR(sc, PIN2PULL_CLR_REG(pin),
6035224f277Smatt 				PIN2PULL_MASK(pin));
6045224f277Smatt 	}
6055224f277Smatt 
6065224f277Smatt 	return;
6075224f277Smatt }
608