⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prpmc2800.c

📁 linux 内核源代码
💻 C
字号:
/* * Motorola ECC prpmc280/f101 & prpmc2800/f101e platform code. * * Author: Mark A. Greer <mgreer@mvista.com> * * 2007 (c) MontaVista, Software, Inc.  This file is licensed under * the terms of the GNU General Public License version 2.  This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <stdarg.h>#include <stddef.h>#include "types.h"#include "elf.h"#include "page.h"#include "string.h"#include "stdio.h"#include "io.h"#include "ops.h"#include "gunzip_util.h"#include "mv64x60.h"#define KB	1024U#define MB	(KB*KB)#define GB	(KB*MB)#define MHz	(1000U*1000U)#define GHz	(1000U*MHz)#define BOARD_MODEL	"PrPMC2800"#define BOARD_MODEL_MAX	32 /* max strlen(BOARD_MODEL) + 1 */#define EEPROM2_ADDR	0xa4#define EEPROM3_ADDR	0xa8BSS_STACK(16*KB);static u8 *bridge_base;typedef enum {	BOARD_MODEL_PRPMC280,	BOARD_MODEL_PRPMC2800,} prpmc2800_board_model;typedef enum {	BRIDGE_TYPE_MV64360,	BRIDGE_TYPE_MV64362,} prpmc2800_bridge_type;struct prpmc2800_board_info {	prpmc2800_board_model model;	char variant;	prpmc2800_bridge_type bridge_type;	u8 subsys0;	u8 subsys1;	u8 vpd4;	u8 vpd4_mask;	u32 core_speed;	u32 mem_size;	u32 boot_flash;	u32 user_flash;};static struct prpmc2800_board_info prpmc2800_board_info[] = {	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'a',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x00,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 1*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'b',		.bridge_type	= BRIDGE_TYPE_MV64362,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x01,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 0,		.user_flash	= 0,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'c',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x02,		.vpd4_mask	= 0x0f,		.core_speed	= 733*MHz,		.mem_size	= 512*MB,		.boot_flash	= 1*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'd',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x03,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 1*GB,		.boot_flash	= 1*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'e',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x04,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 1*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'f',		.bridge_type	= BRIDGE_TYPE_MV64362,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x05,		.vpd4_mask	= 0x0f,		.core_speed	= 733*MHz,		.mem_size	= 128*MB,		.boot_flash	= 1*MB,		.user_flash	= 0,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'g',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x06,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 256*MB,		.boot_flash	= 1*MB,		.user_flash	= 0,	},	{		.model		= BOARD_MODEL_PRPMC280,		.variant	= 'h',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xff,		.subsys1	= 0xff,		.vpd4		= 0x07,		.vpd4_mask	= 0x0f,		.core_speed	= 1*GHz,		.mem_size	= 1*GB,		.boot_flash	= 1*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'a',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xb2,		.subsys1	= 0x8c,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'b',		.bridge_type	= BRIDGE_TYPE_MV64362,		.subsys0	= 0xb2,		.subsys1	= 0x8d,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 0,		.user_flash	= 0,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'c',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xb2,		.subsys1	= 0x8e,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 733*MHz,		.mem_size	= 512*MB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'd',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xb2,		.subsys1	= 0x8f,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 1*GHz,		.mem_size	= 1*GB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'e',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xa2,		.subsys1	= 0x8a,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 1*GHz,		.mem_size	= 512*MB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'f',		.bridge_type	= BRIDGE_TYPE_MV64362,		.subsys0	= 0xa2,		.subsys1	= 0x8b,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 733*MHz,		.mem_size	= 128*MB,		.boot_flash	= 2*MB,		.user_flash	= 0,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'g',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xa2,		.subsys1	= 0x8c,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 1*GHz,		.mem_size	= 2*GB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},	{		.model		= BOARD_MODEL_PRPMC2800,		.variant	= 'h',		.bridge_type	= BRIDGE_TYPE_MV64360,		.subsys0	= 0xa2,		.subsys1	= 0x8d,		.vpd4		= 0x00,		.vpd4_mask	= 0x00,		.core_speed	= 733*MHz,		.mem_size	= 1*GB,		.boot_flash	= 2*MB,		.user_flash	= 64*MB,	},};static struct prpmc2800_board_info *prpmc2800_get_board_info(u8 *vpd){	struct prpmc2800_board_info *bip;	int i;	for (i=0,bip=prpmc2800_board_info; i<ARRAY_SIZE(prpmc2800_board_info);			i++,bip++)		if ((vpd[0] == bip->subsys0) && (vpd[1] == bip->subsys1)				&& ((vpd[4] & bip->vpd4_mask) == bip->vpd4))			return bip;	return NULL;}/* Get VPD from i2c eeprom 2, then match it to a board info entry */static struct prpmc2800_board_info *prpmc2800_get_bip(void){	struct prpmc2800_board_info *bip;	u8 vpd[5];	int rc;	if (mv64x60_i2c_open())		fatal("Error: Can't open i2c device\n\r");	/* Get VPD from i2c eeprom-2 */	memset(vpd, 0, sizeof(vpd));	rc = mv64x60_i2c_read(EEPROM2_ADDR, vpd, 0x1fde, 2, sizeof(vpd));	if (rc < 0)		fatal("Error: Couldn't read eeprom2\n\r");	mv64x60_i2c_close();	/* Get board type & related info */	bip = prpmc2800_get_board_info(vpd);	if (bip == NULL) {		printf("Error: Unsupported board or corrupted VPD:\n\r");		printf("  0x%x 0x%x 0x%x 0x%x 0x%x\n\r",				vpd[0], vpd[1], vpd[2], vpd[3], vpd[4]);		printf("Using device tree defaults...\n\r");	}	return bip;}static void prpmc2800_bridge_setup(u32 mem_size){	u32 i, v[12], enables, acc_bits;	u32 pci_base_hi, pci_base_lo, size, buf[2];	unsigned long cpu_base;	int rc;	void *devp;	u8 *bridge_pbase, is_coherent;	struct mv64x60_cpu2pci_win *tbl;	bridge_pbase = mv64x60_get_bridge_pbase();	is_coherent = mv64x60_is_coherent();	if (is_coherent)		acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB			| MV64x60_PCI_ACC_CNTL_SWAP_NONE			| MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES			| MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES;	else		acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE			| MV64x60_PCI_ACC_CNTL_SWAP_NONE			| MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES			| MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES;	mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent);	mv64x60_config_pci_windows(bridge_base, bridge_pbase, 0, 0, mem_size,			acc_bits);	/* Get the cpu -> pci i/o & mem mappings from the device tree */	devp = finddevice("/mv64x60/pci@80000000");	if (devp == NULL)		fatal("Error: Missing /mv64x60/pci@80000000"				" device tree node\n\r");	rc = getprop(devp, "ranges", v, sizeof(v));	if (rc != sizeof(v))		fatal("Error: Can't find /mv64x60/pci@80000000/ranges"				" property\n\r");	/* Get the cpu -> pci i/o & mem mappings from the device tree */	devp = finddevice("/mv64x60");	if (devp == NULL)		fatal("Error: Missing /mv64x60 device tree node\n\r");	enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));	enables |= 0x0007fe00; /* Disable all cpu->pci windows */	out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);	for (i=0; i<12; i+=6) {		switch (v[i] & 0xff000000) {		case 0x01000000: /* PCI I/O Space */			tbl = mv64x60_cpu2pci_io;			break;		case 0x02000000: /* PCI MEM Space */			tbl = mv64x60_cpu2pci_mem;			break;		default:			continue;		}		pci_base_hi = v[i+1];		pci_base_lo = v[i+2];		cpu_base = v[i+3];		size = v[i+5];		buf[0] = cpu_base;		buf[1] = size;		if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base))			fatal("Error: Can't translate PCI address 0x%x\n\r",					(u32)cpu_base);		mv64x60_config_cpu2pci_window(bridge_base, 0, pci_base_hi,				pci_base_lo, cpu_base, size, tbl);	}	enables &= ~0x00000600; /* Enable cpu->pci0 i/o, cpu->pci0 mem0 */	out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables);}static void prpmc2800_fixups(void){	u32 v[2], l, mem_size;	int rc;	void *devp;	char model[BOARD_MODEL_MAX];	struct prpmc2800_board_info *bip;	bip = prpmc2800_get_bip(); /* Get board info based on VPD */	mem_size = (bip) ? bip->mem_size : mv64x60_get_mem_size(bridge_base);	prpmc2800_bridge_setup(mem_size); /* Do necessary bridge setup */	/* If the VPD doesn't match what we know about, just use the	 * defaults already in the device tree.	 */	if (!bip)		return;	/* Know the board type so override device tree defaults */	/* Set /model appropriately */	devp = finddevice("/");	if (devp == NULL)		fatal("Error: Missing '/' device tree node\n\r");	memset(model, 0, BOARD_MODEL_MAX);	strncpy(model, BOARD_MODEL, BOARD_MODEL_MAX - 2);	l = strlen(model);	if (bip->model == BOARD_MODEL_PRPMC280)		l--;	model[l++] = bip->variant;	model[l++] = '\0';	setprop(devp, "model", model, l);	/* Set /cpus/PowerPC,7447/clock-frequency */	devp = finddevice("/cpus/PowerPC,7447");	if (devp == NULL)		fatal("Error: Missing proper /cpus device tree node\n\r");	v[0] = bip->core_speed;	setprop(devp, "clock-frequency", &v[0], sizeof(v[0]));	/* Set /memory/reg size */	devp = finddevice("/memory");	if (devp == NULL)		fatal("Error: Missing /memory device tree node\n\r");	v[0] = 0;	v[1] = bip->mem_size;	setprop(devp, "reg", v, sizeof(v));	/* Update /mv64x60/model, if this is a mv64362 */	if (bip->bridge_type == BRIDGE_TYPE_MV64362) {		devp = finddevice("/mv64x60");		if (devp == NULL)			fatal("Error: Missing /mv64x60 device tree node\n\r");		setprop(devp, "model", "mv64362", strlen("mv64362") + 1);	}	/* Set User FLASH size */	devp = finddevice("/mv64x60/flash@a0000000");	if (devp == NULL)		fatal("Error: Missing User FLASH device tree node\n\r");	rc = getprop(devp, "reg", v, sizeof(v));	if (rc != sizeof(v))		fatal("Error: Can't find User FLASH reg property\n\r");	v[1] = bip->user_flash;	setprop(devp, "reg", v, sizeof(v));}#define MV64x60_MPP_CNTL_0	0xf000#define MV64x60_MPP_CNTL_2	0xf008#define MV64x60_GPP_IO_CNTL	0xf100#define MV64x60_GPP_LEVEL_CNTL	0xf110#define MV64x60_GPP_VALUE_SET	0xf118static void prpmc2800_reset(void){	u32 temp;	udelay(5000000);	if (bridge_base != 0) {		temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0));		temp &= 0xFFFF0FFF;		out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp);		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));		temp |= 0x00000004;		out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));		temp |= 0x00000004;		out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);		temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2));		temp &= 0xFFFF0FFF;		out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp);		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL));		temp |= 0x00080000;		out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp);		temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL));		temp |= 0x00080000;		out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp);		out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET),				0x00080004);	}	for (;;);}#define HEAP_SIZE	(16*MB)static struct gunzip_state gzstate;void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,                   unsigned long r6, unsigned long r7){	struct elf_info ei;	char *heap_start, *dtb;	int dt_size = _dtb_end - _dtb_start;	void *vmlinuz_addr = _vmlinux_start;	unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;	char elfheader[256];	if (dt_size <= 0) /* No fdt */		exit();	/*	 * Start heap after end of the kernel (after decompressed to	 * address 0) or the end of the zImage, whichever is higher.	 * That's so things allocated by simple_alloc won't overwrite	 * any part of the zImage and the kernel won't overwrite the dtb	 * when decompressed & relocated.	 */	gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);	gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));	if (!parse_elf32(elfheader, &ei))		exit();	heap_start = (char *)(ei.memsize + ei.elfoffset); /* end of kernel*/	heap_start = max(heap_start, (char *)_end); /* end of zImage */	if ((unsigned)simple_alloc_init(heap_start, HEAP_SIZE, 2*KB, 16)			> (128*MB))		exit();	/* Relocate dtb to safe area past end of zImage & kernel */	dtb = malloc(dt_size);	if (!dtb)		exit();	memmove(dtb, _dtb_start, dt_size);	if (ft_init(dtb, dt_size, 16))		exit();	bridge_base = mv64x60_get_bridge_base();	platform_ops.fixups = prpmc2800_fixups;	platform_ops.exit = prpmc2800_reset;	if (serial_console_init() < 0)		exit();}/* _zimage_start called very early--need to turn off external interrupts */asm ("	.globl _zimage_start\n\	_zimage_start:\n\		mfmsr	10\n\		rlwinm	10,10,0,~(1<<15)	/* Clear MSR_EE */\n\		sync\n\		mtmsr	10\n\		isync\n\		b _zimage_start_lib\n\");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -