| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 1 | /* | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 2 |  * Board setup routines for the Marvell EV-64360-BP Evaluation Board. | 
 | 3 |  * | 
 | 4 |  * Author: Lee Nicks <allinux@gmail.com> | 
 | 5 |  * | 
 | 6 |  * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | 
 | 7 |  * Based on code done by - Mark A. Greer <mgreer@mvista.com> | 
 | 8 |  * | 
 | 9 |  * This program is free software; you can redistribute it and/or modify it | 
 | 10 |  * under the terms of the GNU General Public License as published by the | 
 | 11 |  * Free Software Foundation; either version 2 of the License, or (at your | 
 | 12 |  * option) any later version. | 
 | 13 |  */ | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 14 | #include <linux/kernel.h> | 
 | 15 | #include <linux/pci.h> | 
 | 16 | #include <linux/kdev_t.h> | 
 | 17 | #include <linux/console.h> | 
 | 18 | #include <linux/initrd.h> | 
 | 19 | #include <linux/root_dev.h> | 
 | 20 | #include <linux/delay.h> | 
 | 21 | #include <linux/seq_file.h> | 
 | 22 | #include <linux/bootmem.h> | 
 | 23 | #include <linux/mtd/physmap.h> | 
 | 24 | #include <linux/mv643xx.h> | 
| Russell King | d052d1b | 2005-10-29 19:07:23 +0100 | [diff] [blame] | 25 | #include <linux/platform_device.h> | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 26 | #ifdef CONFIG_BOOTIMG | 
 | 27 | #include <linux/bootimg.h> | 
 | 28 | #endif | 
 | 29 | #include <asm/page.h> | 
 | 30 | #include <asm/time.h> | 
 | 31 | #include <asm/smp.h> | 
 | 32 | #include <asm/todc.h> | 
 | 33 | #include <asm/bootinfo.h> | 
 | 34 | #include <asm/ppcboot.h> | 
 | 35 | #include <asm/mv64x60.h> | 
| Paul Mackerras | fd582ec | 2005-10-11 22:08:12 +1000 | [diff] [blame] | 36 | #include <asm/machdep.h> | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 37 | #include <platforms/ev64360.h> | 
 | 38 |  | 
 | 39 | #define BOARD_VENDOR    "Marvell" | 
 | 40 | #define BOARD_MACHINE   "EV-64360-BP" | 
 | 41 |  | 
 | 42 | static struct		mv64x60_handle bh; | 
 | 43 | static void __iomem	*sram_base; | 
 | 44 |  | 
 | 45 | static u32		ev64360_flash_size_0; | 
 | 46 | static u32		ev64360_flash_size_1; | 
 | 47 |  | 
 | 48 | static u32		ev64360_bus_frequency; | 
 | 49 |  | 
 | 50 | unsigned char	__res[sizeof(bd_t)]; | 
 | 51 |  | 
| Lee Nicks | 2104da9 | 2005-11-07 00:58:10 -0800 | [diff] [blame] | 52 | TODC_ALLOC(); | 
 | 53 |  | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 54 | static int __init | 
 | 55 | ev64360_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | 
 | 56 | { | 
 | 57 | 	return 0; | 
 | 58 | } | 
 | 59 |  | 
 | 60 | static void __init | 
 | 61 | ev64360_setup_bridge(void) | 
 | 62 | { | 
 | 63 | 	struct mv64x60_setup_info si; | 
 | 64 | 	int i; | 
 | 65 |  | 
 | 66 | 	memset(&si, 0, sizeof(si)); | 
 | 67 |  | 
 | 68 | 	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | 
 | 69 |  | 
 | 70 | 	#ifdef CONFIG_PCI | 
 | 71 | 	si.pci_1.enable_bus = 1; | 
 | 72 | 	si.pci_1.pci_io.cpu_base = EV64360_PCI1_IO_START_PROC_ADDR; | 
 | 73 | 	si.pci_1.pci_io.pci_base_hi = 0; | 
 | 74 | 	si.pci_1.pci_io.pci_base_lo = EV64360_PCI1_IO_START_PCI_ADDR; | 
 | 75 | 	si.pci_1.pci_io.size = EV64360_PCI1_IO_SIZE; | 
 | 76 | 	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | 
 | 77 | 	si.pci_1.pci_mem[0].cpu_base = EV64360_PCI1_MEM_START_PROC_ADDR; | 
 | 78 | 	si.pci_1.pci_mem[0].pci_base_hi = EV64360_PCI1_MEM_START_PCI_HI_ADDR; | 
 | 79 | 	si.pci_1.pci_mem[0].pci_base_lo = EV64360_PCI1_MEM_START_PCI_LO_ADDR; | 
 | 80 | 	si.pci_1.pci_mem[0].size = EV64360_PCI1_MEM_SIZE; | 
 | 81 | 	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | 
 | 82 | 	si.pci_1.pci_cmd_bits = 0; | 
 | 83 | 	si.pci_1.latency_timer = 0x80; | 
 | 84 | 	#else | 
 | 85 | 	si.pci_0.enable_bus = 0; | 
 | 86 | 	si.pci_1.enable_bus = 0; | 
 | 87 | 	#endif | 
 | 88 |  | 
 | 89 | 	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { | 
 | 90 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 
 | 91 | 		si.cpu_prot_options[i] = 0; | 
 | 92 | 		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | 
 | 93 | 		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | 
 | 94 | 		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | 
 | 95 |  | 
 | 96 | 		si.pci_1.acc_cntl_options[i] = | 
 | 97 | 		    MV64360_PCI_ACC_CNTL_SNOOP_NONE | | 
 | 98 | 		    MV64360_PCI_ACC_CNTL_SWAP_NONE | | 
 | 99 | 		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | 
 | 100 | 		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | 
 | 101 | #else | 
 | 102 | 		si.cpu_prot_options[i] = 0; | 
 | 103 | 		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */ | 
 | 104 | 		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */ | 
 | 105 | 		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */ | 
 | 106 |  | 
 | 107 | 		si.pci_1.acc_cntl_options[i] = | 
 | 108 | 		    MV64360_PCI_ACC_CNTL_SNOOP_WB | | 
 | 109 | 		    MV64360_PCI_ACC_CNTL_SWAP_NONE | | 
 | 110 | 		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | 
 | 111 | 		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; | 
 | 112 | #endif | 
 | 113 | 	} | 
 | 114 |  | 
 | 115 | 	if (mv64x60_init(&bh, &si)) | 
 | 116 | 		printk(KERN_WARNING "Bridge initialization failed.\n"); | 
 | 117 |  | 
 | 118 | 	#ifdef CONFIG_PCI | 
 | 119 | 	pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ | 
 | 120 | 	ppc_md.pci_swizzle = common_swizzle; | 
 | 121 | 	ppc_md.pci_map_irq = ev64360_map_irq; | 
 | 122 | 	ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | 
 | 123 |  | 
 | 124 | 	mv64x60_set_bus(&bh, 1, 0); | 
 | 125 | 	bh.hose_b->first_busno = 0; | 
 | 126 | 	bh.hose_b->last_busno = 0xff; | 
 | 127 | 	#endif | 
 | 128 | } | 
 | 129 |  | 
 | 130 | /* Bridge & platform setup routines */ | 
 | 131 | void __init | 
 | 132 | ev64360_intr_setup(void) | 
 | 133 | { | 
 | 134 | 	/* MPP 8, 9, and 10 */ | 
 | 135 | 	mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff); | 
 | 136 |  | 
 | 137 | 	/* | 
 | 138 | 	 * Define GPP 8,9,and 10 interrupt polarity as active low | 
 | 139 | 	 * input signal and level triggered | 
 | 140 | 	 */ | 
 | 141 | 	mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700); | 
 | 142 | 	mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700); | 
 | 143 |  | 
 | 144 | 	/* Config GPP intr ctlr to respond to level trigger */ | 
 | 145 | 	mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10)); | 
 | 146 |  | 
 | 147 | 	/* Erranum FEr PCI-#8 */ | 
 | 148 | 	mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9)); | 
 | 149 | 	mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9)); | 
 | 150 |  | 
 | 151 | 	/* | 
 | 152 | 	 * Dismiss and then enable interrupt on GPP interrupt cause | 
 | 153 | 	 * for CPU #0 | 
 | 154 | 	 */ | 
 | 155 | 	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700); | 
 | 156 | 	mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700); | 
 | 157 |  | 
 | 158 | 	/* | 
 | 159 | 	 * Dismiss and then enable interrupt on CPU #0 high cause reg | 
 | 160 | 	 * BIT25 summarizes GPP interrupts 8-15 | 
 | 161 | 	 */ | 
 | 162 | 	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25)); | 
 | 163 | } | 
 | 164 |  | 
 | 165 | void __init | 
 | 166 | ev64360_setup_peripherals(void) | 
 | 167 | { | 
 | 168 | 	u32 base; | 
 | 169 |  | 
 | 170 | 	/* Set up window for boot CS */ | 
 | 171 | 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | 
 | 172 | 		 EV64360_BOOT_WINDOW_BASE, EV64360_BOOT_WINDOW_SIZE, 0); | 
 | 173 | 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | 
 | 174 |  | 
 | 175 | 	/* We only use the 32-bit flash */ | 
 | 176 | 	mv64x60_get_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, &base, | 
 | 177 | 		&ev64360_flash_size_0); | 
 | 178 | 	ev64360_flash_size_1 = 0; | 
 | 179 |  | 
 | 180 | 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | 
 | 181 | 		 EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE, 0); | 
 | 182 | 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | 
 | 183 |  | 
| Lee Nicks | 2104da9 | 2005-11-07 00:58:10 -0800 | [diff] [blame] | 184 | 	TODC_INIT(TODC_TYPE_DS1501, 0, 0, | 
 | 185 | 		ioremap(EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE), 8); | 
 | 186 |  | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 187 | 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | 
 | 188 | 		 EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0); | 
 | 189 | 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | 
 | 190 | 	sram_base = ioremap(EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); | 
 | 191 |  | 
 | 192 | 	/* Set up Enet->SRAM window */ | 
 | 193 | 	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, | 
 | 194 | 		EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2); | 
 | 195 | 	bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); | 
 | 196 |  | 
 | 197 | 	/* Give enet r/w access to memory region */ | 
 | 198 | 	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1))); | 
 | 199 | 	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1))); | 
 | 200 | 	mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1))); | 
 | 201 |  | 
 | 202 | 	mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); | 
 | 203 | 	mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | 
 | 204 | 			 ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); | 
 | 205 |  | 
 | 206 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 
 | 207 | 	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000); | 
 | 208 | #else | 
 | 209 | 	mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); | 
 | 210 | #endif | 
 | 211 |  | 
 | 212 | 	/* | 
 | 213 | 	 * Setting the SRAM to 0. Note that this generates parity errors on | 
 | 214 | 	 * internal data path in SRAM since it's first time accessing it | 
 | 215 | 	 * while after reset it's not configured. | 
 | 216 | 	 */ | 
 | 217 | 	memset(sram_base, 0, MV64360_SRAM_SIZE); | 
 | 218 |  | 
 | 219 | 	/* set up PCI interrupt controller */ | 
 | 220 | 	ev64360_intr_setup(); | 
 | 221 | } | 
 | 222 |  | 
 | 223 | static void __init | 
 | 224 | ev64360_setup_arch(void) | 
 | 225 | { | 
 | 226 | 	if (ppc_md.progress) | 
 | 227 | 		ppc_md.progress("ev64360_setup_arch: enter", 0); | 
 | 228 |  | 
 | 229 | 	set_tb(0, 0); | 
 | 230 |  | 
 | 231 | #ifdef CONFIG_BLK_DEV_INITRD | 
 | 232 | 	if (initrd_start) | 
 | 233 | 		ROOT_DEV = Root_RAM0; | 
 | 234 | 	else | 
 | 235 | #endif | 
 | 236 | #ifdef   CONFIG_ROOT_NFS | 
 | 237 | 		ROOT_DEV = Root_NFS; | 
 | 238 | #else | 
 | 239 | 		ROOT_DEV = Root_SDA2; | 
 | 240 | #endif | 
 | 241 |  | 
 | 242 | 	/* | 
 | 243 | 	 * Set up the L2CR register. | 
 | 244 | 	 */ | 
 | 245 | 	_set_L2CR(L2CR_L2E | L2CR_L2PE); | 
 | 246 |  | 
 | 247 | 	if (ppc_md.progress) | 
 | 248 | 		ppc_md.progress("ev64360_setup_arch: calling setup_bridge", 0); | 
 | 249 |  | 
 | 250 | 	ev64360_setup_bridge(); | 
 | 251 | 	ev64360_setup_peripherals(); | 
 | 252 | 	ev64360_bus_frequency = ev64360_bus_freq(); | 
 | 253 |  | 
 | 254 | 	printk(KERN_INFO "%s %s port (C) 2005 Lee Nicks " | 
 | 255 | 		"(allinux@gmail.com)\n", BOARD_VENDOR, BOARD_MACHINE); | 
 | 256 | 	if (ppc_md.progress) | 
 | 257 | 		ppc_md.progress("ev64360_setup_arch: exit", 0); | 
 | 258 | } | 
 | 259 |  | 
 | 260 | /* Platform device data fixup routines. */ | 
 | 261 | #if defined(CONFIG_SERIAL_MPSC) | 
 | 262 | static void __init | 
 | 263 | ev64360_fixup_mpsc_pdata(struct platform_device *pdev) | 
 | 264 | { | 
 | 265 | 	struct mpsc_pdata *pdata; | 
 | 266 |  | 
 | 267 | 	pdata = (struct mpsc_pdata *)pdev->dev.platform_data; | 
 | 268 |  | 
 | 269 | 	pdata->max_idle = 40; | 
 | 270 | 	pdata->default_baud = EV64360_DEFAULT_BAUD; | 
 | 271 | 	pdata->brg_clk_src = EV64360_MPSC_CLK_SRC; | 
 | 272 | 	/* | 
 | 273 | 	 * TCLK (not SysCLk) is routed to BRG, then to the MPSC.  On most parts, | 
 | 274 | 	 * TCLK == SysCLK but on 64460, they are separate pins. | 
 | 275 | 	 * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz. | 
 | 276 | 	 */ | 
 | 277 | 	pdata->brg_clk_freq = min(ev64360_bus_frequency, MV64x60_TCLK_FREQ_MAX); | 
 | 278 | } | 
 | 279 | #endif | 
 | 280 |  | 
 | 281 | #if defined(CONFIG_MV643XX_ETH) | 
 | 282 | static void __init | 
 | 283 | ev64360_fixup_eth_pdata(struct platform_device *pdev) | 
 | 284 | { | 
 | 285 | 	struct mv643xx_eth_platform_data *eth_pd; | 
 | 286 | 	static u16 phy_addr[] = { | 
 | 287 | 		EV64360_ETH0_PHY_ADDR, | 
 | 288 | 		EV64360_ETH1_PHY_ADDR, | 
 | 289 | 		EV64360_ETH2_PHY_ADDR, | 
 | 290 | 	}; | 
 | 291 |  | 
 | 292 | 	eth_pd = pdev->dev.platform_data; | 
 | 293 | 	eth_pd->force_phy_addr = 1; | 
 | 294 | 	eth_pd->phy_addr = phy_addr[pdev->id]; | 
 | 295 | 	eth_pd->tx_queue_size = EV64360_ETH_TX_QUEUE_SIZE; | 
 | 296 | 	eth_pd->rx_queue_size = EV64360_ETH_RX_QUEUE_SIZE; | 
 | 297 | } | 
 | 298 | #endif | 
 | 299 |  | 
| Adrian Cox | bbbe121 | 2006-03-08 22:10:20 +0000 | [diff] [blame] | 300 | static int | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 301 | ev64360_platform_notify(struct device *dev) | 
 | 302 | { | 
 | 303 | 	static struct { | 
 | 304 | 		char	*bus_id; | 
 | 305 | 		void	((*rtn)(struct platform_device *pdev)); | 
 | 306 | 	} dev_map[] = { | 
 | 307 | #if defined(CONFIG_SERIAL_MPSC) | 
 | 308 | 		{ MPSC_CTLR_NAME ".0", ev64360_fixup_mpsc_pdata }, | 
 | 309 | 		{ MPSC_CTLR_NAME ".1", ev64360_fixup_mpsc_pdata }, | 
 | 310 | #endif | 
 | 311 | #if defined(CONFIG_MV643XX_ETH) | 
 | 312 | 		{ MV643XX_ETH_NAME ".0", ev64360_fixup_eth_pdata }, | 
 | 313 | 		{ MV643XX_ETH_NAME ".1", ev64360_fixup_eth_pdata }, | 
 | 314 | 		{ MV643XX_ETH_NAME ".2", ev64360_fixup_eth_pdata }, | 
 | 315 | #endif | 
 | 316 | 	}; | 
 | 317 | 	struct platform_device	*pdev; | 
 | 318 | 	int	i; | 
 | 319 |  | 
 | 320 | 	if (dev && dev->bus_id) | 
 | 321 | 		for (i=0; i<ARRAY_SIZE(dev_map); i++) | 
 | 322 | 			if (!strncmp(dev->bus_id, dev_map[i].bus_id, | 
 | 323 | 				BUS_ID_SIZE)) { | 
 | 324 |  | 
 | 325 | 				pdev = container_of(dev, | 
 | 326 | 					struct platform_device, dev); | 
 | 327 | 				dev_map[i].rtn(pdev); | 
 | 328 | 			} | 
 | 329 |  | 
 | 330 | 	return 0; | 
 | 331 | } | 
 | 332 |  | 
 | 333 | #ifdef CONFIG_MTD_PHYSMAP | 
 | 334 |  | 
 | 335 | #ifndef MB | 
 | 336 | #define MB	(1 << 20) | 
 | 337 | #endif | 
 | 338 |  | 
 | 339 | /* | 
 | 340 |  * MTD Layout. | 
 | 341 |  * | 
 | 342 |  * FLASH Amount:	0xff000000 - 0xffffffff | 
 | 343 |  * -------------	----------------------- | 
 | 344 |  * Reserved:		0xff000000 - 0xff03ffff | 
 | 345 |  * JFFS2 file system:	0xff040000 - 0xffefffff | 
 | 346 |  * U-boot:		0xfff00000 - 0xffffffff | 
 | 347 |  */ | 
 | 348 | static int __init | 
 | 349 | ev64360_setup_mtd(void) | 
 | 350 | { | 
 | 351 | 	u32	size; | 
 | 352 | 	int	ptbl_entries; | 
 | 353 | 	static struct mtd_partition	*ptbl; | 
 | 354 |  | 
 | 355 | 	size = ev64360_flash_size_0 + ev64360_flash_size_1; | 
 | 356 | 	if (!size) | 
 | 357 | 		return -ENOMEM; | 
 | 358 |  | 
 | 359 | 	ptbl_entries = 3; | 
 | 360 |  | 
| Burman Yan | 95b93a0 | 2006-11-15 21:10:29 +0200 | [diff] [blame] | 361 | 	if ((ptbl = kzalloc(ptbl_entries * sizeof(struct mtd_partition), | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 362 | 		GFP_KERNEL)) == NULL) { | 
 | 363 |  | 
 | 364 | 		printk(KERN_WARNING "Can't alloc MTD partition table\n"); | 
 | 365 | 		return -ENOMEM; | 
 | 366 | 	} | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 367 |  | 
 | 368 | 	ptbl[0].name = "reserved"; | 
 | 369 | 	ptbl[0].offset = 0; | 
 | 370 | 	ptbl[0].size = EV64360_MTD_RESERVED_SIZE; | 
 | 371 | 	ptbl[1].name = "jffs2"; | 
 | 372 | 	ptbl[1].offset = EV64360_MTD_RESERVED_SIZE; | 
 | 373 | 	ptbl[1].size = EV64360_MTD_JFFS2_SIZE; | 
 | 374 | 	ptbl[2].name = "U-BOOT"; | 
 | 375 | 	ptbl[2].offset = EV64360_MTD_RESERVED_SIZE + EV64360_MTD_JFFS2_SIZE; | 
 | 376 | 	ptbl[2].size = EV64360_MTD_UBOOT_SIZE; | 
 | 377 |  | 
 | 378 | 	physmap_map.size = size; | 
 | 379 | 	physmap_set_partitions(ptbl, ptbl_entries); | 
 | 380 | 	return 0; | 
 | 381 | } | 
 | 382 |  | 
 | 383 | arch_initcall(ev64360_setup_mtd); | 
 | 384 | #endif | 
 | 385 |  | 
 | 386 | static void | 
 | 387 | ev64360_restart(char *cmd) | 
 | 388 | { | 
 | 389 | 	ulong	i = 0xffffffff; | 
 | 390 | 	volatile unsigned char * rtc_base = ioremap(EV64360_RTC_WINDOW_BASE,0x4000); | 
 | 391 |  | 
 | 392 | 	/* issue hard reset */ | 
 | 393 | 	rtc_base[0xf] = 0x80; | 
 | 394 | 	rtc_base[0xc] = 0x00; | 
 | 395 | 	rtc_base[0xd] = 0x01; | 
 | 396 | 	rtc_base[0xf] = 0x83; | 
 | 397 |  | 
 | 398 | 	while (i-- > 0) ; | 
 | 399 | 	panic("restart failed\n"); | 
 | 400 | } | 
 | 401 |  | 
 | 402 | static void | 
 | 403 | ev64360_halt(void) | 
 | 404 | { | 
 | 405 | 	while (1) ; | 
 | 406 | 	/* NOTREACHED */ | 
 | 407 | } | 
 | 408 |  | 
 | 409 | static void | 
 | 410 | ev64360_power_off(void) | 
 | 411 | { | 
 | 412 | 	ev64360_halt(); | 
 | 413 | 	/* NOTREACHED */ | 
 | 414 | } | 
 | 415 |  | 
 | 416 | static int | 
 | 417 | ev64360_show_cpuinfo(struct seq_file *m) | 
 | 418 | { | 
 | 419 | 	seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n"); | 
 | 420 | 	seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n"); | 
 | 421 | 	seq_printf(m, "bus speed\t: %dMHz\n", ev64360_bus_frequency/1000/1000); | 
 | 422 |  | 
 | 423 | 	return 0; | 
 | 424 | } | 
 | 425 |  | 
 | 426 | static void __init | 
 | 427 | ev64360_calibrate_decr(void) | 
 | 428 | { | 
 | 429 | 	u32 freq; | 
 | 430 |  | 
 | 431 | 	freq = ev64360_bus_frequency / 4; | 
 | 432 |  | 
 | 433 | 	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | 
 | 434 | 	       (long)freq / 1000000, (long)freq % 1000000); | 
 | 435 |  | 
 | 436 | 	tb_ticks_per_jiffy = freq / HZ; | 
 | 437 | 	tb_to_us = mulhwu_scale_factor(freq, 1000000); | 
 | 438 | } | 
 | 439 |  | 
 | 440 | unsigned long __init | 
 | 441 | ev64360_find_end_of_memory(void) | 
 | 442 | { | 
 | 443 | 	return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | 
 | 444 | 		MV64x60_TYPE_MV64360); | 
 | 445 | } | 
 | 446 |  | 
 | 447 | static inline void | 
 | 448 | ev64360_set_bat(void) | 
 | 449 | { | 
 | 450 | 	mb(); | 
 | 451 | 	mtspr(SPRN_DBAT2U, 0xf0001ffe); | 
 | 452 | 	mtspr(SPRN_DBAT2L, 0xf000002a); | 
 | 453 | 	mb(); | 
 | 454 | } | 
 | 455 |  | 
 | 456 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | 
 | 457 | static void __init | 
 | 458 | ev64360_map_io(void) | 
 | 459 | { | 
 | 460 | 	io_block_mapping(CONFIG_MV64X60_NEW_BASE, \ | 
 | 461 | 			 CONFIG_MV64X60_NEW_BASE, \ | 
 | 462 | 			 0x00020000, _PAGE_IO); | 
 | 463 | } | 
 | 464 | #endif | 
 | 465 |  | 
 | 466 | void __init | 
 | 467 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 
 | 468 | 	      unsigned long r6, unsigned long r7) | 
 | 469 | { | 
 | 470 | 	parse_bootinfo(find_bootinfo()); | 
 | 471 |  | 
 | 472 | 	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer) | 
 | 473 | 	 * are non-zero, then we should use the board info from the bd_t | 
 | 474 | 	 * structure and the cmdline pointed to by r6 instead of the | 
 | 475 | 	 * information from birecs, if any.  Otherwise, use the information | 
| Simon Arlott | a8de5ce | 2007-05-12 05:42:54 +1000 | [diff] [blame] | 476 | 	 * from birecs as discovered by the preceding call to | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 477 | 	 * parse_bootinfo().  This rule should work with both PPCBoot, which | 
 | 478 | 	 * uses a bd_t board info structure, and the kernel boot wrapper, | 
 | 479 | 	 * which uses birecs. | 
 | 480 | 	 */ | 
 | 481 | 	if (r3 && r6) { | 
 | 482 | 		/* copy board info structure */ | 
 | 483 | 		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); | 
 | 484 | 		/* copy command line */ | 
 | 485 | 		*(char *)(r7+KERNELBASE) = 0; | 
 | 486 | 		strcpy(cmd_line, (char *)(r6+KERNELBASE)); | 
 | 487 | 	} | 
 | 488 | 	#ifdef CONFIG_ISA | 
 | 489 | 	isa_mem_base = 0; | 
 | 490 | 	#endif | 
 | 491 |  | 
 | 492 | 	ppc_md.setup_arch = ev64360_setup_arch; | 
 | 493 | 	ppc_md.show_cpuinfo = ev64360_show_cpuinfo; | 
 | 494 | 	ppc_md.init_IRQ = mv64360_init_irq; | 
 | 495 | 	ppc_md.get_irq = mv64360_get_irq; | 
 | 496 | 	ppc_md.restart = ev64360_restart; | 
 | 497 | 	ppc_md.power_off = ev64360_power_off; | 
 | 498 | 	ppc_md.halt = ev64360_halt; | 
 | 499 | 	ppc_md.find_end_of_memory = ev64360_find_end_of_memory; | 
| Lee Nicks | 2104da9 | 2005-11-07 00:58:10 -0800 | [diff] [blame] | 500 | 	ppc_md.init = NULL; | 
 | 501 |  | 
 | 502 | 	ppc_md.time_init = todc_time_init; | 
 | 503 | 	ppc_md.set_rtc_time = todc_set_rtc_time; | 
 | 504 | 	ppc_md.get_rtc_time = todc_get_rtc_time; | 
 | 505 | 	ppc_md.nvram_read_val = todc_direct_read_val; | 
 | 506 | 	ppc_md.nvram_write_val = todc_direct_write_val; | 
| Lee Nicks | 3acb234 | 2005-09-03 15:55:48 -0700 | [diff] [blame] | 507 | 	ppc_md.calibrate_decr = ev64360_calibrate_decr; | 
 | 508 |  | 
 | 509 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | 
 | 510 | 	ppc_md.setup_io_mappings = ev64360_map_io; | 
 | 511 | 	ppc_md.progress = mv64x60_mpsc_progress; | 
 | 512 | 	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); | 
 | 513 | #endif | 
 | 514 |  | 
 | 515 | #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) | 
 | 516 | 	platform_notify = ev64360_platform_notify; | 
 | 517 | #endif | 
 | 518 |  | 
 | 519 | 	ev64360_set_bat(); /* Need for ev64360_find_end_of_memory and progress */ | 
 | 520 | } |