 7b6d864b48
			
		
	
	
	7b6d864b48
	
	
	
		
			
			Preparing to move the parsing of reboot= to generic kernel code forces the change in reboot_mode handling to use the enum. [akpm@linux-foundation.org: fix arch/arm/mach-socfpga/socfpga.c] Signed-off-by: Robin Holt <holt@sgi.com> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Russ Anderson <rja@sgi.com> Cc: Robin Holt <holt@sgi.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Guan Xuetao <gxt@mprc.pku.edu.cn> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			415 lines
		
	
	
	
		
			11 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			415 lines
		
	
	
	
		
			11 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *
 | |
|  * arch/arm/mach-u300/core.c
 | |
|  *
 | |
|  *
 | |
|  * Copyright (C) 2007-2012 ST-Ericsson SA
 | |
|  * License terms: GNU General Public License (GPL) version 2
 | |
|  * Core platform support, IRQ handling and device definitions.
 | |
|  * Author: Linus Walleij <linus.walleij@stericsson.com>
 | |
|  */
 | |
| #include <linux/kernel.h>
 | |
| #include <linux/pinctrl/machine.h>
 | |
| #include <linux/pinctrl/pinconf-generic.h>
 | |
| #include <linux/platform_data/clk-u300.h>
 | |
| #include <linux/irqchip.h>
 | |
| #include <linux/of_address.h>
 | |
| #include <linux/of_platform.h>
 | |
| #include <linux/clocksource.h>
 | |
| #include <linux/clk.h>
 | |
| 
 | |
| #include <asm/mach/map.h>
 | |
| #include <asm/mach/arch.h>
 | |
| 
 | |
| /*
 | |
|  * These are the large blocks of memory allocated for I/O.
 | |
|  * the defines are used for setting up the I/O memory mapping.
 | |
|  */
 | |
| 
 | |
| /* NAND Flash CS0 */
 | |
| #define U300_NAND_CS0_PHYS_BASE		0x80000000
 | |
| /* NFIF */
 | |
| #define U300_NAND_IF_PHYS_BASE		0x9f800000
 | |
| /* ALE, CLE offset for FSMC NAND */
 | |
| #define PLAT_NAND_CLE			(1 << 16)
 | |
| #define PLAT_NAND_ALE			(1 << 17)
 | |
| /* AHB Peripherals */
 | |
| #define U300_AHB_PER_PHYS_BASE		0xa0000000
 | |
| #define U300_AHB_PER_VIRT_BASE		0xff010000
 | |
| /* FAST Peripherals */
 | |
| #define U300_FAST_PER_PHYS_BASE		0xc0000000
 | |
| #define U300_FAST_PER_VIRT_BASE		0xff020000
 | |
| /* SLOW Peripherals */
 | |
| #define U300_SLOW_PER_PHYS_BASE		0xc0010000
 | |
| #define U300_SLOW_PER_VIRT_BASE		0xff000000
 | |
| /* Boot ROM */
 | |
| #define U300_BOOTROM_PHYS_BASE		0xffff0000
 | |
| #define U300_BOOTROM_VIRT_BASE		0xffff0000
 | |
| /* SEMI config base */
 | |
| #define U300_SEMI_CONFIG_BASE		0x2FFE0000
 | |
| 
 | |
| /*
 | |
|  * AHB peripherals
 | |
|  */
 | |
| 
 | |
| /* AHB Peripherals Bridge Controller */
 | |
| #define U300_AHB_BRIDGE_BASE		(U300_AHB_PER_PHYS_BASE+0x0000)
 | |
| /* Vectored Interrupt Controller 0, servicing 32 interrupts */
 | |
| #define U300_INTCON0_BASE		(U300_AHB_PER_PHYS_BASE+0x1000)
 | |
| #define U300_INTCON0_VBASE		IOMEM(U300_AHB_PER_VIRT_BASE+0x1000)
 | |
| /* Vectored Interrupt Controller 1, servicing 32 interrupts */
 | |
| #define U300_INTCON1_BASE		(U300_AHB_PER_PHYS_BASE+0x2000)
 | |
| #define U300_INTCON1_VBASE		IOMEM(U300_AHB_PER_VIRT_BASE+0x2000)
 | |
| /* Memory Stick Pro (MSPRO) controller */
 | |
| #define U300_MSPRO_BASE			(U300_AHB_PER_PHYS_BASE+0x3000)
 | |
| /* EMIF Configuration Area */
 | |
| #define U300_EMIF_CFG_BASE		(U300_AHB_PER_PHYS_BASE+0x4000)
 | |
| 
 | |
| /*
 | |
|  * FAST peripherals
 | |
|  */
 | |
| 
 | |
| /* FAST bridge control */
 | |
| #define U300_FAST_BRIDGE_BASE		(U300_FAST_PER_PHYS_BASE+0x0000)
 | |
| /* MMC/SD controller */
 | |
| #define U300_MMCSD_BASE			(U300_FAST_PER_PHYS_BASE+0x1000)
 | |
| /* PCM I2S0 controller */
 | |
| #define U300_PCM_I2S0_BASE		(U300_FAST_PER_PHYS_BASE+0x2000)
 | |
| /* PCM I2S1 controller */
 | |
| #define U300_PCM_I2S1_BASE		(U300_FAST_PER_PHYS_BASE+0x3000)
 | |
| /* I2C0 controller */
 | |
| #define U300_I2C0_BASE			(U300_FAST_PER_PHYS_BASE+0x4000)
 | |
| /* I2C1 controller */
 | |
| #define U300_I2C1_BASE			(U300_FAST_PER_PHYS_BASE+0x5000)
 | |
| /* SPI controller */
 | |
| #define U300_SPI_BASE			(U300_FAST_PER_PHYS_BASE+0x6000)
 | |
| /* Fast UART1 on U335 only */
 | |
| #define U300_UART1_BASE			(U300_FAST_PER_PHYS_BASE+0x7000)
 | |
| 
 | |
| /*
 | |
|  * SLOW peripherals
 | |
|  */
 | |
| 
 | |
| /* SLOW bridge control */
 | |
| #define U300_SLOW_BRIDGE_BASE		(U300_SLOW_PER_PHYS_BASE)
 | |
| /* SYSCON */
 | |
| #define U300_SYSCON_BASE		(U300_SLOW_PER_PHYS_BASE+0x1000)
 | |
| #define U300_SYSCON_VBASE		IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000)
 | |
| /* Watchdog */
 | |
| #define U300_WDOG_BASE			(U300_SLOW_PER_PHYS_BASE+0x2000)
 | |
| /* UART0 */
 | |
| #define U300_UART0_BASE			(U300_SLOW_PER_PHYS_BASE+0x3000)
 | |
| /* APP side special timer */
 | |
| #define U300_TIMER_APP_BASE		(U300_SLOW_PER_PHYS_BASE+0x4000)
 | |
| #define U300_TIMER_APP_VBASE		IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000)
 | |
| /* Keypad */
 | |
| #define U300_KEYPAD_BASE		(U300_SLOW_PER_PHYS_BASE+0x5000)
 | |
| /* GPIO */
 | |
| #define U300_GPIO_BASE			(U300_SLOW_PER_PHYS_BASE+0x6000)
 | |
| /* RTC */
 | |
| #define U300_RTC_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
 | |
| /* Bus tracer */
 | |
| #define U300_BUSTR_BASE			(U300_SLOW_PER_PHYS_BASE+0x8000)
 | |
| /* Event handler (hardware queue) */
 | |
| #define U300_EVHIST_BASE		(U300_SLOW_PER_PHYS_BASE+0x9000)
 | |
| /* Genric Timer */
 | |
| #define U300_TIMER_BASE			(U300_SLOW_PER_PHYS_BASE+0xa000)
 | |
| /* PPM */
 | |
| #define U300_PPM_BASE			(U300_SLOW_PER_PHYS_BASE+0xb000)
 | |
| 
 | |
| /*
 | |
|  * REST peripherals
 | |
|  */
 | |
| 
 | |
| /* ISP (image signal processor) */
 | |
| #define U300_ISP_BASE			(0xA0008000)
 | |
| /* DMA Controller base */
 | |
| #define U300_DMAC_BASE			(0xC0020000)
 | |
| /* MSL Base */
 | |
| #define U300_MSL_BASE			(0xc0022000)
 | |
| /* APEX Base */
 | |
| #define U300_APEX_BASE			(0xc0030000)
 | |
| /* Video Encoder Base */
 | |
| #define U300_VIDEOENC_BASE		(0xc0080000)
 | |
| /* XGAM Base */
 | |
| #define U300_XGAM_BASE			(0xd0000000)
 | |
| 
 | |
| /*
 | |
|  * SYSCON addresses applicable to the core machine.
 | |
|  */
 | |
| 
 | |
| /* Chip ID register 16bit (R/-) */
 | |
| #define U300_SYSCON_CIDR					(0x400)
 | |
| /* SMCR */
 | |
| #define U300_SYSCON_SMCR					(0x4d0)
 | |
| #define U300_SYSCON_SMCR_FIELD_MASK				(0x000e)
 | |
| #define U300_SYSCON_SMCR_SEMI_SREFACK_IND			(0x0008)
 | |
| #define U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE			(0x0004)
 | |
| #define U300_SYSCON_SMCR_SEMI_EXT_BOOT_MODE_ENABLE		(0x0002)
 | |
| /* CPU_SW_DBGEN Software Debug Enable 16bit (R/W) */
 | |
| #define U300_SYSCON_CSDR					(0x4f0)
 | |
| #define U300_SYSCON_CSDR_SW_DEBUG_ENABLE			(0x0001)
 | |
| /* PRINT_CONTROL Print Control 16bit (R/-) */
 | |
| #define U300_SYSCON_PCR						(0x4f8)
 | |
| #define U300_SYSCON_PCR_SERV_IND				(0x0001)
 | |
| /* BOOT_CONTROL 16bit (R/-) */
 | |
| #define U300_SYSCON_BCR						(0x4fc)
 | |
| #define U300_SYSCON_BCR_ACC_CPU_SUBSYS_VINITHI_IND		(0x0400)
 | |
| #define U300_SYSCON_BCR_APP_CPU_SUBSYS_VINITHI_IND		(0x0200)
 | |
| #define U300_SYSCON_BCR_EXTRA_BOOT_OPTION_MASK			(0x01FC)
 | |
| #define U300_SYSCON_BCR_APP_BOOT_SERV_MASK			(0x0003)
 | |
| 
 | |
| static void __iomem *syscon_base;
 | |
| 
 | |
| /*
 | |
|  * Static I/O mappings that are needed for booting the U300 platforms. The
 | |
|  * only things we need are the areas where we find the timer, syscon and
 | |
|  * intcon, since the remaining device drivers will map their own memory
 | |
|  * physical to virtual as the need arise.
 | |
|  */
 | |
| static struct map_desc u300_io_desc[] __initdata = {
 | |
| 	{
 | |
| 		.virtual	= U300_SLOW_PER_VIRT_BASE,
 | |
| 		.pfn		= __phys_to_pfn(U300_SLOW_PER_PHYS_BASE),
 | |
| 		.length		= SZ_64K,
 | |
| 		.type		= MT_DEVICE,
 | |
| 	},
 | |
| 	{
 | |
| 		.virtual	= U300_AHB_PER_VIRT_BASE,
 | |
| 		.pfn		= __phys_to_pfn(U300_AHB_PER_PHYS_BASE),
 | |
| 		.length		= SZ_32K,
 | |
| 		.type		= MT_DEVICE,
 | |
| 	},
 | |
| 	{
 | |
| 		.virtual	= U300_FAST_PER_VIRT_BASE,
 | |
| 		.pfn		= __phys_to_pfn(U300_FAST_PER_PHYS_BASE),
 | |
| 		.length		= SZ_32K,
 | |
| 		.type		= MT_DEVICE,
 | |
| 	},
 | |
| };
 | |
| 
 | |
| static void __init u300_map_io(void)
 | |
| {
 | |
| 	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
 | |
| }
 | |
| 
 | |
| static unsigned long pin_pullup_conf[] = {
 | |
| 	PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 1),
 | |
| };
 | |
| 
 | |
| static unsigned long pin_highz_conf[] = {
 | |
| 	PIN_CONF_PACKED(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0),
 | |
| };
 | |
| 
 | |
| /* Pin control settings */
 | |
| static struct pinctrl_map __initdata u300_pinmux_map[] = {
 | |
| 	/* anonymous maps for chip power and EMIFs */
 | |
| 	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "power"),
 | |
| 	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif0"),
 | |
| 	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif1"),
 | |
| 	/* per-device maps for MMC/SD, SPI and UART */
 | |
| 	PIN_MAP_MUX_GROUP_DEFAULT("mmci",  "pinctrl-u300", NULL, "mmc0"),
 | |
| 	PIN_MAP_MUX_GROUP_DEFAULT("pl022", "pinctrl-u300", NULL, "spi0"),
 | |
| 	PIN_MAP_MUX_GROUP_DEFAULT("uart0", "pinctrl-u300", NULL, "uart0"),
 | |
| 	/* This pin is used for clock return rather than GPIO */
 | |
| 	PIN_MAP_CONFIGS_PIN_DEFAULT("mmci", "pinctrl-u300", "PIO APP GPIO 11",
 | |
| 				    pin_pullup_conf),
 | |
| 	/* This pin is used for card detect */
 | |
| 	PIN_MAP_CONFIGS_PIN_DEFAULT("mmci", "pinctrl-u300", "PIO MS INS",
 | |
| 				    pin_highz_conf),
 | |
| };
 | |
| 
 | |
| struct db_chip {
 | |
| 	u16 chipid;
 | |
| 	const char *name;
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * This is a list of the Digital Baseband chips used in the U300 platform.
 | |
|  */
 | |
| static struct db_chip db_chips[] __initdata = {
 | |
| 	{
 | |
| 		.chipid = 0xb800,
 | |
| 		.name = "DB3000",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xc000,
 | |
| 		.name = "DB3100",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xc800,
 | |
| 		.name = "DB3150",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xd800,
 | |
| 		.name = "DB3200",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xe000,
 | |
| 		.name = "DB3250",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xe800,
 | |
| 		.name = "DB3210",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xf000,
 | |
| 		.name = "DB3350 P1x",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0xf100,
 | |
| 		.name = "DB3350 P2x",
 | |
| 	},
 | |
| 	{
 | |
| 		.chipid = 0x0000, /* List terminator */
 | |
| 		.name = NULL,
 | |
| 	}
 | |
| };
 | |
| 
 | |
| static void __init u300_init_check_chip(void)
 | |
| {
 | |
| 
 | |
| 	u16 val;
 | |
| 	struct db_chip *chip;
 | |
| 	const char *chipname;
 | |
| 	const char unknown[] = "UNKNOWN";
 | |
| 
 | |
| 	/* Read out and print chip ID */
 | |
| 	val = readw(syscon_base + U300_SYSCON_CIDR);
 | |
| 	/* This is in funky bigendian order... */
 | |
| 	val = (val & 0xFFU) << 8 | (val >> 8);
 | |
| 	chip = db_chips;
 | |
| 	chipname = unknown;
 | |
| 
 | |
| 	for ( ; chip->chipid; chip++) {
 | |
| 		if (chip->chipid == (val & 0xFF00U)) {
 | |
| 			chipname = chip->name;
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 	printk(KERN_INFO "Initializing U300 system on %s baseband chip " \
 | |
| 	       "(chip ID 0x%04x)\n", chipname, val);
 | |
| 
 | |
| 	if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
 | |
| 		printk(KERN_ERR "Platform configured for BS335 " \
 | |
| 		       " with DB3350 but %s detected, expect problems!",
 | |
| 		       chipname);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Forward declare this function from the watchdog */
 | |
| void coh901327_watchdog_reset(void);
 | |
| 
 | |
| static void u300_restart(enum reboot_mode mode, const char *cmd)
 | |
| {
 | |
| 	switch (mode) {
 | |
| 	case REBOOT_SOFT:
 | |
| 	case REBOOT_HARD:
 | |
| #ifdef CONFIG_COH901327_WATCHDOG
 | |
| 		coh901327_watchdog_reset();
 | |
| #endif
 | |
| 		break;
 | |
| 	default:
 | |
| 		/* Do nothing */
 | |
| 		break;
 | |
| 	}
 | |
| 	/* Wait for system do die/reset. */
 | |
| 	while (1);
 | |
| }
 | |
| 
 | |
| /* These are mostly to get the right device names for the clock lookups */
 | |
| static struct of_dev_auxdata u300_auxdata_lookup[] __initdata = {
 | |
| 	OF_DEV_AUXDATA("stericsson,pinctrl-u300", U300_SYSCON_BASE,
 | |
| 		"pinctrl-u300", NULL),
 | |
| 	OF_DEV_AUXDATA("stericsson,gpio-coh901", U300_GPIO_BASE,
 | |
| 		"u300-gpio", NULL),
 | |
| 	OF_DEV_AUXDATA("stericsson,coh901327", U300_WDOG_BASE,
 | |
| 		"coh901327_wdog", NULL),
 | |
| 	OF_DEV_AUXDATA("stericsson,coh901331", U300_RTC_BASE,
 | |
| 		"rtc-coh901331", NULL),
 | |
| 	OF_DEV_AUXDATA("stericsson,coh901318", U300_DMAC_BASE,
 | |
| 		"coh901318", NULL),
 | |
| 	OF_DEV_AUXDATA("stericsson,fsmc-nand", U300_NAND_IF_PHYS_BASE,
 | |
| 		"fsmc-nand", NULL),
 | |
| 	OF_DEV_AUXDATA("arm,primecell", U300_UART0_BASE,
 | |
| 		"uart0", NULL),
 | |
| 	OF_DEV_AUXDATA("arm,primecell", U300_UART1_BASE,
 | |
| 		"uart1", NULL),
 | |
| 	OF_DEV_AUXDATA("arm,primecell", U300_SPI_BASE,
 | |
| 		"pl022", NULL),
 | |
| 	OF_DEV_AUXDATA("st,ddci2c", U300_I2C0_BASE,
 | |
| 		"stu300.0", NULL),
 | |
| 	OF_DEV_AUXDATA("st,ddci2c", U300_I2C1_BASE,
 | |
| 		"stu300.1", NULL),
 | |
| 	OF_DEV_AUXDATA("arm,primecell", U300_MMCSD_BASE,
 | |
| 		"mmci", NULL),
 | |
| 	{ /* sentinel */ },
 | |
| };
 | |
| 
 | |
| static void __init u300_init_irq_dt(void)
 | |
| {
 | |
| 	struct device_node *syscon;
 | |
| 	struct clk *clk;
 | |
| 
 | |
| 	syscon = of_find_node_by_path("/syscon@c0011000");
 | |
| 	if (!syscon) {
 | |
| 		pr_crit("could not find syscon node\n");
 | |
| 		return;
 | |
| 	}
 | |
| 	syscon_base = of_iomap(syscon, 0);
 | |
| 	if (!syscon_base) {
 | |
| 		pr_crit("could not remap syscon\n");
 | |
| 		return;
 | |
| 	}
 | |
| 	/* initialize clocking early, we want to clock the INTCON */
 | |
| 	u300_clk_init(syscon_base);
 | |
| 
 | |
| 	/* Bootstrap EMIF and SEMI clocks */
 | |
| 	clk = clk_get_sys("pl172", NULL);
 | |
| 	BUG_ON(IS_ERR(clk));
 | |
| 	clk_prepare_enable(clk);
 | |
| 	clk = clk_get_sys("semi", NULL);
 | |
| 	BUG_ON(IS_ERR(clk));
 | |
| 	clk_prepare_enable(clk);
 | |
| 
 | |
| 	/* Clock the interrupt controller */
 | |
| 	clk = clk_get_sys("intcon", NULL);
 | |
| 	BUG_ON(IS_ERR(clk));
 | |
| 	clk_prepare_enable(clk);
 | |
| 
 | |
| 	irqchip_init();
 | |
| }
 | |
| 
 | |
| static void __init u300_init_machine_dt(void)
 | |
| {
 | |
| 	u16 val;
 | |
| 
 | |
| 	/* Check what platform we run and print some status information */
 | |
| 	u300_init_check_chip();
 | |
| 
 | |
| 	/* Initialize pinmuxing */
 | |
| 	pinctrl_register_mappings(u300_pinmux_map,
 | |
| 				  ARRAY_SIZE(u300_pinmux_map));
 | |
| 
 | |
| 	of_platform_populate(NULL, of_default_bus_match_table,
 | |
| 			u300_auxdata_lookup, NULL);
 | |
| 
 | |
| 	/* Enable SEMI self refresh */
 | |
| 	val = readw(syscon_base + U300_SYSCON_SMCR) |
 | |
| 		U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
 | |
| 	writew(val, syscon_base + U300_SYSCON_SMCR);
 | |
| }
 | |
| 
 | |
| static const char * u300_board_compat[] = {
 | |
| 	"stericsson,u300",
 | |
| 	NULL,
 | |
| };
 | |
| 
 | |
| DT_MACHINE_START(U300_DT, "U300 S335/B335 (Device Tree)")
 | |
| 	.map_io		= u300_map_io,
 | |
| 	.init_irq	= u300_init_irq_dt,
 | |
| 	.init_time	= clocksource_of_init,
 | |
| 	.init_machine	= u300_init_machine_dt,
 | |
| 	.restart	= u300_restart,
 | |
| 	.dt_compat      = u300_board_compat,
 | |
| MACHINE_END
 |