blob: 99f9504017324e4f331035cce866d029f06c3b5c [file] [log] [blame]
Travis Geiselbrecht2c691e82008-09-04 02:41:01 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <debug.h>
24#include <reg.h>
25#include <dev/usb.h>
26#include <dev/usbc.h>
27#include <dev/twl4030.h>
28#include <hw/usb.h>
29#include <platform/interrupts.h>
30#include <platform/omap3.h>
31
32#define LOCAL_TRACE 1
33
34#define hsusb_reg8(reg) *REG8(USB_HS_BASE + (reg))
35#define hsusb_reg16(reg) *REG16(USB_HS_BASE + (reg))
36#define hsusb_reg32(reg) *REG32(USB_HS_BASE + (reg))
37
38/* registers */
39#define FADDR 0x0
40#define POWER 0x1
41#define INTRTX 0x2
42#define INTRRX 0x4
43#define INTRTXE 0x6
44#define INTRRXE 0x8
45#define INTRUSB 0xa
46#define INTRUSBE 0xb
47#define FRAME 0xc
48#define INDEX 0xe
49#define TESTMODE 0xf
50
51// indexed endpoint regs
52#define IDX_TXMAXP 0x10
53#define IDX_TXCSR 0x12
54#define IDX_TXCSRL 0x12
55#define IDX_TXCSRH 0x13
56#define IDX_RXMAXP 0x14
57#define IDX_RXCSR 0x16
58#define IDX_RXCSRL 0x16
59#define IDX_RXCSRH 0x17
60#define IDX_RXCOUNT 0x18
61#define IDX_FIFOSIZE 0x1f
62
63// if endpoint 0 is selected
64#define IDX_CSR0 0x12
65#define IDX_CONFIGDATA 0x1f
66
67// endpoint FIFOs
68#define FIFOBASE 0x20
69
70#define DEVCTL 0x60
71#define TXFIFOSZ 0x62
72#define RXFIFOSZ 0x63
73#define TXFIFOADD 0x64
74#define RXFIFOADD 0x66
75#define HWVERS 0x6c
76#define EPINFO 0x78
77#define RAMINFO 0x79
78#define LINKINFO 0x7a
79
80static enum handler_return hsusb_interrupt(void *arg)
81{
82 uint16_t intrtx = hsusb_reg16(INTRTX);
83 uint16_t intrrx = hsusb_reg16(INTRRX);
84 uint8_t intrusb = hsusb_reg8(INTRUSB);
85 enum handler_return ret = INT_NO_RESCHEDULE;
86
87 LTRACEF("intrtx 0x%hx (0x%x), intrrx 0x%hx (0x%x), intrusb 0x%hhx, intrusbe 0x%hhx\n",
88 intrtx, hsusb_reg16(INTRTXE), intrrx, hsusb_reg16(INTRRXE), intrusb, hsusb_reg8(INTRUSBE));
89
90 return ret;
91}
92
93int usbc_set_active(bool active)
94{
95 if (active) {
96// DEBUG_ASSERT(!usbc->active);
97
98 hsusb_reg8(POWER) |= (1<<6); // soft conn
99 twl4030_set_usb_pullup(true);
100// usbc->active = true;
101 } else {
102 hsusb_reg8(POWER) &= ~(1<<6); // soft conn
103 twl4030_set_usb_pullup(false);
104// usbc->active = false;
105 }
106
107 return 0;
108}
109
110static void otg_reset(void)
111{
112 /* reset the chip */
113 *REG32(OTG_SYSCONFIG) |= (1<<1);
114 while ((*REG32(OTG_SYSSTATUS) & 1) == 0)
115 ;
116
117 /* power up the controller */
118 *REG32(OTG_FORCESTDBY) = 0; // disable forced standby
119 *REG32(OTG_SYSCONFIG) &= ~(1<<1); // autoidle off
120 *REG32(OTG_SYSCONFIG) = (2<<12) | (2<<3) | (0<<0); // master in smart-standby, periph in smart-idle, autoidle off
121
122 *REG32(OTG_SYSCONFIG) |= 1; // autoidle on
123
124 *REG32(OTG_INTERFSEL) = 1; // 8 bit ULPI
125}
126
127static void hsusb_init(void)
128{
129 LTRACE_ENTRY;
130
131 // select endpoint 0
132 dprintf("hwvers 0x%hx\n", hsusb_reg16(HWVERS));
133 dprintf("epinfo 0x%hhx\n", hsusb_reg8(EPINFO));
134 dprintf("raminfo 0x%hhx\n", hsusb_reg8(RAMINFO));
135 hsusb_reg8(INDEX) = 0;
136 dprintf("config 0x%hhx\n", hsusb_reg8(IDX_CONFIGDATA));
137
138 // assert that we have dynamic fifo sizing
139 DEBUG_ASSERT(hsusb_reg8(IDX_CONFIGDATA) & (1<<2));
140
141 // mask all the interrupts for the endpoints (except 0)
142 hsusb_reg16(INTRTXE) = (1<<0);
143 hsusb_reg16(INTRRXE) = 0;
144
145 twl4030_usb_reset();
146 twl4030_init_hs();
147
148 hsusb_reg8(DEVCTL) = 0; // peripheral mode
149// hsusb_reg8(POWER) &= (1<<5); // disable high speed
150 hsusb_reg8(POWER) |= (1<<5); // enable high speed
151
152 hsusb_reg8(INTRUSBE) = (1<<5)|(1<<2)|(1<<1)|(1<<0); // disconnect, reset, resume, suspend
153
154 LTRACE_EXIT;
155}
156
157void usbc_init(void)
158{
159 // enable the clock
160 RMWREG32(CM_ICLKEN1_CORE, 4, 1, 1);
161
162 // register the interrupt handlers
163 register_int_handler(92, hsusb_interrupt, NULL);
164// register_int_handler(93, hsusb_dma_interrupt, NULL);
165
166 otg_reset();
167 hsusb_init();
168
169 unmask_interrupt(92, NULL);
170// unmask_interrupt(93, NULL);
171
172 usbc_set_active(true);
173}
174