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 */ 114 static void 115 usb_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 */ 195 static void 196 board_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 207 SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL); 208