xref: /rk3399_rockchip-uboot/drivers/usb/host/ehci-mxc.c (revision f55feafdee3e73863b80d0d4107382daffd9afe3)
15b591502SStefano Babic /*
25b591502SStefano Babic  * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
35b591502SStefano Babic  *
45b591502SStefano Babic  * This program is free software; you can redistribute it and/or modify it
55b591502SStefano Babic  * under the terms of the GNU General Public License as published by the
65b591502SStefano Babic  * Free Software Foundation; either version 2 of the License, or (at your
75b591502SStefano Babic  * option) any later version.
85b591502SStefano Babic  *
95b591502SStefano Babic  * This program is distributed in the hope that it will be useful, but
105b591502SStefano Babic  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
115b591502SStefano Babic  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
125b591502SStefano Babic  * for more details.
135b591502SStefano Babic  *
145b591502SStefano Babic  * You should have received a copy of the GNU General Public License
155b591502SStefano Babic  * along with this program; if not, write to the Free Software Foundation,
165b591502SStefano Babic  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
175b591502SStefano Babic  */
185b591502SStefano Babic 
195b591502SStefano Babic 
205b591502SStefano Babic #include <common.h>
215b591502SStefano Babic #include <usb.h>
225b591502SStefano Babic #include <asm/io.h>
2386271115SStefano Babic #include <asm/arch/imx-regs.h>
245b591502SStefano Babic #include <usb/ehci-fsl.h>
255b591502SStefano Babic #include <errno.h>
265b591502SStefano Babic 
275b591502SStefano Babic #include "ehci.h"
285b591502SStefano Babic #include "ehci-core.h"
295b591502SStefano Babic 
305b591502SStefano Babic #define USBCTRL_OTGBASE_OFFSET	0x600
315b591502SStefano Babic 
32dddb7c9fSMatthias Weisser #ifdef CONFIG_MX25
33dddb7c9fSMatthias Weisser #define MX25_USB_CTRL_IP_PUE_DOWN_BIT	(1<<6)
34dddb7c9fSMatthias Weisser #define MX25_USB_CTRL_HSTD_BIT		(1<<5)
35dddb7c9fSMatthias Weisser #define MX25_USB_CTRL_USBTE_BIT		(1<<4)
36dddb7c9fSMatthias Weisser #define MX25_USB_CTRL_OCPOL_OTG_BIT	(1<<3)
37dddb7c9fSMatthias Weisser #endif
38dddb7c9fSMatthias Weisser 
39dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31
405b591502SStefano Babic #define MX31_OTG_SIC_SHIFT	29
415b591502SStefano Babic #define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
425b591502SStefano Babic #define MX31_OTG_PM_BIT		(1 << 24)
435b591502SStefano Babic 
445b591502SStefano Babic #define MX31_H2_SIC_SHIFT	21
455b591502SStefano Babic #define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
465b591502SStefano Babic #define MX31_H2_PM_BIT		(1 << 16)
475b591502SStefano Babic #define MX31_H2_DT_BIT		(1 << 5)
485b591502SStefano Babic 
495b591502SStefano Babic #define MX31_H1_SIC_SHIFT	13
505b591502SStefano Babic #define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
515b591502SStefano Babic #define MX31_H1_PM_BIT		(1 << 8)
525b591502SStefano Babic #define MX31_H1_DT_BIT		(1 << 4)
53dddb7c9fSMatthias Weisser #endif
545b591502SStefano Babic 
555b591502SStefano Babic static int mxc_set_usbcontrol(int port, unsigned int flags)
565b591502SStefano Babic {
575b591502SStefano Babic 	unsigned int v;
58dddb7c9fSMatthias Weisser 
59dddb7c9fSMatthias Weisser #ifdef CONFIG_MX25
60dddb7c9fSMatthias Weisser 	v = MX25_USB_CTRL_IP_PUE_DOWN_BIT | MX25_USB_CTRL_HSTD_BIT |
61dddb7c9fSMatthias Weisser 		MX25_USB_CTRL_USBTE_BIT | MX25_USB_CTRL_OCPOL_OTG_BIT;
62dddb7c9fSMatthias Weisser #endif
63dddb7c9fSMatthias Weisser 
645b591502SStefano Babic #ifdef CONFIG_MX31
65dddb7c9fSMatthias Weisser 		v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET);
665b591502SStefano Babic 
675b591502SStefano Babic 		switch (port) {
685b591502SStefano Babic 		case 0:	/* OTG port */
695b591502SStefano Babic 			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
705b591502SStefano Babic 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
715b591502SStefano Babic 					<< MX31_OTG_SIC_SHIFT;
725b591502SStefano Babic 			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
735b591502SStefano Babic 				v |= MX31_OTG_PM_BIT;
745b591502SStefano Babic 
755b591502SStefano Babic 			break;
765b591502SStefano Babic 		case 1: /* H1 port */
775b591502SStefano Babic 			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT |
785b591502SStefano Babic 				MX31_H1_DT_BIT);
795b591502SStefano Babic 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
805b591502SStefano Babic 						<< MX31_H1_SIC_SHIFT;
815b591502SStefano Babic 			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
825b591502SStefano Babic 				v |= MX31_H1_PM_BIT;
835b591502SStefano Babic 
845b591502SStefano Babic 			if (!(flags & MXC_EHCI_TTL_ENABLED))
855b591502SStefano Babic 				v |= MX31_H1_DT_BIT;
865b591502SStefano Babic 
875b591502SStefano Babic 			break;
885b591502SStefano Babic 		case 2:	/* H2 port */
895b591502SStefano Babic 			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT |
905b591502SStefano Babic 				MX31_H2_DT_BIT);
915b591502SStefano Babic 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
925b591502SStefano Babic 						<< MX31_H2_SIC_SHIFT;
935b591502SStefano Babic 			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
945b591502SStefano Babic 				v |= MX31_H2_PM_BIT;
955b591502SStefano Babic 
965b591502SStefano Babic 			if (!(flags & MXC_EHCI_TTL_ENABLED))
975b591502SStefano Babic 				v |= MX31_H2_DT_BIT;
985b591502SStefano Babic 
995b591502SStefano Babic 			break;
1005b591502SStefano Babic 		default:
1015b591502SStefano Babic 			return -EINVAL;
1025b591502SStefano Babic 		}
1035b591502SStefano Babic #endif
104dddb7c9fSMatthias Weisser 
105dddb7c9fSMatthias Weisser 	writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET);
1065b591502SStefano Babic 	return 0;
1075b591502SStefano Babic }
1085b591502SStefano Babic 
1095b591502SStefano Babic int ehci_hcd_init(void)
1105b591502SStefano Babic {
1115b591502SStefano Babic 	struct usb_ehci *ehci;
112dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31
1135b591502SStefano Babic 	struct clock_control_regs *sc_regs =
1145b591502SStefano Babic 		(struct clock_control_regs *)CCM_BASE;
1155b591502SStefano Babic 
116*f55feafdSAnatolij Gustschin 	__raw_readl(&sc_regs->ccmr);
1175b591502SStefano Babic 	__raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ;
118dddb7c9fSMatthias Weisser #endif
1195b591502SStefano Babic 
1205b591502SStefano Babic 	udelay(80);
1215b591502SStefano Babic 
122dddb7c9fSMatthias Weisser 	ehci = (struct usb_ehci *)(IMX_USB_BASE +
1235b591502SStefano Babic 		(0x200 * CONFIG_MXC_USB_PORT));
1245b591502SStefano Babic 	hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
1255b591502SStefano Babic 	hcor = (struct ehci_hcor *)((uint32_t) hccr +
1265b591502SStefano Babic 			HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
1275b591502SStefano Babic 	setbits_le32(&ehci->usbmode, CM_HOST);
128dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31
1295b591502SStefano Babic 	setbits_le32(&ehci->control, USB_EN);
1305b591502SStefano Babic 
1315b591502SStefano Babic 	__raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
132dddb7c9fSMatthias Weisser #endif
1335b591502SStefano Babic 	mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS);
1345b591502SStefano Babic 
135a2f9bff9SStefano Babic 	udelay(10000);
136a2f9bff9SStefano Babic 
1375b591502SStefano Babic 	return 0;
1385b591502SStefano Babic }
1395b591502SStefano Babic 
1405b591502SStefano Babic /*
1415b591502SStefano Babic  * Destroy the appropriate control structures corresponding
1425b591502SStefano Babic  * the the EHCI host controller.
1435b591502SStefano Babic  */
1445b591502SStefano Babic int ehci_hcd_stop(void)
1455b591502SStefano Babic {
1465b591502SStefano Babic 	return 0;
1475b591502SStefano Babic }
148