1239691Srwatson/*- 2239691Srwatson * Copyright (c) 2012 Robert N. M. Watson 3239691Srwatson * All rights reserved. 4239691Srwatson * 5239691Srwatson * This software was developed by SRI International and the University of 6239691Srwatson * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7239691Srwatson * ("CTSRD"), as part of the DARPA CRASH research programme. 8239691Srwatson * 9239691Srwatson * Redistribution and use in source and binary forms, with or without 10239691Srwatson * modification, are permitted provided that the following conditions 11239691Srwatson * are met: 12239691Srwatson * 1. Redistributions of source code must retain the above copyright 13239691Srwatson * notice, this list of conditions and the following disclaimer. 14239691Srwatson * 2. Redistributions in binary form must reproduce the above copyright 15239691Srwatson * notice, this list of conditions and the following disclaimer in the 16239691Srwatson * documentation and/or other materials provided with the distribution. 17239691Srwatson * 18239691Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19239691Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20239691Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21239691Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22239691Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23239691Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24239691Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25239691Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26239691Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27239691Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28239691Srwatson * SUCH DAMAGE. 29239691Srwatson */ 30239691Srwatson 31239691Srwatson#include <sys/cdefs.h> 32239691Srwatson__FBSDID("$FreeBSD: releng/10.2/sys/dev/terasic/mtl/terasic_mtl_nexus.c 265999 2014-05-14 01:35:43Z ian $"); 33239691Srwatson 34239691Srwatson#include <sys/param.h> 35239691Srwatson#include <sys/bus.h> 36239691Srwatson#include <sys/condvar.h> 37239691Srwatson#include <sys/conf.h> 38239691Srwatson#include <sys/consio.h> /* struct vt_mode */ 39239691Srwatson#include <sys/fbio.h> /* video_adapter_t */ 40239691Srwatson#include <sys/kernel.h> 41239691Srwatson#include <sys/lock.h> 42239691Srwatson#include <sys/malloc.h> 43239691Srwatson#include <sys/module.h> 44239691Srwatson#include <sys/mutex.h> 45239691Srwatson#include <sys/rman.h> 46239691Srwatson#include <sys/systm.h> 47239691Srwatson 48239691Srwatson#include <machine/bus.h> 49239691Srwatson#include <machine/resource.h> 50239691Srwatson 51239691Srwatson#include <dev/terasic/mtl/terasic_mtl.h> 52239691Srwatson 53239691Srwatsonstatic int 54239691Srwatsonterasic_mtl_nexus_probe(device_t dev) 55239691Srwatson{ 56239691Srwatson 57239691Srwatson device_set_desc(dev, "Terasic Multi-touch LCD (MTL)"); 58265999Sian return (BUS_PROBE_NOWILDCARD); 59239691Srwatson} 60239691Srwatson 61239691Srwatsonstatic int 62239691Srwatsonterasic_mtl_nexus_attach(device_t dev) 63239691Srwatson{ 64239691Srwatson struct terasic_mtl_softc *sc; 65239691Srwatson u_long pixel_maddr, text_maddr, reg_maddr; 66239691Srwatson u_long pixel_msize, text_msize, reg_msize; 67239691Srwatson int error; 68239691Srwatson 69239691Srwatson sc = device_get_softc(dev); 70239691Srwatson sc->mtl_dev = dev; 71239691Srwatson sc->mtl_unit = device_get_unit(dev); 72239691Srwatson 73239691Srwatson /* 74239691Srwatson * Query non-standard hints to find the locations of our two memory 75239691Srwatson * regions. Enforce certain alignment and size requirements. 76239691Srwatson */ 77239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 78239691Srwatson "reg_maddr", ®_maddr) != 0 || (reg_maddr % PAGE_SIZE != 0)) { 79239691Srwatson device_printf(dev, "improper register address"); 80239691Srwatson return (ENXIO); 81239691Srwatson } 82239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 83239691Srwatson "reg_msize", ®_msize) != 0 || (reg_msize % PAGE_SIZE != 0)) { 84239691Srwatson device_printf(dev, "improper register size"); 85239691Srwatson return (ENXIO); 86239691Srwatson } 87239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 88239691Srwatson "pixel_maddr", &pixel_maddr) != 0 || 89239691Srwatson (pixel_maddr % PAGE_SIZE != 0)) { 90239691Srwatson device_printf(dev, "improper pixel frame buffer address"); 91239691Srwatson return (ENXIO); 92239691Srwatson } 93239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 94239691Srwatson "pixel_msize", &pixel_msize) != 0 || 95239691Srwatson (pixel_msize % PAGE_SIZE != 0)) { 96239691Srwatson device_printf(dev, "improper pixel frame buffer size"); 97239691Srwatson return (ENXIO); 98239691Srwatson } 99239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 100239691Srwatson "text_maddr", &text_maddr) != 0 || 101239691Srwatson (text_maddr % PAGE_SIZE != 0)) { 102239691Srwatson device_printf(dev, "improper text frame buffer address"); 103239691Srwatson return (ENXIO); 104239691Srwatson } 105239691Srwatson if (resource_long_value(device_get_name(dev), device_get_unit(dev), 106239691Srwatson "text_msize", &text_msize) != 0 || 107239691Srwatson (text_msize % PAGE_SIZE != 0)) { 108239691Srwatson device_printf(dev, "improper text frame buffer size"); 109239691Srwatson return (ENXIO); 110239691Srwatson } 111239691Srwatson 112239691Srwatson /* 113239691Srwatson * Allocate resources. 114239691Srwatson */ 115239691Srwatson sc->mtl_reg_rid = 0; 116239691Srwatson sc->mtl_reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 117239691Srwatson &sc->mtl_reg_rid, reg_maddr, reg_maddr + reg_msize - 1, 118239691Srwatson reg_msize, RF_ACTIVE); 119239691Srwatson if (sc->mtl_reg_res == NULL) { 120239691Srwatson device_printf(dev, "couldn't map register memory\n"); 121239691Srwatson error = ENXIO; 122239691Srwatson goto error; 123239691Srwatson } 124239691Srwatson device_printf(sc->mtl_dev, "registers at mem %p-%p\n", 125239691Srwatson (void *)reg_maddr, (void *)(reg_maddr + reg_msize)); 126239691Srwatson sc->mtl_pixel_rid = 0; 127239691Srwatson sc->mtl_pixel_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 128239691Srwatson &sc->mtl_pixel_rid, pixel_maddr, pixel_maddr + pixel_msize - 1, 129239691Srwatson pixel_msize, RF_ACTIVE); 130239691Srwatson if (sc->mtl_pixel_res == NULL) { 131239691Srwatson device_printf(dev, "couldn't map pixel memory\n"); 132239691Srwatson error = ENXIO; 133239691Srwatson goto error; 134239691Srwatson } 135239691Srwatson device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n", 136239691Srwatson (void *)pixel_maddr, (void *)(pixel_maddr + pixel_msize)); 137239691Srwatson sc->mtl_text_rid = 0; 138239691Srwatson sc->mtl_text_res = bus_alloc_resource(dev, SYS_RES_MEMORY, 139239691Srwatson &sc->mtl_text_rid, text_maddr, text_maddr + text_msize - 1, 140239691Srwatson text_msize, RF_ACTIVE); 141239691Srwatson if (sc->mtl_text_res == NULL) { 142239691Srwatson device_printf(dev, "couldn't map text memory\n"); 143239691Srwatson error = ENXIO; 144239691Srwatson goto error; 145239691Srwatson } 146239691Srwatson device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n", 147239691Srwatson (void *)text_maddr, (void *)(text_maddr + text_msize)); 148239691Srwatson error = terasic_mtl_attach(sc); 149239691Srwatson if (error == 0) 150239691Srwatson return (0); 151239691Srwatsonerror: 152239691Srwatson if (sc->mtl_text_res != NULL) 153239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid, 154239691Srwatson sc->mtl_text_res); 155239691Srwatson if (sc->mtl_pixel_res != NULL) 156239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid, 157239691Srwatson sc->mtl_pixel_res); 158239691Srwatson if (sc->mtl_reg_res != NULL) 159239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid, 160239691Srwatson sc->mtl_reg_res); 161239691Srwatson return (error); 162239691Srwatson} 163239691Srwatson 164239691Srwatsonstatic int 165239691Srwatsonterasic_mtl_nexus_detach(device_t dev) 166239691Srwatson{ 167239691Srwatson struct terasic_mtl_softc *sc; 168239691Srwatson 169239691Srwatson sc = device_get_softc(dev); 170239691Srwatson terasic_mtl_detach(sc); 171239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid, 172239691Srwatson sc->mtl_text_res); 173239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid, 174239691Srwatson sc->mtl_pixel_res); 175239691Srwatson bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid, 176239691Srwatson sc->mtl_reg_res); 177239691Srwatson return (0); 178239691Srwatson} 179239691Srwatson 180239691Srwatsonstatic device_method_t terasic_mtl_nexus_methods[] = { 181239691Srwatson DEVMETHOD(device_probe, terasic_mtl_nexus_probe), 182239691Srwatson DEVMETHOD(device_attach, terasic_mtl_nexus_attach), 183239691Srwatson DEVMETHOD(device_detach, terasic_mtl_nexus_detach), 184239691Srwatson { 0, 0 } 185239691Srwatson}; 186239691Srwatson 187239691Srwatsonstatic driver_t terasic_mtl_nexus_driver = { 188239691Srwatson "terasic_mtl", 189239691Srwatson terasic_mtl_nexus_methods, 190239691Srwatson sizeof(struct terasic_mtl_softc), 191239691Srwatson}; 192239691Srwatson 193239691SrwatsonDRIVER_MODULE(mtl, nexus, terasic_mtl_nexus_driver, terasic_mtl_devclass, 0, 194239691Srwatson 0); 195