^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) * Rockchip USB3.0 and PCIE COMBPHY with Innosilicon IP block driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/phy/pcie.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <dt-bindings/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define BIT_WRITEABLE_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct rockchip_combphy_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) enum rockchip_combphy_rst {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) OTG_RSTN = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) PHY_POR_RSTN = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) PHY_APB_RSTN = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) PHY_PIPE_RSTN = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) PHY_GRF_P_RSTN = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) PHY_RESET_MAX = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct combphy_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 bitend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct rockchip_combphy_grfcfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct combphy_reg pipe_l1_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct combphy_reg pipe_l1_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct combphy_reg pipe_l1pd_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct combphy_reg pipe_l1pd_p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct combphy_reg pipe_l0pd_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct combphy_reg pipe_l0pd_p3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct combphy_reg pipe_clk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct combphy_reg pipe_clk_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct combphy_reg pipe_rate_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct combphy_reg pipe_rate_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct combphy_reg pipe_mode_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct combphy_reg pipe_mode_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct combphy_reg pipe_txrx_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct combphy_reg pipe_txrx_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct combphy_reg pipe_width_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct combphy_reg pipe_width_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct combphy_reg pipe_usb3_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct combphy_reg pipe_pll_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct combphy_reg pipe_status_l0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct combphy_reg pipe_l0rxterm_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct combphy_reg pipe_l1rxterm_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct combphy_reg pipe_l0rxterm_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct combphy_reg pipe_l1rxterm_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct combphy_reg pipe_l0rxelec_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct combphy_reg u3_port_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct combphy_reg u3_port_num;
^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) struct rockchip_combphy_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const struct rockchip_combphy_grfcfg grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int (*combphy_low_power_ctrl)(struct rockchip_combphy_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bool en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct rockchip_combphy_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) bool phy_initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bool phy_suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u8 phy_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) void __iomem *mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct clk *ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct regmap *combphy_grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct regmap *usb_pcie_grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct reset_control *rsts[PHY_RESET_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const struct rockchip_combphy_cfg *cfg;
^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) static const char *get_reset_name(enum rockchip_combphy_rst rst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) switch (rst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case OTG_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return "otg-rst";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case PHY_POR_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return "combphy-por";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case PHY_APB_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return "combphy-apb";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case PHY_PIPE_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return "combphy-pipe";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case PHY_GRF_P_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return "usb3phy_grf_p";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return "invalid";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline bool param_read(struct regmap *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const struct combphy_reg *reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 mask, orig, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = regmap_read(base, reg->offset, &orig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mask = GENMASK(reg->bitend, reg->bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) tmp = (orig & mask) >> reg->bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return tmp == val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static inline int param_write(struct regmap *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) const struct combphy_reg *reg, bool en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 val, mask, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) tmp = en ? reg->enable : reg->disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mask = GENMASK(reg->bitend, reg->bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return regmap_write(base, reg->offset, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static ssize_t u3phy_mode_show(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct rockchip_combphy_priv *priv = dev_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (param_read(priv->usb_pcie_grf, &priv->cfg->grfcfg.u3_port_num, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return sprintf(buf, "u2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return sprintf(buf, "u3\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static ssize_t u3phy_mode_store(struct device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct rockchip_combphy_priv *priv = dev_get_drvdata(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!strncmp(buf, "u3", 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) param_read(priv->usb_pcie_grf, &priv->cfg->grfcfg.u3_port_num, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Enable USB 3.0 rx termination, need to select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * pipe_l0_rxtermination from USB 3.0 controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) param_write(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) &priv->cfg->grfcfg.pipe_l0rxterm_sel, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Set xHCI USB 3.0 port number to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) param_write(priv->usb_pcie_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) &priv->cfg->grfcfg.u3_port_num, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* Enable xHCI USB 3.0 port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) param_write(priv->usb_pcie_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) &priv->cfg->grfcfg.u3_port_disable, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dev_info(priv->dev, "Set usb3.0 and usb2.0 mode successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) } else if (!strncmp(buf, "u2", 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) param_read(priv->usb_pcie_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) &priv->cfg->grfcfg.u3_port_num, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * Disable USB 3.0 rx termination, need to select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * pipe_l0_rxtermination from grf and remove rx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * termimation by grf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) param_write(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) &priv->cfg->grfcfg.pipe_l0rxterm_set, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) param_write(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) &priv->cfg->grfcfg.pipe_l0rxterm_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Set xHCI USB 3.0 port number to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) param_write(priv->usb_pcie_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) &priv->cfg->grfcfg.u3_port_num, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* Disable xHCI USB 3.0 port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) param_write(priv->usb_pcie_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) &priv->cfg->grfcfg.u3_port_disable, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * Don't disable the USB 3.0 PIPE pclk here(set reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * pipe_usb3_sel to false), because USB 3.0 PHY depend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * on this clk, if we disable it, we need to reinit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * the USB 3.0 PHY when use USB 3.0 mode, in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * simplify the process, don't disable this PIPE pclk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) dev_info(priv->dev, "Set usb2.0 only mode successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dev_info(priv->dev, "Same or illegal mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static DEVICE_ATTR_RW(u3phy_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static struct attribute *rockchip_combphy_u3phy_mode_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) &dev_attr_u3phy_mode.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static struct attribute_group rockchip_combphy_u3phy_mode_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .name = NULL, /* we want them in the same directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .attrs = rockchip_combphy_u3phy_mode_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static u32 rockchip_combphy_pll_lock(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u32 mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) mask = GENMASK(grfcfg->pipe_pll_lock.bitend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) grfcfg->pipe_pll_lock.bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) regmap_read(priv->combphy_grf, grfcfg->pipe_pll_lock.offset, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) val = (val & mask) >> grfcfg->pipe_pll_lock.bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mask = GENMASK(grfcfg->pipe_status_l0.bitend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) grfcfg->pipe_status_l0.bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) regmap_read(priv->combphy_grf, grfcfg->pipe_status_l0.offset, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) val = (val & mask) >> grfcfg->pipe_status_l0.bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int phy_pcie_init(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* reset PCIe phy to default configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) reset_control_assert(priv->rsts[PHY_POR_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) reset_control_assert(priv->rsts[PHY_APB_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) reset_control_assert(priv->rsts[PHY_PIPE_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) reset_control_deassert(priv->rsts[PHY_POR_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Wait PHY power on stable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) reset_control_deassert(priv->rsts[PHY_APB_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Set rxtermination for lane0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) param_write(priv->combphy_grf, &grfcfg->pipe_l0rxterm_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Set rxtermination for lane1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) param_write(priv->combphy_grf, &grfcfg->pipe_l1rxterm_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* Select pipe_l0_rxtermination from grf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) param_write(priv->combphy_grf, &grfcfg->pipe_l0rxterm_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Select pipe_l1_rxtermination from grf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) param_write(priv->combphy_grf, &grfcfg->pipe_l1rxterm_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Select rxelecidle_disable and txcommonmode from PCIe controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) param_write(priv->combphy_grf, &grfcfg->pipe_txrx_sel, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Start to configurate PHY registers for PCIE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (priv->cfg->combphy_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret = priv->cfg->combphy_cfg(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Wait Tx PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) usleep_range(300, 350);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = readx_poll_timeout_atomic(rockchip_combphy_pll_lock, priv, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) val == grfcfg->pipe_pll_lock.enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dev_err(priv->dev, "wait phy PLL lock timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) reset_control_deassert(priv->rsts[PHY_PIPE_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int phy_u3_init(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Reset the USB3 controller first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) reset_control_assert(priv->rsts[OTG_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) reset_control_deassert(priv->rsts[PHY_POR_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Wait PHY power on stable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) reset_control_deassert(priv->rsts[PHY_APB_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * Start to configurate PHY registers for USB3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * Note: set operation must be done before corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * sel operation, otherwise, the PIPE PHY status lane0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * may be unable to get ready.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* Disable PHY lane1 which isn't needed for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) param_write(priv->combphy_grf, &grfcfg->pipe_l1_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) param_write(priv->combphy_grf, &grfcfg->pipe_l1_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Set PHY Tx and Rx for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) param_write(priv->combphy_grf, &grfcfg->pipe_txrx_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) param_write(priv->combphy_grf, &grfcfg->pipe_txrx_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Set PHY PIPE MAC pclk request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) param_write(priv->combphy_grf, &grfcfg->pipe_clk_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) param_write(priv->combphy_grf, &grfcfg->pipe_clk_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Set PHY PIPE rate for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) param_write(priv->combphy_grf, &grfcfg->pipe_rate_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) param_write(priv->combphy_grf, &grfcfg->pipe_rate_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Set PHY mode for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) param_write(priv->combphy_grf, &grfcfg->pipe_mode_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) param_write(priv->combphy_grf, &grfcfg->pipe_mode_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* Set PHY data bus width for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) param_write(priv->combphy_grf, &grfcfg->pipe_width_set, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) param_write(priv->combphy_grf, &grfcfg->pipe_width_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* Select PIPE for USB3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) param_write(priv->combphy_grf, &grfcfg->pipe_usb3_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (priv->cfg->combphy_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ret = priv->cfg->combphy_cfg(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Wait Tx PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) usleep_range(300, 350);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ret = readx_poll_timeout_atomic(rockchip_combphy_pll_lock, priv, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) val == grfcfg->pipe_pll_lock.enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) dev_err(priv->dev, "wait phy PLL lock timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) reset_control_deassert(priv->rsts[PHY_PIPE_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* Wait PIPE PHY status lane0 ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = readx_poll_timeout_atomic(rockchip_combphy_is_ready, priv, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) val == grfcfg->pipe_status_l0.enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 10, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) dev_err(priv->dev, "wait phy status lane0 ready timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) reset_control_deassert(priv->rsts[OTG_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int rockchip_combphy_set_phy_type(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (priv->phy_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) switch (priv->phy_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case PHY_TYPE_PCIE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = phy_pcie_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case PHY_TYPE_USB3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = phy_u3_init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* Attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ret = sysfs_create_group(&priv->dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) &rockchip_combphy_u3phy_mode_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) dev_err(priv->dev, "incompatible PHY type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int rockchip_combphy_init(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret = clk_prepare_enable(priv->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dev_err(priv->dev, "failed to enable ref_clk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ret = rockchip_combphy_set_phy_type(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) dev_err(priv->dev, "failed to set phy type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) priv->phy_initialized = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int rockchip_combphy_exit(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * Note: don't assert PHY reset here, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * we set many phy configurations during phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * init to reduce PHY power consumption, if we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * assert PHY reset here, these configurations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * will be lost, and increase power consumption.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) clk_disable_unprepare(priv->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* in case of waiting phy PLL lock timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (priv->phy_type == PHY_TYPE_PCIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) reset_control_assert(priv->rsts[PHY_GRF_P_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) reset_control_deassert(priv->rsts[PHY_GRF_P_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) priv->phy_initialized = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static int rockchip_combphy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!priv->phy_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (priv->phy_type == PHY_TYPE_USB3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (priv->cfg->combphy_low_power_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) priv->cfg->combphy_low_power_ctrl(priv, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* Enable lane 0 squelch detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) param_write(priv->combphy_grf, &grfcfg->pipe_l0rxelec_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * Check if lane 0 powerdown is already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * controlled by USB 3.0 controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (param_read(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) &grfcfg->pipe_l0pd_sel, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* Exit to P0 from P3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) usleep_range(250, 300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * Set lane 0 powerdown to be controlled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * by USB 3.0 controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_sel, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) priv->phy_suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static int rockchip_combphy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) const struct rockchip_combphy_grfcfg *grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (priv->phy_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) grfcfg = &priv->cfg->grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (priv->phy_type == PHY_TYPE_USB3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) priv->phy_type == PHY_TYPE_PCIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * Check if lane 0 powerdown is already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * controlled by grf and in P3 state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (param_read(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) &grfcfg->pipe_l0pd_sel, 1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) param_read(priv->combphy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) &grfcfg->pipe_l0pd_p3, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* Exit to P0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_sel, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* Enter to P3 from P0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) param_write(priv->combphy_grf, &grfcfg->pipe_l0pd_p3, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * Disable lane 0 squelch detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * Note: if squelch detection is disabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * the PHY can't detect LFPS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) param_write(priv->combphy_grf, &grfcfg->pipe_l0rxelec_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (priv->cfg->combphy_low_power_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) priv->cfg->combphy_low_power_ctrl(priv, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) priv->phy_suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static int rockchip_combphy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct rockchip_combphy_priv *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (priv->phy_type != PHY_TYPE_PCIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) reg = readl(priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (PHY_MODE_PCIE_EP == submode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) reg |= (0x1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) else if (PHY_MODE_PCIE_RC == submode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) reg &= ~(0x1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) writel(reg, priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static const struct phy_ops rockchip_combphy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) .init = rockchip_combphy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .exit = rockchip_combphy_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .power_on = rockchip_combphy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .power_off = rockchip_combphy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .set_mode = rockchip_combphy_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static struct phy *rockchip_combphy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (args->args_count < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dev_err(dev, "invalid number of arguments\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (priv->phy_type != PHY_NONE && priv->phy_type != args->args[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) dev_err(dev, "type select %d overwriting phy type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) args->args[0], priv->phy_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) priv->phy_type = args->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (priv->phy_type < PHY_TYPE_SATA || priv->phy_type > PHY_TYPE_USB3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) dev_err(dev, "invalid phy type select argument\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return priv->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int rockchip_combphy_parse_dt(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) priv->combphy_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) "rockchip,combphygrf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (IS_ERR(priv->combphy_grf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dev_err(dev, "failed to find combphy grf regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return PTR_ERR(priv->combphy_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) priv->usb_pcie_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) "rockchip,usbpciegrf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (IS_ERR(priv->usb_pcie_grf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dev_err(dev, "failed to find usb_pcie_grf regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return PTR_ERR(priv->usb_pcie_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) priv->ref_clk = devm_clk_get(dev, "refclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (IS_ERR(priv->ref_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dev_err(dev, "failed to find ref clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return PTR_ERR(priv->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) for (i = 0; i < PHY_RESET_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) priv->rsts[i] = devm_reset_control_get(dev, get_reset_name(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (IS_ERR(priv->rsts[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dev_warn(dev, "no %s reset control specified\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) get_reset_name(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) priv->rsts[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static int rockchip_combphy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct rockchip_combphy_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) const struct rockchip_combphy_cfg *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) phy_cfg = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!phy_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) dev_err(dev, "No OF match data provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) priv->mmio = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (IS_ERR(priv->mmio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ret = PTR_ERR(priv->mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = rockchip_combphy_parse_dt(dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_err(dev, "parse dt failed, ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) reset_control_assert(priv->rsts[PHY_POR_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) reset_control_assert(priv->rsts[PHY_APB_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) reset_control_assert(priv->rsts[PHY_PIPE_RSTN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) priv->phy_type = PHY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) priv->cfg = phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (IS_ERR(priv->phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dev_err(dev, "failed to create combphy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return PTR_ERR(priv->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) dev_set_drvdata(dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) phy_set_drvdata(priv->phy, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) phy_provider = devm_of_phy_provider_register(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) rockchip_combphy_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return PTR_ERR_OR_ZERO(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int rockchip_combphy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct rockchip_combphy_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (priv->phy_type == PHY_TYPE_USB3 && priv->phy_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) sysfs_remove_group(&priv->dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) &rockchip_combphy_u3phy_mode_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static int rk1808_combphy_cfg(struct rockchip_combphy_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) bool ssc_en = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) rate = clk_get_rate(priv->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* Configure PHY reference clock frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case 24000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * The default PHY refclk frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * configuration is 24MHz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case 25000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) writel(0x00, priv->mmio + 0x2118);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) writel(0x64, priv->mmio + 0x211c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) writel(0x01, priv->mmio + 0x2020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) writel(0x64, priv->mmio + 0x2028);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) writel(0x21, priv->mmio + 0x2030);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (priv->phy_type == PHY_TYPE_PCIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) writel(0x1, priv->mmio + 0x3020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) writel(0x64, priv->mmio + 0x3028);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) writel(0x21, priv->mmio + 0x3030);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case 50000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) writel(0x00, priv->mmio + 0x2118);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) writel(0x32, priv->mmio + 0x211c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) writel(0x01, priv->mmio + 0x2020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) writel(0x32, priv->mmio + 0x2028);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) writel(0x21, priv->mmio + 0x2030);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (priv->phy_type == PHY_TYPE_PCIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* turn on pcie phy pd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) writel(0x08400000, priv->mmio + 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) writel(0x03030000, priv->mmio + 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* Adjust Lane 0 Rx interface timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) writel(0x20, priv->mmio + 0x20ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) writel(0x12, priv->mmio + 0x20c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) writel(0x76, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /* Adjust Lane 1 Rx interface timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) writel(0x20, priv->mmio + 0x30ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) writel(0x12, priv->mmio + 0x30c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) writel(0x76, priv->mmio + 0x3150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* Set PHY output refclk path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) writel(0x0, priv->mmio + 0x21a4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) writel(0x0, priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) writel(0xb, priv->mmio + 0x21ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /* Physical ordered set for PCIe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) writel(0x02, priv->mmio + 0x45c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) writel(0x83, priv->mmio + 0x45c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) writel(0x03, priv->mmio + 0x45c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) writel(0x43, priv->mmio + 0x45cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) writel(0x00, priv->mmio + 0x45d0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) writel(0xbc, priv->mmio + 0x45d4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* Boost pre-emphasis */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) writel(0xaa, priv->mmio + 0x21b8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) writel(0xaa, priv->mmio + 0x31b8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) } else if (priv->phy_type == PHY_TYPE_USB3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * Disable PHY Lane 1 which isn't needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * for USB3 to reduce power consumption.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* Lane 1 cdr power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) writel(0x09, priv->mmio + 0x3148);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* Lane 1 rx bias disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) writel(0x01, priv->mmio + 0x21cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* Lane 1 cdr disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) writel(0x08, priv->mmio + 0x30c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) writel(0x08, priv->mmio + 0x20f4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* Lane 1 rx lock disable and tx bias disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) writel(0x12, priv->mmio + 0x3150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* Lane 1 rx termination disable, and tx_cmenb disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) writel(0x04, priv->mmio + 0x3080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* Lane 1 tx termination disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) writel(0x1d, priv->mmio + 0x3090);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* Lane 1 tx driver disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) writel(0x50, priv->mmio + 0x21c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) writel(0x10, priv->mmio + 0x2050);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* Lane 1 txldo_refsel disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) writel(0x81, priv->mmio + 0x31a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* Lane 1 txdetrx_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) writel(0x00, priv->mmio + 0x31e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* Lane 1 rxcm_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) writel(0x08, priv->mmio + 0x30c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* Adjust Lane 0 Rx interface timing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) writel(0x20, priv->mmio + 0x20ac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Set and enable SSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) case 24000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) /* Set SSC rate to 31.25KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) reg = readl(priv->mmio + 0x2108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) reg = (reg & ~0xf) | 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) writel(reg, priv->mmio + 0x2108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ssc_en = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case 25000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* Set SSC rate to 32.55KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) reg = readl(priv->mmio + 0x2108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) reg = (reg & ~0xf) | 0x6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) writel(reg, priv->mmio + 0x2108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ssc_en = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) dev_warn(priv->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) "failed to set SSC on rate: %lu\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (ssc_en) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Enable SSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) reg = readl(priv->mmio + 0x2120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) reg &= ~BIT(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) writel(reg, priv->mmio + 0x2120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) reg = readl(priv->mmio + 0x2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) reg &= ~0x6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) writel(reg, priv->mmio + 0x2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * Tuning Tx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * offset 0x21b8 bit[7:4]: lane 0 TX driver swing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * tuning bits with weight, "1111" represents the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * largest swing and "0000" the smallest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) reg = readl(priv->mmio + 0x21b8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) reg = (reg & ~0xf0) | 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) writel(reg, priv->mmio + 0x21b8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * Tuning Rx for RJTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * Decrease CDR Chump Bump current.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) reg = readl(priv->mmio + 0x20c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) reg = (reg & ~0x6) | BIT(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) writel(reg, priv->mmio + 0x20c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) reg = readl(priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) reg |= BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) writel(reg, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dev_err(priv->dev, "failed to cfg incompatible PHY type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static int rk1808_combphy_low_power_control(struct rockchip_combphy_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) bool en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (priv->phy_type != PHY_TYPE_USB3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* turn off pcie phy pd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) writel(0x08400840, priv->mmio + 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) writel(0x03030303, priv->mmio + 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) /* enter PCIe phy low power mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) writel(0x36, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) writel(0x36, priv->mmio + 0x3150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) writel(0x02, priv->mmio + 0x21e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) writel(0x02, priv->mmio + 0x31e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) writel(0x0c, priv->mmio + 0x2080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) writel(0x0c, priv->mmio + 0x3080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) writel(0x08, priv->mmio + 0x20c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) writel(0x08, priv->mmio + 0x30c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) writel(0x08, priv->mmio + 0x2058);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) writel(0x10, priv->mmio + 0x2044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) writel(0x10, priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) writel(0x10, priv->mmio + 0x31a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) writel(0x08, priv->mmio + 0x2058);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) writel(0x08, priv->mmio + 0x3058);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) writel(0x40, priv->mmio + 0x205c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) writel(0x40, priv->mmio + 0x305c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) writel(0x08, priv->mmio + 0x2184);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) writel(0x08, priv->mmio + 0x3184);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) writel(0x00, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) writel(0x00, priv->mmio + 0x3150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) writel(0x10, priv->mmio + 0x20e0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) writel(0x00, priv->mmio + 0x21e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) writel(0x00, priv->mmio + 0x31e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (en) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Lane 0 tx_biasen disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) writel(0x36, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /* Lane 0 txdetrx_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) writel(0x02, priv->mmio + 0x21e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* Lane 0 tx_cmenb disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) writel(0x0c, priv->mmio + 0x2080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /* Lane 0 rxcm_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) writel(0x08, priv->mmio + 0x20c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* Lane 0 and Lane 1 bg_pwrdn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) writel(0x10, priv->mmio + 0x2044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Lane 0 and Lane 1 rcomp_osenseampen disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) writel(0x08, priv->mmio + 0x2058);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* Lane 0 txldo_refsel disable and LDO disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) writel(0x91, priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* Lane 1 LDO disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) writel(0x91, priv->mmio + 0x31a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* Lane 0 tx_biasen enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) writel(0x76, priv->mmio + 0x2150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* Lane 0 txdetrx_en enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) writel(0x02, priv->mmio + 0x21e8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* Lane 0 tx_cmenb enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) writel(0x08, priv->mmio + 0x2080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* Lane 0 rxcm_en enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) writel(0x18, priv->mmio + 0x20c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* Lane 0 and Lane 1 bg_pwrdn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) writel(0x00, priv->mmio + 0x2044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) /* Lane 0 and Lane 1 rcomp_osenseampen enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) writel(0x28, priv->mmio + 0x2058);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* Lane 0 txldo_refsel enable and LDO enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) writel(0x01, priv->mmio + 0x21a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* Lane 1 LDO enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) writel(0x81, priv->mmio + 0x31a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static const struct rockchip_combphy_cfg rk1808_combphy_cfgs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .grfcfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .pipe_l1_sel = { 0x0000, 15, 11, 0x00, 0x1f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .pipe_l1_set = { 0x0008, 13, 8, 0x00, 0x13 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) .pipe_l1rxterm_sel = { 0x0000, 12, 12, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .pipe_l1pd_sel = { 0x0000, 11, 11, 0x0, 0x1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .pipe_l1pd_p3 = { 0x0008, 9, 8, 0x0, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .pipe_l0rxterm_sel = { 0x0000, 7, 7, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .pipe_l0pd_sel = { 0x0000, 6, 6, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .pipe_l0pd_p3 = { 0x0008, 1, 0, 0x0, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .pipe_clk_sel = { 0x0000, 3, 3, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .pipe_clk_set = { 0x0004, 7, 6, 0x1, 0x0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .pipe_rate_sel = { 0x0000, 2, 2, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .pipe_rate_set = { 0x0004, 5, 4, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .pipe_mode_sel = { 0x0000, 1, 1, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) .pipe_mode_set = { 0x0004, 3, 2, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) .pipe_txrx_sel = { 0x0004, 15, 8, 0x10, 0x2f },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) .pipe_txrx_set = { 0x0008, 15, 14, 0x0, 0x3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) .pipe_l1rxterm_set = { 0x0008, 10, 10, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) .pipe_l0rxterm_set = { 0x0008, 2, 2, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) .pipe_l0rxelec_set = { 0x0008, 6, 6, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .pipe_width_sel = { 0x0000, 0, 0, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .pipe_width_set = { 0x0004, 1, 0, 0x2, 0x0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .pipe_usb3_sel = { 0x000c, 0, 0, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .pipe_pll_lock = { 0x0034, 14, 14, 0x0, 0x1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .pipe_status_l0 = { 0x0034, 7, 7, 0x1, 0x0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .u3_port_disable = { 0x0434, 0, 0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .u3_port_num = { 0x0434, 15, 12, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .combphy_cfg = rk1808_combphy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .combphy_low_power_ctrl = rk1808_combphy_low_power_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) static const struct of_device_id rockchip_combphy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .compatible = "rockchip,rk1808-combphy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) .data = &rk1808_combphy_cfgs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) MODULE_DEVICE_TABLE(of, rockchip_combphy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static struct platform_driver rockchip_combphy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) .probe = rockchip_combphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) .remove = rockchip_combphy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .name = "rockchip-combphy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) .of_match_table = rockchip_combphy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) module_platform_driver(rockchip_combphy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) MODULE_AUTHOR("William Wu <william.wu@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) MODULE_DESCRIPTION("Rockchip USB3.0 and PCIE COMBPHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) MODULE_LICENSE("GPL v2");