uboot/drivers/usb/host/ehci-atmel.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2012
   4 * Atmel Semiconductor <www.atmel.com>
   5 * Written-by: Bo Shen <voice.shen@atmel.com>
   6 */
   7
   8#include <common.h>
   9#include <clk.h>
  10#include <dm.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <usb.h>
  14#include <asm/io.h>
  15#include <asm/arch/clk.h>
  16
  17#include "ehci.h"
  18
  19#if !CONFIG_IS_ENABLED(DM_USB)
  20
  21int ehci_hcd_init(int index, enum usb_init_type init,
  22                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
  23{
  24        /* Enable UTMI PLL */
  25        if (at91_upll_clk_enable())
  26                return -1;
  27
  28        /* Enable USB Host clock */
  29        at91_periph_clk_enable(ATMEL_ID_UHPHS);
  30
  31        *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
  32        *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
  33                        HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
  34
  35        return 0;
  36}
  37
  38int ehci_hcd_stop(int index)
  39{
  40        /* Disable USB Host Clock */
  41        at91_periph_clk_disable(ATMEL_ID_UHPHS);
  42
  43        /* Disable UTMI PLL */
  44        if (at91_upll_clk_disable())
  45                return -1;
  46
  47        return 0;
  48}
  49
  50#else
  51
  52struct ehci_atmel_priv {
  53        struct ehci_ctrl ehci;
  54};
  55
  56static int ehci_atmel_enable_clk(struct udevice *dev)
  57{
  58        struct clk clk;
  59        int ret;
  60
  61        ret = clk_get_by_index(dev, 0, &clk);
  62        if (ret)
  63                return ret;
  64
  65        ret = clk_enable(&clk);
  66        if (ret)
  67                return ret;
  68
  69        ret = clk_get_by_index(dev, 1, &clk);
  70        if (ret)
  71                return -EINVAL;
  72
  73        ret = clk_enable(&clk);
  74        if (ret)
  75                return ret;
  76
  77        clk_free(&clk);
  78
  79        return 0;
  80}
  81
  82static int ehci_atmel_probe(struct udevice *dev)
  83{
  84        struct ehci_hccr *hccr;
  85        struct ehci_hcor *hcor;
  86        fdt_addr_t hcd_base;
  87        int ret;
  88
  89        ret = ehci_atmel_enable_clk(dev);
  90        if (ret) {
  91                debug("Failed to enable USB Host clock\n");
  92                return ret;
  93        }
  94
  95        /*
  96         * Get the base address for EHCI controller from the device node
  97         */
  98        hcd_base = dev_read_addr(dev);
  99        if (hcd_base == FDT_ADDR_T_NONE) {
 100                debug("Can't get the EHCI register base address\n");
 101                return -ENXIO;
 102        }
 103
 104        hccr = (struct ehci_hccr *)hcd_base;
 105        hcor = (struct ehci_hcor *)
 106                ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 107
 108        debug("echi-atmel: init hccr %x and hcor %x hc_length %d\n",
 109              (u32)hccr, (u32)hcor,
 110              (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 111
 112        return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
 113}
 114
 115static const struct udevice_id ehci_usb_ids[] = {
 116        { .compatible = "atmel,at91sam9g45-ehci", },
 117        { }
 118};
 119
 120U_BOOT_DRIVER(ehci_atmel) = {
 121        .name           = "ehci_atmel",
 122        .id             = UCLASS_USB,
 123        .of_match       = ehci_usb_ids,
 124        .probe          = ehci_atmel_probe,
 125        .remove         = ehci_deregister,
 126        .ops            = &ehci_usb_ops,
 127        .plat_auto      = sizeof(struct usb_plat),
 128        .priv_auto      = sizeof(struct ehci_atmel_priv),
 129        .flags          = DM_FLAG_ALLOC_PRIV_DMA,
 130};
 131
 132#endif
 133