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                goto err_gclk;
 195
 196        osc = clk_get(NULL, "osc1");
 197        if (IS_ERR(osc))
 198                goto err_osc;
 199
 200        if (clk_set_parent(gclk, osc)) {
 201                pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
 202                goto err_set_clk;
 203        }
 204
 205        /* set clock to 6MHz */
 206        clk_set_rate(gclk, 6000000);
 207
 208        /* and enable */
 209        clk_enable(gclk);
 210
 211        /* select GCLK0 peripheral function */
 212        at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0,
 213                           GPIO_PERIPH_A, 0);
 214
 215        /* enable CS2 peripheral function */
 216        at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2,
 217                           GPIO_PERIPH_A, 0);
 218
 219        /* H_WAKEUP must be driven low */
 220        at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT);
 221
 222        /* Select EXTINT0 for PB25 */
 223        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0,
 224                           GPIO_PERIPH_A, 0);
 225
 226        /* register usbh device driver */
 227        platform_device_register(&isp1160_device);
 228
 229 err_set_clk:
 230        clk_put(osc);
 231 err_osc:
 232        clk_put(gclk);
 233 err_gclk:
 234        return ret;
 235}
 236#endif
 237
 238#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
 239static struct smc_timing fpga_timing __initdata = {
 240        .ncs_read_setup         = 16,
 241        .nrd_setup              = 32,
 242        .ncs_read_pulse         = 48,
 243        .nrd_pulse              = 32,
 244        .read_cycle             = 64,
 245
 246        .ncs_write_setup        = 16,
 247        .nwe_setup              = 16,
 248        .ncs_write_pulse        = 32,
 249        .nwe_pulse              = 32,
 250        .write_cycle            = 64,
 251};
 252
 253static struct smc_config fpga_config __initdata = {
 254        .bus_width              = 4,
 255        .nrd_controlled         = 1,
 256        .nwe_controlled         = 1,
 257        .byte_write             = 0,
 258};
 259
 260static struct resource hh_fpga0_resource[] = {
 261        {
 262                .start          = 0xffe00400,
 263                .end            = 0xffe00400 + 0x3ff,
 264                .flags          = IORESOURCE_MEM,
 265        },
 266        {
 267                .start          = 4,
 268                .end            = 4,
 269                .flags          = IORESOURCE_IRQ,
 270        },
 271        {
 272                .start          = 0x0c000000,
 273                .end            = 0x0c000100,
 274                .flags          = IORESOURCE_MEM,
 275        },
 276        {
 277                .start          = 67,
 278                .end            = 67,
 279                .flags          = IORESOURCE_IRQ,
 280        },
 281};
 282
 283static u64 hh_fpga0_dma_mask = DMA_BIT_MASK(32);
 284static struct platform_device hh_fpga0_device = {
 285        .name           = "hh_fpga",
 286        .id             = 0,
 287        .dev            = {
 288                .dma_mask = &hh_fpga0_dma_mask,
 289                .coherent_dma_mask = DMA_BIT_MASK(32),
 290        },
 291        .resource       = hh_fpga0_resource,
 292        .num_resources  = ARRAY_SIZE(hh_fpga0_resource),
 293};
 294
 295static struct clk hh_fpga0_spi_clk = {
 296        .name           = "spi_clk",
 297        .dev            = &hh_fpga0_device.dev,
 298        .mode           = pba_clk_mode,
 299        .get_rate       = pba_clk_get_rate,
 300        .index          = 1,
 301};
 302
 303struct platform_device *__init at32_add_device_hh_fpga(void)
 304{
 305        /* Select peripheral functionallity for SPI SCK and MOSI */
 306        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK,
 307                           GPIO_PERIPH_B, 0);
 308        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI,
 309                           GPIO_PERIPH_B, 0);
 310
 311        /* reserve all other needed gpio
 312         * We have on board pull ups, so there is no need
 313         * to enable gpio pull ups */
 314        /* INIT_DONE (input) */
 315        at32_select_gpio(GPIO_PIN_PB(0), 0);
 316
 317        /* nSTATUS (input) */
 318        at32_select_gpio(GPIO_PIN_PB(2), 0);
 319
 320        /* nCONFIG (output, low) */
 321        at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT);
 322
 323        /* CONF_DONE (input) */
 324        at32_select_gpio(GPIO_PIN_PB(4), 0);
 325
 326        /* Select EXTINT3 for PB28 (Interrupt from FPGA) */
 327        at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3,
 328                           GPIO_PERIPH_A, 0);
 329
 330        /* Get our parent clock */
 331        hh_fpga0_spi_clk.parent = clk_get(NULL, "pba");
 332        clk_put(hh_fpga0_spi_clk.parent);
 333
 334        /* Register clock in at32 clock tree */
 335        at32_clk_register(&hh_fpga0_spi_clk);
 336
 337        platform_device_register(&hh_fpga0_device);
 338        return &hh_fpga0_device;
 339}
 340#endif
 341
 342/* This needs to be called after the SMC has been initialized */
 343static int __init hammerhead_flash_init(void)
 344{
 345        int ret;
 346
 347        smc_set_timing(&flash_config, &flash_timing);
 348        ret = smc_set_configuration(0, &flash_config);
 349
 350        if (ret < 0) {
 351                printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n");
 352                return ret;
 353        }
 354
 355        platform_device_register(&flash_device);
 356
 357#ifdef CONFIG_BOARD_HAMMERHEAD_USB
 358        hammerhead_usbh_init();
 359#endif
 360
 361#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
 362        /* Setup SMC for FPGA interface */
 363        smc_set_timing(&fpga_config, &fpga_timing);
 364        ret = smc_set_configuration(3, &fpga_config);
 365#endif
 366
 367
 368        if (ret < 0) {
 369                printk(KERN_ERR "hammerhead: failed to set FPGA timing\n");
 370                return ret;
 371        }
 372
 373        return 0;
 374}
 375
 376device_initcall(hammerhead_flash_init);
 377