File Index
Files and directories
Sign in
FILE

phy-rockchip-inno-usb2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/phy/rockchip/phy-rockchip-inno-usb2.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Rockchip USB2.0 PHY with Innosilicon IP block driver
   4 *
   5 * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/clk-provider.h>
  10#include <linux/delay.h>
  11#include <linux/extcon-provider.h>
  12#include <linux/interrupt.h>
  13#include <linux/io.h>
  14#include <linux/gpio/consumer.h>
  15#include <linux/jiffies.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/mutex.h>
  19#include <linux/of.h>
  20#include <linux/of_irq.h>
  21#include <linux/phy/phy.h>
  22#include <linux/platform_device.h>
  23#include <linux/power_supply.h>
  24#include <linux/regmap.h>
  25#include <linux/reset.h>
  26#include <linux/mfd/syscon.h>
  27#include <linux/usb/of.h>
  28#include <linux/usb/otg.h>
  29
  30#define BIT_WRITEABLE_SHIFT	16
  31#define SCHEDULE_DELAY		(60 * HZ)
  32#define OTG_SCHEDULE_DELAY	(2 * HZ)
  33
  34struct rockchip_usb2phy;
  35
  36enum rockchip_usb2phy_port_id {
  37	USB2PHY_PORT_OTG,
  38	USB2PHY_PORT_HOST,
  39	USB2PHY_NUM_PORTS,
  40};
  41
  42enum rockchip_usb2phy_host_state {
  43	PHY_STATE_HS_ONLINE	= 0,
  44	PHY_STATE_DISCONNECT	= 1,
  45	PHY_STATE_CONNECT	= 2,
  46	PHY_STATE_FS_LS_ONLINE	= 4,
  47};
  48
  49/**
  50 * enum usb_chg_state - Different states involved in USB charger detection.
  51 * @USB_CHG_STATE_UNDEFINED:	USB charger is not connected or detection
  52 *				process is not yet started.
  53 * @USB_CHG_STATE_WAIT_FOR_DCD:	Waiting for Data pins contact.
  54 * @USB_CHG_STATE_DCD_DONE:	Data pin contact is detected.
  55 * @USB_CHG_STATE_PRIMARY_DONE:	Primary detection is completed (Detects
  56 *				between SDP and DCP/CDP).
  57 * @USB_CHG_STATE_SECONDARY_DONE: Secondary detection is completed (Detects
  58 *				  between DCP and CDP).
  59 * @USB_CHG_STATE_DETECTED:	USB charger type is determined.
  60 */
  61enum usb_chg_state {
  62	USB_CHG_STATE_UNDEFINED = 0,
  63	USB_CHG_STATE_WAIT_FOR_DCD,
  64	USB_CHG_STATE_DCD_DONE,
  65	USB_CHG_STATE_PRIMARY_DONE,
  66	USB_CHG_STATE_SECONDARY_DONE,
  67	USB_CHG_STATE_DETECTED,
  68};
  69
  70static const unsigned int rockchip_usb2phy_extcon_cable[] = {
  71	EXTCON_USB,
  72	EXTCON_USB_HOST,
  73	EXTCON_CHG_USB_SDP,
  74	EXTCON_CHG_USB_CDP,
  75	EXTCON_CHG_USB_DCP,
  76	EXTCON_CHG_USB_SLOW,
  77	EXTCON_NONE,
  78};
  79
  80struct usb2phy_reg {
  81	unsigned int	offset;
  82	unsigned int	bitend;
  83	unsigned int	bitstart;
  84	unsigned int	disable;
  85	unsigned int	enable;
  86};
  87
  88/**
  89 * struct rockchip_chg_det_reg - usb charger detect registers
  90 * @cp_det: charging port detected successfully.
  91 * @dcp_det: dedicated charging port detected successfully.
  92 * @dp_det: assert data pin connect successfully.
  93 * @idm_sink_en: open dm sink curren.
  94 * @idp_sink_en: open dp sink current.
  95 * @idp_src_en: open dm source current.
  96 * @rdm_pdwn_en: open dm pull down resistor.
  97 * @vdm_src_en: open dm voltage source.
  98 * @vdp_src_en: open dp voltage source.
  99 * @opmode: utmi operational mode.
 100 */
 101struct rockchip_chg_det_reg {
 102	struct usb2phy_reg	cp_det;
 103	struct usb2phy_reg	dcp_det;
 104	struct usb2phy_reg	dp_det;
 105	struct usb2phy_reg	idm_sink_en;
 106	struct usb2phy_reg	idp_sink_en;
 107	struct usb2phy_reg	idp_src_en;
 108	struct usb2phy_reg	rdm_pdwn_en;
 109	struct usb2phy_reg	vdm_src_en;
 110	struct usb2phy_reg	vdp_src_en;
 111	struct usb2phy_reg	opmode;
 112};
 113
 114/**
 115 * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
 116 * @phy_sus: phy suspend register.
 117 * @bvalid_det_en: vbus valid rise detection enable register.
 118 * @bvalid_det_st: vbus valid rise detection status register.
 119 * @bvalid_det_clr: vbus valid rise detection clear register.
 120 * @disfall_en: host disconnect fall edge detection enable.
 121 * @disfall_st: host disconnect fall edge detection state.
 122 * @disfall_clr: host disconnect fall edge detection clear.
 123 * @disrise_en: host disconnect rise edge detection enable.
 124 * @disrise_st: host disconnect rise edge detection state.
 125 * @disrise_clr: host disconnect rise edge detection clear.
 126 * @idfall_det_en: id detection enable register, falling edge
 127 * @idfall_det_st: id detection state register, falling edge
 128 * @idfall_det_clr: id detection clear register, falling edge
 129 * @idrise_det_en: id detection enable register, rising edge
 130 * @idrise_det_st: id detection state register, rising edge
 131 * @idrise_det_clr: id detection clear register, rising edge
 132 * @ls_det_en: linestate detection enable register.
 133 * @ls_det_st: linestate detection state register.
 134 * @ls_det_clr: linestate detection clear register.
 135 * @utmi_avalid: utmi vbus avalid status register.
 136 * @utmi_bvalid: utmi vbus bvalid status register.
 137 * @utmi_id: utmi id state register.
 138 * @utmi_ls: utmi linestate state register.
 139 * @utmi_hstdet: utmi host disconnect register.
 140 */
 141struct rockchip_usb2phy_port_cfg {
 142	struct usb2phy_reg	phy_sus;
 143	struct usb2phy_reg	bvalid_det_en;
 144	struct usb2phy_reg	bvalid_det_st;
 145	struct usb2phy_reg	bvalid_det_clr;
 146	struct usb2phy_reg      disfall_en;
 147	struct usb2phy_reg      disfall_st;
 148	struct usb2phy_reg      disfall_clr;
 149	struct usb2phy_reg      disrise_en;
 150	struct usb2phy_reg      disrise_st;
 151	struct usb2phy_reg      disrise_clr;
 152	struct usb2phy_reg	idfall_det_en;
 153	struct usb2phy_reg	idfall_det_st;
 154	struct usb2phy_reg	idfall_det_clr;
 155	struct usb2phy_reg	idrise_det_en;
 156	struct usb2phy_reg	idrise_det_st;
 157	struct usb2phy_reg	idrise_det_clr;
 158	struct usb2phy_reg	ls_det_en;
 159	struct usb2phy_reg	ls_det_st;
 160	struct usb2phy_reg	ls_det_clr;
 161	struct usb2phy_reg	utmi_avalid;
 162	struct usb2phy_reg	utmi_bvalid;
 163	struct usb2phy_reg	utmi_id;
 164	struct usb2phy_reg	utmi_ls;
 165	struct usb2phy_reg	utmi_hstdet;
 166};
 167
 168/**
 169 * struct rockchip_usb2phy_cfg - usb-phy configuration.
 170 * @reg: the address offset of grf for usb-phy config.
 171 * @num_ports: specify how many ports that the phy has.
 172 * @phy_tuning: phy default parameters tuning.
 173 * @clkout_ctl: keep on/turn off output clk of phy.
 174 * @port_cfgs: usb-phy port configurations.
 175 * @chg_det: charger detection registers.
 176 */
 177struct rockchip_usb2phy_cfg {
 178	unsigned int	reg;
 179	unsigned int	num_ports;
 180	int (*phy_tuning)(struct rockchip_usb2phy *rphy);
 181	struct usb2phy_reg	clkout_ctl;
 182	const struct rockchip_usb2phy_port_cfg	port_cfgs[USB2PHY_NUM_PORTS];
 183	const struct rockchip_chg_det_reg	chg_det;
 184};
 185
 186/**
 187 * struct rockchip_usb2phy_port - usb-phy port data.
 188 * @phy: generic phy.
 189 * @port_id: flag for otg port or host port.
 190 * @suspended: phy suspended flag.
 191 * @vbus_attached: otg device vbus status.
 192 * @host_disconnect: usb host disconnect status.
 193 * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
 194 * @id_irq: IRQ number assigned for ID pin detection.
 195 * @ls_irq: IRQ number assigned for linestate detection.
 196 * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
 197 *		 irqs to one irq in otg-port.
 198 * @mutex: for register updating in sm_work.
 199 * @chg_work: charge detect work.
 200 * @otg_sm_work: OTG state machine work.
 201 * @sm_work: HOST state machine work.
 202 * @port_cfg: port register configuration, assigned by driver data.
 203 * @event_nb: hold event notification callback.
 204 * @state: define OTG enumeration states before device reset.
 205 * @mode: the dr_mode of the controller.
 206 */
 207struct rockchip_usb2phy_port {
 208	struct phy	*phy;
 209	unsigned int	port_id;
 210	bool		suspended;
 211	bool		vbus_attached;
 212	bool            host_disconnect;
 213	int		bvalid_irq;
 214	int		id_irq;
 215	int		ls_irq;
 216	int		otg_mux_irq;
 217	struct mutex	mutex;
 218	struct		delayed_work chg_work;
 219	struct		delayed_work otg_sm_work;
 220	struct		delayed_work sm_work;
 221	const struct	rockchip_usb2phy_port_cfg *port_cfg;
 222	struct notifier_block	event_nb;
 223	enum usb_otg_state	state;
 224	enum usb_dr_mode	mode;
 225};
 226
 227/**
 228 * struct rockchip_usb2phy - usb2.0 phy driver data.
 229 * @dev: pointer to device.
 230 * @grf: General Register Files regmap.
 231 * @usbgrf: USB General Register Files regmap.
 232 * @clks: array of phy input clocks.
 233 * @clk480m: clock struct of phy output clk.
 234 * @clk480m_hw: clock struct of phy output clk management.
 235 * @num_clks: number of phy input clocks.
 236 * @phy_reset: phy reset control.
 237 * @chg_state: states involved in USB charger detection.
 238 * @chg_type: USB charger types.
 239 * @dcd_retries: The retry count used to track Data contact
 240 *		 detection process.
 241 * @edev: extcon device for notification registration
 242 * @irq: muxed interrupt for single irq configuration
 243 * @phy_cfg: phy register configuration, assigned by driver data.
 244 * @ports: phy port instance.
 245 */
 246struct rockchip_usb2phy {
 247	struct device	*dev;
 248	struct regmap	*grf;
 249	struct regmap	*usbgrf;
 250	struct clk_bulk_data	*clks;
 251	struct clk	*clk480m;
 252	struct clk_hw	clk480m_hw;
 253	int			num_clks;
 254	struct reset_control	*phy_reset;
 255	enum usb_chg_state	chg_state;
 256	enum power_supply_type	chg_type;
 257	u8			dcd_retries;
 258	struct extcon_dev	*edev;
 259	int			irq;
 260	const struct rockchip_usb2phy_cfg	*phy_cfg;
 261	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
 262};
 263
 264static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
 265{
 266	return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
 267}
 268
 269static inline int property_enable(struct regmap *base,
 270				  const struct usb2phy_reg *reg, bool en)
 271{
 272	unsigned int val, mask, tmp;
 273
 274	tmp = en ? reg->enable : reg->disable;
 275	mask = GENMASK(reg->bitend, reg->bitstart);
 276	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
 277
 278	return regmap_write(base, reg->offset, val);
 279}
 280
 281static inline bool property_enabled(struct regmap *base,
 282				    const struct usb2phy_reg *reg)
 283{
 284	int ret;
 285	unsigned int tmp, orig;
 286	unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
 287
 288	ret = regmap_read(base, reg->offset, &orig);
 289	if (ret)
 290		return false;
 291
 292	tmp = (orig & mask) >> reg->bitstart;
 293	return tmp != reg->disable;
 294}
 295
 296static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
 297{
 298	int ret;
 299
 300	ret = reset_control_assert(rphy->phy_reset);
 301	if (ret)
 302		return ret;
 303
 304	udelay(10);
 305
 306	ret = reset_control_deassert(rphy->phy_reset);
 307	if (ret)
 308		return ret;
 309
 310	usleep_range(100, 200);
 311
 312	return 0;
 313}
 314
 315static void rockchip_usb2phy_clk_bulk_disable(void *data)
 316{
 317	struct rockchip_usb2phy *rphy = data;
 318
 319	clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
 320}
 321
 322static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
 323{
 324	struct rockchip_usb2phy *rphy =
 325		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
 326	struct regmap *base = get_reg_base(rphy);
 327	int ret;
 328
 329	/* turn on 480m clk output if it is off */
 330	if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
 331		ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
 332		if (ret)
 333			return ret;
 334
 335		/* waiting for the clk become stable */
 336		usleep_range(1200, 1300);
 337	}
 338
 339	return 0;
 340}
 341
 342static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
 343{
 344	struct rockchip_usb2phy *rphy =
 345		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
 346	struct regmap *base = get_reg_base(rphy);
 347
 348	/* turn off 480m clk output */
 349	property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
 350}
 351
 352static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
 353{
 354	struct rockchip_usb2phy *rphy =
 355		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
 356	struct regmap *base = get_reg_base(rphy);
 357
 358	return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
 359}
 360
 361static unsigned long
 362rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw *hw,
 363				     unsigned long parent_rate)
 364{
 365	return 480000000;
 366}
 367
 368static const struct clk_ops rockchip_usb2phy_clkout_ops = {
 369	.prepare = rockchip_usb2phy_clk480m_prepare,
 370	.unprepare = rockchip_usb2phy_clk480m_unprepare,
 371	.is_prepared = rockchip_usb2phy_clk480m_prepared,
 372	.recalc_rate = rockchip_usb2phy_clk480m_recalc_rate,
 373};
 374
 375static void rockchip_usb2phy_clk480m_unregister(void *data)
 376{
 377	struct rockchip_usb2phy *rphy = data;
 378
 379	of_clk_del_provider(rphy->dev->of_node);
 380	clk_unregister(rphy->clk480m);
 381}
 382
 383static int
 384rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
 385{
 386	struct device_node *node = rphy->dev->of_node;
 387	struct clk_init_data init;
 388	struct clk *refclk = NULL;
 389	const char *clk_name;
 390	int i;
 391	int ret = 0;
 392
 393	init.flags = 0;
 394	init.name = "clk_usbphy_480m";
 395	init.ops = &rockchip_usb2phy_clkout_ops;
 396
 397	/* optional override of the clockname */
 398	of_property_read_string(node, "clock-output-names", &init.name);
 399
 400	for (i = 0; i < rphy->num_clks; i++) {
 401		if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
 402			refclk = rphy->clks[i].clk;
 403			break;
 404		}
 405	}
 406
 407	if (!IS_ERR(refclk)) {
 408		clk_name = __clk_get_name(refclk);
 409		init.parent_names = &clk_name;
 410		init.num_parents = 1;
 411	} else {
 412		init.parent_names = NULL;
 413		init.num_parents = 0;
 414	}
 415
 416	rphy->clk480m_hw.init = &init;
 417
 418	/* register the clock */
 419	rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw);
 420	if (IS_ERR(rphy->clk480m)) {
 421		ret = PTR_ERR(rphy->clk480m);
 422		goto err_ret;
 423	}
 424
 425	ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m);
 426	if (ret < 0)
 427		goto err_clk_provider;
 428
 429	return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy);
 430
 431err_clk_provider:
 432	clk_unregister(rphy->clk480m);
 433err_ret:
 434	return ret;
 435}
 436
 437static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
 438{
 439	struct device_node *node = rphy->dev->of_node;
 440	struct extcon_dev *edev;
 441	int ret;
 442
 443	if (of_property_present(node, "extcon")) {
 444		edev = extcon_get_edev_by_phandle(rphy->dev, 0);
 445		if (IS_ERR(edev))
 446			return dev_err_probe(rphy->dev, PTR_ERR(edev),
 447					     "invalid or missing extcon\n");
 448	} else {
 449		/* Initialize extcon device */
 450		edev = devm_extcon_dev_allocate(rphy->dev,
 451						rockchip_usb2phy_extcon_cable);
 452
 453		if (IS_ERR(edev))
 454			return dev_err_probe(rphy->dev, PTR_ERR(edev),
 455					     "failed to allocate extcon device\n");
 456
 457		ret = devm_extcon_dev_register(rphy->dev, edev);
 458		if (ret)
 459			return dev_err_probe(rphy->dev, ret,
 460					     "failed to register extcon device\n");
 461	}
 462
 463	rphy->edev = edev;
 464
 465	return 0;
 466}
 467
 468static int rockchip_usb2phy_enable_host_disc_irq(struct rockchip_usb2phy *rphy,
 469						 struct rockchip_usb2phy_port *rport,
 470						 bool en)
 471{
 472	int ret;
 473
 474	ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true);
 475	if (ret)
 476		return ret;
 477
 478	ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en);
 479	if (ret)
 480		return ret;
 481
 482	ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true);
 483	if (ret)
 484		return ret;
 485
 486	return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en);
 487}
 488
 489static int rockchip_usb2phy_init(struct phy *phy)
 490{
 491	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 492	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
 493	int ret = 0;
 494
 495	mutex_lock(&rport->mutex);
 496
 497	if (rport->port_id == USB2PHY_PORT_OTG) {
 498		if (rport->mode != USB_DR_MODE_HOST &&
 499		    rport->mode != USB_DR_MODE_UNKNOWN) {
 500			/* clear bvalid status and enable bvalid detect irq */
 501			ret = property_enable(rphy->grf,
 502					      &rport->port_cfg->bvalid_det_clr,
 503					      true);
 504			if (ret)
 505				goto out;
 506
 507			ret = property_enable(rphy->grf,
 508					      &rport->port_cfg->bvalid_det_en,
 509					      true);
 510			if (ret)
 511				goto out;
 512
 513			/* clear id status and enable id detect irqs */
 514			ret = property_enable(rphy->grf,
 515					      &rport->port_cfg->idfall_det_clr,
 516					      true);
 517			if (ret)
 518				goto out;
 519
 520			ret = property_enable(rphy->grf,
 521					      &rport->port_cfg->idrise_det_clr,
 522					      true);
 523			if (ret)
 524				goto out;
 525
 526			ret = property_enable(rphy->grf,
 527					      &rport->port_cfg->idfall_det_en,
 528					      true);
 529			if (ret)
 530				goto out;
 531
 532			ret = property_enable(rphy->grf,
 533					      &rport->port_cfg->idrise_det_en,
 534					      true);
 535			if (ret)
 536				goto out;
 537
 538			schedule_delayed_work(&rport->otg_sm_work,
 539					      OTG_SCHEDULE_DELAY * 3);
 540		} else {
 541			/* If OTG works in host only mode, do nothing. */
 542			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
 543		}
 544	} else if (rport->port_id == USB2PHY_PORT_HOST) {
 545		if (rport->port_cfg->disfall_en.offset) {
 546			rport->host_disconnect = true;
 547			ret = rockchip_usb2phy_enable_host_disc_irq(rphy, rport, true);
 548			if (ret) {
 549				dev_err(rphy->dev, "failed to enable disconnect irq\n");
 550				goto out;
 551			}
 552		}
 553
 554		/* clear linestate and enable linestate detect irq */
 555		ret = property_enable(rphy->grf,
 556				      &rport->port_cfg->ls_det_clr, true);
 557		if (ret)
 558			goto out;
 559
 560		ret = property_enable(rphy->grf,
 561				      &rport->port_cfg->ls_det_en, true);
 562		if (ret)
 563			goto out;
 564
 565		schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
 566	}
 567
 568out:
 569	mutex_unlock(&rport->mutex);
 570	return ret;
 571}
 572
 573static int rockchip_usb2phy_power_on(struct phy *phy)
 574{
 575	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 576	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
 577	struct regmap *base = get_reg_base(rphy);
 578	int ret;
 579
 580	dev_dbg(&rport->phy->dev, "port power on\n");
 581
 582	if (!rport->suspended)
 583		return 0;
 584
 585	ret = clk_prepare_enable(rphy->clk480m);
 586	if (ret)
 587		return ret;
 588
 589	ret = property_enable(base, &rport->port_cfg->phy_sus, false);
 590	if (ret) {
 591		clk_disable_unprepare(rphy->clk480m);
 592		return ret;
 593	}
 594
 595	/*
 596	 * For rk3588, it needs to reset phy when exit from
 597	 * suspend mode with common_on_n 1'b1(aka REFCLK_LOGIC,
 598	 * Bias, and PLL blocks are powered down) for lower
 599	 * power consumption. If you don't want to reset phy,
 600	 * please keep the common_on_n 1'b0 to set these blocks
 601	 * remain powered.
 602	 */
 603	ret = rockchip_usb2phy_reset(rphy);
 604	if (ret)
 605		return ret;
 606
 607	/* waiting for the utmi_clk to become stable */
 608	usleep_range(1500, 2000);
 609
 610	rport->suspended = false;
 611	return 0;
 612}
 613
 614static int rockchip_usb2phy_power_off(struct phy *phy)
 615{
 616	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 617	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
 618	struct regmap *base = get_reg_base(rphy);
 619	int ret;
 620
 621	dev_dbg(&rport->phy->dev, "port power off\n");
 622
 623	if (rport->suspended)
 624		return 0;
 625
 626	ret = property_enable(base, &rport->port_cfg->phy_sus, true);
 627	if (ret)
 628		return ret;
 629
 630	rport->suspended = true;
 631	clk_disable_unprepare(rphy->clk480m);
 632
 633	return 0;
 634}
 635
 636static int rockchip_usb2phy_exit(struct phy *phy)
 637{
 638	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 639
 640	if (rport->port_id == USB2PHY_PORT_OTG &&
 641	    rport->mode != USB_DR_MODE_HOST &&
 642	    rport->mode != USB_DR_MODE_UNKNOWN) {
 643		cancel_delayed_work_sync(&rport->otg_sm_work);
 644		cancel_delayed_work_sync(&rport->chg_work);
 645	} else if (rport->port_id == USB2PHY_PORT_HOST)
 646		cancel_delayed_work_sync(&rport->sm_work);
 647
 648	return 0;
 649}
 650
 651static const struct phy_ops rockchip_usb2phy_ops = {
 652	.init		= rockchip_usb2phy_init,
 653	.exit		= rockchip_usb2phy_exit,
 654	.power_on	= rockchip_usb2phy_power_on,
 655	.power_off	= rockchip_usb2phy_power_off,
 656	.owner		= THIS_MODULE,
 657};
 658
 659static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
 660{
 661	struct rockchip_usb2phy_port *rport =
 662		container_of(work, struct rockchip_usb2phy_port,
 663			     otg_sm_work.work);
 664	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
 665	static unsigned int cable;
 666	unsigned long delay;
 667	bool vbus_attach, sch_work, notify_charger;
 668
 669	vbus_attach = property_enabled(rphy->grf,
 670				       &rport->port_cfg->utmi_bvalid);
 671
 672	sch_work = false;
 673	notify_charger = false;
 674	delay = OTG_SCHEDULE_DELAY;
 675	dev_dbg(&rport->phy->dev, "%s otg sm work\n",
 676		usb_otg_state_string(rport->state));
 677
 678	switch (rport->state) {
 679	case OTG_STATE_UNDEFINED:
 680		rport->state = OTG_STATE_B_IDLE;
 681		if (!vbus_attach)
 682			rockchip_usb2phy_power_off(rport->phy);
 683		fallthrough;
 684	case OTG_STATE_B_IDLE:
 685		if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) {
 686			dev_dbg(&rport->phy->dev, "usb otg host connect\n");
 687			rport->state = OTG_STATE_A_HOST;
 688			rockchip_usb2phy_power_on(rport->phy);
 689			return;
 690		} else if (vbus_attach) {
 691			dev_dbg(&rport->phy->dev, "vbus_attach\n");
 692			switch (rphy->chg_state) {
 693			case USB_CHG_STATE_UNDEFINED:
 694				schedule_delayed_work(&rport->chg_work, 0);
 695				return;
 696			case USB_CHG_STATE_DETECTED:
 697				switch (rphy->chg_type) {
 698				case POWER_SUPPLY_TYPE_USB:
 699					dev_dbg(&rport->phy->dev, "sdp cable is connected\n");
 700					rockchip_usb2phy_power_on(rport->phy);
 701					rport->state = OTG_STATE_B_PERIPHERAL;
 702					notify_charger = true;
 703					sch_work = true;
 704					cable = EXTCON_CHG_USB_SDP;
 705					break;
 706				case POWER_SUPPLY_TYPE_USB_DCP:
 707					dev_dbg(&rport->phy->dev, "dcp cable is connected\n");
 708					rockchip_usb2phy_power_off(rport->phy);
 709					notify_charger = true;
 710					sch_work = true;
 711					cable = EXTCON_CHG_USB_DCP;
 712					break;
 713				case POWER_SUPPLY_TYPE_USB_CDP:
 714					dev_dbg(&rport->phy->dev, "cdp cable is connected\n");
 715					rockchip_usb2phy_power_on(rport->phy);
 716					rport->state = OTG_STATE_B_PERIPHERAL;
 717					notify_charger = true;
 718					sch_work = true;
 719					cable = EXTCON_CHG_USB_CDP;
 720					break;
 721				default:
 722					break;
 723				}
 724				break;
 725			default:
 726				break;
 727			}
 728		} else {
 729			notify_charger = true;
 730			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
 731			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
 732		}
 733
 734		if (rport->vbus_attached != vbus_attach) {
 735			rport->vbus_attached = vbus_attach;
 736
 737			if (notify_charger && rphy->edev) {
 738				extcon_set_state_sync(rphy->edev,
 739							cable, vbus_attach);
 740				if (cable == EXTCON_CHG_USB_SDP)
 741					extcon_set_state_sync(rphy->edev,
 742							      EXTCON_USB,
 743							      vbus_attach);
 744			}
 745		}
 746		break;
 747	case OTG_STATE_B_PERIPHERAL:
 748		if (!vbus_attach) {
 749			dev_dbg(&rport->phy->dev, "usb disconnect\n");
 750			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
 751			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
 752			rport->state = OTG_STATE_B_IDLE;
 753			delay = 0;
 754			rockchip_usb2phy_power_off(rport->phy);
 755		}
 756		sch_work = true;
 757		break;
 758	case OTG_STATE_A_HOST:
 759		if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) {
 760			dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
 761			rport->state = OTG_STATE_B_IDLE;
 762			rockchip_usb2phy_power_off(rport->phy);
 763		}
 764		break;
 765	default:
 766		break;
 767	}
 768
 769	if (sch_work)
 770		schedule_delayed_work(&rport->otg_sm_work, delay);
 771}
 772
 773static const char *chg_to_string(enum power_supply_type chg_type)
 774{
 775	switch (chg_type) {
 776	case POWER_SUPPLY_TYPE_USB:
 777		return "USB_SDP_CHARGER";
 778	case POWER_SUPPLY_TYPE_USB_DCP:
 779		return "USB_DCP_CHARGER";
 780	case POWER_SUPPLY_TYPE_USB_CDP:
 781		return "USB_CDP_CHARGER";
 782	default:
 783		return "INVALID_CHARGER";
 784	}
 785}
 786
 787static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
 788				    bool en)
 789{
 790	struct regmap *base = get_reg_base(rphy);
 791
 792	property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
 793	property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
 794}
 795
 796static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
 797					    bool en)
 798{
 799	struct regmap *base = get_reg_base(rphy);
 800
 801	property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
 802	property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
 803}
 804
 805static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
 806					      bool en)
 807{
 808	struct regmap *base = get_reg_base(rphy);
 809
 810	property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
 811	property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
 812}
 813
 814#define CHG_DCD_POLL_TIME	(100 * HZ / 1000)
 815#define CHG_DCD_MAX_RETRIES	6
 816#define CHG_PRIMARY_DET_TIME	(40 * HZ / 1000)
 817#define CHG_SECONDARY_DET_TIME	(40 * HZ / 1000)
 818static void rockchip_chg_detect_work(struct work_struct *work)
 819{
 820	struct rockchip_usb2phy_port *rport =
 821		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
 822	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
 823	struct regmap *base = get_reg_base(rphy);
 824	bool is_dcd, tmout, vout, vbus_attach;
 825	unsigned long delay;
 826
 827	vbus_attach = property_enabled(rphy->grf, &rport->port_cfg->utmi_bvalid);
 828
 829	dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
 830		rphy->chg_state);
 831	switch (rphy->chg_state) {
 832	case USB_CHG_STATE_UNDEFINED:
 833		if (!rport->suspended && !vbus_attach)
 834			rockchip_usb2phy_power_off(rport->phy);
 835		/* put the controller in non-driving mode */
 836		if (!vbus_attach)
 837			property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
 838		/* Start DCD processing stage 1 */
 839		rockchip_chg_enable_dcd(rphy, true);
 840		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
 841		rphy->dcd_retries = 0;
 842		delay = CHG_DCD_POLL_TIME;
 843		break;
 844	case USB_CHG_STATE_WAIT_FOR_DCD:
 845		/* get data contact detection status */
 846		is_dcd = property_enabled(rphy->grf,
 847					  &rphy->phy_cfg->chg_det.dp_det);
 848		tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
 849		/* stage 2 */
 850		if (is_dcd || tmout) {
 851			/* stage 4 */
 852			/* Turn off DCD circuitry */
 853			rockchip_chg_enable_dcd(rphy, false);
 854			/* Voltage Source on DP, Probe on DM */
 855			rockchip_chg_enable_primary_det(rphy, true);
 856			delay = CHG_PRIMARY_DET_TIME;
 857			rphy->chg_state = USB_CHG_STATE_DCD_DONE;
 858		} else {
 859			/* stage 3 */
 860			delay = CHG_DCD_POLL_TIME;
 861		}
 862		break;
 863	case USB_CHG_STATE_DCD_DONE:
 864		vout = property_enabled(rphy->grf,
 865					&rphy->phy_cfg->chg_det.cp_det);
 866		rockchip_chg_enable_primary_det(rphy, false);
 867		if (vout) {
 868			/* Voltage Source on DM, Probe on DP  */
 869			rockchip_chg_enable_secondary_det(rphy, true);
 870			delay = CHG_SECONDARY_DET_TIME;
 871			rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
 872		} else {
 873			if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) {
 874				/* floating charger found */
 875				rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
 876				rphy->chg_state = USB_CHG_STATE_DETECTED;
 877				delay = 0;
 878			} else {
 879				rphy->chg_type = POWER_SUPPLY_TYPE_USB;
 880				rphy->chg_state = USB_CHG_STATE_DETECTED;
 881				delay = 0;
 882			}
 883		}
 884		break;
 885	case USB_CHG_STATE_PRIMARY_DONE:
 886		vout = property_enabled(rphy->grf,
 887					&rphy->phy_cfg->chg_det.dcp_det);
 888		/* Turn off voltage source */
 889		rockchip_chg_enable_secondary_det(rphy, false);
 890		if (vout)
 891			rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
 892		else
 893			rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
 894		fallthrough;
 895	case USB_CHG_STATE_SECONDARY_DONE:
 896		rphy->chg_state = USB_CHG_STATE_DETECTED;
 897		fallthrough;
 898	case USB_CHG_STATE_DETECTED:
 899		/* put the controller in normal mode */
 900		if (!vbus_attach)
 901			property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
 902		rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
 903		dev_dbg(&rport->phy->dev, "charger = %s\n",
 904			 chg_to_string(rphy->chg_type));
 905		return;
 906	default:
 907		return;
 908	}
 909
 910	schedule_delayed_work(&rport->chg_work, delay);
 911}
 912
 913/*
 914 * The function manage host-phy port state and suspend/resume phy port
 915 * to save power.
 916 *
 917 * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
 918 * devices is disconnect or not. Besides, we do not need care it is FS/LS
 919 * disconnected or HS disconnected, actually, we just only need get the
 920 * device is disconnected at last through rearm the delayed work,
 921 * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
 922 *
 923 * NOTE: It may invoke *phy_powr_off or *phy_power_on which will invoke
 924 * some clk related APIs, so do not invoke it from interrupt context directly.
 925 */
 926static void rockchip_usb2phy_sm_work(struct work_struct *work)
 927{
 928	struct rockchip_usb2phy_port *rport =
 929		container_of(work, struct rockchip_usb2phy_port, sm_work.work);
 930	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
 931	unsigned int sh, ul, uhd, state;
 932	unsigned int ul_mask, uhd_mask;
 933	int ret;
 934
 935	mutex_lock(&rport->mutex);
 936
 937	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul);
 938	if (ret < 0)
 939		goto next_schedule;
 940
 941	ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend,
 942			  rport->port_cfg->utmi_ls.bitstart);
 943
 944	if (rport->port_cfg->utmi_hstdet.offset) {
 945		ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
 946		if (ret < 0)
 947			goto next_schedule;
 948
 949		uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend,
 950				   rport->port_cfg->utmi_hstdet.bitstart);
 951
 952		sh = rport->port_cfg->utmi_hstdet.bitend -
 953		     rport->port_cfg->utmi_hstdet.bitstart + 1;
 954		/* stitch on utmi_ls and utmi_hstdet as phy state */
 955		state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) |
 956			(((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh);
 957	} else {
 958		state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 |
 959			rport->host_disconnect;
 960	}
 961
 962	switch (state) {
 963	case PHY_STATE_HS_ONLINE:
 964		dev_dbg(&rport->phy->dev, "HS online\n");
 965		break;
 966	case PHY_STATE_FS_LS_ONLINE:
 967		/*
 968		 * For FS/LS device, the online state share with connect state
 969		 * from utmi_ls and utmi_hstdet register, so we distinguish
 970		 * them via suspended flag.
 971		 *
 972		 * Plus, there are two cases, one is D- Line pull-up, and D+
 973		 * line pull-down, the state is 4; another is D+ line pull-up,
 974		 * and D- line pull-down, the state is 2.
 975		 */
 976		if (!rport->suspended) {
 977			/* D- line pull-up, D+ line pull-down */
 978			dev_dbg(&rport->phy->dev, "FS/LS online\n");
 979			break;
 980		}
 981		fallthrough;
 982	case PHY_STATE_CONNECT:
 983		if (rport->suspended) {
 984			dev_dbg(&rport->phy->dev, "Connected\n");
 985			rockchip_usb2phy_power_on(rport->phy);
 986			rport->suspended = false;
 987		} else {
 988			/* D+ line pull-up, D- line pull-down */
 989			dev_dbg(&rport->phy->dev, "FS/LS online\n");
 990		}
 991		break;
 992	case PHY_STATE_DISCONNECT:
 993		if (!rport->suspended) {
 994			dev_dbg(&rport->phy->dev, "Disconnected\n");
 995			rockchip_usb2phy_power_off(rport->phy);
 996			rport->suspended = true;
 997		}
 998
 999		/*
1000		 * activate the linestate detection to get the next device
1001		 * plug-in irq.
1002		 */
1003		property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
1004		property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true);
1005
1006		/*
1007		 * we don't need to rearm the delayed work when the phy port
1008		 * is suspended.
1009		 */
1010		mutex_unlock(&rport->mutex);
1011		return;
1012	default:
1013		dev_dbg(&rport->phy->dev, "unknown phy state\n");
1014		break;
1015	}
1016
1017next_schedule:
1018	mutex_unlock(&rport->mutex);
1019	schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
1020}
1021
1022static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
1023{
1024	struct rockchip_usb2phy_port *rport = data;
1025	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1026
1027	if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st))
1028		return IRQ_NONE;
1029
1030	mutex_lock(&rport->mutex);
1031
1032	/* disable linestate detect irq and clear its status */
1033	property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false);
1034	property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
1035
1036	mutex_unlock(&rport->mutex);
1037
1038	/*
1039	 * In this case for host phy port, a new device is plugged in,
1040	 * meanwhile, if the phy port is suspended, we need rearm the work to
1041	 * resume it and mange its states; otherwise, we do nothing about that.
1042	 */
1043	if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST)
1044		rockchip_usb2phy_sm_work(&rport->sm_work.work);
1045
1046	return IRQ_HANDLED;
1047}
1048
1049static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
1050{
1051	struct rockchip_usb2phy_port *rport = data;
1052	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1053
1054	if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
1055		return IRQ_NONE;
1056
1057	/* clear bvalid detect irq pending status */
1058	property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true);
1059
1060	rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
1061
1062	return IRQ_HANDLED;
1063}
1064
1065static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
1066{
1067	struct rockchip_usb2phy_port *rport = data;
1068	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1069	bool id;
1070
1071	if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) &&
1072	    !property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st))
1073		return IRQ_NONE;
1074
1075	/* clear id detect irq pending status */
1076	if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st))
1077		property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, true);
1078
1079	if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st))
1080		property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, true);
1081
1082	id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
1083	extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
1084
1085	return IRQ_HANDLED;
1086}
1087
1088static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
1089{
1090	irqreturn_t ret = IRQ_NONE;
1091
1092	ret |= rockchip_usb2phy_bvalid_irq(irq, data);
1093	ret |= rockchip_usb2phy_id_irq(irq, data);
1094
1095	return ret;
1096}
1097
1098static irqreturn_t rockchip_usb2phy_host_disc_irq(int irq, void *data)
1099{
1100	struct rockchip_usb2phy_port *rport = data;
1101	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1102
1103	if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) &&
1104	    !property_enabled(rphy->grf, &rport->port_cfg->disrise_st))
1105		return IRQ_NONE;
1106
1107	mutex_lock(&rport->mutex);
1108
1109	/* clear disconnect fall or rise detect irq pending status */
1110	if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) {
1111		property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true);
1112		rport->host_disconnect = false;
1113	} else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) {
1114		property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true);
1115		rport->host_disconnect = true;
1116	}
1117
1118	mutex_unlock(&rport->mutex);
1119
1120	return IRQ_HANDLED;
1121}
1122
1123static irqreturn_t rockchip_usb2phy_irq(int irq, void *data)
1124{
1125	struct rockchip_usb2phy *rphy = data;
1126	struct rockchip_usb2phy_port *rport;
1127	irqreturn_t ret = IRQ_NONE;
1128	unsigned int index;
1129
1130	for (index = 0; index < rphy->phy_cfg->num_ports; index++) {
1131		rport = &rphy->ports[index];
1132		if (!rport->phy)
1133			continue;
1134
1135		if (rport->port_id == USB2PHY_PORT_HOST &&
1136		    rport->port_cfg->disfall_en.offset)
1137			ret |= rockchip_usb2phy_host_disc_irq(irq, rport);
1138
1139		switch (rport->port_id) {
1140		case USB2PHY_PORT_OTG:
1141			if (rport->mode != USB_DR_MODE_HOST &&
1142			    rport->mode != USB_DR_MODE_UNKNOWN)
1143				ret |= rockchip_usb2phy_otg_mux_irq(irq, rport);
1144			break;
1145		case USB2PHY_PORT_HOST:
1146			ret |= rockchip_usb2phy_linestate_irq(irq, rport);
1147			break;
1148		}
1149	}
1150
1151	return ret;
1152}
1153
1154static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy,
1155					  struct rockchip_usb2phy_port *rport,
1156					  struct device_node *child_np)
1157{
1158	int ret;
1159
1160	/*
1161	 * If the usb2 phy used combined irq for otg and host port,
1162	 * don't need to init otg and host port irq separately.
1163	 */
1164	if (rphy->irq > 0)
1165		return 0;
1166
1167	switch (rport->port_id) {
1168	case USB2PHY_PORT_HOST:
1169		rport->ls_irq = of_irq_get_byname(child_np, "linestate");
1170		if (rport->ls_irq < 0) {
1171			dev_err(rphy->dev, "no linestate irq provided\n");
1172			return rport->ls_irq;
1173		}
1174
1175		ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
1176						rockchip_usb2phy_linestate_irq,
1177						IRQF_ONESHOT,
1178						"rockchip_usb2phy", rport);
1179		if (ret) {
1180			dev_err(rphy->dev, "failed to request linestate irq handle\n");
1181			return ret;
1182		}
1183		break;
1184	case USB2PHY_PORT_OTG:
1185		/*
1186		 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
1187		 * interrupts muxed together, so probe the otg-mux interrupt first,
1188		 * if not found, then look for the regular interrupts one by one.
1189		 */
1190		rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
1191		if (rport->otg_mux_irq > 0) {
1192			ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
1193							NULL,
1194							rockchip_usb2phy_otg_mux_irq,
1195							IRQF_ONESHOT,
1196							"rockchip_usb2phy_otg",
1197							rport);
1198			if (ret) {
1199				dev_err(rphy->dev,
1200					"failed to request otg-mux irq handle\n");
1201				return ret;
1202			}
1203		} else {
1204			rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
1205			if (rport->bvalid_irq < 0) {
1206				dev_err(rphy->dev, "no vbus valid irq provided\n");
1207				ret = rport->bvalid_irq;
1208				return ret;
1209			}
1210
1211			ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
1212							NULL,
1213							rockchip_usb2phy_bvalid_irq,
1214							IRQF_ONESHOT,
1215							"rockchip_usb2phy_bvalid",
1216							rport);
1217			if (ret) {
1218				dev_err(rphy->dev,
1219					"failed to request otg-bvalid irq handle\n");
1220				return ret;
1221			}
1222
1223			rport->id_irq = of_irq_get_byname(child_np, "otg-id");
1224			if (rport->id_irq < 0) {
1225				dev_err(rphy->dev, "no otg-id irq provided\n");
1226				ret = rport->id_irq;
1227				return ret;
1228			}
1229
1230			ret = devm_request_threaded_irq(rphy->dev, rport->id_irq,
1231							NULL,
1232							rockchip_usb2phy_id_irq,
1233							IRQF_ONESHOT,
1234							"rockchip_usb2phy_id",
1235							rport);
1236			if (ret) {
1237				dev_err(rphy->dev,
1238					"failed to request otg-id irq handle\n");
1239				return ret;
1240			}
1241		}
1242		break;
1243	default:
1244		return -EINVAL;
1245	}
1246
1247	return 0;
1248}
1249
1250static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
1251					   struct rockchip_usb2phy_port *rport,
1252					   struct device_node *child_np)
1253{
1254	int ret;
1255
1256	rport->port_id = USB2PHY_PORT_HOST;
1257	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST];
1258	rport->suspended = true;
1259
1260	mutex_init(&rport->mutex);
1261	INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work);
1262
1263	ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
1264	if (ret) {
1265		dev_err(rphy->dev, "failed to setup host irq\n");
1266		return ret;
1267	}
1268
1269	return 0;
1270}
1271
1272static int rockchip_otg_event(struct notifier_block *nb,
1273			      unsigned long event, void *ptr)
1274{
1275	struct rockchip_usb2phy_port *rport =
1276		container_of(nb, struct rockchip_usb2phy_port, event_nb);
1277
1278	schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
1279
1280	return NOTIFY_DONE;
1281}
1282
1283static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
1284					  struct rockchip_usb2phy_port *rport,
1285					  struct device_node *child_np)
1286{
1287	int ret, id;
1288
1289	rport->port_id = USB2PHY_PORT_OTG;
1290	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
1291	rport->state = OTG_STATE_UNDEFINED;
1292
1293	/*
1294	 * set suspended flag to true, but actually don't
1295	 * put phy in suspend mode, it aims to enable usb
1296	 * phy and clock in power_on() called by usb controller
1297	 * driver during probe.
1298	 */
1299	rport->suspended = true;
1300	rport->vbus_attached = false;
1301
1302	mutex_init(&rport->mutex);
1303
1304	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
1305	if (rport->mode == USB_DR_MODE_HOST ||
1306	    rport->mode == USB_DR_MODE_UNKNOWN) {
1307		ret = 0;
1308		goto out;
1309	}
1310
1311	INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
1312	INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
1313
1314	ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
1315	if (ret) {
1316		dev_err(rphy->dev, "failed to init irq for host port\n");
1317		goto out;
1318	}
1319
1320	if (!IS_ERR(rphy->edev)) {
1321		rport->event_nb.notifier_call = rockchip_otg_event;
1322
1323		ret = devm_extcon_register_notifier(rphy->dev, rphy->edev,
1324					EXTCON_USB_HOST, &rport->event_nb);
1325		if (ret) {
1326			dev_err(rphy->dev, "register USB HOST notifier failed\n");
1327			goto out;
1328		}
1329
1330		if (!of_property_present(rphy->dev->of_node, "extcon")) {
1331			/* do initial sync of usb state */
1332			id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
1333			extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
1334		}
1335	}
1336
1337out:
1338	return ret;
1339}
1340
1341static int rockchip_usb2phy_probe(struct platform_device *pdev)
1342{
1343	struct device *dev = &pdev->dev;
1344	struct device_node *np = dev->of_node;
1345	struct device_node *child_np;
1346	struct phy_provider *provider;
1347	struct rockchip_usb2phy *rphy;
1348	const struct rockchip_usb2phy_cfg *phy_cfgs;
1349	unsigned int reg;
1350	int index = 0, ret;
1351
1352	rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
1353	if (!rphy)
1354		return -ENOMEM;
1355
1356	if (!dev->parent || !dev->parent->of_node) {
1357		rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
1358		if (IS_ERR(rphy->grf)) {
1359			dev_err(dev, "failed to locate usbgrf\n");
1360			return PTR_ERR(rphy->grf);
1361		}
1362	} else {
1363		rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
1364		if (IS_ERR(rphy->grf))
1365			return PTR_ERR(rphy->grf);
1366	}
1367
1368	if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
1369		rphy->usbgrf =
1370			syscon_regmap_lookup_by_phandle(dev->of_node,
1371							"rockchip,usbgrf");
1372		if (IS_ERR(rphy->usbgrf))
1373			return PTR_ERR(rphy->usbgrf);
1374	} else {
1375		rphy->usbgrf = NULL;
1376	}
1377
1378	if (of_property_read_u32_index(np, "reg", 0, &reg)) {
1379		dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
1380		return -EINVAL;
1381	}
1382
1383	/* support address_cells=2 */
1384	if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) {
1385		if (of_property_read_u32_index(np, "reg", 1, &reg)) {
1386			dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
1387			return -EINVAL;
1388		}
1389	}
1390
1391	rphy->dev = dev;
1392	phy_cfgs = device_get_match_data(dev);
1393	rphy->chg_state = USB_CHG_STATE_UNDEFINED;
1394	rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
1395	rphy->irq = platform_get_irq_optional(pdev, 0);
1396	platform_set_drvdata(pdev, rphy);
1397
1398	if (!phy_cfgs)
1399		return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n");
1400
1401	ret = rockchip_usb2phy_extcon_register(rphy);
1402	if (ret)
1403		return ret;
1404
1405	/* find a proper config that can be matched with the DT */
1406	do {
1407		if (phy_cfgs[index].reg == reg) {
1408			rphy->phy_cfg = &phy_cfgs[index];
1409			break;
1410		}
1411
1412		++index;
1413	} while (phy_cfgs[index].reg);
1414
1415	if (!rphy->phy_cfg) {
1416		dev_err(dev, "could not find phy config for reg=0x%08x\n", reg);
1417		return -EINVAL;
1418	}
1419
1420	rphy->phy_reset = devm_reset_control_get_optional(dev, "phy");
1421	if (IS_ERR(rphy->phy_reset))
1422		return PTR_ERR(rphy->phy_reset);
1423
1424	ret = devm_clk_bulk_get_all(dev, &rphy->clks);
1425	if (ret == -EPROBE_DEFER)
1426		return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
1427				     "failed to get phy clock\n");
1428
1429	/* Clocks are optional */
1430	rphy->num_clks = ret < 0 ? 0 : ret;
1431
1432	ret = rockchip_usb2phy_clk480m_register(rphy);
1433	if (ret)
1434		return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
1435
1436	ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
1437	if (ret)
1438		return dev_err_probe(dev, ret, "failed to enable phy clock\n");
1439
1440	ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
1441	if (ret)
1442		return ret;
1443
1444	if (rphy->phy_cfg->phy_tuning) {
1445		ret = rphy->phy_cfg->phy_tuning(rphy);
1446		if (ret)
1447			return ret;
1448	}
1449
1450	index = 0;
1451	for_each_available_child_of_node(np, child_np) {
1452		struct rockchip_usb2phy_port *rport = &rphy->ports[index];
1453		struct phy *phy;
1454
1455		/* This driver aims to support both otg-port and host-port */
1456		if (!of_node_name_eq(child_np, "host-port") &&
1457		    !of_node_name_eq(child_np, "otg-port"))
1458			goto next_child;
1459
1460		phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
1461		if (IS_ERR(phy)) {
1462			ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
1463			goto put_child;
1464		}
1465
1466		rport->phy = phy;
1467		phy_set_drvdata(rport->phy, rport);
1468
1469		/* initialize otg/host port separately */
1470		if (of_node_name_eq(child_np, "host-port")) {
1471			ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
1472			if (ret)
1473				goto put_child;
1474		} else {
1475			ret = rockchip_usb2phy_otg_port_init(rphy, rport, child_np);
1476			if (ret)
1477				goto put_child;
1478		}
1479
1480next_child:
1481		/* to prevent out of boundary */
1482		if (++index >= rphy->phy_cfg->num_ports) {
1483			of_node_put(child_np);
1484			break;
1485		}
1486	}
1487
1488	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1489
1490	if (rphy->irq > 0) {
1491		ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL,
1492						rockchip_usb2phy_irq,
1493						IRQF_ONESHOT,
1494						"rockchip_usb2phy",
1495						rphy);
1496		if (ret) {
1497			dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
1498			return ret;
1499		}
1500	}
1501
1502	return PTR_ERR_OR_ZERO(provider);
1503
1504put_child:
1505	of_node_put(child_np);
1506	return ret;
1507}
1508
1509static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1510{
1511	/* Turn off differential receiver in suspend mode */
1512	return regmap_write_bits(rphy->grf, 0x298,
1513				BIT(2) << BIT_WRITEABLE_SHIFT | BIT(2),
1514				BIT(2) << BIT_WRITEABLE_SHIFT | 0);
1515}
1516
1517static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1518{
1519	int ret;
1520	u32 reg = rphy->phy_cfg->reg;
1521
1522	/* Deassert SIDDQ to power on analog block */
1523	ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
1524	if (ret)
1525		return ret;
1526
1527	/* Do reset after exit IDDQ mode */
1528	ret = rockchip_usb2phy_reset(rphy);
1529	if (ret)
1530		return ret;
1531
1532	/* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
1533	ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
1534
1535	/* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
1536	ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
1537
1538	return ret;
1539}
1540
1541static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1542{
1543	int ret;
1544	bool usb3otg = false;
1545	/*
1546	 * utmi_termselect = 1'b1 (en FS terminations)
1547	 * utmi_xcvrselect = 2'b01 (FS transceiver)
1548	 */
1549	int suspend_cfg = 0x14;
1550
1551	if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) {
1552		/* USB2 config for USB3_0 and USB3_1 */
1553		suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */
1554		usb3otg = true;
1555	} else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) {
1556		/* USB2 config for USB2_0 and USB2_1 */
1557		suspend_cfg |= 0x00; /* utmi_opmode = 2'b00 (normal) */
1558	} else {
1559		return -EINVAL;
1560	}
1561
1562	/* Deassert SIDDQ to power on analog block */
1563	ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000);
1564	if (ret)
1565		return ret;
1566
1567	/* Do reset after exit IDDQ mode */
1568	ret = rockchip_usb2phy_reset(rphy);
1569	if (ret)
1570		return ret;
1571
1572	/* suspend configuration */
1573	ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg);
1574
1575	/* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
1576	ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900);
1577
1578	/* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
1579	ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010);
1580
1581	if (!usb3otg)
1582		return ret;
1583
1584	/* Pullup iddig pin for USB3_0 OTG mode */
1585	ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003);
1586
1587	return ret;
1588}
1589
1590static const struct rockchip_usb2phy_cfg rk3036_phy_cfgs[] = {
1591	{
1592		.reg = 0x17c,
1593		.num_ports	= 2,
1594		.phy_tuning	= rk3128_usb2phy_tuning,
1595		.clkout_ctl	= { 0x017c, 11, 11, 1, 0 },
1596		.port_cfgs	= {
1597			[USB2PHY_PORT_OTG] = {
1598				.phy_sus	= { 0x017c, 8, 0, 0, 0x1d1 },
1599				.bvalid_det_en	= { 0x017c, 14, 14, 0, 1 },
1600				.bvalid_det_st	= { 0x017c, 15, 15, 0, 1 },
1601				.bvalid_det_clr	= { 0x017c, 15, 15, 0, 1 },
1602				.ls_det_en	= { 0x017c, 12, 12, 0, 1 },
1603				.ls_det_st	= { 0x017c, 13, 13, 0, 1 },
1604				.ls_det_clr	= { 0x017c, 13, 13, 0, 1 },
1605				.utmi_bvalid	= { 0x014c, 8, 8, 0, 1 },
1606				.utmi_id	= { 0x014c, 11, 11, 0, 1 },
1607				.utmi_ls	= { 0x014c, 10, 9, 0, 1 },
1608
1609			},
1610			[USB2PHY_PORT_HOST] = {
1611				.phy_sus	= { 0x0194, 8, 0, 0, 0x1d1 },
1612				.ls_det_en	= { 0x0194, 14, 14, 0, 1 },
1613				.ls_det_st	= { 0x0194, 15, 15, 0, 1 },
1614				.ls_det_clr	= { 0x0194, 15, 15, 0, 1 }
1615			}
1616		},
1617	},
1618	{ /* sentinel */ }
1619};
1620
1621static const struct rockchip_usb2phy_cfg rk3128_phy_cfgs[] = {
1622	{
1623		.reg = 0x17c,
1624		.num_ports	= 2,
1625		.phy_tuning	= rk3128_usb2phy_tuning,
1626		.clkout_ctl	= { 0x0190, 15, 15, 1, 0 },
1627		.port_cfgs	= {
1628			[USB2PHY_PORT_OTG] = {
1629				.phy_sus	= { 0x017c, 8, 0, 0, 0x1d1 },
1630				.bvalid_det_en	= { 0x017c, 14, 14, 0, 1 },
1631				.bvalid_det_st	= { 0x017c, 15, 15, 0, 1 },
1632				.bvalid_det_clr	= { 0x017c, 15, 15, 0, 1 },
1633				.idfall_det_en  = { 0x01a0, 2, 2, 0, 1 },
1634				.idfall_det_st  = { 0x01a0, 3, 3, 0, 1 },
1635				.idfall_det_clr = { 0x01a0, 3, 3, 0, 1 },
1636				.idrise_det_en  = { 0x01a0, 0, 0, 0, 1 },
1637				.idrise_det_st  = { 0x01a0, 1, 1, 0, 1 },
1638				.idrise_det_clr = { 0x01a0, 1, 1, 0, 1 },
1639				.ls_det_en	= { 0x017c, 12, 12, 0, 1 },
1640				.ls_det_st	= { 0x017c, 13, 13, 0, 1 },
1641				.ls_det_clr	= { 0x017c, 13, 13, 0, 1 },
1642				.utmi_bvalid	= { 0x014c, 5, 5, 0, 1 },
1643				.utmi_id	= { 0x014c, 8, 8, 0, 1 },
1644				.utmi_ls	= { 0x014c, 7, 6, 0, 1 },
1645			},
1646			[USB2PHY_PORT_HOST] = {
1647				.phy_sus	= { 0x0194, 8, 0, 0, 0x1d1 },
1648				.ls_det_en	= { 0x0194, 14, 14, 0, 1 },
1649				.ls_det_st	= { 0x0194, 15, 15, 0, 1 },
1650				.ls_det_clr	= { 0x0194, 15, 15, 0, 1 }
1651			}
1652		},
1653		.chg_det = {
1654			.opmode		= { 0x017c, 3, 0, 5, 1 },
1655			.cp_det		= { 0x02c0, 6, 6, 0, 1 },
1656			.dcp_det	= { 0x02c0, 5, 5, 0, 1 },
1657			.dp_det		= { 0x02c0, 7, 7, 0, 1 },
1658			.idm_sink_en	= { 0x0184, 8, 8, 0, 1 },
1659			.idp_sink_en	= { 0x0184, 7, 7, 0, 1 },
1660			.idp_src_en	= { 0x0184, 9, 9, 0, 1 },
1661			.rdm_pdwn_en	= { 0x0184, 10, 10, 0, 1 },
1662			.vdm_src_en	= { 0x0184, 12, 12, 0, 1 },
1663			.vdp_src_en	= { 0x0184, 11, 11, 0, 1 },
1664		},
1665	},
1666	{ /* sentinel */ }
1667};
1668
1669static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
1670	{
1671		.reg = 0x760,
1672		.num_ports	= 2,
1673		.clkout_ctl	= { 0x0768, 4, 4, 1, 0 },
1674		.port_cfgs	= {
1675			[USB2PHY_PORT_OTG] = {
1676				.phy_sus	= { 0x0760, 15, 0, 0, 0x1d1 },
1677				.bvalid_det_en	= { 0x0680, 3, 3, 0, 1 },
1678				.bvalid_det_st	= { 0x0690, 3, 3, 0, 1 },
1679				.bvalid_det_clr	= { 0x06a0, 3, 3, 0, 1 },
1680				.idfall_det_en	= { 0x0680, 6, 6, 0, 1 },
1681				.idfall_det_st	= { 0x0690, 6, 6, 0, 1 },
1682				.idfall_det_clr	= { 0x06a0, 6, 6, 0, 1 },
1683				.idrise_det_en	= { 0x0680, 5, 5, 0, 1 },
1684				.idrise_det_st	= { 0x0690, 5, 5, 0, 1 },
1685				.idrise_det_clr	= { 0x06a0, 5, 5, 0, 1 },
1686				.ls_det_en	= { 0x0680, 2, 2, 0, 1 },
1687				.ls_det_st	= { 0x0690, 2, 2, 0, 1 },
1688				.ls_det_clr	= { 0x06a0, 2, 2, 0, 1 },
1689				.utmi_bvalid	= { 0x0480, 4, 4, 0, 1 },
1690				.utmi_id	= { 0x0480, 1, 1, 0, 1 },
1691				.utmi_ls	= { 0x0480, 3, 2, 0, 1 },
1692			},
1693			[USB2PHY_PORT_HOST] = {
1694				.phy_sus	= { 0x0764, 15, 0, 0, 0x1d1 },
1695				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
1696				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
1697				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 }
1698			}
1699		},
1700		.chg_det = {
1701			.opmode		= { 0x0760, 3, 0, 5, 1 },
1702			.cp_det		= { 0x0884, 4, 4, 0, 1 },
1703			.dcp_det	= { 0x0884, 3, 3, 0, 1 },
1704			.dp_det		= { 0x0884, 5, 5, 0, 1 },
1705			.idm_sink_en	= { 0x0768, 8, 8, 0, 1 },
1706			.idp_sink_en	= { 0x0768, 7, 7, 0, 1 },
1707			.idp_src_en	= { 0x0768, 9, 9, 0, 1 },
1708			.rdm_pdwn_en	= { 0x0768, 10, 10, 0, 1 },
1709			.vdm_src_en	= { 0x0768, 12, 12, 0, 1 },
1710			.vdp_src_en	= { 0x0768, 11, 11, 0, 1 },
1711		},
1712	},
1713	{
1714		.reg = 0x800,
1715		.num_ports	= 2,
1716		.clkout_ctl	= { 0x0808, 4, 4, 1, 0 },
1717		.port_cfgs	= {
1718			[USB2PHY_PORT_OTG] = {
1719				.phy_sus	= { 0x800, 15, 0, 0, 0x1d1 },
1720				.ls_det_en	= { 0x0684, 0, 0, 0, 1 },
1721				.ls_det_st	= { 0x0694, 0, 0, 0, 1 },
1722				.ls_det_clr	= { 0x06a4, 0, 0, 0, 1 }
1723			},
1724			[USB2PHY_PORT_HOST] = {
1725				.phy_sus	= { 0x804, 15, 0, 0, 0x1d1 },
1726				.ls_det_en	= { 0x0684, 1, 1, 0, 1 },
1727				.ls_det_st	= { 0x0694, 1, 1, 0, 1 },
1728				.ls_det_clr	= { 0x06a4, 1, 1, 0, 1 }
1729			}
1730		},
1731	},
1732	{ /* sentinel */ }
1733};
1734
1735static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = {
1736	{
1737		.reg = 0x100,
1738		.num_ports	= 2,
1739		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
1740		.port_cfgs	= {
1741			[USB2PHY_PORT_OTG] = {
1742				.phy_sus	= { 0x0100, 8, 0, 0, 0x1d1 },
1743				.bvalid_det_en	= { 0x3020, 3, 2, 0, 3 },
1744				.bvalid_det_st	= { 0x3024, 3, 2, 0, 3 },
1745				.bvalid_det_clr = { 0x3028, 3, 2, 0, 3 },
1746				.idfall_det_en	= { 0x3020, 5, 5, 0, 1 },
1747				.idfall_det_st	= { 0x3024, 5, 5, 0, 1 },
1748				.idfall_det_clr = { 0x3028, 5, 5, 0, 1 },
1749				.idrise_det_en	= { 0x3020, 4, 4, 0, 1 },
1750				.idrise_det_st	= { 0x3024, 4, 4, 0, 1 },
1751				.idrise_det_clr = { 0x3028, 4, 4, 0, 1 },
1752				.ls_det_en	= { 0x3020, 0, 0, 0, 1 },
1753				.ls_det_st	= { 0x3024, 0, 0, 0, 1 },
1754				.ls_det_clr	= { 0x3028, 0, 0, 0, 1 },
1755				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
1756				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
1757				.utmi_id	= { 0x0120, 6, 6, 0, 1 },
1758				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
1759			},
1760			[USB2PHY_PORT_HOST] = {
1761				.phy_sus	= { 0x0104, 8, 0, 0, 0x1d1 },
1762				.ls_det_en	= { 0x3020, 1, 1, 0, 1 },
1763				.ls_det_st	= { 0x3024, 1, 1, 0, 1 },
1764				.ls_det_clr	= { 0x3028, 1, 1, 0, 1 },
1765				.utmi_ls	= { 0x0120, 17, 16, 0, 1 },
1766				.utmi_hstdet	= { 0x0120, 19, 19, 0, 1 }
1767			}
1768		},
1769		.chg_det = {
1770			.opmode		= { 0x0100, 3, 0, 5, 1 },
1771			.cp_det		= { 0x0120, 24, 24, 0, 1 },
1772			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
1773			.dp_det		= { 0x0120, 25, 25, 0, 1 },
1774			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
1775			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
1776			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
1777			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
1778			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
1779			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
1780		},
1781	},
1782	{ /* sentinel */ }
1783};
1784
1785static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
1786	{
1787		.reg = 0x100,
1788		.num_ports	= 2,
1789		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
1790		.port_cfgs	= {
1791			[USB2PHY_PORT_OTG] = {
1792				.phy_sus	= { 0x0100, 15, 0, 0, 0x1d1 },
1793				.bvalid_det_en	= { 0x0110, 3, 2, 0, 3 },
1794				.bvalid_det_st	= { 0x0114, 3, 2, 0, 3 },
1795				.bvalid_det_clr = { 0x0118, 3, 2, 0, 3 },
1796				.idfall_det_en	= { 0x0110, 5, 5, 0, 1 },
1797				.idfall_det_st	= { 0x0114, 5, 5, 0, 1 },
1798				.idfall_det_clr = { 0x0118, 5, 5, 0, 1 },
1799				.idrise_det_en	= { 0x0110, 4, 4, 0, 1 },
1800				.idrise_det_st	= { 0x0114, 4, 4, 0, 1 },
1801				.idrise_det_clr = { 0x0118, 4, 4, 0, 1 },
1802				.ls_det_en	= { 0x0110, 0, 0, 0, 1 },
1803				.ls_det_st	= { 0x0114, 0, 0, 0, 1 },
1804				.ls_det_clr	= { 0x0118, 0, 0, 0, 1 },
1805				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
1806				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
1807				.utmi_id	= { 0x0120, 6, 6, 0, 1 },
1808				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
1809			},
1810			[USB2PHY_PORT_HOST] = {
1811				.phy_sus	= { 0x104, 15, 0, 0, 0x1d1 },
1812				.ls_det_en	= { 0x110, 1, 1, 0, 1 },
1813				.ls_det_st	= { 0x114, 1, 1, 0, 1 },
1814				.ls_det_clr	= { 0x118, 1, 1, 0, 1 },
1815				.utmi_ls	= { 0x120, 17, 16, 0, 1 },
1816				.utmi_hstdet	= { 0x120, 19, 19, 0, 1 }
1817			}
1818		},
1819		.chg_det = {
1820			.opmode		= { 0x0100, 3, 0, 5, 1 },
1821			.cp_det		= { 0x0120, 24, 24, 0, 1 },
1822			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
1823			.dp_det		= { 0x0120, 25, 25, 0, 1 },
1824			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
1825			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
1826			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
1827			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
1828			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
1829			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
1830		},
1831	},
1832	{ /* sentinel */ }
1833};
1834
1835static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
1836	{
1837		.reg = 0x700,
1838		.num_ports	= 2,
1839		.clkout_ctl	= { 0x0724, 15, 15, 1, 0 },
1840		.port_cfgs	= {
1841			[USB2PHY_PORT_HOST] = {
1842				.phy_sus	= { 0x0728, 15, 0, 0, 0x1d1 },
1843				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
1844				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
1845				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 },
1846				.utmi_ls	= { 0x049c, 14, 13, 0, 1 },
1847				.utmi_hstdet	= { 0x049c, 12, 12, 0, 1 }
1848			}
1849		},
1850	},
1851	{ /* sentinel */ }
1852};
1853
1854static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
1855	{
1856		.reg		= 0xe450,
1857		.num_ports	= 2,
1858		.clkout_ctl	= { 0xe450, 4, 4, 1, 0 },
1859		.port_cfgs	= {
1860			[USB2PHY_PORT_OTG] = {
1861				.phy_sus	= { 0xe454, 1, 0, 2, 1 },
1862				.bvalid_det_en	= { 0xe3c0, 3, 3, 0, 1 },
1863				.bvalid_det_st	= { 0xe3e0, 3, 3, 0, 1 },
1864				.bvalid_det_clr	= { 0xe3d0, 3, 3, 0, 1 },
1865				.idfall_det_en	= { 0xe3c0, 5, 5, 0, 1 },
1866				.idfall_det_st	= { 0xe3e0, 5, 5, 0, 1 },
1867				.idfall_det_clr	= { 0xe3d0, 5, 5, 0, 1 },
1868				.idrise_det_en	= { 0xe3c0, 4, 4, 0, 1 },
1869				.idrise_det_st	= { 0xe3e0, 4, 4, 0, 1 },
1870				.idrise_det_clr	= { 0xe3d0, 4, 4, 0, 1 },
1871				.utmi_avalid	= { 0xe2ac, 7, 7, 0, 1 },
1872				.utmi_bvalid	= { 0xe2ac, 12, 12, 0, 1 },
1873				.utmi_id	= { 0xe2ac, 8, 8, 0, 1 },
1874			},
1875			[USB2PHY_PORT_HOST] = {
1876				.phy_sus	= { 0xe458, 1, 0, 0x2, 0x1 },
1877				.ls_det_en	= { 0xe3c0, 6, 6, 0, 1 },
1878				.ls_det_st	= { 0xe3e0, 6, 6, 0, 1 },
1879				.ls_det_clr	= { 0xe3d0, 6, 6, 0, 1 },
1880				.utmi_ls	= { 0xe2ac, 22, 21, 0, 1 },
1881				.utmi_hstdet	= { 0xe2ac, 23, 23, 0, 1 }
1882			}
1883		},
1884		.chg_det = {
1885			.opmode		= { 0xe454, 3, 0, 5, 1 },
1886			.cp_det		= { 0xe2ac, 2, 2, 0, 1 },
1887			.dcp_det	= { 0xe2ac, 1, 1, 0, 1 },
1888			.dp_det		= { 0xe2ac, 0, 0, 0, 1 },
1889			.idm_sink_en	= { 0xe450, 8, 8, 0, 1 },
1890			.idp_sink_en	= { 0xe450, 7, 7, 0, 1 },
1891			.idp_src_en	= { 0xe450, 9, 9, 0, 1 },
1892			.rdm_pdwn_en	= { 0xe450, 10, 10, 0, 1 },
1893			.vdm_src_en	= { 0xe450, 12, 12, 0, 1 },
1894			.vdp_src_en	= { 0xe450, 11, 11, 0, 1 },
1895		},
1896	},
1897	{
1898		.reg		= 0xe460,
1899		.num_ports	= 2,
1900		.clkout_ctl	= { 0xe460, 4, 4, 1, 0 },
1901		.port_cfgs	= {
1902			[USB2PHY_PORT_OTG] = {
1903				.phy_sus        = { 0xe464, 1, 0, 2, 1 },
1904				.bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
1905				.bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
1906				.bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
1907				.idfall_det_en	= { 0xe3c0, 10, 10, 0, 1 },
1908				.idfall_det_st	= { 0xe3e0, 10, 10, 0, 1 },
1909				.idfall_det_clr	= { 0xe3d0, 10, 10, 0, 1 },
1910				.idrise_det_en	= { 0xe3c0, 9, 9, 0, 1 },
1911				.idrise_det_st	= { 0xe3e0, 9, 9, 0, 1 },
1912				.idrise_det_clr	= { 0xe3d0, 9, 9, 0, 1 },
1913				.utmi_avalid	= { 0xe2ac, 10, 10, 0, 1 },
1914				.utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
1915				.utmi_id	= { 0xe2ac, 11, 11, 0, 1 },
1916			},
1917			[USB2PHY_PORT_HOST] = {
1918				.phy_sus	= { 0xe468, 1, 0, 0x2, 0x1 },
1919				.ls_det_en	= { 0xe3c0, 11, 11, 0, 1 },
1920				.ls_det_st	= { 0xe3e0, 11, 11, 0, 1 },
1921				.ls_det_clr	= { 0xe3d0, 11, 11, 0, 1 },
1922				.utmi_ls	= { 0xe2ac, 26, 25, 0, 1 },
1923				.utmi_hstdet	= { 0xe2ac, 27, 27, 0, 1 }
1924			}
1925		},
1926	},
1927	{ /* sentinel */ }
1928};
1929
1930static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = {
1931	{
1932		.reg = 0xff740000,
1933		.num_ports	= 2,
1934		.clkout_ctl	= { 0x0108, 4, 4, 1, 0 },
1935		.port_cfgs	= {
1936			[USB2PHY_PORT_OTG] = {
1937				.phy_sus	= { 0x0100, 8, 0, 0, 0x1d1 },
1938				.bvalid_det_en	= { 0x0110, 2, 2, 0, 1 },
1939				.bvalid_det_st	= { 0x0114, 2, 2, 0, 1 },
1940				.bvalid_det_clr = { 0x0118, 2, 2, 0, 1 },
1941				.idfall_det_en	= { 0x0110, 5, 5, 0, 1 },
1942				.idfall_det_st	= { 0x0114, 5, 5, 0, 1 },
1943				.idfall_det_clr = { 0x0118, 5, 5, 0, 1 },
1944				.idrise_det_en	= { 0x0110, 4, 4, 0, 1 },
1945				.idrise_det_st	= { 0x0114, 4, 4, 0, 1 },
1946				.idrise_det_clr = { 0x0118, 4, 4, 0, 1 },
1947				.ls_det_en	= { 0x0110, 0, 0, 0, 1 },
1948				.ls_det_st	= { 0x0114, 0, 0, 0, 1 },
1949				.ls_det_clr	= { 0x0118, 0, 0, 0, 1 },
1950				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
1951				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
1952				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
1953			},
1954			[USB2PHY_PORT_HOST] = {
1955				.phy_sus	= { 0x0104, 8, 0, 0x1d2, 0x1d1 },
1956				.ls_det_en	= { 0x0110, 1, 1, 0, 1 },
1957				.ls_det_st	= { 0x0114, 1, 1, 0, 1 },
1958				.ls_det_clr	= { 0x0118, 1, 1, 0, 1 },
1959				.utmi_ls	= { 0x0120, 17, 16, 0, 1 },
1960				.utmi_hstdet	= { 0x0120, 19, 19, 0, 1 }
1961			}
1962		},
1963		.chg_det = {
1964			.cp_det		= { 0x0120, 24, 24, 0, 1 },
1965			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
1966			.dp_det		= { 0x0120, 25, 25, 0, 1 },
1967			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
1968			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
1969			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
1970			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
1971			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
1972			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
1973		},
1974	},
1975	{ /* sentinel */ }
1976};
1977
1978static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
1979	{
1980		.reg = 0xfe8a0000,
1981		.num_ports	= 2,
1982		.clkout_ctl	= { 0x0008, 4, 4, 1, 0 },
1983		.port_cfgs	= {
1984			[USB2PHY_PORT_OTG] = {
1985				.phy_sus	= { 0x0000, 8, 0, 0, 0x1d1 },
1986				.bvalid_det_en	= { 0x0080, 3, 2, 0, 3 },
1987				.bvalid_det_st	= { 0x0084, 3, 2, 0, 3 },
1988				.bvalid_det_clr = { 0x0088, 3, 2, 0, 3 },
1989				.idfall_det_en	= { 0x0080, 5, 5, 0, 1 },
1990				.idfall_det_st	= { 0x0084, 5, 5, 0, 1 },
1991				.idfall_det_clr	= { 0x0088, 5, 5, 0, 1 },
1992				.idrise_det_en	= { 0x0080, 4, 4, 0, 1 },
1993				.idrise_det_st	= { 0x0084, 4, 4, 0, 1 },
1994				.idrise_det_clr	= { 0x0088, 4, 4, 0, 1 },
1995				.utmi_avalid	= { 0x00c0, 10, 10, 0, 1 },
1996				.utmi_bvalid	= { 0x00c0, 9, 9, 0, 1 },
1997				.utmi_id	= { 0x00c0, 6, 6, 0, 1 },
1998			},
1999			[USB2PHY_PORT_HOST] = {
2000				/* Select suspend control from controller */
2001				.phy_sus	= { 0x0004, 8, 0, 0x1d2, 0x1d2 },
2002				.ls_det_en	= { 0x0080, 1, 1, 0, 1 },
2003				.ls_det_st	= { 0x0084, 1, 1, 0, 1 },
2004				.ls_det_clr	= { 0x0088, 1, 1, 0, 1 },
2005				.utmi_ls	= { 0x00c0, 17, 16, 0, 1 },
2006				.utmi_hstdet	= { 0x00c0, 19, 19, 0, 1 }
2007			}
2008		},
2009		.chg_det = {
2010			.opmode		= { 0x0000, 3, 0, 5, 1 },
2011			.cp_det		= { 0x00c0, 24, 24, 0, 1 },
2012			.dcp_det	= { 0x00c0, 23, 23, 0, 1 },
2013			.dp_det		= { 0x00c0, 25, 25, 0, 1 },
2014			.idm_sink_en	= { 0x0008, 8, 8, 0, 1 },
2015			.idp_sink_en	= { 0x0008, 7, 7, 0, 1 },
2016			.idp_src_en	= { 0x0008, 9, 9, 0, 1 },
2017			.rdm_pdwn_en	= { 0x0008, 10, 10, 0, 1 },
2018			.vdm_src_en	= { 0x0008, 12, 12, 0, 1 },
2019			.vdp_src_en	= { 0x0008, 11, 11, 0, 1 },
2020		},
2021	},
2022	{
2023		.reg = 0xfe8b0000,
2024		.num_ports	= 2,
2025		.clkout_ctl	= { 0x0008, 4, 4, 1, 0 },
2026		.port_cfgs	= {
2027			[USB2PHY_PORT_OTG] = {
2028				.phy_sus	= { 0x0000, 8, 0, 0x1d2, 0x1d1 },
2029				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2030				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2031				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2032				.utmi_ls	= { 0x00c0, 5, 4, 0, 1 },
2033				.utmi_hstdet	= { 0x00c0, 7, 7, 0, 1 }
2034			},
2035			[USB2PHY_PORT_HOST] = {
2036				.phy_sus	= { 0x0004, 8, 0, 0x1d2, 0x1d1 },
2037				.ls_det_en	= { 0x0080, 1, 1, 0, 1 },
2038				.ls_det_st	= { 0x0084, 1, 1, 0, 1 },
2039				.ls_det_clr	= { 0x0088, 1, 1, 0, 1 },
2040				.utmi_ls	= { 0x00c0, 17, 16, 0, 1 },
2041				.utmi_hstdet	= { 0x00c0, 19, 19, 0, 1 }
2042			}
2043		},
2044	},
2045	{ /* sentinel */ }
2046};
2047
2048static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
2049	{
2050		.reg = 0x0,
2051		.num_ports	= 1,
2052		.phy_tuning	= rk3576_usb2phy_tuning,
2053		.clkout_ctl	= { 0x0008, 0, 0, 1, 0 },
2054		.port_cfgs	= {
2055			[USB2PHY_PORT_OTG] = {
2056				.phy_sus	= { 0x0000, 8, 0, 0, 0x1d1 },
2057				.bvalid_det_en	= { 0x00c0, 1, 1, 0, 1 },
2058				.bvalid_det_st	= { 0x00c4, 1, 1, 0, 1 },
2059				.bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
2060				.ls_det_en	= { 0x00c0, 0, 0, 0, 1 },
2061				.ls_det_st	= { 0x00c4, 0, 0, 0, 1 },
2062				.ls_det_clr	= { 0x00c8, 0, 0, 0, 1 },
2063				.disfall_en	= { 0x00c0, 6, 6, 0, 1 },
2064				.disfall_st	= { 0x00c4, 6, 6, 0, 1 },
2065				.disfall_clr	= { 0x00c8, 6, 6, 0, 1 },
2066				.disrise_en	= { 0x00c0, 5, 5, 0, 1 },
2067				.disrise_st	= { 0x00c4, 5, 5, 0, 1 },
2068				.disrise_clr	= { 0x00c8, 5, 5, 0, 1 },
2069				.utmi_avalid	= { 0x0080, 1, 1, 0, 1 },
2070				.utmi_bvalid	= { 0x0080, 0, 0, 0, 1 },
2071				.utmi_ls	= { 0x0080, 5, 4, 0, 1 },
2072			}
2073		},
2074		.chg_det = {
2075			.cp_det		= { 0x0080, 8, 8, 0, 1 },
2076			.dcp_det	= { 0x0080, 8, 8, 0, 1 },
2077			.dp_det		= { 0x0080, 9, 9, 1, 0 },
2078			.idm_sink_en	= { 0x0010, 5, 5, 1, 0 },
2079			.idp_sink_en	= { 0x0010, 5, 5, 0, 1 },
2080			.idp_src_en	= { 0x0010, 14, 14, 0, 1 },
2081			.rdm_pdwn_en	= { 0x0010, 14, 14, 0, 1 },
2082			.vdm_src_en	= { 0x0010, 7, 6, 0, 3 },
2083			.vdp_src_en	= { 0x0010, 7, 6, 0, 3 },
2084		},
2085	},
2086	{
2087		.reg = 0x2000,
2088		.num_ports	= 1,
2089		.phy_tuning	= rk3576_usb2phy_tuning,
2090		.clkout_ctl	= { 0x2008, 0, 0, 1, 0 },
2091		.port_cfgs	= {
2092			[USB2PHY_PORT_OTG] = {
2093				.phy_sus	= { 0x2000, 8, 0, 0, 0x1d1 },
2094				.bvalid_det_en	= { 0x20c0, 1, 1, 0, 1 },
2095				.bvalid_det_st	= { 0x20c4, 1, 1, 0, 1 },
2096				.bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
2097				.ls_det_en	= { 0x20c0, 0, 0, 0, 1 },
2098				.ls_det_st	= { 0x20c4, 0, 0, 0, 1 },
2099				.ls_det_clr	= { 0x20c8, 0, 0, 0, 1 },
2100				.disfall_en	= { 0x20c0, 6, 6, 0, 1 },
2101				.disfall_st	= { 0x20c4, 6, 6, 0, 1 },
2102				.disfall_clr	= { 0x20c8, 6, 6, 0, 1 },
2103				.disrise_en	= { 0x20c0, 5, 5, 0, 1 },
2104				.disrise_st	= { 0x20c4, 5, 5, 0, 1 },
2105				.disrise_clr	= { 0x20c8, 5, 5, 0, 1 },
2106				.utmi_avalid	= { 0x2080, 1, 1, 0, 1 },
2107				.utmi_bvalid	= { 0x2080, 0, 0, 0, 1 },
2108				.utmi_ls	= { 0x2080, 5, 4, 0, 1 },
2109			}
2110		},
2111		.chg_det = {
2112			.cp_det		= { 0x2080, 8, 8, 0, 1 },
2113			.dcp_det	= { 0x2080, 8, 8, 0, 1 },
2114			.dp_det		= { 0x2080, 9, 9, 1, 0 },
2115			.idm_sink_en	= { 0x2010, 5, 5, 1, 0 },
2116			.idp_sink_en	= { 0x2010, 5, 5, 0, 1 },
2117			.idp_src_en	= { 0x2010, 14, 14, 0, 1 },
2118			.rdm_pdwn_en	= { 0x2010, 14, 14, 0, 1 },
2119			.vdm_src_en	= { 0x2010, 7, 6, 0, 3 },
2120			.vdp_src_en	= { 0x2010, 7, 6, 0, 3 },
2121		},
2122	},
2123	{ /* sentinel */ }
2124};
2125
2126static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
2127	{
2128		.reg = 0x0000,
2129		.num_ports	= 1,
2130		.phy_tuning	= rk3588_usb2phy_tuning,
2131		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2132		.port_cfgs	= {
2133			[USB2PHY_PORT_OTG] = {
2134				.phy_sus	= { 0x000c, 11, 11, 0, 1 },
2135				.bvalid_det_en	= { 0x0080, 1, 1, 0, 1 },
2136				.bvalid_det_st	= { 0x0084, 1, 1, 0, 1 },
2137				.bvalid_det_clr = { 0x0088, 1, 1, 0, 1 },
2138				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2139				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2140				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2141				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2142				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2143				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2144				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2145				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2146				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2147				.utmi_avalid	= { 0x00c0, 7, 7, 0, 1 },
2148				.utmi_bvalid	= { 0x00c0, 6, 6, 0, 1 },
2149				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2150			}
2151		},
2152		.chg_det = {
2153			.cp_det		= { 0x00c0, 0, 0, 0, 1 },
2154			.dcp_det	= { 0x00c0, 0, 0, 0, 1 },
2155			.dp_det		= { 0x00c0, 1, 1, 1, 0 },
2156			.idm_sink_en	= { 0x0008, 5, 5, 1, 0 },
2157			.idp_sink_en	= { 0x0008, 5, 5, 0, 1 },
2158			.idp_src_en	= { 0x0008, 14, 14, 0, 1 },
2159			.rdm_pdwn_en	= { 0x0008, 14, 14, 0, 1 },
2160			.vdm_src_en	= { 0x0008, 7, 6, 0, 3 },
2161			.vdp_src_en	= { 0x0008, 7, 6, 0, 3 },
2162		},
2163	},
2164	{
2165		.reg = 0x4000,
2166		.num_ports	= 1,
2167		.phy_tuning	= rk3588_usb2phy_tuning,
2168		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2169		.port_cfgs	= {
2170			[USB2PHY_PORT_OTG] = {
2171				.phy_sus	= { 0x000c, 11, 11, 0, 1 },
2172				.bvalid_det_en	= { 0x0080, 1, 1, 0, 1 },
2173				.bvalid_det_st	= { 0x0084, 1, 1, 0, 1 },
2174				.bvalid_det_clr = { 0x0088, 1, 1, 0, 1 },
2175				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2176				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2177				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2178				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2179				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2180				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2181				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2182				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2183				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2184				.utmi_avalid	= { 0x00c0, 7, 7, 0, 1 },
2185				.utmi_bvalid	= { 0x00c0, 6, 6, 0, 1 },
2186				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2187			}
2188		},
2189		.chg_det = {
2190			.cp_det		= { 0x00c0, 0, 0, 0, 1 },
2191			.dcp_det	= { 0x00c0, 0, 0, 0, 1 },
2192			.dp_det		= { 0x00c0, 1, 1, 1, 0 },
2193			.idm_sink_en	= { 0x0008, 5, 5, 1, 0 },
2194			.idp_sink_en	= { 0x0008, 5, 5, 0, 1 },
2195			.idp_src_en	= { 0x0008, 14, 14, 0, 1 },
2196			.rdm_pdwn_en	= { 0x0008, 14, 14, 0, 1 },
2197			.vdm_src_en	= { 0x0008, 7, 6, 0, 3 },
2198			.vdp_src_en	= { 0x0008, 7, 6, 0, 3 },
2199		},
2200	},
2201	{
2202		.reg = 0x8000,
2203		.num_ports	= 1,
2204		.phy_tuning	= rk3588_usb2phy_tuning,
2205		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2206		.port_cfgs	= {
2207			[USB2PHY_PORT_HOST] = {
2208				.phy_sus	= { 0x0008, 2, 2, 0, 1 },
2209				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2210				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2211				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2212				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2213				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2214				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2215				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2216				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2217				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2218				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2219			}
2220		},
2221	},
2222	{
2223		.reg = 0xc000,
2224		.num_ports	= 1,
2225		.phy_tuning	= rk3588_usb2phy_tuning,
2226		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2227		.port_cfgs	= {
2228			[USB2PHY_PORT_HOST] = {
2229				.phy_sus	= { 0x0008, 2, 2, 0, 1 },
2230				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2231				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2232				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2233				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2234				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2235				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2236				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2237				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2238				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2239				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2240			}
2241		},
2242	},
2243	{ /* sentinel */ }
2244};
2245
2246static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
2247	{
2248		.reg = 0x100,
2249		.num_ports	= 2,
2250		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
2251		.port_cfgs	= {
2252			[USB2PHY_PORT_OTG] = {
2253				.phy_sus	= { 0x0100, 15, 0, 0, 0x1d1 },
2254				.bvalid_det_en	= { 0x0680, 3, 3, 0, 1 },
2255				.bvalid_det_st	= { 0x0690, 3, 3, 0, 1 },
2256				.bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
2257				.ls_det_en	= { 0x0680, 2, 2, 0, 1 },
2258				.ls_det_st	= { 0x0690, 2, 2, 0, 1 },
2259				.ls_det_clr	= { 0x06a0, 2, 2, 0, 1 },
2260				.utmi_bvalid	= { 0x0804, 10, 10, 0, 1 },
2261				.utmi_ls	= { 0x0804, 13, 12, 0, 1 },
2262			},
2263			[USB2PHY_PORT_HOST] = {
2264				.phy_sus	= { 0x0104, 15, 0, 0, 0x1d1 },
2265				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
2266				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
2267				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 },
2268				.utmi_ls	= { 0x0804, 9, 8, 0, 1 },
2269				.utmi_hstdet	= { 0x0804, 7, 7, 0, 1 }
2270			}
2271		},
2272		.chg_det = {
2273			.opmode		= { 0x0100, 3, 0, 5, 1 },
2274			.cp_det		= { 0x0804, 1, 1, 0, 1 },
2275			.dcp_det	= { 0x0804, 0, 0, 0, 1 },
2276			.dp_det		= { 0x0804, 2, 2, 0, 1 },
2277			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
2278			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
2279			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
2280			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
2281			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
2282			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
2283		},
2284	},
2285	{ /* sentinel */ }
2286};
2287
2288static const struct of_device_id rockchip_usb2phy_dt_match[] = {
2289	{ .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
2290	{ .compatible = "rockchip,rk3036-usb2phy", .data = &rk3036_phy_cfgs },
2291	{ .compatible = "rockchip,rk3128-usb2phy", .data = &rk3128_phy_cfgs },
2292	{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
2293	{ .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
2294	{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
2295	{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
2296	{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
2297	{ .compatible = "rockchip,rk3562-usb2phy", .data = &rk3562_phy_cfgs },
2298	{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
2299	{ .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
2300	{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
2301	{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
2302	{}
2303};
2304MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
2305
2306static struct platform_driver rockchip_usb2phy_driver = {
2307	.probe		= rockchip_usb2phy_probe,
2308	.driver		= {
2309		.name	= "rockchip-usb2phy",
2310		.of_match_table = rockchip_usb2phy_dt_match,
2311	},
2312};
2313module_platform_driver(rockchip_usb2phy_driver);
2314
2315MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
2316MODULE_DESCRIPTION("Rockchip USB2.0 PHY driver");
2317MODULE_LICENSE("GPL v2");
~/ Read-only file preview.