128ad94ecSAlessandro Rubini /* 228ad94ecSAlessandro Rubini * Copyright STMicroelectronics, 2007. 328ad94ecSAlessandro Rubini * 428ad94ecSAlessandro Rubini * This program is free software; you can redistribute it and/or modify 528ad94ecSAlessandro Rubini * it under the terms of the GNU General Public License as published by 628ad94ecSAlessandro Rubini * the Free Software Foundation; either version 2 of the License, or 728ad94ecSAlessandro Rubini * (at your option) any later version. 828ad94ecSAlessandro Rubini * 928ad94ecSAlessandro Rubini * This program is distributed in the hope that it will be useful, 1028ad94ecSAlessandro Rubini * but WITHOUT ANY WARRANTY; without even the implied warranty of 1128ad94ecSAlessandro Rubini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1228ad94ecSAlessandro Rubini * GNU General Public License for more details. 1328ad94ecSAlessandro Rubini * 1428ad94ecSAlessandro Rubini * You should have received a copy of the GNU General Public License 1528ad94ecSAlessandro Rubini * along with this program; if not, write to the Free Software 1628ad94ecSAlessandro Rubini * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1728ad94ecSAlessandro Rubini */ 1828ad94ecSAlessandro Rubini 1928ad94ecSAlessandro Rubini #include <linux/types.h> 2028ad94ecSAlessandro Rubini #include <linux/init.h> 2128ad94ecSAlessandro Rubini #include <linux/device.h> 222ec1d359SAlessandro Rubini #include <linux/amba/bus.h> 233e3c62caSRabin Vincent #include <linux/platform_device.h> 2435b47a40SRussell King #include <linux/io.h> 257c77852dSLinus Walleij #include <linux/slab.h> 267c77852dSLinus Walleij #include <linux/irq.h> 277c77852dSLinus Walleij #include <linux/dma-mapping.h> 28f8635abdSLinus Walleij #include <linux/irqchip.h> 294a31bd28SLinus Walleij #include <linux/platform_data/clk-nomadik.h> 30bb16bd9bSLinus Walleij #include <linux/platform_data/pinctrl-nomadik.h> 311b542757SLinus Walleij #include <linux/pinctrl/machine.h> 32f8635abdSLinus Walleij #include <linux/platform_data/clocksource-nomadik-mtu.h> 33f8635abdSLinus Walleij #include <linux/of_irq.h> 342ad6e398SLinus Walleij #include <linux/of_gpio.h> 35f8635abdSLinus Walleij #include <linux/of_address.h> 36f8635abdSLinus Walleij #include <linux/of_platform.h> 37ba785205SLinus Walleij #include <linux/mtd/fsmc.h> 382ad6e398SLinus Walleij #include <linux/gpio.h> 394fd243c6SLinus Walleij #include <linux/amba/mmci.h> 4028ad94ecSAlessandro Rubini 4128ad94ecSAlessandro Rubini #include <mach/hardware.h> 4228ad94ecSAlessandro Rubini #include <mach/irqs.h> 43f8635abdSLinus Walleij #include <asm/mach/arch.h> 4428ad94ecSAlessandro Rubini #include <asm/mach/map.h> 45f8635abdSLinus Walleij #include <asm/mach/time.h> 4627bda036SLinus Walleij #include <asm/mach-types.h> 4728ad94ecSAlessandro Rubini 480b260fd4SAlessandro Rubini #include <asm/cacheflush.h> 490b260fd4SAlessandro Rubini #include <asm/hardware/cache-l2x0.h> 500b260fd4SAlessandro Rubini 511b542757SLinus Walleij static unsigned long out_low[] = { PIN_OUTPUT_LOW }; 521b542757SLinus Walleij static unsigned long out_high[] = { PIN_OUTPUT_HIGH }; 531b542757SLinus Walleij static unsigned long in_nopull[] = { PIN_INPUT_NOPULL }; 541b542757SLinus Walleij static unsigned long in_pullup[] = { PIN_INPUT_PULLUP }; 551b542757SLinus Walleij 561b542757SLinus Walleij static struct pinctrl_map __initdata nhk8815_pinmap[] = { 571b542757SLinus Walleij PIN_MAP_MUX_GROUP_DEFAULT("uart0", "pinctrl-stn8815", "u0_a_1", "u0"), 581b542757SLinus Walleij PIN_MAP_MUX_GROUP_DEFAULT("uart1", "pinctrl-stn8815", "u1_a_1", "u1"), 591b542757SLinus Walleij /* Hog in MMC/SD card mux */ 601b542757SLinus Walleij PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-stn8815", "mmcsd_a_1", "mmcsd"), 611b542757SLinus Walleij /* MCCLK */ 621b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO8_B10", out_low), 631b542757SLinus Walleij /* MCCMD */ 641b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO9_A10", in_pullup), 651b542757SLinus Walleij /* MCCMDDIR */ 661b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO10_C11", out_high), 671b542757SLinus Walleij /* MCDAT3-0 */ 681b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO11_B11", in_pullup), 691b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO12_A11", in_pullup), 701b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO13_C12", in_pullup), 711b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO14_B12", in_pullup), 721b542757SLinus Walleij /* MCDAT0DIR */ 731b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO15_A12", out_high), 741b542757SLinus Walleij /* MCDAT31DIR */ 751b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO16_C13", out_high), 761b542757SLinus Walleij /* MCMSFBCLK */ 771b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO24_C15", in_pullup), 781b542757SLinus Walleij /* CD input GPIO */ 791b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO111_H21", in_nopull), 801b542757SLinus Walleij /* CD bias drive */ 811b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO112_J21", out_low), 821b542757SLinus Walleij /* I2C0 */ 831b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO62_D3", in_pullup), 841b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO63_D2", in_pullup), 851b542757SLinus Walleij /* I2C1 */ 861b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO53_L4", in_pullup), 871b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO54_L3", in_pullup), 881b542757SLinus Walleij /* I2C2 */ 891b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO73_C21", in_pullup), 901b542757SLinus Walleij PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO74_C20", in_pullup), 911b542757SLinus Walleij }; 921b542757SLinus Walleij 9328ad94ecSAlessandro Rubini /* All SoC devices live in the same area (see hardware.h) */ 9428ad94ecSAlessandro Rubini static struct map_desc nomadik_io_desc[] __initdata = { 9528ad94ecSAlessandro Rubini { 9628ad94ecSAlessandro Rubini .virtual = NOMADIK_IO_VIRTUAL, 9728ad94ecSAlessandro Rubini .pfn = __phys_to_pfn(NOMADIK_IO_PHYSICAL), 9828ad94ecSAlessandro Rubini .length = NOMADIK_IO_SIZE, 9928ad94ecSAlessandro Rubini .type = MT_DEVICE, 10028ad94ecSAlessandro Rubini } 10128ad94ecSAlessandro Rubini /* static ram and secured ram may be added later */ 10228ad94ecSAlessandro Rubini }; 10328ad94ecSAlessandro Rubini 1045f66d482SLinus Walleij static void __init cpu8815_map_io(void) 10528ad94ecSAlessandro Rubini { 10628ad94ecSAlessandro Rubini iotable_init(nomadik_io_desc, ARRAY_SIZE(nomadik_io_desc)); 10728ad94ecSAlessandro Rubini } 10828ad94ecSAlessandro Rubini 1095f66d482SLinus Walleij static void cpu8815_restart(char mode, const char *cmd) 11035b47a40SRussell King { 11135b47a40SRussell King void __iomem *src_rstsr = io_p2v(NOMADIK_SRC_BASE + 0x18); 11235b47a40SRussell King 11335b47a40SRussell King /* FIXME: use egpio when implemented */ 11435b47a40SRussell King 11535b47a40SRussell King /* Write anything to Reset status register */ 11635b47a40SRussell King writel(1, src_rstsr); 11735b47a40SRussell King } 118f8635abdSLinus Walleij 119f8635abdSLinus Walleij /* Initial value for SRC control register: all timers use MXTAL/8 source */ 120f8635abdSLinus Walleij #define SRC_CR_INIT_MASK 0x00007fff 121f8635abdSLinus Walleij #define SRC_CR_INIT_VAL 0x2aaa8000 122f8635abdSLinus Walleij 123f8635abdSLinus Walleij static void __init cpu8815_timer_init_of(void) 124f8635abdSLinus Walleij { 125f8635abdSLinus Walleij struct device_node *mtu; 126f8635abdSLinus Walleij void __iomem *base; 127f8635abdSLinus Walleij int irq; 128f8635abdSLinus Walleij u32 src_cr; 129f8635abdSLinus Walleij 130f8635abdSLinus Walleij /* We need this to be up now */ 131f8635abdSLinus Walleij nomadik_clk_init(); 132f8635abdSLinus Walleij 133f8635abdSLinus Walleij mtu = of_find_node_by_path("/mtu0"); 134f8635abdSLinus Walleij if (!mtu) 135f8635abdSLinus Walleij return; 136f8635abdSLinus Walleij base = of_iomap(mtu, 0); 137f8635abdSLinus Walleij if (WARN_ON(!base)) 138f8635abdSLinus Walleij return; 139f8635abdSLinus Walleij irq = irq_of_parse_and_map(mtu, 0); 140f8635abdSLinus Walleij 141f8635abdSLinus Walleij pr_info("Remapped MTU @ %p, irq: %d\n", base, irq); 142f8635abdSLinus Walleij 143f8635abdSLinus Walleij /* Configure timer sources in "system reset controller" ctrl reg */ 144f8635abdSLinus Walleij src_cr = readl(base); 145f8635abdSLinus Walleij src_cr &= SRC_CR_INIT_MASK; 146f8635abdSLinus Walleij src_cr |= SRC_CR_INIT_VAL; 147f8635abdSLinus Walleij writel(src_cr, base); 148f8635abdSLinus Walleij 149f8635abdSLinus Walleij nmdk_timer_init(base, irq); 150f8635abdSLinus Walleij } 151f8635abdSLinus Walleij 152ba785205SLinus Walleij static struct fsmc_nand_timings cpu8815_nand_timings = { 153ba785205SLinus Walleij .thiz = 0, 154ba785205SLinus Walleij .thold = 0x10, 155ba785205SLinus Walleij .twait = 0x0A, 156ba785205SLinus Walleij .tset = 0, 157ba785205SLinus Walleij }; 158ba785205SLinus Walleij 159ba785205SLinus Walleij static struct fsmc_nand_platform_data cpu8815_nand_data = { 160ba785205SLinus Walleij .nand_timings = &cpu8815_nand_timings, 161ba785205SLinus Walleij }; 162ba785205SLinus Walleij 1632ad6e398SLinus Walleij /* 1642ad6e398SLinus Walleij * The SMSC911x IRQ is connected to a GPIO pin, but the driver expects 1652ad6e398SLinus Walleij * to simply request an IRQ passed as a resource. So the GPIO pin needs 1662ad6e398SLinus Walleij * to be requested by this hog and set as input. 1672ad6e398SLinus Walleij */ 1682ad6e398SLinus Walleij static int __init cpu8815_eth_init(void) 1692ad6e398SLinus Walleij { 1702ad6e398SLinus Walleij struct device_node *eth; 1712ad6e398SLinus Walleij int gpio, irq, err; 1722ad6e398SLinus Walleij 1732ad6e398SLinus Walleij eth = of_find_node_by_path("/usb-s8815/ethernet-gpio"); 1742ad6e398SLinus Walleij if (!eth) { 1752ad6e398SLinus Walleij pr_info("could not find any ethernet GPIO\n"); 1762ad6e398SLinus Walleij return 0; 1772ad6e398SLinus Walleij } 1782ad6e398SLinus Walleij gpio = of_get_gpio(eth, 0); 1792ad6e398SLinus Walleij err = gpio_request(gpio, "eth_irq"); 1802ad6e398SLinus Walleij if (err) { 1812ad6e398SLinus Walleij pr_info("failed to request ethernet GPIO\n"); 1822ad6e398SLinus Walleij return -ENODEV; 1832ad6e398SLinus Walleij } 1842ad6e398SLinus Walleij err = gpio_direction_input(gpio); 1852ad6e398SLinus Walleij if (err) { 1862ad6e398SLinus Walleij pr_info("failed to set ethernet GPIO as input\n"); 1872ad6e398SLinus Walleij return -ENODEV; 1882ad6e398SLinus Walleij } 1892ad6e398SLinus Walleij irq = gpio_to_irq(gpio); 1902ad6e398SLinus Walleij pr_info("enabled USB-S8815 ethernet GPIO %d, IRQ %d\n", gpio, irq); 1912ad6e398SLinus Walleij return 0; 1922ad6e398SLinus Walleij } 1932ad6e398SLinus Walleij device_initcall(cpu8815_eth_init); 1942ad6e398SLinus Walleij 1954fd243c6SLinus Walleij /* 1964fd243c6SLinus Walleij * TODO: 1974fd243c6SLinus Walleij * cannot be set from device tree, convert to a proper DT 1984fd243c6SLinus Walleij * binding. 1994fd243c6SLinus Walleij */ 2004fd243c6SLinus Walleij static struct mmci_platform_data mmcsd_plat_data = { 2014fd243c6SLinus Walleij .ocr_mask = MMC_VDD_29_30, 2024fd243c6SLinus Walleij }; 2034fd243c6SLinus Walleij 2044fd243c6SLinus Walleij /* 2054fd243c6SLinus Walleij * This GPIO pin turns on a line that is used to detect card insertion 2064fd243c6SLinus Walleij * on this board. 2074fd243c6SLinus Walleij */ 2084fd243c6SLinus Walleij static int __init cpu8815_mmcsd_init(void) 2094fd243c6SLinus Walleij { 2104fd243c6SLinus Walleij struct device_node *cdbias; 2114fd243c6SLinus Walleij int gpio, err; 2124fd243c6SLinus Walleij 2134fd243c6SLinus Walleij cdbias = of_find_node_by_path("/usb-s8815/mmcsd-gpio"); 2144fd243c6SLinus Walleij if (!cdbias) { 2154fd243c6SLinus Walleij pr_info("could not find MMC/SD card detect bias node\n"); 2164fd243c6SLinus Walleij return 0; 2174fd243c6SLinus Walleij } 2184fd243c6SLinus Walleij gpio = of_get_gpio(cdbias, 0); 2194fd243c6SLinus Walleij if (gpio < 0) { 2204fd243c6SLinus Walleij pr_info("could not obtain MMC/SD card detect bias GPIO\n"); 2214fd243c6SLinus Walleij return 0; 2224fd243c6SLinus Walleij } 2234fd243c6SLinus Walleij err = gpio_request(gpio, "card detect bias"); 2244fd243c6SLinus Walleij if (err) { 2254fd243c6SLinus Walleij pr_info("failed to request card detect bias GPIO %d\n", gpio); 2264fd243c6SLinus Walleij return -ENODEV; 2274fd243c6SLinus Walleij } 2284fd243c6SLinus Walleij err = gpio_direction_output(gpio, 0); 2294fd243c6SLinus Walleij if (err){ 2304fd243c6SLinus Walleij pr_info("failed to set GPIO %d as output, low\n", gpio); 2314fd243c6SLinus Walleij return err; 2324fd243c6SLinus Walleij } 2334fd243c6SLinus Walleij pr_info("enabled USB-S8815 CD bias GPIO %d, low\n", gpio); 2344fd243c6SLinus Walleij return 0; 2354fd243c6SLinus Walleij } 2364fd243c6SLinus Walleij device_initcall(cpu8815_mmcsd_init); 2374fd243c6SLinus Walleij 2384fd243c6SLinus Walleij 239f8635abdSLinus Walleij /* These are mostly to get the right device names for the clock lookups */ 240f8635abdSLinus Walleij static struct of_dev_auxdata cpu8815_auxdata_lookup[] __initdata = { 2416010d403SLinus Walleij OF_DEV_AUXDATA("st,nomadik-gpio", NOMADIK_GPIO0_BASE, 2426010d403SLinus Walleij "gpio.0", NULL), 2436010d403SLinus Walleij OF_DEV_AUXDATA("st,nomadik-gpio", NOMADIK_GPIO1_BASE, 2446010d403SLinus Walleij "gpio.1", NULL), 2456010d403SLinus Walleij OF_DEV_AUXDATA("st,nomadik-gpio", NOMADIK_GPIO2_BASE, 2466010d403SLinus Walleij "gpio.2", NULL), 2476010d403SLinus Walleij OF_DEV_AUXDATA("st,nomadik-gpio", NOMADIK_GPIO3_BASE, 2486010d403SLinus Walleij "gpio.3", NULL), 2496010d403SLinus Walleij OF_DEV_AUXDATA("stericsson,nmk-pinctrl-stn8815", 0, 2506010d403SLinus Walleij "pinctrl-stn8815", NULL), 251f8635abdSLinus Walleij OF_DEV_AUXDATA("arm,primecell", NOMADIK_UART0_BASE, 252f8635abdSLinus Walleij "uart0", NULL), 253f8635abdSLinus Walleij OF_DEV_AUXDATA("arm,primecell", NOMADIK_UART1_BASE, 254f8635abdSLinus Walleij "uart1", NULL), 25527bda036SLinus Walleij OF_DEV_AUXDATA("arm,primecell", NOMADIK_RNG_BASE, 25627bda036SLinus Walleij "rng", NULL), 25727bda036SLinus Walleij OF_DEV_AUXDATA("arm,primecell", NOMADIK_RTC_BASE, 25827bda036SLinus Walleij "rtc-pl031", NULL), 259ba785205SLinus Walleij OF_DEV_AUXDATA("stericsson,fsmc-nand", NOMADIK_FSMC_BASE, 260ba785205SLinus Walleij "fsmc-nand", &cpu8815_nand_data), 2614fd243c6SLinus Walleij OF_DEV_AUXDATA("arm,primecell", NOMADIK_SDI_BASE, 2624fd243c6SLinus Walleij "mmci", &mmcsd_plat_data), 263f8635abdSLinus Walleij { /* sentinel */ }, 264f8635abdSLinus Walleij }; 265f8635abdSLinus Walleij 266f8635abdSLinus Walleij static void __init cpu8815_init_of(void) 267f8635abdSLinus Walleij { 268f8635abdSLinus Walleij #ifdef CONFIG_CACHE_L2X0 269f8635abdSLinus Walleij /* At full speed latency must be >=2, so 0x249 in low bits */ 270f8635abdSLinus Walleij l2x0_of_init(0x00730249, 0xfe000fff); 271f8635abdSLinus Walleij #endif 2726010d403SLinus Walleij pinctrl_register_mappings(nhk8815_pinmap, ARRAY_SIZE(nhk8815_pinmap)); 273f8635abdSLinus Walleij of_platform_populate(NULL, of_default_bus_match_table, 274f8635abdSLinus Walleij cpu8815_auxdata_lookup, NULL); 275f8635abdSLinus Walleij } 276f8635abdSLinus Walleij 277f8635abdSLinus Walleij static const char * cpu8815_board_compat[] = { 278f8635abdSLinus Walleij "calaosystems,usb-s8815", 279f8635abdSLinus Walleij NULL, 280f8635abdSLinus Walleij }; 281f8635abdSLinus Walleij 282f8635abdSLinus Walleij DT_MACHINE_START(NOMADIK_DT, "Nomadik STn8815") 283f8635abdSLinus Walleij .map_io = cpu8815_map_io, 284f8635abdSLinus Walleij .init_irq = irqchip_init, 285f8635abdSLinus Walleij .init_time = cpu8815_timer_init_of, 286f8635abdSLinus Walleij .init_machine = cpu8815_init_of, 287f8635abdSLinus Walleij .restart = cpu8815_restart, 288f8635abdSLinus Walleij .dt_compat = cpu8815_board_compat, 289f8635abdSLinus Walleij MACHINE_END 290