Release 4.11 drivers/usb/host/ehci-atmel.c
/*
* Driver for EHCI UHP on Atmel chips
*
* Copyright (C) 2009 Atmel Corporation,
* Nicolas Ferre <nicolas.ferre@atmel.com>
*
* Based on various ehci-*.c drivers
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include "ehci.h"
#define DRIVER_DESC "EHCI Atmel driver"
static const char hcd_name[] = "ehci-atmel";
/* interface and function clocks */
#define hcd_to_atmel_ehci_priv(h) \
((struct atmel_ehci_priv *)hcd_to_ehci(h)->priv)
struct atmel_ehci_priv {
struct clk *iclk;
struct clk *uclk;
bool clocked;
};
static struct hc_driver __read_mostly ehci_atmel_hc_driver;
static const struct ehci_driver_overrides ehci_atmel_drv_overrides __initconst = {
.extra_priv_size = sizeof(struct atmel_ehci_priv),
};
/*-------------------------------------------------------------------------*/
static void atmel_start_clock(struct atmel_ehci_priv *atmel_ehci)
{
if (atmel_ehci->clocked)
return;
clk_prepare_enable(atmel_ehci->uclk);
clk_prepare_enable(atmel_ehci->iclk);
atmel_ehci->clocked = true;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sylvain Rochet | 16 | 42.11% | 2 | 40.00% |
Nicolas Ferre | 14 | 36.84% | 1 | 20.00% |
Boris Brezillon | 8 | 21.05% | 2 | 40.00% |
Total | 38 | 100.00% | 5 | 100.00% |
static void atmel_stop_clock(struct atmel_ehci_priv *atmel_ehci)
{
if (!atmel_ehci->clocked)
return;
clk_disable_unprepare(atmel_ehci->iclk);
clk_disable_unprepare(atmel_ehci->uclk);
atmel_ehci->clocked = false;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sylvain Rochet | 19 | 48.72% | 2 | 40.00% |
Nicolas Ferre | 14 | 35.90% | 1 | 20.00% |
Boris Brezillon | 6 | 15.38% | 2 | 40.00% |
Total | 39 | 100.00% | 5 | 100.00% |
static void atmel_start_ehci(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
dev_dbg(&pdev->dev, "start\n");
atmel_start_clock(atmel_ehci);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Nicolas Ferre | 23 | 50.00% | 1 | 50.00% |
Sylvain Rochet | 23 | 50.00% | 1 | 50.00% |
Total | 46 | 100.00% | 2 | 100.00% |
static void atmel_stop_ehci(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
dev_dbg(&pdev->dev, "stop\n");
atmel_stop_clock(atmel_ehci);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sylvain Rochet | 23 | 50.00% | 1 | 50.00% |
Nicolas Ferre | 23 | 50.00% | 1 | 50.00% |
Total | 46 | 100.00% | 2 | 100.00% |
/*-------------------------------------------------------------------------*/
static int ehci_atmel_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
const struct hc_driver *driver = &ehci_atmel_hc_driver;
struct resource *res;
struct ehci_hcd *ehci;
struct atmel_ehci_priv *atmel_ehci;
int irq;
int retval;
if (usb_disabled())
return -ENODEV;
pr_debug("Initializing Atmel-SoC USB Host Controller\n");
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
dev_name(&pdev->dev));
retval = -ENODEV;
goto fail_create_hcd;
}
/* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
* Once we have dma capability bindings this can go away.
*/
retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (retval)
goto fail_create_hcd;
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
goto fail_create_hcd;
}
atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hcd->regs)) {
retval = PTR_ERR(hcd->regs);
goto fail_request_resource;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
atmel_ehci->iclk = devm_clk_get(&pdev->dev, "ehci_clk");
if (IS_ERR(atmel_ehci->iclk)) {
dev_err(&pdev->dev, "Error getting interface clock\n");
retval = -ENOENT;
goto fail_request_resource;
}
atmel_ehci->uclk = devm_clk_get(&pdev->dev, "usb_clk");
if (IS_ERR(atmel_ehci->uclk)) {
dev_err(&pdev->dev, "failed to get uclk\n");
retval = PTR_ERR(atmel_ehci->uclk);
goto fail_request_resource;
}
ehci = hcd_to_ehci(hcd);
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
atmel_start_ehci(pdev);
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
goto fail_add_hcd;
device_wakeup_enable(hcd->self.controller);
return retval;
fail_add_hcd:
atmel_stop_ehci(pdev);
fail_request_resource:
usb_put_hcd(hcd);
fail_create_hcd:
dev_err(&pdev->dev, "init %s fail, %d\n",
dev_name(&pdev->dev), retval);
return retval;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Nicolas Ferre | 265 | 64.16% | 1 | 8.33% |
Boris Brezillon | 41 | 9.93% | 1 | 8.33% |
Sylvain Rochet | 22 | 5.33% | 1 | 8.33% |
Manjunath Goudar | 21 | 5.08% | 1 | 8.33% |
Varka Bhadram | 17 | 4.12% | 1 | 8.33% |
Russell King | 12 | 2.91% | 2 | 16.67% |
Thierry Reding | 9 | 2.18% | 1 | 8.33% |
Peter Chen | 9 | 2.18% | 1 | 8.33% |
Stephen Warren | 7 | 1.69% | 1 | 8.33% |
Julia Lawall | 6 | 1.45% | 1 | 8.33% |
Jean-Christophe Plagniol-Villard | 4 | 0.97% | 1 | 8.33% |
Total | 413 | 100.00% | 12 | 100.00% |
static int ehci_atmel_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
atmel_stop_ehci(pdev);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Nicolas Ferre | 39 | 100.00% | 1 | 100.00% |
Total | 39 | 100.00% | 1 | 100.00% |
static int __maybe_unused ehci_atmel_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
int ret;
ret = ehci_suspend(hcd, false);
if (ret)
return ret;
atmel_stop_clock(atmel_ehci);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sylvain Rochet | 58 | 98.31% | 2 | 66.67% |
Arnd Bergmann | 1 | 1.69% | 1 | 33.33% |
Total | 59 | 100.00% | 3 | 100.00% |
static int __maybe_unused ehci_atmel_drv_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd);
atmel_start_clock(atmel_ehci);
return ehci_resume(hcd, false);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sylvain Rochet | 44 | 97.78% | 2 | 66.67% |
Arnd Bergmann | 1 | 2.22% | 1 | 33.33% |
Total | 45 | 100.00% | 3 | 100.00% |
#ifdef CONFIG_OF
static const struct of_device_id atmel_ehci_dt_ids[] = {
{ .compatible = "atmel,at91sam9g45-ehci" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
#endif
static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend,
ehci_atmel_drv_resume);
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
.remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "atmel-ehci",
.pm = &ehci_atmel_pm_ops,
.of_match_table = of_match_ptr(atmel_ehci_dt_ids),
},
};
static int __init ehci_atmel_init(void)
{
if (usb_disabled())
return -ENODEV;
pr_info("%s: " DRIVER_DESC "\n", hcd_name);
ehci_init_driver(&ehci_atmel_hc_driver, &ehci_atmel_drv_overrides);
return platform_driver_register(&ehci_atmel_driver);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Manjunath Goudar | 41 | 95.35% | 1 | 50.00% |
Sylvain Rochet | 2 | 4.65% | 1 | 50.00% |
Total | 43 | 100.00% | 2 | 100.00% |
module_init(ehci_atmel_init);
static void __exit ehci_atmel_cleanup(void)
{
platform_driver_unregister(&ehci_atmel_driver);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Manjunath Goudar | 15 | 100.00% | 1 | 100.00% |
Total | 15 | 100.00% | 1 | 100.00% |
module_exit(ehci_atmel_cleanup);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:atmel-ehci");
MODULE_AUTHOR("Nicolas Ferre");
MODULE_LICENSE("GPL");
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Nicolas Ferre | 426 | 42.60% | 2 | 12.50% |
Sylvain Rochet | 266 | 26.60% | 2 | 12.50% |
Manjunath Goudar | 141 | 14.10% | 1 | 6.25% |
Boris Brezillon | 57 | 5.70% | 2 | 12.50% |
Jean-Christophe Plagniol-Villard | 48 | 4.80% | 1 | 6.25% |
Varka Bhadram | 17 | 1.70% | 1 | 6.25% |
Russell King | 12 | 1.20% | 2 | 12.50% |
Peter Chen | 9 | 0.90% | 1 | 6.25% |
Thierry Reding | 9 | 0.90% | 1 | 6.25% |
Stephen Warren | 7 | 0.70% | 1 | 6.25% |
Julia Lawall | 6 | 0.60% | 1 | 6.25% |
Arnd Bergmann | 2 | 0.20% | 1 | 6.25% |
Total | 1000 | 100.00% | 16 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.