/* * arch/sh/boards/mach-adi7108/setup.c * * Copyright (C) 2011 STMicroelectronics Limited * Author: Srinivas Kandagatla (srinivas.kandagatla@st.com) * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ADI7108_PIO_POWER_ON_ETHERNET0 stm_gpio(19, 7) #define ADI7108_PIO_POWER_ON_ETHERNET1 stm_gpio(15, 4) #define ADI7108_GPIO_MII1_SPEED_SEL stm_gpio(21, 7) static void __init adi7108_setup(char **cmdline_p) { printk(KERN_INFO "STMicroelectronics STi7108-ADI Board " "initialisation\n"); stx7108_early_device_init(); stx7108_configure_asc(3, &(struct stx7108_asc_config) { .routing.asc3.txd = stx7108_asc3_txd_pio24_4, .routing.asc3.rxd = stx7108_asc3_rxd_pio24_5, .hw_flow_control = 0, .is_console = 1, }); stx7108_configure_asc(1, &(struct stx7108_asc_config) { .hw_flow_control = 1, }); } static int adi7108_phy1_reset(void *bus) { static int done; if (!done) { gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET1, 0); udelay(10000); /* 10 miliseconds is enough for everyone ;-) */ gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET1, 1); done = 1; } return 1; } static void adi7108_mii_txclk_select(int txclk_250_not_25_mhz) { /* When 1000 speed is negotiated we have to set the PIO21[7]. */ if (txclk_250_not_25_mhz) gpio_set_value(ADI7108_GPIO_MII1_SPEED_SEL, 1); else gpio_set_value(ADI7108_GPIO_MII1_SPEED_SEL, 0); } #ifdef CONFIG_SH_ST_ADI7108_STMMAC0 static int adi7108_phy0_reset(void *bus) { static int done; if (!done) { gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET0, 0); udelay(10000); /* 10 miliseconds is enough for everyone ;-) */ gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET0, 1); done = 1; } return 1; } static struct stmmac_mdio_bus_data stmmac0_mdio_bus = { .bus_id = 0, .phy_reset = adi7108_phy0_reset, .phy_mask = 0, }; #endif /* CONFIG_SH_ST_ADI7108_STMMAC0 */ static struct stmmac_mdio_bus_data stmmac1_mdio_bus = { .bus_id = 1, .phy_reset = adi7108_phy1_reset, .phy_mask = 0, }; /* NOR FLASH */ static struct platform_device adi7108_nor_flash = { .name = "physmap-flash", .id = -1, .num_resources = 1, .resource = (struct resource[]) { { .start = 0x00000000, .end = 256*1024*1024 - 1, .flags = IORESOURCE_MEM, } }, .dev.platform_data = &(struct physmap_flash_data) { .width = 2, .set_vpp = NULL, .nr_parts = 3, .parts = (struct mtd_partition []) { { .name = "NOR Flash 1", .size = 0x00080000, .offset = 0x00000000, }, { .name = "NOR Flash 2", .size = 0x00200000, .offset = MTDPART_OFS_NXTBLK, }, { .name = "NOR Flash 3", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK, } }, }, }; /* Serial FLASH */ static struct stm_plat_spifsm_data adi7108_serial_flash = { .name = "m25p128", .nr_parts = 2, .parts = (struct mtd_partition []) { { .name = "Serial Flash 1", .size = 0x00200000, .offset = 0, }, { .name = "Serial Flash 2", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK, }, }, }; /* NAND FLASH */ static struct stm_nand_bank_data adi7108_nand_flash = { .csn = 1, .options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT, .nr_partitions = 2, .partitions = (struct mtd_partition []) { { .name = "NAND Flash 1", .offset = 0, .size = 0x00800000 }, { .name = "NAND Flash 2", .offset = MTDPART_OFS_NXTBLK, .size = MTDPART_SIZ_FULL }, }, .timing_data = &(struct stm_nand_timing_data) { .sig_setup = 10, /* times in ns */ .sig_hold = 10, .CE_deassert = 0, .WE_to_RBn = 100, .wr_on = 10, .wr_off = 30, .rd_on = 10, .rd_off = 30, .chip_delay = 30, /* in us */ }, }; static struct platform_device *adi7108_devices[] __initdata = { &adi7108_nor_flash, }; static int __init device_init(void) { struct sysconf_field *sc; unsigned long nor_bank_base = 0; unsigned long nor_bank_size = 0; /* * * BootUp RE32 & RE35 RE33 & RE34 * NOR 0R NC * NAND/SPI NC 0R * */ /* Configure Flash according to boot-device * * [Only tested on boot-from-NOR, board-mod required for * boot-from-NAND/SPI] */ sc = sysconf_claim(SYS_STA_BANK1, 3, 2, 6, "boot_device"); switch (sysconf_read(sc)) { case 0x15: pr_info("Configuring FLASH for boot-from-NOR\n"); nor_bank_base = emi_bank_base(0); nor_bank_size = emi_bank_base(1) - nor_bank_base; adi7108_nand_flash.csn = 1; break; case 0x14: pr_info("Configuring FLASH for boot-from-NAND\n"); nor_bank_base = emi_bank_base(1); nor_bank_size = emi_bank_base(2) - nor_bank_base; adi7108_nand_flash.csn = 0; break; case 0x1a: pr_info("Configuring FLASH for boot-from-SPI\n"); nor_bank_base = emi_bank_base(1); nor_bank_size = emi_bank_base(2) - nor_bank_base; adi7108_nand_flash.csn = 0; break; default: BUG(); break; } sysconf_release(sc); /* Update NOR Flash base address and size: */ /* - limit bank size to 64MB (some targetpacks define 128MB!) */ if (nor_bank_size > 64*1024*1024) nor_bank_size = 64*1024*1024; /* - reduce visibility of NOR flash to EMI bank size */ if (adi7108_nor_flash.resource[0].end > nor_bank_size - 1) adi7108_nor_flash.resource[0].end = nor_bank_size - 1; /* - update resource parameters */ adi7108_nor_flash.resource[0].start += nor_bank_base; adi7108_nor_flash.resource[0].end += nor_bank_base; /* NIM */ stx7108_configure_ssc_i2c(1, NULL); /* AV */ stx7108_configure_ssc_i2c(2, &(struct stx7108_ssc_config) { .routing.ssc2.sclk = stx7108_ssc2_sclk_pio14_4, .routing.ssc2.mtsr = stx7108_ssc2_mtsr_pio14_5, }); /* EEPROM */ stx7108_configure_ssc_i2c(5, NULL); /* HDMI */ stx7108_configure_ssc_i2c(6, NULL); stx7108_configure_lirc(&(struct stx7108_lirc_config) { .rx_mode = stx7108_lirc_rx_mode_ir, }); stx7108_configure_usb(0); stx7108_configure_usb(1); stx7108_configure_usb(2); /*------------------------------------------------------------- * | Ver1.0 VerB VerC VerD * SATA 0/1 connector | E-sata0+1 E-sata0 E-sata0 Sata on board * PCI-e Connector | √ √ *-------------------------------------------------------------*/ #if defined(CONFIG_SH_ST_ADI7108_VER_B_BOARD) || \ defined(CONFIG_SH_ST_ADI7108_VER_C_BOARD) stx7108_configure_miphy(&(struct stx7108_miphy_config) { .modes = (enum miphy_mode[2]) { SATA_MODE, PCIE_MODE }, }); stx7108_configure_sata(0, &(struct stx7108_sata_config) { }); #elif defined(CONFIG_SH_ST_ADI7108_VER_D_BOARD) || \ defined(CONFIG_SH_ST_ADI7108_VER_1_0_BOARD) stx7108_configure_miphy(&(struct stx7108_miphy_config) { .modes = (enum miphy_mode[2]) { SATA_MODE, SATA_MODE }, }); stx7108_configure_sata(0, &(struct stx7108_sata_config) { }); stx7108_configure_sata(1, &(struct stx7108_sata_config) { }); #endif #ifdef CONFIG_SH_ST_ADI7108_STMMAC0 /* By default the RJ45 connector is removed on this board. */ gpio_request(ADI7108_PIO_POWER_ON_ETHERNET0, "POWER_ON_ETHERNET"); gpio_direction_output(ADI7108_PIO_POWER_ON_ETHERNET0, 0); stx7108_configure_ethernet(0, &(struct stx7108_ethernet_config) { .mode = stx7108_ethernet_mode_mii, .ext_clk = 1, .phy_bus = 0, .phy_addr = -1, .mdio_bus_data = &stmmac0_mdio_bus, }); #endif /* CONFIG_SH_ST_ADI7108_STMMAC0 */ /* To use the MII/GMII mode. * * RP1 MII1_EN * GMII NC 1 * MII 51R 0 * */ /* The "POWER_ON_ETH" line should be rather called "PHY_RESET", * but it isn't... ;-) */ gpio_request(ADI7108_PIO_POWER_ON_ETHERNET1, "POWER_ON_ETHERNET"); gpio_direction_output(ADI7108_PIO_POWER_ON_ETHERNET1, 0); gpio_request(ADI7108_GPIO_MII1_SPEED_SEL, "stmmac"); gpio_direction_output(ADI7108_GPIO_MII1_SPEED_SEL, 0); stx7108_configure_ethernet(1, &(struct stx7108_ethernet_config) { .mode = stx7108_ethernet_mode_gmii_gtx, .ext_clk = 0, .phy_bus = 1, .txclk_select = adi7108_mii_txclk_select, .phy_addr = 1, .mdio_bus_data = &stmmac1_mdio_bus, }); stx7108_configure_nand(&(struct stm_nand_config) { .driver = stm_nand_flex, .nr_banks = 1, .banks = &adi7108_nand_flash, .rbn.flex_connected = 1,}); stx7108_configure_spifsm(&adi7108_serial_flash); stx7108_configure_mmc(0); return platform_add_devices(adi7108_devices, ARRAY_SIZE(adi7108_devices)); } arch_initcall(device_init); static void __iomem *adi7108_ioport_map(unsigned long port, unsigned int size) { /* If we have PCI then this should never be called because we * are using the generic iomap implementation. If we don't * have PCI then there are no IO mapped devices, so it still * shouldn't be called. */ BUG(); return NULL; } struct sh_machine_vector mv_adi7108 __initmv = { .mv_name = "adi7108", .mv_setup = adi7108_setup, .mv_nr_irqs = NR_IRQS, .mv_ioport_map = adi7108_ioport_map, }; #ifdef CONFIG_HIBERNATION_ON_MEMORY int stm_defrost_board(void *data) { gpio_direction_output(ADI7108_PIO_POWER_ON_ETHERNET1, 0); gpio_direction_output(ADI7108_GPIO_MII1_SPEED_SEL, 0); /* * adi7108_phy_reset(...); */ gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET1, 0); udelay(10000); /* 10 miliseconds is enough for everyone ;-) */ gpio_set_value(ADI7108_PIO_POWER_ON_ETHERNET1, 1); return 0; } #endif