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