root/drivers/usb/dwc3/ulpi.c

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

DEFINITIONS

This source file includes following definitions.
  1. dwc3_ulpi_busyloop
  2. dwc3_ulpi_read
  3. dwc3_ulpi_write
  4. dwc3_ulpi_init
  5. dwc3_ulpi_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /**
   3  * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface
   4  *
   5  * Copyright (C) 2015 Intel Corporation
   6  *
   7  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
   8  */
   9 
  10 #include <linux/ulpi/regs.h>
  11 
  12 #include "core.h"
  13 #include "io.h"
  14 
  15 #define DWC3_ULPI_ADDR(a) \
  16                 ((a >= ULPI_EXT_VENDOR_SPECIFIC) ? \
  17                 DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \
  18                 DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a))
  19 
  20 static int dwc3_ulpi_busyloop(struct dwc3 *dwc)
  21 {
  22         unsigned count = 1000;
  23         u32 reg;
  24 
  25         while (count--) {
  26                 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  27                 if (!(reg & DWC3_GUSB2PHYACC_BUSY))
  28                         return 0;
  29                 cpu_relax();
  30         }
  31 
  32         return -ETIMEDOUT;
  33 }
  34 
  35 static int dwc3_ulpi_read(struct device *dev, u8 addr)
  36 {
  37         struct dwc3 *dwc = dev_get_drvdata(dev);
  38         u32 reg;
  39         int ret;
  40 
  41         reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  42         if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
  43                 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  44                 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
  45         }
  46 
  47         reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  48         dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  49 
  50         ret = dwc3_ulpi_busyloop(dwc);
  51         if (ret)
  52                 return ret;
  53 
  54         reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
  55 
  56         return DWC3_GUSB2PHYACC_DATA(reg);
  57 }
  58 
  59 static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
  60 {
  61         struct dwc3 *dwc = dev_get_drvdata(dev);
  62         u32 reg;
  63 
  64         reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  65         if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
  66                 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
  67                 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
  68         }
  69 
  70         reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
  71         reg |= DWC3_GUSB2PHYACC_WRITE | val;
  72         dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
  73 
  74         return dwc3_ulpi_busyloop(dwc);
  75 }
  76 
  77 static const struct ulpi_ops dwc3_ulpi_ops = {
  78         .read = dwc3_ulpi_read,
  79         .write = dwc3_ulpi_write,
  80 };
  81 
  82 int dwc3_ulpi_init(struct dwc3 *dwc)
  83 {
  84         /* Register the interface */
  85         dwc->ulpi = ulpi_register_interface(dwc->dev, &dwc3_ulpi_ops);
  86         if (IS_ERR(dwc->ulpi)) {
  87                 dev_err(dwc->dev, "failed to register ULPI interface");
  88                 return PTR_ERR(dwc->ulpi);
  89         }
  90 
  91         return 0;
  92 }
  93 
  94 void dwc3_ulpi_exit(struct dwc3 *dwc)
  95 {
  96         if (dwc->ulpi) {
  97                 ulpi_unregister_interface(dwc->ulpi);
  98                 dwc->ulpi = NULL;
  99         }
 100 }

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