1/*-
2 * Copyright (c) 2011
3 *	Ben Gray <ben.r.gray@gmail.com>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the company nor the name of the author may be used to
15 *    endorse or promote products derived from this software without specific
16 *    prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36
37#include <vm/vm.h>
38#include <vm/pmap.h>
39
40#include <machine/bus.h>
41#include <machine/vmparam.h>
42#include <machine/fdt.h>
43
44#include <arm/ti/omap4/omap4_reg.h>
45
46/* Registers in the SCRM that control the AUX clocks */
47#define SCRM_ALTCLKSRC			     (0x110)
48#define SCRM_AUXCLK0                         (0x0310)
49#define SCRM_AUXCLK1                         (0x0314)
50#define SCRM_AUXCLK2                         (0x0318)
51#define SCRM_AUXCLK3                         (0x031C)
52
53/* Some of the GPIO register set */
54#define GPIO1_OE                             (0x0134)
55#define GPIO1_CLEARDATAOUT                   (0x0190)
56#define GPIO1_SETDATAOUT                     (0x0194)
57#define GPIO2_OE                             (0x0134)
58#define GPIO2_CLEARDATAOUT                   (0x0190)
59#define GPIO2_SETDATAOUT                     (0x0194)
60
61/* Some of the PADCONF register set */
62#define CONTROL_WKUP_PAD0_FREF_CLK3_OUT  (0x058)
63#define CONTROL_CORE_PAD1_KPD_COL2       (0x186)
64#define CONTROL_CORE_PAD0_GPMC_WAIT1     (0x08C)
65
66#define REG_WRITE32(r, x)    *((volatile uint32_t*)(r)) = (uint32_t)(x)
67#define REG_READ32(r)        *((volatile uint32_t*)(r))
68
69#define REG_WRITE16(r, x)    *((volatile uint16_t*)(r)) = (uint16_t)(x)
70#define REG_READ16(r)        *((volatile uint16_t*)(r))
71
72/**
73 *	usb_hub_init - initialises and resets the external USB hub
74 *
75 *	The USB hub needs to be held in reset while the power is being applied
76 *	and the reference clock is enabled at 19.2MHz.  The following is the
77 *	layout of the USB hub taken from the Pandaboard reference manual.
78 *
79 *
80 *	   .-------------.         .--------------.         .----------------.
81 *	   |  OMAP4430   |         |   USB3320C   |         |    LAN9514     |
82 *	   |             |         |              |         | USB Hub / Eth  |
83 *	   |         CLK | <------ | CLKOUT       |         |                |
84 *	   |         STP | ------> | STP          |         |                |
85 *	   |         DIR | <------ | DIR          |         |                |
86 *	   |         NXT | <------ | NXT          |         |                |
87 *	   |        DAT0 | <-----> | DAT0         |         |                |
88 *	   |        DAT1 | <-----> | DAT1      DP | <-----> | DP             |
89 *	   |        DAT2 | <-----> | DAT2      DM | <-----> | DM             |
90 *	   |        DAT3 | <-----> | DAT3         |         |                |
91 *	   |        DAT4 | <-----> | DAT4         |         |                |
92 *	   |        DAT5 | <-----> | DAT5         |  +----> | N_RESET        |
93 *	   |        DAT6 | <-----> | DAT6         |  |      |                |
94 *	   |        DAT7 | <-----> | DAT7         |  |      |                |
95 *	   |             |         |              |  |  +-> | VDD33IO        |
96 *	   |    AUX_CLK3 | ------> | REFCLK       |  |  +-> | VDD33A         |
97 *	   |             |         |              |  |  |   |                |
98 *	   |     GPIO_62 | --+---> | RESET        |  |  |   |                |
99 *	   |             |   |     |              |  |  |   |                |
100 *	   |             |   |     '--------------'  |  |   '----------------'
101 *	   |             |   |     .--------------.  |  |
102 *	   |             |   '---->| VOLT CONVERT |--'  |
103 *	   |             |         '--------------'     |
104 *	   |             |                              |
105 *	   |             |         .--------------.     |
106 *	   |      GPIO_1 | ------> |   TPS73633   |-----'
107 *	   |             |         '--------------'
108 *	   '-------------'
109 *
110 *
111 *	RETURNS:
112 *	nothing.
113 */
114static void
115usb_hub_init(void)
116{
117	bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr;
118
119	if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCRM_HWBASE,
120	    OMAP44XX_SCRM_SIZE, 0, &scrm_addr) != 0)
121		panic("Couldn't map SCRM registers");
122	if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO1_HWBASE,
123	    OMAP44XX_GPIO1_SIZE, 0, &gpio1_addr) != 0)
124		panic("Couldn't map GPIO1 registers");
125	if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO2_HWBASE,
126	    OMAP44XX_GPIO2_SIZE, 0, &gpio2_addr) != 0)
127		panic("Couldn't map GPIO2 registers");
128	if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCM_PADCONF_HWBASE,
129	    OMAP44XX_SCM_PADCONF_SIZE, 0, &scm_addr) != 0)
130		panic("Couldn't map SCM Padconf registers");
131
132
133
134	/* Need to set FREF_CLK3_OUT to 19.2 MHz and pump it out on pin GPIO_WK31.
135	 * We know the SYS_CLK is 38.4Mhz and therefore to get the needed 19.2Mhz,
136	 * just use a 2x divider and ensure the SYS_CLK is used as the source.
137	 */
138	REG_WRITE32(scrm_addr + SCRM_AUXCLK3, (1 << 16) |    /* Divider of 2 */
139	                          (0 << 1) |     /* Use the SYS_CLK as the source */
140	                          (1 << 8));     /* Enable the clock */
141
142	/* Enable the clock out to the pin (GPIO_WK31).
143	 *   muxmode=fref_clk3_out, pullup/down=disabled, input buffer=disabled,
144	 *   wakeup=disabled.
145	 */
146	REG_WRITE16(scm_addr + CONTROL_WKUP_PAD0_FREF_CLK3_OUT, 0x0000);
147
148
149	/* Disable the power to the USB hub, drive GPIO1 low */
150	REG_WRITE32(gpio1_addr + GPIO1_OE, REG_READ32(gpio1_addr +
151	    GPIO1_OE) & ~(1UL << 1));
152	REG_WRITE32(gpio1_addr + GPIO1_CLEARDATAOUT, (1UL << 1));
153	REG_WRITE16(scm_addr + CONTROL_CORE_PAD1_KPD_COL2, 0x0003);
154
155
156	/* Reset the USB PHY and Hub using GPIO_62 */
157	REG_WRITE32(gpio2_addr + GPIO2_OE,
158	    REG_READ32(gpio2_addr + GPIO2_OE) & ~(1UL << 30));
159	REG_WRITE32(gpio2_addr + GPIO2_CLEARDATAOUT, (1UL << 30));
160	REG_WRITE16(scm_addr + CONTROL_CORE_PAD0_GPMC_WAIT1, 0x0003);
161	DELAY(10);
162	REG_WRITE32(gpio2_addr + GPIO2_SETDATAOUT, (1UL << 30));
163
164
165	/* Enable power to the hub (GPIO_1) */
166	REG_WRITE32(gpio1_addr + GPIO1_SETDATAOUT, (1UL << 1));
167	bus_space_unmap(fdtbus_bs_tag, scrm_addr, OMAP44XX_SCRM_SIZE);
168	bus_space_unmap(fdtbus_bs_tag, gpio1_addr, OMAP44XX_GPIO1_SIZE);
169	bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE);
170	bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE);
171}
172
173/**
174 *	board_init - initialises the pandaboard
175 *	@dummy: ignored
176 *
177 *	This function is called before any of the driver are initialised, which is
178 *	annoying because it means we can't use the SCM, PRCM and GPIO modules which
179 *	would really be useful.
180 *
181 *	So we don't have:
182 *	   - any drivers
183 *	   - no interrupts
184 *
185 *	What we do have:
186 *	   - virt/phys mappings from the devmap (see omap4.c)
187 *	   -
188 *
189 *
190 *	So we are hamstrung without the useful drivers and we have to go back to
191 *	direct register manupulation. Luckly we don't have to do to much, basically
192 *	just setup the usb hub/ethernet.
193 *
194 */
195static void
196board_init(void *dummy)
197{
198	/* Initialise the USB phy and hub */
199	usb_hub_init();
200
201	/*
202	 * XXX Board identification e.g. read out from FPGA or similar should
203	 * go here
204	 */
205}
206
207SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL);
208