u32 value;
int timeout_us = 100000;
+ if (role == CDNS3_ROLE_END)
+ return;
+
/* Wait clk value */
value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
writel(value, cdns->none_core_regs + USB3_SSPHY_STATUS);
if (cdns->roles[CDNS3_ROLE_HOST] && cdns->roles[CDNS3_ROLE_GADGET]) {
if (extcon_get_state(cdns->extcon, EXTCON_USB_HOST))
return CDNS3_ROLE_HOST;
- else
+ else if (extcon_get_state(cdns->extcon, EXTCON_USB))
return CDNS3_ROLE_GADGET;
+ else
+ return CDNS3_ROLE_END;
} else {
return cdns->roles[CDNS3_ROLE_HOST]
? CDNS3_ROLE_HOST
struct device *dev = cdns->dev;
enum usb_dr_mode dr_mode = usb_get_dr_mode(dev);
- cdns->role = CDNS3_ROLE_GADGET;
+ cdns->role = CDNS3_ROLE_END;
if (dr_mode == USB_DR_MODE_UNKNOWN)
dr_mode = USB_DR_MODE_OTG;
static irqreturn_t cdns3_irq(int irq, void *data)
{
struct cdns3 *cdns = data;
+ irqreturn_t ret = IRQ_NONE;
/* Handle device/host interrupt */
- return cdns3_role(cdns)->irq(cdns);
+ if (cdns->role != CDNS3_ROLE_END)
+ ret = cdns3_role(cdns)->irq(cdns);
+
+ return ret;
}
static int cdns3_get_clks(struct device *dev)
current_role = cdns->role;
cdns3_role_stop(cdns);
+ if (role == CDNS3_ROLE_END)
+ return 0;
+
cdns_set_role(cdns, role);
ret = cdns3_role_start(cdns, role);
if (ret) {
{
struct cdns3 *cdns = container_of(work, struct cdns3,
role_switch_wq);
- bool host;
+ bool device, host;
host = extcon_get_state(cdns->extcon, EXTCON_USB_HOST);
+ device = extcon_get_state(cdns->extcon, EXTCON_USB);
if (host)
cdsn3_do_role_switch(cdns, CDNS3_ROLE_HOST);
- else
+ else if (device)
cdsn3_do_role_switch(cdns, CDNS3_ROLE_GADGET);
+ else
+ cdsn3_do_role_switch(cdns, CDNS3_ROLE_END);
}
static int cdns3_extcon_notifier(struct notifier_block *nb, unsigned long event,
return ret;
}
+ ret = devm_extcon_register_notifier(dev, extcon,
+ EXTCON_USB, &cdns->extcon_nb);
+ if (ret < 0) {
+ dev_err(dev, "register Device Connector failed\n");
+ return ret;
+ }
+
cdns->extcon = extcon;
cdns->extcon_nb.notifier_call = cdns3_extcon_notifier;
}
enum cdns3_roles {
CDNS3_ROLE_HOST = 0,
CDNS3_ROLE_GADGET,
+ CDNS3_ROLE_END,
};
/**
struct usbss_dev_register_block_type __iomem *dev_regs;
void __iomem *none_core_regs;
int irq;
- struct cdns3_role_driver *roles[CDNS3_ROLE_GADGET + 1];
+ struct cdns3_role_driver *roles[CDNS3_ROLE_END];
enum cdns3_roles role;
struct device *host_dev;
struct device *gadget_dev;
static inline struct cdns3_role_driver *cdns3_role(struct cdns3 *cdns)
{
- WARN_ON(!cdns->roles[cdns->role]);
+ WARN_ON(cdns->role >= CDNS3_ROLE_END || !cdns->roles[cdns->role]);
return cdns->roles[cdns->role];
}
static inline int cdns3_role_start(struct cdns3 *cdns, enum cdns3_roles role)
{
+ if (role >= CDNS3_ROLE_END)
+ return 0;
+
if (!cdns->roles[role])
return -ENXIO;
{
enum cdns3_roles role = cdns->role;
+ if (role == CDNS3_ROLE_END)
+ return;
+
cdns->roles[role]->stop(cdns);
+ cdns->role = CDNS3_ROLE_END;
}
#endif /* __DRIVERS_USB_CDNS3_CORE_H */