static void board_configure_analogix(void) { int node, ret; struct fdt_gpio_state reset_gpio; struct fdt_gpio_state powerdown_gpio; node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_ANALOGIX_ANX7805); if (node <= 0) return; /* Configure Analogix 780x bridge in USB pass-through mode */ ret = fdtdec_decode_gpio(gd->fdt_blob, node, "reset-gpio", &reset_gpio); if (ret < 0) { debug("%s: Could not find reset-gpio", __func__); return; } ret = fdtdec_decode_gpio(gd->fdt_blob, node, "powerdown-gpio", &powerdown_gpio); if (ret < 0) { debug("%s: Could not find powerdown-gpio", __func__); return; } fdtdec_setup_gpio(&powerdown_gpio); fdtdec_setup_gpio(&reset_gpio); gpio_direction_output(powerdown_gpio.gpio, 1); gpio_direction_output(reset_gpio.gpio, 1); }
static int board_i2c_arb_init(const void *blob) { int node; local.arbitrate_node = -1; node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_ARBITRATOR); if (node < 0) { debug("Cannot find bus arbitrator node\n"); return 0; } if (fdtdec_decode_gpio(blob, node, "google,ap-claim-gpios", &local.ap_claim) || fdtdec_decode_gpio(blob, node, "google,ec-claim-gpios", &local.ec_claim)) { debug("Cannot find bus arbitrator GPIOs\n"); return 0; } if (fdtdec_setup_gpio(&local.ap_claim) || fdtdec_setup_gpio(&local.ec_claim)) { debug("Cannot claim arbitration GPIOs\n"); return -1; } /* We are currently not claiming the bus */ gpio_direction_output(local.ap_claim.gpio, 1); gpio_direction_input(local.ec_claim.gpio); gpio_set_pull(local.ec_claim.gpio, EXYNOS_GPIO_PULL_UP); local.arbitrate_node = fdtdec_lookup_phandle(blob, node, "google,arbitrate-bus"); if (local.arbitrate_node < 0) { debug("Cannot find bus to arbitrate\n"); return -1; } local.slew_delay_us = fdtdec_get_int(blob, node, "google,slew-delay-us", 10); local.wait_retry_ms = fdtdec_get_int(blob, node, "google,wait-retry-us", 2000); local.wait_retry_ms = DIV_ROUND_UP(local.wait_retry_ms, 1000); local.wait_free_ms = fdtdec_get_int(blob, node, "google,wait-free-us", 50000); local.wait_free_ms = DIV_ROUND_UP(local.wait_free_ms, 1000); debug("Bus arbitration ready on fdt node %d\n", local.arbitrate_node); return 0; }
int board_dp_bridge_setup(const void *blob, unsigned *wait_ms) { int ret; ret = board_dp_fill_gpios(blob); if (ret) return ret; /* Mux HPHPD to the special hotplug detect mode */ exynos_pinmux_config(PERIPH_ID_DPHPD, 0); /* Setup the GPIOs */ ret = fdtdec_setup_gpio(&local.dp_pd); if (ret) { debug("%s: Could not setup pd gpio (%d)\n", __func__, ret); return ret; } ret = fdtdec_setup_gpio(&local.dp_rst); if (ret) { debug("%s: Could not setup rst gpio (%d)\n", __func__, ret); return ret; } ret = fdtdec_setup_gpio(&local.dp_hpd); if (ret) { debug("%s: Could not setup hpd gpio (%d)\n", __func__, ret); return ret; } fdtdec_set_gpio(&local.dp_pd, 0); gpio_cfg_pin(local.dp_pd.gpio, EXYNOS_GPIO_OUTPUT); gpio_set_pull(local.dp_pd.gpio, EXYNOS_GPIO_PULL_NONE); if (fdt_gpio_isvalid(&local.dp_rst)) { fdtdec_set_gpio(&local.dp_rst, 1); gpio_cfg_pin(local.dp_rst.gpio, EXYNOS_GPIO_OUTPUT); gpio_set_pull(local.dp_rst.gpio, EXYNOS_GPIO_PULL_NONE); udelay(10); fdtdec_set_gpio(&local.dp_rst, 0); } *wait_ms = 0; return 0; }
/* * This functions disable the USB3.0 PLL to save power */ static void disable_usb30_pll(void) { int node, ret; struct fdt_gpio_state en_gpio; node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_SAMSUNG_EXYNOS_USB); if (node < 0) return; ret = fdtdec_decode_gpio(gd->fdt_blob, node, "usb3-pll-gpio", &en_gpio); if (ret) return; fdtdec_setup_gpio(&en_gpio); gpio_direction_output(en_gpio.gpio, en_gpio.flags); }
/* Put the port into host mode (this only works for OTG ports) */ static void set_host_mode(struct fdt_usb *config) { if (config->dr_mode == DR_MODE_OTG) { /* Check whether remote host from USB1 is driving VBus */ if (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS) return; /* * If not driving, we set the GPIO to enable VBUS. We assume * that the pinmux is set up correctly for this. */ if (fdt_gpio_isvalid(&config->vbus_gpio)) { fdtdec_setup_gpio(&config->vbus_gpio); gpio_direction_output(config->vbus_gpio.gpio, 1); debug("set_host_mode: GPIO %d high\n", config->vbus_gpio.gpio); } } }
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { struct exynos_xhci *ctx = &exynos; int ret; #ifdef CONFIG_OF_CONTROL exynos_usb3_parse_dt(gd->fdt_blob, ctx); #else ctx->usb3_phy = (struct exynos_usb3_phy *)samsung_get_base_usb3_phy(); ctx->hcd = (struct xhci_hccr *)samsung_get_base_usb_xhci(); #endif ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); #ifdef CONFIG_OF_CONTROL /* setup the Vbus gpio here */ if (fdt_gpio_isvalid(&ctx->vbus_gpio) && !fdtdec_setup_gpio(&ctx->vbus_gpio)) gpio_direction_output(ctx->vbus_gpio.gpio, 1); #endif ret = exynos_xhci_core_init(ctx); if (ret) { puts("XHCI: failed to initialize controller\n"); return -EINVAL; } *hccr = (ctx->hcd); *hcor = (struct xhci_hcor *)((uint32_t) *hccr + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); debug("Exynos5-xhci: init hccr %x and hcor %x hc_length %d\n", (uint32_t)*hccr, (uint32_t)*hcor, (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); return 0; }
/* * EHCI-initialization * Create the appropriate control structures to manage * a new EHCI host controller. */ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { struct exynos_ehci *ctx = &exynos; #ifdef CONFIG_OF_CONTROL if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) { debug("Unable to parse device tree for ehci-exynos\n"); return -ENODEV; } #else ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy(); ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci(); #endif #ifdef CONFIG_OF_CONTROL /* setup the Vbus gpio here */ if (fdt_gpio_isvalid(&ctx->vbus_gpio) && !fdtdec_setup_gpio(&ctx->vbus_gpio)) gpio_direction_output(ctx->vbus_gpio.gpio, 1); #endif setup_usb_phy(ctx->usb); board_usb_init(index, init); *hccr = ctx->hcd; *hcor = (struct ehci_hcor *)((uint32_t) *hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n", (uint32_t)*hccr, (uint32_t)*hcor, (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); return 0; }
/* Put the port into host mode */ static void set_host_mode(struct fdt_usb *config) { /* * If we are an OTG port, check if remote host is driving VBus and * bail out in this case. */ if (config->dr_mode == DR_MODE_OTG && (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) return; /* * If not driving, we set the GPIO to enable VBUS. We assume * that the pinmux is set up correctly for this. */ if (fdt_gpio_isvalid(&config->vbus_gpio)) { fdtdec_setup_gpio(&config->vbus_gpio); gpio_direction_output(config->vbus_gpio.gpio, (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? 0 : 1); debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? "low" : "high"); } }
/* set up the ULPI USB controller with the parameters provided */ static int init_ulpi_usb_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) { u32 val; int loop_count; struct ulpi_viewport ulpi_vp; /* set up ULPI reference clock on pllp_out4 */ clock_enable(PERIPH_ID_DEV2_OUT); clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); /* reset ULPI phy */ if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { fdtdec_setup_gpio(&config->phy_reset_gpio); gpio_direction_output(config->phy_reset_gpio.gpio, 0); mdelay(5); gpio_set_value(config->phy_reset_gpio.gpio, 1); } /* Reset the usb controller */ clock_enable(config->periph_id); usbf_reset_controller(config, usbctlr); /* enable pinmux bypass */ setbits_le32(&usbctlr->ulpi_timing_ctrl_0, ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); /* Select ULPI parallel interface */ clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT); /* enable ULPI transceiver */ setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); /* configure ULPI transceiver timings */ val = 0; writel(val, &usbctlr->ulpi_timing_ctrl_1); val |= ULPI_DATA_TRIMMER_SEL(4); val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); val |= ULPI_DIR_TRIMMER_SEL(4); writel(val, &usbctlr->ulpi_timing_ctrl_1); udelay(10); val |= ULPI_DATA_TRIMMER_LOAD; val |= ULPI_STPDIRNXT_TRIMMER_LOAD; val |= ULPI_DIR_TRIMMER_LOAD; writel(val, &usbctlr->ulpi_timing_ctrl_1); /* set up phy for host operation with external vbus supply */ ulpi_vp.port_num = 0; ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; if (ulpi_init(&ulpi_vp)) { printf("Tegra ULPI viewport init failed\n"); return -1; } ulpi_set_vbus(&ulpi_vp, 1, 1); ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); /* enable wakeup events */ setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); /* Enable and wait for the phy clock to become valid in 100 ms */ setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); for (loop_count = 100000; loop_count != 0; loop_count--) { if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) break; udelay(1); } if (!loop_count) return -1; clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); return 0; }
/** * Handle the next stage of device init */ static int handle_stage(const void *blob) { debug("%s: stage %d\n", __func__, stage); /* do the things for this stage */ switch (stage) { case STAGE_START: /* Initialize the Tegra display controller */ if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) { printf("%s: Failed to probe display driver\n", __func__); return -1; } /* get panel details */ if (fdt_decode_lcd(blob, &config)) { printf("No valid LCD information in device tree\n"); return -1; } /* * It is possible that the FDT has requested that the LCD be * disabled. We currently don't support this. It would require * changes to U-Boot LCD subsystem to have LCD support * compiled in but not used. An easier option might be to * still have a frame buffer, but leave the backlight off and * remove all mention of lcd in the stdout environment * variable. */ funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); fdtdec_setup_gpio(&config.panel_vdd); fdtdec_setup_gpio(&config.lvds_shutdown); fdtdec_setup_gpio(&config.backlight_vdd); fdtdec_setup_gpio(&config.backlight_en); /* * TODO: If fdt includes output flag we can omit this code * since fdtdec_setup_gpio will do it for us. */ if (fdt_gpio_isvalid(&config.panel_vdd)) gpio_direction_output(config.panel_vdd.gpio, 0); if (fdt_gpio_isvalid(&config.lvds_shutdown)) gpio_direction_output(config.lvds_shutdown.gpio, 0); if (fdt_gpio_isvalid(&config.backlight_vdd)) gpio_direction_output(config.backlight_vdd.gpio, 0); if (fdt_gpio_isvalid(&config.backlight_en)) gpio_direction_output(config.backlight_en.gpio, 0); break; case STAGE_PANEL_VDD: if (fdt_gpio_isvalid(&config.panel_vdd)) gpio_direction_output(config.panel_vdd.gpio, 1); break; case STAGE_LVDS: if (fdt_gpio_isvalid(&config.lvds_shutdown)) gpio_set_value(config.lvds_shutdown.gpio, 1); break; case STAGE_BACKLIGHT_VDD: if (fdt_gpio_isvalid(&config.backlight_vdd)) gpio_set_value(config.backlight_vdd.gpio, 1); break; case STAGE_PWM: /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */ pinmux_set_func(PINGRP_GPU, PMUX_FUNC_PWM); pinmux_tristate_disable(PINGRP_GPU); pwm_enable(config.pwm_channel, 32768, 0xdf, 1); break; case STAGE_BACKLIGHT_EN: if (fdt_gpio_isvalid(&config.backlight_en)) gpio_set_value(config.backlight_en.gpio, 1); break; case STAGE_DONE: break; } /* set up timer for next stage */ timer_next = timer_get_us(); if (stage < FDT_LCD_TIMINGS) timer_next += config.panel_timings[stage] * 1000; /* move to next stage */ stage++; return 0; }
int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp) { char id[MSG_BYTES]; struct cros_ec_dev *dev; int node = 0; *cros_ecp = NULL; do { node = fdtdec_next_compatible(blob, node, COMPAT_GOOGLE_CROS_EC); if (node < 0) { debug("%s: Node not found\n", __func__); return 0; } } while (!fdtdec_get_is_enabled(blob, node)); if (cros_ec_decode_fdt(blob, node, &dev)) { debug("%s: Failed to decode device.\n", __func__); return -CROS_EC_ERR_FDT_DECODE; } switch (dev->interface) { #ifdef CONFIG_CROS_EC_SPI case CROS_EC_IF_SPI: if (cros_ec_spi_init(dev, blob)) { debug("%s: Could not setup SPI interface\n", __func__); return -CROS_EC_ERR_DEV_INIT; } break; #endif #ifdef CONFIG_CROS_EC_I2C case CROS_EC_IF_I2C: if (cros_ec_i2c_init(dev, blob)) return -CROS_EC_ERR_DEV_INIT; break; #endif #ifdef CONFIG_CROS_EC_LPC case CROS_EC_IF_LPC: if (cros_ec_lpc_init(dev, blob)) return -CROS_EC_ERR_DEV_INIT; break; #endif #ifdef CONFIG_CROS_EC_SANDBOX case CROS_EC_IF_SANDBOX: if (cros_ec_sandbox_init(dev, blob)) return -CROS_EC_ERR_DEV_INIT; break; #endif case CROS_EC_IF_NONE: default: return 0; } /* we will poll the EC interrupt line */ fdtdec_setup_gpio(&dev->ec_int); if (fdt_gpio_isvalid(&dev->ec_int)) gpio_direction_input(dev->ec_int.gpio); if (cros_ec_check_version(dev)) { debug("%s: Could not detect CROS-EC version\n", __func__); return -CROS_EC_ERR_CHECK_VERSION; } if (cros_ec_read_id(dev, id, sizeof(id))) { debug("%s: Could not read KBC ID\n", __func__); return -CROS_EC_ERR_READ_ID; } /* Remember this device for use by the cros_ec command */ last_dev = *cros_ecp = dev; debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id); return 0; }