/* $Id: omap2_gpmc.c,v 1.10 2016/10/04 15:23:40 kiyohara Exp $ */ /* adapted from: */ /* $NetBSD: omap2_gpmc.c,v 1.10 2016/10/04 15:23:40 kiyohara Exp $ */ /* * Autoconfiguration support for the Texas Instruments OMAP GPMC bus. * Based on arm/omap/omap_emifs.c which in turn was derived * Based on arm/xscale/pxa2x0.c which in turn was derived * from arm/sa11x0/sa11x0.c * * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved. * Written by Hiroyuki Bessho for Genetec Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Genetec Corporation. * 4. The name of Genetec Corporation may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Copyright (c) 1997,1998, 2001, The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by IWAMOTO Toshihiro, Ichiro FUKUHARA and Paul Kranenburg. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Copyright (c) 1999 * Shin Takemura and PocketBSD Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the PocketBSD project * and its contributors. * 4. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_omap.h" #include __KERNEL_RCSID(0, "$NetBSD: omap2_gpmc.c,v 1.10 2016/10/04 15:23:40 kiyohara Exp $"); #include "locators.h" #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { boolean_t cs_valid; ulong cs_addr; ulong cs_size; } gpmc_csconfig_t; struct gpmc_softc { device_t sc_dev; bus_dma_tag_t sc_dmac; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; gpmc_csconfig_t sc_csconfig[GPMC_NCS]; }; static bus_size_t csreg7[GPMC_NCS] = { GPMC_CONFIG7_0, GPMC_CONFIG7_1, GPMC_CONFIG7_2, GPMC_CONFIG7_3, GPMC_CONFIG7_4, GPMC_CONFIG7_5, GPMC_CONFIG7_6, GPMC_CONFIG7_7, }; /* prototypes */ static int gpmc_match(device_t, cfdata_t, void *); static void gpmc_attach(device_t, device_t, void *); static void gpmc_csconfig_init(struct gpmc_softc *); static int gpmc_search(device_t, cfdata_t, const int *, void *); static int gpmc_print(void *, const char *); /* attach structures */ CFATTACH_DECL_NEW(gpmc, sizeof(struct gpmc_softc), gpmc_match, gpmc_attach, NULL, NULL); static int gpmc_attached; /* XXX assumes only 1 instance */ static int gpmc_match(device_t parent, cfdata_t match, void *aux) { struct mainbus_attach_args *mb = aux; if (gpmc_attached != 0) return 0; #if defined(OMAP2) if (mb->mb_iobase == GPMC_BASE) return 1; #endif return 0; } static void gpmc_attach(device_t parent, device_t self, void *aux) { struct gpmc_softc *sc = device_private(self); struct mainbus_attach_args *mb = aux; bus_space_handle_t ioh; uint32_t rev; int err; sc->sc_dev = self; sc->sc_iot = &omap_bs_tag; err = bus_space_map(sc->sc_iot, mb->mb_iobase, GPMC_SIZE, 0, &ioh); if (err != 0) panic("%s: Cannot map registers, error %d", device_xname(self), err); aprint_normal(": General Purpose Memory Controller"); rev = bus_space_read_4(sc->sc_iot, ioh, GPMC_REVISION); aprint_normal(", rev %d.%d\n", GPMC_REVISION_REV_MAJ(rev), GPMC_REVISION_REV_MIN(rev)); sc->sc_ioh = ioh; sc->sc_dmac = NULL; gpmc_csconfig_init(sc); gpmc_attached = 1; /* * Attach all our devices */ config_search_ia(gpmc_search, self, "gpmc", NULL); } static void gpmc_csconfig_init(struct gpmc_softc *sc) { gpmc_csconfig_t *cs; uint32_t r; int i; cs = &sc->sc_csconfig[0]; for (i=0; i < GPMC_NCS; i++) { memset(cs, 0, sizeof(gpmc_csconfig_t)); r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, csreg7[i]); if ((r & GPMC_CONFIG7_CSVALID) != 0) { cs->cs_valid = TRUE; cs->cs_addr = omap_gpmc_config7_addr(r); cs->cs_size = omap_gpmc_config7_size(r); aprint_normal("%s: CS#%d valid, " "addr 0x%08lx, size %3ldMB\n", device_xname(sc->sc_dev), i, cs->cs_addr, (cs->cs_size >> 20)); } cs++; } } static int gpmc_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) { struct gpmc_softc *sc = device_private(parent); struct gpmc_attach_args aa; gpmc_csconfig_t *cs; int i; /* Set up the attach args. */ if (cf->cf_loc[GPMCCF_NOBYTEACC] == 1) { if (cf->cf_loc[GPMCCF_MULT] == 1) aa.gpmc_iot = &nobyteacc_bs_tag; else panic("nobyteacc specified for device with " "non-byte multiplier\n"); } else { switch (cf->cf_loc[GPMCCF_MULT]) { case 1: aa.gpmc_iot = &omap_bs_tag; break; case 2: aa.gpmc_iot = &omap_a2x_bs_tag; break; case 4: aa.gpmc_iot = &omap_a4x_bs_tag; break; default: panic("Unsupported EMIFS multiplier."); break; } } aa.gpmc_dmac = sc->sc_dmac; aa.gpmc_addr = cf->cf_loc[GPMCCF_ADDR]; aa.gpmc_size = cf->cf_loc[GPMCCF_SIZE]; aa.gpmc_intr = cf->cf_loc[GPMCCF_INTR]; cs = &sc->sc_csconfig[0]; for (i = 0; i < GPMC_NCS; i++) { if (cf->cf_loc[GPMCCF_CS] != GPMCCF_CS_DEFAULT) { if (i != cf->cf_loc[GPMCCF_CS]) { cs++; continue; } if (aa.gpmc_addr != GPMCCF_ADDR_DEFAULT && aa.gpmc_addr != cs->cs_addr) panic("cs:addr missmatch:" " cs %d(0x%08lx), addr 0x%08lx\n", cf->cf_loc[GPMCCF_CS], cs->cs_addr, aa.gpmc_addr); aa.gpmc_addr = cs->cs_addr; } if ((aa.gpmc_addr >= cs->cs_addr) && (aa.gpmc_addr < (cs->cs_addr + cs->cs_size))) { /* XXX * if size was specified, then check it too * otherwise just assume it is OK */ if ((aa.gpmc_size != GPMCCF_SIZE_DEFAULT) && ((aa.gpmc_addr + aa.gpmc_size) >= (cs->cs_addr + cs->cs_size))) continue; /* NG */ aa.gpmc_cs = i; if (config_match(parent, cf, &aa)) { config_attach(parent, cf, &aa, gpmc_print); return 0; /* love it */ } } cs++; } return 1; /* NG */ } static int gpmc_print(void *aux, const char *name) { struct gpmc_attach_args *sa = (struct gpmc_attach_args*)aux; if (sa->gpmc_addr != GPMCCF_ADDR_DEFAULT) { aprint_normal(" addr 0x%08lx", sa->gpmc_addr); if (sa->gpmc_size != GPMCCF_SIZE_DEFAULT) aprint_normal("-0x%08lx", sa->gpmc_addr + sa->gpmc_size-1); } if (sa->gpmc_intr != GPMCCF_INTR_DEFAULT) aprint_normal(" intr %d", sa->gpmc_intr); return UNCONF; } uint32_t gpmc_register_read(struct gpmc_softc *sc, bus_size_t reg) { return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg); } void gpmc_register_write(struct gpmc_softc *sc, bus_size_t reg, const uint32_t data) { bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, data); }