diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 00:59:26 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-27 00:59:26 +0200 |
commit | 2a298679b41199ae742a77ce69766385dffe816f (patch) | |
tree | 93a23c0d828ccca7053f604dbfcdd4d3278972b3 /drivers/usb/dwc3/ulpi.c | |
parent | Merge tag 'tty-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/greg... (diff) | |
parent | usb: dwc3: Use ASCII space in Kconfig (diff) | |
download | linux-2a298679b41199ae742a77ce69766385dffe816f.tar.xz linux-2a298679b41199ae742a77ce69766385dffe816f.zip |
Merge tag 'usb-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
"Here's the big USB patchset for 4.2-rc1. As is normal these days, the
majority of changes are in the gadget drivers, with a bunch of other
small driver changes.
All of these have been in linux-next with no reported issues"
* tag 'usb-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (175 commits)
usb: dwc3: Use ASCII space in Kconfig
usb: chipidea: add work-around for Marvell HSIC PHY startup
usb: chipidea: allow multiple instances to use default ci_default_pdata
dt-bindings: Consolidate ChipIdea USB ci13xxx bindings
phy: add Marvell HSIC 28nm PHY
phy: Add Marvell USB 2.0 OTG 28nm PHY
dt-bindings: Add Marvell PXA1928 USB and HSIC PHY bindings
USB: ssb: use devm_kzalloc
USB: ssb: fix error handling in ssb_hcd_create_pdev()
usb: isp1760: check for null return from kzalloc
cdc-acm: Add support of ATOL FPrint fiscal printers
usb: chipidea: usbmisc_imx: Remove unneeded semicolon
USB: usbtmc: add device quirk for Rigol DS6104
USB: serial: mos7840: Use setup_timer
phy: twl4030-usb: add ABI documentation
phy: twl4030-usb: remove incorrect pm_runtime_get_sync() in probe function.
phy: twl4030-usb: remove pointless 'suspended' test in 'suspend' callback.
phy: twl4030-usb: make runtime pm more reliable.
drivers:usb:fsl: Fix compilation error for fsl ehci drv
usb: renesas_usbhs: Don't disable the pipe if Control write status stage
...
Diffstat (limited to 'drivers/usb/dwc3/ulpi.c')
-rw-r--r-- | drivers/usb/dwc3/ulpi.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c new file mode 100644 index 000000000000..ec004c6d76f2 --- /dev/null +++ b/drivers/usb/dwc3/ulpi.c @@ -0,0 +1,91 @@ +/** + * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface + * + * Copyright (C) 2015 Intel Corporation + * + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/ulpi/regs.h> + +#include "core.h" +#include "io.h" + +#define DWC3_ULPI_ADDR(a) \ + ((a >= ULPI_EXT_VENDOR_SPECIFIC) ? \ + DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \ + DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a)) + +static int dwc3_ulpi_busyloop(struct dwc3 *dwc) +{ + unsigned count = 1000; + u32 reg; + + while (count--) { + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0)); + if (!(reg & DWC3_GUSB2PHYACC_BUSY)) + return 0; + cpu_relax(); + } + + return -ETIMEDOUT; +} + +static int dwc3_ulpi_read(struct ulpi_ops *ops, u8 addr) +{ + struct dwc3 *dwc = dev_get_drvdata(ops->dev); + u32 reg; + int ret; + + reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); + dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); + + ret = dwc3_ulpi_busyloop(dwc); + if (ret) + return ret; + + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0)); + + return DWC3_GUSB2PHYACC_DATA(reg); +} + +static int dwc3_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val) +{ + struct dwc3 *dwc = dev_get_drvdata(ops->dev); + u32 reg; + + reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); + reg |= DWC3_GUSB2PHYACC_WRITE | val; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); + + return dwc3_ulpi_busyloop(dwc); +} + +static struct ulpi_ops dwc3_ulpi_ops = { + .read = dwc3_ulpi_read, + .write = dwc3_ulpi_write, +}; + +int dwc3_ulpi_init(struct dwc3 *dwc) +{ + /* Register the interface */ + dwc->ulpi = ulpi_register_interface(dwc->dev, &dwc3_ulpi_ops); + if (IS_ERR(dwc->ulpi)) { + dev_err(dwc->dev, "failed to register ULPI interface"); + return PTR_ERR(dwc->ulpi); + } + + return 0; +} + +void dwc3_ulpi_exit(struct dwc3 *dwc) +{ + if (dwc->ulpi) { + ulpi_unregister_interface(dwc->ulpi); + dwc->ulpi = NULL; + } +} |