blob: 9a8f004ecebc99fbcf6278ba6d2b716484ebb00c [file] [log] [blame]
Bo Shencc30b782012-06-27 21:58:20 +00001/*
2 * (C) Copyright 2012
3 * Atmel Semiconductor <www.atmel.com>
4 * Written-by: Bo Shen <voice.shen@atmel.com>
5 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
Bo Shencc30b782012-06-27 21:58:20 +00007 */
8
9#include <common.h>
10#include <watchdog.h>
11#include <usb.h>
12#include <asm/io.h>
13#include <asm/arch/hardware.h>
14#include <asm/arch/at91_pmc.h>
15#include <asm/arch/clk.h>
16
17#include "ehci.h"
Bo Shencc30b782012-06-27 21:58:20 +000018
19/* Enable UTMI PLL time out 500us
20 * 10 times as datasheet specified
21 */
22#define EN_UPLL_TIMEOUT 500UL
23
Troy Kisky127efc42013-10-10 15:27:57 -070024int ehci_hcd_init(int index, enum usb_init_type init,
25 struct ehci_hccr **hccr, struct ehci_hcor **hcor)
Bo Shencc30b782012-06-27 21:58:20 +000026{
27 at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
28 ulong start_time, tmp_time;
29
30 start_time = get_timer(0);
31 /* Enable UTMI PLL */
32 writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
Andreas Bießmann81f40342012-06-28 02:50:37 +000033 while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) {
Bo Shencc30b782012-06-27 21:58:20 +000034 WATCHDOG_RESET();
35 tmp_time = get_timer(0);
36 if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
37 printf("ERROR: failed to enable UPLL\n");
38 return -1;
39 }
40 }
41
42 /* Enable USB Host clock */
Bo Shen97b20432014-08-06 17:24:57 +080043#ifdef CPU_HAS_PCR
44 at91_periph_clk_enable(ATMEL_ID_UHPHS);
45#else
Bo Shencc30b782012-06-27 21:58:20 +000046 writel(1 << ATMEL_ID_UHPHS, &pmc->pcer);
Bo Shen97b20432014-08-06 17:24:57 +080047#endif
Bo Shencc30b782012-06-27 21:58:20 +000048
Lucas Stach676ae062012-09-26 00:14:35 +020049 *hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
50 *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
51 HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
Bo Shencc30b782012-06-27 21:58:20 +000052
53 return 0;
54}
55
Lucas Stach676ae062012-09-26 00:14:35 +020056int ehci_hcd_stop(int index)
Bo Shencc30b782012-06-27 21:58:20 +000057{
58 at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
59 ulong start_time, tmp_time;
60
61 /* Disable USB Host Clock */
Bo Shen97b20432014-08-06 17:24:57 +080062#ifdef CPU_HAS_PCR
63 at91_periph_clk_disable(ATMEL_ID_UHPHS);
64#else
Bo Shencc30b782012-06-27 21:58:20 +000065 writel(1 << ATMEL_ID_UHPHS, &pmc->pcdr);
Bo Shen97b20432014-08-06 17:24:57 +080066#endif
Bo Shencc30b782012-06-27 21:58:20 +000067
68 start_time = get_timer(0);
69 /* Disable UTMI PLL */
70 writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr);
Andreas Bießmann81f40342012-06-28 02:50:37 +000071 while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) {
Bo Shencc30b782012-06-27 21:58:20 +000072 WATCHDOG_RESET();
73 tmp_time = get_timer(0);
74 if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
75 printf("ERROR: failed to stop UPLL\n");
76 return -1;
77 }
78 }
79
80 return 0;
81}