xref: /rk3399_rockchip-uboot/drivers/usb/host/ohci-lpc32xx.c (revision b491b49882fc71838b46c47a860daf2978c80be4)
1adf8d58dSSylvain Lemieux /*
2adf8d58dSSylvain Lemieux  * Copyright (C) 2008 by NXP Semiconductors
3adf8d58dSSylvain Lemieux  * @Author: Based on code by Kevin Wells
4adf8d58dSSylvain Lemieux  * @Descr: USB driver - Embedded Artists LPC3250 OEM Board support functions
5adf8d58dSSylvain Lemieux  *
6adf8d58dSSylvain Lemieux  * Copyright (c) 2015 Tyco Fire Protection Products.
7adf8d58dSSylvain Lemieux  *
8adf8d58dSSylvain Lemieux  * SPDX-License-Identifier:	GPL-2.0+
9adf8d58dSSylvain Lemieux  */
10adf8d58dSSylvain Lemieux 
11adf8d58dSSylvain Lemieux #include <common.h>
129ad69f0bSLiam Beguin #include <dm.h>
13adf8d58dSSylvain Lemieux #include <errno.h>
148d5c7bb2SMateusz Kulikowski #include <wait_bit.h>
15adf8d58dSSylvain Lemieux #include <asm/io.h>
16adf8d58dSSylvain Lemieux #include <asm/arch/cpu.h>
17adf8d58dSSylvain Lemieux #include <asm/arch/clk.h>
189ad69f0bSLiam Beguin #include <asm/arch/i2c.h>
19adf8d58dSSylvain Lemieux #include <usb.h>
20adf8d58dSSylvain Lemieux #include <i2c.h>
21adf8d58dSSylvain Lemieux 
22adf8d58dSSylvain Lemieux /* OTG I2C controller module register structures */
23adf8d58dSSylvain Lemieux struct otgi2c_regs {
24adf8d58dSSylvain Lemieux 	u32 otg_i2c_txrx;   /* OTG I2C Tx/Rx Data FIFO */
25adf8d58dSSylvain Lemieux 	u32 otg_i2c_stat;   /* OTG I2C Status Register */
26adf8d58dSSylvain Lemieux 	u32 otg_i2c_ctrl;   /* OTG I2C Control Register */
27adf8d58dSSylvain Lemieux 	u32 otg_i2c_clk_hi; /* OTG I2C Clock Divider high */
28adf8d58dSSylvain Lemieux 	u32 otg_i2c_clk_lo; /* OTG I2C Clock Divider low */
29adf8d58dSSylvain Lemieux };
30adf8d58dSSylvain Lemieux 
31adf8d58dSSylvain Lemieux /* OTG controller module register structures */
32adf8d58dSSylvain Lemieux struct otg_regs {
33adf8d58dSSylvain Lemieux 	u32 reserved1[64];
34adf8d58dSSylvain Lemieux 	u32 otg_int_sts;    /* OTG int status register */
35adf8d58dSSylvain Lemieux 	u32 otg_int_enab;   /* OTG int enable register */
36adf8d58dSSylvain Lemieux 	u32 otg_int_set;    /* OTG int set register */
37adf8d58dSSylvain Lemieux 	u32 otg_int_clr;    /* OTG int clear register */
38adf8d58dSSylvain Lemieux 	u32 otg_sts_ctrl;   /* OTG status/control register */
39adf8d58dSSylvain Lemieux 	u32 otg_timer;      /* OTG timer register */
40adf8d58dSSylvain Lemieux 	u32 reserved2[122];
41adf8d58dSSylvain Lemieux 	struct otgi2c_regs otg_i2c;
42adf8d58dSSylvain Lemieux 	u32 reserved3[824];
43adf8d58dSSylvain Lemieux 	u32 otg_clk_ctrl;   /* OTG clock control reg */
44adf8d58dSSylvain Lemieux 	u32 otg_clk_sts;    /* OTG clock status reg */
45adf8d58dSSylvain Lemieux };
46adf8d58dSSylvain Lemieux 
47adf8d58dSSylvain Lemieux /* otg_sts_ctrl register definitions */
48adf8d58dSSylvain Lemieux #define OTG_HOST_EN			(1 << 0) /* Enable host mode */
49adf8d58dSSylvain Lemieux 
50adf8d58dSSylvain Lemieux /* otg_clk_ctrl and otg_clk_sts register definitions */
51adf8d58dSSylvain Lemieux #define OTG_CLK_AHB_EN			(1 << 4) /* Enable AHB clock */
52adf8d58dSSylvain Lemieux #define OTG_CLK_OTG_EN			(1 << 3) /* Enable OTG clock */
53adf8d58dSSylvain Lemieux #define OTG_CLK_I2C_EN			(1 << 2) /* Enable I2C clock */
54adf8d58dSSylvain Lemieux #define OTG_CLK_HOST_EN			(1 << 0) /* Enable host clock */
55adf8d58dSSylvain Lemieux 
56adf8d58dSSylvain Lemieux /* ISP1301 USB transceiver I2C registers */
57adf8d58dSSylvain Lemieux #define MC1_SPEED_REG			(1 << 0)
58adf8d58dSSylvain Lemieux #define MC1_DAT_SE0			(1 << 2)
59adf8d58dSSylvain Lemieux #define MC1_UART_EN			(1 << 6)
60adf8d58dSSylvain Lemieux 
61adf8d58dSSylvain Lemieux #define MC2_SPD_SUSP_CTRL		(1 << 1)
62adf8d58dSSylvain Lemieux #define MC2_BI_DI			(1 << 2)
63adf8d58dSSylvain Lemieux #define MC2_PSW_EN			(1 << 6)
64adf8d58dSSylvain Lemieux 
65adf8d58dSSylvain Lemieux #define OTG1_DP_PULLUP			(1 << 0)
66adf8d58dSSylvain Lemieux #define OTG1_DM_PULLUP			(1 << 1)
67adf8d58dSSylvain Lemieux #define OTG1_DP_PULLDOWN		(1 << 2)
68adf8d58dSSylvain Lemieux #define OTG1_DM_PULLDOWN		(1 << 3)
69adf8d58dSSylvain Lemieux #define OTG1_VBUS_DRV			(1 << 5)
70adf8d58dSSylvain Lemieux 
71adf8d58dSSylvain Lemieux #define ISP1301_I2C_ADDR		CONFIG_USB_ISP1301_I2C_ADDR
72adf8d58dSSylvain Lemieux 
73adf8d58dSSylvain Lemieux #define ISP1301_I2C_MODE_CONTROL_1_SET		0x04
74adf8d58dSSylvain Lemieux #define ISP1301_I2C_MODE_CONTROL_1_CLR		0x05
75adf8d58dSSylvain Lemieux #define ISP1301_I2C_MODE_CONTROL_2_SET		0x12
76adf8d58dSSylvain Lemieux #define ISP1301_I2C_MODE_CONTROL_2_CLR		0x13
77adf8d58dSSylvain Lemieux #define ISP1301_I2C_OTG_CONTROL_1_SET		0x06
78adf8d58dSSylvain Lemieux #define ISP1301_I2C_OTG_CONTROL_1_CLR		0x07
79adf8d58dSSylvain Lemieux #define ISP1301_I2C_INTERRUPT_LATCH_CLR		0x0B
80adf8d58dSSylvain Lemieux #define ISP1301_I2C_INTERRUPT_FALLING_CLR	0x0D
81adf8d58dSSylvain Lemieux #define ISP1301_I2C_INTERRUPT_RISING_CLR	0x0F
82adf8d58dSSylvain Lemieux 
83adf8d58dSSylvain Lemieux static struct otg_regs *otg = (struct otg_regs *)USB_BASE;
84adf8d58dSSylvain Lemieux static struct clk_pm_regs *clk_pwr = (struct clk_pm_regs *)CLK_PM_BASE;
85adf8d58dSSylvain Lemieux 
isp1301_set_value(struct udevice * dev,int reg,u8 value)869ad69f0bSLiam Beguin static int isp1301_set_value(struct udevice *dev, int reg, u8 value)
87adf8d58dSSylvain Lemieux {
889ad69f0bSLiam Beguin #ifndef CONFIG_DM_I2C
89adf8d58dSSylvain Lemieux 	return i2c_write(ISP1301_I2C_ADDR, reg, 1, &value, 1);
909ad69f0bSLiam Beguin #else
919ad69f0bSLiam Beguin 	return dm_i2c_write(dev, reg, &value, 1);
929ad69f0bSLiam Beguin #endif
93adf8d58dSSylvain Lemieux }
94adf8d58dSSylvain Lemieux 
isp1301_configure(struct udevice * dev)959ad69f0bSLiam Beguin static void isp1301_configure(struct udevice *dev)
96adf8d58dSSylvain Lemieux {
979ad69f0bSLiam Beguin #ifndef CONFIG_DM_I2C
98adf8d58dSSylvain Lemieux 	i2c_set_bus_num(I2C_2);
999ad69f0bSLiam Beguin #endif
100adf8d58dSSylvain Lemieux 
101adf8d58dSSylvain Lemieux 	/*
102adf8d58dSSylvain Lemieux 	 * LPC32XX only supports DAT_SE0 USB mode
103adf8d58dSSylvain Lemieux 	 * This sequence is important
104adf8d58dSSylvain Lemieux 	 */
105adf8d58dSSylvain Lemieux 
106adf8d58dSSylvain Lemieux 	/* Disable transparent UART mode first */
1079ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_CLR, MC1_UART_EN);
108adf8d58dSSylvain Lemieux 
1099ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_CLR, ~MC1_SPEED_REG);
1109ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_SET, MC1_SPEED_REG);
1119ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_2_CLR, ~0);
1129ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_2_SET,
113adf8d58dSSylvain Lemieux 			  MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL);
114adf8d58dSSylvain Lemieux 
1159ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_CLR, ~0);
1169ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_SET, MC1_DAT_SE0);
1179ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET,
118adf8d58dSSylvain Lemieux 			  OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
1199ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_CLR,
120adf8d58dSSylvain Lemieux 			  OTG1_DM_PULLUP | OTG1_DP_PULLUP);
1219ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_LATCH_CLR, ~0);
1229ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_FALLING_CLR, ~0);
1239ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_RISING_CLR, ~0);
124adf8d58dSSylvain Lemieux 
125adf8d58dSSylvain Lemieux 	/* Enable usb_need_clk clock after transceiver is initialized */
126adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_USBDVND_EN);
127adf8d58dSSylvain Lemieux }
128adf8d58dSSylvain Lemieux 
usbpll_setup(void)129adf8d58dSSylvain Lemieux static int usbpll_setup(void)
130adf8d58dSSylvain Lemieux {
131adf8d58dSSylvain Lemieux 	u32 ret;
132adf8d58dSSylvain Lemieux 
133adf8d58dSSylvain Lemieux 	/* make sure clocks are disabled */
134adf8d58dSSylvain Lemieux 	clrbits_le32(&clk_pwr->usb_ctrl,
135adf8d58dSSylvain Lemieux 		     CLK_USBCTRL_CLK_EN1 | CLK_USBCTRL_CLK_EN2);
136adf8d58dSSylvain Lemieux 
137adf8d58dSSylvain Lemieux 	/* start PLL clock input */
138adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_CLK_EN1);
139adf8d58dSSylvain Lemieux 
140adf8d58dSSylvain Lemieux 	/* Setup PLL. */
141adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl,
142adf8d58dSSylvain Lemieux 		     CLK_USBCTRL_FDBK_PLUS1(192 - 1));
143adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01));
144adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP);
145adf8d58dSSylvain Lemieux 
146*b491b498SJon Lin 	ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
1478d5c7bb2SMateusz Kulikowski 				true, CONFIG_SYS_HZ, false);
148adf8d58dSSylvain Lemieux 	if (ret)
149adf8d58dSSylvain Lemieux 		return ret;
150adf8d58dSSylvain Lemieux 
151adf8d58dSSylvain Lemieux 	/* enable PLL output */
152adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_CLK_EN2);
153adf8d58dSSylvain Lemieux 
154adf8d58dSSylvain Lemieux 	return 0;
155adf8d58dSSylvain Lemieux }
156adf8d58dSSylvain Lemieux 
usb_cpu_init(void)157adf8d58dSSylvain Lemieux int usb_cpu_init(void)
158adf8d58dSSylvain Lemieux {
159adf8d58dSSylvain Lemieux 	u32 ret;
1609ad69f0bSLiam Beguin 	struct udevice *dev = NULL;
1619ad69f0bSLiam Beguin 
1629ad69f0bSLiam Beguin #ifdef CONFIG_DM_I2C
1639ad69f0bSLiam Beguin 	ret = i2c_get_chip_for_busnum(I2C_2, ISP1301_I2C_ADDR, 1, &dev);
1649ad69f0bSLiam Beguin 	if (ret) {
1659ad69f0bSLiam Beguin 		debug("%s: No bus %d\n", __func__, I2C_2);
1669ad69f0bSLiam Beguin 		return ret;
1679ad69f0bSLiam Beguin 	}
1689ad69f0bSLiam Beguin #endif
169adf8d58dSSylvain Lemieux 
170adf8d58dSSylvain Lemieux 	/*
171adf8d58dSSylvain Lemieux 	 * USB pins routing setup is done by "lpc32xx_usb_init()" and should
172adf8d58dSSylvain Lemieux 	 * be call by board "board_init()" or "misc_init_r()" functions.
173adf8d58dSSylvain Lemieux 	 */
174adf8d58dSSylvain Lemieux 
175adf8d58dSSylvain Lemieux 	/* enable AHB slave USB clock */
176adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl,
177adf8d58dSSylvain Lemieux 		     CLK_USBCTRL_HCLK_EN | CLK_USBCTRL_BUS_KEEPER);
178adf8d58dSSylvain Lemieux 
179adf8d58dSSylvain Lemieux 	/* enable I2C clock */
180adf8d58dSSylvain Lemieux 	writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl);
181*b491b498SJon Lin 	ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
1828d5c7bb2SMateusz Kulikowski 				CONFIG_SYS_HZ, false);
183adf8d58dSSylvain Lemieux 	if (ret)
184adf8d58dSSylvain Lemieux 		return ret;
185adf8d58dSSylvain Lemieux 
186adf8d58dSSylvain Lemieux 	/* Configure ISP1301 */
1879ad69f0bSLiam Beguin 	isp1301_configure(dev);
188adf8d58dSSylvain Lemieux 
189adf8d58dSSylvain Lemieux 	/* setup USB clocks and PLL */
190adf8d58dSSylvain Lemieux 	ret = usbpll_setup();
191adf8d58dSSylvain Lemieux 	if (ret)
192adf8d58dSSylvain Lemieux 		return ret;
193adf8d58dSSylvain Lemieux 
194adf8d58dSSylvain Lemieux 	/* enable usb_host_need_clk */
195adf8d58dSSylvain Lemieux 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_USBHSTND_EN);
196adf8d58dSSylvain Lemieux 
197adf8d58dSSylvain Lemieux 	/* enable all needed USB clocks */
198adf8d58dSSylvain Lemieux 	const u32 mask = OTG_CLK_AHB_EN | OTG_CLK_OTG_EN |
199adf8d58dSSylvain Lemieux 			 OTG_CLK_I2C_EN | OTG_CLK_HOST_EN;
200adf8d58dSSylvain Lemieux 	writel(mask, &otg->otg_clk_ctrl);
201adf8d58dSSylvain Lemieux 
202*b491b498SJon Lin 	ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true,
2038d5c7bb2SMateusz Kulikowski 				CONFIG_SYS_HZ, false);
204adf8d58dSSylvain Lemieux 	if (ret)
205adf8d58dSSylvain Lemieux 		return ret;
206adf8d58dSSylvain Lemieux 
207adf8d58dSSylvain Lemieux 	setbits_le32(&otg->otg_sts_ctrl, OTG_HOST_EN);
2089ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET, OTG1_VBUS_DRV);
209adf8d58dSSylvain Lemieux 
210adf8d58dSSylvain Lemieux 	return 0;
211adf8d58dSSylvain Lemieux }
212adf8d58dSSylvain Lemieux 
usb_cpu_stop(void)213adf8d58dSSylvain Lemieux int usb_cpu_stop(void)
214adf8d58dSSylvain Lemieux {
2159ad69f0bSLiam Beguin 	struct udevice *dev = NULL;
2169ad69f0bSLiam Beguin 	int ret = 0;
2179ad69f0bSLiam Beguin 
2189ad69f0bSLiam Beguin #ifdef CONFIG_DM_I2C
2199ad69f0bSLiam Beguin 	ret = i2c_get_chip_for_busnum(I2C_2, ISP1301_I2C_ADDR, 1, &dev);
2209ad69f0bSLiam Beguin 	if (ret) {
2219ad69f0bSLiam Beguin 		debug("%s: No bus %d\n", __func__, I2C_2);
2229ad69f0bSLiam Beguin 		return ret;
2239ad69f0bSLiam Beguin 	}
2249ad69f0bSLiam Beguin #endif
2259ad69f0bSLiam Beguin 
226adf8d58dSSylvain Lemieux 	/* vbus off */
2279ad69f0bSLiam Beguin 	isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET, OTG1_VBUS_DRV);
228adf8d58dSSylvain Lemieux 
229adf8d58dSSylvain Lemieux 	clrbits_le32(&otg->otg_sts_ctrl, OTG_HOST_EN);
230adf8d58dSSylvain Lemieux 
231adf8d58dSSylvain Lemieux 	clrbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_HCLK_EN);
232adf8d58dSSylvain Lemieux 
2339ad69f0bSLiam Beguin 	return ret;
234adf8d58dSSylvain Lemieux }
235adf8d58dSSylvain Lemieux 
usb_cpu_init_fail(void)236adf8d58dSSylvain Lemieux int usb_cpu_init_fail(void)
237adf8d58dSSylvain Lemieux {
238adf8d58dSSylvain Lemieux 	return usb_cpu_stop();
239adf8d58dSSylvain Lemieux }
240