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/pte.h> 42 #include <machine/vmparam.h> 43 #include <machine/fdt.h> 44 45 #include <arm/ti/omap4/omap4_reg.h> 46 47 /* Registers in the SCRM that control the AUX clocks */ 48 #define SCRM_ALTCLKSRC (0x110) 49 #define SCRM_AUXCLK0 (0x0310) 50 #define SCRM_AUXCLK1 (0x0314) 51 #define SCRM_AUXCLK2 (0x0318) 52 #define SCRM_AUXCLK3 (0x031C) 53 54 /* Some of the GPIO register set */ 55 #define GPIO1_OE (0x0134) 56 #define GPIO1_CLEARDATAOUT (0x0190) 57 #define GPIO1_SETDATAOUT (0x0194) 58 #define GPIO2_OE (0x0134) 59 #define GPIO2_CLEARDATAOUT (0x0190) 60 #define GPIO2_SETDATAOUT (0x0194) 61 62 /* Some of the PADCONF register set */ 63 #define CONTROL_WKUP_PAD0_FREF_CLK3_OUT (0x058) 64 #define CONTROL_CORE_PAD1_KPD_COL2 (0x186) 65 #define CONTROL_CORE_PAD0_GPMC_WAIT1 (0x08C) 66 67 #define REG_WRITE32(r, x) *((volatile uint32_t*)(r)) = (uint32_t)(x) 68 #define REG_READ32(r) *((volatile uint32_t*)(r)) 69 70 #define REG_WRITE16(r, x) *((volatile uint16_t*)(r)) = (uint16_t)(x) 71 #define REG_READ16(r) *((volatile uint16_t*)(r)) 72 73 /** 74 * usb_hub_init - initialises and resets the external USB hub 75 * 76 * The USB hub needs to be held in reset while the power is being applied 77 * and the reference clock is enabled at 19.2MHz. The following is the 78 * layout of the USB hub taken from the Pandaboard reference manual. 79 * 80 * 81 * .-------------. .--------------. .----------------. 82 * | OMAP4430 | | USB3320C | | LAN9514 | 83 * | | | | | USB Hub / Eth | 84 * | CLK | <------ | CLKOUT | | | 85 * | STP | ------> | STP | | | 86 * | DIR | <------ | DIR | | | 87 * | NXT | <------ | NXT | | | 88 * | DAT0 | <-----> | DAT0 | | | 89 * | DAT1 | <-----> | DAT1 DP | <-----> | DP | 90 * | DAT2 | <-----> | DAT2 DM | <-----> | DM | 91 * | DAT3 | <-----> | DAT3 | | | 92 * | DAT4 | <-----> | DAT4 | | | 93 * | DAT5 | <-----> | DAT5 | +----> | N_RESET | 94 * | DAT6 | <-----> | DAT6 | | | | 95 * | DAT7 | <-----> | DAT7 | | | | 96 * | | | | | +-> | VDD33IO | 97 * | AUX_CLK3 | ------> | REFCLK | | +-> | VDD33A | 98 * | | | | | | | | 99 * | GPIO_62 | --+---> | RESET | | | | | 100 * | | | | | | | | | 101 * | | | '--------------' | | '----------------' 102 * | | | .--------------. | | 103 * | | '---->| VOLT CONVERT |--' | 104 * | | '--------------' | 105 * | | | 106 * | | .--------------. | 107 * | GPIO_1 | ------> | TPS73633 |-----' 108 * | | '--------------' 109 * '-------------' 110 * 111 * 112 * RETURNS: 113 * nothing. 114 */ 115 static void 116 usb_hub_init(void) 117 { 118 bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr; 119 120 if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCRM_HWBASE, 121 OMAP44XX_SCRM_SIZE, 0, &scrm_addr) != 0) 122 panic("Couldn't map SCRM registers"); 123 if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO1_HWBASE, 124 OMAP44XX_GPIO1_SIZE, 0, &gpio1_addr) != 0) 125 panic("Couldn't map GPIO1 registers"); 126 if (bus_space_map(fdtbus_bs_tag, OMAP44XX_GPIO2_HWBASE, 127 OMAP44XX_GPIO2_SIZE, 0, &gpio2_addr) != 0) 128 panic("Couldn't map GPIO2 registers"); 129 if (bus_space_map(fdtbus_bs_tag, OMAP44XX_SCM_PADCONF_HWBASE, 130 OMAP44XX_SCM_PADCONF_SIZE, 0, &scm_addr) != 0) 131 panic("Couldn't map SCM Padconf registers"); 132 133 134 135 /* Need to set FREF_CLK3_OUT to 19.2 MHz and pump it out on pin GPIO_WK31. 136 * We know the SYS_CLK is 38.4Mhz and therefore to get the needed 19.2Mhz, 137 * just use a 2x divider and ensure the SYS_CLK is used as the source. 138 */ 139 REG_WRITE32(scrm_addr + SCRM_AUXCLK3, (1 << 16) | /* Divider of 2 */ 140 (0 << 1) | /* Use the SYS_CLK as the source */ 141 (1 << 8)); /* Enable the clock */ 142 143 /* Enable the clock out to the pin (GPIO_WK31). 144 * muxmode=fref_clk3_out, pullup/down=disabled, input buffer=disabled, 145 * wakeup=disabled. 146 */ 147 REG_WRITE16(scm_addr + CONTROL_WKUP_PAD0_FREF_CLK3_OUT, 0x0000); 148 149 150 /* Disable the power to the USB hub, drive GPIO1 low */ 151 REG_WRITE32(gpio1_addr + GPIO1_OE, REG_READ32(gpio1_addr + 152 GPIO1_OE) & ~(1UL << 1)); 153 REG_WRITE32(gpio1_addr + GPIO1_CLEARDATAOUT, (1UL << 1)); 154 REG_WRITE16(scm_addr + CONTROL_CORE_PAD1_KPD_COL2, 0x0003); 155 156 157 /* Reset the USB PHY and Hub using GPIO_62 */ 158 REG_WRITE32(gpio2_addr + GPIO2_OE, 159 REG_READ32(gpio2_addr + GPIO2_OE) & ~(1UL << 30)); 160 REG_WRITE32(gpio2_addr + GPIO2_CLEARDATAOUT, (1UL << 30)); 161 REG_WRITE16(scm_addr + CONTROL_CORE_PAD0_GPMC_WAIT1, 0x0003); 162 DELAY(10); 163 REG_WRITE32(gpio2_addr + GPIO2_SETDATAOUT, (1UL << 30)); 164 165 166 /* Enable power to the hub (GPIO_1) */ 167 REG_WRITE32(gpio1_addr + GPIO1_SETDATAOUT, (1UL << 1)); 168 bus_space_unmap(fdtbus_bs_tag, scrm_addr, OMAP44XX_SCRM_SIZE); 169 bus_space_unmap(fdtbus_bs_tag, gpio1_addr, OMAP44XX_GPIO1_SIZE); 170 bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE); 171 bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE); 172 } 173 174 /** 175 * board_init - initialises the pandaboard 176 * @dummy: ignored 177 * 178 * This function is called before any of the driver are initialised, which is 179 * annoying because it means we can't use the SCM, PRCM and GPIO modules which 180 * would really be useful. 181 * 182 * So we don't have: 183 * - any drivers 184 * - no interrupts 185 * 186 * What we do have: 187 * - virt/phys mappings from the devmap (see omap4.c) 188 * - 189 * 190 * 191 * So we are hamstrung without the useful drivers and we have to go back to 192 * direct register manupulation. Luckly we don't have to do to much, basically 193 * just setup the usb hub/ethernet. 194 * 195 */ 196 static void 197 board_init(void *dummy) 198 { 199 /* Initialise the USB phy and hub */ 200 usb_hub_init(); 201 202 /* 203 * XXX Board identification e.g. read out from FPGA or similar should 204 * go here 205 */ 206 } 207 208 SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL); 209