]>
Commit | Line | Data |
---|---|---|
ede4d5e3 NI |
1 | /* |
2 | * EHCI HCD (Host Controller Driver) for USB. | |
3 | * | |
4 | * Copyright (C) 2013,2014 Renesas Electronics Corporation | |
5 | * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0 | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
11 | #include <asm/io.h> | |
12 | #include <asm/arch/ehci-rmobile.h> | |
13 | #include "ehci.h" | |
14 | ||
15 | #if defined(CONFIG_R8A7740) | |
865ed5ea | 16 | static u32 usb_base_address[] = { |
ede4d5e3 NI |
17 | 0xC6700000 |
18 | }; | |
19 | #elif defined(CONFIG_R8A7790) | |
865ed5ea | 20 | static u32 usb_base_address[] = { |
ede4d5e3 NI |
21 | 0xEE080000, /* USB0 (EHCI) */ |
22 | 0xEE0A0000, /* USB1 */ | |
23 | 0xEE0C0000, /* USB2 */ | |
ede4d5e3 | 24 | }; |
4dc94926 NI |
25 | #elif defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \ |
26 | defined(CONFIG_R8A7794) | |
865ed5ea | 27 | static u32 usb_base_address[] = { |
ed7ce836 NI |
28 | 0xEE080000, /* USB0 (EHCI) */ |
29 | 0xEE0C0000, /* USB1 */ | |
ed7ce836 | 30 | }; |
ede4d5e3 NI |
31 | #else |
32 | #error rmobile EHCI USB driver not supported on this platform | |
33 | #endif | |
34 | ||
35 | int ehci_hcd_stop(int index) | |
36 | { | |
37 | int i; | |
38 | u32 base; | |
39 | struct ahbcom_pci_bridge *ahbcom_pci; | |
40 | ||
41 | base = usb_base_address[index]; | |
42 | ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); | |
43 | writel(0, &ahbcom_pci->ahb_bus_ctr); | |
44 | ||
45 | /* reset ehci */ | |
46 | setbits_le32(base + EHCI_USBCMD, CMD_RESET); | |
47 | for (i = 100; i > 0; i--) { | |
48 | if (!(readl(base + EHCI_USBCMD) & CMD_RESET)) | |
49 | break; | |
50 | udelay(100); | |
51 | } | |
52 | ||
53 | if (!i) | |
54 | printf("error : ehci(%d) reset failed.\n", index); | |
55 | ||
865ed5ea | 56 | if (index == (ARRAY_SIZE(usb_base_address) - 1)) |
ede4d5e3 NI |
57 | setbits_le32(SMSTPCR7, SMSTPCR703); |
58 | ||
59 | return 0; | |
60 | } | |
61 | ||
62 | int ehci_hcd_init(int index, enum usb_init_type init, | |
63 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | |
64 | { | |
65 | u32 base; | |
66 | u32 phys_base; | |
67 | struct rmobile_ehci_reg *rehci; | |
68 | struct ahbcom_pci_bridge *ahbcom_pci; | |
69 | struct ahbconf_pci_bridge *ahbconf_pci; | |
70 | struct ahb_pciconf *ahb_pciconf_ohci; | |
71 | struct ahb_pciconf *ahb_pciconf_ehci; | |
72 | uint32_t cap_base; | |
73 | ||
74 | base = usb_base_address[index]; | |
75 | phys_base = base; | |
76 | if (index == 0) | |
77 | clrbits_le32(SMSTPCR7, SMSTPCR703); | |
78 | ||
79 | rehci = (struct rmobile_ehci_reg *)(base + EHCI_OFFSET); | |
80 | ahbcom_pci = (struct ahbcom_pci_bridge *)(base + AHBPCI_OFFSET); | |
81 | ahbconf_pci = | |
82 | (struct ahbconf_pci_bridge *)(base + PCI_CONF_AHBPCI_OFFSET); | |
83 | ahb_pciconf_ohci = (struct ahb_pciconf *)(base + PCI_CONF_OHCI_OFFSET); | |
84 | ahb_pciconf_ehci = (struct ahb_pciconf *)(base + PCI_CONF_EHCI_OFFSET); | |
85 | ||
86 | /* Clock & Reset & Direct Power Down */ | |
87 | clrsetbits_le32(&ahbcom_pci->usbctr, | |
88 | (DIRPD | PCICLK_MASK | USBH_RST), USBCTR_WIN_SIZE_1GB); | |
89 | clrbits_le32(&ahbcom_pci->usbctr, PLL_RST); | |
90 | ||
91 | /* AHB-PCI Bridge Communication Registers */ | |
92 | writel(AHB_BUS_CTR_INIT, &ahbcom_pci->ahb_bus_ctr); | |
93 | writel((CONFIG_SYS_SDRAM_BASE & 0xf0000000) | PCIAHB_WIN_PREFETCH, | |
94 | &ahbcom_pci->pciahb_win1_ctr); | |
95 | writel(0xf0000000 | PCIAHB_WIN_PREFETCH, | |
96 | &ahbcom_pci->pciahb_win2_ctr); | |
97 | writel(phys_base | PCIWIN2_PCICMD, &ahbcom_pci->ahbpci_win2_ctr); | |
98 | ||
99 | setbits_le32(&ahbcom_pci->pci_arbiter_ctr, | |
100 | PCIBP_MODE | PCIREQ1 | PCIREQ0); | |
101 | ||
102 | /* PCI Configuration Registers for AHBPCI */ | |
103 | writel(PCIWIN1_PCICMD | AHB_CFG_AHBPCI, | |
104 | &ahbcom_pci->ahbpci_win1_ctr); | |
105 | writel(phys_base + AHBPCI_OFFSET, &ahbconf_pci->basead); | |
106 | writel(CONFIG_SYS_SDRAM_BASE & 0xf0000000, &ahbconf_pci->win1_basead); | |
107 | writel(0xf0000000, &ahbconf_pci->win2_basead); | |
108 | writel(SERREN | PERREN | MASTEREN | MEMEN, | |
109 | &ahbconf_pci->cmnd_sts); | |
110 | ||
111 | /* PCI Configuration Registers for EHCI */ | |
112 | writel(PCIWIN1_PCICMD | AHB_CFG_HOST, &ahbcom_pci->ahbpci_win1_ctr); | |
113 | writel(phys_base + OHCI_OFFSET, &ahb_pciconf_ohci->basead); | |
114 | writel(phys_base + EHCI_OFFSET, &ahb_pciconf_ehci->basead); | |
115 | writel(SERREN | PERREN | MASTEREN | MEMEN, | |
116 | &ahb_pciconf_ohci->cmnd_sts); | |
117 | writel(SERREN | PERREN | MASTEREN | MEMEN, | |
118 | &ahb_pciconf_ehci->cmnd_sts); | |
119 | ||
120 | /* Enable PCI interrupt */ | |
121 | setbits_le32(&ahbcom_pci->pci_int_enable, | |
122 | USBH_PMEEN | USBH_INTBEN | USBH_INTAEN); | |
123 | ||
124 | *hccr = (struct ehci_hccr *)((uint32_t)&rehci->hciversion); | |
125 | cap_base = ehci_readl(&(*hccr)->cr_capbase); | |
126 | *hcor = (struct ehci_hcor *)((uint32_t)*hccr + HC_LENGTH(cap_base)); | |
127 | ||
128 | return 0; | |
129 | } |