linux/arch/avr32/boards/hammerhead/setup.c
<<
>>
Prefs
   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_pdata __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 macb_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 (IS_ERR(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, &eth_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