aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/mtu3
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mtu3')
-rw-r--r--drivers/usb/mtu3/mtu3.h30
-rw-r--r--drivers/usb/mtu3/mtu3_core.c20
-rw-r--r--drivers/usb/mtu3/mtu3_debugfs.c1
-rw-r--r--drivers/usb/mtu3/mtu3_dr.c169
-rw-r--r--drivers/usb/mtu3/mtu3_gadget.c2
-rw-r--r--drivers/usb/mtu3/mtu3_host.c6
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c95
7 files changed, 92 insertions, 231 deletions
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
index aef0a0bba25a..5546b868b08b 100644
--- a/drivers/usb/mtu3/mtu3.h
+++ b/drivers/usb/mtu3/mtu3.h
@@ -10,6 +10,7 @@
#ifndef __MTU3_H__
#define __MTU3_H__
+#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/extcon.h>
@@ -21,6 +22,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
+#include <linux/usb/role.h>
struct mtu3;
struct mtu3_ep;
@@ -88,6 +90,8 @@ struct mtu3_request;
*/
#define EP0_RESPONSE_BUF 6
+#define BULK_CLKS_CNT 4
+
/* device operated link and speed got from DEVICE_CONF register */
enum mtu3_speed {
MTU3_SPEED_INACTIVE = 0,
@@ -192,13 +196,9 @@ struct mtu3_gpd_ring {
/**
* @vbus: vbus 5V used by host mode
* @edev: external connector used to detect vbus and iddig changes
-* @vbus_nb: notifier for vbus detection
-* @vbus_work : work of vbus detection notifier, used to avoid sleep in
-* notifier callback which is atomic context
-* @vbus_event : event of vbus detecion notifier
* @id_nb : notifier for iddig(idpin) detection
-* @id_work : work of iddig detection notifier
-* @id_event : event of iddig detecion notifier
+* @dr_work : work for drd mode switch, used to avoid sleep in atomic context
+* @desired_role : role desired to switch
* @role_sw : use USB Role Switch to support dual-role switch, can't use
* extcon at the same time, and extcon is deprecated.
* @role_sw_used : true when the USB Role Switch is used.
@@ -209,12 +209,9 @@ struct mtu3_gpd_ring {
struct otg_switch_mtk {
struct regulator *vbus;
struct extcon_dev *edev;
- struct notifier_block vbus_nb;
- struct work_struct vbus_work;
- unsigned long vbus_event;
struct notifier_block id_nb;
- struct work_struct id_work;
- unsigned long id_event;
+ struct work_struct dr_work;
+ enum usb_role desired_role;
struct usb_role_switch *role_sw;
bool role_sw_used;
bool is_u3_drd;
@@ -225,10 +222,6 @@ struct otg_switch_mtk {
* @mac_base: register base address of device MAC, exclude xHCI's
* @ippc_base: register base address of IP Power and Clock interface (IPPC)
* @vusb33: usb3.3V shared by device/host IP
- * @sys_clk: system clock of mtu3, shared by device/host IP
- * @ref_clk: reference clock
- * @mcu_clk: mcu_bus_ck clock for AHB bus etc
- * @dma_clk: dma_bus_ck clock for AXI bus etc
* @dr_mode: works in which mode:
* host only, device only or dual-role mode
* @u2_ports: number of usb2.0 host ports
@@ -250,10 +243,7 @@ struct ssusb_mtk {
int num_phys;
/* common power & clock */
struct regulator *vusb33;
- struct clk *sys_clk;
- struct clk *ref_clk;
- struct clk *mcu_clk;
- struct clk *dma_clk;
+ struct clk_bulk_data clks[BULK_CLKS_CNT];
/* otg */
struct otg_switch_mtk otg_switch;
enum usb_dr_mode dr_mode;
@@ -422,11 +412,9 @@ int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep,
int interval, int burst, int mult);
void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep);
void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set);
-void mtu3_ep0_setup(struct mtu3 *mtu);
void mtu3_start(struct mtu3 *mtu);
void mtu3_stop(struct mtu3 *mtu);
void mtu3_dev_on_off(struct mtu3 *mtu, int is_on);
-void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed);
int mtu3_gadget_setup(struct mtu3 *mtu);
void mtu3_gadget_cleanup(struct mtu3 *mtu);
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c
index b3b459937566..562f4357831e 100644
--- a/drivers/usb/mtu3/mtu3_core.c
+++ b/drivers/usb/mtu3/mtu3_core.c
@@ -207,7 +207,7 @@ static void mtu3_intr_enable(struct mtu3 *mtu)
mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR);
}
-void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed)
+static void mtu3_set_speed(struct mtu3 *mtu, enum usb_device_speed speed)
{
void __iomem *mbase = mtu->mac_base;
@@ -334,6 +334,10 @@ void mtu3_start(struct mtu3 *mtu)
mtu3_readl(mbase, U3D_DEVICE_CONTROL));
mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
+ if (mtu->is_u3_ip)
+ mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
+
+ mtu3_clrbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
mtu3_csr_init(mtu);
mtu3_set_speed(mtu, mtu->speed);
@@ -356,6 +360,11 @@ void mtu3_stop(struct mtu3 *mtu)
mtu3_dev_on_off(mtu, 0);
mtu->is_active = 0;
+
+ if (mtu->is_u3_ip)
+ mtu3_setbits(mtu->ippc_base, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_PDN);
+
+ mtu3_setbits(mtu->ippc_base, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_PDN);
mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
}
@@ -536,7 +545,7 @@ static void get_ep_fifo_config(struct mtu3 *mtu)
rx_fifo->base, rx_fifo->limit);
}
-void mtu3_ep0_setup(struct mtu3 *mtu)
+static void mtu3_ep0_setup(struct mtu3 *mtu)
{
u32 maxpacket = mtu->g.ep0->maxpacket;
u32 csr;
@@ -921,16 +930,15 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb)
device_init_wakeup(dev, true);
+ /* power down device IP for power saving by default */
+ mtu3_stop(mtu);
+
ret = mtu3_gadget_setup(mtu);
if (ret) {
dev_err(dev, "mtu3 gadget init failed:%d\n", ret);
goto gadget_err;
}
- /* init as host mode, power down device IP for power saving */
- if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG)
- mtu3_stop(mtu);
-
ssusb_dev_debugfs_init(ssusb);
dev_dbg(dev, " %s() done...\n", __func__);
diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c
index 7537bfd651af..d27de647c86a 100644
--- a/drivers/usb/mtu3/mtu3_debugfs.c
+++ b/drivers/usb/mtu3/mtu3_debugfs.c
@@ -30,6 +30,7 @@ static const struct debugfs_reg32 mtu3_ippc_regs[] = {
dump_register(SSUSB_IP_PW_CTRL1),
dump_register(SSUSB_IP_PW_CTRL2),
dump_register(SSUSB_IP_PW_CTRL3),
+ dump_register(SSUSB_IP_PW_STS1),
dump_register(SSUSB_OTG_STS),
dump_register(SSUSB_IP_XHCI_CAP),
dump_register(SSUSB_IP_DEV_CAP),
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c
index 04f666e85731..318fbc618137 100644
--- a/drivers/usb/mtu3/mtu3_dr.c
+++ b/drivers/usb/mtu3/mtu3_dr.c
@@ -7,8 +7,6 @@
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
*/
-#include <linux/usb/role.h>
-
#include "mtu3.h"
#include "mtu3_dr.h"
#include "mtu3_debug.h"
@@ -16,27 +14,9 @@
#define USB2_PORT 2
#define USB3_PORT 3
-enum mtu3_vbus_id_state {
- MTU3_ID_FLOAT = 1,
- MTU3_ID_GROUND,
- MTU3_VBUS_OFF,
- MTU3_VBUS_VALID,
-};
-
-static char *mailbox_state_string(enum mtu3_vbus_id_state state)
+static inline struct ssusb_mtk *otg_sx_to_ssusb(struct otg_switch_mtk *otg_sx)
{
- switch (state) {
- case MTU3_ID_FLOAT:
- return "ID_FLOAT";
- case MTU3_ID_GROUND:
- return "ID_GROUND";
- case MTU3_VBUS_OFF:
- return "VBUS_OFF";
- case MTU3_VBUS_VALID:
- return "VBUS_VALID";
- default:
- return "UNKNOWN";
- }
+ return container_of(otg_sx, struct ssusb_mtk, otg_switch);
}
static void toggle_opstate(struct ssusb_mtk *ssusb)
@@ -123,8 +103,7 @@ static void switch_port_to_device(struct ssusb_mtk *ssusb)
int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
{
- struct ssusb_mtk *ssusb =
- container_of(otg_sx, struct ssusb_mtk, otg_switch);
+ struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
struct regulator *vbus = otg_sx->vbus;
int ret;
@@ -147,99 +126,72 @@ int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
return 0;
}
-/*
- * switch to host: -> MTU3_VBUS_OFF --> MTU3_ID_GROUND
- * switch to device: -> MTU3_ID_FLOAT --> MTU3_VBUS_VALID
- */
-static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx,
- enum mtu3_vbus_id_state status)
+static void ssusb_mode_sw_work(struct work_struct *work)
{
- struct ssusb_mtk *ssusb =
- container_of(otg_sx, struct ssusb_mtk, otg_switch);
+ struct otg_switch_mtk *otg_sx =
+ container_of(work, struct otg_switch_mtk, dr_work);
+ struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
struct mtu3 *mtu = ssusb->u3d;
+ enum usb_role desired_role = otg_sx->desired_role;
+ enum usb_role current_role;
+
+ current_role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
+
+ if (desired_role == USB_ROLE_NONE)
+ desired_role = USB_ROLE_HOST;
- dev_dbg(ssusb->dev, "mailbox %s\n", mailbox_state_string(status));
- mtu3_dbg_trace(ssusb->dev, "mailbox %s", mailbox_state_string(status));
+ if (current_role == desired_role)
+ return;
+
+ dev_dbg(ssusb->dev, "set role : %s\n", usb_role_string(desired_role));
+ mtu3_dbg_trace(ssusb->dev, "set role : %s", usb_role_string(desired_role));
- switch (status) {
- case MTU3_ID_GROUND:
+ switch (desired_role) {
+ case USB_ROLE_HOST:
+ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
+ mtu3_stop(mtu);
switch_port_to_host(ssusb);
ssusb_set_vbus(otg_sx, 1);
ssusb->is_host = true;
break;
- case MTU3_ID_FLOAT:
+ case USB_ROLE_DEVICE:
+ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE);
ssusb->is_host = false;
ssusb_set_vbus(otg_sx, 0);
switch_port_to_device(ssusb);
- break;
- case MTU3_VBUS_OFF:
- mtu3_stop(mtu);
- pm_relax(ssusb->dev);
- break;
- case MTU3_VBUS_VALID:
- /* avoid suspend when works as device */
- pm_stay_awake(ssusb->dev);
mtu3_start(mtu);
break;
+ case USB_ROLE_NONE:
default:
- dev_err(ssusb->dev, "invalid state\n");
+ dev_err(ssusb->dev, "invalid role\n");
}
}
-static void ssusb_id_work(struct work_struct *work)
+static void ssusb_set_mode(struct otg_switch_mtk *otg_sx, enum usb_role role)
{
- struct otg_switch_mtk *otg_sx =
- container_of(work, struct otg_switch_mtk, id_work);
+ struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
- if (otg_sx->id_event)
- ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
- else
- ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
-}
-
-static void ssusb_vbus_work(struct work_struct *work)
-{
- struct otg_switch_mtk *otg_sx =
- container_of(work, struct otg_switch_mtk, vbus_work);
+ if (ssusb->dr_mode != USB_DR_MODE_OTG)
+ return;
- if (otg_sx->vbus_event)
- ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
- else
- ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
+ otg_sx->desired_role = role;
+ queue_work(system_freezable_wq, &otg_sx->dr_work);
}
-/*
- * @ssusb_id_notifier is called in atomic context, but @ssusb_set_mailbox
- * may sleep, so use work queue here
- */
static int ssusb_id_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct otg_switch_mtk *otg_sx =
container_of(nb, struct otg_switch_mtk, id_nb);
- otg_sx->id_event = event;
- schedule_work(&otg_sx->id_work);
-
- return NOTIFY_DONE;
-}
-
-static int ssusb_vbus_notifier(struct notifier_block *nb,
- unsigned long event, void *ptr)
-{
- struct otg_switch_mtk *otg_sx =
- container_of(nb, struct otg_switch_mtk, vbus_nb);
-
- otg_sx->vbus_event = event;
- schedule_work(&otg_sx->vbus_work);
+ ssusb_set_mode(otg_sx, event ? USB_ROLE_HOST : USB_ROLE_DEVICE);
return NOTIFY_DONE;
}
static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx)
{
- struct ssusb_mtk *ssusb =
- container_of(otg_sx, struct ssusb_mtk, otg_switch);
+ struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
struct extcon_dev *edev = otg_sx->edev;
int ret;
@@ -247,14 +199,6 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx)
if (!edev)
return 0;
- otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier;
- ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB,
- &otg_sx->vbus_nb);
- if (ret < 0) {
- dev_err(ssusb->dev, "failed to register notifier for USB\n");
- return ret;
- }
-
otg_sx->id_nb.notifier_call = ssusb_id_notifier;
ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST,
&otg_sx->id_nb);
@@ -263,15 +207,12 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx)
return ret;
}
- dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n",
- extcon_get_state(edev, EXTCON_USB),
- extcon_get_state(edev, EXTCON_USB_HOST));
+ ret = extcon_get_state(edev, EXTCON_USB_HOST);
+ dev_dbg(ssusb->dev, "EXTCON_USB_HOST: %d\n", ret);
/* default as host, switch to device mode if needed */
- if (extcon_get_state(edev, EXTCON_USB_HOST) == false)
- ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
- if (extcon_get_state(edev, EXTCON_USB) == true)
- ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
+ if (!ret)
+ ssusb_set_mode(otg_sx, USB_ROLE_DEVICE);
return 0;
}
@@ -286,15 +227,7 @@ void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
{
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
- if (to_host) {
- ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
- ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
- ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
- } else {
- ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE);
- ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
- ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
- }
+ ssusb_set_mode(otg_sx, to_host ? USB_ROLE_HOST : USB_ROLE_DEVICE);
}
void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
@@ -323,13 +256,9 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
static int ssusb_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
{
struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw);
- bool to_host = false;
-
- if (role == USB_ROLE_HOST)
- to_host = true;
+ struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
- if (to_host ^ ssusb->is_host)
- ssusb_mode_switch(ssusb, to_host);
+ ssusb_set_mode(otg_sx, role);
return 0;
}
@@ -337,18 +266,14 @@ static int ssusb_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
static enum usb_role ssusb_role_sw_get(struct usb_role_switch *sw)
{
struct ssusb_mtk *ssusb = usb_role_switch_get_drvdata(sw);
- enum usb_role role;
-
- role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
- return role;
+ return ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
}
static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx)
{
struct usb_role_switch_desc role_sx_desc = { 0 };
- struct ssusb_mtk *ssusb =
- container_of(otg_sx, struct ssusb_mtk, otg_switch);
+ struct ssusb_mtk *ssusb = otg_sx_to_ssusb(otg_sx);
if (!otg_sx->role_sw_used)
return 0;
@@ -367,8 +292,7 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
int ret = 0;
- INIT_WORK(&otg_sx->id_work, ssusb_id_work);
- INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work);
+ INIT_WORK(&otg_sx->dr_work, ssusb_mode_sw_work);
if (otg_sx->manual_drd_enabled)
ssusb_dr_debugfs_init(ssusb);
@@ -384,7 +308,6 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
{
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
- cancel_work_sync(&otg_sx->id_work);
- cancel_work_sync(&otg_sx->vbus_work);
+ cancel_work_sync(&otg_sx->dr_work);
usb_role_switch_unregister(otg_sx->role_sw);
}
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c
index 38f17d66d5bc..5e21ba05ebf0 100644
--- a/drivers/usb/mtu3/mtu3_gadget.c
+++ b/drivers/usb/mtu3/mtu3_gadget.c
@@ -577,7 +577,7 @@ mtu3_gadget_set_speed(struct usb_gadget *g, enum usb_device_speed speed)
dev_dbg(mtu->dev, "%s %s\n", __func__, usb_speed_string(speed));
spin_lock_irqsave(&mtu->lock, flags);
- mtu3_set_speed(mtu, speed);
+ mtu->speed = speed;
spin_unlock_irqrestore(&mtu->lock, flags);
}
diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c
index 0a8cd446cf1b..93a1a4c11e1e 100644
--- a/drivers/usb/mtu3/mtu3_host.c
+++ b/drivers/usb/mtu3/mtu3_host.c
@@ -213,8 +213,6 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend)
static void ssusb_host_setup(struct ssusb_mtk *ssusb)
{
- struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
-
host_ports_num_get(ssusb);
/*
@@ -222,9 +220,7 @@ static void ssusb_host_setup(struct ssusb_mtk *ssusb)
* if support OTG, gadget driver will switch port0 to device mode
*/
ssusb_host_enable(ssusb);
-
- if (otg_sx->manual_drd_enabled)
- ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
+ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
/* if port0 supports dual-role, works as host mode by default */
ssusb_set_vbus(&ssusb->otg_switch, 1);
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 7786a95a874e..c0615f6e5cce 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -5,7 +5,6 @@
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
*/
-#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
@@ -101,54 +100,6 @@ static void ssusb_phy_power_off(struct ssusb_mtk *ssusb)
phy_power_off(ssusb->phys[i]);
}
-static int ssusb_clks_enable(struct ssusb_mtk *ssusb)
-{
- int ret;
-
- ret = clk_prepare_enable(ssusb->sys_clk);
- if (ret) {
- dev_err(ssusb->dev, "failed to enable sys_clk\n");
- goto sys_clk_err;
- }
-
- ret = clk_prepare_enable(ssusb->ref_clk);
- if (ret) {
- dev_err(ssusb->dev, "failed to enable ref_clk\n");
- goto ref_clk_err;
- }
-
- ret = clk_prepare_enable(ssusb->mcu_clk);
- if (ret) {
- dev_err(ssusb->dev, "failed to enable mcu_clk\n");
- goto mcu_clk_err;
- }
-
- ret = clk_prepare_enable(ssusb->dma_clk);
- if (ret) {
- dev_err(ssusb->dev, "failed to enable dma_clk\n");
- goto dma_clk_err;
- }
-
- return 0;
-
-dma_clk_err:
- clk_disable_unprepare(ssusb->mcu_clk);
-mcu_clk_err:
- clk_disable_unprepare(ssusb->ref_clk);
-ref_clk_err:
- clk_disable_unprepare(ssusb->sys_clk);
-sys_clk_err:
- return ret;
-}
-
-static void ssusb_clks_disable(struct ssusb_mtk *ssusb)
-{
- clk_disable_unprepare(ssusb->dma_clk);
- clk_disable_unprepare(ssusb->mcu_clk);
- clk_disable_unprepare(ssusb->ref_clk);
- clk_disable_unprepare(ssusb->sys_clk);
-}
-
static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
{
int ret = 0;
@@ -159,7 +110,7 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
goto vusb33_err;
}
- ret = ssusb_clks_enable(ssusb);
+ ret = clk_bulk_prepare_enable(BULK_CLKS_CNT, ssusb->clks);
if (ret)
goto clks_err;
@@ -180,7 +131,7 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
phy_err:
ssusb_phy_exit(ssusb);
phy_init_err:
- ssusb_clks_disable(ssusb);
+ clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
clks_err:
regulator_disable(ssusb->vusb33);
vusb33_err:
@@ -189,7 +140,7 @@ vusb33_err:
static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
{
- ssusb_clks_disable(ssusb);
+ clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
regulator_disable(ssusb->vusb33);
ssusb_phy_power_off(ssusb);
ssusb_phy_exit(ssusb);
@@ -215,6 +166,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
{
struct device_node *node = pdev->dev.of_node;
struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
+ struct clk_bulk_data *clks = ssusb->clks;
struct device *dev = &pdev->dev;
int i;
int ret;
@@ -225,23 +177,13 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
return PTR_ERR(ssusb->vusb33);
}
- ssusb->sys_clk = devm_clk_get(dev, "sys_ck");
- if (IS_ERR(ssusb->sys_clk)) {
- dev_err(dev, "failed to get sys clock\n");
- return PTR_ERR(ssusb->sys_clk);
- }
-
- ssusb->ref_clk = devm_clk_get_optional(dev, "ref_ck");
- if (IS_ERR(ssusb->ref_clk))
- return PTR_ERR(ssusb->ref_clk);
-
- ssusb->mcu_clk = devm_clk_get_optional(dev, "mcu_ck");
- if (IS_ERR(ssusb->mcu_clk))
- return PTR_ERR(ssusb->mcu_clk);
-
- ssusb->dma_clk = devm_clk_get_optional(dev, "dma_ck");
- if (IS_ERR(ssusb->dma_clk))
- return PTR_ERR(ssusb->dma_clk);
+ clks[0].id = "sys_ck";
+ clks[1].id = "ref_ck";
+ clks[2].id = "mcu_ck";
+ clks[3].id = "dma_ck";
+ ret = devm_clk_bulk_get_optional(dev, BULK_CLKS_CNT, clks);
+ if (ret)
+ return ret;
ssusb->num_phys = of_count_phandle_with_args(node,
"phys", "#phy-cells");
@@ -299,11 +241,14 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
of_property_read_bool(node, "enable-manual-drd");
otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
- if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
+ if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled)
+ goto out;
+
+ if (of_property_read_bool(node, "extcon")) {
otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
if (IS_ERR(otg_sx->edev)) {
- dev_err(ssusb->dev, "couldn't get extcon device\n");
- return PTR_ERR(otg_sx->edev);
+ return dev_err_probe(dev, PTR_ERR(otg_sx->edev),
+ "couldn't get extcon device\n");
}
}
@@ -461,7 +406,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev)
ssusb_host_disable(ssusb, true);
ssusb_phy_power_off(ssusb);
- ssusb_clks_disable(ssusb);
+ clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
ssusb_wakeup_set(ssusb, true);
return 0;
@@ -478,7 +423,7 @@ static int __maybe_unused mtu3_resume(struct device *dev)
return 0;
ssusb_wakeup_set(ssusb, false);
- ret = ssusb_clks_enable(ssusb);
+ ret = clk_bulk_prepare_enable(BULK_CLKS_CNT, ssusb->clks);
if (ret)
goto clks_err;
@@ -491,7 +436,7 @@ static int __maybe_unused mtu3_resume(struct device *dev)
return 0;
phy_err:
- ssusb_clks_disable(ssusb);
+ clk_bulk_disable_unprepare(BULK_CLKS_CNT, ssusb->clks);
clks_err:
return ret;
}