Path: blob/main/sys/arm/freescale/vybrid/vf_iomuxc.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2013-2014 Ruslan Bukin <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728/*29* Vybrid Family Input/Output Multiplexer Controller (IOMUXC)30* Chapter 5, Vybrid Reference Manual, Rev. 5, 07/201331*/3233#include <sys/param.h>34#include <sys/systm.h>35#include <sys/bus.h>36#include <sys/kernel.h>37#include <sys/module.h>38#include <sys/malloc.h>39#include <sys/rman.h>40#include <sys/timeet.h>41#include <sys/timetc.h>42#include <sys/watchdog.h>4344#include <dev/fdt/fdt_common.h>45#include <dev/ofw/openfirm.h>46#include <dev/ofw/ofw_bus.h>47#include <dev/ofw/ofw_bus_subr.h>4849#include <machine/bus.h>50#include <machine/cpu.h>51#include <machine/intr.h>5253#include <arm/freescale/vybrid/vf_iomuxc.h>54#include <arm/freescale/vybrid/vf_common.h>5556#define MUX_MODE_MASK 757#define MUX_MODE_SHIFT 2058#define MUX_MODE_GPIO 059#define MUX_MODE_VBUS_EN_OTG 26061#define IBE (1 << 0) /* Input Buffer Enable Field */62#define OBE (1 << 1) /* Output Buffer Enable Field. */63#define PUE (1 << 2) /* Pull / Keep Select Field. */64#define PKE (1 << 3) /* Pull / Keep Enable Field. */65#define HYS (1 << 9) /* Hysteresis Enable Field */66#define ODE (1 << 10) /* Open Drain Enable Field. */67#define SRE (1 << 11) /* Slew Rate Field. */6869#define SPEED_SHIFT 1270#define SPEED_MASK 0x371#define SPEED_LOW 0 /* 50 MHz */72#define SPEED_MEDIUM 0x1 /* 100 MHz */73#define SPEED_HIGH 0x3 /* 200 MHz */7475#define PUS_SHIFT 4 /* Pull Up / Down Config Field Shift */76#define PUS_MASK 0x377#define PUS_100_KOHM_PULL_DOWN 078#define PUS_47_KOHM_PULL_UP 0x179#define PUS_100_KOHM_PULL_UP 0x280#define PUS_22_KOHM_PULL_UP 0x38182#define DSE_SHIFT 6 /* Drive Strength Field Shift */83#define DSE_MASK 0x784#define DSE_DISABLED 0 /* Output driver disabled */85#define DSE_150_OHM 0x186#define DSE_75_OHM 0x287#define DSE_50_OHM 0x388#define DSE_37_OHM 0x489#define DSE_30_OHM 0x590#define DSE_25_OHM 0x691#define DSE_20_OHM 0x79293#define MAX_MUX_LEN 10249495struct iomuxc_softc {96struct resource *tmr_res[1];97bus_space_tag_t bst;98bus_space_handle_t bsh;99device_t dev;100};101102static struct resource_spec iomuxc_spec[] = {103{ SYS_RES_MEMORY, 0, RF_ACTIVE },104{ -1, 0 }105};106107static int108iomuxc_probe(device_t dev)109{110111if (!ofw_bus_status_okay(dev))112return (ENXIO);113114if (!ofw_bus_is_compatible(dev, "fsl,mvf600-iomuxc"))115return (ENXIO);116117device_set_desc(dev, "Vybrid Family IOMUXC Unit");118return (BUS_PROBE_DEFAULT);119}120121static int122pinmux_set(struct iomuxc_softc *sc)123{124phandle_t child, parent, root;125pcell_t iomux_config[MAX_MUX_LEN];126int len;127int values;128int pin;129int pin_cfg;130int i;131132root = OF_finddevice("/");133len = 0;134parent = root;135136/* Find 'iomux_config' prop in the nodes */137for (child = OF_child(parent); child != 0; child = OF_peer(child)) {138/* Find a 'leaf'. Start the search from this node. */139while (OF_child(child)) {140parent = child;141child = OF_child(child);142}143144if (!ofw_bus_node_status_okay(child))145continue;146147if ((len = OF_getproplen(child, "iomux_config")) > 0) {148OF_getencprop(child, "iomux_config", iomux_config, len);149150values = len / (sizeof(uint32_t));151for (i = 0; i < values; i += 2) {152pin = iomux_config[i];153pin_cfg = iomux_config[i+1];154#if 0155device_printf(sc->dev, "Set pin %d to 0x%08x\n",156pin, pin_cfg);157#endif158WRITE4(sc, IOMUXC(pin), pin_cfg);159}160}161162if (OF_peer(child) == 0) {163/* No more siblings. */164child = parent;165parent = OF_parent(child);166}167}168169return (0);170}171172static int173iomuxc_attach(device_t dev)174{175struct iomuxc_softc *sc;176177sc = device_get_softc(dev);178sc->dev = dev;179180if (bus_alloc_resources(dev, iomuxc_spec, sc->tmr_res)) {181device_printf(dev, "could not allocate resources\n");182return (ENXIO);183}184185/* Memory interface */186sc->bst = rman_get_bustag(sc->tmr_res[0]);187sc->bsh = rman_get_bushandle(sc->tmr_res[0]);188189pinmux_set(sc);190191return (0);192}193194static device_method_t iomuxc_methods[] = {195DEVMETHOD(device_probe, iomuxc_probe),196DEVMETHOD(device_attach, iomuxc_attach),197{ 0, 0 }198};199200static driver_t iomuxc_driver = {201"iomuxc",202iomuxc_methods,203sizeof(struct iomuxc_softc),204};205206DRIVER_MODULE(iomuxc, simplebus, iomuxc_driver, 0, 0);207208209