linux/arch/avr32/boards/hammerhead/flash.c
<<
>>
Prefs
   1/*
   2 * Hammerhead board-specific flash initialization
   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
  11#include <linux/init.h>
  12#include <linux/platform_device.h>
  13#include <linux/mtd/mtd.h>
  14#include <linux/mtd/partitions.h>
  15#include <linux/mtd/physmap.h>
  16#include <linux/usb/isp116x.h>
  17#include <linux/dma-mapping.h>
  18#include <linux/delay.h>
  19
  20#include <mach/portmux.h>
  21#include <mach/at32ap700x.h>
  22#include <mach/smc.h>
  23
  24#include "../../mach-at32ap/clock.h"
  25#include "flash.h"
  26
  27
  28#define HAMMERHEAD_USB_PERIPH_GCLK0     0x40000000
  29#define HAMMERHEAD_USB_PERIPH_CS2       0x02000000
  30#define HAMMERHEAD_USB_PERIPH_EXTINT0   0x02000000
  31
  32#define HAMMERHEAD_FPGA_PERIPH_MOSI     0x00000002
  33#define HAMMERHEAD_FPGA_PERIPH_SCK      0x00000020
  34#define HAMMERHEAD_FPGA_PERIPH_EXTINT3  0x10000000
  35
  36static struct smc_timing flash_timing __initdata = {
  37        .ncs_read_setup         = 0,
  38        .nrd_setup              = 40,
  39        .ncs_write_setup        = 0,
  40        .nwe_setup              = 10,
  41
  42        .ncs_read_pulse         = 80,
  43        .nrd_pulse              = 40,
  44        .ncs_write_pulse        = 65,
  45        .nwe_pulse              = 55,
  46
  47        .read_cycle             = 120,
  48        .write_cycle            = 120,
  49};
  50
  51static struct smc_config flash_config __initdata = {
  52        .bus_width              = 2,
  53        .nrd_controlled         = 1,
  54        .nwe_controlled         = 1,
  55        .byte_write             = 1,
  56};
  57
  58static struct mtd_partition flash_parts[] = {
  59        {
  60                .name           = "u-boot",
  61                .offset         = 0x00000000,
  62                .size           = 0x00020000,           /* 128 KiB */
  63                .mask_flags     = MTD_WRITEABLE,
  64        },
  65        {
  66                .name           = "root",
  67                .offset         = 0x00020000,
  68                .size           = 0x007d0000,
  69        },
  70        {
  71                .name           = "env",
  72                .offset         = 0x007f0000,
  73                .size           = 0x00010000,
  74                .mask_flags     = MTD_WRITEABLE,
  75        },
  76};
  77
  78static struct physmap_flash_data flash_data = {
  79        .width          = 2,
  80        .nr_parts       = ARRAY_SIZE(flash_parts),
  81        .parts          = flash_parts,
  82};
  83
  84static struct resource flash_resource = {
  85        .start          = 0x00000000,
  86        .end            = 0x007fffff,
  87        .flags          = IORESOURCE_MEM,
  88};
  89
  90static struct platform_device flash_device = {
  91        .name           = "physmap-flash",
  92        .id             = 0,
  93        .resource       = &flash_resource,
  94        .num_resources  = 1,
  95        .dev            = { .platform_data = &flash_data, },
  96};
  97
  98#ifdef CONFIG_BOARD_HAMMERHEAD_USB
  99
 100static struct smc_timing isp1160_timing __initdata = {
 101        .ncs_read_setup         = 75,
 102        .nrd_setup              = 75,
 103        .ncs_write_setup        = 75,
 104        .nwe_setup              = 75,
 105
 106
 107        /* We use conservative timing settings, as the minimal settings aren't
 108           stable. There may be room for tweaking. */
 109        .ncs_read_pulse         = 75,  /* min. 33ns */
 110        .nrd_pulse              = 75,  /* min. 33ns */
 111        .ncs_write_pulse        = 75,  /* min. 26ns */
 112        .nwe_pulse              = 75,  /* min. 26ns */
 113
 114        .read_cycle             = 225, /* min. 143ns */
 115        .write_cycle            = 225, /* min. 136ns */
 116};
 117
 118static struct smc_config isp1160_config __initdata = {
 119        .bus_width              = 2,
 120        .nrd_controlled         = 1,
 121        .nwe_controlled         = 1,
 122        .byte_write             = 0,
 123};
 124
 125/*
 126 * The platform delay function is only used to enforce the strange
 127 * read to write delay. This can not be configured in the SMC. All other
 128 * timings are controlled by the SMC (see timings obove)
 129 * So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY
 130 */
 131void isp116x_delay(struct device *dev, int delay)
 132{
 133        if (delay > 150)
 134                ndelay(delay - 150);
 135}
 136
 137static struct  isp116x_platform_data isp1160_data = {
 138        .sel15Kres              = 1,    /* use internal downstream resistors */
 139        .oc_enable              = 0,    /* external overcurrent detection */
 140        .int_edge_triggered     = 0,    /* interrupt is level triggered */
 141        .int_act_high           = 0,    /* interrupt is active low */
 142        .delay = isp116x_delay,         /* platform delay function */
 143};
 144
 145static struct resource isp1160_resource[] = {
 146        {
 147                .start          = 0x08000000,
 148                .end            = 0x08000001,
 149                .flags          = IORESOURCE_MEM,
 150        },
 151        {
 152                .start          = 0x08000002,
 153                .end            = 0x08000003,
 154                .flags          = IORESOURCE_MEM,
 155        },
 156        {
 157                .start          = 64,
 158                .flags          = IORESOURCE_IRQ,
 159        },
 160};
 161
 162static struct platform_device isp1160_device = {
 163        .name           = "isp116x-hcd",
 164        .id             = 0,
 165        .resource       = isp1160_resource,
 166        .num_resources  = 3,
 167        .dev            = {
 168                .platform_data = &isp1160_data,
 169        },
 170};
 171#endif
 172
 173#ifdef CONFIG_BOARD_HAMMERHEAD_USB
 174static int __init hammerhead_usbh_init(void)
 175{
 176        struct clk *gclk;
 177        struct clk *osc;
 178
 179        int ret;
 180
 181        /* setup smc for usbh */
 182        smc_set_timing(&isp1160_config, &isp1160_timing);
 183        ret = smc_set_configuration(2, &isp1160_config);
 184
 185        if (ret < 0) {
 186                printk(KERN_ERR
 187                       "hammerhead: failed to set ISP1160 USBH timing\n");
 188                return ret;
 189        }
 190
 191        /* setup gclk0 to run from osc1 */
 192        gclk = clk_get(NULL, "gclk0");
 193        if (IS_ERR(gclk)) {
 194                ret = PTR_ERR(gclk);
 195                goto err_gclk;
 196        }
 197
 198        osc = clk_get(NULL, "osc1");
 199        if (IS_ERR(osc)) {
 200                ret = PTR_ERR(osc);
 201                goto err_osc;
 202        }
 203
 204        ret = clk_set_parent(gclk, osc);
 205        if (ret < 0) {
 206                pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
 207                goto err_set_clk;
 208        }
 209
 210        /* set clock to 6MHz */
 211        clk_set_rate(gclk, 6000000);
 212
 213        /* and enable */
 214        clk_enable(gclk);
 215
 216        /* select GCLK0 peripheral function */
 217        at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0,
 218                           GPIO_PERIPH_A, 0);
 219
 220        /* enable CS2 peripheral function */
 221        at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2,
 222                           GPIO_PERIPH_A, 0);
 223
 224        /* H_WAKEUP must be driven low */
 225        at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT);
 226
 227        /* Select EXTINT0 for PB25 */
 228        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0,
 229                           GPIO_PERIPH_A, 0);
 230
 231        /* register usbh device driver */
 232        platform_device_register(&isp1160_device);
 233
 234 err_set_clk:
 235        clk_put(osc);
 236 err_osc:
 237        clk_put(gclk);
 238 err_gclk:
 239        return ret;
 240}
 241#endif
 242
 243#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
 244static struct smc_timing fpga_timing __initdata = {
 245        .ncs_read_setup         = 16,
 246        .nrd_setup              = 32,
 247        .ncs_read_pulse         = 48,
 248        .nrd_pulse              = 32,
 249        .read_cycle             = 64,
 250
 251        .ncs_write_setup        = 16,
 252        .nwe_setup              = 16,
 253        .ncs_write_pulse        = 32,
 254        .nwe_pulse              = 32,
 255        .write_cycle            = 64,
 256};
 257
 258static struct smc_config fpga_config __initdata = {
 259        .bus_width              = 4,
 260        .nrd_controlled         = 1,
 261        .nwe_controlled         = 1,
 262        .byte_write             = 0,
 263};
 264
 265static struct resource hh_fpga0_resource[] = {
 266        {
 267                .start          = 0xffe00400,
 268                .end            = 0xffe00400 + 0x3ff,
 269                .flags          = IORESOURCE_MEM,
 270        },
 271        {
 272                .start          = 4,
 273                .end            = 4,
 274                .flags          = IORESOURCE_IRQ,
 275        },
 276        {
 277                .start          = 0x0c000000,
 278                .end            = 0x0c000100,
 279                .flags          = IORESOURCE_MEM,
 280        },
 281        {
 282                .start          = 67,
 283                .end            = 67,
 284                .flags          = IORESOURCE_IRQ,
 285        },
 286};
 287
 288static u64 hh_fpga0_dma_mask = DMA_BIT_MASK(32);
 289static struct platform_device hh_fpga0_device = {
 290        .name           = "hh_fpga",
 291        .id             = 0,
 292        .dev            = {
 293                .dma_mask = &hh_fpga0_dma_mask,
 294                .coherent_dma_mask = DMA_BIT_MASK(32),
 295        },
 296        .resource       = hh_fpga0_resource,
 297        .num_resources  = ARRAY_SIZE(hh_fpga0_resource),
 298};
 299
 300static struct clk hh_fpga0_spi_clk = {
 301        .name           = "spi_clk",
 302        .dev            = &hh_fpga0_device.dev,
 303        .mode           = pba_clk_mode,
 304        .get_rate       = pba_clk_get_rate,
 305        .index          = 1,
 306};
 307
 308struct platform_device *__init at32_add_device_hh_fpga(void)
 309{
 310        /* Select peripheral functionallity for SPI SCK and MOSI */
 311        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK,
 312                           GPIO_PERIPH_B, 0);
 313        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI,
 314                           GPIO_PERIPH_B, 0);
 315
 316        /* reserve all other needed gpio
 317         * We have on board pull ups, so there is no need
 318         * to enable gpio pull ups */
 319        /* INIT_DONE (input) */
 320        at32_select_gpio(GPIO_PIN_PB(0), 0);
 321
 322        /* nSTATUS (input) */
 323        at32_select_gpio(GPIO_PIN_PB(2), 0);
 324
 325        /* nCONFIG (output, low) */
 326        at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT);
 327
 328        /* CONF_DONE (input) */
 329        at32_select_gpio(GPIO_PIN_PB(4), 0);
 330
 331        /* Select EXTINT3 for PB28 (Interrupt from FPGA) */
 332        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3,
 333                           GPIO_PERIPH_A, 0);
 334
 335        /* Get our parent clock */
 336        hh_fpga0_spi_clk.parent = clk_get(NULL, "pba");
 337        clk_put(hh_fpga0_spi_clk.parent);
 338
 339        /* Register clock in at32 clock tree */
 340        at32_clk_register(&hh_fpga0_spi_clk);
 341
 342        platform_device_register(&hh_fpga0_device);
 343        return &hh_fpga0_device;
 344}
 345#endif
 346
 347/* This needs to be called after the SMC has been initialized */
 348static int __init hammerhead_flash_init(void)
 349{
 350        int ret;
 351
 352        smc_set_timing(&flash_config, &flash_timing);
 353        ret = smc_set_configuration(0, &flash_config);
 354
 355        if (ret < 0) {
 356                printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n");
 357                return ret;
 358        }
 359
 360        platform_device_register(&flash_device);
 361
 362#ifdef CONFIG_BOARD_HAMMERHEAD_USB
 363        hammerhead_usbh_init();
 364#endif
 365
 366#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
 367        /* Setup SMC for FPGA interface */
 368        smc_set_timing(&fpga_config, &fpga_timing);
 369        ret = smc_set_configuration(3, &fpga_config);
 370#endif
 371
 372
 373        if (ret < 0) {
 374                printk(KERN_ERR "hammerhead: failed to set FPGA timing\n");
 375                return ret;
 376        }
 377
 378        return 0;
 379}
 380
 381device_initcall(hammerhead_flash_init);
 382