1*f0c40dcdSWu Liang feng /* 2*f0c40dcdSWu Liang feng * Copyright 2017 Rockchip Electronics Co., Ltd 3*f0c40dcdSWu Liang feng * 4*f0c40dcdSWu Liang feng * SPDX-License-Identifier: GPL-2.0+ 5*f0c40dcdSWu Liang feng */ 6*f0c40dcdSWu Liang feng 7*f0c40dcdSWu Liang feng #include <asm/io.h> 8*f0c40dcdSWu Liang feng #include <asm/arch/clock.h> 9*f0c40dcdSWu Liang feng #include <common.h> 10*f0c40dcdSWu Liang feng #include <dm.h> 11*f0c40dcdSWu Liang feng #include <generic-phy.h> 12*f0c40dcdSWu Liang feng #include <syscon.h> 13*f0c40dcdSWu Liang feng 14*f0c40dcdSWu Liang feng #define U2PHY_BIT_WRITEABLE_SHIFT 16 15*f0c40dcdSWu Liang feng #define CHG_DCD_MAX_RETRIES 6 16*f0c40dcdSWu Liang feng #define CHG_PRI_MAX_RETRIES 2 17*f0c40dcdSWu Liang feng #define CHG_DCD_POLL_TIME 100 /* millisecond */ 18*f0c40dcdSWu Liang feng #define CHG_PRIMARY_DET_TIME 40 /* millisecond */ 19*f0c40dcdSWu Liang feng #define CHG_SECONDARY_DET_TIME 40 /* millisecond */ 20*f0c40dcdSWu Liang feng 21*f0c40dcdSWu Liang feng struct rockchip_usb2phy; 22*f0c40dcdSWu Liang feng 23*f0c40dcdSWu Liang feng enum power_supply_type { 24*f0c40dcdSWu Liang feng POWER_SUPPLY_TYPE_UNKNOWN = 0, 25*f0c40dcdSWu Liang feng POWER_SUPPLY_TYPE_USB, /* Standard Downstream Port */ 26*f0c40dcdSWu Liang feng POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */ 27*f0c40dcdSWu Liang feng POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */ 28*f0c40dcdSWu Liang feng POWER_SUPPLY_TYPE_USB_FLOATING, /* DCP without shorting D+/D- */ 29*f0c40dcdSWu Liang feng }; 30*f0c40dcdSWu Liang feng 31*f0c40dcdSWu Liang feng enum rockchip_usb2phy_port_id { 32*f0c40dcdSWu Liang feng USB2PHY_PORT_OTG, 33*f0c40dcdSWu Liang feng USB2PHY_PORT_HOST, 34*f0c40dcdSWu Liang feng USB2PHY_NUM_PORTS, 35*f0c40dcdSWu Liang feng }; 36*f0c40dcdSWu Liang feng 37*f0c40dcdSWu Liang feng struct usb2phy_reg { 38*f0c40dcdSWu Liang feng u32 offset; 39*f0c40dcdSWu Liang feng u32 bitend; 40*f0c40dcdSWu Liang feng u32 bitstart; 41*f0c40dcdSWu Liang feng u32 disable; 42*f0c40dcdSWu Liang feng u32 enable; 43*f0c40dcdSWu Liang feng }; 44*f0c40dcdSWu Liang feng 45*f0c40dcdSWu Liang feng /** 46*f0c40dcdSWu Liang feng * struct rockchip_chg_det_reg: usb charger detect registers 47*f0c40dcdSWu Liang feng * @cp_det: charging port detected successfully. 48*f0c40dcdSWu Liang feng * @dcp_det: dedicated charging port detected successfully. 49*f0c40dcdSWu Liang feng * @dp_det: assert data pin connect successfully. 50*f0c40dcdSWu Liang feng * @idm_sink_en: open dm sink curren. 51*f0c40dcdSWu Liang feng * @idp_sink_en: open dp sink current. 52*f0c40dcdSWu Liang feng * @idp_src_en: open dm source current. 53*f0c40dcdSWu Liang feng * @rdm_pdwn_en: open dm pull down resistor. 54*f0c40dcdSWu Liang feng * @vdm_src_en: open dm voltage source. 55*f0c40dcdSWu Liang feng * @vdp_src_en: open dp voltage source. 56*f0c40dcdSWu Liang feng * @opmode: utmi operational mode. 57*f0c40dcdSWu Liang feng */ 58*f0c40dcdSWu Liang feng struct rockchip_chg_det_reg { 59*f0c40dcdSWu Liang feng struct usb2phy_reg cp_det; 60*f0c40dcdSWu Liang feng struct usb2phy_reg dcp_det; 61*f0c40dcdSWu Liang feng struct usb2phy_reg dp_det; 62*f0c40dcdSWu Liang feng struct usb2phy_reg idm_sink_en; 63*f0c40dcdSWu Liang feng struct usb2phy_reg idp_sink_en; 64*f0c40dcdSWu Liang feng struct usb2phy_reg idp_src_en; 65*f0c40dcdSWu Liang feng struct usb2phy_reg rdm_pdwn_en; 66*f0c40dcdSWu Liang feng struct usb2phy_reg vdm_src_en; 67*f0c40dcdSWu Liang feng struct usb2phy_reg vdp_src_en; 68*f0c40dcdSWu Liang feng struct usb2phy_reg opmode; 69*f0c40dcdSWu Liang feng }; 70*f0c40dcdSWu Liang feng 71*f0c40dcdSWu Liang feng /** 72*f0c40dcdSWu Liang feng * struct rockchip_usb2phy_port_cfg: usb-phy port configuration. 73*f0c40dcdSWu Liang feng * @phy_sus: phy suspend register. 74*f0c40dcdSWu Liang feng * @bvalid_det_en: vbus valid rise detection enable register. 75*f0c40dcdSWu Liang feng * @bvalid_det_st: vbus valid rise detection status register. 76*f0c40dcdSWu Liang feng * @bvalid_det_clr: vbus valid rise detection clear register. 77*f0c40dcdSWu Liang feng * @ls_det_en: linestate detection enable register. 78*f0c40dcdSWu Liang feng * @ls_det_st: linestate detection state register. 79*f0c40dcdSWu Liang feng * @ls_det_clr: linestate detection clear register. 80*f0c40dcdSWu Liang feng * @iddig_output: iddig output from grf. 81*f0c40dcdSWu Liang feng * @iddig_en: utmi iddig select between grf and phy, 82*f0c40dcdSWu Liang feng * 0: from phy; 1: from grf 83*f0c40dcdSWu Liang feng * @idfall_det_en: id fall detection enable register. 84*f0c40dcdSWu Liang feng * @idfall_det_st: id fall detection state register. 85*f0c40dcdSWu Liang feng * @idfall_det_clr: id fall detection clear register. 86*f0c40dcdSWu Liang feng * @idrise_det_en: id rise detection enable register. 87*f0c40dcdSWu Liang feng * @idrise_det_st: id rise detection state register. 88*f0c40dcdSWu Liang feng * @idrise_det_clr: id rise detection clear register. 89*f0c40dcdSWu Liang feng * @utmi_avalid: utmi vbus avalid status register. 90*f0c40dcdSWu Liang feng * @utmi_bvalid: utmi vbus bvalid status register. 91*f0c40dcdSWu Liang feng * @utmi_iddig: otg port id pin status register. 92*f0c40dcdSWu Liang feng * @utmi_ls: utmi linestate state register. 93*f0c40dcdSWu Liang feng * @utmi_hstdet: utmi host disconnect register. 94*f0c40dcdSWu Liang feng * @vbus_det_en: vbus detect function power down register. 95*f0c40dcdSWu Liang feng */ 96*f0c40dcdSWu Liang feng struct rockchip_usb2phy_port_cfg { 97*f0c40dcdSWu Liang feng struct usb2phy_reg phy_sus; 98*f0c40dcdSWu Liang feng struct usb2phy_reg bvalid_det_en; 99*f0c40dcdSWu Liang feng struct usb2phy_reg bvalid_det_st; 100*f0c40dcdSWu Liang feng struct usb2phy_reg bvalid_det_clr; 101*f0c40dcdSWu Liang feng struct usb2phy_reg ls_det_en; 102*f0c40dcdSWu Liang feng struct usb2phy_reg ls_det_st; 103*f0c40dcdSWu Liang feng struct usb2phy_reg ls_det_clr; 104*f0c40dcdSWu Liang feng struct usb2phy_reg iddig_output; 105*f0c40dcdSWu Liang feng struct usb2phy_reg iddig_en; 106*f0c40dcdSWu Liang feng struct usb2phy_reg idfall_det_en; 107*f0c40dcdSWu Liang feng struct usb2phy_reg idfall_det_st; 108*f0c40dcdSWu Liang feng struct usb2phy_reg idfall_det_clr; 109*f0c40dcdSWu Liang feng struct usb2phy_reg idrise_det_en; 110*f0c40dcdSWu Liang feng struct usb2phy_reg idrise_det_st; 111*f0c40dcdSWu Liang feng struct usb2phy_reg idrise_det_clr; 112*f0c40dcdSWu Liang feng struct usb2phy_reg utmi_avalid; 113*f0c40dcdSWu Liang feng struct usb2phy_reg utmi_bvalid; 114*f0c40dcdSWu Liang feng struct usb2phy_reg utmi_iddig; 115*f0c40dcdSWu Liang feng struct usb2phy_reg utmi_ls; 116*f0c40dcdSWu Liang feng struct usb2phy_reg utmi_hstdet; 117*f0c40dcdSWu Liang feng struct usb2phy_reg vbus_det_en; 118*f0c40dcdSWu Liang feng }; 119*f0c40dcdSWu Liang feng 120*f0c40dcdSWu Liang feng /** 121*f0c40dcdSWu Liang feng * struct rockchip_usb2phy_cfg: usb-phy configuration. 122*f0c40dcdSWu Liang feng * @reg: the address offset of grf for usb-phy config. 123*f0c40dcdSWu Liang feng * @num_ports: specify how many ports that the phy has. 124*f0c40dcdSWu Liang feng * @phy_tuning: phy default parameters tunning. 125*f0c40dcdSWu Liang feng * @clkout_ctl: keep on/turn off output clk of phy. 126*f0c40dcdSWu Liang feng * @chg_det: charger detection registers. 127*f0c40dcdSWu Liang feng */ 128*f0c40dcdSWu Liang feng struct rockchip_usb2phy_cfg { 129*f0c40dcdSWu Liang feng u32 reg; 130*f0c40dcdSWu Liang feng u32 num_ports; 131*f0c40dcdSWu Liang feng int (*phy_tuning)(struct rockchip_usb2phy *); 132*f0c40dcdSWu Liang feng struct usb2phy_reg clkout_ctl; 133*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; 134*f0c40dcdSWu Liang feng const struct rockchip_chg_det_reg chg_det; 135*f0c40dcdSWu Liang feng }; 136*f0c40dcdSWu Liang feng 137*f0c40dcdSWu Liang feng /** 138*f0c40dcdSWu Liang feng * @dcd_retries: The retry count used to track Data contact 139*f0c40dcdSWu Liang feng * detection process. 140*f0c40dcdSWu Liang feng * @primary_retries: The retry count used to do usb bc detection 141*f0c40dcdSWu Liang feng * primary stage. 142*f0c40dcdSWu Liang feng * @grf: General Register Files register base. 143*f0c40dcdSWu Liang feng * @usbgrf_base : USB General Register Files register base. 144*f0c40dcdSWu Liang feng * @phy_cfg: phy register configuration, assigned by driver data. 145*f0c40dcdSWu Liang feng */ 146*f0c40dcdSWu Liang feng struct rockchip_usb2phy { 147*f0c40dcdSWu Liang feng u8 dcd_retries; 148*f0c40dcdSWu Liang feng u8 primary_retries; 149*f0c40dcdSWu Liang feng void __iomem *grf_base; 150*f0c40dcdSWu Liang feng void __iomem *usbgrf_base; 151*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_cfg *phy_cfg; 152*f0c40dcdSWu Liang feng }; 153*f0c40dcdSWu Liang feng 154*f0c40dcdSWu Liang feng static inline void __iomem *get_reg_base(struct rockchip_usb2phy *rphy) 155*f0c40dcdSWu Liang feng { 156*f0c40dcdSWu Liang feng return !rphy->usbgrf_base ? rphy->grf_base : rphy->usbgrf_base; 157*f0c40dcdSWu Liang feng } 158*f0c40dcdSWu Liang feng 159*f0c40dcdSWu Liang feng static inline int property_enable(void __iomem *base, 160*f0c40dcdSWu Liang feng const struct usb2phy_reg *reg, bool en) 161*f0c40dcdSWu Liang feng { 162*f0c40dcdSWu Liang feng u32 val, mask, tmp; 163*f0c40dcdSWu Liang feng 164*f0c40dcdSWu Liang feng tmp = en ? reg->enable : reg->disable; 165*f0c40dcdSWu Liang feng mask = GENMASK(reg->bitend, reg->bitstart); 166*f0c40dcdSWu Liang feng val = (tmp << reg->bitstart) | (mask << U2PHY_BIT_WRITEABLE_SHIFT); 167*f0c40dcdSWu Liang feng 168*f0c40dcdSWu Liang feng return writel(val, base + reg->offset); 169*f0c40dcdSWu Liang feng } 170*f0c40dcdSWu Liang feng 171*f0c40dcdSWu Liang feng static inline bool property_enabled(void __iomem *base, 172*f0c40dcdSWu Liang feng const struct usb2phy_reg *reg) 173*f0c40dcdSWu Liang feng { 174*f0c40dcdSWu Liang feng u32 tmp, orig; 175*f0c40dcdSWu Liang feng u32 mask = GENMASK(reg->bitend, reg->bitstart); 176*f0c40dcdSWu Liang feng 177*f0c40dcdSWu Liang feng orig = readl(base + reg->offset); 178*f0c40dcdSWu Liang feng 179*f0c40dcdSWu Liang feng tmp = (orig & mask) >> reg->bitstart; 180*f0c40dcdSWu Liang feng 181*f0c40dcdSWu Liang feng return tmp == reg->enable; 182*f0c40dcdSWu Liang feng } 183*f0c40dcdSWu Liang feng 184*f0c40dcdSWu Liang feng static const char *chg_to_string(enum power_supply_type chg_type) 185*f0c40dcdSWu Liang feng { 186*f0c40dcdSWu Liang feng switch (chg_type) { 187*f0c40dcdSWu Liang feng case POWER_SUPPLY_TYPE_USB: 188*f0c40dcdSWu Liang feng return "USB_SDP_CHARGER"; 189*f0c40dcdSWu Liang feng case POWER_SUPPLY_TYPE_USB_DCP: 190*f0c40dcdSWu Liang feng return "USB_DCP_CHARGER"; 191*f0c40dcdSWu Liang feng case POWER_SUPPLY_TYPE_USB_CDP: 192*f0c40dcdSWu Liang feng return "USB_CDP_CHARGER"; 193*f0c40dcdSWu Liang feng case POWER_SUPPLY_TYPE_USB_FLOATING: 194*f0c40dcdSWu Liang feng return "USB_FLOATING_CHARGER"; 195*f0c40dcdSWu Liang feng default: 196*f0c40dcdSWu Liang feng return "INVALID_CHARGER"; 197*f0c40dcdSWu Liang feng } 198*f0c40dcdSWu Liang feng } 199*f0c40dcdSWu Liang feng 200*f0c40dcdSWu Liang feng static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, 201*f0c40dcdSWu Liang feng bool en) 202*f0c40dcdSWu Liang feng { 203*f0c40dcdSWu Liang feng void __iomem *base = get_reg_base(rphy); 204*f0c40dcdSWu Liang feng 205*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); 206*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); 207*f0c40dcdSWu Liang feng } 208*f0c40dcdSWu Liang feng 209*f0c40dcdSWu Liang feng static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy, 210*f0c40dcdSWu Liang feng bool en) 211*f0c40dcdSWu Liang feng { 212*f0c40dcdSWu Liang feng void __iomem *base = get_reg_base(rphy); 213*f0c40dcdSWu Liang feng 214*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); 215*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); 216*f0c40dcdSWu Liang feng } 217*f0c40dcdSWu Liang feng 218*f0c40dcdSWu Liang feng static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy, 219*f0c40dcdSWu Liang feng bool en) 220*f0c40dcdSWu Liang feng { 221*f0c40dcdSWu Liang feng void __iomem *base = get_reg_base(rphy); 222*f0c40dcdSWu Liang feng 223*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); 224*f0c40dcdSWu Liang feng property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); 225*f0c40dcdSWu Liang feng } 226*f0c40dcdSWu Liang feng 227*f0c40dcdSWu Liang feng static bool rockchip_chg_primary_det_retry(struct rockchip_usb2phy *rphy) 228*f0c40dcdSWu Liang feng { 229*f0c40dcdSWu Liang feng bool vout = false; 230*f0c40dcdSWu Liang feng 231*f0c40dcdSWu Liang feng while (rphy->primary_retries--) { 232*f0c40dcdSWu Liang feng /* voltage source on DP, probe on DM */ 233*f0c40dcdSWu Liang feng rockchip_chg_enable_primary_det(rphy, true); 234*f0c40dcdSWu Liang feng mdelay(CHG_PRIMARY_DET_TIME); 235*f0c40dcdSWu Liang feng vout = property_enabled(rphy->grf_base, 236*f0c40dcdSWu Liang feng &rphy->phy_cfg->chg_det.cp_det); 237*f0c40dcdSWu Liang feng if (vout) 238*f0c40dcdSWu Liang feng break; 239*f0c40dcdSWu Liang feng } 240*f0c40dcdSWu Liang feng 241*f0c40dcdSWu Liang feng return vout; 242*f0c40dcdSWu Liang feng } 243*f0c40dcdSWu Liang feng 244*f0c40dcdSWu Liang feng int rockchip_chg_get_type(void) 245*f0c40dcdSWu Liang feng { 246*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_cfg *phy_cfgs; 247*f0c40dcdSWu Liang feng enum power_supply_type chg_type; 248*f0c40dcdSWu Liang feng struct rockchip_usb2phy rphy; 249*f0c40dcdSWu Liang feng struct udevice *dev; 250*f0c40dcdSWu Liang feng ofnode u2phy_node, grf_node; 251*f0c40dcdSWu Liang feng fdt_size_t size; 252*f0c40dcdSWu Liang feng u32 reg, index; 253*f0c40dcdSWu Liang feng bool is_dcd, vout; 254*f0c40dcdSWu Liang feng int ret; 255*f0c40dcdSWu Liang feng 256*f0c40dcdSWu Liang feng u2phy_node = ofnode_null(); 257*f0c40dcdSWu Liang feng grf_node = ofnode_null(); 258*f0c40dcdSWu Liang feng 259*f0c40dcdSWu Liang feng u2phy_node = ofnode_path("/usb2-phy"); 260*f0c40dcdSWu Liang feng 261*f0c40dcdSWu Liang feng if (!ofnode_valid(u2phy_node)) { 262*f0c40dcdSWu Liang feng grf_node = ofnode_path("/syscon-usb"); 263*f0c40dcdSWu Liang feng if (ofnode_valid(grf_node)) 264*f0c40dcdSWu Liang feng u2phy_node = ofnode_find_subnode(grf_node, 265*f0c40dcdSWu Liang feng "usb2-phy"); 266*f0c40dcdSWu Liang feng } 267*f0c40dcdSWu Liang feng 268*f0c40dcdSWu Liang feng if (!ofnode_valid(u2phy_node)) { 269*f0c40dcdSWu Liang feng printf("%s: missing u2phy node\n", __func__); 270*f0c40dcdSWu Liang feng return -EINVAL; 271*f0c40dcdSWu Liang feng } 272*f0c40dcdSWu Liang feng 273*f0c40dcdSWu Liang feng if (ofnode_valid(grf_node)) { 274*f0c40dcdSWu Liang feng rphy.grf_base = 275*f0c40dcdSWu Liang feng (void __iomem *)ofnode_get_addr_size(grf_node, 276*f0c40dcdSWu Liang feng "reg", &size); 277*f0c40dcdSWu Liang feng } else { 278*f0c40dcdSWu Liang feng if (ofnode_read_bool(u2phy_node, "rockchip,grf")) 279*f0c40dcdSWu Liang feng rphy.grf_base = 280*f0c40dcdSWu Liang feng syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 281*f0c40dcdSWu Liang feng } 282*f0c40dcdSWu Liang feng 283*f0c40dcdSWu Liang feng if (rphy.grf_base <= 0) { 284*f0c40dcdSWu Liang feng dev_err(dev, "get syscon grf failed\n"); 285*f0c40dcdSWu Liang feng return -EINVAL; 286*f0c40dcdSWu Liang feng } 287*f0c40dcdSWu Liang feng 288*f0c40dcdSWu Liang feng if (ofnode_read_u32(u2phy_node, "reg", ®)) { 289*f0c40dcdSWu Liang feng printf("%s: could not read reg\n", __func__); 290*f0c40dcdSWu Liang feng return -EINVAL; 291*f0c40dcdSWu Liang feng } 292*f0c40dcdSWu Liang feng 293*f0c40dcdSWu Liang feng if (ofnode_read_bool(u2phy_node, "rockchip,usbgrf")) { 294*f0c40dcdSWu Liang feng rphy.usbgrf_base = 295*f0c40dcdSWu Liang feng syscon_get_first_range(ROCKCHIP_SYSCON_USBGRF); 296*f0c40dcdSWu Liang feng if (rphy.usbgrf_base <= 0) { 297*f0c40dcdSWu Liang feng dev_err(dev, "get syscon usbgrf failed\n"); 298*f0c40dcdSWu Liang feng return -EINVAL; 299*f0c40dcdSWu Liang feng } 300*f0c40dcdSWu Liang feng } else { 301*f0c40dcdSWu Liang feng rphy.usbgrf_base = NULL; 302*f0c40dcdSWu Liang feng } 303*f0c40dcdSWu Liang feng 304*f0c40dcdSWu Liang feng ret = uclass_get_device_by_ofnode(UCLASS_PHY, u2phy_node, &dev); 305*f0c40dcdSWu Liang feng if (ret) { 306*f0c40dcdSWu Liang feng printf("%s: uclass_get_device_by_ofnode failed: %d\n", 307*f0c40dcdSWu Liang feng __func__, ret); 308*f0c40dcdSWu Liang feng return ret; 309*f0c40dcdSWu Liang feng } 310*f0c40dcdSWu Liang feng 311*f0c40dcdSWu Liang feng phy_cfgs = 312*f0c40dcdSWu Liang feng (const struct rockchip_usb2phy_cfg *)dev_get_driver_data(dev); 313*f0c40dcdSWu Liang feng if (!phy_cfgs) { 314*f0c40dcdSWu Liang feng printf("%s: unable to get phy_cfgs\n", __func__); 315*f0c40dcdSWu Liang feng return -EINVAL; 316*f0c40dcdSWu Liang feng } 317*f0c40dcdSWu Liang feng 318*f0c40dcdSWu Liang feng /* find out a proper config which can be matched with dt. */ 319*f0c40dcdSWu Liang feng index = 0; 320*f0c40dcdSWu Liang feng while (phy_cfgs[index].reg) { 321*f0c40dcdSWu Liang feng if (phy_cfgs[index].reg == reg) { 322*f0c40dcdSWu Liang feng rphy.phy_cfg = &phy_cfgs[index]; 323*f0c40dcdSWu Liang feng break; 324*f0c40dcdSWu Liang feng } 325*f0c40dcdSWu Liang feng ++index; 326*f0c40dcdSWu Liang feng } 327*f0c40dcdSWu Liang feng 328*f0c40dcdSWu Liang feng if (!rphy.phy_cfg) { 329*f0c40dcdSWu Liang feng printf("%s: no phy-config can be matched\n", __func__); 330*f0c40dcdSWu Liang feng return -EINVAL; 331*f0c40dcdSWu Liang feng } 332*f0c40dcdSWu Liang feng 333*f0c40dcdSWu Liang feng rphy.dcd_retries = CHG_DCD_MAX_RETRIES; 334*f0c40dcdSWu Liang feng rphy.primary_retries = CHG_PRI_MAX_RETRIES; 335*f0c40dcdSWu Liang feng 336*f0c40dcdSWu Liang feng /* stage 1, start DCD processing stage */ 337*f0c40dcdSWu Liang feng rockchip_chg_enable_dcd(&rphy, true); 338*f0c40dcdSWu Liang feng 339*f0c40dcdSWu Liang feng while (rphy.dcd_retries--) { 340*f0c40dcdSWu Liang feng mdelay(CHG_DCD_POLL_TIME); 341*f0c40dcdSWu Liang feng 342*f0c40dcdSWu Liang feng /* get data contact detection status */ 343*f0c40dcdSWu Liang feng is_dcd = property_enabled(rphy.grf_base, 344*f0c40dcdSWu Liang feng &rphy.phy_cfg->chg_det.dp_det); 345*f0c40dcdSWu Liang feng 346*f0c40dcdSWu Liang feng if (is_dcd || !rphy.dcd_retries) { 347*f0c40dcdSWu Liang feng /* 348*f0c40dcdSWu Liang feng * stage 2, turn off DCD circuitry, then 349*f0c40dcdSWu Liang feng * voltage source on DP, probe on DM. 350*f0c40dcdSWu Liang feng */ 351*f0c40dcdSWu Liang feng rockchip_chg_enable_dcd(&rphy, false); 352*f0c40dcdSWu Liang feng rockchip_chg_enable_primary_det(&rphy, true); 353*f0c40dcdSWu Liang feng break; 354*f0c40dcdSWu Liang feng } 355*f0c40dcdSWu Liang feng } 356*f0c40dcdSWu Liang feng 357*f0c40dcdSWu Liang feng mdelay(CHG_PRIMARY_DET_TIME); 358*f0c40dcdSWu Liang feng vout = property_enabled(rphy.grf_base, 359*f0c40dcdSWu Liang feng &rphy.phy_cfg->chg_det.cp_det); 360*f0c40dcdSWu Liang feng rockchip_chg_enable_primary_det(&rphy, false); 361*f0c40dcdSWu Liang feng if (vout) { 362*f0c40dcdSWu Liang feng /* stage 3, voltage source on DM, probe on DP */ 363*f0c40dcdSWu Liang feng rockchip_chg_enable_secondary_det(&rphy, true); 364*f0c40dcdSWu Liang feng } else { 365*f0c40dcdSWu Liang feng if (!rphy.dcd_retries) { 366*f0c40dcdSWu Liang feng /* floating charger found */ 367*f0c40dcdSWu Liang feng chg_type = POWER_SUPPLY_TYPE_USB_FLOATING; 368*f0c40dcdSWu Liang feng goto out; 369*f0c40dcdSWu Liang feng } else { 370*f0c40dcdSWu Liang feng /* 371*f0c40dcdSWu Liang feng * Retry some times to make sure that it's 372*f0c40dcdSWu Liang feng * really a USB SDP charger. 373*f0c40dcdSWu Liang feng */ 374*f0c40dcdSWu Liang feng vout = rockchip_chg_primary_det_retry(&rphy); 375*f0c40dcdSWu Liang feng if (vout) { 376*f0c40dcdSWu Liang feng /* stage 3, voltage source on DM, probe on DP */ 377*f0c40dcdSWu Liang feng rockchip_chg_enable_secondary_det(&rphy, true); 378*f0c40dcdSWu Liang feng } else { 379*f0c40dcdSWu Liang feng /* USB SDP charger found */ 380*f0c40dcdSWu Liang feng chg_type = POWER_SUPPLY_TYPE_USB; 381*f0c40dcdSWu Liang feng goto out; 382*f0c40dcdSWu Liang feng } 383*f0c40dcdSWu Liang feng } 384*f0c40dcdSWu Liang feng } 385*f0c40dcdSWu Liang feng 386*f0c40dcdSWu Liang feng mdelay(CHG_SECONDARY_DET_TIME); 387*f0c40dcdSWu Liang feng vout = property_enabled(rphy.grf_base, 388*f0c40dcdSWu Liang feng &rphy.phy_cfg->chg_det.dcp_det); 389*f0c40dcdSWu Liang feng /* stage 4, turn off voltage source */ 390*f0c40dcdSWu Liang feng rockchip_chg_enable_secondary_det(&rphy, false); 391*f0c40dcdSWu Liang feng if (vout) 392*f0c40dcdSWu Liang feng chg_type = POWER_SUPPLY_TYPE_USB_DCP; 393*f0c40dcdSWu Liang feng else 394*f0c40dcdSWu Liang feng chg_type = POWER_SUPPLY_TYPE_USB_CDP; 395*f0c40dcdSWu Liang feng 396*f0c40dcdSWu Liang feng out: 397*f0c40dcdSWu Liang feng printf("charger is %s\n", chg_to_string(chg_type)); 398*f0c40dcdSWu Liang feng 399*f0c40dcdSWu Liang feng return chg_type; 400*f0c40dcdSWu Liang feng } 401*f0c40dcdSWu Liang feng 402*f0c40dcdSWu Liang feng static int rockchip_usb2phy_init(struct phy *phy) 403*f0c40dcdSWu Liang feng { 404*f0c40dcdSWu Liang feng struct rockchip_usb2phy *rphy; 405*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_port_cfg *port_cfg; 406*f0c40dcdSWu Liang feng void __iomem *base; 407*f0c40dcdSWu Liang feng 408*f0c40dcdSWu Liang feng rphy = dev_get_priv(phy->dev); 409*f0c40dcdSWu Liang feng base = get_reg_base(rphy); 410*f0c40dcdSWu Liang feng 411*f0c40dcdSWu Liang feng if (phy->id == USB2PHY_PORT_OTG) { 412*f0c40dcdSWu Liang feng port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; 413*f0c40dcdSWu Liang feng } else if (phy->id == USB2PHY_PORT_HOST) { 414*f0c40dcdSWu Liang feng port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; 415*f0c40dcdSWu Liang feng } else { 416*f0c40dcdSWu Liang feng dev_err(phy->dev, "phy id %lu not support", phy->id); 417*f0c40dcdSWu Liang feng return -EINVAL; 418*f0c40dcdSWu Liang feng } 419*f0c40dcdSWu Liang feng 420*f0c40dcdSWu Liang feng property_enable(base, &port_cfg->phy_sus, false); 421*f0c40dcdSWu Liang feng 422*f0c40dcdSWu Liang feng /* waiting for the utmi_clk to become stable */ 423*f0c40dcdSWu Liang feng udelay(2000); 424*f0c40dcdSWu Liang feng 425*f0c40dcdSWu Liang feng return 0; 426*f0c40dcdSWu Liang feng } 427*f0c40dcdSWu Liang feng 428*f0c40dcdSWu Liang feng static int rockchip_usb2phy_exit(struct phy *phy) 429*f0c40dcdSWu Liang feng { 430*f0c40dcdSWu Liang feng struct rockchip_usb2phy *rphy; 431*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_port_cfg *port_cfg; 432*f0c40dcdSWu Liang feng void __iomem *base; 433*f0c40dcdSWu Liang feng 434*f0c40dcdSWu Liang feng rphy = dev_get_priv(phy->dev); 435*f0c40dcdSWu Liang feng base = get_reg_base(rphy); 436*f0c40dcdSWu Liang feng 437*f0c40dcdSWu Liang feng if (phy->id == USB2PHY_PORT_OTG) { 438*f0c40dcdSWu Liang feng port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; 439*f0c40dcdSWu Liang feng } else if (phy->id == USB2PHY_PORT_HOST) { 440*f0c40dcdSWu Liang feng port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; 441*f0c40dcdSWu Liang feng } else { 442*f0c40dcdSWu Liang feng dev_err(phy->dev, "phy id %lu not support", phy->id); 443*f0c40dcdSWu Liang feng return -EINVAL; 444*f0c40dcdSWu Liang feng } 445*f0c40dcdSWu Liang feng 446*f0c40dcdSWu Liang feng property_enable(base, &port_cfg->phy_sus, true); 447*f0c40dcdSWu Liang feng 448*f0c40dcdSWu Liang feng return 0; 449*f0c40dcdSWu Liang feng } 450*f0c40dcdSWu Liang feng 451*f0c40dcdSWu Liang feng static int rockchip_usb2phy_probe(struct udevice *dev) 452*f0c40dcdSWu Liang feng { 453*f0c40dcdSWu Liang feng const struct rockchip_usb2phy_cfg *phy_cfgs; 454*f0c40dcdSWu Liang feng struct rockchip_usb2phy *rphy; 455*f0c40dcdSWu Liang feng struct udevice *parent; 456*f0c40dcdSWu Liang feng u32 reg, index; 457*f0c40dcdSWu Liang feng 458*f0c40dcdSWu Liang feng rphy = dev_get_priv(dev); 459*f0c40dcdSWu Liang feng 460*f0c40dcdSWu Liang feng parent = dev_get_parent(dev); 461*f0c40dcdSWu Liang feng if (!parent) { 462*f0c40dcdSWu Liang feng dev_dbg(dev, "could not find u2phy parent\n"); 463*f0c40dcdSWu Liang feng if (ofnode_read_bool(dev_ofnode(dev), "rockchip,grf")) 464*f0c40dcdSWu Liang feng rphy->usbgrf_base = 465*f0c40dcdSWu Liang feng syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 466*f0c40dcdSWu Liang feng } else { 467*f0c40dcdSWu Liang feng rphy->grf_base = 468*f0c40dcdSWu Liang feng (void __iomem *)((uintptr_t)dev_read_addr(parent)); 469*f0c40dcdSWu Liang feng } 470*f0c40dcdSWu Liang feng 471*f0c40dcdSWu Liang feng if (rphy->grf_base <= 0) { 472*f0c40dcdSWu Liang feng dev_err(dev, "get syscon grf failed\n"); 473*f0c40dcdSWu Liang feng return -EINVAL; 474*f0c40dcdSWu Liang feng } 475*f0c40dcdSWu Liang feng 476*f0c40dcdSWu Liang feng if (ofnode_read_u32(dev_ofnode(dev), "reg", ®)) { 477*f0c40dcdSWu Liang feng dev_err(dev, "could not read reg\n"); 478*f0c40dcdSWu Liang feng return -EINVAL; 479*f0c40dcdSWu Liang feng } 480*f0c40dcdSWu Liang feng 481*f0c40dcdSWu Liang feng if (ofnode_read_bool(dev_ofnode(dev), "rockchip,usbgrf")) { 482*f0c40dcdSWu Liang feng rphy->usbgrf_base = 483*f0c40dcdSWu Liang feng syscon_get_first_range(ROCKCHIP_SYSCON_USBGRF); 484*f0c40dcdSWu Liang feng if (rphy->usbgrf_base <= 0) { 485*f0c40dcdSWu Liang feng dev_err(dev, "get syscon usbgrf failed\n"); 486*f0c40dcdSWu Liang feng return -EINVAL; 487*f0c40dcdSWu Liang feng } 488*f0c40dcdSWu Liang feng } else { 489*f0c40dcdSWu Liang feng rphy->usbgrf_base = NULL; 490*f0c40dcdSWu Liang feng } 491*f0c40dcdSWu Liang feng 492*f0c40dcdSWu Liang feng phy_cfgs = 493*f0c40dcdSWu Liang feng (const struct rockchip_usb2phy_cfg *)dev_get_driver_data(dev); 494*f0c40dcdSWu Liang feng if (!phy_cfgs) { 495*f0c40dcdSWu Liang feng dev_err(dev, "unable to get phy_cfgs\n"); 496*f0c40dcdSWu Liang feng return -EINVAL; 497*f0c40dcdSWu Liang feng } 498*f0c40dcdSWu Liang feng 499*f0c40dcdSWu Liang feng /* find out a proper config which can be matched with dt. */ 500*f0c40dcdSWu Liang feng index = 0; 501*f0c40dcdSWu Liang feng while (phy_cfgs[index].reg) { 502*f0c40dcdSWu Liang feng if (phy_cfgs[index].reg == reg) { 503*f0c40dcdSWu Liang feng rphy->phy_cfg = &phy_cfgs[index]; 504*f0c40dcdSWu Liang feng break; 505*f0c40dcdSWu Liang feng } 506*f0c40dcdSWu Liang feng ++index; 507*f0c40dcdSWu Liang feng } 508*f0c40dcdSWu Liang feng 509*f0c40dcdSWu Liang feng if (!rphy->phy_cfg) { 510*f0c40dcdSWu Liang feng dev_err(dev, "no phy-config can be matched\n"); 511*f0c40dcdSWu Liang feng return -EINVAL; 512*f0c40dcdSWu Liang feng } 513*f0c40dcdSWu Liang feng 514*f0c40dcdSWu Liang feng return 0; 515*f0c40dcdSWu Liang feng } 516*f0c40dcdSWu Liang feng 517*f0c40dcdSWu Liang feng static struct phy_ops rockchip_usb2phy_ops = { 518*f0c40dcdSWu Liang feng .init = rockchip_usb2phy_init, 519*f0c40dcdSWu Liang feng .exit = rockchip_usb2phy_exit, 520*f0c40dcdSWu Liang feng }; 521*f0c40dcdSWu Liang feng 522*f0c40dcdSWu Liang feng static const struct rockchip_usb2phy_cfg rk312x_phy_cfgs[] = { 523*f0c40dcdSWu Liang feng { 524*f0c40dcdSWu Liang feng .reg = 0x17c, 525*f0c40dcdSWu Liang feng .num_ports = 2, 526*f0c40dcdSWu Liang feng .clkout_ctl = { 0x0190, 15, 15, 1, 0 }, 527*f0c40dcdSWu Liang feng .port_cfgs = { 528*f0c40dcdSWu Liang feng [USB2PHY_PORT_OTG] = { 529*f0c40dcdSWu Liang feng .phy_sus = { 0x017c, 8, 0, 0, 0x1d1 }, 530*f0c40dcdSWu Liang feng .bvalid_det_en = { 0x017c, 14, 14, 0, 1 }, 531*f0c40dcdSWu Liang feng .bvalid_det_st = { 0x017c, 15, 15, 0, 1 }, 532*f0c40dcdSWu Liang feng .bvalid_det_clr = { 0x017c, 15, 15, 0, 1 }, 533*f0c40dcdSWu Liang feng .iddig_output = { 0x017c, 10, 10, 0, 1 }, 534*f0c40dcdSWu Liang feng .iddig_en = { 0x017c, 9, 9, 0, 1 }, 535*f0c40dcdSWu Liang feng .idfall_det_en = { 0x01a0, 2, 2, 0, 1 }, 536*f0c40dcdSWu Liang feng .idfall_det_st = { 0x01a0, 3, 3, 0, 1 }, 537*f0c40dcdSWu Liang feng .idfall_det_clr = { 0x01a0, 3, 3, 0, 1 }, 538*f0c40dcdSWu Liang feng .idrise_det_en = { 0x01a0, 0, 0, 0, 1 }, 539*f0c40dcdSWu Liang feng .idrise_det_st = { 0x01a0, 1, 1, 0, 1 }, 540*f0c40dcdSWu Liang feng .idrise_det_clr = { 0x01a0, 1, 1, 0, 1 }, 541*f0c40dcdSWu Liang feng .ls_det_en = { 0x017c, 12, 12, 0, 1 }, 542*f0c40dcdSWu Liang feng .ls_det_st = { 0x017c, 13, 13, 0, 1 }, 543*f0c40dcdSWu Liang feng .ls_det_clr = { 0x017c, 13, 13, 0, 1 }, 544*f0c40dcdSWu Liang feng .utmi_bvalid = { 0x014c, 5, 5, 0, 1 }, 545*f0c40dcdSWu Liang feng .utmi_iddig = { 0x014c, 8, 8, 0, 1 }, 546*f0c40dcdSWu Liang feng .utmi_ls = { 0x014c, 7, 6, 0, 1 }, 547*f0c40dcdSWu Liang feng }, 548*f0c40dcdSWu Liang feng [USB2PHY_PORT_HOST] = { 549*f0c40dcdSWu Liang feng .phy_sus = { 0x0194, 8, 0, 0, 0x1d1 }, 550*f0c40dcdSWu Liang feng .ls_det_en = { 0x0194, 14, 14, 0, 1 }, 551*f0c40dcdSWu Liang feng .ls_det_st = { 0x0194, 15, 15, 0, 1 }, 552*f0c40dcdSWu Liang feng .ls_det_clr = { 0x0194, 15, 15, 0, 1 } 553*f0c40dcdSWu Liang feng } 554*f0c40dcdSWu Liang feng }, 555*f0c40dcdSWu Liang feng .chg_det = { 556*f0c40dcdSWu Liang feng .opmode = { 0x017c, 3, 0, 5, 1 }, 557*f0c40dcdSWu Liang feng .cp_det = { 0x02c0, 6, 6, 0, 1 }, 558*f0c40dcdSWu Liang feng .dcp_det = { 0x02c0, 5, 5, 0, 1 }, 559*f0c40dcdSWu Liang feng .dp_det = { 0x02c0, 7, 7, 0, 1 }, 560*f0c40dcdSWu Liang feng .idm_sink_en = { 0x0184, 8, 8, 0, 1 }, 561*f0c40dcdSWu Liang feng .idp_sink_en = { 0x0184, 7, 7, 0, 1 }, 562*f0c40dcdSWu Liang feng .idp_src_en = { 0x0184, 9, 9, 0, 1 }, 563*f0c40dcdSWu Liang feng .rdm_pdwn_en = { 0x0184, 10, 10, 0, 1 }, 564*f0c40dcdSWu Liang feng .vdm_src_en = { 0x0184, 12, 12, 0, 1 }, 565*f0c40dcdSWu Liang feng .vdp_src_en = { 0x0184, 11, 11, 0, 1 }, 566*f0c40dcdSWu Liang feng }, 567*f0c40dcdSWu Liang feng }, 568*f0c40dcdSWu Liang feng { /* sentinel */ } 569*f0c40dcdSWu Liang feng }; 570*f0c40dcdSWu Liang feng 571*f0c40dcdSWu Liang feng static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = { 572*f0c40dcdSWu Liang feng { 573*f0c40dcdSWu Liang feng .reg = 0x100, 574*f0c40dcdSWu Liang feng .num_ports = 2, 575*f0c40dcdSWu Liang feng .clkout_ctl = { 0x108, 4, 4, 1, 0 }, 576*f0c40dcdSWu Liang feng .port_cfgs = { 577*f0c40dcdSWu Liang feng [USB2PHY_PORT_OTG] = { 578*f0c40dcdSWu Liang feng .phy_sus = { 0x0100, 8, 0, 0, 0x1d1 }, 579*f0c40dcdSWu Liang feng .bvalid_det_en = { 0x0110, 2, 2, 0, 1 }, 580*f0c40dcdSWu Liang feng .bvalid_det_st = { 0x0114, 2, 2, 0, 1 }, 581*f0c40dcdSWu Liang feng .bvalid_det_clr = { 0x0118, 2, 2, 0, 1 }, 582*f0c40dcdSWu Liang feng .iddig_output = { 0x0100, 10, 10, 0, 1 }, 583*f0c40dcdSWu Liang feng .iddig_en = { 0x0100, 9, 9, 0, 1 }, 584*f0c40dcdSWu Liang feng .idfall_det_en = { 0x0110, 5, 5, 0, 1 }, 585*f0c40dcdSWu Liang feng .idfall_det_st = { 0x0114, 5, 5, 0, 1 }, 586*f0c40dcdSWu Liang feng .idfall_det_clr = { 0x0118, 5, 5, 0, 1 }, 587*f0c40dcdSWu Liang feng .idrise_det_en = { 0x0110, 4, 4, 0, 1 }, 588*f0c40dcdSWu Liang feng .idrise_det_st = { 0x0114, 4, 4, 0, 1 }, 589*f0c40dcdSWu Liang feng .idrise_det_clr = { 0x0118, 4, 4, 0, 1 }, 590*f0c40dcdSWu Liang feng .ls_det_en = { 0x0110, 0, 0, 0, 1 }, 591*f0c40dcdSWu Liang feng .ls_det_st = { 0x0114, 0, 0, 0, 1 }, 592*f0c40dcdSWu Liang feng .ls_det_clr = { 0x0118, 0, 0, 0, 1 }, 593*f0c40dcdSWu Liang feng .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, 594*f0c40dcdSWu Liang feng .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, 595*f0c40dcdSWu Liang feng .utmi_iddig = { 0x0120, 6, 6, 0, 1 }, 596*f0c40dcdSWu Liang feng .utmi_ls = { 0x0120, 5, 4, 0, 1 }, 597*f0c40dcdSWu Liang feng .vbus_det_en = { 0x001c, 15, 15, 1, 0 }, 598*f0c40dcdSWu Liang feng }, 599*f0c40dcdSWu Liang feng [USB2PHY_PORT_HOST] = { 600*f0c40dcdSWu Liang feng .phy_sus = { 0x104, 8, 0, 0, 0x1d1 }, 601*f0c40dcdSWu Liang feng .ls_det_en = { 0x110, 1, 1, 0, 1 }, 602*f0c40dcdSWu Liang feng .ls_det_st = { 0x114, 1, 1, 0, 1 }, 603*f0c40dcdSWu Liang feng .ls_det_clr = { 0x118, 1, 1, 0, 1 }, 604*f0c40dcdSWu Liang feng .utmi_ls = { 0x120, 17, 16, 0, 1 }, 605*f0c40dcdSWu Liang feng .utmi_hstdet = { 0x120, 19, 19, 0, 1 } 606*f0c40dcdSWu Liang feng } 607*f0c40dcdSWu Liang feng }, 608*f0c40dcdSWu Liang feng .chg_det = { 609*f0c40dcdSWu Liang feng .opmode = { 0x0100, 3, 0, 5, 1 }, 610*f0c40dcdSWu Liang feng .cp_det = { 0x0120, 24, 24, 0, 1 }, 611*f0c40dcdSWu Liang feng .dcp_det = { 0x0120, 23, 23, 0, 1 }, 612*f0c40dcdSWu Liang feng .dp_det = { 0x0120, 25, 25, 0, 1 }, 613*f0c40dcdSWu Liang feng .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, 614*f0c40dcdSWu Liang feng .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, 615*f0c40dcdSWu Liang feng .idp_src_en = { 0x0108, 9, 9, 0, 1 }, 616*f0c40dcdSWu Liang feng .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, 617*f0c40dcdSWu Liang feng .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, 618*f0c40dcdSWu Liang feng .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, 619*f0c40dcdSWu Liang feng }, 620*f0c40dcdSWu Liang feng }, 621*f0c40dcdSWu Liang feng { /* sentinel */ } 622*f0c40dcdSWu Liang feng }; 623*f0c40dcdSWu Liang feng 624*f0c40dcdSWu Liang feng static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { 625*f0c40dcdSWu Liang feng { 626*f0c40dcdSWu Liang feng .reg = 0x100, 627*f0c40dcdSWu Liang feng .num_ports = 2, 628*f0c40dcdSWu Liang feng .clkout_ctl = { 0x108, 4, 4, 1, 0 }, 629*f0c40dcdSWu Liang feng .port_cfgs = { 630*f0c40dcdSWu Liang feng [USB2PHY_PORT_OTG] = { 631*f0c40dcdSWu Liang feng .phy_sus = { 0x0100, 8, 0, 0, 0x1d1 }, 632*f0c40dcdSWu Liang feng .bvalid_det_en = { 0x0680, 3, 3, 0, 1 }, 633*f0c40dcdSWu Liang feng .bvalid_det_st = { 0x0690, 3, 3, 0, 1 }, 634*f0c40dcdSWu Liang feng .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 }, 635*f0c40dcdSWu Liang feng .ls_det_en = { 0x0680, 2, 2, 0, 1 }, 636*f0c40dcdSWu Liang feng .ls_det_st = { 0x0690, 2, 2, 0, 1 }, 637*f0c40dcdSWu Liang feng .ls_det_clr = { 0x06a0, 2, 2, 0, 1 }, 638*f0c40dcdSWu Liang feng .utmi_bvalid = { 0x0804, 10, 10, 0, 1 }, 639*f0c40dcdSWu Liang feng .utmi_ls = { 0x0804, 13, 12, 0, 1 }, 640*f0c40dcdSWu Liang feng }, 641*f0c40dcdSWu Liang feng [USB2PHY_PORT_HOST] = { 642*f0c40dcdSWu Liang feng .phy_sus = { 0x0104, 8, 0, 0, 0x1d1 }, 643*f0c40dcdSWu Liang feng .ls_det_en = { 0x0680, 4, 4, 0, 1 }, 644*f0c40dcdSWu Liang feng .ls_det_st = { 0x0690, 4, 4, 0, 1 }, 645*f0c40dcdSWu Liang feng .ls_det_clr = { 0x06a0, 4, 4, 0, 1 }, 646*f0c40dcdSWu Liang feng .utmi_ls = { 0x0804, 9, 8, 0, 1 }, 647*f0c40dcdSWu Liang feng .utmi_hstdet = { 0x0804, 7, 7, 0, 1 } 648*f0c40dcdSWu Liang feng } 649*f0c40dcdSWu Liang feng }, 650*f0c40dcdSWu Liang feng .chg_det = { 651*f0c40dcdSWu Liang feng .opmode = { 0x0100, 3, 0, 5, 1 }, 652*f0c40dcdSWu Liang feng .cp_det = { 0x0804, 1, 1, 0, 1 }, 653*f0c40dcdSWu Liang feng .dcp_det = { 0x0804, 0, 0, 0, 1 }, 654*f0c40dcdSWu Liang feng .dp_det = { 0x0804, 2, 2, 0, 1 }, 655*f0c40dcdSWu Liang feng .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, 656*f0c40dcdSWu Liang feng .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, 657*f0c40dcdSWu Liang feng .idp_src_en = { 0x0108, 9, 9, 0, 1 }, 658*f0c40dcdSWu Liang feng .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, 659*f0c40dcdSWu Liang feng .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, 660*f0c40dcdSWu Liang feng .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, 661*f0c40dcdSWu Liang feng }, 662*f0c40dcdSWu Liang feng }, 663*f0c40dcdSWu Liang feng { /* sentinel */ } 664*f0c40dcdSWu Liang feng }; 665*f0c40dcdSWu Liang feng 666*f0c40dcdSWu Liang feng static const struct udevice_id rockchip_usb2phy_ids[] = { 667*f0c40dcdSWu Liang feng { .compatible = "rockchip,rk3128-usb2phy", .data = (ulong)&rk312x_phy_cfgs }, 668*f0c40dcdSWu Liang feng { .compatible = "rockchip,rk3328-usb2phy", .data = (ulong)&rk3328_phy_cfgs }, 669*f0c40dcdSWu Liang feng { .compatible = "rockchip,rv1108-usb2phy", .data = (ulong)&rv1108_phy_cfgs }, 670*f0c40dcdSWu Liang feng { } 671*f0c40dcdSWu Liang feng }; 672*f0c40dcdSWu Liang feng 673*f0c40dcdSWu Liang feng U_BOOT_DRIVER(rockchip_usb2phy) = { 674*f0c40dcdSWu Liang feng .name = "rockchip_usb2phy", 675*f0c40dcdSWu Liang feng .id = UCLASS_PHY, 676*f0c40dcdSWu Liang feng .of_match = rockchip_usb2phy_ids, 677*f0c40dcdSWu Liang feng .ops = &rockchip_usb2phy_ops, 678*f0c40dcdSWu Liang feng .probe = rockchip_usb2phy_probe, 679*f0c40dcdSWu Liang feng .priv_auto_alloc_size = sizeof(struct rockchip_usb2phy), 680*f0c40dcdSWu Liang feng }; 681