1/* 2 * Board-specific setup code for the Miromico Hammerhead board 3 * 4 * Copyright (C) 2008 Miromico AG 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/atmel-mci.h> 11#include <linux/clk.h> 12#include <linux/fb.h> 13#include <linux/etherdevice.h> 14#include <linux/i2c.h> 15#include <linux/i2c-gpio.h> 16#include <linux/init.h> 17#include <linux/linkage.h> 18#include <linux/platform_device.h> 19#include <linux/types.h> 20#include <linux/spi/spi.h> 21 22#include <video/atmel_lcdc.h> 23 24#include <linux/io.h> 25#include <asm/setup.h> 26 27#include <mach/at32ap700x.h> 28#include <mach/board.h> 29#include <mach/init.h> 30#include <mach/portmux.h> 31 32#include <sound/atmel-ac97c.h> 33 34#include "../../mach-at32ap/clock.h" 35#include "flash.h" 36 37/* Oscillator frequencies. These are board-specific */ 38unsigned long at32_board_osc_rates[3] = { 39 [0] = 32768, /* 32.768 kHz on RTC osc */ 40 [1] = 25000000, /* 25MHz on osc0 */ 41 [2] = 12000000, /* 12 MHz on osc1 */ 42}; 43 44/* Initialized by bootloader-specific startup code. */ 45struct tag *bootloader_tags __initdata; 46 47#ifdef CONFIG_BOARD_HAMMERHEAD_LCD 48static struct fb_videomode __initdata hda350tlv_modes[] = { 49 { 50 .name = "320x240 @ 75", 51 .refresh = 75, 52 .xres = 320, 53 .yres = 240, 54 .pixclock = KHZ2PICOS(6891), 55 56 .left_margin = 48, 57 .right_margin = 18, 58 .upper_margin = 18, 59 .lower_margin = 4, 60 .hsync_len = 20, 61 .vsync_len = 2, 62 63 .sync = 0, 64 .vmode = FB_VMODE_NONINTERLACED, 65 }, 66}; 67 68static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = { 69 .manufacturer = "HAN", 70 .monitor = "HDA350T-LV", 71 .modedb = hda350tlv_modes, 72 .modedb_len = ARRAY_SIZE(hda350tlv_modes), 73 .hfmin = 14900, 74 .hfmax = 22350, 75 .vfmin = 60, 76 .vfmax = 90, 77 .dclkmax = 10000000, 78}; 79 80struct atmel_lcdfb_info __initdata hammerhead_lcdc_data = { 81 .default_bpp = 24, 82 .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, 83 .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT 84 | ATMEL_LCDC_INVCLK 85 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE 86 | ATMEL_LCDC_MEMOR_BIG), 87 .default_monspecs = &hammerhead_hda350t_monspecs, 88 .guard_time = 2, 89}; 90#endif 91 92static struct mci_platform_data __initdata mci0_data = { 93 .slot[0] = { 94 .bus_width = 4, 95 .detect_pin = -ENODEV, 96 .wp_pin = -ENODEV, 97 }, 98}; 99 100struct eth_addr { 101 u8 addr[6]; 102}; 103 104static struct eth_addr __initdata hw_addr[1]; 105static struct eth_platform_data __initdata eth_data[1]; 106 107/* 108 * The next two functions should go away as the boot loader is 109 * supposed to initialize the macb address registers with a valid 110 * ethernet address. But we need to keep it around for a while until 111 * we can be reasonably sure the boot loader does this. 112 * 113 * The phy_id is ignored as the driver will probe for it. 114 */ 115static int __init parse_tag_ethernet(struct tag *tag) 116{ 117 int i = tag->u.ethernet.mac_index; 118 119 if (i < ARRAY_SIZE(hw_addr)) 120 memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address, 121 sizeof(hw_addr[i].addr)); 122 123 return 0; 124} 125__tagtable(ATAG_ETHERNET, parse_tag_ethernet); 126 127static void __init set_hw_addr(struct platform_device *pdev) 128{ 129 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 130 const u8 *addr; 131 void __iomem *regs; 132 struct clk *pclk; 133 134 if (!res) 135 return; 136 137 if (pdev->id >= ARRAY_SIZE(hw_addr)) 138 return; 139 140 addr = hw_addr[pdev->id].addr; 141 142 if (!is_valid_ether_addr(addr)) 143 return; 144 145 /* 146 * Since this is board-specific code, we'll cheat and use the 147 * physical address directly as we happen to know that it's 148 * the same as the virtual address. 149 */ 150 regs = (void __iomem __force *)res->start; 151 pclk = clk_get(&pdev->dev, "pclk"); 152 153 if (!pclk) 154 return; 155 156 clk_enable(pclk); 157 158 __raw_writel((addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | 159 addr[0], regs + 0x98); 160 __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c); 161 162 clk_disable(pclk); 163 clk_put(pclk); 164} 165 166void __init setup_board(void) 167{ 168 at32_map_usart(1, 0, 0); /* USART 1: /dev/ttyS0, DB9 */ 169 at32_setup_serial_console(0); 170} 171 172static struct i2c_gpio_platform_data i2c_gpio_data = { 173 .sda_pin = GPIO_PIN_PA(6), 174 .scl_pin = GPIO_PIN_PA(7), 175 .sda_is_open_drain = 1, 176 .scl_is_open_drain = 1, 177 .udelay = 2, /* close to 100 kHz */ 178}; 179 180static struct platform_device i2c_gpio_device = { 181 .name = "i2c-gpio", 182 .id = 0, 183 .dev = { .platform_data = &i2c_gpio_data, }, 184}; 185 186static struct i2c_board_info __initdata i2c_info[] = {}; 187 188#ifdef CONFIG_BOARD_HAMMERHEAD_SND 189static struct ac97c_platform_data ac97c_data = { 190 .reset_pin = GPIO_PIN_PA(16), 191}; 192#endif 193 194static int __init hammerhead_init(void) 195{ 196 /* 197 * Hammerhead uses 32-bit SDRAM interface. Reserve the 198 * SDRAM-specific pins so that nobody messes with them. 199 */ 200 at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL); 201 202 at32_add_device_usart(0); 203 204 /* Reserve PB29 (GCLK3). This pin is used as clock source 205 * for ETH PHY (25MHz). GCLK3 setup is done by U-Boot. 206 */ 207 at32_reserve_pin(GPIO_PIOB_BASE, (1<<29)); 208 209 /* 210 * Hammerhead uses only one ethernet port, so we don't set 211 * address of second port 212 */ 213 set_hw_addr(at32_add_device_eth(0, ð_data[0])); 214 215#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA 216 at32_add_device_hh_fpga(); 217#endif 218 at32_add_device_mci(0, &mci0_data); 219 220#ifdef CONFIG_BOARD_HAMMERHEAD_USB 221 at32_add_device_usba(0, NULL); 222#endif 223#ifdef CONFIG_BOARD_HAMMERHEAD_LCD 224 at32_add_device_lcdc(0, &hammerhead_lcdc_data, fbmem_start, 225 fbmem_size, ATMEL_LCDC_PRI_24BIT); 226#endif 227 228 at32_select_gpio(i2c_gpio_data.sda_pin, 229 AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | 230 AT32_GPIOF_HIGH); 231 at32_select_gpio(i2c_gpio_data.scl_pin, 232 AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | 233 AT32_GPIOF_HIGH); 234 platform_device_register(&i2c_gpio_device); 235 i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info)); 236 237#ifdef CONFIG_BOARD_HAMMERHEAD_SND 238 at32_add_device_ac97c(0, &ac97c_data, AC97C_BOTH); 239#endif 240 241 /* Select the Touchscreen interrupt pin mode */ 242 at32_select_periph(GPIO_PIOB_BASE, 0x08000000, GPIO_PERIPH_A, 0); 243 244 return 0; 245} 246 247postcore_initcall(hammerhead_init); 248