Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. */
0003 
0004 #include <linux/module.h>
0005 #include <linux/platform_device.h>
0006 #include <linux/pm_runtime.h>
0007 #include <linux/usb/chipidea.h>
0008 #include <linux/clk.h>
0009 #include <linux/reset.h>
0010 #include <linux/mfd/syscon.h>
0011 #include <linux/regmap.h>
0012 #include <linux/io.h>
0013 #include <linux/reset-controller.h>
0014 #include <linux/extcon.h>
0015 #include <linux/of.h>
0016 
0017 #include "ci.h"
0018 
0019 #define HS_PHY_AHB_MODE         0x0098
0020 
0021 #define HS_PHY_GENCONFIG        0x009c
0022 #define HS_PHY_TXFIFO_IDLE_FORCE_DIS    BIT(4)
0023 
0024 #define HS_PHY_GENCONFIG_2      0x00a0
0025 #define HS_PHY_SESS_VLD_CTRL_EN     BIT(7)
0026 #define HS_PHY_ULPI_TX_PKT_EN_CLR_FIX   BIT(19)
0027 
0028 #define HSPHY_SESS_VLD_CTRL     BIT(25)
0029 
0030 /* Vendor base starts at 0x200 beyond CI base */
0031 #define HS_PHY_CTRL         0x0040
0032 #define HS_PHY_SEC_CTRL         0x0078
0033 #define HS_PHY_DIG_CLAMP_N      BIT(16)
0034 #define HS_PHY_POR_ASSERT       BIT(0)
0035 
0036 struct ci_hdrc_msm {
0037     struct platform_device *ci;
0038     struct clk *core_clk;
0039     struct clk *iface_clk;
0040     struct clk *fs_clk;
0041     struct ci_hdrc_platform_data pdata;
0042     struct reset_controller_dev rcdev;
0043     bool secondary_phy;
0044     bool hsic;
0045     void __iomem *base;
0046 };
0047 
0048 static int
0049 ci_hdrc_msm_por_reset(struct reset_controller_dev *r, unsigned long id)
0050 {
0051     struct ci_hdrc_msm *ci_msm = container_of(r, struct ci_hdrc_msm, rcdev);
0052     void __iomem *addr = ci_msm->base;
0053     u32 val;
0054 
0055     if (id)
0056         addr += HS_PHY_SEC_CTRL;
0057     else
0058         addr += HS_PHY_CTRL;
0059 
0060     val = readl_relaxed(addr);
0061     val |= HS_PHY_POR_ASSERT;
0062     writel(val, addr);
0063     /*
0064      * wait for minimum 10 microseconds as suggested by manual.
0065      * Use a slightly larger value since the exact value didn't
0066      * work 100% of the time.
0067      */
0068     udelay(12);
0069     val &= ~HS_PHY_POR_ASSERT;
0070     writel(val, addr);
0071 
0072     return 0;
0073 }
0074 
0075 static const struct reset_control_ops ci_hdrc_msm_reset_ops = {
0076     .reset = ci_hdrc_msm_por_reset,
0077 };
0078 
0079 static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
0080 {
0081     struct device *dev = ci->dev->parent;
0082     struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev);
0083     int ret;
0084 
0085     switch (event) {
0086     case CI_HDRC_CONTROLLER_RESET_EVENT:
0087         dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
0088 
0089         hw_phymode_configure(ci);
0090         if (msm_ci->secondary_phy) {
0091             u32 val = readl_relaxed(msm_ci->base + HS_PHY_SEC_CTRL);
0092             val |= HS_PHY_DIG_CLAMP_N;
0093             writel_relaxed(val, msm_ci->base + HS_PHY_SEC_CTRL);
0094         }
0095 
0096         ret = phy_init(ci->phy);
0097         if (ret)
0098             return ret;
0099 
0100         ret = phy_power_on(ci->phy);
0101         if (ret) {
0102             phy_exit(ci->phy);
0103             return ret;
0104         }
0105 
0106         /* use AHB transactor, allow posted data writes */
0107         hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
0108 
0109         /* workaround for rx buffer collision issue */
0110         hw_write_id_reg(ci, HS_PHY_GENCONFIG,
0111                 HS_PHY_TXFIFO_IDLE_FORCE_DIS, 0);
0112 
0113         if (!msm_ci->hsic)
0114             hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
0115                     HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
0116 
0117         if (!IS_ERR(ci->platdata->vbus_extcon.edev) || ci->role_switch) {
0118             hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
0119                     HS_PHY_SESS_VLD_CTRL_EN,
0120                     HS_PHY_SESS_VLD_CTRL_EN);
0121             hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL,
0122                  HSPHY_SESS_VLD_CTRL);
0123 
0124         }
0125         break;
0126     case CI_HDRC_CONTROLLER_STOPPED_EVENT:
0127         dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
0128         phy_power_off(ci->phy);
0129         phy_exit(ci->phy);
0130         break;
0131     default:
0132         dev_dbg(dev, "unknown ci_hdrc event\n");
0133         break;
0134     }
0135 
0136     return 0;
0137 }
0138 
0139 static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
0140                    struct platform_device *pdev)
0141 {
0142     struct regmap *regmap;
0143     struct device *dev = &pdev->dev;
0144     struct of_phandle_args args;
0145     u32 val;
0146     int ret;
0147 
0148     ret = of_parse_phandle_with_fixed_args(dev->of_node, "phy-select", 2, 0,
0149                            &args);
0150     if (ret)
0151         return 0;
0152 
0153     regmap = syscon_node_to_regmap(args.np);
0154     of_node_put(args.np);
0155     if (IS_ERR(regmap))
0156         return PTR_ERR(regmap);
0157 
0158     ret = regmap_write(regmap, args.args[0], args.args[1]);
0159     if (ret)
0160         return ret;
0161 
0162     ci->secondary_phy = !!args.args[1];
0163     if (ci->secondary_phy) {
0164         val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
0165         val |= HS_PHY_DIG_CLAMP_N;
0166         writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
0167     }
0168 
0169     return 0;
0170 }
0171 
0172 static int ci_hdrc_msm_probe(struct platform_device *pdev)
0173 {
0174     struct ci_hdrc_msm *ci;
0175     struct platform_device *plat_ci;
0176     struct clk *clk;
0177     struct reset_control *reset;
0178     int ret;
0179     struct device_node *ulpi_node, *phy_node;
0180 
0181     dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
0182 
0183     ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
0184     if (!ci)
0185         return -ENOMEM;
0186     platform_set_drvdata(pdev, ci);
0187 
0188     ci->pdata.name = "ci_hdrc_msm";
0189     ci->pdata.capoffset = DEF_CAPOFFSET;
0190     ci->pdata.flags = CI_HDRC_REGS_SHARED | CI_HDRC_DISABLE_STREAMING |
0191               CI_HDRC_OVERRIDE_AHB_BURST |
0192               CI_HDRC_OVERRIDE_PHY_CONTROL;
0193     ci->pdata.notify_event = ci_hdrc_msm_notify_event;
0194 
0195     reset = devm_reset_control_get(&pdev->dev, "core");
0196     if (IS_ERR(reset))
0197         return PTR_ERR(reset);
0198 
0199     ci->core_clk = clk = devm_clk_get(&pdev->dev, "core");
0200     if (IS_ERR(clk))
0201         return PTR_ERR(clk);
0202 
0203     ci->iface_clk = clk = devm_clk_get(&pdev->dev, "iface");
0204     if (IS_ERR(clk))
0205         return PTR_ERR(clk);
0206 
0207     ci->fs_clk = clk = devm_clk_get_optional(&pdev->dev, "fs");
0208     if (IS_ERR(clk))
0209         return PTR_ERR(clk);
0210 
0211     ci->base = devm_platform_ioremap_resource(pdev, 1);
0212     if (IS_ERR(ci->base))
0213         return PTR_ERR(ci->base);
0214 
0215     ci->rcdev.owner = THIS_MODULE;
0216     ci->rcdev.ops = &ci_hdrc_msm_reset_ops;
0217     ci->rcdev.of_node = pdev->dev.of_node;
0218     ci->rcdev.nr_resets = 2;
0219     ret = devm_reset_controller_register(&pdev->dev, &ci->rcdev);
0220     if (ret)
0221         return ret;
0222 
0223     ret = clk_prepare_enable(ci->fs_clk);
0224     if (ret)
0225         return ret;
0226 
0227     reset_control_assert(reset);
0228     usleep_range(10000, 12000);
0229     reset_control_deassert(reset);
0230 
0231     clk_disable_unprepare(ci->fs_clk);
0232 
0233     ret = clk_prepare_enable(ci->core_clk);
0234     if (ret)
0235         return ret;
0236 
0237     ret = clk_prepare_enable(ci->iface_clk);
0238     if (ret)
0239         goto err_iface;
0240 
0241     ret = ci_hdrc_msm_mux_phy(ci, pdev);
0242     if (ret)
0243         goto err_mux;
0244 
0245     ulpi_node = of_get_child_by_name(pdev->dev.of_node, "ulpi");
0246     if (ulpi_node) {
0247         phy_node = of_get_next_available_child(ulpi_node, NULL);
0248         ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
0249         of_node_put(phy_node);
0250     }
0251     of_node_put(ulpi_node);
0252 
0253     plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
0254                      pdev->num_resources, &ci->pdata);
0255     if (IS_ERR(plat_ci)) {
0256         ret = PTR_ERR(plat_ci);
0257         if (ret != -EPROBE_DEFER)
0258             dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
0259         goto err_mux;
0260     }
0261 
0262     ci->ci = plat_ci;
0263 
0264     pm_runtime_set_active(&pdev->dev);
0265     pm_runtime_no_callbacks(&pdev->dev);
0266     pm_runtime_enable(&pdev->dev);
0267 
0268     return 0;
0269 
0270 err_mux:
0271     clk_disable_unprepare(ci->iface_clk);
0272 err_iface:
0273     clk_disable_unprepare(ci->core_clk);
0274     return ret;
0275 }
0276 
0277 static int ci_hdrc_msm_remove(struct platform_device *pdev)
0278 {
0279     struct ci_hdrc_msm *ci = platform_get_drvdata(pdev);
0280 
0281     pm_runtime_disable(&pdev->dev);
0282     ci_hdrc_remove_device(ci->ci);
0283     clk_disable_unprepare(ci->iface_clk);
0284     clk_disable_unprepare(ci->core_clk);
0285 
0286     return 0;
0287 }
0288 
0289 static const struct of_device_id msm_ci_dt_match[] = {
0290     { .compatible = "qcom,ci-hdrc", },
0291     { }
0292 };
0293 MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
0294 
0295 static struct platform_driver ci_hdrc_msm_driver = {
0296     .probe = ci_hdrc_msm_probe,
0297     .remove = ci_hdrc_msm_remove,
0298     .driver = {
0299         .name = "msm_hsusb",
0300         .of_match_table = msm_ci_dt_match,
0301     },
0302 };
0303 
0304 module_platform_driver(ci_hdrc_msm_driver);
0305 
0306 MODULE_ALIAS("platform:msm_hsusb");
0307 MODULE_ALIAS("platform:ci13xxx_msm");
0308 MODULE_LICENSE("GPL v2");