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: stable/11/sys/arm/ti/ti_adc.c 314503 2017-03-01 18:53:05Z ian $"); 29263693Sloos 30307762Sgonzo#include "opt_evdev.h" 31307762Sgonzo 32263693Sloos#include <sys/param.h> 33263693Sloos#include <sys/systm.h> 34263693Sloos#include <sys/bus.h> 35263693Sloos 36298802Sgonzo#include <sys/conf.h> 37263693Sloos#include <sys/kernel.h> 38263693Sloos#include <sys/limits.h> 39263693Sloos#include <sys/lock.h> 40263693Sloos#include <sys/module.h> 41263693Sloos#include <sys/mutex.h> 42298802Sgonzo#include <sys/condvar.h> 43263693Sloos#include <sys/resource.h> 44263693Sloos#include <sys/rman.h> 45263693Sloos#include <sys/sysctl.h> 46298802Sgonzo#include <sys/selinfo.h> 47298802Sgonzo#include <sys/poll.h> 48298802Sgonzo#include <sys/uio.h> 49263693Sloos 50263693Sloos#include <machine/bus.h> 51263693Sloos 52263693Sloos#include <dev/ofw/openfirm.h> 53263693Sloos#include <dev/ofw/ofw_bus.h> 54263693Sloos#include <dev/ofw/ofw_bus_subr.h> 55263693Sloos 56307775Sgonzo#ifdef EVDEV_SUPPORT 57307762Sgonzo#include <dev/evdev/input.h> 58307762Sgonzo#include <dev/evdev/evdev.h> 59307762Sgonzo#endif 60307762Sgonzo 61263693Sloos#include <arm/ti/ti_prcm.h> 62263693Sloos#include <arm/ti/ti_adcreg.h> 63263693Sloos#include <arm/ti/ti_adcvar.h> 64263693Sloos 65298802Sgonzo#undef DEBUG_TSC 66298802Sgonzo 67298802Sgonzo#define DEFAULT_CHARGE_DELAY 0x400 68298802Sgonzo#define STEPDLY_OPEN 0x98 69298802Sgonzo 70298802Sgonzo#define ORDER_XP 0 71298802Sgonzo#define ORDER_XN 1 72298802Sgonzo#define ORDER_YP 2 73298802Sgonzo#define ORDER_YN 3 74298802Sgonzo 75266960Sloos/* Define our 8 steps, one for each input channel. */ 76263693Sloosstatic struct ti_adc_input ti_adc_inputs[TI_ADC_NPINS] = { 77298802Sgonzo { .stepconfig = ADC_STEPCFG(1), .stepdelay = ADC_STEPDLY(1) }, 78298802Sgonzo { .stepconfig = ADC_STEPCFG(2), .stepdelay = ADC_STEPDLY(2) }, 79298802Sgonzo { .stepconfig = ADC_STEPCFG(3), .stepdelay = ADC_STEPDLY(3) }, 80298802Sgonzo { .stepconfig = ADC_STEPCFG(4), .stepdelay = ADC_STEPDLY(4) }, 81298802Sgonzo { .stepconfig = ADC_STEPCFG(5), .stepdelay = ADC_STEPDLY(5) }, 82298802Sgonzo { .stepconfig = ADC_STEPCFG(6), .stepdelay = ADC_STEPDLY(6) }, 83298802Sgonzo { .stepconfig = ADC_STEPCFG(7), .stepdelay = ADC_STEPDLY(7) }, 84298802Sgonzo { .stepconfig = ADC_STEPCFG(8), .stepdelay = ADC_STEPDLY(8) }, 85263693Sloos}; 86263693Sloos 87263693Sloosstatic int ti_adc_samples[5] = { 0, 2, 4, 8, 16 }; 88263693Sloos 89307762Sgonzostatic int ti_adc_detach(device_t dev); 90307762Sgonzo 91307775Sgonzo#ifdef EVDEV_SUPPORT 92263693Sloosstatic void 93307762Sgonzoti_adc_ev_report(struct ti_adc_softc *sc) 94307762Sgonzo{ 95307762Sgonzo 96307762Sgonzo evdev_push_event(sc->sc_evdev, EV_ABS, ABS_X, sc->sc_x); 97307762Sgonzo evdev_push_event(sc->sc_evdev, EV_ABS, ABS_Y, sc->sc_y); 98307762Sgonzo evdev_push_event(sc->sc_evdev, EV_KEY, BTN_TOUCH, sc->sc_pen_down); 99307762Sgonzo evdev_sync(sc->sc_evdev); 100307762Sgonzo} 101307762Sgonzo#endif /* EVDEV */ 102307762Sgonzo 103307762Sgonzostatic void 104263693Sloosti_adc_enable(struct ti_adc_softc *sc) 105263693Sloos{ 106298802Sgonzo uint32_t reg; 107263693Sloos 108263693Sloos TI_ADC_LOCK_ASSERT(sc); 109263693Sloos 110263693Sloos if (sc->sc_last_state == 1) 111263693Sloos return; 112263693Sloos 113263693Sloos /* Enable the FIFO0 threshold and the end of sequence interrupt. */ 114263693Sloos ADC_WRITE4(sc, ADC_IRQENABLE_SET, 115298802Sgonzo ADC_IRQ_FIFO0_THRES | ADC_IRQ_FIFO1_THRES | ADC_IRQ_END_OF_SEQ); 116263693Sloos 117298802Sgonzo reg = ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID; 118298802Sgonzo if (sc->sc_tsc_wires > 0) { 119298802Sgonzo reg |= ADC_CTRL_TSC_ENABLE; 120298802Sgonzo switch (sc->sc_tsc_wires) { 121298802Sgonzo case 4: 122298802Sgonzo reg |= ADC_CTRL_TSC_4WIRE; 123298802Sgonzo break; 124298802Sgonzo case 5: 125298802Sgonzo reg |= ADC_CTRL_TSC_5WIRE; 126298802Sgonzo break; 127298802Sgonzo case 8: 128298802Sgonzo reg |= ADC_CTRL_TSC_8WIRE; 129298802Sgonzo break; 130298802Sgonzo default: 131298802Sgonzo break; 132298802Sgonzo } 133298802Sgonzo } 134298802Sgonzo reg |= ADC_CTRL_ENABLE; 135263693Sloos /* Enable the ADC. Run thru enabled steps, start the conversions. */ 136298802Sgonzo ADC_WRITE4(sc, ADC_CTRL, reg); 137263693Sloos 138263693Sloos sc->sc_last_state = 1; 139263693Sloos} 140263693Sloos 141263693Sloosstatic void 142263693Sloosti_adc_disable(struct ti_adc_softc *sc) 143263693Sloos{ 144263693Sloos int count; 145263693Sloos uint32_t data; 146263693Sloos 147263693Sloos TI_ADC_LOCK_ASSERT(sc); 148263693Sloos 149263693Sloos if (sc->sc_last_state == 0) 150263693Sloos return; 151263693Sloos 152263693Sloos /* Disable all the enabled steps. */ 153263693Sloos ADC_WRITE4(sc, ADC_STEPENABLE, 0); 154263693Sloos 155263693Sloos /* Disable the ADC. */ 156263693Sloos ADC_WRITE4(sc, ADC_CTRL, ADC_READ4(sc, ADC_CTRL) & ~ADC_CTRL_ENABLE); 157263693Sloos 158263693Sloos /* Disable the FIFO0 threshold and the end of sequence interrupt. */ 159263693Sloos ADC_WRITE4(sc, ADC_IRQENABLE_CLR, 160298802Sgonzo ADC_IRQ_FIFO0_THRES | ADC_IRQ_FIFO1_THRES | ADC_IRQ_END_OF_SEQ); 161263693Sloos 162263693Sloos /* ACK any pending interrupt. */ 163263693Sloos ADC_WRITE4(sc, ADC_IRQSTATUS, ADC_READ4(sc, ADC_IRQSTATUS)); 164263693Sloos 165263693Sloos /* Drain the FIFO data. */ 166263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 167263693Sloos while (count > 0) { 168263693Sloos data = ADC_READ4(sc, ADC_FIFO0DATA); 169263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 170263693Sloos } 171263693Sloos 172298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 173298802Sgonzo while (count > 0) { 174298802Sgonzo data = ADC_READ4(sc, ADC_FIFO1DATA); 175298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 176298802Sgonzo } 177298802Sgonzo 178263693Sloos sc->sc_last_state = 0; 179263693Sloos} 180263693Sloos 181263693Sloosstatic int 182263693Sloosti_adc_setup(struct ti_adc_softc *sc) 183263693Sloos{ 184298802Sgonzo int ain, i; 185263693Sloos uint32_t enabled; 186263693Sloos 187263693Sloos TI_ADC_LOCK_ASSERT(sc); 188263693Sloos 189263693Sloos /* Check for enabled inputs. */ 190298802Sgonzo enabled = sc->sc_tsc_enabled; 191298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 192298802Sgonzo ain = sc->sc_adc_channels[i]; 193263693Sloos if (ti_adc_inputs[ain].enable) 194263693Sloos enabled |= (1U << (ain + 1)); 195263693Sloos } 196263693Sloos 197263693Sloos /* Set the ADC global status. */ 198263693Sloos if (enabled != 0) { 199263693Sloos ti_adc_enable(sc); 200263693Sloos /* Update the enabled steps. */ 201263693Sloos if (enabled != ADC_READ4(sc, ADC_STEPENABLE)) 202263693Sloos ADC_WRITE4(sc, ADC_STEPENABLE, enabled); 203263693Sloos } else 204263693Sloos ti_adc_disable(sc); 205263693Sloos 206263693Sloos return (0); 207263693Sloos} 208263693Sloos 209263693Sloosstatic void 210263693Sloosti_adc_input_setup(struct ti_adc_softc *sc, int32_t ain) 211263693Sloos{ 212263693Sloos struct ti_adc_input *input; 213263693Sloos uint32_t reg, val; 214263693Sloos 215263693Sloos TI_ADC_LOCK_ASSERT(sc); 216263693Sloos 217263693Sloos input = &ti_adc_inputs[ain]; 218263693Sloos reg = input->stepconfig; 219263693Sloos val = ADC_READ4(sc, reg); 220263693Sloos 221263693Sloos /* Set single ended operation. */ 222263693Sloos val &= ~ADC_STEP_DIFF_CNTRL; 223263693Sloos 224263693Sloos /* Set the negative voltage reference. */ 225263693Sloos val &= ~ADC_STEP_RFM_MSK; 226263693Sloos 227263693Sloos /* Set the positive voltage reference. */ 228263693Sloos val &= ~ADC_STEP_RFP_MSK; 229263693Sloos 230263693Sloos /* Set the samples average. */ 231263693Sloos val &= ~ADC_STEP_AVG_MSK; 232263693Sloos val |= input->samples << ADC_STEP_AVG_SHIFT; 233263693Sloos 234263693Sloos /* Select the desired input. */ 235263693Sloos val &= ~ADC_STEP_INP_MSK; 236263693Sloos val |= ain << ADC_STEP_INP_SHIFT; 237263693Sloos 238263693Sloos /* Set the ADC to one-shot mode. */ 239263693Sloos val &= ~ADC_STEP_MODE_MSK; 240263693Sloos 241263693Sloos ADC_WRITE4(sc, reg, val); 242263693Sloos} 243263693Sloos 244263693Sloosstatic void 245263693Sloosti_adc_reset(struct ti_adc_softc *sc) 246263693Sloos{ 247298802Sgonzo int ain, i; 248263693Sloos 249263693Sloos TI_ADC_LOCK_ASSERT(sc); 250263693Sloos 251263693Sloos /* Disable all the inputs. */ 252298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 253298802Sgonzo ain = sc->sc_adc_channels[i]; 254263693Sloos ti_adc_inputs[ain].enable = 0; 255298802Sgonzo } 256263693Sloos} 257263693Sloos 258263693Sloosstatic int 259263693Sloosti_adc_clockdiv_proc(SYSCTL_HANDLER_ARGS) 260263693Sloos{ 261263693Sloos int error, reg; 262263693Sloos struct ti_adc_softc *sc; 263263693Sloos 264263693Sloos sc = (struct ti_adc_softc *)arg1; 265263693Sloos 266263693Sloos TI_ADC_LOCK(sc); 267263693Sloos reg = (int)ADC_READ4(sc, ADC_CLKDIV) + 1; 268263693Sloos TI_ADC_UNLOCK(sc); 269263693Sloos 270263693Sloos error = sysctl_handle_int(oidp, ®, sizeof(reg), req); 271263693Sloos if (error != 0 || req->newptr == NULL) 272263693Sloos return (error); 273263693Sloos 274263693Sloos /* 275263693Sloos * The actual written value is the prescaler setting - 1. 276263693Sloos * Enforce a minimum value of 10 (i.e. 9) which limits the maximum 277263693Sloos * ADC clock to ~2.4Mhz (CLK_M_OSC / 10). 278263693Sloos */ 279263693Sloos reg--; 280263693Sloos if (reg < 9) 281263693Sloos reg = 9; 282263693Sloos if (reg > USHRT_MAX) 283263693Sloos reg = USHRT_MAX; 284263693Sloos 285263693Sloos TI_ADC_LOCK(sc); 286263693Sloos /* Disable the ADC. */ 287263693Sloos ti_adc_disable(sc); 288263693Sloos /* Update the ADC prescaler setting. */ 289263693Sloos ADC_WRITE4(sc, ADC_CLKDIV, reg); 290263693Sloos /* Enable the ADC again. */ 291263693Sloos ti_adc_setup(sc); 292263693Sloos TI_ADC_UNLOCK(sc); 293263693Sloos 294263693Sloos return (0); 295263693Sloos} 296263693Sloos 297263693Sloosstatic int 298263693Sloosti_adc_enable_proc(SYSCTL_HANDLER_ARGS) 299263693Sloos{ 300263693Sloos int error; 301263693Sloos int32_t enable; 302263693Sloos struct ti_adc_softc *sc; 303263693Sloos struct ti_adc_input *input; 304263693Sloos 305263693Sloos input = (struct ti_adc_input *)arg1; 306263693Sloos sc = input->sc; 307263693Sloos 308263693Sloos enable = input->enable; 309263693Sloos error = sysctl_handle_int(oidp, &enable, sizeof(enable), 310263693Sloos req); 311263693Sloos if (error != 0 || req->newptr == NULL) 312263693Sloos return (error); 313263693Sloos 314263693Sloos if (enable) 315263693Sloos enable = 1; 316263693Sloos 317263693Sloos TI_ADC_LOCK(sc); 318263693Sloos /* Setup the ADC as needed. */ 319263693Sloos if (input->enable != enable) { 320263693Sloos input->enable = enable; 321263693Sloos ti_adc_setup(sc); 322263693Sloos if (input->enable == 0) 323263693Sloos input->value = 0; 324263693Sloos } 325263693Sloos TI_ADC_UNLOCK(sc); 326263693Sloos 327263693Sloos return (0); 328263693Sloos} 329263693Sloos 330263693Sloosstatic int 331263693Sloosti_adc_open_delay_proc(SYSCTL_HANDLER_ARGS) 332263693Sloos{ 333263693Sloos int error, reg; 334263693Sloos struct ti_adc_softc *sc; 335263693Sloos struct ti_adc_input *input; 336263693Sloos 337263693Sloos input = (struct ti_adc_input *)arg1; 338263693Sloos sc = input->sc; 339263693Sloos 340263693Sloos TI_ADC_LOCK(sc); 341263693Sloos reg = (int)ADC_READ4(sc, input->stepdelay) & ADC_STEP_OPEN_DELAY; 342263693Sloos TI_ADC_UNLOCK(sc); 343263693Sloos 344263693Sloos error = sysctl_handle_int(oidp, ®, sizeof(reg), req); 345263693Sloos if (error != 0 || req->newptr == NULL) 346263693Sloos return (error); 347263693Sloos 348263693Sloos if (reg < 0) 349263693Sloos reg = 0; 350263693Sloos 351263693Sloos TI_ADC_LOCK(sc); 352263693Sloos ADC_WRITE4(sc, input->stepdelay, reg & ADC_STEP_OPEN_DELAY); 353263693Sloos TI_ADC_UNLOCK(sc); 354263693Sloos 355263693Sloos return (0); 356263693Sloos} 357263693Sloos 358263693Sloosstatic int 359263693Sloosti_adc_samples_avg_proc(SYSCTL_HANDLER_ARGS) 360263693Sloos{ 361263693Sloos int error, samples, i; 362263693Sloos struct ti_adc_softc *sc; 363263693Sloos struct ti_adc_input *input; 364263693Sloos 365263693Sloos input = (struct ti_adc_input *)arg1; 366263693Sloos sc = input->sc; 367263693Sloos 368263693Sloos if (input->samples > nitems(ti_adc_samples)) 369263693Sloos input->samples = nitems(ti_adc_samples); 370263693Sloos samples = ti_adc_samples[input->samples]; 371263693Sloos 372263693Sloos error = sysctl_handle_int(oidp, &samples, 0, req); 373263693Sloos if (error != 0 || req->newptr == NULL) 374263693Sloos return (error); 375263693Sloos 376263693Sloos TI_ADC_LOCK(sc); 377263693Sloos if (samples != ti_adc_samples[input->samples]) { 378263693Sloos input->samples = 0; 379263693Sloos for (i = 0; i < nitems(ti_adc_samples); i++) 380263693Sloos if (samples >= ti_adc_samples[i]) 381263693Sloos input->samples = i; 382263693Sloos ti_adc_input_setup(sc, input->input); 383263693Sloos } 384263693Sloos TI_ADC_UNLOCK(sc); 385263693Sloos 386263693Sloos return (error); 387263693Sloos} 388263693Sloos 389263693Sloosstatic void 390263693Sloosti_adc_read_data(struct ti_adc_softc *sc) 391263693Sloos{ 392263693Sloos int count, ain; 393263693Sloos struct ti_adc_input *input; 394263693Sloos uint32_t data; 395263693Sloos 396263693Sloos TI_ADC_LOCK_ASSERT(sc); 397263693Sloos 398263693Sloos /* Read the available data. */ 399263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 400263693Sloos while (count > 0) { 401263693Sloos data = ADC_READ4(sc, ADC_FIFO0DATA); 402263693Sloos ain = (data & ADC_FIFO_STEP_ID_MSK) >> ADC_FIFO_STEP_ID_SHIFT; 403263693Sloos input = &ti_adc_inputs[ain]; 404263693Sloos if (input->enable == 0) 405263693Sloos input->value = 0; 406263693Sloos else 407263693Sloos input->value = (int32_t)(data & ADC_FIFO_DATA_MSK); 408263693Sloos count = ADC_READ4(sc, ADC_FIFO0COUNT) & ADC_FIFO_COUNT_MSK; 409263693Sloos } 410263693Sloos} 411263693Sloos 412298802Sgonzostatic int 413298802Sgonzocmp_values(const void *a, const void *b) 414298802Sgonzo{ 415298802Sgonzo const uint32_t *v1, *v2; 416298802Sgonzo v1 = a; 417298802Sgonzo v2 = b; 418298802Sgonzo if (*v1 < *v2) 419298802Sgonzo return -1; 420298802Sgonzo if (*v1 > *v2) 421298802Sgonzo return 1; 422298802Sgonzo 423298802Sgonzo return (0); 424298802Sgonzo} 425298802Sgonzo 426263693Sloosstatic void 427298802Sgonzoti_adc_tsc_read_data(struct ti_adc_softc *sc) 428298802Sgonzo{ 429298802Sgonzo int count; 430298802Sgonzo uint32_t data[16]; 431298802Sgonzo uint32_t x, y; 432298802Sgonzo int i, start, end; 433298802Sgonzo 434298802Sgonzo TI_ADC_LOCK_ASSERT(sc); 435298802Sgonzo 436298802Sgonzo /* Read the available data. */ 437298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 438298802Sgonzo if (count == 0) 439298802Sgonzo return; 440298802Sgonzo 441298802Sgonzo i = 0; 442298802Sgonzo while (count > 0) { 443298802Sgonzo data[i++] = ADC_READ4(sc, ADC_FIFO1DATA) & ADC_FIFO_DATA_MSK; 444298802Sgonzo count = ADC_READ4(sc, ADC_FIFO1COUNT) & ADC_FIFO_COUNT_MSK; 445298802Sgonzo } 446298802Sgonzo 447298802Sgonzo if (sc->sc_coord_readouts > 3) { 448298802Sgonzo start = 1; 449298802Sgonzo end = sc->sc_coord_readouts - 1; 450298802Sgonzo qsort(data, sc->sc_coord_readouts, 451298802Sgonzo sizeof(data[0]), &cmp_values); 452298802Sgonzo qsort(&data[sc->sc_coord_readouts + 2], 453298802Sgonzo sc->sc_coord_readouts, 454298802Sgonzo sizeof(data[0]), &cmp_values); 455298802Sgonzo } 456298802Sgonzo else { 457298802Sgonzo start = 0; 458298802Sgonzo end = sc->sc_coord_readouts; 459298802Sgonzo } 460298802Sgonzo 461298802Sgonzo x = y = 0; 462298802Sgonzo for (i = start; i < end; i++) 463298802Sgonzo y += data[i]; 464298802Sgonzo y /= (end - start); 465298802Sgonzo 466298802Sgonzo for (i = sc->sc_coord_readouts + 2 + start; i < sc->sc_coord_readouts + 2 + end; i++) 467298802Sgonzo x += data[i]; 468298802Sgonzo x /= (end - start); 469298802Sgonzo 470298802Sgonzo#ifdef DEBUG_TSC 471298802Sgonzo device_printf(sc->sc_dev, "touchscreen x: %d, y: %d\n", x, y); 472298802Sgonzo#endif 473307762Sgonzo 474307775Sgonzo#ifdef EVDEV_SUPPORT 475307762Sgonzo if ((sc->sc_x != x) || (sc->sc_y != y)) { 476307762Sgonzo sc->sc_x = x; 477307762Sgonzo sc->sc_y = y; 478307762Sgonzo ti_adc_ev_report(sc); 479307762Sgonzo } 480307762Sgonzo#endif 481298802Sgonzo} 482298802Sgonzo 483298802Sgonzostatic void 484298802Sgonzoti_adc_intr_locked(struct ti_adc_softc *sc, uint32_t status) 485298802Sgonzo{ 486298802Sgonzo /* Read the available data. */ 487298802Sgonzo if (status & ADC_IRQ_FIFO0_THRES) 488298802Sgonzo ti_adc_read_data(sc); 489298802Sgonzo} 490298802Sgonzo 491298802Sgonzostatic void 492298802Sgonzoti_adc_tsc_intr_locked(struct ti_adc_softc *sc, uint32_t status) 493298802Sgonzo{ 494298802Sgonzo /* Read the available data. */ 495298802Sgonzo if (status & ADC_IRQ_FIFO1_THRES) 496298802Sgonzo ti_adc_tsc_read_data(sc); 497298802Sgonzo 498298802Sgonzo} 499298802Sgonzo 500298802Sgonzostatic void 501263693Sloosti_adc_intr(void *arg) 502263693Sloos{ 503263693Sloos struct ti_adc_softc *sc; 504298802Sgonzo uint32_t status, rawstatus; 505263693Sloos 506263693Sloos sc = (struct ti_adc_softc *)arg; 507263693Sloos 508298802Sgonzo TI_ADC_LOCK(sc); 509298802Sgonzo 510298802Sgonzo rawstatus = ADC_READ4(sc, ADC_IRQSTATUS_RAW); 511263693Sloos status = ADC_READ4(sc, ADC_IRQSTATUS); 512263693Sloos 513298802Sgonzo if (rawstatus & ADC_IRQ_HW_PEN_ASYNC) { 514298802Sgonzo sc->sc_pen_down = 1; 515298802Sgonzo status |= ADC_IRQ_HW_PEN_ASYNC; 516298802Sgonzo ADC_WRITE4(sc, ADC_IRQENABLE_CLR, 517298802Sgonzo ADC_IRQ_HW_PEN_ASYNC); 518307775Sgonzo#ifdef EVDEV_SUPPORT 519307762Sgonzo ti_adc_ev_report(sc); 520307762Sgonzo#endif 521298802Sgonzo } 522263693Sloos 523298802Sgonzo if (rawstatus & ADC_IRQ_PEN_UP) { 524298802Sgonzo sc->sc_pen_down = 0; 525298802Sgonzo status |= ADC_IRQ_PEN_UP; 526307775Sgonzo#ifdef EVDEV_SUPPORT 527307762Sgonzo ti_adc_ev_report(sc); 528307762Sgonzo#endif 529298802Sgonzo } 530298802Sgonzo 531263693Sloos if (status & ADC_IRQ_FIFO0_THRES) 532298802Sgonzo ti_adc_intr_locked(sc, status); 533263693Sloos 534298802Sgonzo if (status & ADC_IRQ_FIFO1_THRES) 535298802Sgonzo ti_adc_tsc_intr_locked(sc, status); 536298802Sgonzo 537298802Sgonzo if (status) { 538298802Sgonzo /* ACK the interrupt. */ 539298802Sgonzo ADC_WRITE4(sc, ADC_IRQSTATUS, status); 540298802Sgonzo } 541298802Sgonzo 542263693Sloos /* Start the next conversion ? */ 543263693Sloos if (status & ADC_IRQ_END_OF_SEQ) 544263693Sloos ti_adc_setup(sc); 545298802Sgonzo 546263693Sloos TI_ADC_UNLOCK(sc); 547263693Sloos} 548263693Sloos 549263693Sloosstatic void 550263693Sloosti_adc_sysctl_init(struct ti_adc_softc *sc) 551263693Sloos{ 552263693Sloos char pinbuf[3]; 553263693Sloos struct sysctl_ctx_list *ctx; 554263693Sloos struct sysctl_oid *tree_node, *inp_node, *inpN_node; 555263693Sloos struct sysctl_oid_list *tree, *inp_tree, *inpN_tree; 556298802Sgonzo int ain, i; 557263693Sloos 558263693Sloos /* 559263693Sloos * Add per-pin sysctl tree/handlers. 560263693Sloos */ 561263693Sloos ctx = device_get_sysctl_ctx(sc->sc_dev); 562263693Sloos tree_node = device_get_sysctl_tree(sc->sc_dev); 563263693Sloos tree = SYSCTL_CHILDREN(tree_node); 564263693Sloos SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clockdiv", 565263693Sloos CTLFLAG_RW | CTLTYPE_UINT, sc, 0, 566263693Sloos ti_adc_clockdiv_proc, "IU", "ADC clock prescaler"); 567263693Sloos inp_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "ain", 568263693Sloos CTLFLAG_RD, NULL, "ADC inputs"); 569263693Sloos inp_tree = SYSCTL_CHILDREN(inp_node); 570263693Sloos 571298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 572298802Sgonzo ain = sc->sc_adc_channels[i]; 573263693Sloos 574263693Sloos snprintf(pinbuf, sizeof(pinbuf), "%d", ain); 575263693Sloos inpN_node = SYSCTL_ADD_NODE(ctx, inp_tree, OID_AUTO, pinbuf, 576263693Sloos CTLFLAG_RD, NULL, "ADC input"); 577263693Sloos inpN_tree = SYSCTL_CHILDREN(inpN_node); 578263693Sloos 579263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "enable", 580263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 581263693Sloos ti_adc_enable_proc, "IU", "Enable ADC input"); 582263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "open_delay", 583263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 584263693Sloos ti_adc_open_delay_proc, "IU", "ADC open delay"); 585263693Sloos SYSCTL_ADD_PROC(ctx, inpN_tree, OID_AUTO, "samples_avg", 586263693Sloos CTLFLAG_RW | CTLTYPE_UINT, &ti_adc_inputs[ain], 0, 587263693Sloos ti_adc_samples_avg_proc, "IU", "ADC samples average"); 588263693Sloos SYSCTL_ADD_INT(ctx, inpN_tree, OID_AUTO, "input", 589263693Sloos CTLFLAG_RD, &ti_adc_inputs[ain].value, 0, 590263693Sloos "Converted raw value for the ADC input"); 591263693Sloos } 592263693Sloos} 593263693Sloos 594263693Sloosstatic void 595263693Sloosti_adc_inputs_init(struct ti_adc_softc *sc) 596263693Sloos{ 597298802Sgonzo int ain, i; 598263693Sloos struct ti_adc_input *input; 599263693Sloos 600263693Sloos TI_ADC_LOCK(sc); 601298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) { 602298802Sgonzo ain = sc->sc_adc_channels[i]; 603263693Sloos input = &ti_adc_inputs[ain]; 604263693Sloos input->sc = sc; 605263693Sloos input->input = ain; 606263693Sloos input->value = 0; 607263693Sloos input->enable = 0; 608263693Sloos input->samples = 0; 609263693Sloos ti_adc_input_setup(sc, ain); 610263693Sloos } 611263693Sloos TI_ADC_UNLOCK(sc); 612263693Sloos} 613263693Sloos 614263693Sloosstatic void 615298802Sgonzoti_adc_tsc_init(struct ti_adc_softc *sc) 616263693Sloos{ 617298802Sgonzo int i, start_step, end_step; 618298802Sgonzo uint32_t stepconfig, val; 619263693Sloos 620298802Sgonzo TI_ADC_LOCK(sc); 621298802Sgonzo 622298802Sgonzo /* X coordinates */ 623298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 624298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_xp_bit; 625298802Sgonzo if (sc->sc_tsc_wires == 4) 626298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yp_inp) | sc->sc_xn_bit; 627298802Sgonzo else if (sc->sc_tsc_wires == 5) 628298802Sgonzo stepconfig |= ADC_STEP_INP(4) | 629298802Sgonzo sc->sc_xn_bit | sc->sc_yn_bit | sc->sc_yp_bit; 630298802Sgonzo else if (sc->sc_tsc_wires == 8) 631298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yp_inp) | sc->sc_xn_bit; 632298802Sgonzo 633298802Sgonzo start_step = ADC_STEPS - sc->sc_coord_readouts + 1; 634298802Sgonzo end_step = start_step + sc->sc_coord_readouts - 1; 635298802Sgonzo for (i = start_step; i <= end_step; i++) { 636298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(i), stepconfig); 637298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(i), STEPDLY_OPEN); 638298802Sgonzo } 639298802Sgonzo 640298802Sgonzo /* Y coordinates */ 641298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 642298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_yn_bit | 643298802Sgonzo ADC_STEP_INM(8); 644298802Sgonzo if (sc->sc_tsc_wires == 4) 645298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_xp_inp) | sc->sc_yp_bit; 646298802Sgonzo else if (sc->sc_tsc_wires == 5) 647298802Sgonzo stepconfig |= ADC_STEP_INP(4) | 648298802Sgonzo sc->sc_xp_bit | sc->sc_xn_bit | sc->sc_yp_bit; 649298802Sgonzo else if (sc->sc_tsc_wires == 8) 650298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_xp_inp) | sc->sc_yp_bit; 651298802Sgonzo 652298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts*2 + 2) + 1; 653298802Sgonzo end_step = start_step + sc->sc_coord_readouts - 1; 654298802Sgonzo for (i = start_step; i <= end_step; i++) { 655298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(i), stepconfig); 656298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(i), STEPDLY_OPEN); 657298802Sgonzo } 658298802Sgonzo 659298802Sgonzo /* Charge config */ 660263693Sloos val = ADC_READ4(sc, ADC_IDLECONFIG); 661298802Sgonzo ADC_WRITE4(sc, ADC_TC_CHARGE_STEPCONFIG, val); 662298802Sgonzo ADC_WRITE4(sc, ADC_TC_CHARGE_DELAY, sc->sc_charge_delay); 663263693Sloos 664298802Sgonzo /* 2 steps for Z */ 665298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts + 2) + 1; 666298802Sgonzo stepconfig = ADC_STEP_FIFO1 | (4 << ADC_STEP_AVG_SHIFT) | 667298802Sgonzo ADC_STEP_MODE_HW_ONESHOT | sc->sc_yp_bit | 668298802Sgonzo sc->sc_xn_bit | ADC_STEP_INP(sc->sc_xp_inp) | 669298802Sgonzo ADC_STEP_INM(8); 670298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(start_step), stepconfig); 671298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(start_step), STEPDLY_OPEN); 672298802Sgonzo start_step++; 673298802Sgonzo stepconfig |= ADC_STEP_INP(sc->sc_yn_inp); 674298802Sgonzo ADC_WRITE4(sc, ADC_STEPCFG(start_step), stepconfig); 675298802Sgonzo ADC_WRITE4(sc, ADC_STEPDLY(start_step), STEPDLY_OPEN); 676263693Sloos 677298802Sgonzo ADC_WRITE4(sc, ADC_FIFO1THRESHOLD, (sc->sc_coord_readouts*2 + 2) - 1); 678263693Sloos 679298802Sgonzo sc->sc_tsc_enabled = 1; 680298802Sgonzo start_step = ADC_STEPS - (sc->sc_coord_readouts*2 + 2) + 1; 681298802Sgonzo end_step = ADC_STEPS; 682298802Sgonzo for (i = start_step; i <= end_step; i++) { 683298802Sgonzo sc->sc_tsc_enabled |= (1 << i); 684298802Sgonzo } 685263693Sloos 686263693Sloos 687298802Sgonzo TI_ADC_UNLOCK(sc); 688298802Sgonzo} 689298802Sgonzo 690298802Sgonzostatic void 691298802Sgonzoti_adc_idlestep_init(struct ti_adc_softc *sc) 692298802Sgonzo{ 693298802Sgonzo uint32_t val; 694298802Sgonzo 695298802Sgonzo val = ADC_STEP_YNN_SW | ADC_STEP_INM(8) | ADC_STEP_INP(8) | ADC_STEP_YPN_SW; 696298802Sgonzo 697263693Sloos ADC_WRITE4(sc, ADC_IDLECONFIG, val); 698263693Sloos} 699263693Sloos 700263693Sloosstatic int 701298802Sgonzoti_adc_config_wires(struct ti_adc_softc *sc, int *wire_configs, int nwire_configs) 702298802Sgonzo{ 703298802Sgonzo int i; 704298802Sgonzo int wire, ai; 705298802Sgonzo 706298802Sgonzo for (i = 0; i < nwire_configs; i++) { 707298802Sgonzo wire = wire_configs[i] & 0xf; 708298802Sgonzo ai = (wire_configs[i] >> 4) & 0xf; 709298802Sgonzo switch (wire) { 710298802Sgonzo case ORDER_XP: 711298802Sgonzo sc->sc_xp_bit = ADC_STEP_XPP_SW; 712298802Sgonzo sc->sc_xp_inp = ai; 713298802Sgonzo break; 714298802Sgonzo case ORDER_XN: 715298802Sgonzo sc->sc_xn_bit = ADC_STEP_XNN_SW; 716298802Sgonzo sc->sc_xn_inp = ai; 717298802Sgonzo break; 718298802Sgonzo case ORDER_YP: 719298802Sgonzo sc->sc_yp_bit = ADC_STEP_YPP_SW; 720298802Sgonzo sc->sc_yp_inp = ai; 721298802Sgonzo break; 722298802Sgonzo case ORDER_YN: 723298802Sgonzo sc->sc_yn_bit = ADC_STEP_YNN_SW; 724298802Sgonzo sc->sc_yn_inp = ai; 725298802Sgonzo break; 726298802Sgonzo default: 727298802Sgonzo device_printf(sc->sc_dev, "Invalid wire config\n"); 728298802Sgonzo return (-1); 729298802Sgonzo } 730298802Sgonzo } 731298802Sgonzo return (0); 732298802Sgonzo} 733298802Sgonzo 734298802Sgonzostatic int 735263693Sloosti_adc_probe(device_t dev) 736263693Sloos{ 737263693Sloos 738283276Sgonzo if (!ofw_bus_is_compatible(dev, "ti,am3359-tscadc")) 739263693Sloos return (ENXIO); 740263693Sloos device_set_desc(dev, "TI ADC controller"); 741263693Sloos 742263693Sloos return (BUS_PROBE_DEFAULT); 743263693Sloos} 744263693Sloos 745263693Sloosstatic int 746263693Sloosti_adc_attach(device_t dev) 747263693Sloos{ 748298802Sgonzo int err, rid, i; 749263693Sloos struct ti_adc_softc *sc; 750298802Sgonzo uint32_t rev, reg; 751298802Sgonzo phandle_t node, child; 752298802Sgonzo pcell_t cell; 753298802Sgonzo int *channels; 754298802Sgonzo int nwire_configs; 755298802Sgonzo int *wire_configs; 756263693Sloos 757263693Sloos sc = device_get_softc(dev); 758263693Sloos sc->sc_dev = dev; 759263693Sloos 760298802Sgonzo node = ofw_bus_get_node(dev); 761297134Sloos 762298802Sgonzo sc->sc_tsc_wires = 0; 763298802Sgonzo sc->sc_coord_readouts = 1; 764298802Sgonzo sc->sc_x_plate_resistance = 0; 765298802Sgonzo sc->sc_charge_delay = DEFAULT_CHARGE_DELAY; 766298802Sgonzo /* Read "tsc" node properties */ 767298802Sgonzo child = ofw_bus_find_child(node, "tsc"); 768300769Sloos if (child != 0 && OF_hasprop(child, "ti,wires")) { 769314503Sian if ((OF_getencprop(child, "ti,wires", &cell, sizeof(cell))) > 0) 770314503Sian sc->sc_tsc_wires = cell; 771314503Sian if ((OF_getencprop(child, "ti,coordinate-readouts", &cell, 772314503Sian sizeof(cell))) > 0) 773314503Sian sc->sc_coord_readouts = cell; 774314503Sian if ((OF_getencprop(child, "ti,x-plate-resistance", &cell, 775314503Sian sizeof(cell))) > 0) 776314503Sian sc->sc_x_plate_resistance = cell; 777314503Sian if ((OF_getencprop(child, "ti,charge-delay", &cell, 778314503Sian sizeof(cell))) > 0) 779314503Sian sc->sc_charge_delay = cell; 780298802Sgonzo nwire_configs = OF_getencprop_alloc(child, "ti,wire-config", 781298802Sgonzo sizeof(*wire_configs), (void **)&wire_configs); 782298802Sgonzo if (nwire_configs != sc->sc_tsc_wires) { 783298802Sgonzo device_printf(sc->sc_dev, 784300769Sloos "invalid number of ti,wire-config: %d (should be %d)\n", 785298802Sgonzo nwire_configs, sc->sc_tsc_wires); 786299477Sgonzo OF_prop_free(wire_configs); 787298802Sgonzo return (EINVAL); 788298802Sgonzo } 789298802Sgonzo err = ti_adc_config_wires(sc, wire_configs, nwire_configs); 790299477Sgonzo OF_prop_free(wire_configs); 791298802Sgonzo if (err) 792298802Sgonzo return (EINVAL); 793298802Sgonzo } 794298802Sgonzo 795298802Sgonzo /* Read "adc" node properties */ 796298802Sgonzo child = ofw_bus_find_child(node, "adc"); 797298802Sgonzo if (child != 0) { 798298802Sgonzo sc->sc_adc_nchannels = OF_getencprop_alloc(child, "ti,adc-channels", 799298802Sgonzo sizeof(*channels), (void **)&channels); 800298802Sgonzo if (sc->sc_adc_nchannels > 0) { 801298802Sgonzo for (i = 0; i < sc->sc_adc_nchannels; i++) 802298802Sgonzo sc->sc_adc_channels[i] = channels[i]; 803299477Sgonzo OF_prop_free(channels); 804298802Sgonzo } 805298802Sgonzo } 806298802Sgonzo 807298802Sgonzo /* Sanity check FDT data */ 808298802Sgonzo if (sc->sc_tsc_wires + sc->sc_adc_nchannels > TI_ADC_NPINS) { 809298802Sgonzo device_printf(dev, "total number of chanels (%d) is larger than %d\n", 810298802Sgonzo sc->sc_tsc_wires + sc->sc_adc_nchannels, TI_ADC_NPINS); 811298802Sgonzo return (ENXIO); 812298802Sgonzo } 813298802Sgonzo 814263693Sloos rid = 0; 815263693Sloos sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 816263693Sloos RF_ACTIVE); 817263693Sloos if (!sc->sc_mem_res) { 818263693Sloos device_printf(dev, "cannot allocate memory window\n"); 819263693Sloos return (ENXIO); 820263693Sloos } 821263693Sloos 822298802Sgonzo /* Activate the ADC_TSC module. */ 823298802Sgonzo err = ti_prcm_clk_enable(TSC_ADC_CLK); 824298802Sgonzo if (err) 825298802Sgonzo return (err); 826298802Sgonzo 827263693Sloos rid = 0; 828263693Sloos sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 829263693Sloos RF_ACTIVE); 830263693Sloos if (!sc->sc_irq_res) { 831263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 832263693Sloos device_printf(dev, "cannot allocate interrupt\n"); 833263693Sloos return (ENXIO); 834263693Sloos } 835263693Sloos 836263693Sloos if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 837263693Sloos NULL, ti_adc_intr, sc, &sc->sc_intrhand) != 0) { 838263693Sloos bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 839263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 840263693Sloos device_printf(dev, "Unable to setup the irq handler.\n"); 841263693Sloos return (ENXIO); 842263693Sloos } 843263693Sloos 844263693Sloos /* Check the ADC revision. */ 845263693Sloos rev = ADC_READ4(sc, ADC_REVISION); 846263693Sloos device_printf(dev, 847263693Sloos "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n", 848263693Sloos (rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT, 849263693Sloos (rev & ADC_REV_FUNC_MSK) >> ADC_REV_FUNC_SHIFT, 850263693Sloos (rev & ADC_REV_RTL_MSK) >> ADC_REV_RTL_SHIFT, 851263693Sloos (rev & ADC_REV_MAJOR_MSK) >> ADC_REV_MAJOR_SHIFT, 852263693Sloos rev & ADC_REV_MINOR_MSK, 853263693Sloos (rev & ADC_REV_CUSTOM_MSK) >> ADC_REV_CUSTOM_SHIFT); 854263693Sloos 855263693Sloos reg = ADC_READ4(sc, ADC_CTRL); 856263693Sloos ADC_WRITE4(sc, ADC_CTRL, reg | ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID); 857263693Sloos 858263693Sloos /* 859298802Sgonzo * Set the ADC prescaler to 2400 if touchscreen is not enabled 860298802Sgonzo * and to 24 if it is. This sets the ADC clock to ~10Khz and 861298802Sgonzo * ~1Mhz respectively (CLK_M_OSC / prescaler). 862263693Sloos */ 863298802Sgonzo if (sc->sc_tsc_wires) 864298802Sgonzo ADC_WRITE4(sc, ADC_CLKDIV, 24 - 1); 865298802Sgonzo else 866298802Sgonzo ADC_WRITE4(sc, ADC_CLKDIV, 2400 - 1); 867263693Sloos 868263693Sloos TI_ADC_LOCK_INIT(sc); 869263693Sloos 870263693Sloos ti_adc_idlestep_init(sc); 871263693Sloos ti_adc_inputs_init(sc); 872263693Sloos ti_adc_sysctl_init(sc); 873298802Sgonzo ti_adc_tsc_init(sc); 874263693Sloos 875298802Sgonzo TI_ADC_LOCK(sc); 876298802Sgonzo ti_adc_setup(sc); 877298802Sgonzo TI_ADC_UNLOCK(sc); 878298802Sgonzo 879307775Sgonzo#ifdef EVDEV_SUPPORT 880307762Sgonzo if (sc->sc_tsc_wires > 0) { 881307762Sgonzo sc->sc_evdev = evdev_alloc(); 882307762Sgonzo evdev_set_name(sc->sc_evdev, device_get_desc(dev)); 883307762Sgonzo evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev)); 884307762Sgonzo evdev_set_id(sc->sc_evdev, BUS_VIRTUAL, 0, 0, 0); 885307762Sgonzo evdev_support_prop(sc->sc_evdev, INPUT_PROP_DIRECT); 886307762Sgonzo evdev_support_event(sc->sc_evdev, EV_SYN); 887307762Sgonzo evdev_support_event(sc->sc_evdev, EV_ABS); 888307762Sgonzo evdev_support_event(sc->sc_evdev, EV_KEY); 889307762Sgonzo 890307762Sgonzo evdev_support_abs(sc->sc_evdev, ABS_X, 0, 0, 891307762Sgonzo ADC_MAX_VALUE, 0, 0, 0); 892307762Sgonzo evdev_support_abs(sc->sc_evdev, ABS_Y, 0, 0, 893307762Sgonzo ADC_MAX_VALUE, 0, 0, 0); 894307762Sgonzo 895307762Sgonzo evdev_support_key(sc->sc_evdev, BTN_TOUCH); 896307762Sgonzo 897307762Sgonzo err = evdev_register(sc->sc_evdev); 898307762Sgonzo if (err) { 899307762Sgonzo device_printf(dev, 900307762Sgonzo "failed to register evdev: error=%d\n", err); 901307762Sgonzo ti_adc_detach(dev); 902307762Sgonzo return (err); 903307762Sgonzo } 904307762Sgonzo 905307762Sgonzo sc->sc_pen_down = 0; 906307762Sgonzo sc->sc_x = -1; 907307762Sgonzo sc->sc_y = -1; 908307762Sgonzo } 909307762Sgonzo#endif /* EVDEV */ 910307762Sgonzo 911263693Sloos return (0); 912263693Sloos} 913263693Sloos 914263693Sloosstatic int 915263693Sloosti_adc_detach(device_t dev) 916263693Sloos{ 917263693Sloos struct ti_adc_softc *sc; 918263693Sloos 919263693Sloos sc = device_get_softc(dev); 920263693Sloos 921263693Sloos /* Turn off the ADC. */ 922263693Sloos TI_ADC_LOCK(sc); 923263693Sloos ti_adc_reset(sc); 924263693Sloos ti_adc_setup(sc); 925307762Sgonzo 926307775Sgonzo#ifdef EVDEV_SUPPORT 927307762Sgonzo evdev_free(sc->sc_evdev); 928307762Sgonzo#endif 929307762Sgonzo 930263693Sloos TI_ADC_UNLOCK(sc); 931263693Sloos 932263693Sloos TI_ADC_LOCK_DESTROY(sc); 933263693Sloos 934263693Sloos if (sc->sc_intrhand) 935263693Sloos bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand); 936263693Sloos if (sc->sc_irq_res) 937263693Sloos bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 938263693Sloos if (sc->sc_mem_res) 939263693Sloos bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 940263693Sloos 941263693Sloos return (bus_generic_detach(dev)); 942263693Sloos} 943263693Sloos 944263693Sloosstatic device_method_t ti_adc_methods[] = { 945263693Sloos DEVMETHOD(device_probe, ti_adc_probe), 946263693Sloos DEVMETHOD(device_attach, ti_adc_attach), 947263693Sloos DEVMETHOD(device_detach, ti_adc_detach), 948263693Sloos 949263693Sloos DEVMETHOD_END 950263693Sloos}; 951263693Sloos 952263693Sloosstatic driver_t ti_adc_driver = { 953263693Sloos "ti_adc", 954263693Sloos ti_adc_methods, 955263693Sloos sizeof(struct ti_adc_softc), 956263693Sloos}; 957263693Sloos 958263693Sloosstatic devclass_t ti_adc_devclass; 959263693Sloos 960263693SloosDRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0); 961263693SloosMODULE_VERSION(ti_adc, 1); 962263693SloosMODULE_DEPEND(ti_adc, simplebus, 1, 1, 1); 963307775Sgonzo#ifdef EVDEV_SUPPORT 964307775SgonzoMODULE_DEPEND(ti_adc, evdev, 1, 1, 1); 965307775Sgonzo#endif 966