ti_adc.c revision 300769
1263693Sloos/*- 2263693Sloos * Copyright 2014 Luiz Otavio O Souza <loos@freebsd.org> 3263693Sloos * All rights reserved. 4263693Sloos * 5263693Sloos * Redistribution and use in source and binary forms, with or without 6263693Sloos * modification, are permitted provided that the following conditions 7263693Sloos * are met: 8263693Sloos * 1. Redistributions of source code must retain the above copyright 9263693Sloos * notice, this list of conditions and the following disclaimer. 10263693Sloos * 2. Redistributions in binary form must reproduce the above copyright 11263693Sloos * notice, this list of conditions and the following disclaimer in the 12263693Sloos * documentation and/or other materials provided with the distribution. 13263693Sloos * 14263693Sloos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15263693Sloos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16263693Sloos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17263693Sloos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18263693Sloos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19263693Sloos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20263693Sloos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21263693Sloos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22263693Sloos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23263693Sloos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24263693Sloos * SUCH DAMAGE. 25263693Sloos */ 26263693Sloos 27263693Sloos#include <sys/cdefs.h> 28263693Sloos__FBSDID("$FreeBSD: head/sys/arm/ti/ti_adc.c 300769 2016-05-26 18:52:26Z loos $"); 29263693Sloos 30263693Sloos#include <sys/param.h> 31263693Sloos#include <sys/systm.h> 32263693Sloos#include <sys/bus.h> 33263693Sloos 34298802Sgonzo#include <sys/conf.h> 35263693Sloos#include <sys/kernel.h> 36263693Sloos#include <sys/limits.h> 37263693Sloos#include <sys/lock.h> 38263693Sloos#include <sys/module.h> 39263693Sloos#include <sys/mutex.h> 40298802Sgonzo#include <sys/condvar.h> 41263693Sloos#include <sys/resource.h> 42263693Sloos#include <sys/rman.h> 43263693Sloos#include <sys/sysctl.h> 44298802Sgonzo#include <sys/selinfo.h> 45298802Sgonzo#include <sys/poll.h> 46298802Sgonzo#include <sys/uio.h> 47263693Sloos 48263693Sloos#include <machine/bus.h> 49263693Sloos 50298802Sgonzo#include <dev/fdt/fdt_common.h> 51263693Sloos#include <dev/ofw/openfirm.h> 52263693Sloos#include <dev/ofw/ofw_bus.h> 53263693Sloos#include <dev/ofw/ofw_bus_subr.h> 54263693Sloos 55263693Sloos#include <arm/ti/ti_prcm.h> 56263693Sloos#include <arm/ti/ti_adcreg.h> 57263693Sloos#include <arm/ti/ti_adcvar.h> 58263693Sloos 59298802Sgonzo#undef DEBUG_TSC 60298802Sgonzo 61298802Sgonzo#define DEFAULT_CHARGE_DELAY 0x400 62298802Sgonzo#define STEPDLY_OPEN 0x98 63298802Sgonzo 64298802Sgonzo#define ORDER_XP 0 65298802Sgonzo#define ORDER_XN 1 66298802Sgonzo#define ORDER_YP 2 67298802Sgonzo#define ORDER_YN 3 68298802Sgonzo 69266960Sloos/* Define our 8 steps, one for each input channel. */ 70263693Sloosstatic struct ti_adc_input ti_adc_inputs[TI_ADC_NPINS] = { 71298802Sgonzo { .stepconfig = ADC_STEPCFG(1), .stepdelay = ADC_STEPDLY(1) }, 72298802Sgonzo { .stepconfig = ADC_STEPCFG(2), .stepdelay = ADC_STEPDLY(2) }, 73298802Sgonzo { .stepconfig = ADC_STEPCFG(3), .stepdelay = ADC_STEPDLY(3) }, 74298802Sgonzo { .stepconfig = ADC_STEPCFG(4), .stepdelay = ADC_STEPDLY(4) }, 75298802Sgonzo { .stepconfig = ADC_STEPCFG(5), .stepdelay = ADC_STEPDLY(5) }, 76298802Sgonzo { .stepconfig = ADC_STEPCFG(6), .stepdelay = ADC_STEPDLY(6) }, 77298802Sgonzo { .stepconfig = ADC_STEPCFG(7), .stepdelay = ADC_STEPDLY(7) }, 78298802Sgonzo { .stepconfig = ADC_STEPCFG(8), .stepdelay = ADC_STEPDLY(8) }, 79263693Sloos}; 80263693Sloos 81263693Sloosstatic int ti_adc_samples[5] = { 0, 2, 4, 8, 16 }; 82263693Sloos 83263693Sloosstatic void 84263693Sloosti_adc_enable(struct ti_adc_softc *sc) 85263693Sloos{ 86298802Sgonzo uint32_t reg; 87263693Sloos 88263693Sloos TI_ADC_LOCK_ASSERT(sc); 89263693Sloos 90263693Sloos if (sc->sc_last_state == 1) 91263693Sloos return; 92263693Sloos 93263693Sloos /* Enable the FIFO0 threshold and the end of sequence interrupt. */ 94263693Sloos ADC_WRITE4(sc, ADC_IRQENABLE_SET, 95298802Sgonzo ADC_IRQ_FIFO0_THRES | ADC_IRQ_FIFO1_THRES | ADC_IRQ_END_OF_SEQ); 96263693Sloos 97298802Sgonzo reg = ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID; 98298802Sgonzo if (sc->sc_tsc_wires > 0) { 99298802Sgonzo reg |= ADC_CTRL_TSC_ENABLE; 100298802Sgonzo switch (sc->sc_tsc_wires) { 101298802Sgonzo case 4: 102298802Sgonzo reg |= ADC_CTRL_TSC_4WIRE; 103298802Sgonzo break; 104298802Sgonzo case 5: 105298802Sgonzo reg |= ADC_CTRL_TSC_5WIRE; 106298802Sgonzo break; 107298802Sgonzo case 8: 108298802Sgonzo reg |= ADC_CTRL_TSC_8WIRE; 109298802Sgonzo break; 110298802Sgonzo default: 111298802Sgonzo break; 112298802Sgonzo } 113298802Sgonzo } 114298802Sgonzo reg |= ADC_CTRL_ENABLE; 115263693Sloos /* Enable the ADC. Run thru enabled steps, start the conversions. */ 116298802Sgonzo ADC_WRITE4(sc, ADC_CTRL, reg); 117263693Sloos 118263693Sloos sc->sc_last_state = 1; 119263693Sloos} 120263693Sloos 121263693Sloosstatic void 122263693Sloosti_adc_disable(struct ti_adc_softc *sc) 123263693Sloos{ 124263693Sloos int count; 125263693Sloos uint32_t data; 126263693Sloos 127263693Sloos TI_ADC_LOCK_ASSERT(sc); 128263693Sloos 129263693Sloos if (sc->sc_last_state == 0) 130263693Sloos return; 131263693Sloos 132263693Sloos /* Disable all the enabled steps. */ 133263693Sloos ADC_WRITE4(sc, ADC_STEPENABLE, 0); 134263693Sloos 135263693Sloos /* Disable the ADC. */ 136263693Sloos ADC_WRITE4(sc, ADC_CTRL, ADC_READ4(sc, ADC_CTRL) & ~ADC_CTRL_ENABLE); 137263693Sloos 138263693Sloos /* Disable the FIFO0 threshold and the end of sequence interrupt. */ 139263693Sloos ADC_WRITE4(sc, ADC_IRQENABLE_CLR, 140298802Sgonzo ADC_IRQ_FIFO0_THRES | ADC_IRQ_FIFO1_THRES | ADC_IRQ_END_OF_SEQ); 141263693Sloos 142263693Sloos /* ACK any pending interrupt. */ 143263693Sloos ADC_WRITE4(sc, ADC_IRQSTATUS, ADC_READ4(sc, ADC_IRQSTATUS)); 144263693Sloos 145263693Sloos /* Drain the FIFO data. */ 146263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 147263693Sloos while (count > 0) { 148263693Sloos data = ADC_READ4(sc, ADC_FIFO0DATA); 149263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 150263693Sloos } 151263693Sloos 152298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 153298802Sgonzo while (count > 0) { 154298802Sgonzo data = ADC_READ4(sc, ADC_FIFO1DATA); 155298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 156298802Sgonzo } 157298802Sgonzo 158263693Sloos sc->sc_last_state = 0; 159263693Sloos} 160263693Sloos 161263693Sloosstatic int 162263693Sloosti_adc_setup(struct ti_adc_softc *sc) 163263693Sloos{ 164298802Sgonzo int ain, i; 165263693Sloos uint32_t enabled; 166263693Sloos 167263693Sloos TI_ADC_LOCK_ASSERT(sc); 168263693Sloos 169263693Sloos /* Check for enabled inputs. */ 170298802Sgonzo enabled = sc->sc_tsc_enabled; 171298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 172298802Sgonzo ain = sc->sc_adc_channels[i]; 173263693Sloos if (ti_adc_inputs[ain].enable) 174263693Sloos enabled |= (1U << (ain + 1)); 175263693Sloos } 176263693Sloos 177263693Sloos /* Set the ADC global status. */ 178263693Sloos if (enabled != 0) { 179263693Sloos ti_adc_enable(sc); 180263693Sloos /* Update the enabled steps. */ 181263693Sloos if (enabled != ADC_READ4(sc, ADC_STEPENABLE)) 182263693Sloos ADC_WRITE4(sc, ADC_STEPENABLE, enabled); 183263693Sloos } else 184263693Sloos ti_adc_disable(sc); 185263693Sloos 186263693Sloos return (0); 187263693Sloos} 188263693Sloos 189263693Sloosstatic void 190263693Sloosti_adc_input_setup(struct ti_adc_softc *sc, int32_t ain) 191263693Sloos{ 192263693Sloos struct ti_adc_input *input; 193263693Sloos uint32_t reg, val; 194263693Sloos 195263693Sloos TI_ADC_LOCK_ASSERT(sc); 196263693Sloos 197263693Sloos input = &ti_adc_inputs[ain]; 198263693Sloos reg = input->stepconfig; 199263693Sloos val = ADC_READ4(sc, reg); 200263693Sloos 201263693Sloos /* Set single ended operation. */ 202263693Sloos val &= ~ADC_STEP_DIFF_CNTRL; 203263693Sloos 204263693Sloos /* Set the negative voltage reference. */ 205263693Sloos val &= ~ADC_STEP_RFM_MSK; 206263693Sloos 207263693Sloos /* Set the positive voltage reference. */ 208263693Sloos val &= ~ADC_STEP_RFP_MSK; 209263693Sloos 210263693Sloos /* Set the samples average. */ 211263693Sloos val &= ~ADC_STEP_AVG_MSK; 212263693Sloos val |= input->samples << ADC_STEP_AVG_SHIFT; 213263693Sloos 214263693Sloos /* Select the desired input. */ 215263693Sloos val &= ~ADC_STEP_INP_MSK; 216263693Sloos val |= ain << ADC_STEP_INP_SHIFT; 217263693Sloos 218263693Sloos /* Set the ADC to one-shot mode. */ 219263693Sloos val &= ~ADC_STEP_MODE_MSK; 220263693Sloos 221263693Sloos ADC_WRITE4(sc, reg, val); 222263693Sloos} 223263693Sloos 224263693Sloosstatic void 225263693Sloosti_adc_reset(struct ti_adc_softc *sc) 226263693Sloos{ 227298802Sgonzo int ain, i; 228263693Sloos 229263693Sloos TI_ADC_LOCK_ASSERT(sc); 230263693Sloos 231263693Sloos /* Disable all the inputs. */ 232298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 233298802Sgonzo ain = sc->sc_adc_channels[i]; 234263693Sloos ti_adc_inputs[ain].enable = 0; 235298802Sgonzo } 236263693Sloos} 237263693Sloos 238263693Sloosstatic int 239263693Sloosti_adc_clockdiv_proc(SYSCTL_HANDLER_ARGS) 240263693Sloos{ 241263693Sloos int error, reg; 242263693Sloos struct ti_adc_softc *sc; 243263693Sloos 244263693Sloos sc = (struct ti_adc_softc *)arg1; 245263693Sloos 246263693Sloos TI_ADC_LOCK(sc); 247263693Sloos reg = (int)ADC_READ4(sc, ADC_CLKDIV) + 1; 248263693Sloos TI_ADC_UNLOCK(sc); 249263693Sloos 250263693Sloos error = sysctl_handle_int(oidp, ®, sizeof(reg), req); 251263693Sloos if (error != 0 || req->newptr == NULL) 252263693Sloos return (error); 253263693Sloos 254263693Sloos /* 255263693Sloos * The actual written value is the prescaler setting - 1. 256263693Sloos * Enforce a minimum value of 10 (i.e. 9) which limits the maximum 257263693Sloos * ADC clock to ~2.4Mhz (CLK_M_OSC / 10). 258263693Sloos */ 259263693Sloos reg--; 260263693Sloos if (reg < 9) 261263693Sloos reg = 9; 262263693Sloos if (reg > USHRT_MAX) 263263693Sloos reg = USHRT_MAX; 264263693Sloos 265263693Sloos TI_ADC_LOCK(sc); 266263693Sloos /* Disable the ADC. */ 267263693Sloos ti_adc_disable(sc); 268263693Sloos /* Update the ADC prescaler setting. */ 269263693Sloos ADC_WRITE4(sc, ADC_CLKDIV, reg); 270263693Sloos /* Enable the ADC again. */ 271263693Sloos ti_adc_setup(sc); 272263693Sloos TI_ADC_UNLOCK(sc); 273263693Sloos 274263693Sloos return (0); 275263693Sloos} 276263693Sloos 277263693Sloosstatic int 278263693Sloosti_adc_enable_proc(SYSCTL_HANDLER_ARGS) 279263693Sloos{ 280263693Sloos int error; 281263693Sloos int32_t enable; 282263693Sloos struct ti_adc_softc *sc; 283263693Sloos struct ti_adc_input *input; 284263693Sloos 285263693Sloos input = (struct ti_adc_input *)arg1; 286263693Sloos sc = input->sc; 287263693Sloos 288263693Sloos enable = input->enable; 289263693Sloos error = sysctl_handle_int(oidp, &enable, sizeof(enable), 290263693Sloos req); 291263693Sloos if (error != 0 || req->newptr == NULL) 292263693Sloos return (error); 293263693Sloos 294263693Sloos if (enable) 295263693Sloos enable = 1; 296263693Sloos 297263693Sloos TI_ADC_LOCK(sc); 298263693Sloos /* Setup the ADC as needed. */ 299263693Sloos if (input->enable != enable) { 300263693Sloos input->enable = enable; 301263693Sloos ti_adc_setup(sc); 302263693Sloos if (input->enable == 0) 303263693Sloos input->value = 0; 304263693Sloos } 305263693Sloos TI_ADC_UNLOCK(sc); 306263693Sloos 307263693Sloos return (0); 308263693Sloos} 309263693Sloos 310263693Sloosstatic int 311263693Sloosti_adc_open_delay_proc(SYSCTL_HANDLER_ARGS) 312263693Sloos{ 313263693Sloos int error, reg; 314263693Sloos struct ti_adc_softc *sc; 315263693Sloos struct ti_adc_input *input; 316263693Sloos 317263693Sloos input = (struct ti_adc_input *)arg1; 318263693Sloos sc = input->sc; 319263693Sloos 320263693Sloos TI_ADC_LOCK(sc); 321263693Sloos reg = (int)ADC_READ4(sc, input->stepdelay) & ADC_STEP_OPEN_DELAY; 322263693Sloos TI_ADC_UNLOCK(sc); 323263693Sloos 324263693Sloos error = sysctl_handle_int(oidp, ®, sizeof(reg), req); 325263693Sloos if (error != 0 || req->newptr == NULL) 326263693Sloos return (error); 327263693Sloos 328263693Sloos if (reg < 0) 329263693Sloos reg = 0; 330263693Sloos 331263693Sloos TI_ADC_LOCK(sc); 332263693Sloos ADC_WRITE4(sc, input->stepdelay, reg & ADC_STEP_OPEN_DELAY); 333263693Sloos TI_ADC_UNLOCK(sc); 334263693Sloos 335263693Sloos return (0); 336263693Sloos} 337263693Sloos 338263693Sloosstatic int 339263693Sloosti_adc_samples_avg_proc(SYSCTL_HANDLER_ARGS) 340263693Sloos{ 341263693Sloos int error, samples, i; 342263693Sloos struct ti_adc_softc *sc; 343263693Sloos struct ti_adc_input *input; 344263693Sloos 345263693Sloos input = (struct ti_adc_input *)arg1; 346263693Sloos sc = input->sc; 347263693Sloos 348263693Sloos if (input->samples > nitems(ti_adc_samples)) 349263693Sloos input->samples = nitems(ti_adc_samples); 350263693Sloos samples = ti_adc_samples[input->samples]; 351263693Sloos 352263693Sloos error = sysctl_handle_int(oidp, &samples, 0, req); 353263693Sloos if (error != 0 || req->newptr == NULL) 354263693Sloos return (error); 355263693Sloos 356263693Sloos TI_ADC_LOCK(sc); 357263693Sloos if (samples != ti_adc_samples[input->samples]) { 358263693Sloos input->samples = 0; 359263693Sloos for (i = 0; i < nitems(ti_adc_samples); i++) 360263693Sloos if (samples >= ti_adc_samples[i]) 361263693Sloos input->samples = i; 362263693Sloos ti_adc_input_setup(sc, input->input); 363263693Sloos } 364263693Sloos TI_ADC_UNLOCK(sc); 365263693Sloos 366263693Sloos return (error); 367263693Sloos} 368263693Sloos 369263693Sloosstatic void 370263693Sloosti_adc_read_data(struct ti_adc_softc *sc) 371263693Sloos{ 372263693Sloos int count, ain; 373263693Sloos struct ti_adc_input *input; 374263693Sloos uint32_t data; 375263693Sloos 376263693Sloos TI_ADC_LOCK_ASSERT(sc); 377263693Sloos 378263693Sloos /* Read the available data. */ 379263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 380263693Sloos while (count > 0) { 381263693Sloos data = ADC_READ4(sc, ADC_FIFO0DATA); 382263693Sloos ain = (data & ADC_FIFO_STEP_ID_MSK) >> ADC_FIFO_STEP_ID_SHIFT; 383263693Sloos input = &ti_adc_inputs[ain]; 384263693Sloos if (input->enable == 0) 385263693Sloos input->value = 0; 386263693Sloos else 387263693Sloos input->value = (int32_t)(data & ADC_FIFO_DATA_MSK); 388263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 389263693Sloos } 390263693Sloos} 391263693Sloos 392298802Sgonzostatic int 393298802Sgonzocmp_values(const void *a, const void *b) 394298802Sgonzo{ 395298802Sgonzo const uint32_t *v1, *v2; 396298802Sgonzo v1 = a; 397298802Sgonzo v2 = b; 398298802Sgonzo if (*v1 < *v2) 399298802Sgonzo return -1; 400298802Sgonzo if (*v1 > *v2) 401298802Sgonzo return 1; 402298802Sgonzo 403298802Sgonzo return (0); 404298802Sgonzo} 405298802Sgonzo 406263693Sloosstatic void 407298802Sgonzoti_adc_tsc_read_data(struct ti_adc_softc *sc) 408298802Sgonzo{ 409298802Sgonzo int count; 410298802Sgonzo uint32_t data[16]; 411298802Sgonzo uint32_t x, y; 412298802Sgonzo int i, start, end; 413298802Sgonzo 414298802Sgonzo TI_ADC_LOCK_ASSERT(sc); 415298802Sgonzo 416298802Sgonzo /* Read the available data. */ 417298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 418298802Sgonzo if (count == 0) 419298802Sgonzo return; 420298802Sgonzo 421298802Sgonzo i = 0; 422298802Sgonzo while (count > 0) { 423298802Sgonzo data[i++] = ADC_READ4(sc, ADC_FIFO1DATA) & ADC_FIFO_DATA_MSK; 424298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 425298802Sgonzo } 426298802Sgonzo 427298802Sgonzo if (sc->sc_coord_readouts > 3) { 428298802Sgonzo start = 1; 429298802Sgonzo end = sc->sc_coord_readouts - 1; 430298802Sgonzo qsort(data, sc->sc_coord_readouts, 431298802Sgonzo sizeof(data[0]), &cmp_values); 432298802Sgonzo qsort(&data[sc->sc_coord_readouts + 2], 433298802Sgonzo sc->sc_coord_readouts, 434298802Sgonzo sizeof(data[0]), &cmp_values); 435298802Sgonzo } 436298802Sgonzo else { 437298802Sgonzo start = 0; 438298802Sgonzo end = sc->sc_coord_readouts; 439298802Sgonzo } 440298802Sgonzo 441298802Sgonzo x = y = 0; 442298802Sgonzo for (i = start; i < end; i++) 443298802Sgonzo y += data[i]; 444298802Sgonzo y /= (end - start); 445298802Sgonzo 446298802Sgonzo for (i = sc->sc_coord_readouts + 2 + start; i < sc->sc_coord_readouts + 2 + end; i++) 447298802Sgonzo x += data[i]; 448298802Sgonzo x /= (end - start); 449298802Sgonzo 450298802Sgonzo#ifdef DEBUG_TSC 451298802Sgonzo device_printf(sc->sc_dev, "touchscreen x: %d, y: %d\n", x, y); 452298802Sgonzo#endif 453298802Sgonzo /* TODO: That's where actual event reporting should take place */ 454298802Sgonzo} 455298802Sgonzo 456298802Sgonzostatic void 457298802Sgonzoti_adc_intr_locked(struct ti_adc_softc *sc, uint32_t status) 458298802Sgonzo{ 459298802Sgonzo /* Read the available data. */ 460298802Sgonzo if (status & ADC_IRQ_FIFO0_THRES) 461298802Sgonzo ti_adc_read_data(sc); 462298802Sgonzo} 463298802Sgonzo 464298802Sgonzostatic void 465298802Sgonzoti_adc_tsc_intr_locked(struct ti_adc_softc *sc, uint32_t status) 466298802Sgonzo{ 467298802Sgonzo /* Read the available data. */ 468298802Sgonzo if (status & ADC_IRQ_FIFO1_THRES) 469298802Sgonzo ti_adc_tsc_read_data(sc); 470298802Sgonzo 471298802Sgonzo} 472298802Sgonzo 473298802Sgonzostatic void 474263693Sloosti_adc_intr(void *arg) 475263693Sloos{ 476263693Sloos struct ti_adc_softc *sc; 477298802Sgonzo uint32_t status, rawstatus; 478263693Sloos 479263693Sloos sc = (struct ti_adc_softc *)arg; 480263693Sloos 481298802Sgonzo TI_ADC_LOCK(sc); 482298802Sgonzo 483298802Sgonzo rawstatus = ADC_READ4(sc, ADC_IRQSTATUS_RAW); 484263693Sloos status = ADC_READ4(sc, ADC_IRQSTATUS); 485263693Sloos 486298802Sgonzo if (rawstatus & ADC_IRQ_HW_PEN_ASYNC) { 487298802Sgonzo sc->sc_pen_down = 1; 488298802Sgonzo status |= ADC_IRQ_HW_PEN_ASYNC; 489298802Sgonzo ADC_WRITE4(sc, ADC_IRQENABLE_CLR, 490298802Sgonzo ADC_IRQ_HW_PEN_ASYNC); 491298802Sgonzo } 492263693Sloos 493298802Sgonzo if (rawstatus & ADC_IRQ_PEN_UP) { 494298802Sgonzo sc->sc_pen_down = 0; 495298802Sgonzo status |= ADC_IRQ_PEN_UP; 496298802Sgonzo } 497298802Sgonzo 498263693Sloos if (status & ADC_IRQ_FIFO0_THRES) 499298802Sgonzo ti_adc_intr_locked(sc, status); 500263693Sloos 501298802Sgonzo if (status & ADC_IRQ_FIFO1_THRES) 502298802Sgonzo ti_adc_tsc_intr_locked(sc, status); 503298802Sgonzo 504298802Sgonzo if (status) { 505298802Sgonzo /* ACK the interrupt. */ 506298802Sgonzo ADC_WRITE4(sc, ADC_IRQSTATUS, status); 507298802Sgonzo } 508298802Sgonzo 509263693Sloos /* Start the next conversion ? */ 510263693Sloos if (status & ADC_IRQ_END_OF_SEQ) 511263693Sloos ti_adc_setup(sc); 512298802Sgonzo 513263693Sloos TI_ADC_UNLOCK(sc); 514263693Sloos} 515263693Sloos 516263693Sloosstatic void 517263693Sloosti_adc_sysctl_init(struct ti_adc_softc *sc) 518263693Sloos{ 519263693Sloos char pinbuf[3]; 520263693Sloos struct sysctl_ctx_list *ctx; 521263693Sloos struct sysctl_oid *tree_node, *inp_node, *inpN_node; 522263693Sloos struct sysctl_oid_list *tree, *inp_tree, *inpN_tree; 523298802Sgonzo int ain, i; 524263693Sloos 525263693Sloos /* 526263693Sloos * Add per-pin sysctl tree/handlers. 527263693Sloos */ 528263693Sloos ctx = device_get_sysctl_ctx(sc->sc_dev); 529263693Sloos tree_node = device_get_sysctl_tree(sc->sc_dev); 530263693Sloos tree = SYSCTL_CHILDREN(tree_node); 531263693Sloos SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clockdiv", 532263693Sloos CTLFLAG_RW | CTLTYPE_UINT, sc, 0, 533263693Sloos ti_adc_clockdiv_proc, "IU", "ADC clock prescaler"); 534263693Sloos inp_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "ain", 535263693Sloos CTLFLAG_RD, NULL, "ADC inputs"); 536263693Sloos inp_tree = SYSCTL_CHILDREN(inp_node); 537263693Sloos 538298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 539298802Sgonzo ain = sc->sc_adc_channels[i]; 540263693Sloos 541263693Sloos snprintf(pinbuf, sizeof(pinbuf), "%d", ain); 542263693Sloos inpN_node = SYSCTL_ADD_NODE(ctx, inp_tree, OID_AUTO, pinbuf, 543263693Sloos CTLFLAG_RD, NULL, "ADC input"); 544263693Sloos inpN_tree = SYSCTL_CHILDREN(inpN_node); 545263693Sloos 546263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "enable", 547263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 548263693Sloos ti_adc_enable_proc, "IU", "Enable ADC input"); 549263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "open_delay", 550263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 551263693Sloos ti_adc_open_delay_proc, "IU", "ADC open delay"); 552263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "samples_avg", 553263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 554263693Sloos ti_adc_samples_avg_proc, "IU", "ADC samples average"); 555263693Sloos SYSCTL_ADD_INT(ctx, inpN_tree, OID_AUTO, "input", 556263693Sloos CTLFLAG_RD, &ti_adc_inputs[ain].value, 0, 557263693Sloos "Converted raw value for the ADC input"); 558263693Sloos } 559263693Sloos} 560263693Sloos 561263693Sloosstatic void 562263693Sloosti_adc_inputs_init(struct ti_adc_softc *sc) 563263693Sloos{ 564298802Sgonzo int ain, i; 565263693Sloos struct ti_adc_input *input; 566263693Sloos 567263693Sloos TI_ADC_LOCK(sc); 568298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 569298802Sgonzo ain = sc->sc_adc_channels[i]; 570263693Sloos input = &ti_adc_inputs[ain]; 571263693Sloos input->sc = sc; 572263693Sloos input->input = ain; 573263693Sloos input->value = 0; 574263693Sloos input->enable = 0; 575263693Sloos input->samples = 0; 576263693Sloos ti_adc_input_setup(sc, ain); 577263693Sloos } 578263693Sloos TI_ADC_UNLOCK(sc); 579263693Sloos} 580263693Sloos 581263693Sloosstatic void 582298802Sgonzoti_adc_tsc_init(struct ti_adc_softc *sc) 583263693Sloos{ 584298802Sgonzo int i, start_step, end_step; 585298802Sgonzo uint32_t stepconfig, val; 586263693Sloos 587298802Sgonzo TI_ADC_LOCK(sc); 588298802Sgonzo 589298802Sgonzo /* X coordinates */ 590298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 591298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_xp_bit; 592298802Sgonzo if (sc->sc_tsc_wires == 4) 593298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yp_inp) | sc->sc_xn_bit; 594298802Sgonzo else if (sc->sc_tsc_wires == 5) 595298802Sgonzo stepconfig |= ADC_STEP_INP(4) | 596298802Sgonzo sc->sc_xn_bit | sc->sc_yn_bit | sc->sc_yp_bit; 597298802Sgonzo else if (sc->sc_tsc_wires == 8) 598298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yp_inp) | sc->sc_xn_bit; 599298802Sgonzo 600298802Sgonzo start_step = ADC_STEPS - sc->sc_coord_readouts + 1; 601298802Sgonzo end_step = start_step + sc->sc_coord_readouts - 1; 602298802Sgonzo for (i = start_step; i <= end_step; i++) { 603298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(i), stepconfig); 604298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(i), STEPDLY_OPEN); 605298802Sgonzo } 606298802Sgonzo 607298802Sgonzo /* Y coordinates */ 608298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 609298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_yn_bit | 610298802Sgonzo ADC_STEP_INM(8); 611298802Sgonzo if (sc->sc_tsc_wires == 4) 612298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_xp_inp) | sc->sc_yp_bit; 613298802Sgonzo else if (sc->sc_tsc_wires == 5) 614298802Sgonzo stepconfig |= ADC_STEP_INP(4) | 615298802Sgonzo sc->sc_xp_bit | sc->sc_xn_bit | sc->sc_yp_bit; 616298802Sgonzo else if (sc->sc_tsc_wires == 8) 617298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_xp_inp) | sc->sc_yp_bit; 618298802Sgonzo 619298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts*2 + 2) + 1; 620298802Sgonzo end_step = start_step + sc->sc_coord_readouts - 1; 621298802Sgonzo for (i = start_step; i <= end_step; i++) { 622298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(i), stepconfig); 623298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(i), STEPDLY_OPEN); 624298802Sgonzo } 625298802Sgonzo 626298802Sgonzo /* Charge config */ 627263693Sloos val = ADC_READ4(sc, ADC_IDLECONFIG); 628298802Sgonzo ADC_WRITE4(sc, ADC_TC_CHARGE_STEPCONFIG, val); 629298802Sgonzo ADC_WRITE4(sc, ADC_TC_CHARGE_DELAY, sc->sc_charge_delay); 630263693Sloos 631298802Sgonzo /* 2 steps for Z */ 632298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts + 2) + 1; 633298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 634298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_yp_bit | 635298802Sgonzo sc->sc_xn_bit | ADC_STEP_INP(sc->sc_xp_inp) | 636298802Sgonzo ADC_STEP_INM(8); 637298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(start_step), stepconfig); 638298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(start_step), STEPDLY_OPEN); 639298802Sgonzo start_step++; 640298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yn_inp); 641298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(start_step), stepconfig); 642298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(start_step), STEPDLY_OPEN); 643263693Sloos 644298802Sgonzo ADC_WRITE4(sc, ADC_FIFO1THRESHOLD, (sc->sc_coord_readouts*2 + 2) - 1); 645263693Sloos 646298802Sgonzo sc->sc_tsc_enabled = 1; 647298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts*2 + 2) + 1; 648298802Sgonzo end_step = ADC_STEPS; 649298802Sgonzo for (i = start_step; i <= end_step; i++) { 650298802Sgonzo sc->sc_tsc_enabled |= (1 << i); 651298802Sgonzo } 652263693Sloos 653263693Sloos 654298802Sgonzo TI_ADC_UNLOCK(sc); 655298802Sgonzo} 656298802Sgonzo 657298802Sgonzostatic void 658298802Sgonzoti_adc_idlestep_init(struct ti_adc_softc *sc) 659298802Sgonzo{ 660298802Sgonzo uint32_t val; 661298802Sgonzo 662298802Sgonzo val = ADC_STEP_YNN_SW | ADC_STEP_INM(8) | ADC_STEP_INP(8) | ADC_STEP_YPN_SW; 663298802Sgonzo 664263693Sloos ADC_WRITE4(sc, ADC_IDLECONFIG, val); 665263693Sloos} 666263693Sloos 667263693Sloosstatic int 668298802Sgonzoti_adc_config_wires(struct ti_adc_softc *sc, int *wire_configs, int nwire_configs) 669298802Sgonzo{ 670298802Sgonzo int i; 671298802Sgonzo int wire, ai; 672298802Sgonzo 673298802Sgonzo for (i = 0; i < nwire_configs; i++) { 674298802Sgonzo wire = wire_configs[i] & 0xf; 675298802Sgonzo ai = (wire_configs[i] >> 4) & 0xf; 676298802Sgonzo switch (wire) { 677298802Sgonzo case ORDER_XP: 678298802Sgonzo sc->sc_xp_bit = ADC_STEP_XPP_SW; 679298802Sgonzo sc->sc_xp_inp = ai; 680298802Sgonzo break; 681298802Sgonzo case ORDER_XN: 682298802Sgonzo sc->sc_xn_bit = ADC_STEP_XNN_SW; 683298802Sgonzo sc->sc_xn_inp = ai; 684298802Sgonzo break; 685298802Sgonzo case ORDER_YP: 686298802Sgonzo sc->sc_yp_bit = ADC_STEP_YPP_SW; 687298802Sgonzo sc->sc_yp_inp = ai; 688298802Sgonzo break; 689298802Sgonzo case ORDER_YN: 690298802Sgonzo sc->sc_yn_bit = ADC_STEP_YNN_SW; 691298802Sgonzo sc->sc_yn_inp = ai; 692298802Sgonzo break; 693298802Sgonzo default: 694298802Sgonzo device_printf(sc->sc_dev, "Invalid wire config\n"); 695298802Sgonzo return (-1); 696298802Sgonzo } 697298802Sgonzo } 698298802Sgonzo return (0); 699298802Sgonzo} 700298802Sgonzo 701298802Sgonzostatic int 702263693Sloosti_adc_probe(device_t dev) 703263693Sloos{ 704263693Sloos 705283276Sgonzo if (!ofw_bus_is_compatible(dev, "ti,am3359-tscadc")) 706263693Sloos return (ENXIO); 707263693Sloos device_set_desc(dev, "TI ADC controller"); 708263693Sloos 709263693Sloos return (BUS_PROBE_DEFAULT); 710263693Sloos} 711263693Sloos 712263693Sloosstatic int 713263693Sloosti_adc_attach(device_t dev) 714263693Sloos{ 715298802Sgonzo int err, rid, i; 716263693Sloos struct ti_adc_softc *sc; 717298802Sgonzo uint32_t rev, reg; 718298802Sgonzo phandle_t node, child; 719298802Sgonzo pcell_t cell; 720298802Sgonzo int *channels; 721298802Sgonzo int nwire_configs; 722298802Sgonzo int *wire_configs; 723263693Sloos 724263693Sloos sc = device_get_softc(dev); 725263693Sloos sc->sc_dev = dev; 726263693Sloos 727298802Sgonzo node = ofw_bus_get_node(dev); 728297134Sloos 729298802Sgonzo sc->sc_tsc_wires = 0; 730298802Sgonzo sc->sc_coord_readouts = 1; 731298802Sgonzo sc->sc_x_plate_resistance = 0; 732298802Sgonzo sc->sc_charge_delay = DEFAULT_CHARGE_DELAY; 733298802Sgonzo /* Read "tsc" node properties */ 734298802Sgonzo child = ofw_bus_find_child(node, "tsc"); 735300769Sloos if (child != 0 && OF_hasprop(child, "ti,wires")) { 736298802Sgonzo if ((OF_getprop(child, "ti,wires", &cell, sizeof(cell))) > 0) 737298802Sgonzo sc->sc_tsc_wires = fdt32_to_cpu(cell); 738298802Sgonzo if ((OF_getprop(child, "ti,coordinate-readouts", &cell, sizeof(cell))) > 0) 739298802Sgonzo sc->sc_coord_readouts = fdt32_to_cpu(cell); 740298802Sgonzo if ((OF_getprop(child, "ti,x-plate-resistance", &cell, sizeof(cell))) > 0) 741298802Sgonzo sc->sc_x_plate_resistance = fdt32_to_cpu(cell); 742298802Sgonzo if ((OF_getprop(child, "ti,charge-delay", &cell, sizeof(cell))) > 0) 743298802Sgonzo sc->sc_charge_delay = fdt32_to_cpu(cell); 744298802Sgonzo nwire_configs = OF_getencprop_alloc(child, "ti,wire-config", 745298802Sgonzo sizeof(*wire_configs), (void **)&wire_configs); 746298802Sgonzo if (nwire_configs != sc->sc_tsc_wires) { 747298802Sgonzo device_printf(sc->sc_dev, 748300769Sloos "invalid number of ti,wire-config: %d (should be %d)\n", 749298802Sgonzo nwire_configs, sc->sc_tsc_wires); 750299477Sgonzo OF_prop_free(wire_configs); 751298802Sgonzo return (EINVAL); 752298802Sgonzo } 753298802Sgonzo err = ti_adc_config_wires(sc, wire_configs, nwire_configs); 754299477Sgonzo OF_prop_free(wire_configs); 755298802Sgonzo if (err) 756298802Sgonzo return (EINVAL); 757298802Sgonzo } 758298802Sgonzo 759298802Sgonzo /* Read "adc" node properties */ 760298802Sgonzo child = ofw_bus_find_child(node, "adc"); 761298802Sgonzo if (child != 0) { 762298802Sgonzo sc->sc_adc_nchannels = OF_getencprop_alloc(child, "ti,adc-channels", 763298802Sgonzo sizeof(*channels), (void **)&channels); 764298802Sgonzo if (sc->sc_adc_nchannels > 0) { 765298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) 766298802Sgonzo sc->sc_adc_channels[i] = channels[i]; 767299477Sgonzo OF_prop_free(channels); 768298802Sgonzo } 769298802Sgonzo } 770298802Sgonzo 771298802Sgonzo /* Sanity check FDT data */ 772298802Sgonzo if (sc->sc_tsc_wires + sc->sc_adc_nchannels > TI_ADC_NPINS) { 773298802Sgonzo device_printf(dev, "total number of chanels (%d) is larger than %d\n", 774298802Sgonzo sc->sc_tsc_wires + sc->sc_adc_nchannels, TI_ADC_NPINS); 775298802Sgonzo return (ENXIO); 776298802Sgonzo } 777298802Sgonzo 778263693Sloos rid = 0; 779263693Sloos sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 780263693Sloos RF_ACTIVE); 781263693Sloos if (!sc->sc_mem_res) { 782263693Sloos device_printf(dev, "cannot allocate memory window\n"); 783263693Sloos return (ENXIO); 784263693Sloos } 785263693Sloos 786298802Sgonzo /* Activate the ADC_TSC module. */ 787298802Sgonzo err = ti_prcm_clk_enable(TSC_ADC_CLK); 788298802Sgonzo if (err) 789298802Sgonzo return (err); 790298802Sgonzo 791263693Sloos rid = 0; 792263693Sloos sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 793263693Sloos RF_ACTIVE); 794263693Sloos if (!sc->sc_irq_res) { 795263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 796263693Sloos device_printf(dev, "cannot allocate interrupt\n"); 797263693Sloos return (ENXIO); 798263693Sloos } 799263693Sloos 800263693Sloos if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 801263693Sloos NULL, ti_adc_intr, sc, &sc->sc_intrhand) != 0) { 802263693Sloos bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 803263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 804263693Sloos device_printf(dev, "Unable to setup the irq handler.\n"); 805263693Sloos return (ENXIO); 806263693Sloos } 807263693Sloos 808263693Sloos /* Check the ADC revision. */ 809263693Sloos rev = ADC_READ4(sc, ADC_REVISION); 810263693Sloos device_printf(dev, 811263693Sloos "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n", 812263693Sloos (rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT, 813263693Sloos (rev & ADC_REV_FUNC_MSK) >> ADC_REV_FUNC_SHIFT, 814263693Sloos (rev & ADC_REV_RTL_MSK) >> ADC_REV_RTL_SHIFT, 815263693Sloos (rev & ADC_REV_MAJOR_MSK) >> ADC_REV_MAJOR_SHIFT, 816263693Sloos rev & ADC_REV_MINOR_MSK, 817263693Sloos (rev & ADC_REV_CUSTOM_MSK) >> ADC_REV_CUSTOM_SHIFT); 818263693Sloos 819263693Sloos reg = ADC_READ4(sc, ADC_CTRL); 820263693Sloos ADC_WRITE4(sc, ADC_CTRL, reg | ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID); 821263693Sloos 822263693Sloos /* 823298802Sgonzo * Set the ADC prescaler to 2400 if touchscreen is not enabled 824298802Sgonzo * and to 24 if it is. This sets the ADC clock to ~10Khz and 825298802Sgonzo * ~1Mhz respectively (CLK_M_OSC / prescaler). 826263693Sloos */ 827298802Sgonzo if (sc->sc_tsc_wires) 828298802Sgonzo ADC_WRITE4(sc, ADC_CLKDIV, 24 - 1); 829298802Sgonzo else 830298802Sgonzo ADC_WRITE4(sc, ADC_CLKDIV, 2400 - 1); 831263693Sloos 832263693Sloos TI_ADC_LOCK_INIT(sc); 833263693Sloos 834263693Sloos ti_adc_idlestep_init(sc); 835263693Sloos ti_adc_inputs_init(sc); 836263693Sloos ti_adc_sysctl_init(sc); 837298802Sgonzo ti_adc_tsc_init(sc); 838263693Sloos 839298802Sgonzo TI_ADC_LOCK(sc); 840298802Sgonzo ti_adc_setup(sc); 841298802Sgonzo TI_ADC_UNLOCK(sc); 842298802Sgonzo 843263693Sloos return (0); 844263693Sloos} 845263693Sloos 846263693Sloosstatic int 847263693Sloosti_adc_detach(device_t dev) 848263693Sloos{ 849263693Sloos struct ti_adc_softc *sc; 850263693Sloos 851263693Sloos sc = device_get_softc(dev); 852263693Sloos 853263693Sloos /* Turn off the ADC. */ 854263693Sloos TI_ADC_LOCK(sc); 855263693Sloos ti_adc_reset(sc); 856263693Sloos ti_adc_setup(sc); 857263693Sloos TI_ADC_UNLOCK(sc); 858263693Sloos 859263693Sloos TI_ADC_LOCK_DESTROY(sc); 860263693Sloos 861263693Sloos if (sc->sc_intrhand) 862263693Sloos bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand); 863263693Sloos if (sc->sc_irq_res) 864263693Sloos bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 865263693Sloos if (sc->sc_mem_res) 866263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 867263693Sloos 868263693Sloos return (bus_generic_detach(dev)); 869263693Sloos} 870263693Sloos 871263693Sloosstatic device_method_t ti_adc_methods[] = { 872263693Sloos DEVMETHOD(device_probe, ti_adc_probe), 873263693Sloos DEVMETHOD(device_attach, ti_adc_attach), 874263693Sloos DEVMETHOD(device_detach, ti_adc_detach), 875263693Sloos 876263693Sloos DEVMETHOD_END 877263693Sloos}; 878263693Sloos 879263693Sloosstatic driver_t ti_adc_driver = { 880263693Sloos "ti_adc", 881263693Sloos ti_adc_methods, 882263693Sloos sizeof(struct ti_adc_softc), 883263693Sloos}; 884263693Sloos 885263693Sloosstatic devclass_t ti_adc_devclass; 886263693Sloos 887263693SloosDRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0); 888263693SloosMODULE_VERSION(ti_adc, 1); 889263693SloosMODULE_DEPEND(ti_adc, simplebus, 1, 1, 1); 890