Path: blob/master/arch/avr32/boards/hammerhead/flash.c
10819 views
/*1* Hammerhead board-specific flash initialization2*3* Copyright (C) 2008 Miromico AG4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License version 2 as7* published by the Free Software Foundation.8*/910#include <linux/init.h>11#include <linux/platform_device.h>12#include <linux/mtd/mtd.h>13#include <linux/mtd/partitions.h>14#include <linux/mtd/physmap.h>15#include <linux/usb/isp116x.h>16#include <linux/dma-mapping.h>17#include <linux/delay.h>1819#include <mach/portmux.h>20#include <mach/at32ap700x.h>21#include <mach/smc.h>2223#include "../../mach-at32ap/clock.h"24#include "flash.h"252627#define HAMMERHEAD_USB_PERIPH_GCLK0 0x4000000028#define HAMMERHEAD_USB_PERIPH_CS2 0x0200000029#define HAMMERHEAD_USB_PERIPH_EXTINT0 0x020000003031#define HAMMERHEAD_FPGA_PERIPH_MOSI 0x0000000232#define HAMMERHEAD_FPGA_PERIPH_SCK 0x0000002033#define HAMMERHEAD_FPGA_PERIPH_EXTINT3 0x100000003435static struct smc_timing flash_timing __initdata = {36.ncs_read_setup = 0,37.nrd_setup = 40,38.ncs_write_setup = 0,39.nwe_setup = 10,4041.ncs_read_pulse = 80,42.nrd_pulse = 40,43.ncs_write_pulse = 65,44.nwe_pulse = 55,4546.read_cycle = 120,47.write_cycle = 120,48};4950static struct smc_config flash_config __initdata = {51.bus_width = 2,52.nrd_controlled = 1,53.nwe_controlled = 1,54.byte_write = 1,55};5657static struct mtd_partition flash_parts[] = {58{59.name = "u-boot",60.offset = 0x00000000,61.size = 0x00020000, /* 128 KiB */62.mask_flags = MTD_WRITEABLE,63},64{65.name = "root",66.offset = 0x00020000,67.size = 0x007d0000,68},69{70.name = "env",71.offset = 0x007f0000,72.size = 0x00010000,73.mask_flags = MTD_WRITEABLE,74},75};7677static struct physmap_flash_data flash_data = {78.width = 2,79.nr_parts = ARRAY_SIZE(flash_parts),80.parts = flash_parts,81};8283static struct resource flash_resource = {84.start = 0x00000000,85.end = 0x007fffff,86.flags = IORESOURCE_MEM,87};8889static struct platform_device flash_device = {90.name = "physmap-flash",91.id = 0,92.resource = &flash_resource,93.num_resources = 1,94.dev = { .platform_data = &flash_data, },95};9697#ifdef CONFIG_BOARD_HAMMERHEAD_USB9899static struct smc_timing isp1160_timing __initdata = {100.ncs_read_setup = 75,101.nrd_setup = 75,102.ncs_write_setup = 75,103.nwe_setup = 75,104105106/* We use conservative timing settings, as the minimal settings aren't107stable. There may be room for tweaking. */108.ncs_read_pulse = 75, /* min. 33ns */109.nrd_pulse = 75, /* min. 33ns */110.ncs_write_pulse = 75, /* min. 26ns */111.nwe_pulse = 75, /* min. 26ns */112113.read_cycle = 225, /* min. 143ns */114.write_cycle = 225, /* min. 136ns */115};116117static struct smc_config isp1160_config __initdata = {118.bus_width = 2,119.nrd_controlled = 1,120.nwe_controlled = 1,121.byte_write = 0,122};123124/*125* The platform delay function is only used to enforce the strange126* read to write delay. This can not be configured in the SMC. All other127* timings are controlled by the SMC (see timings obove)128* So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY129*/130void isp116x_delay(struct device *dev, int delay)131{132if (delay > 150)133ndelay(delay - 150);134}135136static struct isp116x_platform_data isp1160_data = {137.sel15Kres = 1, /* use internal downstream resistors */138.oc_enable = 0, /* external overcurrent detection */139.int_edge_triggered = 0, /* interrupt is level triggered */140.int_act_high = 0, /* interrupt is active low */141.delay = isp116x_delay, /* platform delay function */142};143144static struct resource isp1160_resource[] = {145{146.start = 0x08000000,147.end = 0x08000001,148.flags = IORESOURCE_MEM,149},150{151.start = 0x08000002,152.end = 0x08000003,153.flags = IORESOURCE_MEM,154},155{156.start = 64,157.flags = IORESOURCE_IRQ,158},159};160161static struct platform_device isp1160_device = {162.name = "isp116x-hcd",163.id = 0,164.resource = isp1160_resource,165.num_resources = 3,166.dev = {167.platform_data = &isp1160_data,168},169};170#endif171172#ifdef CONFIG_BOARD_HAMMERHEAD_USB173static int __init hammerhead_usbh_init(void)174{175struct clk *gclk;176struct clk *osc;177178int ret;179180/* setup smc for usbh */181smc_set_timing(&isp1160_config, &isp1160_timing);182ret = smc_set_configuration(2, &isp1160_config);183184if (ret < 0) {185printk(KERN_ERR186"hammerhead: failed to set ISP1160 USBH timing\n");187return ret;188}189190/* setup gclk0 to run from osc1 */191gclk = clk_get(NULL, "gclk0");192if (IS_ERR(gclk))193goto err_gclk;194195osc = clk_get(NULL, "osc1");196if (IS_ERR(osc))197goto err_osc;198199if (clk_set_parent(gclk, osc)) {200pr_debug("hammerhead: failed to set osc1 for USBH clock\n");201goto err_set_clk;202}203204/* set clock to 6MHz */205clk_set_rate(gclk, 6000000);206207/* and enable */208clk_enable(gclk);209210/* select GCLK0 peripheral function */211at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0,212GPIO_PERIPH_A, 0);213214/* enable CS2 peripheral function */215at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2,216GPIO_PERIPH_A, 0);217218/* H_WAKEUP must be driven low */219at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT);220221/* Select EXTINT0 for PB25 */222at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0,223GPIO_PERIPH_A, 0);224225/* register usbh device driver */226platform_device_register(&isp1160_device);227228err_set_clk:229clk_put(osc);230err_osc:231clk_put(gclk);232err_gclk:233return ret;234}235#endif236237#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA238static struct smc_timing fpga_timing __initdata = {239.ncs_read_setup = 16,240.nrd_setup = 32,241.ncs_read_pulse = 48,242.nrd_pulse = 32,243.read_cycle = 64,244245.ncs_write_setup = 16,246.nwe_setup = 16,247.ncs_write_pulse = 32,248.nwe_pulse = 32,249.write_cycle = 64,250};251252static struct smc_config fpga_config __initdata = {253.bus_width = 4,254.nrd_controlled = 1,255.nwe_controlled = 1,256.byte_write = 0,257};258259static struct resource hh_fpga0_resource[] = {260{261.start = 0xffe00400,262.end = 0xffe00400 + 0x3ff,263.flags = IORESOURCE_MEM,264},265{266.start = 4,267.end = 4,268.flags = IORESOURCE_IRQ,269},270{271.start = 0x0c000000,272.end = 0x0c000100,273.flags = IORESOURCE_MEM,274},275{276.start = 67,277.end = 67,278.flags = IORESOURCE_IRQ,279},280};281282static u64 hh_fpga0_dma_mask = DMA_BIT_MASK(32);283static struct platform_device hh_fpga0_device = {284.name = "hh_fpga",285.id = 0,286.dev = {287.dma_mask = &hh_fpga0_dma_mask,288.coherent_dma_mask = DMA_BIT_MASK(32),289},290.resource = hh_fpga0_resource,291.num_resources = ARRAY_SIZE(hh_fpga0_resource),292};293294static struct clk hh_fpga0_spi_clk = {295.name = "spi_clk",296.dev = &hh_fpga0_device.dev,297.mode = pba_clk_mode,298.get_rate = pba_clk_get_rate,299.index = 1,300};301302struct platform_device *__init at32_add_device_hh_fpga(void)303{304/* Select peripheral functionallity for SPI SCK and MOSI */305at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK,306GPIO_PERIPH_B, 0);307at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI,308GPIO_PERIPH_B, 0);309310/* reserve all other needed gpio311* We have on board pull ups, so there is no need312* to enable gpio pull ups */313/* INIT_DONE (input) */314at32_select_gpio(GPIO_PIN_PB(0), 0);315316/* nSTATUS (input) */317at32_select_gpio(GPIO_PIN_PB(2), 0);318319/* nCONFIG (output, low) */320at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT);321322/* CONF_DONE (input) */323at32_select_gpio(GPIO_PIN_PB(4), 0);324325/* Select EXTINT3 for PB28 (Interrupt from FPGA) */326at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3,327GPIO_PERIPH_A, 0);328329/* Get our parent clock */330hh_fpga0_spi_clk.parent = clk_get(NULL, "pba");331clk_put(hh_fpga0_spi_clk.parent);332333/* Register clock in at32 clock tree */334at32_clk_register(&hh_fpga0_spi_clk);335336platform_device_register(&hh_fpga0_device);337return &hh_fpga0_device;338}339#endif340341/* This needs to be called after the SMC has been initialized */342static int __init hammerhead_flash_init(void)343{344int ret;345346smc_set_timing(&flash_config, &flash_timing);347ret = smc_set_configuration(0, &flash_config);348349if (ret < 0) {350printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n");351return ret;352}353354platform_device_register(&flash_device);355356#ifdef CONFIG_BOARD_HAMMERHEAD_USB357hammerhead_usbh_init();358#endif359360#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA361/* Setup SMC for FPGA interface */362smc_set_timing(&fpga_config, &fpga_timing);363ret = smc_set_configuration(3, &fpga_config);364#endif365366367if (ret < 0) {368printk(KERN_ERR "hammerhead: failed to set FPGA timing\n");369return ret;370}371372return 0;373}374375device_initcall(hammerhead_flash_init);376377378