xref: /openbmc/linux/drivers/usb/cdns3/drd.c (revision 55e43d6abd078ed6d219902ce8cb4d68e3c993ba)
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Cadence USBSS and USBSSP DRD Driver.
4   *
5   * Copyright (C) 2018-2020 Cadence.
6   * Copyright (C) 2019 Texas Instruments
7   *
8   * Author: Pawel Laszczak <pawell@cadence.com>
9   *         Roger Quadros <rogerq@ti.com>
10   *
11   */
12  #include <linux/kernel.h>
13  #include <linux/interrupt.h>
14  #include <linux/delay.h>
15  #include <linux/iopoll.h>
16  #include <linux/usb/otg.h>
17  
18  #include "drd.h"
19  #include "core.h"
20  
21  /**
22   * cdns_set_mode - change mode of OTG Core
23   * @cdns: pointer to context structure
24   * @mode: selected mode from cdns_role
25   *
26   * Returns 0 on success otherwise negative errno
27   */
cdns_set_mode(struct cdns * cdns,enum usb_dr_mode mode)28  static int cdns_set_mode(struct cdns *cdns, enum usb_dr_mode mode)
29  {
30  	void __iomem  *override_reg;
31  	u32 reg;
32  
33  	switch (mode) {
34  	case USB_DR_MODE_PERIPHERAL:
35  		break;
36  	case USB_DR_MODE_HOST:
37  		break;
38  	case USB_DR_MODE_OTG:
39  		dev_dbg(cdns->dev, "Set controller to OTG mode\n");
40  
41  		if (cdns->version == CDNSP_CONTROLLER_V2)
42  			override_reg = &cdns->otg_cdnsp_regs->override;
43  		else if (cdns->version == CDNS3_CONTROLLER_V1)
44  			override_reg = &cdns->otg_v1_regs->override;
45  		else
46  			override_reg = &cdns->otg_v0_regs->ctrl1;
47  
48  		reg = readl(override_reg);
49  
50  		if (cdns->version != CDNS3_CONTROLLER_V0)
51  			reg |= OVERRIDE_IDPULLUP;
52  		else
53  			reg |= OVERRIDE_IDPULLUP_V0;
54  
55  		writel(reg, override_reg);
56  
57  		if (cdns->version == CDNS3_CONTROLLER_V1) {
58  			/*
59  			 * Enable work around feature built into the
60  			 * controller to address issue with RX Sensitivity
61  			 * est (EL_17) for USB2 PHY. The issue only occures
62  			 * for 0x0002450D controller version.
63  			 */
64  			if (cdns->phyrst_a_enable) {
65  				reg = readl(&cdns->otg_v1_regs->phyrst_cfg);
66  				reg |= PHYRST_CFG_PHYRST_A_ENABLE;
67  				writel(reg, &cdns->otg_v1_regs->phyrst_cfg);
68  			}
69  		}
70  
71  		/*
72  		 * Hardware specification says: "ID_VALUE must be valid within
73  		 * 50ms after idpullup is set to '1" so driver must wait
74  		 * 50ms before reading this pin.
75  		 */
76  		usleep_range(50000, 60000);
77  		break;
78  	default:
79  		dev_err(cdns->dev, "Unsupported mode of operation %d\n", mode);
80  		return -EINVAL;
81  	}
82  
83  	return 0;
84  }
85  
cdns_get_id(struct cdns * cdns)86  int cdns_get_id(struct cdns *cdns)
87  {
88  	int id;
89  
90  	id = readl(&cdns->otg_regs->sts) & OTGSTS_ID_VALUE;
91  	dev_dbg(cdns->dev, "OTG ID: %d", id);
92  
93  	return id;
94  }
95  
cdns_get_vbus(struct cdns * cdns)96  int cdns_get_vbus(struct cdns *cdns)
97  {
98  	int vbus;
99  
100  	vbus = !!(readl(&cdns->otg_regs->sts) & OTGSTS_VBUS_VALID);
101  	dev_dbg(cdns->dev, "OTG VBUS: %d", vbus);
102  
103  	return vbus;
104  }
105  
cdns_clear_vbus(struct cdns * cdns)106  void cdns_clear_vbus(struct cdns *cdns)
107  {
108  	u32 reg;
109  
110  	if (cdns->version != CDNSP_CONTROLLER_V2)
111  		return;
112  
113  	reg = readl(&cdns->otg_cdnsp_regs->override);
114  	reg |= OVERRIDE_SESS_VLD_SEL;
115  	writel(reg, &cdns->otg_cdnsp_regs->override);
116  }
117  EXPORT_SYMBOL_GPL(cdns_clear_vbus);
118  
cdns_set_vbus(struct cdns * cdns)119  void cdns_set_vbus(struct cdns *cdns)
120  {
121  	u32 reg;
122  
123  	if (cdns->version != CDNSP_CONTROLLER_V2)
124  		return;
125  
126  	reg = readl(&cdns->otg_cdnsp_regs->override);
127  	reg &= ~OVERRIDE_SESS_VLD_SEL;
128  	writel(reg, &cdns->otg_cdnsp_regs->override);
129  }
130  EXPORT_SYMBOL_GPL(cdns_set_vbus);
131  
cdns_is_host(struct cdns * cdns)132  bool cdns_is_host(struct cdns *cdns)
133  {
134  	if (cdns->dr_mode == USB_DR_MODE_HOST)
135  		return true;
136  	else if (cdns_get_id(cdns) == CDNS3_ID_HOST)
137  		return true;
138  
139  	return false;
140  }
141  
cdns_is_device(struct cdns * cdns)142  bool cdns_is_device(struct cdns *cdns)
143  {
144  	if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL)
145  		return true;
146  	else if (cdns->dr_mode == USB_DR_MODE_OTG)
147  		if (cdns_get_id(cdns) == CDNS3_ID_PERIPHERAL)
148  			return true;
149  
150  	return false;
151  }
152  
153  /**
154   * cdns_otg_disable_irq - Disable all OTG interrupts
155   * @cdns: Pointer to controller context structure
156   */
cdns_otg_disable_irq(struct cdns * cdns)157  static void cdns_otg_disable_irq(struct cdns *cdns)
158  {
159  	if (cdns->version)
160  		writel(0, &cdns->otg_irq_regs->ien);
161  }
162  
163  /**
164   * cdns_otg_enable_irq - enable id and sess_valid interrupts
165   * @cdns: Pointer to controller context structure
166   */
cdns_otg_enable_irq(struct cdns * cdns)167  static void cdns_otg_enable_irq(struct cdns *cdns)
168  {
169  	writel(OTGIEN_ID_CHANGE_INT | OTGIEN_VBUSVALID_RISE_INT |
170  	       OTGIEN_VBUSVALID_FALL_INT, &cdns->otg_irq_regs->ien);
171  }
172  
173  /**
174   * cdns_drd_host_on - start host.
175   * @cdns: Pointer to controller context structure.
176   *
177   * Returns 0 on success otherwise negative errno.
178   */
cdns_drd_host_on(struct cdns * cdns)179  int cdns_drd_host_on(struct cdns *cdns)
180  {
181  	u32 val, ready_bit;
182  	int ret;
183  
184  	/* Enable host mode. */
185  	writel(OTGCMD_HOST_BUS_REQ | OTGCMD_OTG_DIS,
186  	       &cdns->otg_regs->cmd);
187  
188  	if (cdns->version == CDNSP_CONTROLLER_V2)
189  		ready_bit = OTGSTS_CDNSP_XHCI_READY;
190  	else
191  		ready_bit = OTGSTS_CDNS3_XHCI_READY;
192  
193  	dev_dbg(cdns->dev, "Waiting till Host mode is turned on\n");
194  	ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
195  					val & ready_bit, 1, 100000);
196  
197  	if (ret)
198  		dev_err(cdns->dev, "timeout waiting for xhci_ready\n");
199  
200  	phy_set_mode(cdns->usb2_phy, PHY_MODE_USB_HOST);
201  	phy_set_mode(cdns->usb3_phy, PHY_MODE_USB_HOST);
202  	return ret;
203  }
204  
205  /**
206   * cdns_drd_host_off - stop host.
207   * @cdns: Pointer to controller context structure.
208   */
cdns_drd_host_off(struct cdns * cdns)209  void cdns_drd_host_off(struct cdns *cdns)
210  {
211  	u32 val;
212  
213  	writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
214  	       OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
215  	       &cdns->otg_regs->cmd);
216  
217  	/* Waiting till H_IDLE state.*/
218  	readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
219  				  !(val & OTGSTATE_HOST_STATE_MASK),
220  				  1, 2000000);
221  	phy_set_mode(cdns->usb2_phy, PHY_MODE_INVALID);
222  	phy_set_mode(cdns->usb3_phy, PHY_MODE_INVALID);
223  }
224  
225  /**
226   * cdns_drd_gadget_on - start gadget.
227   * @cdns: Pointer to controller context structure.
228   *
229   * Returns 0 on success otherwise negative errno
230   */
cdns_drd_gadget_on(struct cdns * cdns)231  int cdns_drd_gadget_on(struct cdns *cdns)
232  {
233  	u32 reg = OTGCMD_OTG_DIS;
234  	u32 ready_bit;
235  	int ret, val;
236  
237  	/* switch OTG core */
238  	writel(OTGCMD_DEV_BUS_REQ | reg, &cdns->otg_regs->cmd);
239  
240  	dev_dbg(cdns->dev, "Waiting till Device mode is turned on\n");
241  
242  	if (cdns->version == CDNSP_CONTROLLER_V2)
243  		ready_bit = OTGSTS_CDNSP_DEV_READY;
244  	else
245  		ready_bit = OTGSTS_CDNS3_DEV_READY;
246  
247  	ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
248  					val & ready_bit, 1, 100000);
249  	if (ret) {
250  		dev_err(cdns->dev, "timeout waiting for dev_ready\n");
251  		return ret;
252  	}
253  
254  	phy_set_mode(cdns->usb2_phy, PHY_MODE_USB_DEVICE);
255  	phy_set_mode(cdns->usb3_phy, PHY_MODE_USB_DEVICE);
256  	return 0;
257  }
258  EXPORT_SYMBOL_GPL(cdns_drd_gadget_on);
259  
260  /**
261   * cdns_drd_gadget_off - stop gadget.
262   * @cdns: Pointer to controller context structure.
263   */
cdns_drd_gadget_off(struct cdns * cdns)264  void cdns_drd_gadget_off(struct cdns *cdns)
265  {
266  	u32 val;
267  
268  	/*
269  	 * Driver should wait at least 10us after disabling Device
270  	 * before turning-off Device (DEV_BUS_DROP).
271  	 */
272  	usleep_range(20, 30);
273  	writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
274  	       OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
275  	       &cdns->otg_regs->cmd);
276  	/* Waiting till DEV_IDLE state.*/
277  	readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
278  				  !(val & OTGSTATE_DEV_STATE_MASK),
279  				  1, 2000000);
280  	phy_set_mode(cdns->usb2_phy, PHY_MODE_INVALID);
281  	phy_set_mode(cdns->usb3_phy, PHY_MODE_INVALID);
282  }
283  EXPORT_SYMBOL_GPL(cdns_drd_gadget_off);
284  
285  /**
286   * cdns_init_otg_mode - initialize drd controller
287   * @cdns: Pointer to controller context structure
288   *
289   * Returns 0 on success otherwise negative errno
290   */
cdns_init_otg_mode(struct cdns * cdns)291  static int cdns_init_otg_mode(struct cdns *cdns)
292  {
293  	int ret;
294  
295  	cdns_otg_disable_irq(cdns);
296  	/* clear all interrupts */
297  	writel(~0, &cdns->otg_irq_regs->ivect);
298  
299  	ret = cdns_set_mode(cdns, USB_DR_MODE_OTG);
300  	if (ret)
301  		return ret;
302  
303  	cdns_otg_enable_irq(cdns);
304  
305  	return 0;
306  }
307  
308  /**
309   * cdns_drd_update_mode - initialize mode of operation
310   * @cdns: Pointer to controller context structure
311   *
312   * Returns 0 on success otherwise negative errno
313   */
cdns_drd_update_mode(struct cdns * cdns)314  int cdns_drd_update_mode(struct cdns *cdns)
315  {
316  	int ret;
317  
318  	switch (cdns->dr_mode) {
319  	case USB_DR_MODE_PERIPHERAL:
320  		ret = cdns_set_mode(cdns, USB_DR_MODE_PERIPHERAL);
321  		break;
322  	case USB_DR_MODE_HOST:
323  		ret = cdns_set_mode(cdns, USB_DR_MODE_HOST);
324  		break;
325  	case USB_DR_MODE_OTG:
326  		ret = cdns_init_otg_mode(cdns);
327  		break;
328  	default:
329  		dev_err(cdns->dev, "Unsupported mode of operation %d\n",
330  			cdns->dr_mode);
331  		return -EINVAL;
332  	}
333  
334  	return ret;
335  }
336  
cdns_drd_thread_irq(int irq,void * data)337  static irqreturn_t cdns_drd_thread_irq(int irq, void *data)
338  {
339  	struct cdns *cdns = data;
340  
341  	cdns_hw_role_switch(cdns);
342  
343  	return IRQ_HANDLED;
344  }
345  
346  /**
347   * cdns_drd_irq - interrupt handler for OTG events
348   *
349   * @irq: irq number for cdns core device
350   * @data: structure of cdns
351   *
352   * Returns IRQ_HANDLED or IRQ_NONE
353   */
cdns_drd_irq(int irq,void * data)354  static irqreturn_t cdns_drd_irq(int irq, void *data)
355  {
356  	irqreturn_t ret = IRQ_NONE;
357  	struct cdns *cdns = data;
358  	u32 reg;
359  
360  	if (cdns->dr_mode != USB_DR_MODE_OTG)
361  		return IRQ_NONE;
362  
363  	if (cdns->in_lpm)
364  		return ret;
365  
366  	reg = readl(&cdns->otg_irq_regs->ivect);
367  
368  	if (!reg)
369  		return IRQ_NONE;
370  
371  	if (reg & OTGIEN_ID_CHANGE_INT) {
372  		dev_dbg(cdns->dev, "OTG IRQ: new ID: %d\n",
373  			cdns_get_id(cdns));
374  
375  		ret = IRQ_WAKE_THREAD;
376  	}
377  
378  	if (reg & (OTGIEN_VBUSVALID_RISE_INT | OTGIEN_VBUSVALID_FALL_INT)) {
379  		dev_dbg(cdns->dev, "OTG IRQ: new VBUS: %d\n",
380  			cdns_get_vbus(cdns));
381  
382  		ret = IRQ_WAKE_THREAD;
383  	}
384  
385  	writel(~0, &cdns->otg_irq_regs->ivect);
386  	return ret;
387  }
388  
cdns_drd_init(struct cdns * cdns)389  int cdns_drd_init(struct cdns *cdns)
390  {
391  	void __iomem *regs;
392  	u32 state, reg;
393  	int ret;
394  
395  	regs = devm_ioremap_resource(cdns->dev, &cdns->otg_res);
396  	if (IS_ERR(regs))
397  		return PTR_ERR(regs);
398  
399  	/* Detection of DRD version. Controller has been released
400  	 * in three versions. All are very similar and are software compatible,
401  	 * but they have same changes in register maps.
402  	 * The first register in oldest version is command register and it's
403  	 * read only. Driver should read 0 from it. On the other hand, in v1
404  	 * and v2 the first register contains device ID number which is not
405  	 * set to 0. Driver uses this fact to detect the proper version of
406  	 * controller.
407  	 */
408  	cdns->otg_v0_regs = regs;
409  	if (!readl(&cdns->otg_v0_regs->cmd)) {
410  		cdns->version  = CDNS3_CONTROLLER_V0;
411  		cdns->otg_v1_regs = NULL;
412  		cdns->otg_cdnsp_regs = NULL;
413  		cdns->otg_regs = regs;
414  		cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem  *)
415  				     &cdns->otg_v0_regs->ien;
416  		writel(1, &cdns->otg_v0_regs->simulate);
417  		dev_dbg(cdns->dev, "DRD version v0 (%08x)\n",
418  			 readl(&cdns->otg_v0_regs->version));
419  	} else {
420  		cdns->otg_v0_regs = NULL;
421  		cdns->otg_v1_regs = regs;
422  		cdns->otg_cdnsp_regs = regs;
423  
424  		cdns->otg_regs = (void __iomem *)&cdns->otg_v1_regs->cmd;
425  
426  		state = readl(&cdns->otg_cdnsp_regs->did);
427  
428  		if (OTG_CDNSP_CHECK_DID(state)) {
429  			cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)
430  					      &cdns->otg_cdnsp_regs->ien;
431  			cdns->version  = CDNSP_CONTROLLER_V2;
432  		} else if (OTG_CDNS3_CHECK_DID(state)) {
433  			cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)
434  					      &cdns->otg_v1_regs->ien;
435  			writel(1, &cdns->otg_v1_regs->simulate);
436  
437  			if (cdns->pdata &&
438  			    (cdns->pdata->quirks & CDNS3_DRD_SUSPEND_RESIDENCY_ENABLE)) {
439  				reg = readl(&cdns->otg_v1_regs->susp_ctrl);
440  				reg |= SUSP_CTRL_SUSPEND_RESIDENCY_ENABLE;
441  				writel(reg, &cdns->otg_v1_regs->susp_ctrl);
442  			}
443  
444  			cdns->version  = CDNS3_CONTROLLER_V1;
445  		} else {
446  			dev_err(cdns->dev, "not supporte DID=0x%08x\n", state);
447  			return -EINVAL;
448  		}
449  
450  		dev_dbg(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n",
451  			 readl(&cdns->otg_v1_regs->did),
452  			 readl(&cdns->otg_v1_regs->rid));
453  	}
454  
455  	state = OTGSTS_STRAP(readl(&cdns->otg_regs->sts));
456  
457  	/* Update dr_mode according to STRAP configuration. */
458  	cdns->dr_mode = USB_DR_MODE_OTG;
459  
460  	if ((cdns->version == CDNSP_CONTROLLER_V2 &&
461  	     state == OTGSTS_CDNSP_STRAP_HOST) ||
462  	    (cdns->version != CDNSP_CONTROLLER_V2 &&
463  	     state == OTGSTS_STRAP_HOST)) {
464  		dev_dbg(cdns->dev, "Controller strapped to HOST\n");
465  		cdns->dr_mode = USB_DR_MODE_HOST;
466  	} else if ((cdns->version == CDNSP_CONTROLLER_V2 &&
467  		    state == OTGSTS_CDNSP_STRAP_GADGET) ||
468  		   (cdns->version != CDNSP_CONTROLLER_V2 &&
469  		    state == OTGSTS_STRAP_GADGET)) {
470  		dev_dbg(cdns->dev, "Controller strapped to PERIPHERAL\n");
471  		cdns->dr_mode = USB_DR_MODE_PERIPHERAL;
472  	}
473  
474  	ret = devm_request_threaded_irq(cdns->dev, cdns->otg_irq,
475  					cdns_drd_irq,
476  					cdns_drd_thread_irq,
477  					IRQF_SHARED,
478  					dev_name(cdns->dev), cdns);
479  	if (ret) {
480  		dev_err(cdns->dev, "couldn't get otg_irq\n");
481  		return ret;
482  	}
483  
484  	state = readl(&cdns->otg_regs->sts);
485  	if (OTGSTS_OTG_NRDY(state)) {
486  		dev_err(cdns->dev, "Cadence USB3 OTG device not ready\n");
487  		return -ENODEV;
488  	}
489  
490  	return 0;
491  }
492  
cdns_drd_exit(struct cdns * cdns)493  int cdns_drd_exit(struct cdns *cdns)
494  {
495  	cdns_otg_disable_irq(cdns);
496  
497  	return 0;
498  }
499  
500  /* Indicate the cdns3 core was power lost before */
cdns_power_is_lost(struct cdns * cdns)501  bool cdns_power_is_lost(struct cdns *cdns)
502  {
503  	if (cdns->version == CDNS3_CONTROLLER_V0) {
504  		if (!(readl(&cdns->otg_v0_regs->simulate) & BIT(0)))
505  			return true;
506  	} else {
507  		if (!(readl(&cdns->otg_v1_regs->simulate) & BIT(0)))
508  			return true;
509  	}
510  	return false;
511  }
512  EXPORT_SYMBOL_GPL(cdns_power_is_lost);
513