root/drivers/usb/host/xhci-histb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hcd_to_histb
  2. xhci_histb_config
  3. xhci_histb_clks_get
  4. xhci_histb_host_enable
  5. xhci_histb_host_disable
  6. xhci_histb_quirks
  7. xhci_histb_setup
  8. xhci_histb_probe
  9. xhci_histb_remove
  10. xhci_histb_suspend
  11. xhci_histb_resume
  12. xhci_histb_init
  13. xhci_histb_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * xHCI host controller driver for HiSilicon STB SoCs
   4  *
   5  * Copyright (C) 2017-2018 HiSilicon Co., Ltd. http://www.hisilicon.com
   6  *
   7  * Authors: Jianguo Sun <sunjianguo1@huawei.com>
   8  */
   9 
  10 #include <linux/clk.h>
  11 #include <linux/dma-mapping.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/pm_runtime.h>
  17 #include <linux/reset.h>
  18 
  19 #include "xhci.h"
  20 
  21 #define GTXTHRCFG               0xc108
  22 #define GRXTHRCFG               0xc10c
  23 #define REG_GUSB2PHYCFG0        0xc200
  24 #define BIT_UTMI_8_16           BIT(3)
  25 #define BIT_UTMI_ULPI           BIT(4)
  26 #define BIT_FREECLK_EXIST       BIT(30)
  27 
  28 #define REG_GUSB3PIPECTL0       0xc2c0
  29 #define USB3_DEEMPHASIS_MASK    GENMASK(2, 1)
  30 #define USB3_DEEMPHASIS0        BIT(1)
  31 #define USB3_TX_MARGIN1         BIT(4)
  32 
  33 struct xhci_hcd_histb {
  34         struct device           *dev;
  35         struct usb_hcd          *hcd;
  36         void __iomem            *ctrl;
  37         struct clk              *bus_clk;
  38         struct clk              *utmi_clk;
  39         struct clk              *pipe_clk;
  40         struct clk              *suspend_clk;
  41         struct reset_control    *soft_reset;
  42 };
  43 
  44 static inline struct xhci_hcd_histb *hcd_to_histb(struct usb_hcd *hcd)
  45 {
  46         return dev_get_drvdata(hcd->self.controller);
  47 }
  48 
  49 static int xhci_histb_config(struct xhci_hcd_histb *histb)
  50 {
  51         struct device_node *np = histb->dev->of_node;
  52         u32 regval;
  53 
  54         if (of_property_match_string(np, "phys-names", "inno") >= 0) {
  55                 /* USB2 PHY chose ulpi 8bit interface */
  56                 regval = readl(histb->ctrl + REG_GUSB2PHYCFG0);
  57                 regval &= ~BIT_UTMI_ULPI;
  58                 regval &= ~(BIT_UTMI_8_16);
  59                 regval &= ~BIT_FREECLK_EXIST;
  60                 writel(regval, histb->ctrl + REG_GUSB2PHYCFG0);
  61         }
  62 
  63         if (of_property_match_string(np, "phys-names", "combo") >= 0) {
  64                 /*
  65                  * write 0x010c0012 to GUSB3PIPECTL0
  66                  * GUSB3PIPECTL0[5:3] = 010 : Tx Margin = 900mV ,
  67                  * decrease TX voltage
  68                  * GUSB3PIPECTL0[2:1] = 01 : Tx Deemphasis = -3.5dB,
  69                  * refer to xHCI spec
  70                  */
  71                 regval = readl(histb->ctrl + REG_GUSB3PIPECTL0);
  72                 regval &= ~USB3_DEEMPHASIS_MASK;
  73                 regval |= USB3_DEEMPHASIS0;
  74                 regval |= USB3_TX_MARGIN1;
  75                 writel(regval, histb->ctrl + REG_GUSB3PIPECTL0);
  76         }
  77 
  78         writel(0x23100000, histb->ctrl + GTXTHRCFG);
  79         writel(0x23100000, histb->ctrl + GRXTHRCFG);
  80 
  81         return 0;
  82 }
  83 
  84 static int xhci_histb_clks_get(struct xhci_hcd_histb *histb)
  85 {
  86         struct device *dev = histb->dev;
  87 
  88         histb->bus_clk = devm_clk_get(dev, "bus");
  89         if (IS_ERR(histb->bus_clk)) {
  90                 dev_err(dev, "fail to get bus clk\n");
  91                 return PTR_ERR(histb->bus_clk);
  92         }
  93 
  94         histb->utmi_clk = devm_clk_get(dev, "utmi");
  95         if (IS_ERR(histb->utmi_clk)) {
  96                 dev_err(dev, "fail to get utmi clk\n");
  97                 return PTR_ERR(histb->utmi_clk);
  98         }
  99 
 100         histb->pipe_clk = devm_clk_get(dev, "pipe");
 101         if (IS_ERR(histb->pipe_clk)) {
 102                 dev_err(dev, "fail to get pipe clk\n");
 103                 return PTR_ERR(histb->pipe_clk);
 104         }
 105 
 106         histb->suspend_clk = devm_clk_get(dev, "suspend");
 107         if (IS_ERR(histb->suspend_clk)) {
 108                 dev_err(dev, "fail to get suspend clk\n");
 109                 return PTR_ERR(histb->suspend_clk);
 110         }
 111 
 112         return 0;
 113 }
 114 
 115 static int xhci_histb_host_enable(struct xhci_hcd_histb *histb)
 116 {
 117         int ret;
 118 
 119         ret = clk_prepare_enable(histb->bus_clk);
 120         if (ret) {
 121                 dev_err(histb->dev, "failed to enable bus clk\n");
 122                 return ret;
 123         }
 124 
 125         ret = clk_prepare_enable(histb->utmi_clk);
 126         if (ret) {
 127                 dev_err(histb->dev, "failed to enable utmi clk\n");
 128                 goto err_utmi_clk;
 129         }
 130 
 131         ret = clk_prepare_enable(histb->pipe_clk);
 132         if (ret) {
 133                 dev_err(histb->dev, "failed to enable pipe clk\n");
 134                 goto err_pipe_clk;
 135         }
 136 
 137         ret = clk_prepare_enable(histb->suspend_clk);
 138         if (ret) {
 139                 dev_err(histb->dev, "failed to enable suspend clk\n");
 140                 goto err_suspend_clk;
 141         }
 142 
 143         reset_control_deassert(histb->soft_reset);
 144 
 145         return 0;
 146 
 147 err_suspend_clk:
 148         clk_disable_unprepare(histb->pipe_clk);
 149 err_pipe_clk:
 150         clk_disable_unprepare(histb->utmi_clk);
 151 err_utmi_clk:
 152         clk_disable_unprepare(histb->bus_clk);
 153 
 154         return ret;
 155 }
 156 
 157 static void xhci_histb_host_disable(struct xhci_hcd_histb *histb)
 158 {
 159         reset_control_assert(histb->soft_reset);
 160 
 161         clk_disable_unprepare(histb->suspend_clk);
 162         clk_disable_unprepare(histb->pipe_clk);
 163         clk_disable_unprepare(histb->utmi_clk);
 164         clk_disable_unprepare(histb->bus_clk);
 165 }
 166 
 167 static void xhci_histb_quirks(struct device *dev, struct xhci_hcd *xhci)
 168 {
 169         /*
 170          * As of now platform drivers don't provide MSI support so we ensure
 171          * here that the generic code does not try to make a pci_dev from our
 172          * dev struct in order to setup MSI
 173          */
 174         xhci->quirks |= XHCI_PLAT;
 175 }
 176 
 177 /* called during probe() after chip reset completes */
 178 static int xhci_histb_setup(struct usb_hcd *hcd)
 179 {
 180         struct xhci_hcd_histb *histb = hcd_to_histb(hcd);
 181         int ret;
 182 
 183         if (usb_hcd_is_primary_hcd(hcd)) {
 184                 ret = xhci_histb_config(histb);
 185                 if (ret)
 186                         return ret;
 187         }
 188 
 189         return xhci_gen_setup(hcd, xhci_histb_quirks);
 190 }
 191 
 192 static const struct xhci_driver_overrides xhci_histb_overrides __initconst = {
 193         .reset = xhci_histb_setup,
 194 };
 195 
 196 static struct hc_driver __read_mostly xhci_histb_hc_driver;
 197 static int xhci_histb_probe(struct platform_device *pdev)
 198 {
 199         struct device *dev = &pdev->dev;
 200         struct xhci_hcd_histb *histb;
 201         const struct hc_driver *driver;
 202         struct usb_hcd *hcd;
 203         struct xhci_hcd *xhci;
 204         struct resource *res;
 205         int irq;
 206         int ret = -ENODEV;
 207 
 208         if (usb_disabled())
 209                 return -ENODEV;
 210 
 211         driver = &xhci_histb_hc_driver;
 212         histb = devm_kzalloc(dev, sizeof(*histb), GFP_KERNEL);
 213         if (!histb)
 214                 return -ENOMEM;
 215 
 216         histb->dev = dev;
 217 
 218         irq = platform_get_irq(pdev, 0);
 219         if (irq < 0)
 220                 return irq;
 221 
 222         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 223         histb->ctrl = devm_ioremap_resource(&pdev->dev, res);
 224         if (IS_ERR(histb->ctrl))
 225                 return PTR_ERR(histb->ctrl);
 226 
 227         ret = xhci_histb_clks_get(histb);
 228         if (ret)
 229                 return ret;
 230 
 231         histb->soft_reset = devm_reset_control_get(dev, "soft");
 232         if (IS_ERR(histb->soft_reset)) {
 233                 dev_err(dev, "failed to get soft reset\n");
 234                 return PTR_ERR(histb->soft_reset);
 235         }
 236 
 237         pm_runtime_enable(dev);
 238         pm_runtime_get_sync(dev);
 239         device_enable_async_suspend(dev);
 240 
 241         /* Initialize dma_mask and coherent_dma_mask to 32-bits */
 242         ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
 243         if (ret)
 244                 return ret;
 245 
 246         hcd = usb_create_hcd(driver, dev, dev_name(dev));
 247         if (!hcd) {
 248                 ret = -ENOMEM;
 249                 goto disable_pm;
 250         }
 251 
 252         hcd->regs = histb->ctrl;
 253         hcd->rsrc_start = res->start;
 254         hcd->rsrc_len = resource_size(res);
 255 
 256         histb->hcd = hcd;
 257         dev_set_drvdata(hcd->self.controller, histb);
 258 
 259         ret = xhci_histb_host_enable(histb);
 260         if (ret)
 261                 goto put_hcd;
 262 
 263         xhci = hcd_to_xhci(hcd);
 264 
 265         device_wakeup_enable(hcd->self.controller);
 266 
 267         xhci->main_hcd = hcd;
 268         xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev),
 269                                                  hcd);
 270         if (!xhci->shared_hcd) {
 271                 ret = -ENOMEM;
 272                 goto disable_host;
 273         }
 274 
 275         if (device_property_read_bool(dev, "usb2-lpm-disable"))
 276                 xhci->quirks |= XHCI_HW_LPM_DISABLE;
 277 
 278         if (device_property_read_bool(dev, "usb3-lpm-capable"))
 279                 xhci->quirks |= XHCI_LPM_SUPPORT;
 280 
 281         /* imod_interval is the interrupt moderation value in nanoseconds. */
 282         xhci->imod_interval = 40000;
 283         device_property_read_u32(dev, "imod-interval-ns",
 284                                  &xhci->imod_interval);
 285 
 286         ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 287         if (ret)
 288                 goto put_usb3_hcd;
 289 
 290         if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
 291                 xhci->shared_hcd->can_do_streams = 1;
 292 
 293         ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
 294         if (ret)
 295                 goto dealloc_usb2_hcd;
 296 
 297         device_enable_async_suspend(dev);
 298         pm_runtime_put_noidle(dev);
 299 
 300         /*
 301          * Prevent runtime pm from being on as default, users should enable
 302          * runtime pm using power/control in sysfs.
 303          */
 304         pm_runtime_forbid(dev);
 305 
 306         return 0;
 307 
 308 dealloc_usb2_hcd:
 309         usb_remove_hcd(hcd);
 310 put_usb3_hcd:
 311         usb_put_hcd(xhci->shared_hcd);
 312 disable_host:
 313         xhci_histb_host_disable(histb);
 314 put_hcd:
 315         usb_put_hcd(hcd);
 316 disable_pm:
 317         pm_runtime_put_sync(dev);
 318         pm_runtime_disable(dev);
 319 
 320         return ret;
 321 }
 322 
 323 static int xhci_histb_remove(struct platform_device *dev)
 324 {
 325         struct xhci_hcd_histb *histb = platform_get_drvdata(dev);
 326         struct usb_hcd *hcd = histb->hcd;
 327         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 328         struct usb_hcd *shared_hcd = xhci->shared_hcd;
 329 
 330         xhci->xhc_state |= XHCI_STATE_REMOVING;
 331 
 332         usb_remove_hcd(shared_hcd);
 333         xhci->shared_hcd = NULL;
 334         device_wakeup_disable(&dev->dev);
 335 
 336         usb_remove_hcd(hcd);
 337         usb_put_hcd(shared_hcd);
 338 
 339         xhci_histb_host_disable(histb);
 340         usb_put_hcd(hcd);
 341         pm_runtime_put_sync(&dev->dev);
 342         pm_runtime_disable(&dev->dev);
 343 
 344         return 0;
 345 }
 346 
 347 static int __maybe_unused xhci_histb_suspend(struct device *dev)
 348 {
 349         struct xhci_hcd_histb *histb = dev_get_drvdata(dev);
 350         struct usb_hcd *hcd = histb->hcd;
 351         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 352         int ret;
 353 
 354         ret = xhci_suspend(xhci, device_may_wakeup(dev));
 355 
 356         if (!device_may_wakeup(dev))
 357                 xhci_histb_host_disable(histb);
 358 
 359         return ret;
 360 }
 361 
 362 static int __maybe_unused xhci_histb_resume(struct device *dev)
 363 {
 364         struct xhci_hcd_histb *histb = dev_get_drvdata(dev);
 365         struct usb_hcd *hcd = histb->hcd;
 366         struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 367 
 368         if (!device_may_wakeup(dev))
 369                 xhci_histb_host_enable(histb);
 370 
 371         return xhci_resume(xhci, 0);
 372 }
 373 
 374 static const struct dev_pm_ops xhci_histb_pm_ops = {
 375         SET_SYSTEM_SLEEP_PM_OPS(xhci_histb_suspend, xhci_histb_resume)
 376 };
 377 #define DEV_PM_OPS (IS_ENABLED(CONFIG_PM) ? &xhci_histb_pm_ops : NULL)
 378 
 379 #ifdef CONFIG_OF
 380 static const struct of_device_id histb_xhci_of_match[] = {
 381         { .compatible = "hisilicon,hi3798cv200-xhci"},
 382         { },
 383 };
 384 MODULE_DEVICE_TABLE(of, histb_xhci_of_match);
 385 #endif
 386 
 387 static struct platform_driver histb_xhci_driver = {
 388         .probe  = xhci_histb_probe,
 389         .remove = xhci_histb_remove,
 390         .driver = {
 391                 .name = "xhci-histb",
 392                 .pm = DEV_PM_OPS,
 393                 .of_match_table = of_match_ptr(histb_xhci_of_match),
 394         },
 395 };
 396 MODULE_ALIAS("platform:xhci-histb");
 397 
 398 static int __init xhci_histb_init(void)
 399 {
 400         xhci_init_driver(&xhci_histb_hc_driver, &xhci_histb_overrides);
 401         return platform_driver_register(&histb_xhci_driver);
 402 }
 403 module_init(xhci_histb_init);
 404 
 405 static void __exit xhci_histb_exit(void)
 406 {
 407         platform_driver_unregister(&histb_xhci_driver);
 408 }
 409 module_exit(xhci_histb_exit);
 410 
 411 MODULE_DESCRIPTION("HiSilicon STB xHCI Host Controller Driver");
 412 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */