184ca5cfganbold/*- 284ca5cfganbold * Copyright (c) 2016 Ganbold Tsagaankhuu <ganbold@freebsd.org> 384ca5cfganbold * All rights reserved. 484ca5cfganbold * 584ca5cfganbold * Redistribution and use in source and binary forms, with or without 684ca5cfganbold * modification, are permitted provided that the following conditions 784ca5cfganbold * are met: 884ca5cfganbold * 1. Redistributions of source code must retain the above copyright 984ca5cfganbold * notice, this list of conditions and the following disclaimer. 1084ca5cfganbold * 2. Redistributions in binary form must reproduce the above copyright 1184ca5cfganbold * notice, this list of conditions and the following disclaimer in the 1284ca5cfganbold * documentation and/or other materials provided with the distribution. 1384ca5cfganbold * 1484ca5cfganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1584ca5cfganbold * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1684ca5cfganbold * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1784ca5cfganbold * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1884ca5cfganbold * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1984ca5cfganbold * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2084ca5cfganbold * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2184ca5cfganbold * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2284ca5cfganbold * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2384ca5cfganbold * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2484ca5cfganbold * SUCH DAMAGE. 2584ca5cfganbold */ 2684ca5cfganbold 2784ca5cfganbold/* 2884ca5cfganbold * Allwinner Consumer IR controller 2984ca5cfganbold */ 3084ca5cfganbold 3184ca5cfganbold#include <sys/cdefs.h> 3284ca5cfganbold__FBSDID("$FreeBSD$"); 3384ca5cfganbold 3484ca5cfganbold#include <sys/param.h> 3584ca5cfganbold#include <sys/systm.h> 3684ca5cfganbold#include <sys/bus.h> 3784ca5cfganbold#include <sys/kernel.h> 3884ca5cfganbold#include <sys/module.h> 3984ca5cfganbold#include <sys/rman.h> 4084ca5cfganbold#include <sys/sysctl.h> 4184ca5cfganbold#include <machine/bus.h> 4284ca5cfganbold 4384ca5cfganbold#include <dev/ofw/openfirm.h> 4484ca5cfganbold#include <dev/ofw/ofw_bus.h> 4584ca5cfganbold#include <dev/ofw/ofw_bus_subr.h> 4684ca5cfganbold#include <dev/extres/clk/clk.h> 4784ca5cfganbold#include <dev/extres/hwreset/hwreset.h> 4884ca5cfganbold 4984ca5cfganbold#include <dev/evdev/input.h> 5084ca5cfganbold#include <dev/evdev/evdev.h> 5184ca5cfganbold 5284ca5cfganbold#define READ(_sc, _r) bus_read_4((_sc)->res[0], (_r)) 5384ca5cfganbold#define WRITE(_sc, _r, _v) bus_write_4((_sc)->res[0], (_r), (_v)) 5484ca5cfganbold 5584ca5cfganbold/* IR Control */ 5684ca5cfganbold#define AW_IR_CTL 0x00 5784ca5cfganbold/* Global Enable */ 5884ca5cfganbold#define AW_IR_CTL_GEN (1 << 0) 5984ca5cfganbold/* RX enable */ 6084ca5cfganbold#define AW_IR_CTL_RXEN (1 << 1) 6184ca5cfganbold/* CIR mode enable */ 6284ca5cfganbold#define AW_IR_CTL_MD (1 << 4) | (1 << 5) 6384ca5cfganbold 6484ca5cfganbold/* RX Config Reg */ 6584ca5cfganbold#define AW_IR_RXCTL 0x10 6684ca5cfganbold/* Pulse Polarity Invert flag */ 6784ca5cfganbold#define AW_IR_RXCTL_RPPI (1 << 2) 6884ca5cfganbold 6984ca5cfganbold/* RX Data */ 7084ca5cfganbold#define AW_IR_RXFIFO 0x20 7184ca5cfganbold 7284ca5cfganbold/* RX Interrupt Control */ 7384ca5cfganbold#define AW_IR_RXINT 0x2C 7484ca5cfganbold/* RX FIFO Overflow */ 7584ca5cfganbold#define AW_IR_RXINT_ROI_EN (1 << 0) 7684ca5cfganbold/* RX Packet End */ 7784ca5cfganbold#define AW_IR_RXINT_RPEI_EN (1 << 1) 7884ca5cfganbold/* RX FIFO Data Available */ 7984ca5cfganbold#define AW_IR_RXINT_RAI_EN (1 << 4) 8084ca5cfganbold/* RX FIFO available byte level */ 8184ca5cfganbold#define AW_IR_RXINT_RAL(val) ((val) << 8) 8284ca5cfganbold 8384ca5cfganbold/* RX Interrupt Status Reg */ 8484ca5cfganbold#define AW_IR_RXSTA 0x30 8584ca5cfganbold/* RX FIFO Get Available Counter */ 8684ca5cfganbold#define AW_IR_RXSTA_COUNTER(val) (((val) >> 8) & (sc->fifo_size * 2 - 1)) 8784ca5cfganbold/* Clear all interrupt status */ 8884ca5cfganbold#define AW_IR_RXSTA_CLEARALL 0xff 8984ca5cfganbold 9084ca5cfganbold/* IR Sample Configure Reg */ 9184ca5cfganbold#define AW_IR_CIR 0x34 9285a60b4ganbold 9385a60b4ganbold/* 9485a60b4ganbold * Frequency sample: 23437.5Hz (Cycle: 42.7us) 9585a60b4ganbold * Pulse of NEC Remote > 560us 9685a60b4ganbold */ 9785a60b4ganbold/* Filter Threshold = 8 * 42.7 = ~341us < 500us */ 9884ca5cfganbold#define AW_IR_RXFILT_VAL (((8) & 0x3f) << 2) 9984ca5cfganbold/* Idle Threshold = (2 + 1) * 128 * 42.7 = ~16.4ms > 9ms */ 10084ca5cfganbold#define AW_IR_RXIDLE_VAL (((2) & 0xff) << 8) 10184ca5cfganbold 10284ca5cfganbold/* Bit 15 - value (pulse/space) */ 10384ca5cfganbold#define VAL_MASK 0x80 10484ca5cfganbold/* Bits 0:14 - sample duration */ 10584ca5cfganbold#define PERIOD_MASK 0x7f 10684ca5cfganbold 10784ca5cfganbold/* Clock rate for IR0 or IR1 clock in CIR mode */ 10884ca5cfganbold#define AW_IR_BASE_CLK 3000000 10984ca5cfganbold/* Frequency sample 3MHz/64 = 46875Hz (21.3us) */ 11084ca5cfganbold#define AW_IR_SAMPLE_64 (0 << 0) 11184ca5cfganbold/* Frequency sample 3MHz/128 = 23437.5Hz (42.7us) */ 11284ca5cfganbold#define AW_IR_SAMPLE_128 (1 << 0) 11384ca5cfganbold 11484ca5cfganbold#define AW_IR_ERROR_CODE 0xffffffff 11584ca5cfganbold#define AW_IR_REPEAT_CODE 0x0 11684ca5cfganbold 11784ca5cfganbold/* 80 * 42.7 = ~3.4ms, Lead1(4.5ms) > AW_IR_L1_MIN */ 11884ca5cfganbold#define AW_IR_L1_MIN 80 11984ca5cfganbold/* 40 * 42.7 = ~1.7ms, Lead0(4.5ms) Lead0R(2.25ms) > AW_IR_L0_MIN */ 12084ca5cfganbold#define AW_IR_L0_MIN 40 12184ca5cfganbold/* 26 * 42.7 = ~1109us ~= 561 * 2, Pulse < AW_IR_PMAX */ 12284ca5cfganbold#define AW_IR_PMAX 26 12384ca5cfganbold/* 26 * 42.7 = ~1109us ~= 561 * 2, D1 > AW_IR_DMID, D0 <= AW_IR_DMID */ 12484ca5cfganbold#define AW_IR_DMID 26 12584ca5cfganbold/* 53 * 42.7 = ~2263us ~= 561 * 4, D < AW_IR_DMAX */ 12684ca5cfganbold#define AW_IR_DMAX 53 12784ca5cfganbold 12884ca5cfganbold/* Active Thresholds */ 12987f861aavg#define AW_IR_ACTIVE_T_VAL AW_IR_L1_MIN 13087f861aavg#define AW_IR_ACTIVE_T (((AW_IR_ACTIVE_T_VAL - 1) & 0xff) << 16) 13187f861aavg#define AW_IR_ACTIVE_T_C_VAL 0 13287f861aavg#define AW_IR_ACTIVE_T_C ((AW_IR_ACTIVE_T_C_VAL & 0xff) << 23) 13384ca5cfganbold 13484ca5cfganbold/* Code masks */ 13584ca5cfganbold#define CODE_MASK 0x00ff00ff 13684ca5cfganbold#define INV_CODE_MASK 0xff00ff00 13784ca5cfganbold#define VALID_CODE_MASK 0x00ff0000 13884ca5cfganbold 1398baf377avgenum { 1408baf377avg A10_IR = 1, 1418baf377avg A13_IR, 1428baf377avg A31_IR, 1438baf377avg}; 14484ca5cfganbold 14584ca5cfganbold#define AW_IR_RAW_BUF_SIZE 128 14684ca5cfganbold 14784ca5cfganboldstruct aw_ir_softc { 14884ca5cfganbold device_t dev; 14984ca5cfganbold struct resource *res[2]; 15084ca5cfganbold void * intrhand; 15184ca5cfganbold int fifo_size; 15284ca5cfganbold int dcnt; /* Packet Count */ 15384ca5cfganbold unsigned char buf[AW_IR_RAW_BUF_SIZE]; 15484ca5cfganbold struct evdev_dev *sc_evdev; 15584ca5cfganbold}; 15684ca5cfganbold 15784ca5cfganboldstatic struct resource_spec aw_ir_spec[] = { 15884ca5cfganbold { SYS_RES_MEMORY, 0, RF_ACTIVE }, 15984ca5cfganbold { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 16084ca5cfganbold { -1, 0 } 16184ca5cfganbold}; 16284ca5cfganbold 16384ca5cfganboldstatic struct ofw_compat_data compat_data[] = { 16484ca5cfganbold { "allwinner,sun4i-a10-ir", A10_IR }, 16584ca5cfganbold { "allwinner,sun5i-a13-ir", A13_IR }, 1668baf377avg { "allwinner,sun6i-a31-ir", A31_IR }, 16784ca5cfganbold { NULL, 0 } 16884ca5cfganbold}; 16984ca5cfganbold 17084ca5cfganboldstatic void 17184ca5cfganboldaw_ir_buf_reset(struct aw_ir_softc *sc) 17284ca5cfganbold{ 17384ca5cfganbold 17484ca5cfganbold sc->dcnt = 0; 17584ca5cfganbold} 17684ca5cfganbold 17784ca5cfganboldstatic void 17884ca5cfganboldaw_ir_buf_write(struct aw_ir_softc *sc, unsigned char data) 17984ca5cfganbold{ 18084ca5cfganbold 18184ca5cfganbold if (sc->dcnt < AW_IR_RAW_BUF_SIZE) 18284ca5cfganbold sc->buf[sc->dcnt++] = data; 18384ca5cfganbold else 18484ca5cfganbold if (bootverbose) 18584ca5cfganbold device_printf(sc->dev, "IR RX Buffer Full!\n"); 18684ca5cfganbold} 18784ca5cfganbold 18884ca5cfganboldstatic int 18984ca5cfganboldaw_ir_buf_full(struct aw_ir_softc *sc) 19084ca5cfganbold{ 19184ca5cfganbold 19284ca5cfganbold return (sc->dcnt >= AW_IR_RAW_BUF_SIZE); 19384ca5cfganbold} 19484ca5cfganbold 19584ca5cfganboldstatic unsigned char 19684ca5cfganboldaw_ir_read_data(struct aw_ir_softc *sc) 19784ca5cfganbold{ 19884ca5cfganbold 19984ca5cfganbold return (unsigned char)(READ(sc, AW_IR_RXFIFO) & 0xff); 20084ca5cfganbold} 20184ca5cfganbold 20284ca5cfganboldstatic unsigned long 20384ca5cfganboldaw_ir_decode_packets(struct aw_ir_softc *sc) 20484ca5cfganbold{ 2057bf4075avg unsigned int len, code; 20684ca5cfganbold unsigned int active_delay; 2077bf4075avg unsigned char val, last; 20884ca5cfganbold int i, bitcount; 20984ca5cfganbold 21084ca5cfganbold if (bootverbose) 21184ca5cfganbold device_printf(sc->dev, "sc->dcnt = %d\n", sc->dcnt); 21284ca5cfganbold 21384ca5cfganbold /* Find Lead 1 (bit separator) */ 21487f861aavg active_delay = AW_IR_ACTIVE_T_VAL * 21587f861aavg (AW_IR_ACTIVE_T_C_VAL != 0 ? 128 : 1); 21687f861aavg len = active_delay; 21784ca5cfganbold if (bootverbose) 2187bf4075avg device_printf(sc->dev, "Initial len: %d\n", len); 21984ca5cfganbold for (i = 0; i < sc->dcnt; i++) { 22084ca5cfganbold val = sc->buf[i]; 22184ca5cfganbold if (val & VAL_MASK) 2227bf4075avg len += (val & PERIOD_MASK) + 1; 22384ca5cfganbold else { 22484ca5cfganbold if (len > AW_IR_L1_MIN) 22584ca5cfganbold break; 22684ca5cfganbold len = 0; 22784ca5cfganbold } 22884ca5cfganbold } 22984ca5cfganbold if (bootverbose) 2307bf4075avg device_printf(sc->dev, "len = %d\n", len); 23184ca5cfganbold if ((val & VAL_MASK) || (len <= AW_IR_L1_MIN)) { 23284ca5cfganbold if (bootverbose) 23384ca5cfganbold device_printf(sc->dev, "Bit separator error\n"); 23484ca5cfganbold goto error_code; 23584ca5cfganbold } 23684ca5cfganbold 23784ca5cfganbold /* Find Lead 0 (bit length) */ 23884ca5cfganbold len = 0; 23984ca5cfganbold for (; i < sc->dcnt; i++) { 24084ca5cfganbold val = sc->buf[i]; 24184ca5cfganbold if (val & VAL_MASK) { 24284ca5cfganbold if(len > AW_IR_L0_MIN) 24384ca5cfganbold break; 24484ca5cfganbold len = 0; 24584ca5cfganbold } else 2467bf4075avg len += (val & PERIOD_MASK) + 1; 24784ca5cfganbold } 24884ca5cfganbold if ((!(val & VAL_MASK)) || (len <= AW_IR_L0_MIN)) { 24984ca5cfganbold if (bootverbose) 25084ca5cfganbold device_printf(sc->dev, "Bit length error\n"); 25184ca5cfganbold goto error_code; 25284ca5cfganbold } 25384ca5cfganbold 25484ca5cfganbold /* Start decoding */ 25584ca5cfganbold code = 0; 25684ca5cfganbold bitcount = 0; 25784ca5cfganbold last = 1; 25884ca5cfganbold len = 0; 25984ca5cfganbold for (; i < sc->dcnt; i++) { 26084ca5cfganbold val = sc->buf[i]; 26184ca5cfganbold if (last) { 26284ca5cfganbold if (val & VAL_MASK) 2637bf4075avg len += (val & PERIOD_MASK) + 1; 26484ca5cfganbold else { 26584ca5cfganbold if (len > AW_IR_PMAX) { 26684ca5cfganbold if (bootverbose) 26784ca5cfganbold device_printf(sc->dev, 2687bf4075avg "Pulse error, len=%d\n", 2697bf4075avg len); 27084ca5cfganbold goto error_code; 27184ca5cfganbold } 27284ca5cfganbold last = 0; 2737bf4075avg len = (val & PERIOD_MASK) + 1; 27484ca5cfganbold } 27584ca5cfganbold } else { 27684ca5cfganbold if (val & VAL_MASK) { 27784ca5cfganbold if (len > AW_IR_DMAX) { 27884ca5cfganbold if (bootverbose) 27984ca5cfganbold device_printf(sc->dev, 2807bf4075avg "Distance error, len=%d\n", 2817bf4075avg len); 28284ca5cfganbold goto error_code; 28384ca5cfganbold } else { 28484ca5cfganbold if (len > AW_IR_DMID) { 28584ca5cfganbold /* Decode */ 28684ca5cfganbold code |= 1 << bitcount; 28784ca5cfganbold } 28884ca5cfganbold bitcount++; 28984ca5cfganbold if (bitcount == 32) 29084ca5cfganbold break; /* Finish decoding */ 29184ca5cfganbold } 29284ca5cfganbold last = 1; 2937bf4075avg len = (val & PERIOD_MASK) + 1; 29484ca5cfganbold } else 2957bf4075avg len += (val & PERIOD_MASK) + 1; 29684ca5cfganbold } 29784ca5cfganbold } 29884ca5cfganbold return (code); 29984ca5cfganbold 30084ca5cfganbolderror_code: 30184ca5cfganbold 30284ca5cfganbold return (AW_IR_ERROR_CODE); 30384ca5cfganbold} 30484ca5cfganbold 30584ca5cfganboldstatic int 30684ca5cfganboldaw_ir_validate_code(unsigned long code) 30784ca5cfganbold{ 30884ca5cfganbold unsigned long v1, v2; 30984ca5cfganbold 31084ca5cfganbold /* Don't check address */ 31184ca5cfganbold v1 = code & CODE_MASK; 31284ca5cfganbold v2 = (code & INV_CODE_MASK) >> 8; 31384ca5cfganbold 31484ca5cfganbold if (((v1 ^ v2) & VALID_CODE_MASK) == VALID_CODE_MASK) 31584ca5cfganbold return (0); /* valid */ 31684ca5cfganbold else 31784ca5cfganbold return (1); /* invalid */ 31884ca5cfganbold} 31984ca5cfganbold 32084ca5cfganboldstatic void 32184ca5cfganboldaw_ir_intr(void *arg) 32284ca5cfganbold{ 32384ca5cfganbold struct aw_ir_softc *sc; 32484ca5cfganbold uint32_t val; 32584ca5cfganbold int i, dcnt; 32684ca5cfganbold unsigned long ir_code; 32784ca5cfganbold int stat; 32884ca5cfganbold 32984ca5cfganbold sc = (struct aw_ir_softc *)arg; 33084ca5cfganbold 33184ca5cfganbold /* Read RX interrupt status */ 33284ca5cfganbold val = READ(sc, AW_IR_RXSTA); 33385a60b4ganbold if (bootverbose) 33485a60b4ganbold device_printf(sc->dev, "RX interrupt status: %x\n", val); 33584ca5cfganbold 33684ca5cfganbold /* Clean all pending interrupt statuses */ 33784ca5cfganbold WRITE(sc, AW_IR_RXSTA, val | AW_IR_RXSTA_CLEARALL); 33884ca5cfganbold 33984ca5cfganbold /* When Rx FIFO Data available or Packet end */ 34084ca5cfganbold if (val & (AW_IR_RXINT_RAI_EN | AW_IR_RXINT_RPEI_EN)) { 34185a60b4ganbold if (bootverbose) 34285a60b4ganbold device_printf(sc->dev, 34385a60b4ganbold "RX FIFO Data available or Packet end\n"); 34484ca5cfganbold /* Get available message count in RX FIFO */ 34584ca5cfganbold dcnt = AW_IR_RXSTA_COUNTER(val); 34684ca5cfganbold /* Read FIFO */ 34784ca5cfganbold for (i = 0; i < dcnt; i++) { 34884ca5cfganbold if (aw_ir_buf_full(sc)) { 34984ca5cfganbold if (bootverbose) 35084ca5cfganbold device_printf(sc->dev, 35184ca5cfganbold "raw buffer full\n"); 35284ca5cfganbold break; 35384ca5cfganbold } else 35484ca5cfganbold aw_ir_buf_write(sc, aw_ir_read_data(sc)); 35584ca5cfganbold } 35684ca5cfganbold } 35784ca5cfganbold 35884ca5cfganbold if (val & AW_IR_RXINT_RPEI_EN) { 35984ca5cfganbold /* RX Packet end */ 36084ca5cfganbold if (bootverbose) 36184ca5cfganbold device_printf(sc->dev, "RX Packet end\n"); 36284ca5cfganbold ir_code = aw_ir_decode_packets(sc); 36384ca5cfganbold stat = aw_ir_validate_code(ir_code); 36484ca5cfganbold if (stat == 0) { 36584ca5cfganbold evdev_push_event(sc->sc_evdev, 36684ca5cfganbold EV_MSC, MSC_SCAN, ir_code); 36784ca5cfganbold evdev_sync(sc->sc_evdev); 36884ca5cfganbold } 36984ca5cfganbold if (bootverbose) { 37084ca5cfganbold device_printf(sc->dev, "Final IR code: %lx\n", 37184ca5cfganbold ir_code); 37284ca5cfganbold device_printf(sc->dev, "IR code status: %d\n", 37384ca5cfganbold stat); 37484ca5cfganbold } 375796399bavg aw_ir_buf_reset(sc); 37684ca5cfganbold } 37784ca5cfganbold if (val & AW_IR_RXINT_ROI_EN) { 37884ca5cfganbold /* RX FIFO overflow */ 37984ca5cfganbold if (bootverbose) 38084ca5cfganbold device_printf(sc->dev, "RX FIFO overflow\n"); 38184ca5cfganbold /* Flush raw buffer */ 38284ca5cfganbold aw_ir_buf_reset(sc); 38384ca5cfganbold } 38484ca5cfganbold} 38584ca5cfganbold 38684ca5cfganboldstatic int 38784ca5cfganboldaw_ir_probe(device_t dev) 38884ca5cfganbold{ 38984ca5cfganbold 39084ca5cfganbold if (!ofw_bus_status_okay(dev)) 39184ca5cfganbold return (ENXIO); 39284ca5cfganbold 39384ca5cfganbold if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 39484ca5cfganbold return (ENXIO); 39584ca5cfganbold 39684ca5cfganbold device_set_desc(dev, "Allwinner CIR controller"); 39784ca5cfganbold return (BUS_PROBE_DEFAULT); 39884ca5cfganbold} 39984ca5cfganbold 40084ca5cfganboldstatic int 40184ca5cfganboldaw_ir_attach(device_t dev) 40284ca5cfganbold{ 40384ca5cfganbold struct aw_ir_softc *sc; 40484ca5cfganbold hwreset_t rst_apb; 40584ca5cfganbold clk_t clk_ir, clk_gate; 40684ca5cfganbold int err; 40784ca5cfganbold uint32_t val = 0; 40884ca5cfganbold 40984ca5cfganbold clk_ir = clk_gate = NULL; 410f250b31manu rst_apb = NULL; 41184ca5cfganbold 41284ca5cfganbold sc = device_get_softc(dev); 41384ca5cfganbold sc->dev = dev; 41484ca5cfganbold 41584ca5cfganbold if (bus_alloc_resources(dev, aw_ir_spec, sc->res) != 0) { 41684ca5cfganbold device_printf(dev, "could not allocate memory resource\n"); 41784ca5cfganbold return (ENXIO); 41884ca5cfganbold } 41984ca5cfganbold 42084ca5cfganbold switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { 42184ca5cfganbold case A10_IR: 42284ca5cfganbold sc->fifo_size = 16; 42384ca5cfganbold break; 42484ca5cfganbold case A13_IR: 4258baf377avg case A31_IR: 42684ca5cfganbold sc->fifo_size = 64; 42784ca5cfganbold break; 42884ca5cfganbold } 42984ca5cfganbold 43084ca5cfganbold /* De-assert reset */ 431a5e409aganbold if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst_apb) == 0) { 43284ca5cfganbold err = hwreset_deassert(rst_apb); 43384ca5cfganbold if (err != 0) { 43484ca5cfganbold device_printf(dev, "cannot de-assert reset\n"); 43584ca5cfganbold goto error; 43684ca5cfganbold } 43784ca5cfganbold } 43884ca5cfganbold 43984ca5cfganbold /* Reset buffer */ 44084ca5cfganbold aw_ir_buf_reset(sc); 44184ca5cfganbold 44284ca5cfganbold /* Get clocks and enable them */ 44384ca5cfganbold err = clk_get_by_ofw_name(dev, 0, "apb", &clk_gate); 44484ca5cfganbold if (err != 0) { 44584ca5cfganbold device_printf(dev, "Cannot get gate clock\n"); 44684ca5cfganbold goto error; 44784ca5cfganbold } 44884ca5cfganbold err = clk_get_by_ofw_name(dev, 0, "ir", &clk_ir); 44984ca5cfganbold if (err != 0) { 45084ca5cfganbold device_printf(dev, "Cannot get IR clock\n"); 45184ca5cfganbold goto error; 45284ca5cfganbold } 45384ca5cfganbold /* Set clock rate */ 45484ca5cfganbold err = clk_set_freq(clk_ir, AW_IR_BASE_CLK, 0); 45584ca5cfganbold if (err != 0) { 45684ca5cfganbold device_printf(dev, "cannot set IR clock rate\n"); 45784ca5cfganbold goto error; 45884ca5cfganbold } 45984ca5cfganbold /* Enable clocks */ 46084ca5cfganbold err = clk_enable(clk_gate); 46184ca5cfganbold if (err != 0) { 46284ca5cfganbold device_printf(dev, "Cannot enable clk gate\n"); 46384ca5cfganbold goto error; 46484ca5cfganbold } 46584ca5cfganbold err = clk_enable(clk_ir); 46684ca5cfganbold if (err != 0) { 46784ca5cfganbold device_printf(dev, "Cannot enable IR clock\n"); 46884ca5cfganbold goto error; 46984ca5cfganbold } 47084ca5cfganbold 47184ca5cfganbold if (bus_setup_intr(dev, sc->res[1], 47284ca5cfganbold INTR_TYPE_MISC | INTR_MPSAFE, NULL, aw_ir_intr, sc, 47384ca5cfganbold &sc->intrhand)) { 47484ca5cfganbold bus_release_resources(dev, aw_ir_spec, sc->res); 47584ca5cfganbold device_printf(dev, "cannot setup interrupt handler\n"); 476796399bavg err = ENXIO; 477796399bavg goto error; 47884ca5cfganbold } 47984ca5cfganbold 48084ca5cfganbold /* Enable CIR Mode */ 48184ca5cfganbold WRITE(sc, AW_IR_CTL, AW_IR_CTL_MD); 48284ca5cfganbold 48384ca5cfganbold /* 48484ca5cfganbold * Set clock sample, filter, idle thresholds. 48584ca5cfganbold * Frequency sample = 3MHz/128 = 23437.5Hz (42.7us) 48684ca5cfganbold */ 48784ca5cfganbold val = AW_IR_SAMPLE_128; 48884ca5cfganbold val |= (AW_IR_RXFILT_VAL | AW_IR_RXIDLE_VAL); 48984ca5cfganbold val |= (AW_IR_ACTIVE_T | AW_IR_ACTIVE_T_C); 49084ca5cfganbold WRITE(sc, AW_IR_CIR, val); 49184ca5cfganbold 49284ca5cfganbold /* Invert Input Signal */ 49384ca5cfganbold WRITE(sc, AW_IR_RXCTL, AW_IR_RXCTL_RPPI); 49484ca5cfganbold 49584ca5cfganbold /* Clear All RX Interrupt Status */ 49684ca5cfganbold WRITE(sc, AW_IR_RXSTA, AW_IR_RXSTA_CLEARALL); 49784ca5cfganbold 49884ca5cfganbold /* 49984ca5cfganbold * Enable RX interrupt in case of overflow, packet end 50084ca5cfganbold * and FIFO available. 50184ca5cfganbold * RX FIFO Threshold = FIFO size / 2 50284ca5cfganbold */ 50384ca5cfganbold WRITE(sc, AW_IR_RXINT, AW_IR_RXINT_ROI_EN | AW_IR_RXINT_RPEI_EN | 50484ca5cfganbold AW_IR_RXINT_RAI_EN | AW_IR_RXINT_RAL((sc->fifo_size >> 1) - 1)); 50584ca5cfganbold 50684ca5cfganbold /* Enable IR Module */ 50784ca5cfganbold val = READ(sc, AW_IR_CTL); 50884ca5cfganbold WRITE(sc, AW_IR_CTL, val | AW_IR_CTL_GEN | AW_IR_CTL_RXEN); 50984ca5cfganbold 51084ca5cfganbold sc->sc_evdev = evdev_alloc(); 51184ca5cfganbold evdev_set_name(sc->sc_evdev, device_get_desc(sc->dev)); 51284ca5cfganbold evdev_set_phys(sc->sc_evdev, device_get_nameunit(sc->dev)); 51384ca5cfganbold evdev_set_id(sc->sc_evdev, BUS_HOST, 0, 0, 0); 51484ca5cfganbold evdev_support_event(sc->sc_evdev, EV_SYN); 51584ca5cfganbold evdev_support_event(sc->sc_evdev, EV_MSC); 51684ca5cfganbold evdev_support_msc(sc->sc_evdev, MSC_SCAN); 51784ca5cfganbold 51884ca5cfganbold err = evdev_register(sc->sc_evdev); 51984ca5cfganbold if (err) { 52084ca5cfganbold device_printf(dev, 52184ca5cfganbold "failed to register evdev: error=%d\n", err); 52284ca5cfganbold goto error; 52384ca5cfganbold } 52484ca5cfganbold 52584ca5cfganbold return (0); 52684ca5cfganbolderror: 52784ca5cfganbold if (clk_gate != NULL) 52884ca5cfganbold clk_release(clk_gate); 52984ca5cfganbold if (clk_ir != NULL) 53084ca5cfganbold clk_release(clk_ir); 53184ca5cfganbold if (rst_apb != NULL) 53284ca5cfganbold hwreset_release(rst_apb); 53384ca5cfganbold evdev_free(sc->sc_evdev); 53484ca5cfganbold sc->sc_evdev = NULL; /* Avoid double free */ 53584ca5cfganbold 53684ca5cfganbold bus_release_resources(dev, aw_ir_spec, sc->res); 53784ca5cfganbold return (ENXIO); 53884ca5cfganbold} 53984ca5cfganbold 54084ca5cfganboldstatic device_method_t aw_ir_methods[] = { 54184ca5cfganbold DEVMETHOD(device_probe, aw_ir_probe), 54284ca5cfganbold DEVMETHOD(device_attach, aw_ir_attach), 54384ca5cfganbold 54484ca5cfganbold DEVMETHOD_END 54584ca5cfganbold}; 54684ca5cfganbold 54784ca5cfganboldstatic driver_t aw_ir_driver = { 54884ca5cfganbold "aw_ir", 54984ca5cfganbold aw_ir_methods, 55084ca5cfganbold sizeof(struct aw_ir_softc), 55184ca5cfganbold}; 55284ca5cfganboldstatic devclass_t aw_ir_devclass; 55384ca5cfganbold 55484ca5cfganboldDRIVER_MODULE(aw_ir, simplebus, aw_ir_driver, aw_ir_devclass, 0, 0); 55584ca5cfganboldMODULE_DEPEND(aw_ir, evdev, 1, 1, 1); 556