xref: /openbmc/linux/drivers/usb/phy/phy-mv-usb.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
294ae9843SFelipe Balbi /*
394ae9843SFelipe Balbi  * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
494ae9843SFelipe Balbi  * Author: Chao Xie <chao.xie@marvell.com>
594ae9843SFelipe Balbi  *	   Neil Zhang <zhangwm@marvell.com>
694ae9843SFelipe Balbi  */
794ae9843SFelipe Balbi 
894ae9843SFelipe Balbi #include <linux/module.h>
994ae9843SFelipe Balbi #include <linux/kernel.h>
1094ae9843SFelipe Balbi #include <linux/io.h>
11f158afecSChunfeng Yun #include <linux/iopoll.h>
1294ae9843SFelipe Balbi #include <linux/uaccess.h>
1394ae9843SFelipe Balbi #include <linux/device.h>
1494ae9843SFelipe Balbi #include <linux/proc_fs.h>
1594ae9843SFelipe Balbi #include <linux/clk.h>
1694ae9843SFelipe Balbi #include <linux/workqueue.h>
1794ae9843SFelipe Balbi #include <linux/platform_device.h>
1894ae9843SFelipe Balbi 
1994ae9843SFelipe Balbi #include <linux/usb.h>
2094ae9843SFelipe Balbi #include <linux/usb/ch9.h>
2194ae9843SFelipe Balbi #include <linux/usb/otg.h>
2294ae9843SFelipe Balbi #include <linux/usb/gadget.h>
2394ae9843SFelipe Balbi #include <linux/usb/hcd.h>
2494ae9843SFelipe Balbi #include <linux/platform_data/mv_usb.h>
2594ae9843SFelipe Balbi 
2694ae9843SFelipe Balbi #include "phy-mv-usb.h"
2794ae9843SFelipe Balbi 
2894ae9843SFelipe Balbi #define	DRIVER_DESC	"Marvell USB OTG transceiver driver"
2994ae9843SFelipe Balbi 
3094ae9843SFelipe Balbi MODULE_DESCRIPTION(DRIVER_DESC);
3194ae9843SFelipe Balbi MODULE_LICENSE("GPL");
3294ae9843SFelipe Balbi 
3394ae9843SFelipe Balbi static const char driver_name[] = "mv-otg";
3494ae9843SFelipe Balbi 
3594ae9843SFelipe Balbi static char *state_string[] = {
3694ae9843SFelipe Balbi 	"undefined",
3794ae9843SFelipe Balbi 	"b_idle",
3894ae9843SFelipe Balbi 	"b_srp_init",
3994ae9843SFelipe Balbi 	"b_peripheral",
4094ae9843SFelipe Balbi 	"b_wait_acon",
4194ae9843SFelipe Balbi 	"b_host",
4294ae9843SFelipe Balbi 	"a_idle",
4394ae9843SFelipe Balbi 	"a_wait_vrise",
4494ae9843SFelipe Balbi 	"a_wait_bcon",
4594ae9843SFelipe Balbi 	"a_host",
4694ae9843SFelipe Balbi 	"a_suspend",
4794ae9843SFelipe Balbi 	"a_peripheral",
4894ae9843SFelipe Balbi 	"a_wait_vfall",
4994ae9843SFelipe Balbi 	"a_vbus_err"
5094ae9843SFelipe Balbi };
5194ae9843SFelipe Balbi 
mv_otg_set_vbus(struct usb_otg * otg,bool on)5294ae9843SFelipe Balbi static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
5394ae9843SFelipe Balbi {
5419c1eac2SAntoine Tenart 	struct mv_otg *mvotg = container_of(otg->usb_phy, struct mv_otg, phy);
5594ae9843SFelipe Balbi 	if (mvotg->pdata->set_vbus == NULL)
5694ae9843SFelipe Balbi 		return -ENODEV;
5794ae9843SFelipe Balbi 
5894ae9843SFelipe Balbi 	return mvotg->pdata->set_vbus(on);
5994ae9843SFelipe Balbi }
6094ae9843SFelipe Balbi 
mv_otg_set_host(struct usb_otg * otg,struct usb_bus * host)6194ae9843SFelipe Balbi static int mv_otg_set_host(struct usb_otg *otg,
6294ae9843SFelipe Balbi 			   struct usb_bus *host)
6394ae9843SFelipe Balbi {
6494ae9843SFelipe Balbi 	otg->host = host;
6594ae9843SFelipe Balbi 
6694ae9843SFelipe Balbi 	return 0;
6794ae9843SFelipe Balbi }
6894ae9843SFelipe Balbi 
mv_otg_set_peripheral(struct usb_otg * otg,struct usb_gadget * gadget)6994ae9843SFelipe Balbi static int mv_otg_set_peripheral(struct usb_otg *otg,
7094ae9843SFelipe Balbi 				 struct usb_gadget *gadget)
7194ae9843SFelipe Balbi {
7294ae9843SFelipe Balbi 	otg->gadget = gadget;
7394ae9843SFelipe Balbi 
7494ae9843SFelipe Balbi 	return 0;
7594ae9843SFelipe Balbi }
7694ae9843SFelipe Balbi 
mv_otg_run_state_machine(struct mv_otg * mvotg,unsigned long delay)7794ae9843SFelipe Balbi static void mv_otg_run_state_machine(struct mv_otg *mvotg,
7894ae9843SFelipe Balbi 				     unsigned long delay)
7994ae9843SFelipe Balbi {
8094ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n");
8194ae9843SFelipe Balbi 	if (!mvotg->qwork)
8294ae9843SFelipe Balbi 		return;
8394ae9843SFelipe Balbi 
8494ae9843SFelipe Balbi 	queue_delayed_work(mvotg->qwork, &mvotg->work, delay);
8594ae9843SFelipe Balbi }
8694ae9843SFelipe Balbi 
mv_otg_timer_await_bcon(struct timer_list * t)879718756fSKees Cook static void mv_otg_timer_await_bcon(struct timer_list *t)
8894ae9843SFelipe Balbi {
899718756fSKees Cook 	struct mv_otg *mvotg = from_timer(mvotg, t,
909718756fSKees Cook 					  otg_ctrl.timer[A_WAIT_BCON_TIMER]);
9194ae9843SFelipe Balbi 
9294ae9843SFelipe Balbi 	mvotg->otg_ctrl.a_wait_bcon_timeout = 1;
9394ae9843SFelipe Balbi 
9494ae9843SFelipe Balbi 	dev_info(&mvotg->pdev->dev, "B Device No Response!\n");
9594ae9843SFelipe Balbi 
9694ae9843SFelipe Balbi 	if (spin_trylock(&mvotg->wq_lock)) {
9794ae9843SFelipe Balbi 		mv_otg_run_state_machine(mvotg, 0);
9894ae9843SFelipe Balbi 		spin_unlock(&mvotg->wq_lock);
9994ae9843SFelipe Balbi 	}
10094ae9843SFelipe Balbi }
10194ae9843SFelipe Balbi 
mv_otg_cancel_timer(struct mv_otg * mvotg,unsigned int id)10294ae9843SFelipe Balbi static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id)
10394ae9843SFelipe Balbi {
10494ae9843SFelipe Balbi 	struct timer_list *timer;
10594ae9843SFelipe Balbi 
10694ae9843SFelipe Balbi 	if (id >= OTG_TIMER_NUM)
10794ae9843SFelipe Balbi 		return -EINVAL;
10894ae9843SFelipe Balbi 
10994ae9843SFelipe Balbi 	timer = &mvotg->otg_ctrl.timer[id];
11094ae9843SFelipe Balbi 
11194ae9843SFelipe Balbi 	if (timer_pending(timer))
11294ae9843SFelipe Balbi 		del_timer(timer);
11394ae9843SFelipe Balbi 
11494ae9843SFelipe Balbi 	return 0;
11594ae9843SFelipe Balbi }
11694ae9843SFelipe Balbi 
mv_otg_set_timer(struct mv_otg * mvotg,unsigned int id,unsigned long interval)11794ae9843SFelipe Balbi static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id,
1189718756fSKees Cook 			    unsigned long interval)
11994ae9843SFelipe Balbi {
12094ae9843SFelipe Balbi 	struct timer_list *timer;
12194ae9843SFelipe Balbi 
12294ae9843SFelipe Balbi 	if (id >= OTG_TIMER_NUM)
12394ae9843SFelipe Balbi 		return -EINVAL;
12494ae9843SFelipe Balbi 
12594ae9843SFelipe Balbi 	timer = &mvotg->otg_ctrl.timer[id];
12694ae9843SFelipe Balbi 	if (timer_pending(timer)) {
12794ae9843SFelipe Balbi 		dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id);
12894ae9843SFelipe Balbi 		return -EBUSY;
12994ae9843SFelipe Balbi 	}
13094ae9843SFelipe Balbi 
13194ae9843SFelipe Balbi 	timer->expires = jiffies + interval;
13294ae9843SFelipe Balbi 	add_timer(timer);
13394ae9843SFelipe Balbi 
13494ae9843SFelipe Balbi 	return 0;
13594ae9843SFelipe Balbi }
13694ae9843SFelipe Balbi 
mv_otg_reset(struct mv_otg * mvotg)13794ae9843SFelipe Balbi static int mv_otg_reset(struct mv_otg *mvotg)
13894ae9843SFelipe Balbi {
13994ae9843SFelipe Balbi 	u32 tmp;
140f158afecSChunfeng Yun 	int ret;
14194ae9843SFelipe Balbi 
14294ae9843SFelipe Balbi 	/* Stop the controller */
14394ae9843SFelipe Balbi 	tmp = readl(&mvotg->op_regs->usbcmd);
14494ae9843SFelipe Balbi 	tmp &= ~USBCMD_RUN_STOP;
14594ae9843SFelipe Balbi 	writel(tmp, &mvotg->op_regs->usbcmd);
14694ae9843SFelipe Balbi 
14794ae9843SFelipe Balbi 	/* Reset the controller to get default values */
14894ae9843SFelipe Balbi 	writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd);
14994ae9843SFelipe Balbi 
150f158afecSChunfeng Yun 	ret = readl_poll_timeout_atomic(&mvotg->op_regs->usbcmd, tmp,
151f158afecSChunfeng Yun 				(tmp & USBCMD_CTRL_RESET), 10, 10000);
152f158afecSChunfeng Yun 	if (ret < 0) {
15394ae9843SFelipe Balbi 		dev_err(&mvotg->pdev->dev,
15494ae9843SFelipe Balbi 			"Wait for RESET completed TIMEOUT\n");
155f158afecSChunfeng Yun 		return ret;
15694ae9843SFelipe Balbi 	}
15794ae9843SFelipe Balbi 
15894ae9843SFelipe Balbi 	writel(0x0, &mvotg->op_regs->usbintr);
15994ae9843SFelipe Balbi 	tmp = readl(&mvotg->op_regs->usbsts);
16094ae9843SFelipe Balbi 	writel(tmp, &mvotg->op_regs->usbsts);
16194ae9843SFelipe Balbi 
16294ae9843SFelipe Balbi 	return 0;
16394ae9843SFelipe Balbi }
16494ae9843SFelipe Balbi 
mv_otg_init_irq(struct mv_otg * mvotg)16594ae9843SFelipe Balbi static void mv_otg_init_irq(struct mv_otg *mvotg)
16694ae9843SFelipe Balbi {
16794ae9843SFelipe Balbi 	u32 otgsc;
16894ae9843SFelipe Balbi 
16994ae9843SFelipe Balbi 	mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID
17094ae9843SFelipe Balbi 	    | OTGSC_INTR_A_VBUS_VALID;
17194ae9843SFelipe Balbi 	mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID
17294ae9843SFelipe Balbi 	    | OTGSC_INTSTS_A_VBUS_VALID;
17394ae9843SFelipe Balbi 
17494ae9843SFelipe Balbi 	if (mvotg->pdata->vbus == NULL) {
17594ae9843SFelipe Balbi 		mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID
17694ae9843SFelipe Balbi 		    | OTGSC_INTR_B_SESSION_END;
17794ae9843SFelipe Balbi 		mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID
17894ae9843SFelipe Balbi 		    | OTGSC_INTSTS_B_SESSION_END;
17994ae9843SFelipe Balbi 	}
18094ae9843SFelipe Balbi 
18194ae9843SFelipe Balbi 	if (mvotg->pdata->id == NULL) {
18294ae9843SFelipe Balbi 		mvotg->irq_en |= OTGSC_INTR_USB_ID;
18394ae9843SFelipe Balbi 		mvotg->irq_status |= OTGSC_INTSTS_USB_ID;
18494ae9843SFelipe Balbi 	}
18594ae9843SFelipe Balbi 
18694ae9843SFelipe Balbi 	otgsc = readl(&mvotg->op_regs->otgsc);
18794ae9843SFelipe Balbi 	otgsc |= mvotg->irq_en;
18894ae9843SFelipe Balbi 	writel(otgsc, &mvotg->op_regs->otgsc);
18994ae9843SFelipe Balbi }
19094ae9843SFelipe Balbi 
mv_otg_start_host(struct mv_otg * mvotg,int on)19194ae9843SFelipe Balbi static void mv_otg_start_host(struct mv_otg *mvotg, int on)
19294ae9843SFelipe Balbi {
19394ae9843SFelipe Balbi #ifdef CONFIG_USB
19494ae9843SFelipe Balbi 	struct usb_otg *otg = mvotg->phy.otg;
19594ae9843SFelipe Balbi 	struct usb_hcd *hcd;
19694ae9843SFelipe Balbi 
19794ae9843SFelipe Balbi 	if (!otg->host)
19894ae9843SFelipe Balbi 		return;
19994ae9843SFelipe Balbi 
20094ae9843SFelipe Balbi 	dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop");
20194ae9843SFelipe Balbi 
20294ae9843SFelipe Balbi 	hcd = bus_to_hcd(otg->host);
20394ae9843SFelipe Balbi 
2043c9740a1SPeter Chen 	if (on) {
20594ae9843SFelipe Balbi 		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
2063c9740a1SPeter Chen 		device_wakeup_enable(hcd->self.controller);
2073c9740a1SPeter Chen 	} else {
20894ae9843SFelipe Balbi 		usb_remove_hcd(hcd);
2093c9740a1SPeter Chen 	}
21094ae9843SFelipe Balbi #endif /* CONFIG_USB */
21194ae9843SFelipe Balbi }
21294ae9843SFelipe Balbi 
mv_otg_start_periphrals(struct mv_otg * mvotg,int on)21394ae9843SFelipe Balbi static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
21494ae9843SFelipe Balbi {
21594ae9843SFelipe Balbi 	struct usb_otg *otg = mvotg->phy.otg;
21694ae9843SFelipe Balbi 
21794ae9843SFelipe Balbi 	if (!otg->gadget)
21894ae9843SFelipe Balbi 		return;
21994ae9843SFelipe Balbi 
22094ae9843SFelipe Balbi 	dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off");
22194ae9843SFelipe Balbi 
22294ae9843SFelipe Balbi 	if (on)
22394ae9843SFelipe Balbi 		usb_gadget_vbus_connect(otg->gadget);
22494ae9843SFelipe Balbi 	else
22594ae9843SFelipe Balbi 		usb_gadget_vbus_disconnect(otg->gadget);
22694ae9843SFelipe Balbi }
22794ae9843SFelipe Balbi 
otg_clock_enable(struct mv_otg * mvotg)22894ae9843SFelipe Balbi static void otg_clock_enable(struct mv_otg *mvotg)
22994ae9843SFelipe Balbi {
230df18fedaSChao Xie 	clk_prepare_enable(mvotg->clk);
23194ae9843SFelipe Balbi }
23294ae9843SFelipe Balbi 
otg_clock_disable(struct mv_otg * mvotg)23394ae9843SFelipe Balbi static void otg_clock_disable(struct mv_otg *mvotg)
23494ae9843SFelipe Balbi {
235df18fedaSChao Xie 	clk_disable_unprepare(mvotg->clk);
23694ae9843SFelipe Balbi }
23794ae9843SFelipe Balbi 
mv_otg_enable_internal(struct mv_otg * mvotg)23894ae9843SFelipe Balbi static int mv_otg_enable_internal(struct mv_otg *mvotg)
23994ae9843SFelipe Balbi {
24094ae9843SFelipe Balbi 	int retval = 0;
24194ae9843SFelipe Balbi 
24294ae9843SFelipe Balbi 	if (mvotg->active)
24394ae9843SFelipe Balbi 		return 0;
24494ae9843SFelipe Balbi 
24594ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "otg enabled\n");
24694ae9843SFelipe Balbi 
24794ae9843SFelipe Balbi 	otg_clock_enable(mvotg);
24894ae9843SFelipe Balbi 	if (mvotg->pdata->phy_init) {
24994ae9843SFelipe Balbi 		retval = mvotg->pdata->phy_init(mvotg->phy_regs);
25094ae9843SFelipe Balbi 		if (retval) {
25194ae9843SFelipe Balbi 			dev_err(&mvotg->pdev->dev,
25294ae9843SFelipe Balbi 				"init phy error %d\n", retval);
25394ae9843SFelipe Balbi 			otg_clock_disable(mvotg);
25494ae9843SFelipe Balbi 			return retval;
25594ae9843SFelipe Balbi 		}
25694ae9843SFelipe Balbi 	}
25794ae9843SFelipe Balbi 	mvotg->active = 1;
25894ae9843SFelipe Balbi 
25994ae9843SFelipe Balbi 	return 0;
26094ae9843SFelipe Balbi 
26194ae9843SFelipe Balbi }
26294ae9843SFelipe Balbi 
mv_otg_enable(struct mv_otg * mvotg)26394ae9843SFelipe Balbi static int mv_otg_enable(struct mv_otg *mvotg)
26494ae9843SFelipe Balbi {
26594ae9843SFelipe Balbi 	if (mvotg->clock_gating)
26694ae9843SFelipe Balbi 		return mv_otg_enable_internal(mvotg);
26794ae9843SFelipe Balbi 
26894ae9843SFelipe Balbi 	return 0;
26994ae9843SFelipe Balbi }
27094ae9843SFelipe Balbi 
mv_otg_disable_internal(struct mv_otg * mvotg)27194ae9843SFelipe Balbi static void mv_otg_disable_internal(struct mv_otg *mvotg)
27294ae9843SFelipe Balbi {
27394ae9843SFelipe Balbi 	if (mvotg->active) {
27494ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev, "otg disabled\n");
27594ae9843SFelipe Balbi 		if (mvotg->pdata->phy_deinit)
27694ae9843SFelipe Balbi 			mvotg->pdata->phy_deinit(mvotg->phy_regs);
27794ae9843SFelipe Balbi 		otg_clock_disable(mvotg);
27894ae9843SFelipe Balbi 		mvotg->active = 0;
27994ae9843SFelipe Balbi 	}
28094ae9843SFelipe Balbi }
28194ae9843SFelipe Balbi 
mv_otg_disable(struct mv_otg * mvotg)28294ae9843SFelipe Balbi static void mv_otg_disable(struct mv_otg *mvotg)
28394ae9843SFelipe Balbi {
28494ae9843SFelipe Balbi 	if (mvotg->clock_gating)
28594ae9843SFelipe Balbi 		mv_otg_disable_internal(mvotg);
28694ae9843SFelipe Balbi }
28794ae9843SFelipe Balbi 
mv_otg_update_inputs(struct mv_otg * mvotg)28894ae9843SFelipe Balbi static void mv_otg_update_inputs(struct mv_otg *mvotg)
28994ae9843SFelipe Balbi {
29094ae9843SFelipe Balbi 	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
29194ae9843SFelipe Balbi 	u32 otgsc;
29294ae9843SFelipe Balbi 
29394ae9843SFelipe Balbi 	otgsc = readl(&mvotg->op_regs->otgsc);
29494ae9843SFelipe Balbi 
29594ae9843SFelipe Balbi 	if (mvotg->pdata->vbus) {
29694ae9843SFelipe Balbi 		if (mvotg->pdata->vbus->poll() == VBUS_HIGH) {
29794ae9843SFelipe Balbi 			otg_ctrl->b_sess_vld = 1;
29894ae9843SFelipe Balbi 			otg_ctrl->b_sess_end = 0;
29994ae9843SFelipe Balbi 		} else {
30094ae9843SFelipe Balbi 			otg_ctrl->b_sess_vld = 0;
30194ae9843SFelipe Balbi 			otg_ctrl->b_sess_end = 1;
30294ae9843SFelipe Balbi 		}
30394ae9843SFelipe Balbi 	} else {
30494ae9843SFelipe Balbi 		otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID);
30594ae9843SFelipe Balbi 		otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END);
30694ae9843SFelipe Balbi 	}
30794ae9843SFelipe Balbi 
30894ae9843SFelipe Balbi 	if (mvotg->pdata->id)
30994ae9843SFelipe Balbi 		otg_ctrl->id = !!mvotg->pdata->id->poll();
31094ae9843SFelipe Balbi 	else
31194ae9843SFelipe Balbi 		otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
31294ae9843SFelipe Balbi 
31394ae9843SFelipe Balbi 	if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
31494ae9843SFelipe Balbi 		otg_ctrl->a_bus_req = 1;
31594ae9843SFelipe Balbi 
31694ae9843SFelipe Balbi 	otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
31794ae9843SFelipe Balbi 	otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID);
31894ae9843SFelipe Balbi 
31994ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "%s: ", __func__);
32094ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id);
32194ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld);
32294ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end);
32394ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld);
32494ae9843SFelipe Balbi 	dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld);
32594ae9843SFelipe Balbi }
32694ae9843SFelipe Balbi 
mv_otg_update_state(struct mv_otg * mvotg)32794ae9843SFelipe Balbi static void mv_otg_update_state(struct mv_otg *mvotg)
32894ae9843SFelipe Balbi {
32994ae9843SFelipe Balbi 	struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
330e47d9254SAntoine Tenart 	int old_state = mvotg->phy.otg->state;
33194ae9843SFelipe Balbi 
33294ae9843SFelipe Balbi 	switch (old_state) {
33394ae9843SFelipe Balbi 	case OTG_STATE_UNDEFINED:
334e47d9254SAntoine Tenart 		mvotg->phy.otg->state = OTG_STATE_B_IDLE;
3354e71e079SGustavo A. R. Silva 		fallthrough;
33694ae9843SFelipe Balbi 	case OTG_STATE_B_IDLE:
33794ae9843SFelipe Balbi 		if (otg_ctrl->id == 0)
338e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_IDLE;
33994ae9843SFelipe Balbi 		else if (otg_ctrl->b_sess_vld)
340e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_B_PERIPHERAL;
34194ae9843SFelipe Balbi 		break;
34294ae9843SFelipe Balbi 	case OTG_STATE_B_PERIPHERAL:
34394ae9843SFelipe Balbi 		if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
344e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_B_IDLE;
34594ae9843SFelipe Balbi 		break;
34694ae9843SFelipe Balbi 	case OTG_STATE_A_IDLE:
34794ae9843SFelipe Balbi 		if (otg_ctrl->id)
348e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_B_IDLE;
34994ae9843SFelipe Balbi 		else if (!(otg_ctrl->a_bus_drop) &&
35094ae9843SFelipe Balbi 			 (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
351e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_WAIT_VRISE;
35294ae9843SFelipe Balbi 		break;
35394ae9843SFelipe Balbi 	case OTG_STATE_A_WAIT_VRISE:
35494ae9843SFelipe Balbi 		if (otg_ctrl->a_vbus_vld)
355e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
35694ae9843SFelipe Balbi 		break;
35794ae9843SFelipe Balbi 	case OTG_STATE_A_WAIT_BCON:
35894ae9843SFelipe Balbi 		if (otg_ctrl->id || otg_ctrl->a_bus_drop
35994ae9843SFelipe Balbi 		    || otg_ctrl->a_wait_bcon_timeout) {
36094ae9843SFelipe Balbi 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
36194ae9843SFelipe Balbi 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
362e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
36394ae9843SFelipe Balbi 			otg_ctrl->a_bus_req = 0;
36494ae9843SFelipe Balbi 		} else if (!otg_ctrl->a_vbus_vld) {
36594ae9843SFelipe Balbi 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
36694ae9843SFelipe Balbi 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
367e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
36894ae9843SFelipe Balbi 		} else if (otg_ctrl->b_conn) {
36994ae9843SFelipe Balbi 			mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
37094ae9843SFelipe Balbi 			mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
371e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_HOST;
37294ae9843SFelipe Balbi 		}
37394ae9843SFelipe Balbi 		break;
37494ae9843SFelipe Balbi 	case OTG_STATE_A_HOST:
37594ae9843SFelipe Balbi 		if (otg_ctrl->id || !otg_ctrl->b_conn
37694ae9843SFelipe Balbi 		    || otg_ctrl->a_bus_drop)
377e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
37894ae9843SFelipe Balbi 		else if (!otg_ctrl->a_vbus_vld)
379e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
38094ae9843SFelipe Balbi 		break;
38194ae9843SFelipe Balbi 	case OTG_STATE_A_WAIT_VFALL:
38294ae9843SFelipe Balbi 		if (otg_ctrl->id
38394ae9843SFelipe Balbi 		    || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
38494ae9843SFelipe Balbi 		    || otg_ctrl->a_bus_req)
385e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_IDLE;
38694ae9843SFelipe Balbi 		break;
38794ae9843SFelipe Balbi 	case OTG_STATE_A_VBUS_ERR:
38894ae9843SFelipe Balbi 		if (otg_ctrl->id || otg_ctrl->a_clr_err
38994ae9843SFelipe Balbi 		    || otg_ctrl->a_bus_drop) {
39094ae9843SFelipe Balbi 			otg_ctrl->a_clr_err = 0;
391e47d9254SAntoine Tenart 			mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
39294ae9843SFelipe Balbi 		}
39394ae9843SFelipe Balbi 		break;
39494ae9843SFelipe Balbi 	default:
39594ae9843SFelipe Balbi 		break;
39694ae9843SFelipe Balbi 	}
39794ae9843SFelipe Balbi }
39894ae9843SFelipe Balbi 
mv_otg_work(struct work_struct * work)39994ae9843SFelipe Balbi static void mv_otg_work(struct work_struct *work)
40094ae9843SFelipe Balbi {
40194ae9843SFelipe Balbi 	struct mv_otg *mvotg;
40294ae9843SFelipe Balbi 	struct usb_otg *otg;
40394ae9843SFelipe Balbi 	int old_state;
40494ae9843SFelipe Balbi 
40594ae9843SFelipe Balbi 	mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
40694ae9843SFelipe Balbi 
40794ae9843SFelipe Balbi run:
40894ae9843SFelipe Balbi 	/* work queue is single thread, or we need spin_lock to protect */
409e47d9254SAntoine Tenart 	otg = mvotg->phy.otg;
410e47d9254SAntoine Tenart 	old_state = otg->state;
41194ae9843SFelipe Balbi 
41294ae9843SFelipe Balbi 	if (!mvotg->active)
41394ae9843SFelipe Balbi 		return;
41494ae9843SFelipe Balbi 
41594ae9843SFelipe Balbi 	mv_otg_update_inputs(mvotg);
41694ae9843SFelipe Balbi 	mv_otg_update_state(mvotg);
41794ae9843SFelipe Balbi 
418e47d9254SAntoine Tenart 	if (old_state != mvotg->phy.otg->state) {
41994ae9843SFelipe Balbi 		dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
42094ae9843SFelipe Balbi 			 state_string[old_state],
421e47d9254SAntoine Tenart 			 state_string[mvotg->phy.otg->state]);
42294ae9843SFelipe Balbi 
423e47d9254SAntoine Tenart 		switch (mvotg->phy.otg->state) {
42494ae9843SFelipe Balbi 		case OTG_STATE_B_IDLE:
42594ae9843SFelipe Balbi 			otg->default_a = 0;
42694ae9843SFelipe Balbi 			if (old_state == OTG_STATE_B_PERIPHERAL)
42794ae9843SFelipe Balbi 				mv_otg_start_periphrals(mvotg, 0);
42894ae9843SFelipe Balbi 			mv_otg_reset(mvotg);
42994ae9843SFelipe Balbi 			mv_otg_disable(mvotg);
430b20f3f9eSKiran Raparthy 			usb_phy_set_event(&mvotg->phy, USB_EVENT_NONE);
43194ae9843SFelipe Balbi 			break;
43294ae9843SFelipe Balbi 		case OTG_STATE_B_PERIPHERAL:
43394ae9843SFelipe Balbi 			mv_otg_enable(mvotg);
43494ae9843SFelipe Balbi 			mv_otg_start_periphrals(mvotg, 1);
435b20f3f9eSKiran Raparthy 			usb_phy_set_event(&mvotg->phy, USB_EVENT_ENUMERATED);
43694ae9843SFelipe Balbi 			break;
43794ae9843SFelipe Balbi 		case OTG_STATE_A_IDLE:
43894ae9843SFelipe Balbi 			otg->default_a = 1;
43994ae9843SFelipe Balbi 			mv_otg_enable(mvotg);
44094ae9843SFelipe Balbi 			if (old_state == OTG_STATE_A_WAIT_VFALL)
44194ae9843SFelipe Balbi 				mv_otg_start_host(mvotg, 0);
44294ae9843SFelipe Balbi 			mv_otg_reset(mvotg);
44394ae9843SFelipe Balbi 			break;
44494ae9843SFelipe Balbi 		case OTG_STATE_A_WAIT_VRISE:
44594ae9843SFelipe Balbi 			mv_otg_set_vbus(otg, 1);
44694ae9843SFelipe Balbi 			break;
44794ae9843SFelipe Balbi 		case OTG_STATE_A_WAIT_BCON:
44894ae9843SFelipe Balbi 			if (old_state != OTG_STATE_A_HOST)
44994ae9843SFelipe Balbi 				mv_otg_start_host(mvotg, 1);
45094ae9843SFelipe Balbi 			mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER,
4519718756fSKees Cook 					 T_A_WAIT_BCON);
45294ae9843SFelipe Balbi 			/*
45394ae9843SFelipe Balbi 			 * Now, we directly enter A_HOST. So set b_conn = 1
45494ae9843SFelipe Balbi 			 * here. In fact, it need host driver to notify us.
45594ae9843SFelipe Balbi 			 */
45694ae9843SFelipe Balbi 			mvotg->otg_ctrl.b_conn = 1;
45794ae9843SFelipe Balbi 			break;
45894ae9843SFelipe Balbi 		case OTG_STATE_A_HOST:
45994ae9843SFelipe Balbi 			break;
46094ae9843SFelipe Balbi 		case OTG_STATE_A_WAIT_VFALL:
46194ae9843SFelipe Balbi 			/*
46294ae9843SFelipe Balbi 			 * Now, we has exited A_HOST. So set b_conn = 0
46394ae9843SFelipe Balbi 			 * here. In fact, it need host driver to notify us.
46494ae9843SFelipe Balbi 			 */
46594ae9843SFelipe Balbi 			mvotg->otg_ctrl.b_conn = 0;
46694ae9843SFelipe Balbi 			mv_otg_set_vbus(otg, 0);
46794ae9843SFelipe Balbi 			break;
46894ae9843SFelipe Balbi 		case OTG_STATE_A_VBUS_ERR:
46994ae9843SFelipe Balbi 			break;
47094ae9843SFelipe Balbi 		default:
47194ae9843SFelipe Balbi 			break;
47294ae9843SFelipe Balbi 		}
47394ae9843SFelipe Balbi 		goto run;
47494ae9843SFelipe Balbi 	}
47594ae9843SFelipe Balbi }
47694ae9843SFelipe Balbi 
mv_otg_irq(int irq,void * dev)47794ae9843SFelipe Balbi static irqreturn_t mv_otg_irq(int irq, void *dev)
47894ae9843SFelipe Balbi {
47994ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev;
48094ae9843SFelipe Balbi 	u32 otgsc;
48194ae9843SFelipe Balbi 
48294ae9843SFelipe Balbi 	otgsc = readl(&mvotg->op_regs->otgsc);
48394ae9843SFelipe Balbi 	writel(otgsc, &mvotg->op_regs->otgsc);
48494ae9843SFelipe Balbi 
48594ae9843SFelipe Balbi 	/*
48694ae9843SFelipe Balbi 	 * if we have vbus, then the vbus detection for B-device
48794ae9843SFelipe Balbi 	 * will be done by mv_otg_inputs_irq().
48894ae9843SFelipe Balbi 	 */
48994ae9843SFelipe Balbi 	if (mvotg->pdata->vbus)
49094ae9843SFelipe Balbi 		if ((otgsc & OTGSC_STS_USB_ID) &&
49194ae9843SFelipe Balbi 		    !(otgsc & OTGSC_INTSTS_USB_ID))
49294ae9843SFelipe Balbi 			return IRQ_NONE;
49394ae9843SFelipe Balbi 
49494ae9843SFelipe Balbi 	if ((otgsc & mvotg->irq_status) == 0)
49594ae9843SFelipe Balbi 		return IRQ_NONE;
49694ae9843SFelipe Balbi 
49794ae9843SFelipe Balbi 	mv_otg_run_state_machine(mvotg, 0);
49894ae9843SFelipe Balbi 
49994ae9843SFelipe Balbi 	return IRQ_HANDLED;
50094ae9843SFelipe Balbi }
50194ae9843SFelipe Balbi 
mv_otg_inputs_irq(int irq,void * dev)50294ae9843SFelipe Balbi static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
50394ae9843SFelipe Balbi {
50494ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev;
50594ae9843SFelipe Balbi 
50694ae9843SFelipe Balbi 	/* The clock may disabled at this time */
50794ae9843SFelipe Balbi 	if (!mvotg->active) {
50894ae9843SFelipe Balbi 		mv_otg_enable(mvotg);
50994ae9843SFelipe Balbi 		mv_otg_init_irq(mvotg);
51094ae9843SFelipe Balbi 	}
51194ae9843SFelipe Balbi 
51294ae9843SFelipe Balbi 	mv_otg_run_state_machine(mvotg, 0);
51394ae9843SFelipe Balbi 
51494ae9843SFelipe Balbi 	return IRQ_HANDLED;
51594ae9843SFelipe Balbi }
51694ae9843SFelipe Balbi 
51794ae9843SFelipe Balbi static ssize_t
a_bus_req_show(struct device * dev,struct device_attribute * attr,char * buf)518ed5bd7a4SGreg Kroah-Hartman a_bus_req_show(struct device *dev, struct device_attribute *attr, char *buf)
51994ae9843SFelipe Balbi {
52094ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev_get_drvdata(dev);
52194ae9843SFelipe Balbi 	return scnprintf(buf, PAGE_SIZE, "%d\n",
52294ae9843SFelipe Balbi 			 mvotg->otg_ctrl.a_bus_req);
52394ae9843SFelipe Balbi }
52494ae9843SFelipe Balbi 
52594ae9843SFelipe Balbi static ssize_t
a_bus_req_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)526ed5bd7a4SGreg Kroah-Hartman a_bus_req_store(struct device *dev, struct device_attribute *attr,
52794ae9843SFelipe Balbi 	      const char *buf, size_t count)
52894ae9843SFelipe Balbi {
52994ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev_get_drvdata(dev);
53094ae9843SFelipe Balbi 
53194ae9843SFelipe Balbi 	if (count > 2)
53294ae9843SFelipe Balbi 		return -1;
53394ae9843SFelipe Balbi 
53494ae9843SFelipe Balbi 	/* We will use this interface to change to A device */
535e47d9254SAntoine Tenart 	if (mvotg->phy.otg->state != OTG_STATE_B_IDLE
536e47d9254SAntoine Tenart 	    && mvotg->phy.otg->state != OTG_STATE_A_IDLE)
53794ae9843SFelipe Balbi 		return -1;
53894ae9843SFelipe Balbi 
53994ae9843SFelipe Balbi 	/* The clock may disabled and we need to set irq for ID detected */
54094ae9843SFelipe Balbi 	mv_otg_enable(mvotg);
54194ae9843SFelipe Balbi 	mv_otg_init_irq(mvotg);
54294ae9843SFelipe Balbi 
54394ae9843SFelipe Balbi 	if (buf[0] == '1') {
54494ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_bus_req = 1;
54594ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_bus_drop = 0;
54694ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev,
54794ae9843SFelipe Balbi 			"User request: a_bus_req = 1\n");
54894ae9843SFelipe Balbi 
54994ae9843SFelipe Balbi 		if (spin_trylock(&mvotg->wq_lock)) {
55094ae9843SFelipe Balbi 			mv_otg_run_state_machine(mvotg, 0);
55194ae9843SFelipe Balbi 			spin_unlock(&mvotg->wq_lock);
55294ae9843SFelipe Balbi 		}
55394ae9843SFelipe Balbi 	}
55494ae9843SFelipe Balbi 
55594ae9843SFelipe Balbi 	return count;
55694ae9843SFelipe Balbi }
55794ae9843SFelipe Balbi 
558ed5bd7a4SGreg Kroah-Hartman static DEVICE_ATTR_RW(a_bus_req);
55994ae9843SFelipe Balbi 
56094ae9843SFelipe Balbi static ssize_t
a_clr_err_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)561ca35910aSGreg Kroah-Hartman a_clr_err_store(struct device *dev, struct device_attribute *attr,
56294ae9843SFelipe Balbi 	      const char *buf, size_t count)
56394ae9843SFelipe Balbi {
56494ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev_get_drvdata(dev);
56594ae9843SFelipe Balbi 	if (!mvotg->phy.otg->default_a)
56694ae9843SFelipe Balbi 		return -1;
56794ae9843SFelipe Balbi 
56894ae9843SFelipe Balbi 	if (count > 2)
56994ae9843SFelipe Balbi 		return -1;
57094ae9843SFelipe Balbi 
57194ae9843SFelipe Balbi 	if (buf[0] == '1') {
57294ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_clr_err = 1;
57394ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev,
57494ae9843SFelipe Balbi 			"User request: a_clr_err = 1\n");
57594ae9843SFelipe Balbi 	}
57694ae9843SFelipe Balbi 
57794ae9843SFelipe Balbi 	if (spin_trylock(&mvotg->wq_lock)) {
57894ae9843SFelipe Balbi 		mv_otg_run_state_machine(mvotg, 0);
57994ae9843SFelipe Balbi 		spin_unlock(&mvotg->wq_lock);
58094ae9843SFelipe Balbi 	}
58194ae9843SFelipe Balbi 
58294ae9843SFelipe Balbi 	return count;
58394ae9843SFelipe Balbi }
58494ae9843SFelipe Balbi 
585ca35910aSGreg Kroah-Hartman static DEVICE_ATTR_WO(a_clr_err);
58694ae9843SFelipe Balbi 
58794ae9843SFelipe Balbi static ssize_t
a_bus_drop_show(struct device * dev,struct device_attribute * attr,char * buf)588ed5bd7a4SGreg Kroah-Hartman a_bus_drop_show(struct device *dev, struct device_attribute *attr,
58994ae9843SFelipe Balbi 	       char *buf)
59094ae9843SFelipe Balbi {
59194ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev_get_drvdata(dev);
59294ae9843SFelipe Balbi 	return scnprintf(buf, PAGE_SIZE, "%d\n",
59394ae9843SFelipe Balbi 			 mvotg->otg_ctrl.a_bus_drop);
59494ae9843SFelipe Balbi }
59594ae9843SFelipe Balbi 
59694ae9843SFelipe Balbi static ssize_t
a_bus_drop_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)597ed5bd7a4SGreg Kroah-Hartman a_bus_drop_store(struct device *dev, struct device_attribute *attr,
59894ae9843SFelipe Balbi 	       const char *buf, size_t count)
59994ae9843SFelipe Balbi {
60094ae9843SFelipe Balbi 	struct mv_otg *mvotg = dev_get_drvdata(dev);
60194ae9843SFelipe Balbi 	if (!mvotg->phy.otg->default_a)
60294ae9843SFelipe Balbi 		return -1;
60394ae9843SFelipe Balbi 
60494ae9843SFelipe Balbi 	if (count > 2)
60594ae9843SFelipe Balbi 		return -1;
60694ae9843SFelipe Balbi 
60794ae9843SFelipe Balbi 	if (buf[0] == '0') {
60894ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_bus_drop = 0;
60994ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev,
61094ae9843SFelipe Balbi 			"User request: a_bus_drop = 0\n");
61194ae9843SFelipe Balbi 	} else if (buf[0] == '1') {
61294ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_bus_drop = 1;
61394ae9843SFelipe Balbi 		mvotg->otg_ctrl.a_bus_req = 0;
61494ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev,
61594ae9843SFelipe Balbi 			"User request: a_bus_drop = 1\n");
61694ae9843SFelipe Balbi 		dev_dbg(&mvotg->pdev->dev,
61794ae9843SFelipe Balbi 			"User request: and a_bus_req = 0\n");
61894ae9843SFelipe Balbi 	}
61994ae9843SFelipe Balbi 
62094ae9843SFelipe Balbi 	if (spin_trylock(&mvotg->wq_lock)) {
62194ae9843SFelipe Balbi 		mv_otg_run_state_machine(mvotg, 0);
62294ae9843SFelipe Balbi 		spin_unlock(&mvotg->wq_lock);
62394ae9843SFelipe Balbi 	}
62494ae9843SFelipe Balbi 
62594ae9843SFelipe Balbi 	return count;
62694ae9843SFelipe Balbi }
62794ae9843SFelipe Balbi 
628ed5bd7a4SGreg Kroah-Hartman static DEVICE_ATTR_RW(a_bus_drop);
62994ae9843SFelipe Balbi 
63094ae9843SFelipe Balbi static struct attribute *inputs_attrs[] = {
63194ae9843SFelipe Balbi 	&dev_attr_a_bus_req.attr,
63294ae9843SFelipe Balbi 	&dev_attr_a_clr_err.attr,
63394ae9843SFelipe Balbi 	&dev_attr_a_bus_drop.attr,
63494ae9843SFelipe Balbi 	NULL,
63594ae9843SFelipe Balbi };
63694ae9843SFelipe Balbi 
6371cefc269SArvind Yadav static const struct attribute_group inputs_attr_group = {
63894ae9843SFelipe Balbi 	.name = "inputs",
63994ae9843SFelipe Balbi 	.attrs = inputs_attrs,
64094ae9843SFelipe Balbi };
64194ae9843SFelipe Balbi 
6423e2cb866SGreg Kroah-Hartman static const struct attribute_group *mv_otg_groups[] = {
6433e2cb866SGreg Kroah-Hartman 	&inputs_attr_group,
6443e2cb866SGreg Kroah-Hartman 	NULL,
6453e2cb866SGreg Kroah-Hartman };
6463e2cb866SGreg Kroah-Hartman 
mv_otg_remove(struct platform_device * pdev)647*25b979e4SUwe Kleine-König static void mv_otg_remove(struct platform_device *pdev)
64894ae9843SFelipe Balbi {
64994ae9843SFelipe Balbi 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
65094ae9843SFelipe Balbi 
651f057a1d4SChristophe JAILLET 	if (mvotg->qwork)
65294ae9843SFelipe Balbi 		destroy_workqueue(mvotg->qwork);
65394ae9843SFelipe Balbi 
65494ae9843SFelipe Balbi 	mv_otg_disable(mvotg);
65594ae9843SFelipe Balbi 
65694ae9843SFelipe Balbi 	usb_remove_phy(&mvotg->phy);
65794ae9843SFelipe Balbi }
65894ae9843SFelipe Balbi 
mv_otg_probe(struct platform_device * pdev)65994ae9843SFelipe Balbi static int mv_otg_probe(struct platform_device *pdev)
66094ae9843SFelipe Balbi {
66119f9e188SJingoo Han 	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
66294ae9843SFelipe Balbi 	struct mv_otg *mvotg;
66394ae9843SFelipe Balbi 	struct usb_otg *otg;
66494ae9843SFelipe Balbi 	struct resource *r;
665df18fedaSChao Xie 	int retval = 0, i;
66694ae9843SFelipe Balbi 
66794ae9843SFelipe Balbi 	if (pdata == NULL) {
66894ae9843SFelipe Balbi 		dev_err(&pdev->dev, "failed to get platform data\n");
66994ae9843SFelipe Balbi 		return -ENODEV;
67094ae9843SFelipe Balbi 	}
67194ae9843SFelipe Balbi 
672df18fedaSChao Xie 	mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
673aa10c7b0SPeter Chen 	if (!mvotg)
67494ae9843SFelipe Balbi 		return -ENOMEM;
67594ae9843SFelipe Balbi 
67694ae9843SFelipe Balbi 	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
67794ae9843SFelipe Balbi 	if (!otg)
67894ae9843SFelipe Balbi 		return -ENOMEM;
67994ae9843SFelipe Balbi 
68094ae9843SFelipe Balbi 	platform_set_drvdata(pdev, mvotg);
68194ae9843SFelipe Balbi 
68294ae9843SFelipe Balbi 	mvotg->pdev = pdev;
68394ae9843SFelipe Balbi 	mvotg->pdata = pdata;
68494ae9843SFelipe Balbi 
685df18fedaSChao Xie 	mvotg->clk = devm_clk_get(&pdev->dev, NULL);
686df18fedaSChao Xie 	if (IS_ERR(mvotg->clk))
687df18fedaSChao Xie 		return PTR_ERR(mvotg->clk);
68894ae9843SFelipe Balbi 
68994ae9843SFelipe Balbi 	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
69094ae9843SFelipe Balbi 	if (!mvotg->qwork) {
69194ae9843SFelipe Balbi 		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
69294ae9843SFelipe Balbi 		return -ENOMEM;
69394ae9843SFelipe Balbi 	}
69494ae9843SFelipe Balbi 
69594ae9843SFelipe Balbi 	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
69694ae9843SFelipe Balbi 
69794ae9843SFelipe Balbi 	/* OTG common part */
69894ae9843SFelipe Balbi 	mvotg->pdev = pdev;
69994ae9843SFelipe Balbi 	mvotg->phy.dev = &pdev->dev;
70094ae9843SFelipe Balbi 	mvotg->phy.otg = otg;
70194ae9843SFelipe Balbi 	mvotg->phy.label = driver_name;
70294ae9843SFelipe Balbi 
703e47d9254SAntoine Tenart 	otg->state = OTG_STATE_UNDEFINED;
70419c1eac2SAntoine Tenart 	otg->usb_phy = &mvotg->phy;
70594ae9843SFelipe Balbi 	otg->set_host = mv_otg_set_host;
70694ae9843SFelipe Balbi 	otg->set_peripheral = mv_otg_set_peripheral;
70794ae9843SFelipe Balbi 	otg->set_vbus = mv_otg_set_vbus;
70894ae9843SFelipe Balbi 
70994ae9843SFelipe Balbi 	for (i = 0; i < OTG_TIMER_NUM; i++)
7109718756fSKees Cook 		timer_setup(&mvotg->otg_ctrl.timer[i],
7119718756fSKees Cook 			    mv_otg_timer_await_bcon, 0);
71294ae9843SFelipe Balbi 
71394ae9843SFelipe Balbi 	r = platform_get_resource_byname(mvotg->pdev,
71494ae9843SFelipe Balbi 					 IORESOURCE_MEM, "phyregs");
71594ae9843SFelipe Balbi 	if (r == NULL) {
71694ae9843SFelipe Balbi 		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
71794ae9843SFelipe Balbi 		retval = -ENODEV;
71894ae9843SFelipe Balbi 		goto err_destroy_workqueue;
71994ae9843SFelipe Balbi 	}
72094ae9843SFelipe Balbi 
72194ae9843SFelipe Balbi 	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
72294ae9843SFelipe Balbi 	if (mvotg->phy_regs == NULL) {
72394ae9843SFelipe Balbi 		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
72494ae9843SFelipe Balbi 		retval = -EFAULT;
72594ae9843SFelipe Balbi 		goto err_destroy_workqueue;
72694ae9843SFelipe Balbi 	}
72794ae9843SFelipe Balbi 
72894ae9843SFelipe Balbi 	r = platform_get_resource_byname(mvotg->pdev,
72994ae9843SFelipe Balbi 					 IORESOURCE_MEM, "capregs");
73094ae9843SFelipe Balbi 	if (r == NULL) {
73194ae9843SFelipe Balbi 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
73294ae9843SFelipe Balbi 		retval = -ENODEV;
73394ae9843SFelipe Balbi 		goto err_destroy_workqueue;
73494ae9843SFelipe Balbi 	}
73594ae9843SFelipe Balbi 
73694ae9843SFelipe Balbi 	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
73794ae9843SFelipe Balbi 	if (mvotg->cap_regs == NULL) {
73894ae9843SFelipe Balbi 		dev_err(&pdev->dev, "failed to map I/O memory\n");
73994ae9843SFelipe Balbi 		retval = -EFAULT;
74094ae9843SFelipe Balbi 		goto err_destroy_workqueue;
74194ae9843SFelipe Balbi 	}
74294ae9843SFelipe Balbi 
74394ae9843SFelipe Balbi 	/* we will acces controller register, so enable the udc controller */
74494ae9843SFelipe Balbi 	retval = mv_otg_enable_internal(mvotg);
74594ae9843SFelipe Balbi 	if (retval) {
74694ae9843SFelipe Balbi 		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
74794ae9843SFelipe Balbi 		goto err_destroy_workqueue;
74894ae9843SFelipe Balbi 	}
74994ae9843SFelipe Balbi 
75094ae9843SFelipe Balbi 	mvotg->op_regs =
75194ae9843SFelipe Balbi 		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
75294ae9843SFelipe Balbi 			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
75394ae9843SFelipe Balbi 
75494ae9843SFelipe Balbi 	if (pdata->id) {
75594ae9843SFelipe Balbi 		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
75694ae9843SFelipe Balbi 						NULL, mv_otg_inputs_irq,
75794ae9843SFelipe Balbi 						IRQF_ONESHOT, "id", mvotg);
75894ae9843SFelipe Balbi 		if (retval) {
75994ae9843SFelipe Balbi 			dev_info(&pdev->dev,
76094ae9843SFelipe Balbi 				 "Failed to request irq for ID\n");
76194ae9843SFelipe Balbi 			pdata->id = NULL;
76294ae9843SFelipe Balbi 		}
76394ae9843SFelipe Balbi 	}
76494ae9843SFelipe Balbi 
76594ae9843SFelipe Balbi 	if (pdata->vbus) {
76694ae9843SFelipe Balbi 		mvotg->clock_gating = 1;
76794ae9843SFelipe Balbi 		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
76894ae9843SFelipe Balbi 						NULL, mv_otg_inputs_irq,
76994ae9843SFelipe Balbi 						IRQF_ONESHOT, "vbus", mvotg);
77094ae9843SFelipe Balbi 		if (retval) {
77194ae9843SFelipe Balbi 			dev_info(&pdev->dev,
77294ae9843SFelipe Balbi 				 "Failed to request irq for VBUS, "
77394ae9843SFelipe Balbi 				 "disable clock gating\n");
77494ae9843SFelipe Balbi 			mvotg->clock_gating = 0;
77594ae9843SFelipe Balbi 			pdata->vbus = NULL;
77694ae9843SFelipe Balbi 		}
77794ae9843SFelipe Balbi 	}
77894ae9843SFelipe Balbi 
77994ae9843SFelipe Balbi 	if (pdata->disable_otg_clock_gating)
78094ae9843SFelipe Balbi 		mvotg->clock_gating = 0;
78194ae9843SFelipe Balbi 
78294ae9843SFelipe Balbi 	mv_otg_reset(mvotg);
78394ae9843SFelipe Balbi 	mv_otg_init_irq(mvotg);
78494ae9843SFelipe Balbi 
78594ae9843SFelipe Balbi 	r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
78694ae9843SFelipe Balbi 	if (r == NULL) {
78794ae9843SFelipe Balbi 		dev_err(&pdev->dev, "no IRQ resource defined\n");
78894ae9843SFelipe Balbi 		retval = -ENODEV;
78994ae9843SFelipe Balbi 		goto err_disable_clk;
79094ae9843SFelipe Balbi 	}
79194ae9843SFelipe Balbi 
79294ae9843SFelipe Balbi 	mvotg->irq = r->start;
79394ae9843SFelipe Balbi 	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
79494ae9843SFelipe Balbi 			driver_name, mvotg)) {
79594ae9843SFelipe Balbi 		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
79694ae9843SFelipe Balbi 			mvotg->irq);
79794ae9843SFelipe Balbi 		mvotg->irq = 0;
79894ae9843SFelipe Balbi 		retval = -ENODEV;
79994ae9843SFelipe Balbi 		goto err_disable_clk;
80094ae9843SFelipe Balbi 	}
80194ae9843SFelipe Balbi 
80294ae9843SFelipe Balbi 	retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
80394ae9843SFelipe Balbi 	if (retval < 0) {
80494ae9843SFelipe Balbi 		dev_err(&pdev->dev, "can't register transceiver, %d\n",
80594ae9843SFelipe Balbi 			retval);
80694ae9843SFelipe Balbi 		goto err_disable_clk;
80794ae9843SFelipe Balbi 	}
80894ae9843SFelipe Balbi 
80994ae9843SFelipe Balbi 	spin_lock_init(&mvotg->wq_lock);
81094ae9843SFelipe Balbi 	if (spin_trylock(&mvotg->wq_lock)) {
81194ae9843SFelipe Balbi 		mv_otg_run_state_machine(mvotg, 2 * HZ);
81294ae9843SFelipe Balbi 		spin_unlock(&mvotg->wq_lock);
81394ae9843SFelipe Balbi 	}
81494ae9843SFelipe Balbi 
81594ae9843SFelipe Balbi 	dev_info(&pdev->dev,
81694ae9843SFelipe Balbi 		 "successful probe OTG device %s clock gating.\n",
81794ae9843SFelipe Balbi 		 mvotg->clock_gating ? "with" : "without");
81894ae9843SFelipe Balbi 
81994ae9843SFelipe Balbi 	return 0;
82094ae9843SFelipe Balbi 
82194ae9843SFelipe Balbi err_disable_clk:
82294ae9843SFelipe Balbi 	mv_otg_disable_internal(mvotg);
82394ae9843SFelipe Balbi err_destroy_workqueue:
82494ae9843SFelipe Balbi 	destroy_workqueue(mvotg->qwork);
82594ae9843SFelipe Balbi 
82694ae9843SFelipe Balbi 	return retval;
82794ae9843SFelipe Balbi }
82894ae9843SFelipe Balbi 
82994ae9843SFelipe Balbi #ifdef CONFIG_PM
mv_otg_suspend(struct platform_device * pdev,pm_message_t state)83094ae9843SFelipe Balbi static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state)
83194ae9843SFelipe Balbi {
83294ae9843SFelipe Balbi 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
83394ae9843SFelipe Balbi 
83490bdf403SArnd Bergmann 	if (mvotg->phy.otg->state != OTG_STATE_B_IDLE) {
83594ae9843SFelipe Balbi 		dev_info(&pdev->dev,
83694ae9843SFelipe Balbi 			 "OTG state is not B_IDLE, it is %d!\n",
83790bdf403SArnd Bergmann 			 mvotg->phy.otg->state);
83894ae9843SFelipe Balbi 		return -EAGAIN;
83994ae9843SFelipe Balbi 	}
84094ae9843SFelipe Balbi 
84194ae9843SFelipe Balbi 	if (!mvotg->clock_gating)
84294ae9843SFelipe Balbi 		mv_otg_disable_internal(mvotg);
84394ae9843SFelipe Balbi 
84494ae9843SFelipe Balbi 	return 0;
84594ae9843SFelipe Balbi }
84694ae9843SFelipe Balbi 
mv_otg_resume(struct platform_device * pdev)84794ae9843SFelipe Balbi static int mv_otg_resume(struct platform_device *pdev)
84894ae9843SFelipe Balbi {
84994ae9843SFelipe Balbi 	struct mv_otg *mvotg = platform_get_drvdata(pdev);
85094ae9843SFelipe Balbi 	u32 otgsc;
85194ae9843SFelipe Balbi 
85294ae9843SFelipe Balbi 	if (!mvotg->clock_gating) {
85394ae9843SFelipe Balbi 		mv_otg_enable_internal(mvotg);
85494ae9843SFelipe Balbi 
85594ae9843SFelipe Balbi 		otgsc = readl(&mvotg->op_regs->otgsc);
85694ae9843SFelipe Balbi 		otgsc |= mvotg->irq_en;
85794ae9843SFelipe Balbi 		writel(otgsc, &mvotg->op_regs->otgsc);
85894ae9843SFelipe Balbi 
85994ae9843SFelipe Balbi 		if (spin_trylock(&mvotg->wq_lock)) {
86094ae9843SFelipe Balbi 			mv_otg_run_state_machine(mvotg, 0);
86194ae9843SFelipe Balbi 			spin_unlock(&mvotg->wq_lock);
86294ae9843SFelipe Balbi 		}
86394ae9843SFelipe Balbi 	}
86494ae9843SFelipe Balbi 	return 0;
86594ae9843SFelipe Balbi }
86694ae9843SFelipe Balbi #endif
86794ae9843SFelipe Balbi 
86894ae9843SFelipe Balbi static struct platform_driver mv_otg_driver = {
86994ae9843SFelipe Balbi 	.probe = mv_otg_probe,
870*25b979e4SUwe Kleine-König 	.remove_new = mv_otg_remove,
87194ae9843SFelipe Balbi 	.driver = {
87294ae9843SFelipe Balbi 		   .name = driver_name,
8733e2cb866SGreg Kroah-Hartman 		   .dev_groups = mv_otg_groups,
87494ae9843SFelipe Balbi 		   },
87594ae9843SFelipe Balbi #ifdef CONFIG_PM
87694ae9843SFelipe Balbi 	.suspend = mv_otg_suspend,
87794ae9843SFelipe Balbi 	.resume = mv_otg_resume,
87894ae9843SFelipe Balbi #endif
87994ae9843SFelipe Balbi };
88094ae9843SFelipe Balbi module_platform_driver(mv_otg_driver);
881