]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/usb/phy/phy-msm-usb.c
usb: phy: msm: use devm_ioremap_resource()
[karo-tx-linux.git] / drivers / usb / phy / phy-msm-usb.c
index 80eb991c2506c758315cc2e6e1f39b6ebbf319f4..301ffb1fa0e439e9c7fd55114099deb721d3093d 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/regulator/consumer.h>
+#include <linux/msm-bus.h>
 
 #define MSM_USB_BASE   (motg->regs)
 #define DRIVER_NAME    "msm_otg"
@@ -76,6 +77,9 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
 {
        int ret = 0;
 
+       if (IS_ERR(motg->vddcx))
+               return 0;
+
        if (init) {
                ret = regulator_set_voltage(motg->vddcx,
                                motg->vdd_levels[VDD_LEVEL_MIN],
@@ -761,7 +765,8 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
         * Kick the state machine work, if peripheral is not supported
         * or peripheral is already registered with us.
         */
-       if (motg->pdata->mode == USB_DR_MODE_HOST || otg->gadget) {
+       if (motg->pdata->mode == USB_DR_MODE_HOST ||
+                       motg->pdata->mode == USB_DR_MODE_OTG || otg->gadget) {
                pm_runtime_get_sync(otg->usb_phy->dev);
                schedule_work(&motg->sm_work);
        }
@@ -831,7 +836,8 @@ static int msm_otg_set_peripheral(struct usb_otg *otg,
         * Kick the state machine work, if host is not supported
         * or host is already registered with us.
         */
-       if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL || otg->host) {
+       if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL ||
+               motg->pdata->mode == USB_DR_MODE_OTG || otg->host) {
                pm_runtime_get_sync(otg->usb_phy->dev);
                schedule_work(&motg->sm_work);
        }
@@ -1506,7 +1512,6 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 {
        struct msm_otg_platform_data *pdata;
        struct extcon_dev *ext_id, *ext_vbus;
-       const struct of_device_id *id;
        struct device_node *node = pdev->dev.of_node;
        struct property *prop;
        int len, ret, words;
@@ -1518,8 +1523,9 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 
        motg->pdata = pdata;
 
-       id = of_match_device(msm_otg_dt_match, &pdev->dev);
-       pdata->phy_type = (enum msm_usb_phy_type) id->data;
+       pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev);
+       if (!pdata->phy_type)
+               return 1;
 
        motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
        if (IS_ERR(motg->link_rst))
@@ -1599,6 +1605,8 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
                                                &motg->id.nb);
                if (ret < 0) {
                        dev_err(&pdev->dev, "register ID notifier failed\n");
+                       extcon_unregister_notifier(motg->vbus.extcon,
+                                                  EXTCON_USB, &motg->vbus.nb);
                        return ret;
                }
 
@@ -1645,9 +1653,22 @@ static int msm_otg_reboot_notify(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
+static void msm_otg_bus_vote(struct msm_otg *motg, enum usb_bus_vote vote)
+{
+       int ret;
+
+       if (motg->bus_perf_client) {
+               ret = msm_bus_scale_client_update_request(
+                               motg->bus_perf_client, vote);
+               if (ret)
+                       dev_err(motg->phy.dev, "%s: Failed to vote (%d)\n"
+                                       "for bus bw %d\n", __func__, vote, ret);
+       }
+}
+
 static int msm_otg_probe(struct platform_device *pdev)
 {
-       struct regulator_bulk_data regs[3];
+       struct regulator_bulk_data regs[2];
        int ret = 0;
        struct device_node *np = pdev->dev.of_node;
        struct msm_otg_platform_data *pdata;
@@ -1660,15 +1681,6 @@ static int msm_otg_probe(struct platform_device *pdev)
        if (!motg)
                return -ENOMEM;
 
-       pdata = dev_get_platdata(&pdev->dev);
-       if (!pdata) {
-               if (!np)
-                       return -ENXIO;
-               ret = msm_otg_read_dt(pdev, motg);
-               if (ret)
-                       return ret;
-       }
-
        motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
                                     GFP_KERNEL);
        if (!motg->phy.otg)
@@ -1676,6 +1688,8 @@ static int msm_otg_probe(struct platform_device *pdev)
 
        phy = &motg->phy;
        phy->dev = &pdev->dev;
+       INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+       INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
 
        motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
        if (IS_ERR(motg->clk)) {
@@ -1704,11 +1718,18 @@ static int msm_otg_probe(struct platform_device *pdev)
                                      np ? "alt_core" : "usb_hs_core_clk");
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EINVAL;
-       motg->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-       if (!motg->regs)
-               return -ENOMEM;
+       motg->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(motg->regs))
+               return PTR_ERR(motg->regs);
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               if (!np)
+                       return -ENXIO;
+               ret = msm_otg_read_dt(pdev, motg);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * NOTE: The PHYs can be multiplexed between the chipidea controller
@@ -1717,8 +1738,10 @@ static int msm_otg_probe(struct platform_device *pdev)
         */
        if (motg->phy_number) {
                phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
-               if (!phy_select)
-                       return -ENOMEM;
+               if (!phy_select) {
+                       ret = -ENOMEM;
+                       goto unregister_extcon;
+               }
                /* Enable second PHY with the OTG port */
                writel(0x1, phy_select);
        }
@@ -1728,20 +1751,25 @@ static int msm_otg_probe(struct platform_device *pdev)
        motg->irq = platform_get_irq(pdev, 0);
        if (motg->irq < 0) {
                dev_err(&pdev->dev, "platform_get_irq failed\n");
-               return motg->irq;
+               ret = motg->irq;
+               goto unregister_extcon;
        }
 
-       regs[0].supply = "vddcx";
-       regs[1].supply = "v3p3";
-       regs[2].supply = "v1p8";
+       regs[0].supply = "v3p3";
+       regs[1].supply = "v1p8";
 
        ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
-       if (ret)
-               return ret;
+       if (ret) {
+               dev_err(&pdev->dev, "no v3p3 or v1p8\n");
+               goto unregister_extcon;
+       }
+
+       motg->v3p3  = regs[0].consumer;
+       motg->v1p8  = regs[1].consumer;
 
-       motg->vddcx = regs[0].consumer;
-       motg->v3p3  = regs[1].consumer;
-       motg->v1p8  = regs[2].consumer;
+       motg->vddcx = devm_regulator_get_optional(motg->phy.dev, "vddcx");
+       if (IS_ERR(motg->vddcx))
+               dev_info(&pdev->dev, "no vddcx\n");
 
        clk_set_rate(motg->clk, 60000000);
 
@@ -1771,8 +1799,6 @@ static int msm_otg_probe(struct platform_device *pdev)
        writel(0, USB_USBINTR);
        writel(0, USB_OTGSC);
 
-       INIT_WORK(&motg->sm_work, msm_otg_sm_work);
-       INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
        ret = devm_request_irq(&pdev->dev, motg->irq, msm_otg_irq, IRQF_SHARED,
                                        "msm_otg", motg);
        if (ret) {
@@ -1799,6 +1825,19 @@ static int msm_otg_probe(struct platform_device *pdev)
                goto disable_ldo;
        }
 
+       motg->pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+       if (!motg->pdata->bus_scale_table)
+               dev_dbg(&pdev->dev, "bus scaling is disabled\n");
+       else {
+               motg->bus_perf_client =
+                       msm_bus_scale_register_client(motg->pdata->bus_scale_table);
+               if (!motg->bus_perf_client)
+                       dev_err(motg->phy.dev, "%s: Failed to register BUS\n"
+                                       "scaling client!!\n", __func__);
+       }
+       /* Hack to max out usb performace */
+       msm_otg_bus_vote(motg, USB_MAX_PERF_VOTE);
+
        platform_set_drvdata(pdev, motg);
        device_init_wakeup(&pdev->dev, 1);
 
@@ -1821,7 +1860,6 @@ static int msm_otg_probe(struct platform_device *pdev)
        register_reboot_notifier(&motg->reboot);
 
        pm_runtime_set_active(&pdev->dev);
-       pm_runtime_enable(&pdev->dev);
 
        return 0;
 
@@ -1834,6 +1872,12 @@ disable_clks:
        clk_disable_unprepare(motg->clk);
        if (!IS_ERR(motg->core_clk))
                clk_disable_unprepare(motg->core_clk);
+unregister_extcon:
+       extcon_unregister_notifier(motg->id.extcon,
+                                  EXTCON_USB_HOST, &motg->id.nb);
+       extcon_unregister_notifier(motg->vbus.extcon,
+                                  EXTCON_USB, &motg->vbus.nb);
+
        return ret;
 }
 
@@ -1868,6 +1912,7 @@ static int msm_otg_remove(struct platform_device *pdev)
 
        usb_remove_phy(phy);
        disable_irq(motg->irq);
+       msm_bus_scale_unregister_client(motg->bus_perf_client);
 
        /*
         * Put PHY in low power mode.