^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2016 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/usb/chipidea.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/ulpi/interface.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "ci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define ULPI_WAKEUP BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define ULPI_RUN BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define ULPI_WRITE BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define ULPI_SYNC_STATE BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define ULPI_ADDR(n) ((n) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define ULPI_DATA(n) (n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned long usec = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) while (usec--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (!hw_read(ci, OP_ULPI_VIEWPORT, mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int ci_ulpi_read(struct device *dev, u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct ci_hdrc *ci = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ret = ci_ulpi_wait(ci, ULPI_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int ci_ulpi_write(struct device *dev, u8 addr, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct ci_hdrc *ci = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return ci_ulpi_wait(ci, ULPI_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int ci_ulpi_init(struct ci_hdrc *ci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Set PORTSC correctly so we can read/write ULPI registers for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * identification purposes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) hw_phymode_configure(ci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ci->ulpi_ops.read = ci_ulpi_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ci->ulpi_ops.write = ci_ulpi_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (IS_ERR(ci->ulpi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_err(ci->dev, "failed to register ULPI interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return PTR_ERR_OR_ZERO(ci->ulpi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) void ci_ulpi_exit(struct ci_hdrc *ci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (ci->ulpi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ulpi_unregister_interface(ci->ulpi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ci->ulpi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ci_ulpi_resume(struct ci_hdrc *ci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int cnt = 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) while (cnt-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }