]>
Commit | Line | Data |
---|---|---|
adf8d58d SL |
1 | /* |
2 | * Copyright (C) 2008 by NXP Semiconductors | |
3 | * @Author: Based on code by Kevin Wells | |
4 | * @Descr: USB driver - Embedded Artists LPC3250 OEM Board support functions | |
5 | * | |
6 | * Copyright (c) 2015 Tyco Fire Protection Products. | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0+ | |
9 | */ | |
10 | ||
11 | #include <common.h> | |
9ad69f0b | 12 | #include <dm.h> |
adf8d58d | 13 | #include <errno.h> |
8d5c7bb2 | 14 | #include <wait_bit.h> |
adf8d58d SL |
15 | #include <asm/io.h> |
16 | #include <asm/arch/cpu.h> | |
17 | #include <asm/arch/clk.h> | |
9ad69f0b | 18 | #include <asm/arch/i2c.h> |
adf8d58d SL |
19 | #include <usb.h> |
20 | #include <i2c.h> | |
21 | ||
22 | /* OTG I2C controller module register structures */ | |
23 | struct otgi2c_regs { | |
24 | u32 otg_i2c_txrx; /* OTG I2C Tx/Rx Data FIFO */ | |
25 | u32 otg_i2c_stat; /* OTG I2C Status Register */ | |
26 | u32 otg_i2c_ctrl; /* OTG I2C Control Register */ | |
27 | u32 otg_i2c_clk_hi; /* OTG I2C Clock Divider high */ | |
28 | u32 otg_i2c_clk_lo; /* OTG I2C Clock Divider low */ | |
29 | }; | |
30 | ||
31 | /* OTG controller module register structures */ | |
32 | struct otg_regs { | |
33 | u32 reserved1[64]; | |
34 | u32 otg_int_sts; /* OTG int status register */ | |
35 | u32 otg_int_enab; /* OTG int enable register */ | |
36 | u32 otg_int_set; /* OTG int set register */ | |
37 | u32 otg_int_clr; /* OTG int clear register */ | |
38 | u32 otg_sts_ctrl; /* OTG status/control register */ | |
39 | u32 otg_timer; /* OTG timer register */ | |
40 | u32 reserved2[122]; | |
41 | struct otgi2c_regs otg_i2c; | |
42 | u32 reserved3[824]; | |
43 | u32 otg_clk_ctrl; /* OTG clock control reg */ | |
44 | u32 otg_clk_sts; /* OTG clock status reg */ | |
45 | }; | |
46 | ||
47 | /* otg_sts_ctrl register definitions */ | |
48 | #define OTG_HOST_EN (1 << 0) /* Enable host mode */ | |
49 | ||
50 | /* otg_clk_ctrl and otg_clk_sts register definitions */ | |
51 | #define OTG_CLK_AHB_EN (1 << 4) /* Enable AHB clock */ | |
52 | #define OTG_CLK_OTG_EN (1 << 3) /* Enable OTG clock */ | |
53 | #define OTG_CLK_I2C_EN (1 << 2) /* Enable I2C clock */ | |
54 | #define OTG_CLK_HOST_EN (1 << 0) /* Enable host clock */ | |
55 | ||
56 | /* ISP1301 USB transceiver I2C registers */ | |
57 | #define MC1_SPEED_REG (1 << 0) | |
58 | #define MC1_DAT_SE0 (1 << 2) | |
59 | #define MC1_UART_EN (1 << 6) | |
60 | ||
61 | #define MC2_SPD_SUSP_CTRL (1 << 1) | |
62 | #define MC2_BI_DI (1 << 2) | |
63 | #define MC2_PSW_EN (1 << 6) | |
64 | ||
65 | #define OTG1_DP_PULLUP (1 << 0) | |
66 | #define OTG1_DM_PULLUP (1 << 1) | |
67 | #define OTG1_DP_PULLDOWN (1 << 2) | |
68 | #define OTG1_DM_PULLDOWN (1 << 3) | |
69 | #define OTG1_VBUS_DRV (1 << 5) | |
70 | ||
71 | #define ISP1301_I2C_ADDR CONFIG_USB_ISP1301_I2C_ADDR | |
72 | ||
73 | #define ISP1301_I2C_MODE_CONTROL_1_SET 0x04 | |
74 | #define ISP1301_I2C_MODE_CONTROL_1_CLR 0x05 | |
75 | #define ISP1301_I2C_MODE_CONTROL_2_SET 0x12 | |
76 | #define ISP1301_I2C_MODE_CONTROL_2_CLR 0x13 | |
77 | #define ISP1301_I2C_OTG_CONTROL_1_SET 0x06 | |
78 | #define ISP1301_I2C_OTG_CONTROL_1_CLR 0x07 | |
79 | #define ISP1301_I2C_INTERRUPT_LATCH_CLR 0x0B | |
80 | #define ISP1301_I2C_INTERRUPT_FALLING_CLR 0x0D | |
81 | #define ISP1301_I2C_INTERRUPT_RISING_CLR 0x0F | |
82 | ||
83 | static struct otg_regs *otg = (struct otg_regs *)USB_BASE; | |
84 | static struct clk_pm_regs *clk_pwr = (struct clk_pm_regs *)CLK_PM_BASE; | |
85 | ||
9ad69f0b | 86 | static int isp1301_set_value(struct udevice *dev, int reg, u8 value) |
adf8d58d | 87 | { |
9ad69f0b | 88 | #ifndef CONFIG_DM_I2C |
adf8d58d | 89 | return i2c_write(ISP1301_I2C_ADDR, reg, 1, &value, 1); |
9ad69f0b LB |
90 | #else |
91 | return dm_i2c_write(dev, reg, &value, 1); | |
92 | #endif | |
adf8d58d SL |
93 | } |
94 | ||
9ad69f0b | 95 | static void isp1301_configure(struct udevice *dev) |
adf8d58d | 96 | { |
9ad69f0b | 97 | #ifndef CONFIG_DM_I2C |
adf8d58d | 98 | i2c_set_bus_num(I2C_2); |
9ad69f0b | 99 | #endif |
adf8d58d SL |
100 | |
101 | /* | |
102 | * LPC32XX only supports DAT_SE0 USB mode | |
103 | * This sequence is important | |
104 | */ | |
105 | ||
106 | /* Disable transparent UART mode first */ | |
9ad69f0b | 107 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_CLR, MC1_UART_EN); |
adf8d58d | 108 | |
9ad69f0b LB |
109 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_CLR, ~MC1_SPEED_REG); |
110 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_SET, MC1_SPEED_REG); | |
111 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_2_CLR, ~0); | |
112 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_2_SET, | |
adf8d58d SL |
113 | MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL); |
114 | ||
9ad69f0b LB |
115 | isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_CLR, ~0); |
116 | isp1301_set_value(dev, ISP1301_I2C_MODE_CONTROL_1_SET, MC1_DAT_SE0); | |
117 | isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET, | |
adf8d58d | 118 | OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN); |
9ad69f0b | 119 | isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_CLR, |
adf8d58d | 120 | OTG1_DM_PULLUP | OTG1_DP_PULLUP); |
9ad69f0b LB |
121 | isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_LATCH_CLR, ~0); |
122 | isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_FALLING_CLR, ~0); | |
123 | isp1301_set_value(dev, ISP1301_I2C_INTERRUPT_RISING_CLR, ~0); | |
adf8d58d SL |
124 | |
125 | /* Enable usb_need_clk clock after transceiver is initialized */ | |
126 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_USBDVND_EN); | |
127 | } | |
128 | ||
129 | static int usbpll_setup(void) | |
130 | { | |
131 | u32 ret; | |
132 | ||
133 | /* make sure clocks are disabled */ | |
134 | clrbits_le32(&clk_pwr->usb_ctrl, | |
135 | CLK_USBCTRL_CLK_EN1 | CLK_USBCTRL_CLK_EN2); | |
136 | ||
137 | /* start PLL clock input */ | |
138 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_CLK_EN1); | |
139 | ||
140 | /* Setup PLL. */ | |
141 | setbits_le32(&clk_pwr->usb_ctrl, | |
142 | CLK_USBCTRL_FDBK_PLUS1(192 - 1)); | |
143 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01)); | |
144 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP); | |
145 | ||
8d5c7bb2 MK |
146 | ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS, |
147 | true, CONFIG_SYS_HZ, false); | |
adf8d58d SL |
148 | if (ret) |
149 | return ret; | |
150 | ||
151 | /* enable PLL output */ | |
152 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_CLK_EN2); | |
153 | ||
154 | return 0; | |
155 | } | |
156 | ||
157 | int usb_cpu_init(void) | |
158 | { | |
159 | u32 ret; | |
9ad69f0b LB |
160 | struct udevice *dev = NULL; |
161 | ||
162 | #ifdef CONFIG_DM_I2C | |
163 | ret = i2c_get_chip_for_busnum(I2C_2, ISP1301_I2C_ADDR, 1, &dev); | |
164 | if (ret) { | |
165 | debug("%s: No bus %d\n", __func__, I2C_2); | |
166 | return ret; | |
167 | } | |
168 | #endif | |
adf8d58d SL |
169 | |
170 | /* | |
171 | * USB pins routing setup is done by "lpc32xx_usb_init()" and should | |
172 | * be call by board "board_init()" or "misc_init_r()" functions. | |
173 | */ | |
174 | ||
175 | /* enable AHB slave USB clock */ | |
176 | setbits_le32(&clk_pwr->usb_ctrl, | |
177 | CLK_USBCTRL_HCLK_EN | CLK_USBCTRL_BUS_KEEPER); | |
178 | ||
179 | /* enable I2C clock */ | |
180 | writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl); | |
8d5c7bb2 MK |
181 | ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true, |
182 | CONFIG_SYS_HZ, false); | |
adf8d58d SL |
183 | if (ret) |
184 | return ret; | |
185 | ||
186 | /* Configure ISP1301 */ | |
9ad69f0b | 187 | isp1301_configure(dev); |
adf8d58d SL |
188 | |
189 | /* setup USB clocks and PLL */ | |
190 | ret = usbpll_setup(); | |
191 | if (ret) | |
192 | return ret; | |
193 | ||
194 | /* enable usb_host_need_clk */ | |
195 | setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_USBHSTND_EN); | |
196 | ||
197 | /* enable all needed USB clocks */ | |
198 | const u32 mask = OTG_CLK_AHB_EN | OTG_CLK_OTG_EN | | |
199 | OTG_CLK_I2C_EN | OTG_CLK_HOST_EN; | |
200 | writel(mask, &otg->otg_clk_ctrl); | |
201 | ||
8d5c7bb2 MK |
202 | ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true, |
203 | CONFIG_SYS_HZ, false); | |
adf8d58d SL |
204 | if (ret) |
205 | return ret; | |
206 | ||
207 | setbits_le32(&otg->otg_sts_ctrl, OTG_HOST_EN); | |
9ad69f0b | 208 | isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET, OTG1_VBUS_DRV); |
adf8d58d SL |
209 | |
210 | return 0; | |
211 | } | |
212 | ||
213 | int usb_cpu_stop(void) | |
214 | { | |
9ad69f0b LB |
215 | struct udevice *dev = NULL; |
216 | int ret = 0; | |
217 | ||
218 | #ifdef CONFIG_DM_I2C | |
219 | ret = i2c_get_chip_for_busnum(I2C_2, ISP1301_I2C_ADDR, 1, &dev); | |
220 | if (ret) { | |
221 | debug("%s: No bus %d\n", __func__, I2C_2); | |
222 | return ret; | |
223 | } | |
224 | #endif | |
225 | ||
adf8d58d | 226 | /* vbus off */ |
9ad69f0b | 227 | isp1301_set_value(dev, ISP1301_I2C_OTG_CONTROL_1_SET, OTG1_VBUS_DRV); |
adf8d58d SL |
228 | |
229 | clrbits_le32(&otg->otg_sts_ctrl, OTG_HOST_EN); | |
230 | ||
231 | clrbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_HCLK_EN); | |
232 | ||
9ad69f0b | 233 | return ret; |
adf8d58d SL |
234 | } |
235 | ||
236 | int usb_cpu_init_fail(void) | |
237 | { | |
238 | return usb_cpu_stop(); | |
239 | } |