12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- /**
- * 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;
- }
- }
|