Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /*
0002  * Copyright (c) 2010
0003  *  Ben Gray <ben.r.gray@gmail.com>.
0004  * All rights reserved.
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  * 3. All advertising materials mentioning features or use of this software
0015  *    must display the following acknowledgement:
0016  *  This product includes software developed by Ben Gray.
0017  * 4. The name of the company nor the name of the author may be used to
0018  *    endorse or promote products derived from this software without specific
0019  *    prior written permission.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
0022  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0023  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0024  * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0025  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
0027  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0028  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0029  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
0030  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0031  */
0032 
0033 /**
0034  * Exposes pinmux module to pinctrl-compatible interface
0035  */
0036 #include <sys/cdefs.h>
0037 #ifndef __rtems__
0038 __FBSDID("$FreeBSD$");
0039 #endif /* __rtems__ */
0040 
0041 #include <sys/param.h>
0042 #ifndef __rtems__
0043 #include <sys/systm.h>
0044 #include <sys/kernel.h>
0045 #include <sys/module.h>
0046 #include <sys/bus.h>
0047 #include <sys/resource.h>
0048 #include <sys/rman.h>
0049 #include <sys/lock.h>
0050 #include <sys/mutex.h>
0051 
0052 #include <machine/bus.h>
0053 #include <machine/resource.h>
0054 
0055 #include <dev/ofw/openfirm.h>
0056 #include <dev/ofw/ofw_bus.h>
0057 #include <dev/ofw/ofw_bus_subr.h>
0058 #include <dev/fdt/fdt_pinctrl.h>
0059 
0060 #include <arm/ti/omap4/omap4_scm_padconf.h>
0061 #else /* __rtems__ */
0062 #include <ofw/ofw_compat.h>
0063 #endif /* __rtems__ */
0064 #include <arm/ti/am335x/am335x_scm_padconf.h>
0065 #include <arm/ti/ti_cpuid.h>
0066 #ifndef __rtems__
0067 #include "ti_pinmux.h"
0068 #else /* __rtems__ */
0069 #include <stdio.h>
0070 #include <string.h>
0071 #include <errno.h>
0072 #include <libfdt.h>
0073 #include <rtems/bspIo.h>
0074 #include <rtems/sysinit.h>
0075 #include <arm/ti/ti_pinmux.h>
0076 #endif /* __rtems__ */
0077 
0078 struct pincfg {
0079     uint32_t reg;
0080     uint32_t conf;
0081 };
0082 
0083 #ifndef __rtems__
0084 static struct resource_spec ti_pinmux_res_spec[] = {
0085     { SYS_RES_MEMORY,   0,  RF_ACTIVE },    /* Control memory window */
0086     { -1, 0 }
0087 };
0088 #endif /* __rtems__ */
0089 
0090 #ifdef __rtems__
0091 struct ti_pinmux_softc {
0092 #ifndef __rtems__
0093     device_t        sc_dev;
0094     struct resource *   sc_res[4];
0095     bus_space_tag_t     sc_bst;
0096     bus_space_handle_t  sc_bsh;
0097 #else /* __rtems__ */
0098     int         sc_bst;
0099     uintptr_t       sc_bsh;
0100 #endif /* __rtems__ */
0101 };
0102 #endif /* __rtems__ */
0103 
0104 static struct ti_pinmux_softc *ti_pinmux_sc;
0105 
0106 #ifndef __rtems__
0107 #define ti_pinmux_read_2(sc, reg)       \
0108     bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg))
0109 #define ti_pinmux_write_2(sc, reg, val)     \
0110     bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
0111 #define ti_pinmux_read_4(sc, reg)       \
0112     bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
0113 #define ti_pinmux_write_4(sc, reg, val)     \
0114     bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
0115 #else /* __rtems__ */
0116 static uint16_t
0117 ti_pinmux_read_2(struct ti_pinmux_softc *sc, uintptr_t ofs) {
0118     uintptr_t bsh = sc->sc_bsh;
0119     return *(uint16_t volatile *)(bsh + ofs);
0120 }
0121 static void
0122 ti_pinmux_write_2(struct ti_pinmux_softc *sc, uintptr_t ofs, uint16_t val) {
0123     uintptr_t bsh = sc->sc_bsh;
0124     uint16_t volatile *bsp = (uint16_t volatile *)(bsh + ofs);
0125     *bsp = val;
0126 }
0127 #endif /* __rtems__ */
0128 
0129 
0130 /**
0131  *  ti_padconf_devmap - Array of pins, should be defined one per SoC
0132  *
0133  *  This array is typically defined in one of the targeted *_scm_pinumx.c
0134  *  files and is specific to the given SoC platform. Each entry in the array
0135  *  corresponds to an individual pin.
0136  */
0137 static const struct ti_pinmux_device *ti_pinmux_dev;
0138 
0139 
0140 /**
0141  *  ti_pinmux_padconf_from_name - searches the list of pads and returns entry
0142  *                               with matching ball name.
0143  *  @ballname: the name of the ball
0144  *
0145  *  RETURNS:
0146  *  A pointer to the matching padconf or NULL if the ball wasn't found.
0147  */
0148 static const struct ti_pinmux_padconf*
0149 ti_pinmux_padconf_from_name(const char *ballname)
0150 {
0151     const struct ti_pinmux_padconf *padconf;
0152 
0153     padconf = ti_pinmux_dev->padconf;
0154     while (padconf->ballname != NULL) {
0155         if (strcmp(ballname, padconf->ballname) == 0)
0156             return(padconf);
0157         padconf++;
0158     }
0159 
0160     return (NULL);
0161 }
0162 
0163 /**
0164  *  ti_pinmux_padconf_set_internal - sets the muxmode and state for a pad/pin
0165  *  @padconf: pointer to the pad structure
0166  *  @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
0167  *  @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
0168  *
0169  *
0170  *  LOCKING:
0171  *  Internally locks it's own context.
0172  *
0173  *  RETURNS:
0174  *  0 on success.
0175  *  EINVAL if pin requested is outside valid range or already in use.
0176  */
0177 static int
0178 ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc,
0179     const struct ti_pinmux_padconf *padconf,
0180     const char *muxmode, unsigned int state)
0181 {
0182     unsigned int mode;
0183     uint16_t reg_val;
0184 
0185     /* populate the new value for the PADCONF register */
0186     reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
0187 
0188     /* find the new mode requested */
0189     for (mode = 0; mode < 8; mode++) {
0190         if ((padconf->muxmodes[mode] != NULL) &&
0191             (strcmp(padconf->muxmodes[mode], muxmode) == 0)) {
0192             break;
0193         }
0194     }
0195 
0196     /* couldn't find the mux mode */
0197     if (mode >= 8) {
0198 #ifndef __rtems__
0199         printf("Invalid mode \"%s\"\n", muxmode);
0200 #else /* __rtems__ */
0201         printk("Invalid mode \"%s\"\n", muxmode);
0202 #endif /* __rtems__ */
0203         return (EINVAL);
0204     }
0205 
0206     /* set the mux mode */
0207     reg_val |= (uint16_t)(mode & ti_pinmux_dev->padconf_muxmode_mask);
0208 
0209 #ifndef __rtems__
0210     if (bootverbose)
0211         device_printf(sc->sc_dev, "setting internal %x for %s\n",
0212             reg_val, muxmode);
0213 #endif /* __rtems__ */
0214     /* write the register value (16-bit writes) */
0215     ti_pinmux_write_2(sc, padconf->reg_off, reg_val);
0216 
0217     return (0);
0218 }
0219 
0220 /**
0221  *  ti_pinmux_padconf_set - sets the muxmode and state for a pad/pin
0222  *  @padname: the name of the pad, i.e. "c12"
0223  *  @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
0224  *  @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
0225  *
0226  *
0227  *  LOCKING:
0228  *  Internally locks it's own context.
0229  *
0230  *  RETURNS:
0231  *  0 on success.
0232  *  EINVAL if pin requested is outside valid range or already in use.
0233  */
0234 int
0235 ti_pinmux_padconf_set(const char *padname, const char *muxmode, unsigned int state)
0236 {
0237     const struct ti_pinmux_padconf *padconf;
0238 
0239     if (!ti_pinmux_sc)
0240         return (ENXIO);
0241 
0242     /* find the pin in the devmap */
0243     padconf = ti_pinmux_padconf_from_name(padname);
0244     if (padconf == NULL)
0245         return (EINVAL);
0246 
0247     return (ti_pinmux_padconf_set_internal(ti_pinmux_sc, padconf, muxmode, state));
0248 }
0249 
0250 /**
0251  *  ti_pinmux_padconf_get - gets the muxmode and state for a pad/pin
0252  *  @padname: the name of the pad, i.e. "c12"
0253  *  @muxmode: upon return will contain the name of the muxmode of the pin
0254  *  @state: upon return will contain the state of the pad/pin
0255  *
0256  *
0257  *  LOCKING:
0258  *  Internally locks it's own context.
0259  *
0260  *  RETURNS:
0261  *  0 on success.
0262  *  EINVAL if pin requested is outside valid range or already in use.
0263  */
0264 int
0265 ti_pinmux_padconf_get(const char *padname, const char **muxmode,
0266     unsigned int *state)
0267 {
0268     const struct ti_pinmux_padconf *padconf;
0269     uint16_t reg_val;
0270 
0271     if (!ti_pinmux_sc)
0272         return (ENXIO);
0273 
0274     /* find the pin in the devmap */
0275     padconf = ti_pinmux_padconf_from_name(padname);
0276     if (padconf == NULL)
0277         return (EINVAL);
0278 
0279     /* read the register value (16-bit reads) */
0280     reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off);
0281 
0282     /* save the state */
0283     if (state)
0284         *state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
0285 
0286     /* save the mode */
0287     if (muxmode)
0288         *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev->padconf_muxmode_mask)];
0289 
0290     return (0);
0291 }
0292 
0293 /**
0294  *  ti_pinmux_padconf_set_gpiomode - converts a pad to GPIO mode.
0295  *  @gpio: the GPIO pin number (0-195)
0296  *  @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
0297  *
0298  *
0299  *
0300  *  LOCKING:
0301  *  Internally locks it's own context.
0302  *
0303  *  RETURNS:
0304  *  0 on success.
0305  *  EINVAL if pin requested is outside valid range or already in use.
0306  */
0307 int
0308 ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
0309 {
0310     const struct ti_pinmux_padconf *padconf;
0311     uint16_t reg_val;
0312 
0313     if (!ti_pinmux_sc)
0314         return (ENXIO);
0315 
0316     /* find the gpio pin in the padconf array */
0317     padconf = ti_pinmux_dev->padconf;
0318     while (padconf->ballname != NULL) {
0319         if (padconf->gpio_pin == gpio)
0320             break;
0321         padconf++;
0322     }
0323     if (padconf->ballname == NULL)
0324         return (EINVAL);
0325 
0326     /* populate the new value for the PADCONF register */
0327     reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
0328 
0329     /* set the mux mode */
0330     reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev->padconf_muxmode_mask);
0331 
0332     /* write the register value (16-bit writes) */
0333     ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val);
0334 
0335     return (0);
0336 }
0337 
0338 /**
0339  *  ti_pinmux_padconf_get_gpiomode - gets the current GPIO mode of the pin
0340  *  @gpio: the GPIO pin number (0-195)
0341  *  @state: upon return will contain the state
0342  *
0343  *
0344  *
0345  *  LOCKING:
0346  *  Internally locks it's own context.
0347  *
0348  *  RETURNS:
0349  *  0 on success.
0350  *  EINVAL if pin requested is outside valid range or not configured as GPIO.
0351  */
0352 int
0353 ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
0354 {
0355     const struct ti_pinmux_padconf *padconf;
0356     uint16_t reg_val;
0357 
0358     if (!ti_pinmux_sc)
0359         return (ENXIO);
0360 
0361     /* find the gpio pin in the padconf array */
0362     padconf = ti_pinmux_dev->padconf;
0363     while (padconf->ballname != NULL) {
0364         if (padconf->gpio_pin == gpio)
0365             break;
0366         padconf++;
0367     }
0368     if (padconf->ballname == NULL)
0369         return (EINVAL);
0370 
0371     /* read the current register settings */
0372     reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off);
0373 
0374     /* check to make sure the pins is configured as GPIO in the first state */
0375     if ((reg_val & ti_pinmux_dev->padconf_muxmode_mask) != padconf->gpio_mode)
0376         return (EINVAL);
0377 
0378     /* read and store the reset of the state, i.e. pull-up, pull-down, etc */
0379     if (state)
0380         *state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
0381 
0382     return (0);
0383 }
0384 
0385 static int
0386 #ifndef __rtems__
0387 ti_pinmux_configure_pins(device_t dev, phandle_t cfgxref)
0388 #else /* __rtems__ */
0389 ti_pinmux_configure_pins(struct ti_pinmux_softc *sc, phandle_t cfgxref)
0390 #endif /* __rtems__ */
0391 {
0392     struct pincfg *cfgtuples, *cfg;
0393     phandle_t cfgnode;
0394     int i, ntuples;
0395 #ifndef __rtems__
0396     static struct ti_pinmux_softc *sc;
0397 
0398     sc = device_get_softc(dev);
0399 #endif /* __rtems__ */
0400     cfgnode = OF_node_from_xref(cfgxref);
0401     ntuples = OF_getencprop_alloc_multi(cfgnode, "pinctrl-single,pins",
0402         sizeof(*cfgtuples), (void **)&cfgtuples);
0403 
0404     if (ntuples < 0)
0405         return (ENOENT);
0406 
0407     if (ntuples == 0)
0408         return (0); /* Empty property is not an error. */
0409 
0410     for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) {
0411 #ifndef __rtems__
0412         if (bootverbose) {
0413             char name[32];
0414             OF_getprop(cfgnode, "name", &name, sizeof(name));
0415             printf("%16s: muxreg 0x%04x muxval 0x%02x\n",
0416                 name, cfg->reg, cfg->conf);
0417         }
0418 #endif /* __rtems__ */
0419 
0420         /* write the register value (16-bit writes) */
0421         ti_pinmux_write_2(sc, cfg->reg, cfg->conf);
0422     }
0423 
0424     OF_prop_free(cfgtuples);
0425 
0426     return (0);
0427 }
0428 
0429 /*
0430  * Device part of OMAP SCM driver
0431  */
0432 
0433 #ifndef __rtems__
0434 static int
0435 ti_pinmux_probe(device_t dev)
0436 {
0437     if (!ofw_bus_status_okay(dev))
0438         return (ENXIO);
0439 
0440     if (!ofw_bus_is_compatible(dev, "pinctrl-single"))
0441         return (ENXIO);
0442 
0443     if (ti_pinmux_sc) {
0444         printf("%s: multiple pinctrl modules in device tree data, ignoring\n",
0445             __func__);
0446         return (EEXIST);
0447     }
0448     switch (ti_chip()) {
0449 #ifdef SOC_OMAP4
0450     case CHIP_OMAP_4:
0451         ti_pinmux_dev = &omap4_pinmux_dev;
0452         break;
0453 #endif
0454 #ifdef SOC_TI_AM335X
0455     case CHIP_AM335X:
0456         ti_pinmux_dev = &ti_am335x_pinmux_dev;
0457         break;
0458 #endif
0459     default:
0460         printf("Unknown CPU in pinmux\n");
0461         return (ENXIO);
0462     }
0463 
0464 
0465     device_set_desc(dev, "TI Pinmux Module");
0466     return (BUS_PROBE_DEFAULT);
0467 }
0468 #endif /* __rtems__ */
0469 
0470 static void
0471 beagle_pinctrl_configure_children(struct ti_pinmux_softc *sc, phandle_t parent)
0472 {
0473     phandle_t node;
0474     int len;
0475     uint32_t phandle;
0476 
0477     for (node = OF_child(parent); node != 0; node = OF_peer(node)) {
0478         if (rtems_ofw_node_status(node)) {
0479             beagle_pinctrl_configure_children(sc, node);
0480             len = OF_getencprop(node, "pinctrl-0", &phandle, sizeof(phandle));
0481             if (len == sizeof(phandle)) {
0482                 ti_pinmux_configure_pins(sc, phandle);
0483             }
0484         }
0485     }
0486 }
0487 
0488 #ifndef __rtems__
0489 /**
0490  *  ti_pinmux_attach - attaches the pinmux to the simplebus
0491  *  @dev: new device
0492  *
0493  *  RETURNS
0494  *  Zero on success or ENXIO if an error occuried.
0495  */
0496 static int
0497 ti_pinmux_attach(device_t dev)
0498 {
0499     struct ti_pinmux_softc *sc = device_get_softc(dev);
0500 
0501 #if 0
0502     if (ti_pinmux_sc)
0503         return (ENXIO);
0504 #endif
0505 
0506     sc->sc_dev = dev;
0507 
0508     if (bus_alloc_resources(dev, ti_pinmux_res_spec, sc->sc_res)) {
0509         device_printf(dev, "could not allocate resources\n");
0510         return (ENXIO);
0511     }
0512 
0513     sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
0514     sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
0515 
0516     if (ti_pinmux_sc == NULL)
0517         ti_pinmux_sc = sc;
0518 
0519     fdt_pinctrl_register(dev, "pinctrl-single,pins");
0520     fdt_pinctrl_configure_tree(dev);
0521 
0522     return (0);
0523 }
0524 #endif
0525 
0526 void
0527 beagle_pinmux_init(phandle_t node)
0528 {
0529     static struct ti_pinmux_softc pinmux_softc;
0530     rtems_ofw_memory_area reg;
0531     int rv;
0532 
0533     if (!rtems_ofw_is_node_compatible(node, "pinctrl-single"))
0534         return ;
0535 
0536     switch (ti_chip()) {
0537     case CHIP_AM335X:
0538         ti_pinmux_dev = &ti_am335x_pinmux_dev;
0539         break;
0540     default:
0541         printk("Unknown CPU in pinmux\n");
0542         return ;
0543     }
0544 
0545     rv = rtems_ofw_get_reg(node, &reg, sizeof(reg));
0546     if (rv == -1) {
0547         printk("pinmux_init: rtems_ofw_get_reg failed %d\n", rv);
0548         return ;
0549     }
0550     pinmux_softc.sc_bsh = reg.start;
0551 
0552     beagle_pinctrl_configure_children(&pinmux_softc, OF_peer(0));
0553 }
0554 
0555 #ifndef __rtems__
0556 static device_method_t ti_pinmux_methods[] = {
0557     DEVMETHOD(device_probe,     ti_pinmux_probe),
0558     DEVMETHOD(device_attach,    ti_pinmux_attach),
0559 
0560         /* fdt_pinctrl interface */
0561     DEVMETHOD(fdt_pinctrl_configure, ti_pinmux_configure_pins),
0562     { 0, 0 }
0563 };
0564 
0565 static driver_t ti_pinmux_driver = {
0566     "ti_pinmux",
0567     ti_pinmux_methods,
0568     sizeof(struct ti_pinmux_softc),
0569 };
0570 
0571 static devclass_t ti_pinmux_devclass;
0572 
0573 DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0);
0574 #endif /* __rtems__ */