static int ti_gpio_bank_init(device_t dev) { int pin; struct ti_gpio_softc *sc; uint32_t flags, reg_oe, reg_set, rev; clk_ident_t clk; sc = device_get_softc(dev); /* Enable the interface and functional clocks for the module. */ clk = ti_hwmods_get_clock(dev); if (clk == INVALID_CLK_IDENT) { device_printf(dev, "failed to get device id based on ti,hwmods\n"); return (EINVAL); } sc->sc_bank = clk - GPIO1_CLK + ti_first_gpio_bank(); ti_prcm_clk_enable(clk); /* * Read the revision number of the module. TI don't publish the * actual revision numbers, so instead the values have been * determined by experimentation. */ rev = ti_gpio_read_4(sc, TI_GPIO_REVISION); /* Check the revision. */ if (rev != ti_gpio_rev()) { device_printf(dev, "Warning: could not determine the revision " "of GPIO module (revision:0x%08x)\n", rev); return (EINVAL); } /* Disable interrupts for all pins. */ ti_gpio_intr_clr(sc, 0xffffffff); /* Init OE register based on pads configuration. */ reg_oe = 0xffffffff; reg_set = 0; for (pin = 0; pin < PINS_PER_BANK; pin++) { TI_GPIO_GET_FLAGS(dev, pin, &flags); if (flags & GPIO_PIN_OUTPUT) { reg_oe &= ~(1UL << pin); if (flags & GPIO_PIN_PULLUP) reg_set |= (1UL << pin); } } ti_gpio_write_4(sc, TI_GPIO_OE, reg_oe); if (reg_set) ti_gpio_write_4(sc, TI_GPIO_SETDATAOUT, reg_set); return (0); }
static int ti_edma3_attach(device_t dev) { struct ti_edma3_softc *sc = device_get_softc(dev); uint32_t reg; int err; int i; if (ti_edma3_sc) return (ENXIO); ti_edma3_sc = sc; sc->sc_dev = dev; /* Request the memory resources */ err = bus_alloc_resources(dev, ti_edma3_mem_spec, sc->mem_res); if (err) { device_printf(dev, "Error: could not allocate mem resources\n"); return (ENXIO); } /* Request the IRQ resources */ err = bus_alloc_resources(dev, ti_edma3_irq_spec, sc->irq_res); if (err) { device_printf(dev, "Error: could not allocate irq resources\n"); return (ENXIO); } /* Enable Channel Controller */ ti_prcm_clk_enable(EDMA_TPCC_CLK); reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID); device_printf(dev, "EDMA revision %08x\n", reg); /* Attach interrupt handlers */ for (i = 0; i < TI_EDMA3_NUM_IRQS; ++i) { err = bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC | INTR_MPSAFE, NULL, *ti_edma3_intrs[i].handler, sc, &sc->ih_cookie[i]); if (err) { device_printf(dev, "could not setup %s\n", ti_edma3_intrs[i].description); return (err); } } return (0); }
static int ti8250_bus_probe(struct uart_softc *sc) { int status; int devid; clk_ident_t clkid; pcell_t prop; phandle_t node; /* * Get the device id from FDT. If it's not there we can't turn on the * right clocks, so bail, unless we're doing unit 0. We assume that's * the serial console, whose clock isn't controllable anyway, and we * sure don't want to break the console because of a config error. */ node = ofw_bus_get_node(sc->sc_dev); if ((OF_getprop(node, "uart-device-id", &prop, sizeof(prop))) <= 0) { device_printf(sc->sc_dev, "missing uart-device-id attribute in FDT\n"); if (device_get_unit(sc->sc_dev) != 0) return (ENXIO); devid = 0; } else devid = fdt32_to_cpu(prop); /* Enable clocks for this device. We can't continue if that fails. */ clkid = UART0_CLK + devid; if ((status = ti_prcm_clk_enable(clkid)) != 0) return (status); /* * Set the hardware to disabled mode, do a full device reset, then set * it to uart mode. Most devices will be reset-and-disabled already, * but you never know what a bootloader might have done. */ uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_DISABLE); uart_setreg(&sc->sc_bas, SYSCC_REG, SYSCC_SOFTRESET); while (uart_getreg(&sc->sc_bas, SYSS_REG) & SYSS_STATUS_RESETDONE) continue; uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_UART); status = ns8250_bus_probe(sc); if (status == 0) device_set_desc(sc->sc_dev, "TI UART (16550 compatible)"); return (status); }
static int omap_tll_init(struct omap_tll_softc *sc) { unsigned long timeout; int ret = 0; /* Enable the USB TLL */ ti_prcm_clk_enable(USBTLL_CLK); /* Perform TLL soft reset, and wait until reset is complete */ omap_tll_write_4(sc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET); /* Set the timeout to 100ms*/ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); /* Wait for TLL reset to complete */ while ((omap_tll_read_4(sc, OMAP_USBTLL_SYSSTATUS) & TLL_SYSSTATUS_RESETDONE) == 0x00) { /* Sleep for a tick */ pause("USBRESET", 1); if (timeout-- == 0) { device_printf(sc->sc_dev, "TLL reset operation timed out\n"); ret = EINVAL; goto err_sys_status; } } /* CLOCKACTIVITY = 1 : OCP-derived internal clocks ON during idle * SIDLEMODE = 2 : Smart-idle mode. Sidleack asserted after Idlereq * assertion when no more activity on the USB. * ENAWAKEUP = 1 : Wakeup generation enabled */ omap_tll_write_4(sc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_ENAWAKEUP | TLL_SYSCONFIG_AUTOIDLE | TLL_SYSCONFIG_SIDLE_SMART_IDLE | TLL_SYSCONFIG_CACTIVITY); return(0); err_sys_status: /* Disable the TLL clocks */ ti_prcm_clk_disable(USBTLL_CLK); return(ret); }
void ti_edma3_init(unsigned int eqn) { uint32_t reg; int i; /* on AM335x Event queue 0 is always mapped to Transfer Controller 0, * event queue 1 to TC2, etc. So we are asking PRCM to power on specific * TC based on what event queue we need to initialize */ ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn); /* Clear Event Missed Regs */ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF); ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 0xFFFFFFFF); ti_edma3_cc_wr_4(TI_EDMA3CC_QEMCR, 0xFFFFFFFF); /* Clear Error Reg */ ti_edma3_cc_wr_4(TI_EDMA3CC_CCERRCLR, 0xFFFFFFFF); /* Enable DMA channels 0-63 */ ti_edma3_cc_wr_4(TI_EDMA3CC_DRAE(0), 0xFFFFFFFF); ti_edma3_cc_wr_4(TI_EDMA3CC_DRAEH(0), 0xFFFFFFFF); for (i = 0; i < 64; i++) { ti_edma3_cc_wr_4(TI_EDMA3CC_DCHMAP(i), i<<5); } /* Initialize the DMA Queue Number Registers */ for (i = 0; i < TI_EDMA3_NUM_DMA_CHS; i++) { reg = ti_edma3_cc_rd_4(TI_EDMA3CC_DMAQNUM(i>>3)); reg &= TI_EDMA3CC_DMAQNUM_CLR(i); reg |= TI_EDMA3CC_DMAQNUM_SET(i, eqn); ti_edma3_cc_wr_4(TI_EDMA3CC_DMAQNUM(i>>3), reg); } /* Enable the QDMA Region access for all channels */ ti_edma3_cc_wr_4(TI_EDMA3CC_QRAE(0), (1 << TI_EDMA3_NUM_QDMA_CHS) - 1); /*Initialize QDMA Queue Number Registers */ for (i = 0; i < TI_EDMA3_NUM_QDMA_CHS; i++) { reg = ti_edma3_cc_rd_4(TI_EDMA3CC_QDMAQNUM); reg &= TI_EDMA3CC_QDMAQNUM_CLR(i); reg |= TI_EDMA3CC_QDMAQNUM_SET(i, eqn); ti_edma3_cc_wr_4(TI_EDMA3CC_QDMAQNUM, reg); } }
static int ti_gpio_bank_init(device_t dev, int bank) { int pin; struct ti_gpio_softc *sc; uint32_t flags, reg_oe; sc = device_get_softc(dev); /* Enable the interface and functional clocks for the module. */ ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank); /* * Read the revision number of the module. TI don't publish the * actual revision numbers, so instead the values have been * determined by experimentation. */ sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION); /* Check the revision. */ if (sc->sc_revision[bank] != TI_GPIO_REV) { device_printf(dev, "Warning: could not determine the revision " "of %u GPIO module (revision:0x%08x)\n", bank, sc->sc_revision[bank]); return (EINVAL); } /* Disable interrupts for all pins. */ ti_gpio_intr_clr(sc, bank, 0xffffffff); /* Init OE register based on pads configuration. */ reg_oe = 0xffffffff; for (pin = 0; pin < PINS_PER_BANK; pin++) { ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin, &flags); if (flags & GPIO_PIN_OUTPUT) reg_oe &= ~(1UL << pin); } ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe); return (0); }
static int ti_i2c_activate(device_t dev) { clk_ident_t clk; int err; struct ti_i2c_softc *sc; sc = (struct ti_i2c_softc*)device_get_softc(dev); /* * 1. Enable the functional and interface clocks (see Section * 23.1.5.1.1.1.1). */ clk = I2C0_CLK + sc->device_id; err = ti_prcm_clk_enable(clk); if (err) return (err); return (ti_i2c_reset(sc, IIC_UNKNOWN)); }
/** * ti_sdma_attach - driver attach function * @dev: dma device handle * * Initialises memory mapping/pointers to the DMA register set and requests * IRQs. This is effectively the setup function for the driver. * * RETURNS: * 0 on success or a negative error code failure. */ static int ti_sdma_attach(device_t dev) { struct ti_sdma_softc *sc = device_get_softc(dev); unsigned int timeout; unsigned int i; int rid; void *ihl; int err; /* Setup the basics */ sc->sc_dev = dev; /* No channels active at the moment */ sc->sc_active_channels = 0x00000000; /* Mutex to protect the shared data structures */ TI_SDMA_LOCK_INIT(sc); /* Get the memory resource for the register mapping */ rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) panic("%s: Cannot map registers", device_get_name(dev)); /* Enable the interface and functional clocks */ ti_prcm_clk_enable(SDMA_CLK); /* Read the sDMA revision register and sanity check it's known */ sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION); device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev); if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) { device_printf(sc->sc_dev, "error - unknown sDMA H/W revision\n"); return (EINVAL); } /* Disable all interrupts */ for (i = 0; i < NUM_DMA_IRQS; i++) { ti_sdma_write_4(sc, DMA4_IRQENABLE_L(i), 0x00000000); } /* Soft-reset is only supported on pre-OMAP44xx devices */ if (ti_sdma_is_omap3_rev(sc)) { /* Soft-reset */ ti_sdma_write_4(sc, DMA4_OCP_SYSCONFIG, 0x0002); /* Set the timeout to 100ms*/ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); /* Wait for DMA reset to complete */ while ((ti_sdma_read_4(sc, DMA4_SYSSTATUS) & 0x1) == 0x0) { /* Sleep for a tick */ pause("DMARESET", 1); if (timeout-- == 0) { device_printf(sc->sc_dev, "sDMA reset operation timed out\n"); return (EINVAL); } } } /* * Install interrupt handlers for the for possible interrupts. Any channel * can trip one of the four IRQs */ rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_irq_res == NULL) panic("Unable to setup the dma irq handler.\n"); err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_sdma_intr, NULL, &ihl); if (err) panic("%s: Cannot register IRQ", device_get_name(dev)); /* Store the DMA structure globally ... this driver should never be unloaded */ ti_sdma_sc = sc; return (0); }
static int ti_adc_attach(device_t dev) { int err, rid; struct ti_adc_softc *sc; uint32_t reg, rev; sc = device_get_softc(dev); sc->sc_dev = dev; rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_mem_res) { device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->sc_irq_res) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot allocate interrupt\n"); return (ENXIO); } if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_adc_intr, sc, &sc->sc_intrhand) != 0) { bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "Unable to setup the irq handler.\n"); return (ENXIO); } /* Activate the ADC_TSC module. */ err = ti_prcm_clk_enable(TSC_ADC_CLK); if (err) return (err); /* Check the ADC revision. */ rev = ADC_READ4(sc, ADC_REVISION); device_printf(dev, "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n", (rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT, (rev & ADC_REV_FUNC_MSK) >> ADC_REV_FUNC_SHIFT, (rev & ADC_REV_RTL_MSK) >> ADC_REV_RTL_SHIFT, (rev & ADC_REV_MAJOR_MSK) >> ADC_REV_MAJOR_SHIFT, rev & ADC_REV_MINOR_MSK, (rev & ADC_REV_CUSTOM_MSK) >> ADC_REV_CUSTOM_SHIFT); /* * Disable the step write protect and make it store the step ID for * the captured data on FIFO. */ reg = ADC_READ4(sc, ADC_CTRL); ADC_WRITE4(sc, ADC_CTRL, reg | ADC_CTRL_STEP_WP | ADC_CTRL_STEP_ID); /* * Set the ADC prescaler to 2400 (yes, the actual value written here * is 2400 - 1). * This sets the ADC clock to ~10Khz (CLK_M_OSC / 2400). */ ADC_WRITE4(sc, ADC_CLKDIV, 2399); TI_ADC_LOCK_INIT(sc); ti_adc_idlestep_init(sc); ti_adc_inputs_init(sc); ti_adc_sysctl_init(sc); return (0); }
static int am335x_lcd_attach(device_t dev) { struct am335x_lcd_softc *sc; int rid; int div; struct panel_info panel; uint32_t reg, timing0, timing1, timing2; struct sysctl_ctx_list *ctx; struct sysctl_oid *tree; uint32_t burst_log; int err; size_t dma_size; sc = device_get_softc(dev); sc->sc_dev = dev; if (am335x_read_panel_info(dev, &panel)) return (ENXIO); int ref_freq = 0; ti_prcm_clk_enable(LCDC_CLK); if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) { device_printf(dev, "Can't get reference frequency\n"); return (ENXIO); } rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_mem_res) { device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->sc_irq_res) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot allocate interrupt\n"); return (ENXIO); } if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, am335x_lcd_intr, sc, &sc->sc_intr_hl) != 0) { bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_irq_res); bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem_res); device_printf(dev, "Unable to setup the irq handler.\n"); return (ENXIO); } LCD_LOCK_INIT(sc); /* Panle initialization */ dma_size = round_page(panel.panel_width*panel.panel_height*panel.bpp/8); /* * Now allocate framebuffer memory */ err = bus_dma_tag_create( bus_get_dma_tag(dev), 4, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ dma_size, 1, /* maxsize, nsegments */ dma_size, 0, /* maxsegsize, flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->sc_dma_tag); if (err) goto fail; err = bus_dmamem_alloc(sc->sc_dma_tag, (void **)&sc->sc_fb_base, BUS_DMA_COHERENT, &sc->sc_dma_map); if (err) { device_printf(dev, "cannot allocate framebuffer\n"); goto fail; } err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, sc->sc_fb_base, dma_size, am335x_fb_dmamap_cb, &sc->sc_fb_phys, BUS_DMA_NOWAIT); if (err) { device_printf(dev, "cannot load DMA map\n"); goto fail; } /* Make sure it's blank */ memset(sc->sc_fb_base, 0x00, dma_size); /* Calculate actual FB Size */ sc->sc_fb_size = panel.panel_width*panel.panel_height*panel.bpp/8; /* Only raster mode is supported */ reg = CTRL_RASTER_MODE; div = am335x_lcd_calc_divisor(ref_freq, panel.panel_pxl_clk); reg |= (div << CTRL_DIV_SHIFT); LCD_WRITE4(sc, LCD_CTRL, reg); /* Set timing */ timing0 = timing1 = timing2 = 0; /* Horizontal back porch */ timing0 |= (panel.panel_hbp & 0xff) << RASTER_TIMING_0_HBP_SHIFT; timing2 |= ((panel.panel_hbp >> 8) & 3) << RASTER_TIMING_2_HBPHI_SHIFT; /* Horizontal front porch */ timing0 |= (panel.panel_hfp & 0xff) << RASTER_TIMING_0_HFP_SHIFT; timing2 |= ((panel.panel_hfp >> 8) & 3) << RASTER_TIMING_2_HFPHI_SHIFT; /* Horizontal sync width */ timing0 |= (panel.panel_hsw & 0x3f) << RASTER_TIMING_0_HSW_SHIFT; timing2 |= ((panel.panel_hsw >> 6) & 0xf) << RASTER_TIMING_2_HSWHI_SHIFT; /* Vertical back porch, front porch, sync width */ timing1 |= (panel.panel_vbp & 0xff) << RASTER_TIMING_1_VBP_SHIFT; timing1 |= (panel.panel_vfp & 0xff) << RASTER_TIMING_1_VFP_SHIFT; timing1 |= (panel.panel_vsw & 0x3f) << RASTER_TIMING_1_VSW_SHIFT; /* Pixels per line */ timing0 |= (((panel.panel_width - 1) >> 10) & 1) << RASTER_TIMING_0_PPLMSB_SHIFT; timing0 |= (((panel.panel_width - 1) >> 4) & 0x3f) << RASTER_TIMING_0_PPLLSB_SHIFT; /* Lines per panel */ timing1 |= ((panel.panel_height - 1) & 0x3ff) << RASTER_TIMING_1_LPP_SHIFT; timing2 |= (((panel.panel_height - 1) >> 10 ) & 1) << RASTER_TIMING_2_LPP_B10_SHIFT; /* clock signal settings */ if (panel.sync_ctrl) timing2 |= RASTER_TIMING_2_PHSVS; if (panel.sync_edge) timing2 |= RASTER_TIMING_2_PHSVS_RISE; else timing2 |= RASTER_TIMING_2_PHSVS_FALL; if (panel.invert_line_clock) timing2 |= RASTER_TIMING_2_IHS; if (panel.invert_frm_clock) timing2 |= RASTER_TIMING_2_IVS; if (panel.panel_invert_pxl_clk) timing2 |= RASTER_TIMING_2_IPC; /* AC bias */ timing2 |= (panel.ac_bias << RASTER_TIMING_2_ACB_SHIFT); timing2 |= (panel.ac_bias_intrpt << RASTER_TIMING_2_ACBI_SHIFT); LCD_WRITE4(sc, LCD_RASTER_TIMING_0, timing0); LCD_WRITE4(sc, LCD_RASTER_TIMING_1, timing1); LCD_WRITE4(sc, LCD_RASTER_TIMING_2, timing2); /* DMA settings */ reg = LCDDMA_CTRL_FB0_FB1; /* Find power of 2 for current burst size */ switch (panel.dma_burst_sz) { case 1: burst_log = 0; break; case 2: burst_log = 1; break; case 4: burst_log = 2; break; case 8: burst_log = 3; break; case 16: default: burst_log = 4; break; } reg |= (burst_log << LCDDMA_CTRL_BURST_SIZE_SHIFT); /* XXX: FIFO TH */ reg |= (0 << LCDDMA_CTRL_TH_FIFO_RDY_SHIFT); LCD_WRITE4(sc, LCD_LCDDMA_CTRL, reg); LCD_WRITE4(sc, LCD_LCDDMA_FB0_BASE, sc->sc_fb_phys); LCD_WRITE4(sc, LCD_LCDDMA_FB0_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); LCD_WRITE4(sc, LCD_LCDDMA_FB1_BASE, sc->sc_fb_phys); LCD_WRITE4(sc, LCD_LCDDMA_FB1_CEILING, sc->sc_fb_phys + sc->sc_fb_size - 1); /* Enable LCD */ reg = RASTER_CTRL_LCDTFT; reg |= (panel.fdd << RASTER_CTRL_REQDLY_SHIFT); reg |= (PALETTE_DATA_ONLY << RASTER_CTRL_PALMODE_SHIFT); if (panel.bpp >= 24) reg |= RASTER_CTRL_TFT24; if (panel.bpp == 32) reg |= RASTER_CTRL_TFT24_UNPACKED; LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); LCD_WRITE4(sc, LCD_CLKC_ENABLE, CLKC_ENABLE_DMA | CLKC_ENABLE_LDID | CLKC_ENABLE_CORE); LCD_WRITE4(sc, LCD_CLKC_RESET, CLKC_RESET_MAIN); DELAY(100); LCD_WRITE4(sc, LCD_CLKC_RESET, 0); reg = IRQ_EOF1 | IRQ_EOF0 | IRQ_FUF | IRQ_PL | IRQ_ACB | IRQ_SYNC_LOST | IRQ_RASTER_DONE | IRQ_FRAME_DONE; LCD_WRITE4(sc, LCD_IRQENABLE_SET, reg); reg = LCD_READ4(sc, LCD_RASTER_CTRL); reg |= RASTER_CTRL_LCDEN; LCD_WRITE4(sc, LCD_RASTER_CTRL, reg); LCD_WRITE4(sc, LCD_SYSCONFIG, SYSCONFIG_STANDBY_SMART | SYSCONFIG_IDLE_SMART); /* Init backlight interface */ ctx = device_get_sysctl_ctx(sc->sc_dev); tree = device_get_sysctl_tree(sc->sc_dev); sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0, am335x_lcd_sysctl_backlight, "I", "LCD backlight"); sc->sc_backlight = 0; /* Check if eCAS interface is available at this point */ if (am335x_pwm_config_ecas(PWM_UNIT, PWM_PERIOD, PWM_PERIOD) == 0) sc->sc_backlight = 100; err = (sc_attach_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD)); if (err) { device_printf(dev, "failed to attach syscons\n"); goto fail; } am335x_lcd_syscons_setup((vm_offset_t)sc->sc_fb_base, sc->sc_fb_phys, &panel); return (0); fail: return (err); }
static int ti_mbox_attach(device_t dev) { struct ti_mbox_softc *sc; int rid, delay, chan; uint32_t rev, sysconfig; if (ti_prcm_clk_enable(MAILBOX0_CLK) != 0) { device_printf(dev, "could not enable MBOX clock\n"); return (ENXIO); } sc = device_get_softc(dev); rid = 0; mtx_init(&sc->sc_mtx, "TI mbox", NULL, MTX_DEF); sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "could not allocate memory resource\n"); return (ENXIO); } sc->sc_bt = rman_get_bustag(sc->sc_mem_res); sc->sc_bh = rman_get_bushandle(sc->sc_mem_res); rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "could not allocate interrupt resource\n"); ti_mbox_detach(dev); return (ENXIO); } if (bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE | INTR_TYPE_MISC, NULL, ti_mbox_intr, sc, &sc->sc_intr) != 0) { device_printf(dev, "unable to setup the interrupt handler\n"); ti_mbox_detach(dev); return (ENXIO); } /* * Reset the controller. */ sysconfig = ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG); DPRINTF("initial sysconfig %d\n", sysconfig); sysconfig |= TI_MBOX_SYSCONFIG_SOFTRST; delay = 100; while (ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) & TI_MBOX_SYSCONFIG_SOFTRST) { delay--; DELAY(10); } if (delay == 0) { device_printf(dev, "controller reset failed\n"); ti_mbox_detach(dev); return (ENXIO); } /* * Enable smart idle mode. */ ti_mbox_reg_write(sc, TI_MBOX_SYSCONFIG, ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) | TI_MBOX_SYSCONFIG_SMARTIDLE); rev = ti_mbox_reg_read(sc, TI_MBOX_REVISION); DPRINTF("rev %d\n", rev); device_printf(dev, "revision %d.%d\n", (rev >> 8) & 0x4, rev & 0x40); /* * Enable message interrupts. */ for (chan = 0; chan < 8; chan++) ti_mbox_reg_write(sc, TI_MBOX_IRQENABLE_SET(chan), 1); return (0); }
static int musbotg_attach(device_t dev) { struct musbotg_super_softc *sc = device_get_softc(dev); int err; int i; uint32_t rev, reg; /* Request the memory resources */ err = bus_alloc_resources(dev, am335x_musbotg_mem_spec, sc->sc_mem_res); if (err) { device_printf(dev, "Error: could not allocate mem resources\n"); return (ENXIO); } /* Request the IRQ resources */ err = bus_alloc_resources(dev, am335x_musbotg_irq_spec, sc->sc_irq_res); if (err) { device_printf(dev, "Error: could not allocate irq resources\n"); return (ENXIO); } /* * Reset USBSS, USB0 and USB1 */ rev = USBSS_READ4(sc, USBSS_REVREG); device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n", (rev >> 8) & 7, (rev >> 6) & 3, rev & 63); ti_prcm_clk_enable(MUSB0_CLK); USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET); while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) ; err = bus_setup_intr(dev, sc->sc_irq_res[0], INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)musbotg_usbss_interrupt, sc, &sc->sc_intr_hdl); if (err) { sc->sc_intr_hdl = NULL; device_printf(dev, "Failed to setup USBSS interrupt\n"); goto error; } for (i = 0; i < AM335X_USB_PORTS; i++) { /* setup MUSB OTG USB controller interface softc */ sc->sc_otg[i].sc_clocks_on = &musbotg_clocks_on; sc->sc_otg[i].sc_clocks_off = &musbotg_clocks_off; sc->sc_otg[i].sc_clocks_arg = &USB_CTRL[i]; sc->sc_otg[i].sc_ep_int_set = musbotg_ep_int_set; /* initialise some bus fields */ sc->sc_otg[i].sc_bus.parent = dev; sc->sc_otg[i].sc_bus.devices = sc->sc_otg[i].sc_devices; sc->sc_otg[i].sc_bus.devices_max = MUSB2_MAX_DEVICES; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_otg[i].sc_bus, USB_GET_DMA_TAG(dev), NULL)) { device_printf(dev, "Failed allocate bus mem for musb%d\n", i); return (ENOMEM); } sc->sc_otg[i].sc_io_res = sc->sc_mem_res[RES_USBCORE(i)]; sc->sc_otg[i].sc_io_tag = rman_get_bustag(sc->sc_otg[i].sc_io_res); sc->sc_otg[i].sc_io_hdl = rman_get_bushandle(sc->sc_otg[i].sc_io_res); sc->sc_otg[i].sc_io_size = rman_get_size(sc->sc_otg[i].sc_io_res); sc->sc_otg[i].sc_irq_res = sc->sc_irq_res[i+1]; sc->sc_otg[i].sc_bus.bdev = device_add_child(dev, "usbus", -1); if (!(sc->sc_otg[i].sc_bus.bdev)) { device_printf(dev, "No busdev for musb%d\n", i); goto error; } device_set_ivars(sc->sc_otg[i].sc_bus.bdev, &sc->sc_otg[i].sc_bus); err = bus_setup_intr(dev, sc->sc_otg[i].sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)musbotg_wrapper_interrupt, &sc->sc_otg[i], &sc->sc_otg[i].sc_intr_hdl); if (err) { sc->sc_otg[i].sc_intr_hdl = NULL; device_printf(dev, "Failed to setup interrupt for musb%d\n", i); goto error; } sc->sc_otg[i].sc_id = i; sc->sc_otg[i].sc_platform_data = sc; if (i == 0) sc->sc_otg[i].sc_mode = MUSB2_DEVICE_MODE; else sc->sc_otg[i].sc_mode = MUSB2_HOST_MODE; /* * software-controlled function */ if (sc->sc_otg[i].sc_mode == MUSB2_HOST_MODE) { reg = USBCTRL_READ4(sc, i, USBCTRL_MODE); reg |= USBCTRL_MODE_IDDIGMUX; reg &= ~USBCTRL_MODE_IDDIG; USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg); USBCTRL_WRITE4(sc, i, USBCTRL_UTMI, USBCTRL_UTMI_FSDATAEXT); } else { reg = USBCTRL_READ4(sc, i, USBCTRL_MODE); reg |= USBCTRL_MODE_IDDIGMUX; reg |= USBCTRL_MODE_IDDIG; USBCTRL_WRITE4(sc, i, USBCTRL_MODE, reg); } reg = USBCTRL_INTEN_USB_ALL & ~USBCTRL_INTEN_USB_SOF; USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_SET1, reg); USBCTRL_WRITE4(sc, i, USBCTRL_INTEN_CLR0, 0xffffffff); err = musbotg_init(&sc->sc_otg[i]); if (!err) err = device_probe_and_attach(sc->sc_otg[i].sc_bus.bdev); if (err) goto error; /* poll VBUS one time */ musbotg_vbus_poll(sc, i); } return (0); error: musbotg_detach(dev); return (ENXIO); }
/** * omap_ehci_init - initialises the USB host EHCI controller * @isc: omap ehci device context * * This initialisation routine is quite heavily based on the work done by the * OMAP Linux team (for which I thank them very much). The init sequence is * almost identical, diverging only for the FreeBSD specifics. * * LOCKING: * none * * RETURNS: * 0 on success, a negative error code on failure. */ static int omap_ehci_init(struct omap_ehci_softc *isc) { unsigned long timeout; int ret = 0; uint8_t tll_ch_mask = 0; uint32_t reg = 0; int reset_performed = 0; int i; device_printf(isc->sc_dev, "Starting TI EHCI USB Controller\n"); /* Enable Clocks for high speed USBHOST */ ti_prcm_clk_enable(USBHSHOST_CLK); /* Hold the PHY in reset while configuring */ for (int i = 0; i < 3; i++) { if (isc->phy_reset[i]) { /* Configure the GPIO to drive low (hold in reset) */ if ((isc->reset_gpio_pin[i] != -1) && (isc->sc_gpio_dev != NULL)) { GPIO_PIN_SETFLAGS(isc->sc_gpio_dev, isc->reset_gpio_pin[i], GPIO_PIN_OUTPUT); GPIO_PIN_SET(isc->sc_gpio_dev, isc->reset_gpio_pin[i], GPIO_PIN_LOW); reset_performed = 1; } } } /* Hold the PHY in RESET for enough time till DIR is high */ if (reset_performed) DELAY(10); /* Read the UHH revision */ isc->ehci_rev = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_REVISION); device_printf(isc->sc_dev, "UHH revision 0x%08x\n", isc->ehci_rev); /* Initilise the low level interface module(s) */ if (isc->ehci_rev == OMAP_EHCI_REV1) { /* Enable the USB TLL */ ti_prcm_clk_enable(USBTLL_CLK); /* Perform TLL soft reset, and wait until reset is complete */ omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET); /* Set the timeout to 100ms*/ timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); /* Wait for TLL reset to complete */ while ((omap_tll_read_4(isc, OMAP_USBTLL_SYSSTATUS) & TLL_SYSSTATUS_RESETDONE) == 0x00) { /* Sleep for a tick */ pause("USBRESET", 1); if (timeout-- == 0) { device_printf(isc->sc_dev, "TLL reset operation timed out\n"); ret = EINVAL; goto err_sys_status; } } device_printf(isc->sc_dev, "TLL RESET DONE\n"); /* CLOCKACTIVITY = 1 : OCP-derived internal clocks ON during idle * SIDLEMODE = 2 : Smart-idle mode. Sidleack asserted after Idlereq * assertion when no more activity on the USB. * ENAWAKEUP = 1 : Wakeup generation enabled */ omap_tll_write_4(isc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_ENAWAKEUP | TLL_SYSCONFIG_AUTOIDLE | TLL_SYSCONFIG_SIDLE_SMART_IDLE | TLL_SYSCONFIG_CACTIVITY); } else if (isc->ehci_rev == OMAP_EHCI_REV2) { /* For OMAP44xx devices you have to enable the per-port clocks: * PHY_MODE - External ULPI clock * TTL_MODE - Internal UTMI clock * HSIC_MODE - Internal 480Mhz and 60Mhz clocks */ if (isc->ehci_rev == OMAP_EHCI_REV2) { if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) { ti_prcm_clk_set_source(USBP1_PHY_CLK, EXT_CLK); ti_prcm_clk_enable(USBP1_PHY_CLK); } else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ti_prcm_clk_enable(USBP1_UTMI_CLK); else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC) ti_prcm_clk_enable(USBP1_HSIC_CLK); if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) { ti_prcm_clk_set_source(USBP2_PHY_CLK, EXT_CLK); ti_prcm_clk_enable(USBP2_PHY_CLK); } else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ti_prcm_clk_enable(USBP2_UTMI_CLK); else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC) ti_prcm_clk_enable(USBP2_HSIC_CLK); } } /* Put UHH in SmartIdle/SmartStandby mode */ reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSCONFIG); if (isc->ehci_rev == OMAP_EHCI_REV1) { reg &= ~(UHH_SYSCONFIG_SIDLEMODE_MASK | UHH_SYSCONFIG_MIDLEMODE_MASK); reg |= (UHH_SYSCONFIG_ENAWAKEUP | UHH_SYSCONFIG_AUTOIDLE | UHH_SYSCONFIG_CLOCKACTIVITY | UHH_SYSCONFIG_SIDLEMODE_SMARTIDLE | UHH_SYSCONFIG_MIDLEMODE_SMARTSTANDBY); } else if (isc->ehci_rev == OMAP_EHCI_REV2) { reg &= ~UHH_SYSCONFIG_IDLEMODE_MASK; reg |= UHH_SYSCONFIG_IDLEMODE_NOIDLE; reg &= ~UHH_SYSCONFIG_STANDBYMODE_MASK; reg |= UHH_SYSCONFIG_STANDBYMODE_NOSTDBY; } omap_uhh_write_4(isc, OMAP_USBHOST_UHH_SYSCONFIG, reg); device_printf(isc->sc_dev, "OMAP_UHH_SYSCONFIG: 0x%08x\n", reg); reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG); /* Setup ULPI bypass and burst configurations */ reg |= (UHH_HOSTCONFIG_ENA_INCR4 | UHH_HOSTCONFIG_ENA_INCR8 | UHH_HOSTCONFIG_ENA_INCR16); reg &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN; if (isc->ehci_rev == OMAP_EHCI_REV1) { if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) reg &= ~UHH_HOSTCONFIG_P1_ULPI_BYPASS; else reg |= UHH_HOSTCONFIG_P1_ULPI_BYPASS; } else if (isc->ehci_rev == OMAP_EHCI_REV2) { reg |= UHH_HOSTCONFIG_APP_START_CLK; /* Clear port mode fields for PHY mode*/ reg &= ~UHH_HOSTCONFIG_P1_MODE_MASK; reg &= ~UHH_HOSTCONFIG_P2_MODE_MASK; if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) reg |= UHH_HOSTCONFIG_P1_MODE_UTMI_PHY; else if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_HSIC) reg |= UHH_HOSTCONFIG_P1_MODE_HSIC; if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) reg |= UHH_HOSTCONFIG_P2_MODE_UTMI_PHY; else if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_HSIC) reg |= UHH_HOSTCONFIG_P2_MODE_HSIC; } omap_uhh_write_4(isc, OMAP_USBHOST_UHH_HOSTCONFIG, reg); device_printf(isc->sc_dev, "UHH setup done, uhh_hostconfig=0x%08x\n", reg); /* I found the code and comments in the Linux EHCI driver - thanks guys :) * * "An undocumented "feature" in the OMAP3 EHCI controller, causes suspended * ports to be taken out of suspend when the USBCMD.Run/Stop bit is cleared * (for example when we do ehci_bus_suspend). This breaks suspend-resume if * the root-hub is allowed to suspend. Writing 1 to this undocumented * register bit disables this feature and restores normal behavior." */ #if 0 omap_ehci_write_4(isc, OMAP_USBHOST_INSNREG04, OMAP_USBHOST_INSNREG04_DISABLE_UNSUSPEND); #endif /* If any of the ports are configured in TLL mode, enable them */ if ((isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= 0x1; if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= 0x2; if (isc->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= 0x4; /* Enable UTMI mode for required TLL channels */ omap_ehci_utmi_init(isc, tll_ch_mask); } /* Release the PHY reset signal now we have configured everything */ if (reset_performed) { /* Delay for 10ms */ DELAY(10000); for (i = 0; i < 3; i++) { /* Release reset */ if (isc->phy_reset[i] && (isc->reset_gpio_pin[i] != -1) && (isc->sc_gpio_dev != NULL)) { GPIO_PIN_SET(isc->sc_gpio_dev, isc->reset_gpio_pin[i], GPIO_PIN_HIGH); } } } /* Set the interrupt threshold control, it controls the maximum rate at * which the host controller issues interrupts. We set it to 1 microframe * at startup - the default is 8 mircoframes (equates to 1ms). */ reg = omap_ehci_read_4(isc, OMAP_USBHOST_USBCMD); reg &= 0xff00ffff; reg |= (1 << 16); omap_ehci_write_4(isc, OMAP_USBHOST_USBCMD, reg); /* Soft reset the PHY using PHY reset command over ULPI */ if (isc->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) omap_ehci_soft_phy_reset(isc, 0); if (isc->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) omap_ehci_soft_phy_reset(isc, 1); return(0); err_sys_status: /* Disable the TLL clocks */ ti_prcm_clk_disable(USBTLL_CLK); /* Disable Clocks for USBHOST */ ti_prcm_clk_disable(USBHSHOST_CLK); return(ret); }
/** * ti_mmchs_hw_init - initialises the MMC/SD/SIO controller * @dev: mmc device handle * * Called by the driver attach function during driver initialisation. This * function is responsibly to setup the controller ready for transactions. * * LOCKING: * No locking, assumed to only be called during initialisation. * * RETURNS: * nothing */ static void ti_mmchs_hw_init(device_t dev) { struct ti_mmchs_softc *sc = device_get_softc(dev); clk_ident_t clk; unsigned long timeout; uint32_t sysctl; uint32_t capa; uint32_t con; /* 1: Enable the controller and interface/functional clocks */ clk = MMC1_CLK + device_get_unit(dev); if (ti_prcm_clk_enable(clk) != 0) { device_printf(dev, "Error: failed to enable MMC clock\n"); return; } /* 1a: Get the frequency of the source clock */ if (ti_prcm_clk_get_source_freq(clk, &sc->sc_ref_freq) != 0) { device_printf(dev, "Error: failed to get source clock freq\n"); return; } /* 2: Issue a softreset to the controller */ ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, 0x0002); timeout = 100; while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & 0x01) == 0x0) { DELAY(1000); if (timeout-- == 0) { device_printf(dev, "Error: reset operation timed out\n"); return; } } /* 3: Reset both the command and data state machines */ sysctl = ti_mmchs_read_4(sc, MMCHS_SYSCTL); ti_mmchs_write_4(sc, MMCHS_SYSCTL, sysctl | MMCHS_SYSCTL_SRA); timeout = 100; while ((ti_mmchs_read_4(sc, MMCHS_SYSCTL) & MMCHS_SYSCTL_SRA) != 0x0) { DELAY(1000); if (timeout-- == 0) { device_printf(dev, "Error: reset operation timed out\n"); return; } } /* 4: Set initial host configuration (1-bit mode, pwroff) and capabilities */ ti_mmchs_write_4(sc, MMCHS_HCTL, MMCHS_HCTL_SDVS_V30); capa = ti_mmchs_read_4(sc, MMCHS_CAPA); ti_mmchs_write_4(sc, MMCHS_CAPA, capa | MMCHS_CAPA_VS30 | MMCHS_CAPA_VS18); /* 5: Set the initial bus configuration * 0 CTPL_MMC_SD : Control Power for DAT1 line * 0 WPP_ACTIVE_HIGH : Write protect polarity * 0 CDP_ACTIVE_HIGH : Card detect polarity * 0 CTO_ENABLED : MMC interrupt command * 0 DW8_DISABLED : 8-bit mode MMC select * 0 MODE_FUNC : Mode select * 0 STREAM_DISABLED : Stream command * 0 HR_DISABLED : Broadcast host response * 0 INIT_DISABLED : Send initialization stream * 0 OD_DISABLED : No Open Drain */ con = ti_mmchs_read_4(sc, MMCHS_CON) & MMCHS_CON_DVAL_MASK; ti_mmchs_write_4(sc, MMCHS_CON, con); }
/** * ti_gpio_attach - attach function for the driver * @dev: gpio device handle * * Allocates and sets up the driver context for all GPIO banks. This function * expects the memory ranges and IRQs to already be allocated to the driver. * * LOCKING: * None * * RETURNS: * Always returns 0 */ static int ti_gpio_attach(device_t dev) { struct ti_gpio_softc *sc = device_get_softc(dev); unsigned int i; int err = 0; int pin; uint32_t flags; uint32_t reg_oe; sc->sc_dev = dev; TI_GPIO_LOCK_INIT(sc); /* There are up to 6 different GPIO register sets located in different * memory areas on the chip. The memory range should have been set for * the driver when it was added as a child. */ err = bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); if (err) { device_printf(dev, "Error: could not allocate mem resources\n"); return (ENXIO); } /* Request the IRQ resources */ err = bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); if (err) { device_printf(dev, "Error: could not allocate irq resources\n"); return (ENXIO); } /* Setup the IRQ resources */ for (i = 0; i < MAX_GPIO_BANKS; i++) { if (sc->sc_irq_res[i] == NULL) break; /* Register an interrupt handler for each of the IRQ resources */ if ((bus_setup_intr(dev, sc->sc_irq_res[i], INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc, &(sc->sc_irq_hdl[i])))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); return (ENXIO); } } /* We need to go through each block and ensure the clocks are running and * the module is enabled. It might be better to do this only when the * pins are configured which would result in less power used if the GPIO * pins weren't used ... */ for (i = 0; i < MAX_GPIO_BANKS; i++) { if (sc->sc_mem_res[i] != NULL) { /* Enable the interface and functional clocks for the module */ ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + i); /* Read the revision number of the module. TI don't publish the * actual revision numbers, so instead the values have been * determined by experimentation. */ sc->sc_revision[i] = ti_gpio_read_4(sc, i, TI_GPIO_REVISION); /* Check the revision */ if (sc->sc_revision[i] != TI_GPIO_REV) { device_printf(dev, "Warning: could not determine the revision" "of %u GPIO module (revision:0x%08x)\n", i, sc->sc_revision[i]); continue; } /* Disable interrupts for all pins */ ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff); ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff); /* Init OE register based on pads configuration */ reg_oe = 0xffffffff; for (pin = 0; pin < 32; pin++) { ti_scm_padconf_get_gpioflags( PINS_PER_BANK*i + pin, &flags); if (flags & GPIO_PIN_OUTPUT) reg_oe &= ~(1U << pin); } ti_gpio_write_4(sc, i, TI_GPIO_OE, reg_oe); } } /* Finish of the probe call */ device_add_child(dev, "gpioc", device_get_unit(dev)); device_add_child(dev, "gpiobus", device_get_unit(dev)); return (bus_generic_attach(dev)); }