void bcmpmu_otg_xceiv_do_srp(struct bcmpmu_otg_xceiv_data *xceiv_data) { #ifdef CONFIG_USB_OTG if (xceiv_data->otg_xceiver.xceiver.gadget && xceiv_data->otg_xceiver.xceiver.gadget->ops && xceiv_data->otg_xceiver.xceiver.gadget->ops->wakeup && xceiv_data->otg_enabled) { bool vbus_status = 0; bcmpmu_usb_get(xceiv_data->bcmpmu, BCMPMU_USB_CTRL_GET_VBUS_STATUS, &vbus_status); /* Should do SRP only if Vbus is not valid */ if (!vbus_status) { bcm_hsotgctrl_phy_set_non_driving(false); /* Do SRP */ xceiv_data->otg_xceiver.xceiver.gadget-> ops->wakeup(xceiv_data->otg_xceiver.xceiver.gadget); /* Start SRP failure timer to do ADP probes * if it expires */ xceiv_data->otg_xceiver.srp_failure_timer.expires = jiffies + msecs_to_jiffies(T_SRP_FAILURE_MAX_IN_MS); add_timer(&xceiv_data->otg_xceiver.srp_failure_timer); /* SRP initiated. Clear the flag */ xceiv_data->otg_xceiver.otg_srp_reqd = false; } } #endif }
static void bcmpmu_otg_xceiv_chg_detect_handler(struct work_struct *work) { struct bcmpmu_otg_xceiv_data *xceiv_data = container_of(work, struct bcmpmu_otg_xceiv_data, bcm_otg_chg_detect_work); dev_info(xceiv_data->dev, "Charger detect event\n"); /* Read and save USB charger type */ bcmpmu_usb_get(xceiv_data->bcmpmu, BCMPMU_USB_CTRL_GET_USB_TYPE, (void *)&xceiv_data->usb_charger_type); if (xceiv_data->otg_enabled) { /* Core is already up so just set the Vbus status */ bcm_hsotgctrl_phy_set_vbus_stat(true); /* Vbus is up so allow the core to connect */ bcm_hsotgctrl_phy_set_non_driving(false); } else { bool id_default_host = false; id_default_host = bcmpmu_otg_xceiv_check_id_gnd(xceiv_data) || bcmpmu_otg_xceiv_check_id_rid_a(xceiv_data); if (!id_default_host && xceiv_data->otg_xceiver.xceiver.gadget) atomic_notifier_call_chain(&xceiv_data->otg_xceiver. xceiver.notifier, USB_EVENT_VBUS, NULL); } }
static int bcmpmu_otg_xceiv_set_host(struct otg_transceiver *otg, struct usb_bus *host) { struct bcmpmu_otg_xceiv_data *xceiv_data = dev_get_drvdata(otg->dev); int status = 0; dev_dbg(xceiv_data->dev, "Setting Host\n"); otg->host = host; if (host) { if (xceiv_data->otg_enabled) { /* Wake lock forever in OTG build */ wake_lock(&xceiv_data->otg_xceiver.xceiver_wake_lock); /* Do calibration probe */ bcm_otg_do_adp_calibration_probe(xceiv_data); } if (bcmpmu_otg_xceiv_check_id_gnd(xceiv_data) || bcmpmu_otg_xceiv_check_id_rid_a(xceiv_data)) { bcm_hsotgctrl_phy_set_id_stat(false); bcm_hsotgctrl_phy_set_non_driving(false); } else bcm_hsotgctrl_phy_set_id_stat(true); } return status; }
static int bcmpmu_otg_xceiv_pullup_on(struct otg_transceiver *otg, bool on) { struct bcmpmu_otg_xceiv_data *xceiv_data = dev_get_drvdata(otg->dev); if (!xceiv_data) return -EINVAL; bcm_hsotgctrl_phy_set_non_driving(!on); return 0; }
static int bcmpmu_otg_xceiv_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) { struct bcmpmu_otg_xceiv_data *xceiv_data = dev_get_drvdata(otg->dev); int status = 0; bool id_default_host = false; dev_dbg(xceiv_data->dev, "Setting Peripheral\n"); otg->gadget = gadget; id_default_host = bcmpmu_otg_xceiv_check_id_gnd(xceiv_data) || bcmpmu_otg_xceiv_check_id_rid_a(xceiv_data); if (!id_default_host) { if (xceiv_data->otg_enabled && (bcmpmu_otg_xceiv_check_id_rid_b(xceiv_data) == false)) { /* No SRP if RID_B */ /* REVISIT. Shutdown uses sequence for lowest power * and does not meet timing so don't do that in OTG mode * for now. Just do SRP for ADP startup */ bcmpmu_otg_xceiv_do_srp(xceiv_data); } else { int data; bcmpmu_usb_get(xceiv_data->bcmpmu, BCMPMU_USB_CTRL_GET_USB_TYPE, &data); if ((data != PMU_USB_TYPE_SDP) && (data != PMU_USB_TYPE_CDP)) { /* Shutdown the core */ atomic_notifier_call_chain(&xceiv_data-> otg_xceiver.xceiver. notifier, USB_EVENT_NONE, NULL); } } } else { bcm_hsotgctrl_phy_set_id_stat(false); /* Come up connected */ bcm_hsotgctrl_phy_set_non_driving(false); } return status; }
static int bcm_hsotgctrl_probe(struct platform_device *pdev) { int error = 0; unsigned int val; struct bcm_hsotgctrl_drv_data *hsotgctrl_drvdata; struct bcm_hsotgctrl_platform_data *plat_data = NULL; if (pdev->dev.platform_data) plat_data = (struct bcm_hsotgctrl_platform_data *) pdev->dev.platform_data; else if (pdev->dev.of_node) { int val; struct resource *resource; plat_data = kzalloc(sizeof(struct bcm_hsotgctrl_platform_data), GFP_KERNEL); if (!plat_data) { dev_err(&pdev->dev, "%s: memory allocation failed.", __func__); error = -ENOMEM; goto err_ret; } resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (resource->start) plat_data->hsotgctrl_virtual_mem_base = HW_IO_PHYS_TO_VIRT(resource->start); else { pr_info("Invalid hsotgctrl_virtual_mem_basei from DT\n"); goto err_read; } if (of_property_read_u32(pdev->dev.of_node, "chipreg-virtual-mem-base", &val)) { error = -EINVAL; dev_err(&pdev->dev, "chipreg-virtual-mem-base read failed\n"); goto err_read; } plat_data->chipreg_virtual_mem_base = HW_IO_PHYS_TO_VIRT(val); resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (resource->start) plat_data->irq = resource->start; else { pr_info("Invalid irq from DT\n"); goto err_read; } if (of_property_read_string(pdev->dev.of_node, "usb-ahb-clk-name", &plat_data->usb_ahb_clk_name) != 0) { error = -EINVAL; dev_err(&pdev->dev, "usb-ahb-clk-name read failed\n"); goto err_read; } if (of_property_read_string(pdev->dev.of_node, "mdio-mstr-clk-name", &plat_data->mdio_mstr_clk_name) != 0) { error = -EINVAL; dev_err(&pdev->dev, "mdio-mstr-clk-name read failed\n"); goto err_read; } } if (plat_data == NULL) { dev_err(&pdev->dev, "platform_data failed\n"); return -ENODEV; } hsotgctrl_drvdata = kzalloc(sizeof(*hsotgctrl_drvdata), GFP_KERNEL); if (!hsotgctrl_drvdata) { dev_warn(&pdev->dev, "Memory allocation failed\n"); return -ENOMEM; } local_hsotgctrl_handle = hsotgctrl_drvdata; hsotgctrl_drvdata->hsotg_ctrl_base = (void *)plat_data->hsotgctrl_virtual_mem_base; if (!hsotgctrl_drvdata->hsotg_ctrl_base) { dev_warn(&pdev->dev, "No vaddr for HSOTGCTRL!\n"); goto error_get_vaddr; } hsotgctrl_drvdata->chipregs_base = (void *)plat_data->chipreg_virtual_mem_base; if (!hsotgctrl_drvdata->chipregs_base) { dev_warn(&pdev->dev, "No vaddr for CHIPREG!\n"); goto error_get_vaddr; } hsotgctrl_drvdata->dev = &pdev->dev; hsotgctrl_drvdata->otg_clk = clk_get(NULL, plat_data->usb_ahb_clk_name); if (IS_ERR(hsotgctrl_drvdata->otg_clk)) { error = PTR_ERR(hsotgctrl_drvdata->otg_clk); dev_warn(&pdev->dev, "OTG clock allocation failed - %d\n", error); goto error_get_otg_clk; } hsotgctrl_drvdata->mdio_master_clk = clk_get(NULL, plat_data->mdio_mstr_clk_name); if (IS_ERR(hsotgctrl_drvdata->mdio_master_clk)) { error = PTR_ERR(hsotgctrl_drvdata->mdio_master_clk); dev_warn(&pdev->dev, "MDIO Mst clk alloc failed - %d\n", error); goto error_get_master_clk; } hsotgctrl_drvdata->allow_suspend = true; platform_set_drvdata(pdev, hsotgctrl_drvdata); bcm_hsotgctrl_en_clock(true); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* clear bit 15 RDB error */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_USB11_OEB_IS_TXEB_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* S/W reset Phy, active low */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_SOFT_RESET_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* bring Phy out of reset */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_PHY_MODE_MASK; val |= HSOTG_CTRL_PHY_P1CTL_SOFT_RESET_MASK; /* use OTG mode */ val |= PHY_MODE_OTG << HSOTG_CTRL_PHY_P1CTL_PHY_MODE_SHIFT; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* Enable pad, internal PLL etc */ bcm_hsotgctrl_set_phy_off(false); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /*Come up as device until we check PMU ID status * to avoid turning on Vbus before checking */ val = HSOTG_CTRL_USBOTGCONTROL_OTGSTAT_CTRL_MASK | HSOTG_CTRL_USBOTGCONTROL_UTMIOTG_IDDIG_SW_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_HCLK_EN_DIRECT_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_ON_IS_HCLK_EN_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_ON_MASK | HSOTG_CTRL_USBOTGCONTROL_PRST_N_SW_MASK | HSOTG_CTRL_USBOTGCONTROL_HRESET_N_SW_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_USBOTGCONTROL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); error = device_create_file(&pdev->dev, &dev_attr_hsotgctrldump); if (error) { dev_warn(&pdev->dev, "Failed to create HOST file\n"); goto Error_bcm_hsotgctrl_probe; } #ifndef CONFIG_USB_OTG_UTILS /* Clear non-driving as default in case there * is no transceiver hookup */ bcm_hsotgctrl_phy_set_non_driving(false); #endif #ifdef CONFIG_NOP_USB_XCEIV /* Clear non-driving as default in case there * is no transceiver hookup */ bcm_hsotgctrl_phy_set_non_driving(false); #endif pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); hsotgctrl_drvdata->hsotgctrl_irq = platform_get_irq(pdev, 0); /* Create a work queue for wakeup work items */ hsotgctrl_drvdata->bcm_hsotgctrl_work_queue = create_workqueue("bcm_hsotgctrl_events"); if (hsotgctrl_drvdata->bcm_hsotgctrl_work_queue == NULL) { dev_warn(&pdev->dev, "BCM HSOTGCTRL events work queue creation failed\n"); /* Treat this as non-fatal error */ } INIT_DELAYED_WORK(&hsotgctrl_drvdata->wakeup_work, bcm_hsotgctrl_delayed_wakeup_handler); /* disable Bvalid interrupt bit * This interrupt is not currently used as the STAT2 detection * happens from the PMU side. Beacsue of not clearing this bit * Master clock gating feature was not working in Java. This * is not a issue in case of Hawaii * */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_USBOTGCONTROL_OFFSET); val |= 1 << HSOTG_CTRL_USBOTGCONTROL_BVALID_CLR_SHIFT; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_USBOTGCONTROL_OFFSET); bcm_hsotgctrl_en_clock(false); /* request_irq enables irq */ hsotgctrl_drvdata->irq_enabled = true; error = request_irq(hsotgctrl_drvdata->hsotgctrl_irq, bcm_hsotgctrl_wake_irq, IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "bcm_hsotgctrl", (void *)hsotgctrl_drvdata); if (error) { hsotgctrl_drvdata->irq_enabled = false; hsotgctrl_drvdata->hsotgctrl_irq = 0; dev_warn(&pdev->dev, "Failed to request IRQ for wakeup\n"); } return 0; Error_bcm_hsotgctrl_probe: clk_put(hsotgctrl_drvdata->mdio_master_clk); bcm_hsotgctrl_en_clock(false); error_get_master_clk: clk_put(hsotgctrl_drvdata->otg_clk); error_get_otg_clk: error_get_vaddr: kfree(hsotgctrl_drvdata); err_read: if (pdev->dev.of_node) kfree(plat_data); err_ret: pr_err("%s probe failed\n", __func__); return error; }
int bcm_hsotgctrl_phy_deinit(void) { struct bcm_hsotgctrl_drv_data *bcm_hsotgctrl_handle = local_hsotgctrl_handle; if (NULL == local_hsotgctrl_handle) return -ENODEV; if (!bcm_hsotgctrl_handle->dev) return -EIO; if (bcm_hsotgctrl_handle->irq_enabled) { /* We are shutting down USB so ensure wake IRQ * is disabled */ disable_irq(bcm_hsotgctrl_handle->hsotgctrl_irq); bcm_hsotgctrl_handle->irq_enabled = false; } if (work_pending(&bcm_hsotgctrl_handle->wakeup_work.work)) { /* Cancel scheduled work */ cancel_delayed_work(&bcm_hsotgctrl_handle-> wakeup_work); /* Make sure work queue is flushed */ flush_workqueue(bcm_hsotgctrl_handle-> bcm_hsotgctrl_work_queue); } /* Disable wakeup condition */ bcm_hsotgctrl_phy_wakeup_condition(false); /* Stay disconnected */ bcm_hsotgctrl_wakeup_core(); bcm_hsotgctrl_phy_set_non_driving(true); /* Disable pad, internal PLL etc. */ bcm_hsotgctrl_set_phy_off(true); /* Enable software control of PHY-PM */ bcm_hsotgctrl_set_soft_ldo_pwrdn(true); /* Isolate PHY */ bcm_hsotgctrl_set_phy_iso(true); /* Power down ALDO */ bcm_hsotgctrl_set_aldo_pdn(false); /* Clear PHY reference clock request */ bcm_hsotgctrl_set_phy_clk_request(false); /* Clear Vbus valid state */ bcm_hsotgctrl_phy_set_vbus_stat(false); /* Disable the OTG core AHB clock */ bcm_hsotgctrl_en_clock(false); return 0; }
int bcm_hsotgctrl_phy_init(bool id_device) { int val; struct bcm_hsotgctrl_drv_data *bcm_hsotgctrl_handle = local_hsotgctrl_handle; if (NULL == local_hsotgctrl_handle) return -ENODEV; if ((!bcm_hsotgctrl_handle->hsotg_ctrl_base) || (!bcm_hsotgctrl_handle->dev)) return -EIO; bcm_hsotgctrl_en_clock(true); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* clear bit 15 RDB error */ val = readl(bcm_hsotgctrl_handle->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_USB11_OEB_IS_TXEB_MASK; writel(val, bcm_hsotgctrl_handle->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* Enable software control of PHY-PM */ bcm_hsotgctrl_set_soft_ldo_pwrdn(true); /* Put PHY in reset state */ bcm_hsotgctrl_set_phy_resetb(false); /* Reset PHY and AHB clock domain */ bcm_hsotgctrl_reset_clk_domain(); /* Power up ALDO */ bcm_hsotgctrl_set_aldo_pdn(true); mdelay(PHY_PM_DELAY_IN_MS); /* Enable pad, internal PLL etc */ bcm_hsotgctrl_set_phy_off(false); bcm_hsotgctrl_set_ldo_suspend_mask(); /* Remove PHY isolation */ bcm_hsotgctrl_set_phy_iso(false); mdelay(PHY_PM_DELAY_IN_MS); /* PHY clock request */ bcm_hsotgctrl_set_phy_clk_request(true); mdelay(PHY_PLL_DELAY_MS); /* Bring Put PHY out of reset state */ bcm_hsotgctrl_set_phy_resetb(true); /* Don't disable software control of PHY-PM * We want to control the PHY LDOs from software */ bcm_hsotgctrl_phy_mdio_initialization(); if (id_device) { /* Set correct ID value */ bcm_hsotgctrl_phy_set_id_stat(true); /* Set Vbus valid state */ bcm_hsotgctrl_phy_set_vbus_stat(true); } else { /* Set correct ID value */ bcm_hsotgctrl_phy_set_id_stat(false); /* Clear non-driving */ bcm_hsotgctrl_phy_set_non_driving(false); } msleep(HSOTGCTRL_ID_CHANGE_DELAY_IN_MS); return 0; }
static void bcmpmu_otg_xceiv_vbus_a_invalid_handler(struct work_struct *work) { struct bcmpmu_otg_xceiv_data *xceiv_data = container_of(work, struct bcmpmu_otg_xceiv_data, bcm_otg_vbus_a_invalid_work); int bcm_hsotgctrl_status; /* dev_info(xceiv_data->dev, "A session invalid\n"); */ fsa9485_vbus_check(0); if ( !(bcm_hsotgctrl_status = bcm_hsotgctrl_get_clk_count()) ) bcm_hsotgctrl_en_clock(true); else if (-ENODEV == bcm_hsotgctrl_status || -EIO == bcm_hsotgctrl_status ) return ; /* Inform the core of session invalid level */ bcm_hsotgctrl_phy_set_vbus_stat(false); if (xceiv_data->otg_enabled) { /* Stop Vbus discharge */ bcmpmu_usb_set(xceiv_data->bcmpmu, BCMPMU_USB_CTRL_DISCHRG_VBUS, 0); if (bcmpmu_otg_xceiv_check_id_gnd(xceiv_data)) { /* Use n-1 method for ADP rise time comparison */ bcmpmu_usb_set(xceiv_data->bcmpmu, BCMPMU_USB_CTRL_SET_ADP_COMP_METHOD, 1); if (xceiv_data->otg_xceiver.otg_vbus_off) schedule_delayed_work(&xceiv_data-> bcm_otg_delayed_adp_work, msecs_to_jiffies (T_NO_ADP_DELAY_MIN_IN_MS)); else bcm_otg_do_adp_probe(xceiv_data, true); } else if (!bcmpmu_otg_xceiv_check_id_rid_a(xceiv_data)) { /* Vbus is off now so don't allow * core to connect */ bcm_hsotgctrl_phy_set_non_driving(true); if (xceiv_data->otg_xceiver.otg_srp_reqd) { /* Start Session End SRP timer */ xceiv_data->otg_xceiver.sess_end_srp_timer.expires = jiffies + msecs_to_jiffies(T_SESS_END_SRP_START_IN_MS); add_timer(&xceiv_data->otg_xceiver.sess_end_srp_timer); } else bcm_otg_do_adp_sense(xceiv_data, true); } } else { bool id_default_host = false; id_default_host = bcmpmu_otg_xceiv_check_id_gnd(xceiv_data) || bcmpmu_otg_xceiv_check_id_rid_a(xceiv_data); if (!id_default_host) { atomic_notifier_call_chain(&xceiv_data->otg_xceiver. xceiver.notifier, USB_EVENT_NONE, NULL); } } }
static int __devinit bcm_hsotgctrl_probe(struct platform_device *pdev) { int error = 0; int val; struct bcm_hsotgctrl_drv_data *hsotgctrl_drvdata; struct bcm_hsotgctrl_platform_data *plat_data = (struct bcm_hsotgctrl_platform_data *)pdev->dev.platform_data; if (plat_data == NULL) { dev_err(&pdev->dev, "platform_data failed\n"); return -ENODEV; } hsotgctrl_drvdata = kzalloc(sizeof(*hsotgctrl_drvdata), GFP_KERNEL); if (!hsotgctrl_drvdata) { dev_warn(&pdev->dev, "Memory allocation failed\n"); return -ENOMEM; } local_hsotgctrl_handle = hsotgctrl_drvdata; hsotgctrl_drvdata->hsotg_ctrl_base = (void *)plat_data->hsotgctrl_virtual_mem_base; if (!hsotgctrl_drvdata->hsotg_ctrl_base) { dev_warn(&pdev->dev, "No vaddr for HSOTGCTRL!\n"); kfree(hsotgctrl_drvdata); return -ENOMEM; } hsotgctrl_drvdata->chipregs_base = (void *)plat_data->chipreg_virtual_mem_base; if (!hsotgctrl_drvdata->chipregs_base) { dev_warn(&pdev->dev, "No vaddr for CHIPREG!\n"); kfree(hsotgctrl_drvdata); return -ENOMEM; } hsotgctrl_drvdata->dev = &pdev->dev; hsotgctrl_drvdata->otg_clk = clk_get(NULL, plat_data->usb_ahb_clk_name); if (IS_ERR(hsotgctrl_drvdata->otg_clk)) { error = PTR_ERR(hsotgctrl_drvdata->otg_clk); dev_warn(&pdev->dev, "OTG clock allocation failed\n"); kfree(hsotgctrl_drvdata); return error; } hsotgctrl_drvdata->mdio_master_clk = clk_get(NULL, plat_data->mdio_mstr_clk_name); if (IS_ERR(hsotgctrl_drvdata->mdio_master_clk)) { error = PTR_ERR(hsotgctrl_drvdata->mdio_master_clk); dev_warn(&pdev->dev, "MDIO Mst clk alloc failed\n"); kfree(hsotgctrl_drvdata); return error; } hsotgctrl_drvdata->allow_suspend = true; platform_set_drvdata(pdev, hsotgctrl_drvdata); /* Init the PHY */ hsotgctrl_drvdata->usb_active = true; bcm_hsotgctrl_en_clock(true); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* clear bit 15 RDB error */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_USB11_OEB_IS_TXEB_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* S/W reset Phy, active low */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_SOFT_RESET_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* bring Phy out of reset */ val = readl(hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); val &= ~HSOTG_CTRL_PHY_P1CTL_PHY_MODE_MASK; val |= HSOTG_CTRL_PHY_P1CTL_SOFT_RESET_MASK; /* use OTG mode */ val |= PHY_MODE_OTG << HSOTG_CTRL_PHY_P1CTL_PHY_MODE_SHIFT; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_PHY_P1CTL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /* Enable pad, internal PLL etc */ bcm_hsotgctrl_set_phy_off(false); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); /*Come up as device until we check PMU ID status * to avoid turning on Vbus before checking */ val = HSOTG_CTRL_USBOTGCONTROL_OTGSTAT_CTRL_MASK | HSOTG_CTRL_USBOTGCONTROL_UTMIOTG_IDDIG_SW_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_HCLK_EN_DIRECT_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_ON_IS_HCLK_EN_MASK | HSOTG_CTRL_USBOTGCONTROL_USB_ON_MASK | HSOTG_CTRL_USBOTGCONTROL_PRST_N_SW_MASK | HSOTG_CTRL_USBOTGCONTROL_HRESET_N_SW_MASK; writel(val, hsotgctrl_drvdata->hsotg_ctrl_base + HSOTG_CTRL_USBOTGCONTROL_OFFSET); mdelay(HSOTGCTRL_STEP_DELAY_IN_MS); error = device_create_file(&pdev->dev, &dev_attr_hsotgctrldump); if (error) { dev_warn(&pdev->dev, "Failed to create HOST file\n"); goto Error_bcm_hsotgctrl_probe; } #ifndef CONFIG_USB_OTG_UTILS /* Clear non-driving as default in case there * is no transceiver hookup */ bcm_hsotgctrl_phy_set_non_driving(false); #endif #ifdef CONFIG_NOP_USB_XCEIV /* Clear non-driving as default in case there * is no transceiver hookup */ bcm_hsotgctrl_phy_set_non_driving(false); #endif pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); hsotgctrl_drvdata->hsotgctrl_irq = platform_get_irq(pdev, 0); /* Create a work queue for wakeup work items */ hsotgctrl_drvdata->bcm_hsotgctrl_work_queue = create_workqueue("bcm_hsotgctrl_events"); if (hsotgctrl_drvdata->bcm_hsotgctrl_work_queue == NULL) { dev_warn(&pdev->dev, "BCM HSOTGCTRL events work queue creation failed\n"); /* Treat this as non-fatal error */ } INIT_DELAYED_WORK(&hsotgctrl_drvdata->wakeup_work, bcm_hsotgctrl_delayed_wakeup_handler); /* request_irq enables irq */ hsotgctrl_drvdata->irq_enabled = true; error = request_irq(hsotgctrl_drvdata->hsotgctrl_irq, bcm_hsotgctrl_wake_irq, IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "bcm_hsotgctrl", (void *)hsotgctrl_drvdata); if (error) { hsotgctrl_drvdata->irq_enabled = false; hsotgctrl_drvdata->hsotgctrl_irq = 0; dev_warn(&pdev->dev, "Failed to request IRQ for wakeup\n"); } local_wakeup_core_cb = NULL; return 0; Error_bcm_hsotgctrl_probe: clk_put(hsotgctrl_drvdata->otg_clk); clk_put(hsotgctrl_drvdata->mdio_master_clk); kfree(hsotgctrl_drvdata); return error; }