Commit 117777b2 authored by Dinh Nguyen's avatar Dinh Nguyen Committed by Felipe Balbi

usb: dwc2: Move gadget probe function into platform code

This patch will aggregate the probing of gadget/hcd driver into platform.c.
The gadget probe funtion is converted into gadget_init that is now only
responsible for gadget only initialization. All the gadget resources are now
handled by platform.c

Since the host workqueue will not get initialized if the driver is configured
for peripheral mode only. Thus we need to check for wq_otg before calling
queue_work().

Also, we move spin_lock_init to common location for both host and gadget that
is either in platform.c or pci.c.

We also move suspend/resume code to common platform code.

Lastly, move the "samsung,s3c6400-hsotg" binding into dwc2_of_match_table.
Signed-off-by: default avatarDinh Nguyen <dinguyen@opensource.altera.com>
Acked-by: default avatarPaul Zimmerman <paulz@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 941fcce4
...@@ -960,4 +960,37 @@ extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg); ...@@ -960,4 +960,37 @@ extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg);
*/ */
extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg); extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
/* Gadget defines */
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
#else
static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
{ return 0; }
static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ return 0; }
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
#else
static inline void dwc2_set_all_params(struct dwc2_core_params *params, int value) {}
static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
const struct dwc2_core_params *params)
{ return 0; }
#endif
#endif /* __DWC2_CORE_H__ */ #endif /* __DWC2_CORE_H__ */
...@@ -287,9 +287,11 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) ...@@ -287,9 +287,11 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
* Release lock before scheduling workq as it holds spinlock during * Release lock before scheduling workq as it holds spinlock during
* scheduling. * scheduling.
*/ */
spin_unlock(&hsotg->lock); if (hsotg->wq_otg) {
queue_work(hsotg->wq_otg, &hsotg->wf_otg); spin_unlock(&hsotg->lock);
spin_lock(&hsotg->lock); queue_work(hsotg->wq_otg, &hsotg->wf_otg);
spin_lock(&hsotg->lock);
}
/* Clear interrupt */ /* Clear interrupt */
writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS); writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
......
...@@ -3423,26 +3423,21 @@ static void s3c_hsotg_delete_debug(struct dwc2_hsotg *hsotg) ...@@ -3423,26 +3423,21 @@ static void s3c_hsotg_delete_debug(struct dwc2_hsotg *hsotg)
} }
/** /**
* s3c_hsotg_probe - probe function for hsotg driver * dwc2_gadget_init - init function for gadget
* @pdev: The platform information for the driver * @dwc2: The data structure for the DWC2 driver.
* @irq: The IRQ number for the controller.
*/ */
static int s3c_hsotg_probe(struct platform_device *pdev) int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
{ {
struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev); struct device *dev = hsotg->dev;
struct s3c_hsotg_plat *plat = dev->platform_data;
struct phy *phy; struct phy *phy;
struct usb_phy *uphy; struct usb_phy *uphy;
struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps; struct s3c_hsotg_ep *eps;
struct dwc2_hsotg *hsotg;
struct resource *res;
int epnum; int epnum;
int ret; int ret;
int i; int i;
hsotg = devm_kzalloc(&pdev->dev, sizeof(struct dwc2_hsotg), GFP_KERNEL);
if (!hsotg)
return -ENOMEM;
/* Set default UTMI width */ /* Set default UTMI width */
hsotg->phyif = GUSBCFG_PHYIF16; hsotg->phyif = GUSBCFG_PHYIF16;
...@@ -3450,14 +3445,14 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3450,14 +3445,14 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
* Attempt to find a generic PHY, then look for an old style * Attempt to find a generic PHY, then look for an old style
* USB PHY, finally fall back to pdata * USB PHY, finally fall back to pdata
*/ */
phy = devm_phy_get(&pdev->dev, "usb2-phy"); phy = devm_phy_get(dev, "usb2-phy");
if (IS_ERR(phy)) { if (IS_ERR(phy)) {
uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR(uphy)) { if (IS_ERR(uphy)) {
/* Fallback for pdata */ /* Fallback for pdata */
plat = dev_get_platdata(&pdev->dev); plat = dev_get_platdata(dev);
if (!plat) { if (!plat) {
dev_err(&pdev->dev, dev_err(dev,
"no platform data or transceiver defined\n"); "no platform data or transceiver defined\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
...@@ -3474,36 +3469,12 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3474,36 +3469,12 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
hsotg->phyif = GUSBCFG_PHYIF8; hsotg->phyif = GUSBCFG_PHYIF8;
} }
hsotg->dev = dev; hsotg->clk = devm_clk_get(dev, "otg");
hsotg->clk = devm_clk_get(&pdev->dev, "otg");
if (IS_ERR(hsotg->clk)) { if (IS_ERR(hsotg->clk)) {
dev_err(dev, "cannot get otg clock\n"); dev_err(dev, "cannot get otg clock\n");
return PTR_ERR(hsotg->clk); return PTR_ERR(hsotg->clk);
} }
platform_set_drvdata(pdev, hsotg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hsotg->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hsotg->regs)) {
ret = PTR_ERR(hsotg->regs);
goto err_clk;
}
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(dev, "cannot find IRQ\n");
goto err_clk;
}
spin_lock_init(&hsotg->lock);
hsotg->irq = ret;
dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = &s3c_hsotg_gadget_ops; hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev); hsotg->gadget.name = dev_name(dev);
...@@ -3520,7 +3491,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3520,7 +3491,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies), ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
hsotg->supplies); hsotg->supplies);
if (ret) { if (ret) {
dev_err(hsotg->dev, "failed to request supplies: %d\n", ret); dev_err(dev, "failed to request supplies: %d\n", ret);
goto err_clk; goto err_clk;
} }
...@@ -3539,7 +3510,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3539,7 +3510,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_hw_cfg(hsotg); s3c_hsotg_hw_cfg(hsotg);
s3c_hsotg_init(hsotg); s3c_hsotg_init(hsotg);
ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, ret = devm_request_irq(dev, irq, s3c_hsotg_irq, 0,
dev_name(dev), hsotg); dev_name(dev), hsotg);
if (ret < 0) { if (ret < 0) {
s3c_hsotg_phy_disable(hsotg); s3c_hsotg_phy_disable(hsotg);
...@@ -3592,11 +3563,11 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3592,11 +3563,11 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies); hsotg->supplies);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to disable supplies: %d\n", ret); dev_err(dev, "failed to disable supplies: %d\n", ret);
goto err_ep_mem; goto err_ep_mem;
} }
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); ret = usb_add_gadget_udc(dev, &hsotg->gadget);
if (ret) if (ret)
goto err_ep_mem; goto err_ep_mem;
...@@ -3615,25 +3586,24 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3615,25 +3586,24 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dwc2_gadget_init);
/** /**
* s3c_hsotg_remove - remove function for hsotg driver * s3c_hsotg_remove - remove function for hsotg driver
* @pdev: The platform information for the driver * @pdev: The platform information for the driver
*/ */
static int s3c_hsotg_remove(struct platform_device *pdev) int s3c_hsotg_remove(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
usb_del_gadget_udc(&hsotg->gadget); usb_del_gadget_udc(&hsotg->gadget);
s3c_hsotg_delete_debug(hsotg); s3c_hsotg_delete_debug(hsotg);
clk_disable_unprepare(hsotg->clk); clk_disable_unprepare(hsotg->clk);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(s3c_hsotg_remove);
static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state) int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
...@@ -3661,10 +3631,10 @@ static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -3661,10 +3631,10 @@ static int s3c_hsotg_suspend(struct platform_device *pdev, pm_message_t state)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(s3c_hsotg_suspend);
static int s3c_hsotg_resume(struct platform_device *pdev) int s3c_hsotg_resume(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_hsotg *hsotg = platform_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
...@@ -3686,31 +3656,4 @@ static int s3c_hsotg_resume(struct platform_device *pdev) ...@@ -3686,31 +3656,4 @@ static int s3c_hsotg_resume(struct platform_device *pdev)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(s3c_hsotg_resume);
#ifdef CONFIG_OF
static const struct of_device_id s3c_hsotg_of_ids[] = {
{ .compatible = "samsung,s3c6400-hsotg", },
{ .compatible = "snps,dwc2", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
#endif
static struct platform_driver s3c_hsotg_driver = {
.driver = {
.name = "s3c-hsotg",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(s3c_hsotg_of_ids),
},
.probe = s3c_hsotg_probe,
.remove = s3c_hsotg_remove,
.suspend = s3c_hsotg_suspend,
.resume = s3c_hsotg_resume,
};
module_platform_driver(s3c_hsotg_driver);
MODULE_DESCRIPTION("Samsung S3C USB High-speed/OtG device");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c-hsotg");
...@@ -2905,7 +2905,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, ...@@ -2905,7 +2905,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
hcd->has_tt = 1; hcd->has_tt = 1;
spin_lock_init(&hsotg->lock);
((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg; ((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg;
hsotg->priv = hcd; hsotg->priv = hcd;
......
...@@ -668,9 +668,6 @@ extern irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg); ...@@ -668,9 +668,6 @@ extern irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg);
*/ */
extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg); extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
/** /**
* dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host, * dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
* and 0 otherwise * and 0 otherwise
...@@ -679,13 +676,6 @@ extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg); ...@@ -679,13 +676,6 @@ extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
*/ */
extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg); extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
/**
* dwc2_hcd_get_frame_number() - Returns current frame number
*
* @hsotg: The DWC2 HCD
*/
extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
/** /**
* dwc2_hcd_dump_state() - Dumps hsotg state * dwc2_hcd_dump_state() - Dumps hsotg state
* *
......
...@@ -141,6 +141,7 @@ static int dwc2_driver_probe(struct pci_dev *dev, ...@@ -141,6 +141,7 @@ static int dwc2_driver_probe(struct pci_dev *dev,
pci_set_master(dev); pci_set_master(dev);
spin_lock_init(&hsotg->lock);
retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params); retval = dwc2_hcd_init(hsotg, dev->irq, &dwc2_module_params);
if (retval) { if (retval) {
pci_disable_device(dev); pci_disable_device(dev);
......
...@@ -121,6 +121,7 @@ static int dwc2_driver_remove(struct platform_device *dev) ...@@ -121,6 +121,7 @@ static int dwc2_driver_remove(struct platform_device *dev)
struct dwc2_hsotg *hsotg = platform_get_drvdata(dev); struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
dwc2_hcd_remove(hsotg); dwc2_hcd_remove(hsotg);
s3c_hsotg_remove(hsotg);
return 0; return 0;
} }
...@@ -129,6 +130,7 @@ static const struct of_device_id dwc2_of_match_table[] = { ...@@ -129,6 +130,7 @@ static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "brcm,bcm2835-usb", .data = &params_bcm2835 }, { .compatible = "brcm,bcm2835-usb", .data = &params_bcm2835 },
{ .compatible = "rockchip,rk3066-usb", .data = &params_rk3066 }, { .compatible = "rockchip,rk3066-usb", .data = &params_rk3066 },
{ .compatible = "snps,dwc2", .data = NULL }, { .compatible = "snps,dwc2", .data = NULL },
{ .compatible = "samsung,s3c6400-hsotg", .data = NULL},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, dwc2_of_match_table); MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
...@@ -204,6 +206,10 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -204,6 +206,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node); hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
spin_lock_init(&hsotg->lock);
retval = dwc2_gadget_init(hsotg, irq);
if (retval)
return retval;
retval = dwc2_hcd_init(hsotg, irq, params); retval = dwc2_hcd_init(hsotg, irq, params);
if (retval) if (retval)
return retval; return retval;
...@@ -213,6 +219,26 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -213,6 +219,26 @@ static int dwc2_driver_probe(struct platform_device *dev)
return retval; return retval;
} }
static int dwc2_suspend(struct platform_device *dev, pm_message_t state)
{
struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
int ret = 0;
if (dwc2_is_device_mode(dwc2))
ret = s3c_hsotg_suspend(dwc2);
return ret;
}
static int dwc2_resume(struct platform_device *dev)
{
struct dwc2_hsotg *dwc2 = platform_get_drvdata(dev);
int ret = 0;
if (dwc2_is_device_mode(dwc2))
ret = s3c_hsotg_resume(dwc2);
return ret;
}
static struct platform_driver dwc2_platform_driver = { static struct platform_driver dwc2_platform_driver = {
.driver = { .driver = {
.name = dwc2_driver_name, .name = dwc2_driver_name,
...@@ -220,6 +246,8 @@ static struct platform_driver dwc2_platform_driver = { ...@@ -220,6 +246,8 @@ static struct platform_driver dwc2_platform_driver = {
}, },
.probe = dwc2_driver_probe, .probe = dwc2_driver_probe,
.remove = dwc2_driver_remove, .remove = dwc2_driver_remove,
.suspend = dwc2_suspend,
.resume = dwc2_resume,
}; };
module_platform_driver(dwc2_platform_driver); module_platform_driver(dwc2_platform_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment