summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/usb-x1000.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/usb-x1000.c')
-rw-r--r--firmware/target/mips/ingenic_x1000/usb-x1000.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_x1000/usb-x1000.c b/firmware/target/mips/ingenic_x1000/usb-x1000.c
new file mode 100644
index 0000000000..32413b0b94
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/usb-x1000.c
@@ -0,0 +1,223 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "system.h"
23#include "usb.h"
24#include "usb_core.h"
25#include "usb_drv.h"
26#include "usb-designware.h"
27#include "irq-x1000.h"
28#include "gpio-x1000.h"
29#include "x1000/cpm.h"
30
31#ifdef FIIO_M3K
32# define USB_DETECT_PORT GPIO_B
33# define USB_DETECT_PIN (1 << 11)
34# define USB_DETECT_PIN_INT GPIOB11
35# define USB_ID_PORT GPIO_B
36# define USB_ID_PIN (1 << 7)
37#else
38# ifndef USB_NONE
39# error "please add USB GPIO pins"
40# endif
41#endif
42
43#define USB_DRVVBUS_PORT GPIO_B
44#define USB_DRVVBUS_PIN (1 << 25)
45
46/*
47 * USB-Designware driver API
48 */
49
50const struct usb_dw_config usb_dw_config = {
51 .phytype = DWC_PHYTYPE_UTMI_16,
52
53 /* Available FIFO memory: 3576 words */
54 .rx_fifosz = 1024,
55 .nptx_fifosz = 128, /* 1 dedicated FIFO for EP0 */
56 .ptx_fifosz = 768, /* 3 dedicated FIFOs */
57
58#ifndef USB_DW_ARCH_SLAVE
59 .ahb_burst_len = HBSTLEN_INCR16,
60 /* Disable Rx FIFO thresholding. It appears to cause problems,
61 * apparently a known issue -- Synopsys recommends disabling it
62 * because it can cause issues during certain error conditions.
63 */
64 .ahb_threshold = 0,
65#else
66 .disable_double_buffering = false,
67#endif
68};
69
70/* USB PHY init from Linux kernel code:
71 * - arch/mips/xburst/soc-x1000/common/cpm_usb.c
72 * Copyright (C) 2005-2017 Ingenic Semiconductor
73 */
74void usb_dw_target_enable_clocks(void)
75{
76 /* Enable CPM clock */
77 jz_writef(CPM_CLKGR, OTG(0));
78#if X1000_EXCLK_FREQ == 24000000
79 jz_writef(CPM_USBCDR, CLKSRC_V(EXCLK), CE(1), CLKDIV(0), PHY_GATE(0));
80#else
81# error "please add USB clock settings for 26 MHz EXCLK"
82#endif
83 while(jz_readf(CPM_USBCDR, BUSY));
84 jz_writef(CPM_USBCDR, CE(0));
85
86 /* PHY soft reset */
87 jz_writef(CPM_SRBC, OTG_SR(1));
88 udelay(10);
89 jz_writef(CPM_SRBC, OTG_SR(0));
90
91 /* Ungate PHY clock */
92 jz_writef(CPM_OPCR, GATE_USBPHY_CLK(0));
93
94 /* Exit suspend state */
95 jz_writef(CPM_OPCR, SPENDN0(1));
96 udelay(45);
97
98 /* Program core configuration */
99 jz_overwritef(CPM_USBVBFIL,
100 IDDIGFIL(0),
101 VBFIL(0));
102 jz_overwritef(CPM_USBRDT,
103 HB_MASK(0),
104 VBFIL_LD_EN(1),
105 IDDIG_EN(0),
106 RDT(0x96));
107 jz_overwritef(CPM_USBPCR,
108 OTG_DISABLE(1),
109 COMMONONN(1),
110 VBUSVLDEXT(1),
111 VBUSVLDEXTSEL(1),
112 SQRXTUNE(7),
113 TXPREEMPHTUNE(1),
114 TXHSXVTUNE(1),
115 TXVREFTUNE(7));
116 jz_overwritef(CPM_USBPCR1,
117 BVLD_REG(1),
118 REFCLK_SEL_V(CLKCORE),
119 REFCLK_DIV_V(24MHZ), /* applies for 26 MHz EXCLK too */
120 WORD_IF_V(16BIT));
121
122 /* Power on reset */
123 jz_writef(CPM_USBPCR, POR(1));
124 mdelay(1);
125 jz_writef(CPM_USBPCR, POR(0));
126 mdelay(1);
127}
128
129void usb_dw_target_disable_clocks(void)
130{
131 /* Suspend and power down PHY, then gate its clock */
132 jz_writef(CPM_OPCR, SPENDN0(0));
133 udelay(5);
134 jz_writef(CPM_USBPCR, OTG_DISABLE(1), SIDDQ(1));
135 jz_writef(CPM_OPCR, GATE_USBPHY_CLK(1));
136
137 /* Disable CPM clock */
138 jz_writef(CPM_USBCDR, CE(1), STOP(1), PHY_GATE(1));
139 while(jz_readf(CPM_USBCDR, BUSY));
140 jz_writef(CPM_USBCDR, CE(0));
141 jz_writef(CPM_CLKGR, OTG(1));
142}
143
144void usb_dw_target_enable_irq(void)
145{
146 system_enable_irq(IRQ_OTG);
147}
148
149void usb_dw_target_disable_irq(void)
150{
151 system_disable_irq(IRQ_OTG);
152}
153
154void usb_dw_target_clear_irq(void)
155{
156}
157
158/*
159 * Rockbox API
160 */
161
162#ifdef USB_STATUS_BY_EVENT
163static volatile int usb_status = USB_EXTRACTED;
164#endif
165
166static int __usb_detect(void)
167{
168 if(REG_GPIO_PIN(USB_DETECT_PORT) & USB_DETECT_PIN)
169 return USB_INSERTED;
170 else
171 return USB_EXTRACTED;
172}
173
174void usb_enable(bool on)
175{
176 if(on)
177 usb_core_init();
178 else
179 usb_core_exit();
180}
181
182void usb_init_device(void)
183{
184 /* Disable drvvbus pin -- it is only used when acting as a host,
185 * which Rockbox does not support */
186 gpio_config(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN, GPIO_OUTPUT(0));
187
188 /* Power up the core clocks to allow writing
189 to some registers needed to power it down */
190 usb_dw_target_disable_irq();
191 usb_dw_target_enable_clocks();
192 usb_drv_exit();
193
194#ifdef USB_STATUS_BY_EVENT
195 /* Setup USB detect pin IRQ */
196 usb_status = __usb_detect();
197 int level = (REG_GPIO_PIN(USB_DETECT_PORT) & USB_DETECT_PIN) ? 1 : 0;
198 gpio_config(USB_DETECT_PORT, USB_DETECT_PIN, GPIO_IRQ_EDGE(level ? 0 : 1));
199 gpio_enable_irq(USB_DETECT_PORT, USB_DETECT_PIN);
200#endif
201}
202
203#ifndef USB_STATUS_BY_EVENT
204int usb_detect(void)
205{
206 return __usb_detect();
207}
208#else
209int usb_detect(void)
210{
211 return usb_status;
212}
213
214void USB_DETECT_PIN_INT(void)
215{
216 /* Update status and flip the IRQ trigger edge */
217 usb_status = __usb_detect();
218 REG_GPIO_PAT0(USB_DETECT_PORT) ^= USB_DETECT_PIN;
219
220 /* Notify Rockbox of event */
221 usb_status_event(usb_status);
222}
223#endif