1/* 2 * Cavium Networks CNS3420 Validation Board 3 * 4 * Copyright 2000 Deep Blue Solutions Ltd 5 * Copyright 2008 ARM Limited 6 * Copyright 2008 Cavium Networks 7 * Scott Shu 8 * Copyright 2010 MontaVista Software, LLC. 9 * Anton Vorontsov <avorontsov@mvista.com> 10 * 11 * This file is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License, Version 2, as 13 * published by the Free Software Foundation. 14 */ 15 16#include <linux/init.h> 17#include <linux/kernel.h> 18#include <linux/compiler.h> 19#include <linux/io.h> 20#include <linux/dma-mapping.h> 21#include <linux/serial_core.h> 22#include <linux/serial_8250.h> 23#include <linux/platform_device.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/physmap.h> 26#include <linux/mtd/partitions.h> 27#include <linux/usb/ehci_pdriver.h> 28#include <linux/usb/ohci_pdriver.h> 29#include <asm/setup.h> 30#include <asm/mach-types.h> 31#include <asm/mach/arch.h> 32#include <asm/mach/map.h> 33#include <asm/mach/time.h> 34#include "cns3xxx.h" 35#include "pm.h" 36#include "core.h" 37#include "devices.h" 38 39/* 40 * NOR Flash 41 */ 42static struct mtd_partition cns3420_nor_partitions[] = { 43 { 44 .name = "uboot", 45 .size = 0x00040000, 46 .offset = 0, 47 .mask_flags = MTD_WRITEABLE, 48 }, { 49 .name = "kernel", 50 .size = 0x004C0000, 51 .offset = MTDPART_OFS_APPEND, 52 }, { 53 .name = "filesystem", 54 .size = 0x7000000, 55 .offset = MTDPART_OFS_APPEND, 56 }, { 57 .name = "filesystem2", 58 .size = 0x0AE0000, 59 .offset = MTDPART_OFS_APPEND, 60 }, { 61 .name = "ubootenv", 62 .size = MTDPART_SIZ_FULL, 63 .offset = MTDPART_OFS_APPEND, 64 }, 65}; 66 67static struct physmap_flash_data cns3420_nor_pdata = { 68 .width = 2, 69 .parts = cns3420_nor_partitions, 70 .nr_parts = ARRAY_SIZE(cns3420_nor_partitions), 71}; 72 73static struct resource cns3420_nor_res = { 74 .start = CNS3XXX_FLASH_BASE, 75 .end = CNS3XXX_FLASH_BASE + SZ_128M - 1, 76 .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, 77}; 78 79static struct platform_device cns3420_nor_pdev = { 80 .name = "physmap-flash", 81 .id = 0, 82 .resource = &cns3420_nor_res, 83 .num_resources = 1, 84 .dev = { 85 .platform_data = &cns3420_nor_pdata, 86 }, 87}; 88 89/* 90 * UART 91 */ 92static void __init cns3420_early_serial_setup(void) 93{ 94#ifdef CONFIG_SERIAL_8250_CONSOLE 95 static struct uart_port cns3420_serial_port = { 96 .membase = (void __iomem *)CNS3XXX_UART0_BASE_VIRT, 97 .mapbase = CNS3XXX_UART0_BASE, 98 .irq = IRQ_CNS3XXX_UART0, 99 .iotype = UPIO_MEM, 100 .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, 101 .regshift = 2, 102 .uartclk = 24000000, 103 .line = 0, 104 .type = PORT_16550A, 105 .fifosize = 16, 106 }; 107 108 early_serial_setup(&cns3420_serial_port); 109#endif 110} 111 112/* 113 * USB 114 */ 115static struct resource cns3xxx_usb_ehci_resources[] = { 116 [0] = { 117 .start = CNS3XXX_USB_BASE, 118 .end = CNS3XXX_USB_BASE + SZ_16M - 1, 119 .flags = IORESOURCE_MEM, 120 }, 121 [1] = { 122 .start = IRQ_CNS3XXX_USB_EHCI, 123 .flags = IORESOURCE_IRQ, 124 }, 125}; 126 127static u64 cns3xxx_usb_ehci_dma_mask = DMA_BIT_MASK(32); 128 129static int csn3xxx_usb_power_on(struct platform_device *pdev) 130{ 131 /* 132 * EHCI and OHCI share the same clock and power, 133 * resetting twice would cause the 1st controller been reset. 134 * Therefore only do power up at the first up device, and 135 * power down at the last down device. 136 * 137 * Set USB AHB INCR length to 16 138 */ 139 if (atomic_inc_return(&usb_pwr_ref) == 1) { 140 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); 141 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); 142 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); 143 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), 144 MISC_CHIP_CONFIG_REG); 145 } 146 147 return 0; 148} 149 150static void csn3xxx_usb_power_off(struct platform_device *pdev) 151{ 152 /* 153 * EHCI and OHCI share the same clock and power, 154 * resetting twice would cause the 1st controller been reset. 155 * Therefore only do power up at the first up device, and 156 * power down at the last down device. 157 */ 158 if (atomic_dec_return(&usb_pwr_ref) == 0) 159 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); 160} 161 162static struct usb_ehci_pdata cns3xxx_usb_ehci_pdata = { 163 .power_on = csn3xxx_usb_power_on, 164 .power_off = csn3xxx_usb_power_off, 165}; 166 167static struct platform_device cns3xxx_usb_ehci_device = { 168 .name = "ehci-platform", 169 .num_resources = ARRAY_SIZE(cns3xxx_usb_ehci_resources), 170 .resource = cns3xxx_usb_ehci_resources, 171 .dev = { 172 .dma_mask = &cns3xxx_usb_ehci_dma_mask, 173 .coherent_dma_mask = DMA_BIT_MASK(32), 174 .platform_data = &cns3xxx_usb_ehci_pdata, 175 }, 176}; 177 178static struct resource cns3xxx_usb_ohci_resources[] = { 179 [0] = { 180 .start = CNS3XXX_USB_OHCI_BASE, 181 .end = CNS3XXX_USB_OHCI_BASE + SZ_16M - 1, 182 .flags = IORESOURCE_MEM, 183 }, 184 [1] = { 185 .start = IRQ_CNS3XXX_USB_OHCI, 186 .flags = IORESOURCE_IRQ, 187 }, 188}; 189 190static u64 cns3xxx_usb_ohci_dma_mask = DMA_BIT_MASK(32); 191 192static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = { 193 .num_ports = 1, 194 .power_on = csn3xxx_usb_power_on, 195 .power_off = csn3xxx_usb_power_off, 196}; 197 198static struct platform_device cns3xxx_usb_ohci_device = { 199 .name = "ohci-platform", 200 .num_resources = ARRAY_SIZE(cns3xxx_usb_ohci_resources), 201 .resource = cns3xxx_usb_ohci_resources, 202 .dev = { 203 .dma_mask = &cns3xxx_usb_ohci_dma_mask, 204 .coherent_dma_mask = DMA_BIT_MASK(32), 205 .platform_data = &cns3xxx_usb_ohci_pdata, 206 }, 207}; 208 209/* 210 * Initialization 211 */ 212static struct platform_device *cns3420_pdevs[] __initdata = { 213 &cns3420_nor_pdev, 214 &cns3xxx_usb_ehci_device, 215 &cns3xxx_usb_ohci_device, 216}; 217 218static void __init cns3420_init(void) 219{ 220 cns3xxx_l2x0_init(); 221 222 platform_add_devices(cns3420_pdevs, ARRAY_SIZE(cns3420_pdevs)); 223 224 cns3xxx_ahci_init(); 225 cns3xxx_sdhci_init(); 226 227 pm_power_off = cns3xxx_power_off; 228} 229 230static struct map_desc cns3420_io_desc[] __initdata = { 231 { 232 .virtual = CNS3XXX_UART0_BASE_VIRT, 233 .pfn = __phys_to_pfn(CNS3XXX_UART0_BASE), 234 .length = SZ_4K, 235 .type = MT_DEVICE, 236 }, 237}; 238 239static void __init cns3420_map_io(void) 240{ 241 cns3xxx_map_io(); 242 iotable_init(cns3420_io_desc, ARRAY_SIZE(cns3420_io_desc)); 243 244 cns3420_early_serial_setup(); 245} 246 247MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board") 248 .atag_offset = 0x100, 249 .map_io = cns3420_map_io, 250 .init_irq = cns3xxx_init_irq, 251 .init_time = cns3xxx_timer_init, 252 .init_machine = cns3420_init, 253 .init_late = cns3xxx_pcie_init_late, 254 .restart = cns3xxx_restart, 255MACHINE_END 256