^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Rockchip USB 3.0 PHY with Innosilicon IP block driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/usb/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define U3PHY_PORT_NUM 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define U3PHY_MAX_CLKS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define BIT_WRITEABLE_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SCHEDULE_DELAY (60 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define U3PHY_APB_RST BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define U3PHY_POR_RST BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define U3PHY_MAC_RST BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct rockchip_u3phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct rockchip_u3phy_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) enum rockchip_u3phy_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) U3PHY_TYPE_PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) U3PHY_TYPE_UTMI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) enum rockchip_u3phy_pipe_pwr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) PIPE_PWR_P0 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) PIPE_PWR_P1 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) PIPE_PWR_P2 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) PIPE_PWR_P3 = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) PIPE_PWR_MAX = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) enum rockchip_u3phy_rest_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) U3_POR_RSTN = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) U2_POR_RSTN = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) PIPE_MAC_RSTN = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) UTMI_MAC_RSTN = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) PIPE_APB_RSTN = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) UTMI_APB_RSTN = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) U3PHY_RESET_MAX = 6,
^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) enum rockchip_u3phy_utmi_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) PHY_UTMI_HS_ONLINE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) PHY_UTMI_DISCONNECT = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) PHY_UTMI_CONNECT = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) PHY_UTMI_FS_LS_ONLINE = 4,
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * @rvalue: reset value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * @dvalue: desired value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct u3phy_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int bitend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned int bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned int rvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned int dvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct rockchip_u3phy_grfcfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct u3phy_reg um_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct u3phy_reg ls_det_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct u3phy_reg ls_det_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct u3phy_reg um_ls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct u3phy_reg um_hstdct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct u3phy_reg u2_only_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct u3phy_reg u3_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct u3phy_reg pp_pwr_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct u3phy_reg pp_pwr_en[PIPE_PWR_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * struct rockchip_u3phy_apbcfg: usb3-phy apb configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @u2_pre_emp: usb2-phy pre-emphasis tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @u2_pre_emp_sth: usb2-phy pre-emphasis strength tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @u2_odt_tuning: usb2-phy odt 45ohm tuning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct rockchip_u3phy_apbcfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned int u2_pre_emp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int u2_pre_emp_sth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned int u2_odt_tuning;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct rockchip_u3phy_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) const struct rockchip_u3phy_grfcfg grfcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int (*phy_pipe_power)(struct rockchip_u3phy *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct rockchip_u3phy_port *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) bool on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int (*phy_tuning)(struct rockchip_u3phy *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct rockchip_u3phy_port *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct device_node *);
^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) struct rockchip_u3phy_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned char type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) bool suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) bool refclk_25m_quirk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct mutex mutex; /* mutex for updating register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct delayed_work um_sm_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct rockchip_u3phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct regmap *u3phy_grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct regmap *grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int um_ls_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct clk *clks[U3PHY_MAX_CLKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct regulator *vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct reset_control *rsts[U3PHY_RESET_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct rockchip_u3phy_apbcfg apbcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) const struct rockchip_u3phy_cfg *cfgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct rockchip_u3phy_port ports[U3PHY_PORT_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct usb_phy usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) bool vbus_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static inline int param_write(void __iomem *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) const struct u3phy_reg *reg, bool desired)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned int val, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned int tmp = desired ? reg->dvalue : reg->rvalue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) mask = GENMASK(reg->bitend, reg->bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = regmap_write(base, reg->offset, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static inline bool param_exped(void __iomem *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) const struct u3phy_reg *reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned int tmp, orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = regmap_read(base, reg->offset, &orig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) tmp = (orig & mask) >> reg->bitstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return tmp == value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int rockchip_set_vbus_power(struct rockchip_u3phy *u3phy, bool en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (!u3phy->vbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (en && !u3phy->vbus_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = regulator_enable(u3phy->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_err(u3phy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) "Failed to enable VBUS supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else if (!en && u3phy->vbus_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = regulator_disable(u3phy->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u3phy->vbus_enabled = en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int rockchip_u3phy_usb2_only_show(struct seq_file *s, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct rockchip_u3phy *u3phy = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (param_exped(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.u2_only_ctrl, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dev_info(u3phy->dev, "u2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dev_info(u3phy->dev, "u3\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int rockchip_u3phy_usb2_only_open(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return single_open(file, rockchip_u3phy_usb2_only_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) inode->i_private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static ssize_t rockchip_u3phy_usb2_only_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) const char __user *ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct seq_file *s = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct rockchip_u3phy *u3phy = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct rockchip_u3phy_port *u3phy_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) char buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!strncmp(buf, "u3", 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) param_exped(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) &u3phy->cfgs->grfcfg.u2_only_ctrl, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dev_info(u3phy->dev, "Set usb3.0 and usb2.0 mode successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) rockchip_set_vbus_power(u3phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) param_write(u3phy->grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) &u3phy->cfgs->grfcfg.u3_disable, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) &u3phy->cfgs->grfcfg.u2_only_ctrl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for (index = 0; index < U3PHY_PORT_NUM; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u3phy_port = &u3phy->ports[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* enable u3 rx termimation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (u3phy_port->type == U3PHY_TYPE_PIPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) writel(0x30, u3phy_port->base + 0xd8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) atomic_notifier_call_chain(&u3phy->usb_phy.notifier, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rockchip_set_vbus_power(u3phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) } else if (!strncmp(buf, "u2", 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) param_exped(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) &u3phy->cfgs->grfcfg.u2_only_ctrl, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dev_info(u3phy->dev, "Set usb2.0 only mode successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) rockchip_set_vbus_power(u3phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) param_write(u3phy->grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) &u3phy->cfgs->grfcfg.u3_disable, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) &u3phy->cfgs->grfcfg.u2_only_ctrl, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) for (index = 0; index < U3PHY_PORT_NUM; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) u3phy_port = &u3phy->ports[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* disable u3 rx termimation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (u3phy_port->type == U3PHY_TYPE_PIPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) writel(0x20, u3phy_port->base + 0xd8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) atomic_notifier_call_chain(&u3phy->usb_phy.notifier, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) rockchip_set_vbus_power(u3phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dev_info(u3phy->dev, "Same or illegal mode\n");
^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) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static const struct file_operations rockchip_u3phy_usb2_only_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .open = rockchip_u3phy_usb2_only_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .write = rockchip_u3phy_usb2_only_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static void rockchip_u3phy_debugfs_init(struct rockchip_u3phy *u3phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) root = debugfs_create_dir(dev_name(u3phy->dev), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) debugfs_create_file("u3phy_mode", 0644, root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u3phy, &rockchip_u3phy_usb2_only_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static const char *get_rest_name(enum rockchip_u3phy_rest_req rst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) switch (rst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case U2_POR_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return "u3phy-u2-por";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case U3_POR_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return "u3phy-u3-por";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case PIPE_MAC_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return "u3phy-pipe-mac";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case UTMI_MAC_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return "u3phy-utmi-mac";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case UTMI_APB_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return "u3phy-utmi-apb";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case PIPE_APB_RSTN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return "u3phy-pipe-apb";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return "invalid";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^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) static void rockchip_u3phy_rest_deassert(struct rockchip_u3phy *u3phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) unsigned int flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int rst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (flag & U3PHY_APB_RST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) dev_dbg(u3phy->dev, "deassert APB bus interface reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) for (rst = PIPE_APB_RSTN; rst <= UTMI_APB_RSTN; rst++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (u3phy->rsts[rst])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) reset_control_deassert(u3phy->rsts[rst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (flag & U3PHY_POR_RST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) usleep_range(12, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dev_dbg(u3phy->dev, "deassert u2 and u3 phy power on reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) for (rst = U3_POR_RSTN; rst <= U2_POR_RSTN; rst++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (u3phy->rsts[rst])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) reset_control_deassert(u3phy->rsts[rst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (flag & U3PHY_MAC_RST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) usleep_range(1200, 1500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_dbg(u3phy->dev, "deassert pipe and utmi MAC reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) for (rst = PIPE_MAC_RSTN; rst <= UTMI_MAC_RSTN; rst++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (u3phy->rsts[rst])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) reset_control_deassert(u3phy->rsts[rst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void rockchip_u3phy_rest_assert(struct rockchip_u3phy *u3phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int rst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dev_dbg(u3phy->dev, "assert u3phy reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) for (rst = 0; rst < U3PHY_RESET_MAX; rst++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (u3phy->rsts[rst])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) reset_control_assert(u3phy->rsts[rst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int rockchip_u3phy_clk_enable(struct rockchip_u3phy *u3phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int ret, clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) for (clk = 0; clk < U3PHY_MAX_CLKS && u3phy->clks[clk]; clk++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = clk_prepare_enable(u3phy->clks[clk]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto err_disable_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) err_disable_clks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) while (--clk >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) clk_disable_unprepare(u3phy->clks[clk]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static void rockchip_u3phy_clk_disable(struct rockchip_u3phy *u3phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) for (clk = U3PHY_MAX_CLKS - 1; clk >= 0; clk--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (u3phy->clks[clk])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) clk_disable_unprepare(u3phy->clks[clk]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int rockchip_u3phy_init(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int rockchip_u3phy_exit(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int rockchip_u3phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct rockchip_u3phy_port *u3phy_port = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct rockchip_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) dev_info(&u3phy_port->phy->dev, "u3phy %s power on\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) (u3phy_port->type == U3PHY_TYPE_UTMI) ? "u2" : "u3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (!u3phy_port->suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = rockchip_u3phy_clk_enable(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (u3phy_port->type == U3PHY_TYPE_UTMI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) &u3phy->cfgs->grfcfg.um_suspend, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /* current in p2 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (param_exped(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) &u3phy->cfgs->grfcfg.pp_pwr_st, PIPE_PWR_P2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (u3phy->cfgs->phy_pipe_power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) dev_dbg(u3phy->dev, "do pipe power up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u3phy->cfgs->phy_pipe_power(u3phy, u3phy_port, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* exit to p0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P0], true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) usleep_range(90, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* enter to p2 from p0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) udelay(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rockchip_set_vbus_power(u3phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u3phy_port->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int rockchip_u3phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct rockchip_u3phy_port *u3phy_port = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct rockchip_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_info(&u3phy_port->phy->dev, "u3phy %s power off\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) (u3phy_port->type == U3PHY_TYPE_UTMI) ? "u2" : "u3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (u3phy_port->suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (u3phy_port->type == U3PHY_TYPE_UTMI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) &u3phy->cfgs->grfcfg.um_suspend, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* current in p3 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (param_exped(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) &u3phy->cfgs->grfcfg.pp_pwr_st, PIPE_PWR_P3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* exit to p0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P0], true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* enter to p3 from p0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) &u3phy->cfgs->grfcfg.pp_pwr_en[PIPE_PWR_P3], true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) udelay(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (u3phy->cfgs->phy_pipe_power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dev_dbg(u3phy->dev, "do pipe power down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) u3phy->cfgs->phy_pipe_power(u3phy, u3phy_port, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) rockchip_u3phy_clk_disable(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) u3phy_port->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static __maybe_unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct phy *rockchip_u3phy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct rockchip_u3phy *u3phy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct rockchip_u3phy_port *u3phy_port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct device_node *phy_np = args->np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (args->args_count != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dev_err(dev, "invalid number of cells in 'phy' property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for (index = 0; index < U3PHY_PORT_NUM; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (phy_np == u3phy->ports[index].phy->dev.of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) u3phy_port = &u3phy->ports[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (!u3phy_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dev_err(dev, "failed to find appropriate phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return u3phy_port->phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static struct phy_ops rockchip_u3phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) .init = rockchip_u3phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) .exit = rockchip_u3phy_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) .power_on = rockchip_u3phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) .power_off = rockchip_u3phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * The function manage host-phy port state and suspend/resume phy port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * to save power automatically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * devices is disconnect or not. Besides, we do not need care it is FS/LS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * disconnected or HS disconnected, actually, we just only need get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * device is disconnected at last through rearm the delayed work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static void rockchip_u3phy_um_sm_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct rockchip_u3phy_port *u3phy_port =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) container_of(work, struct rockchip_u3phy_port, um_sm_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct rockchip_u3phy *u3phy =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dev_get_drvdata(u3phy_port->phy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) unsigned int sh = u3phy->cfgs->grfcfg.um_hstdct.bitend -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) u3phy->cfgs->grfcfg.um_hstdct.bitstart + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) unsigned int ul, uhd, state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) unsigned int ul_mask, uhd_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mutex_lock(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ret = regmap_read(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) u3phy->cfgs->grfcfg.um_ls.offset, &ul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) goto next_schedule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = regmap_read(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) u3phy->cfgs->grfcfg.um_hstdct.offset, &uhd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) goto next_schedule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) uhd_mask = GENMASK(u3phy->cfgs->grfcfg.um_hstdct.bitend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) u3phy->cfgs->grfcfg.um_hstdct.bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ul_mask = GENMASK(u3phy->cfgs->grfcfg.um_ls.bitend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) u3phy->cfgs->grfcfg.um_ls.bitstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* stitch on um_ls and um_hstdct as phy state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) state = ((uhd & uhd_mask) >> u3phy->cfgs->grfcfg.um_hstdct.bitstart) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) (((ul & ul_mask) >> u3phy->cfgs->grfcfg.um_ls.bitstart) << sh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) case PHY_UTMI_HS_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dev_dbg(&u3phy_port->phy->dev, "HS online\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case PHY_UTMI_FS_LS_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * For FS/LS device, the online state share with connect state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * from um_ls and um_hstdct register, so we distinguish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * them via suspended flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * Plus, there are two cases, one is D- Line pull-up, and D+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * line pull-down, the state is 4; another is D+ line pull-up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * and D- line pull-down, the state is 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!u3phy_port->suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* D- line pull-up, D+ line pull-down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) dev_dbg(&u3phy_port->phy->dev, "FS/LS online\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) case PHY_UTMI_CONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (u3phy_port->suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dev_dbg(&u3phy_port->phy->dev, "Connected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rockchip_u3phy_power_on(u3phy_port->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) u3phy_port->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* D+ line pull-up, D- line pull-down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) dev_dbg(&u3phy_port->phy->dev, "FS/LS online\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case PHY_UTMI_DISCONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (!u3phy_port->suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dev_dbg(&u3phy_port->phy->dev, "Disconnected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) rockchip_u3phy_power_off(u3phy_port->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) u3phy_port->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * activate the linestate detection to get the next device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * plug-in irq.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) &u3phy->cfgs->grfcfg.ls_det_st, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) param_write(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) &u3phy->cfgs->grfcfg.ls_det_en, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * we don't need to rearm the delayed work when the phy port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * is suspended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) mutex_unlock(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dev_dbg(&u3phy_port->phy->dev, "unknown phy state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) next_schedule:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mutex_unlock(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) schedule_delayed_work(&u3phy_port->um_sm_work, SCHEDULE_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static irqreturn_t rockchip_u3phy_um_ls_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct rockchip_u3phy_port *u3phy_port = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct rockchip_u3phy *u3phy =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) dev_get_drvdata(u3phy_port->phy->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (!param_exped(u3phy->u3phy_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) &u3phy->cfgs->grfcfg.ls_det_st,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) u3phy->cfgs->grfcfg.ls_det_st.dvalue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) dev_dbg(u3phy->dev, "utmi linestate interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) mutex_lock(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* disable linestate detect irq and clear its status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) param_write(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.ls_det_en, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) param_write(u3phy->u3phy_grf, &u3phy->cfgs->grfcfg.ls_det_st, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) mutex_unlock(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * In this case for host phy, a new device is plugged in, meanwhile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * if the phy port is suspended, we need rearm the work to resume it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * and mange its states; otherwise, we just return irq handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (u3phy_port->suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dev_dbg(u3phy->dev, "schedule utmi sm work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) rockchip_u3phy_um_sm_work(&u3phy_port->um_sm_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int rockchip_u3phy_parse_dt(struct rockchip_u3phy *u3phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int ret, i, clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) u3phy->um_ls_irq = platform_get_irq_byname(pdev, "linestate");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (u3phy->um_ls_irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev_err(dev, "get utmi linestate irq failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* Get Vbus regulators */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) u3phy->vbus = devm_regulator_get_optional(dev, "vbus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (IS_ERR(u3phy->vbus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ret = PTR_ERR(u3phy->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dev_warn(dev, "Failed to get VBUS supply regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) u3phy->vbus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) for (clk = 0; clk < U3PHY_MAX_CLKS; clk++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) u3phy->clks[clk] = of_clk_get(np, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (IS_ERR(u3phy->clks[clk])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ret = PTR_ERR(u3phy->clks[clk]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) goto err_put_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u3phy->clks[clk] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) for (i = 0; i < U3PHY_RESET_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) u3phy->rsts[i] = devm_reset_control_get(dev, get_rest_name(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (IS_ERR(u3phy->rsts[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) dev_info(dev, "no %s reset control specified\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) get_rest_name(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) u3phy->rsts[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) err_put_clks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) while (--clk >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) clk_put(u3phy->clks[clk]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int rockchip_u3phy_port_init(struct rockchip_u3phy *u3phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct rockchip_u3phy_port *u3phy_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct device_node *child_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) dev_dbg(u3phy->dev, "u3phy port initialize\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) mutex_init(&u3phy_port->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) u3phy_port->suspended = true; /* initial status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) phy = devm_phy_create(u3phy->dev, child_np, &rockchip_u3phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (IS_ERR(phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) dev_err(u3phy->dev, "failed to create phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) u3phy_port->phy = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) ret = of_address_to_resource(child_np, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) dev_err(u3phy->dev, "failed to get address resource(np-%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) child_np->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return ret;
^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) u3phy_port->base = devm_ioremap_resource(&u3phy_port->phy->dev, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (IS_ERR(u3phy_port->base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev_err(u3phy->dev, "failed to remap phy regs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return PTR_ERR(u3phy_port->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (!of_node_cmp(child_np->name, "pipe")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) u3phy_port->type = U3PHY_TYPE_PIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) u3phy_port->refclk_25m_quirk =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) of_property_read_bool(child_np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) "rockchip,refclk-25m-quirk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) u3phy_port->type = U3PHY_TYPE_UTMI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) INIT_DELAYED_WORK(&u3phy_port->um_sm_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) rockchip_u3phy_um_sm_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ret = devm_request_threaded_irq(u3phy->dev, u3phy->um_ls_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) NULL, rockchip_u3phy_um_ls_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) IRQF_ONESHOT, "rockchip_u3phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) u3phy_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) dev_err(u3phy->dev, "failed to request utmi linestate irq handle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (u3phy->cfgs->phy_tuning) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) dev_dbg(u3phy->dev, "do u3phy tuning\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ret = u3phy->cfgs->phy_tuning(u3phy, u3phy_port, child_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) phy_set_drvdata(u3phy_port->phy, u3phy_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static int rockchip_u3phy_on_init(struct usb_phy *usb_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct rockchip_u3phy *u3phy =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) container_of(usb_phy, struct rockchip_u3phy, usb_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) rockchip_u3phy_rest_deassert(u3phy, U3PHY_POR_RST | U3PHY_MAC_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static void rockchip_u3phy_on_shutdown(struct usb_phy *usb_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct rockchip_u3phy *u3phy =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) container_of(usb_phy, struct rockchip_u3phy, usb_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int rst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) for (rst = 0; rst < U3PHY_RESET_MAX; rst++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (u3phy->rsts[rst] && rst != UTMI_APB_RSTN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) rst != PIPE_APB_RSTN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) reset_control_assert(u3phy->rsts[rst]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static int rockchip_u3phy_on_disconnect(struct usb_phy *usb_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) enum usb_device_speed speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct rockchip_u3phy *u3phy =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) container_of(usb_phy, struct rockchip_u3phy, usb_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) dev_info(u3phy->dev, "%s device has disconnected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) (speed == USB_SPEED_SUPER) ? "U3" : "UW/U2/U1.1/U1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (speed == USB_SPEED_SUPER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) atomic_notifier_call_chain(&usb_phy->notifier, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static int rockchip_u3phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct device_node *child_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct phy_provider *provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct rockchip_u3phy *u3phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) const struct rockchip_u3phy_cfg *phy_cfgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) unsigned int reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int index, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) match = of_match_device(dev->driver->of_match_table, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (!match || !match->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dev_err(dev, "phy-cfgs are not assigned!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return -EINVAL;
^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) u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!u3phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) u3phy->u3phy_grf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) syscon_regmap_lookup_by_phandle(np, "rockchip,u3phygrf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (IS_ERR(u3phy->u3phy_grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return PTR_ERR(u3phy->u3phy_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) u3phy->grf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (IS_ERR(u3phy->grf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dev_err(dev, "Missing rockchip,grf property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return PTR_ERR(u3phy->grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (of_property_read_u32_array(np, "reg", reg, 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) dev_err(dev, "the reg property is not assigned in %s node\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) np->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return -EINVAL;
^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) u3phy->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) u3phy->vbus_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) phy_cfgs = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) platform_set_drvdata(pdev, u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* find out a proper config which can be matched with dt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) while (phy_cfgs[index].reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (phy_cfgs[index].reg == reg[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) u3phy->cfgs = &phy_cfgs[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ++index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (!u3phy->cfgs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) dev_err(dev, "no phy-cfgs can be matched with %s node\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) np->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ret = rockchip_u3phy_parse_dt(u3phy, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) dev_err(dev, "parse dt failed, ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ret = rockchip_u3phy_clk_enable(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_err(dev, "clk enable failed, ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) rockchip_u3phy_rest_assert(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) rockchip_u3phy_rest_deassert(u3phy, U3PHY_APB_RST | U3PHY_POR_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) for_each_available_child_of_node(np, child_np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct rockchip_u3phy_port *u3phy_port = &u3phy->ports[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) u3phy_port->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ret = rockchip_u3phy_port_init(u3phy, u3phy_port, child_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) dev_err(dev, "u3phy port init failed,ret(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) goto put_child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* to prevent out of boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (++index >= U3PHY_PORT_NUM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (IS_ERR(provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret = PTR_ERR(provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) goto put_child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) rockchip_u3phy_rest_deassert(u3phy, U3PHY_MAC_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) rockchip_u3phy_clk_disable(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) u3phy->usb_phy.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) u3phy->usb_phy.init = rockchip_u3phy_on_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) u3phy->usb_phy.shutdown = rockchip_u3phy_on_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) u3phy->usb_phy.notify_disconnect = rockchip_u3phy_on_disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) usb_add_phy(&u3phy->usb_phy, USB_PHY_TYPE_USB3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ATOMIC_INIT_NOTIFIER_HEAD(&u3phy->usb_phy.notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) rockchip_u3phy_debugfs_init(u3phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dev_info(dev, "Rockchip u3phy initialized successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) put_child:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) of_node_put(child_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int rk3328_u3phy_pipe_power(struct rockchip_u3phy *u3phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct rockchip_u3phy_port *u3phy_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) reg = readl(u3phy_port->base + 0x1a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) reg &= ~BIT(4); /* ldo power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) writel(reg, u3phy_port->base + 0x1a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) reg = readl(u3phy_port->base + 0x044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) reg &= ~BIT(4); /* bg power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) writel(reg, u3phy_port->base + 0x044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) reg = readl(u3phy_port->base + 0x150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) reg |= BIT(6); /* tx bias enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) writel(reg, u3phy_port->base + 0x150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) reg = readl(u3phy_port->base + 0x080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) reg &= ~BIT(2); /* tx cm power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) writel(reg, u3phy_port->base + 0x080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) reg = readl(u3phy_port->base + 0x0c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* tx obs enable and rx cm enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) reg |= (BIT(3) | BIT(4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) writel(reg, u3phy_port->base + 0x0c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) reg = readl(u3phy_port->base + 0x1a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) reg |= BIT(4); /* ldo power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) writel(reg, u3phy_port->base + 0x1a8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) reg = readl(u3phy_port->base + 0x044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) reg |= BIT(4); /* bg power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) writel(reg, u3phy_port->base + 0x044);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) reg = readl(u3phy_port->base + 0x150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) reg &= ~BIT(6); /* tx bias disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) writel(reg, u3phy_port->base + 0x150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) reg = readl(u3phy_port->base + 0x080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) reg |= BIT(2); /* tx cm power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) writel(reg, u3phy_port->base + 0x080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) reg = readl(u3phy_port->base + 0x0c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* tx obs disable and rx cm disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) reg &= ~(BIT(3) | BIT(4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) writel(reg, u3phy_port->base + 0x0c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) static int rk3328_u3phy_tuning(struct rockchip_u3phy *u3phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct rockchip_u3phy_port *u3phy_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct device_node *child_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (u3phy_port->type == U3PHY_TYPE_UTMI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * For rk3328 SoC, pre-emphasis and pre-emphasis strength must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * be written as one fixed value as below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * Dissimilarly, the odt 45ohm value should be flexibly tuninged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * for the different boards to adjust HS eye height, so its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * value can be assigned in DT in code design.
^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) /* {bits[2:0]=111}: always enable pre-emphasis */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) u3phy->apbcfg.u2_pre_emp = 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /* {bits[5:3]=000}: pre-emphasis strength as the weakest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) u3phy->apbcfg.u2_pre_emp_sth = 0x41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) /* {bits[4:0]=10101}: odt 45ohm tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) u3phy->apbcfg.u2_odt_tuning = 0xb5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* optional override of the odt 45ohm tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) of_property_read_u32(child_np, "rockchip,odt-val-tuning",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) &u3phy->apbcfg.u2_odt_tuning);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) writel(u3phy->apbcfg.u2_pre_emp, u3phy_port->base + 0x030);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) writel(u3phy->apbcfg.u2_pre_emp_sth, u3phy_port->base + 0x040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) writel(u3phy->apbcfg.u2_odt_tuning, u3phy_port->base + 0x11c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) } else if (u3phy_port->type == U3PHY_TYPE_PIPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (u3phy_port->refclk_25m_quirk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) dev_dbg(u3phy->dev, "switch to 25m refclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* ref clk switch to 25M */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) writel(0x64, u3phy_port->base + 0x11c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) writel(0x64, u3phy_port->base + 0x028);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) writel(0x01, u3phy_port->base + 0x020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) writel(0x21, u3phy_port->base + 0x030);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) writel(0x06, u3phy_port->base + 0x108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) writel(0x00, u3phy_port->base + 0x118);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /* configure for 24M ref clk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) writel(0x80, u3phy_port->base + 0x10c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) writel(0x01, u3phy_port->base + 0x118);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) writel(0x38, u3phy_port->base + 0x11c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) writel(0x83, u3phy_port->base + 0x020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) writel(0x02, u3phy_port->base + 0x108);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /* Enable SSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) udelay(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) writel(0x08, u3phy_port->base + 0x000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) writel(0x0c, u3phy_port->base + 0x120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) /* Tuning Rx for compliance RJTL test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) writel(0x70, u3phy_port->base + 0x150);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) writel(0x12, u3phy_port->base + 0x0c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) writel(0x05, u3phy_port->base + 0x148);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) writel(0x08, u3phy_port->base + 0x068);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) writel(0xf0, u3phy_port->base + 0x1c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) writel(0xff, u3phy_port->base + 0x070);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) writel(0x0f, u3phy_port->base + 0x06c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) writel(0xe0, u3phy_port->base + 0x060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * Tuning Tx to increase the bias current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * used in TX driver and RX EQ, it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * also increase the voltage of LFPS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) writel(0x08, u3phy_port->base + 0x180);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) dev_err(u3phy->dev, "invalid u3phy port type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static const struct rockchip_u3phy_cfg rk3328_u3phy_cfgs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) .reg = 0xff470000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) .grfcfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) .um_suspend = { 0x0004, 15, 0, 0x1452, 0x15d1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .u2_only_ctrl = { 0x0020, 15, 15, 0, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) .um_ls = { 0x0030, 5, 4, 0, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) .um_hstdct = { 0x0030, 7, 7, 0, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) .ls_det_en = { 0x0040, 0, 0, 0, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) .ls_det_st = { 0x0044, 0, 0, 0, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .pp_pwr_st = { 0x0034, 14, 13, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) .pp_pwr_en = { {0x0020, 14, 0, 0x0014, 0x0005},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) {0x0020, 14, 0, 0x0014, 0x000d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {0x0020, 14, 0, 0x0014, 0x0015},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {0x0020, 14, 0, 0x0014, 0x001d} },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) .u3_disable = { 0x04c4, 15, 0, 0x1100, 0x101},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) .phy_pipe_power = rk3328_u3phy_pipe_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) .phy_tuning = rk3328_u3phy_tuning,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static const struct of_device_id rockchip_u3phy_dt_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) { .compatible = "rockchip,rk3328-u3phy", .data = &rk3328_u3phy_cfgs },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) MODULE_DEVICE_TABLE(of, rockchip_u3phy_dt_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) static struct platform_driver rockchip_u3phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) .probe = rockchip_u3phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) .name = "rockchip-u3phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) .of_match_table = rockchip_u3phy_dt_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) module_platform_driver(rockchip_u3phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) MODULE_AUTHOR("William Wu <william.wu@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) MODULE_DESCRIPTION("Rockchip USB 3.0 PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) MODULE_LICENSE("GPL v2");