static int populate_spdm_data(struct spdm_data *data, struct platform_device *pdev) { int ret = -EINVAL; struct device_node *node = pdev->dev.of_node; ret = populate_config_data(data, pdev); if (ret) return ret; ret = of_property_read_u32(node, "qcom,spdm-client", &data->spdm_client); if (ret) goto no_client; ret = of_property_read_u32(node, "qcom,spdm-interval", &data->window); if (ret) data->window = DEVFREQ_SPDM_DEFAULT_WINDOW_MS; data->pdata = msm_bus_cl_get_pdata(pdev); if (!data->pdata) { ret = -EINVAL; goto no_pdata; } return 0; no_client: no_pdata: devm_kfree(&pdev->dev, data->config_data.ports); data->config_data.ports = NULL; return ret; }
static int of_read_bus_pdata(struct platform_device *pdev, struct pil_tz_data *d) { struct msm_bus_scale_pdata *pdata; pdata = msm_bus_cl_get_pdata(pdev); if (!pdata) return -EINVAL; d->bus_client = msm_bus_scale_register_client(pdata); if (!d->bus_client) return -EINVAL; return 0; }
static int __get_bus_vote_client(struct platform_device *pdev, struct msm_iommu_drvdata *drvdata) { int ret = 0; struct msm_bus_scale_pdata *bs_table; const char *dummy; /* Check whether bus scaling has been specified for this node */ ret = of_property_read_string(pdev->dev.of_node, "qcom,msm-bus,name", &dummy); if (ret) return 0; bs_table = msm_bus_cl_get_pdata(pdev); if (bs_table) { drvdata->bus_client = msm_bus_scale_register_client(bs_table); if (IS_ERR(&drvdata->bus_client)) { pr_err("%s(): Bus client register failed.\n", __func__); ret = -EINVAL; } } return ret; }
static int broadcast_tdmb_fc8080_probe(struct spi_device *spi) { int rc; if(spi == NULL) { printk("broadcast_fc8080_probe spi is NULL, so spi can not be set\n"); return -1; } fc8080_ctrl_info.TdmbPowerOnState = FALSE; fc8080_ctrl_info.spi_ptr = spi; fc8080_ctrl_info.spi_ptr->mode = SPI_MODE_0; fc8080_ctrl_info.spi_ptr->bits_per_word = 8; fc8080_ctrl_info.spi_ptr->max_speed_hz = (15000*1000); fc8080_ctrl_info.pdev = to_platform_device(&spi->dev); #ifdef FEATURE_DMB_USE_BUS_SCALE fc8080_ctrl_info.bus_scale_pdata = msm_bus_cl_get_pdata(fc8080_ctrl_info.pdev); fc8080_ctrl_info.bus_scale_client_id = msm_bus_scale_register_client(fc8080_ctrl_info.bus_scale_pdata); #endif // Once I have a spi_device structure I can do a transfer anytime rc = spi_setup(spi); printk("broadcast_tdmb_fc8080_probe spi_setup=%d\n", rc); bbm_com_hostif_select(NULL, 1); #ifdef FEATURE_DMB_USE_XO fc8080_ctrl_info.clk = clk_get(&fc8080_ctrl_info.spi_ptr->dev, "xo"); if (IS_ERR(fc8080_ctrl_info.clk)) { rc = PTR_ERR(fc8080_ctrl_info.clk); dev_err(&fc8080_ctrl_info.spi_ptr->dev, "could not get clock\n"); return rc; } /* We enable/disable the clock only to assure it works */ rc = clk_prepare_enable(fc8080_ctrl_info.clk); if (rc) { dev_err(&fc8080_ctrl_info.spi_ptr->dev, "could not enable clock\n"); return rc; } clk_disable_unprepare(fc8080_ctrl_info.clk); #endif #ifdef FEATURE_DMB_USE_WORKQUEUE INIT_WORK(&fc8080_ctrl_info.spi_work, broacast_tdmb_spi_work); fc8080_ctrl_info.spi_wq = create_singlethread_workqueue("tdmb_spi_wq"); if(fc8080_ctrl_info.spi_wq == NULL){ printk("Failed to setup tdmb spi workqueue \n"); return -ENOMEM; } #endif tdmb_configure_gpios(); #ifdef FEATURE_DMB_USE_WORKQUEUE rc = request_irq(spi->irq, broadcast_tdmb_spi_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, spi->dev.driver->name, &fc8080_ctrl_info); #else rc = request_threaded_irq(spi->irq, NULL, broadcast_tdmb_spi_event_handler, IRQF_ONESHOT | IRQF_DISABLED | IRQF_TRIGGER_FALLING, spi->dev.driver->name, &fc8080_ctrl_info); #endif printk("broadcast_tdmb_fc8080_probe request_irq=%d\n", rc); tdmb_fc8080_interrupt_lock(); mutex_init(&fc8080_ctrl_info.mutex); wake_lock_init(&fc8080_ctrl_info.wake_lock, WAKE_LOCK_SUSPEND, dev_name(&spi->dev)); spin_lock_init(&fc8080_ctrl_info.spin_lock); #ifdef FEATURE_DMB_USE_PM_QOS pm_qos_add_request(&fc8080_ctrl_info.pm_req_list, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); #endif printk("broadcast_fc8080_probe End\n"); return rc; }
static int msm_rng_probe(struct platform_device *pdev) { struct resource *res; struct msm_rng_device *msm_rng_dev = NULL; void __iomem *base = NULL; int error = 0; int ret = 0; struct device *dev; struct msm_bus_scale_pdata *qrng_platform_support = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "invalid address\n"); error = -EFAULT; goto err_exit; } msm_rng_dev = kzalloc(sizeof(msm_rng_dev), GFP_KERNEL); if (!msm_rng_dev) { dev_err(&pdev->dev, "cannot allocate memory\n"); error = -ENOMEM; goto err_exit; } base = ioremap(res->start, resource_size(res)); if (!base) { dev_err(&pdev->dev, "ioremap failed\n"); error = -ENOMEM; goto err_iomap; } msm_rng_dev->base = base; /* create a handle for clock control */ if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node, "qcom,msm-rng-iface-clk"))) msm_rng_dev->prng_clk = clk_get(&pdev->dev, "iface_clk"); else msm_rng_dev->prng_clk = clk_get(&pdev->dev, "core_clk"); if (IS_ERR(msm_rng_dev->prng_clk)) { dev_err(&pdev->dev, "failed to register clock source\n"); error = -EPERM; goto err_clk_get; } /* save away pdev and register driver data */ msm_rng_dev->pdev = pdev; platform_set_drvdata(pdev, msm_rng_dev); if (pdev->dev.of_node) { /* Register bus client */ qrng_platform_support = msm_bus_cl_get_pdata(pdev); msm_rng_dev->qrng_perf_client = msm_bus_scale_register_client( qrng_platform_support); msm_rng_device_info.qrng_perf_client = msm_rng_dev->qrng_perf_client; if (!msm_rng_dev->qrng_perf_client) pr_err("Unable to register bus client\n"); } /* Enable rng h/w */ error = msm_rng_enable_hw(msm_rng_dev); if (error) goto rollback_clk; /* register with hwrng framework */ msm_rng.priv = (unsigned long) msm_rng_dev; error = hwrng_register(&msm_rng); if (error) { dev_err(&pdev->dev, "failed to register hwrng\n"); error = -EPERM; goto rollback_clk; } ret = register_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME, &msm_rng_fops); msm_rng_class = class_create(THIS_MODULE, "msm-rng"); if (IS_ERR(msm_rng_class)) { pr_err("class_create failed\n"); return PTR_ERR(msm_rng_class); } dev = device_create(msm_rng_class, NULL, MKDEV(QRNG_IOC_MAGIC, 0), NULL, "msm-rng"); if (IS_ERR(dev)) { pr_err("Device create failed\n"); error = PTR_ERR(dev); goto unregister_chrdev; } cdev_init(&msm_rng_cdev, &msm_rng_fops); return ret; unregister_chrdev: unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME); rollback_clk: clk_put(msm_rng_dev->prng_clk); err_clk_get: iounmap(msm_rng_dev->base); err_iomap: kfree(msm_rng_dev); err_exit: return error; }
static int ath6kl_hsic_probe(struct platform_device *pdev) { struct ath6kl_platform_data *pdata = NULL; struct device *dev = &pdev->dev; int ret = 0; if (machine_is_apq8064_dma()) { ath6kl_dbg(ATH6KL_DBG_BOOT, "%s\n", __func__); previous = 0; ath6kl_toggle_radio(pdev->dev.platform_data, 1); } else { ath6kl_bus_scale_pdata = msm_bus_cl_get_pdata(pdev); bus_perf_client = msm_bus_scale_register_client( ath6kl_bus_scale_pdata); msm_bus_scale_client_update_request(bus_perf_client, 4); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { ath6kl_err("%s: Could not allocate memory for platform data\n", __func__); return -ENOMEM; } if (ath6kl_dt_parse_vreg_info(dev, &pdata->wifi_chip_pwd, "qca,wifi-chip-pwd") != 0) { ath6kl_err("%s: parse vreg info for %s error\n", "chip_pwd", __func__); goto err; } if (ath6kl_dt_parse_vreg_info(dev, &pdata->wifi_vddpa, "qca,wifi-vddpa") != 0) { ath6kl_err("%s: parse vreg info for %s error\n", "vddpa", __func__); goto err; } if (ath6kl_dt_parse_vreg_info(dev, &pdata->wifi_vddio, "qca,wifi-vddio") != 0) { ath6kl_err("%s: parse vreg info for %s error\n", "vddio", __func__); goto err; } pdata->pdev = pdev; platform_set_drvdata(pdev, pdata); gpdata = pdata; if (pdata->wifi_chip_pwd != NULL) { ret = ath6kl_platform_power(pdata, 1); if (ret == 0 && ath6kl_bt_on == 0) ath6kl_hsic_bind(1); *platform_has_vreg = 1; } } return ret; err: if (pdata != NULL) devm_kfree(dev, pdata); return -EINVAL; }
static int ehci_msm2_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct resource *res; struct msm_hcd *mhcd; struct pinctrl_state *set_state; const struct msm_usb_host_platform_data *pdata; char pdev_name[PDEV_NAME_LEN]; int ret; dev_dbg(&pdev->dev, "ehci_msm2 probe\n"); /* * Fail probe in case of uicc till userspace activates driver through * sysfs entry. */ if (!uicc_card_present && pdev->dev.of_node && of_property_read_bool( pdev->dev.of_node, "qcom,usb2-enable-uicc")) return -ENODEV; hcd = usb_create_hcd(&ehci_msm2_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); return -ENOMEM; } mhcd = hcd_to_mhcd(hcd); mhcd->dev = &pdev->dev; mhcd->xo_clk = clk_get(&pdev->dev, "xo"); if (IS_ERR(mhcd->xo_clk)) { ret = PTR_ERR(mhcd->xo_clk); mhcd->xo_clk = NULL; if (ret == -EPROBE_DEFER) goto put_hcd; } ret = msm_ehci_init_clocks(mhcd, 1); if (ret) goto xo_put; if (pdev->dev.of_node) { dev_dbg(&pdev->dev, "device tree enabled\n"); pdev->dev.platform_data = ehci_msm2_dt_to_pdata(pdev); } if (!pdev->dev.platform_data) dev_dbg(&pdev->dev, "No platform data given\n"); pdata = pdev->dev.platform_data; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &ehci_msm_dma_mask; if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); hcd_to_bus(hcd)->skip_resume = true; hcd->irq = platform_get_irq(pdev, 0); if (hcd->irq < 0) { dev_err(&pdev->dev, "Unable to get IRQ resource\n"); ret = hcd->irq; goto deinit_clocks; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Unable to get memory resource\n"); ret = -ENODEV; goto deinit_clocks; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto deinit_clocks; } spin_lock_init(&mhcd->wakeup_lock); mhcd->async_irq = platform_get_irq_byname(pdev, "async_irq"); if (mhcd->async_irq < 0) { dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n"); mhcd->async_irq = 0; } else { ret = request_irq(mhcd->async_irq, msm_async_irq, IRQF_TRIGGER_RISING, "msm_ehci_host", mhcd); if (ret) { dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n"); goto unmap; } disable_irq(mhcd->async_irq); } snprintf(pdev_name, PDEV_NAME_LEN, "%s.%d", pdev->name, pdev->id); if (mhcd->xo_clk) ret = clk_prepare_enable(mhcd->xo_clk); if (ret) { dev_err(&pdev->dev, "%s failed to vote for TCXO %d\n", __func__, ret); goto free_xo_handle; } /* Get pinctrl if target uses pinctrl */ mhcd->hsusb_pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR(mhcd->hsusb_pinctrl)) { if (of_property_read_bool(pdev->dev.of_node, "pinctrl-names")) { dev_err(&pdev->dev, "Error encountered while getting pinctrl"); ret = PTR_ERR(mhcd->hsusb_pinctrl); goto devote_xo_handle; } pr_debug("Target does not use pinctrl\n"); mhcd->hsusb_pinctrl = NULL; } if (mhcd->hsusb_pinctrl) { set_state = pinctrl_lookup_state(mhcd->hsusb_pinctrl, "ehci_active"); if (IS_ERR(set_state)) { pr_err("cannot get hsusb pinctrl active state\n"); ret = PTR_ERR(set_state); goto devote_xo_handle; } ret = pinctrl_select_state(mhcd->hsusb_pinctrl, set_state); if (ret) { pr_err("cannot set hsusb pinctrl active state\n"); goto devote_xo_handle; } } if (pdata && gpio_is_valid(pdata->resume_gpio)) { mhcd->resume_gpio = pdata->resume_gpio; ret = devm_gpio_request(&pdev->dev, mhcd->resume_gpio, "hsusb_resume"); if (ret) { dev_err(&pdev->dev, "resume gpio(%d) request failed:%d\n", mhcd->resume_gpio, ret); mhcd->resume_gpio = -EINVAL; } else { /* to override ehci_bus_resume from ehci-hcd library */ ehci_bus_resume_func = ehci_msm2_hc_driver.bus_resume; ehci_msm2_hc_driver.bus_resume = msm_ehci_bus_resume_with_gpio; } } if (pdata && gpio_is_valid(pdata->ext_hub_reset_gpio)) { ret = devm_gpio_request(&pdev->dev, pdata->ext_hub_reset_gpio, "hsusb_reset"); if (ret) { dev_err(&pdev->dev, "reset gpio(%d) request failed:%d\n", pdata->ext_hub_reset_gpio, ret); goto pinctrl_sleep; } else { /* reset external hub */ gpio_direction_output(pdata->ext_hub_reset_gpio, 0); /* * Hub reset should be asserted for minimum 5microsec * before deasserting. */ usleep_range(5, 1000); gpio_direction_output(pdata->ext_hub_reset_gpio, 1); } } spin_lock_init(&mhcd->wakeup_lock); ret = msm_ehci_init_vddcx(mhcd, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize VDDCX\n"); ret = -ENODEV; goto pinctrl_sleep; } ret = msm_ehci_config_vddcx(mhcd, 1); if (ret) { dev_err(&pdev->dev, "hsusb vddcx configuration failed\n"); goto deinit_vddcx; } ret = msm_ehci_ldo_init(mhcd, 1); if (ret) { dev_err(&pdev->dev, "hsusb vreg configuration failed\n"); goto deinit_vddcx; } ret = msm_ehci_ldo_enable(mhcd, 1); if (ret) { dev_err(&pdev->dev, "hsusb vreg enable failed\n"); goto deinit_ldo; } ret = msm_ehci_init_vbus(mhcd, 1); if (ret) goto disable_ldo; hcd->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); if (IS_ERR(hcd->phy)) { if (PTR_ERR(hcd->phy) == -EPROBE_DEFER) { dev_dbg(&pdev->dev, "usb-phy not probed yet\n"); ret = -EPROBE_DEFER; goto vbus_deinit; } hcd->phy = NULL; } if (hcd->phy) { usb_phy_init(hcd->phy); /* Set Host mode flag */ hcd->phy->flags |= PHY_HOST_MODE; } else if (pdata && pdata->use_sec_phy) { mhcd->usb_phy_ctrl_reg = USB_PHY_CTRL2; } else { mhcd->usb_phy_ctrl_reg = USB_PHY_CTRL; } ret = msm_hsusb_reset(mhcd); if (ret) { dev_err(&pdev->dev, "hsusb PHY initialization failed\n"); goto vbus_deinit; } ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); if (ret) { dev_err(&pdev->dev, "unable to register HCD\n"); goto vbus_deinit; } mhcd->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (!mhcd->bus_scale_table) { dev_dbg(&pdev->dev, "bus scaling is disabled\n"); } else { mhcd->bus_perf_client = msm_bus_scale_register_client(mhcd->bus_scale_table); ret = msm_bus_scale_client_update_request( mhcd->bus_perf_client, 1); if (ret) dev_err(&pdev->dev, "Failed to vote for bus scaling\n"); } pdata = mhcd->dev->platform_data; if (pdata && (!pdata->dock_connect_irq || !irq_read_line(pdata->dock_connect_irq))) msm_ehci_vbus_power(mhcd, 1); /* For peripherals directly conneted to downstream port of root hub * and require to drive suspend and resume by controller driver instead * of root hub. */ if (pdata) mhcd->ehci.no_selective_suspend = pdata->no_selective_suspend; mhcd->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq"); if (mhcd->wakeup_irq > 0) { dev_dbg(&pdev->dev, "wakeup irq:%d\n", mhcd->wakeup_irq); irq_set_status_flags(mhcd->wakeup_irq, IRQ_NOAUTOEN); ret = request_irq(mhcd->wakeup_irq, msm_hsusb_wakeup_irq, IRQF_TRIGGER_HIGH, "msm_hsusb_wakeup", mhcd); if (ret) { dev_err(&pdev->dev, "request_irq(%d) failed:%d\n", mhcd->wakeup_irq, ret); mhcd->wakeup_irq = 0; } } else { mhcd->wakeup_irq = 0; } device_init_wakeup(&pdev->dev, 1); wakeup_source_init(&mhcd->ws, dev_name(&pdev->dev)); pm_stay_awake(mhcd->dev); INIT_WORK(&mhcd->phy_susp_fail_work, msm_ehci_phy_susp_fail_work); /* * This pdev->dev is assigned parent of root-hub by USB core, * hence, runtime framework automatically calls this driver's * runtime APIs based on root-hub's state. */ /* configure pmic_gpio_irq for D+ change */ if (pdata && pdata->pmic_gpio_dp_irq) mhcd->pmic_gpio_dp_irq = pdata->pmic_gpio_dp_irq; if (mhcd->pmic_gpio_dp_irq) { ret = request_threaded_irq(mhcd->pmic_gpio_dp_irq, NULL, msm_ehci_host_wakeup_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "msm_ehci_host_wakeup", mhcd); if (!ret) { disable_irq_nosync(mhcd->pmic_gpio_dp_irq); } else { dev_err(&pdev->dev, "request_irq(%d) failed: %d\n", mhcd->pmic_gpio_dp_irq, ret); mhcd->pmic_gpio_dp_irq = 0; } } if (pdata && pdata->pm_qos_latency) pm_qos_add_request(&mhcd->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, pdata->pm_qos_latency + 1); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); if (ehci_debugfs_init(mhcd) < 0) dev_err(mhcd->dev, "%s: debugfs init failed\n", __func__); return 0; vbus_deinit: msm_ehci_init_vbus(mhcd, 0); disable_ldo: msm_ehci_ldo_enable(mhcd, 0); deinit_ldo: msm_ehci_ldo_init(mhcd, 0); deinit_vddcx: msm_ehci_init_vddcx(mhcd, 0); pinctrl_sleep: if (mhcd->hsusb_pinctrl) { set_state = pinctrl_lookup_state(mhcd->hsusb_pinctrl, "ehci_sleep"); if (IS_ERR(set_state)) pr_err("cannot get hsusb pinctrl sleep state\n"); else pinctrl_select_state(mhcd->hsusb_pinctrl, set_state); } devote_xo_handle: if (mhcd->xo_clk) clk_disable_unprepare(mhcd->xo_clk); free_xo_handle: if (mhcd->xo_clk) { clk_put(mhcd->xo_clk); mhcd->xo_clk = NULL; } if (mhcd->async_irq) free_irq(mhcd->async_irq, mhcd); unmap: iounmap(hcd->regs); deinit_clocks: msm_ehci_init_clocks(mhcd, 0); xo_put: if (mhcd->xo_clk) clk_put(mhcd->xo_clk); put_hcd: usb_put_hcd(hcd); return ret; }
static int mxhci_hsic_probe(struct platform_device *pdev) { struct hc_driver *driver; struct device_node *node = pdev->dev.of_node; struct mxhci_hsic_hcd *mxhci; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; unsigned int reg; int ret; int irq; u32 tmp[3]; if (usb_disabled()) return -ENODEV; driver = &mxhci_hsic_hc_driver; pdev->dev.dma_mask = &dma_mask; /* dbg log event settings */ dbg_hsic.log_events = enable_dbg_log; dbg_hsic.log_payload = enable_payload_log; dbg_hsic.inep_log_mask = ep_addr_rxdbg_mask; dbg_hsic.outep_log_mask = ep_addr_rxdbg_mask; /* usb2.0 root hub */ driver->hcd_priv_size = sizeof(struct mxhci_hsic_hcd); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = -ENODEV; goto put_hcd; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; goto put_hcd; } hcd_to_bus(hcd)->skip_resume = true; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { dev_err(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; goto put_hcd; } mxhci = hcd_to_hsic(hcd); mxhci->dev = &pdev->dev; mxhci->strobe = of_get_named_gpio(node, "hsic,strobe-gpio", 0); if (mxhci->strobe < 0) { ret = -EINVAL; goto put_hcd; } mxhci->data = of_get_named_gpio(node, "hsic,data-gpio", 0); if (mxhci->data < 0) { ret = -EINVAL; goto put_hcd; } ret = of_property_read_u32_array(node, "qcom,vdd-voltage-level", tmp, ARRAY_SIZE(tmp)); if (!ret) { mxhci->vdd_no_vol_level = tmp[0]; mxhci->vdd_low_vol_level = tmp[1]; mxhci->vdd_high_vol_level = tmp[2]; } else { dev_err(&pdev->dev, "failed to read qcom,vdd-voltage-level property\n"); ret = -EINVAL; goto put_hcd; } ret = mxhci_msm_config_gdsc(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to configure hsic gdsc\n"); goto put_hcd; } ret = mxhci_hsic_init_clocks(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize clocks\n"); goto put_hcd; } ret = mxhci_hsic_init_vddcx(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize vddcx\n"); goto deinit_clocks; } mxhci_hsic_reset(mxhci); /* HSIC phy caliberation:set periodic caliberation interval ~2.048sec */ mxhci_hsic_ulpi_write(mxhci, 0xFF, MSM_HSIC_IO_CAL_PER); /* Enable periodic IO calibration in HSIC_CFG register */ mxhci_hsic_ulpi_write(mxhci, 0xA8, MSM_HSIC_CFG); /* Configure Strobe and Data GPIOs to enable HSIC */ ret = mxhci_hsic_config_gpios(mxhci); if (ret) { dev_err(mxhci->dev, " gpio configuarion failed\n"); goto deinit_vddcx; } /* enable STROBE_PAD_CTL */ reg = readl_relaxed(TLMM_GPIO_HSIC_STROBE_PAD_CTL); writel_relaxed(reg | 0x2000000, TLMM_GPIO_HSIC_STROBE_PAD_CTL); /* enable DATA_PAD_CTL */ reg = readl_relaxed(TLMM_GPIO_HSIC_DATA_PAD_CTL); writel_relaxed(reg | 0x2000000, TLMM_GPIO_HSIC_DATA_PAD_CTL); mb(); /* Enable LPM in Sleep mode and suspend mode */ reg = readl_relaxed(MSM_HSIC_CTRL_REG); reg |= CTRLREG_PLL_CTRL_SLEEP | CTRLREG_PLL_CTRL_SUSP; writel_relaxed(reg, MSM_HSIC_CTRL_REG); if (of_property_read_bool(node, "qti,disable-hw-clk-gating")) { reg = readl_relaxed(MSM_HSIC_GCTL); writel_relaxed((reg | GCTL_DSBLCLKGTNG), MSM_HSIC_GCTL); } /* enable pwr event irq for LPM_IN_L2_IRQ */ writel_relaxed(LPM_IN_L2_IRQ_MASK, MSM_HSIC_PWR_EVNT_IRQ_MASK); mxhci->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq"); if (mxhci->wakeup_irq < 0) { mxhci->wakeup_irq = 0; dev_err(&pdev->dev, "failed to init wakeup_irq\n"); } else { /* enable wakeup irq only when entering lpm */ irq_set_status_flags(mxhci->wakeup_irq, IRQ_NOAUTOEN); ret = devm_request_irq(&pdev->dev, mxhci->wakeup_irq, mxhci_hsic_wakeup_irq, 0, "mxhci_hsic_wakeup", mxhci); if (ret) { dev_err(&pdev->dev, "request irq failed (wakeup irq)\n"); goto deinit_vddcx; } } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto deinit_vddcx; hcd = dev_get_drvdata(&pdev->dev); xhci = hcd_to_xhci(hcd); /* USB 3.0 roothub */ /* no need for another instance of mxhci */ driver->hcd_priv_size = sizeof(struct xhci_hcd *); xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto remove_usb2_hcd; } hcd_to_bus(xhci->shared_hcd)->skip_resume = true; /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; spin_lock_init(&mxhci->wakeup_lock); mxhci->pwr_event_irq = platform_get_irq_byname(pdev, "pwr_event_irq"); if (mxhci->pwr_event_irq < 0) { dev_err(&pdev->dev, "platform_get_irq for pwr_event_irq failed\n"); goto remove_usb3_hcd; } ret = devm_request_irq(&pdev->dev, mxhci->pwr_event_irq, mxhci_hsic_pwr_event_irq, 0, "mxhci_hsic_pwr_evt", mxhci); if (ret) { dev_err(&pdev->dev, "request irq failed (pwr event irq)\n"); goto remove_usb3_hcd; } init_completion(&mxhci->phy_in_lpm); mxhci->wq = create_singlethread_workqueue("mxhci_wq"); if (!mxhci->wq) { dev_err(&pdev->dev, "unable to create workqueue\n"); ret = -ENOMEM; goto remove_usb3_hcd; } INIT_WORK(&mxhci->bus_vote_w, mxhci_hsic_bus_vote_w); mxhci->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (!mxhci->bus_scale_table) { dev_dbg(&pdev->dev, "bus scaling is disabled\n"); } else { mxhci->bus_perf_client = msm_bus_scale_register_client(mxhci->bus_scale_table); /* Configure BUS performance parameters for MAX bandwidth */ if (mxhci->bus_perf_client) { mxhci->bus_vote = true; queue_work(mxhci->wq, &mxhci->bus_vote_w); } else { dev_err(&pdev->dev, "%s: bus scaling client reg err\n", __func__); ret = -ENODEV; goto delete_wq; } } ret = device_create_file(&pdev->dev, &dev_attr_config_imod); if (ret) dev_dbg(&pdev->dev, "%s: unable to create imod sysfs entry\n", __func__); /* Enable HSIC PHY */ mxhci_hsic_ulpi_write(mxhci, 0x01, MSM_HSIC_CFG_SET); device_init_wakeup(&pdev->dev, 1); wakeup_source_init(&mxhci->ws, dev_name(&pdev->dev)); pm_stay_awake(mxhci->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; delete_wq: destroy_workqueue(mxhci->wq); remove_usb3_hcd: usb_remove_hcd(xhci->shared_hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); remove_usb2_hcd: usb_remove_hcd(hcd); deinit_vddcx: mxhci_hsic_init_vddcx(mxhci, 0); deinit_clocks: mxhci_hsic_init_clocks(mxhci, 0); put_hcd: usb_put_hcd(hcd); return ret; }