diff options
Diffstat (limited to 'arch/arm/mach-integrator/integrator_ap.c')
| -rw-r--r-- | arch/arm/mach-integrator/integrator_ap.c | 278 | 
1 files changed, 208 insertions, 70 deletions
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 7b1055c8e0b..ff1255ae712 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -34,6 +34,9 @@  #include <linux/mtd/physmap.h>  #include <linux/clk.h>  #include <linux/platform_data/clk-integrator.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> +#include <linux/of_platform.h>  #include <video/vga.h>  #include <mach/hardware.h> @@ -161,23 +164,6 @@ static void __init ap_map_io(void)  	vga_base = PCI_MEMORY_VADDR;  } -#define INTEGRATOR_SC_VALID_INT	0x003fffff - -static void __init ap_init_irq(void) -{ -	/* Disable all interrupts initially. */ -	/* Do the core module ones */ -	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); - -	/* do the header card stuff next */ -	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); -	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); - -	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START, -		-1, INTEGRATOR_SC_VALID_INT, NULL); -	integrator_clk_init(false); -} -  #ifdef CONFIG_PM  static unsigned long ic_irq_enable; @@ -270,50 +256,6 @@ static struct physmap_flash_data ap_flash_data = {  	.set_vpp	= ap_flash_set_vpp,  }; -static struct resource cfi_flash_resource = { -	.start		= INTEGRATOR_FLASH_BASE, -	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1, -	.flags		= IORESOURCE_MEM, -}; - -static struct platform_device cfi_flash_device = { -	.name		= "physmap-flash", -	.id		= 0, -	.dev		= { -		.platform_data	= &ap_flash_data, -	}, -	.num_resources	= 1, -	.resource	= &cfi_flash_resource, -}; - -static void __init ap_init(void) -{ -	unsigned long sc_dec; -	int i; - -	platform_device_register(&cfi_flash_device); - -	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET); -	for (i = 0; i < 4; i++) { -		struct lm_device *lmdev; - -		if ((sc_dec & (16 << i)) == 0) -			continue; - -		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL); -		if (!lmdev) -			continue; - -		lmdev->resource.start = 0xc0000000 + 0x10000000 * i; -		lmdev->resource.end = lmdev->resource.start + 0x0fffffff; -		lmdev->resource.flags = IORESOURCE_MEM; -		lmdev->irq = IRQ_AP_EXPINT0 + i; -		lmdev->id = i; - -		lm_device_register(lmdev); -	} -} -  /*   * Where is the timer (VA)?   */ @@ -328,9 +270,9 @@ static u32 notrace integrator_read_sched_clock(void)  	return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);  } -static void integrator_clocksource_init(unsigned long inrate) +static void integrator_clocksource_init(unsigned long inrate, +					void __iomem *base)  { -	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;  	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;  	unsigned long rate = inrate; @@ -347,7 +289,7 @@ static void integrator_clocksource_init(unsigned long inrate)  	setup_sched_clock(integrator_read_sched_clock, 16, rate);  } -static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; +static void __iomem * clkevt_base;  /*   * IRQ handler for the timer @@ -419,11 +361,13 @@ static struct irqaction integrator_timer_irq = {  	.dev_id		= &integrator_clockevent,  }; -static void integrator_clockevent_init(unsigned long inrate) +static void integrator_clockevent_init(unsigned long inrate, +				void __iomem *base, int irq)  {  	unsigned long rate = inrate;  	unsigned int ctrl = 0; +	clkevt_base = base;  	/* Calculate and program a divisor */  	if (rate > 0x100000 * HZ) {  		rate /= 256; @@ -435,7 +379,7 @@ static void integrator_clockevent_init(unsigned long inrate)  	timer_reload = rate / HZ;  	writel(ctrl, clkevt_base + TIMER_CTRL); -	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); +	setup_irq(irq, &integrator_timer_irq);  	clockevents_config_and_register(&integrator_clockevent,  					rate,  					1, @@ -446,9 +390,153 @@ void __init ap_init_early(void)  {  } +#ifdef CONFIG_OF + +static void __init ap_init_timer_of(void) +{ +	struct device_node *node; +	const char *path; +	void __iomem *base; +	int err; +	int irq; +	struct clk *clk; +	unsigned long rate; + +	clk = clk_get_sys("ap_timer", NULL); +	BUG_ON(IS_ERR(clk)); +	clk_prepare_enable(clk); +	rate = clk_get_rate(clk); + +	err = of_property_read_string(of_aliases, +				"arm,timer-primary", &path); +	if (WARN_ON(err)) +		return; +	node = of_find_node_by_path(path); +	base = of_iomap(node, 0); +	if (WARN_ON(!base)) +		return; +	writel(0, base + TIMER_CTRL); +	integrator_clocksource_init(rate, base); + +	err = of_property_read_string(of_aliases, +				"arm,timer-secondary", &path); +	if (WARN_ON(err)) +		return; +	node = of_find_node_by_path(path); +	base = of_iomap(node, 0); +	if (WARN_ON(!base)) +		return; +	irq = irq_of_parse_and_map(node, 0); +	writel(0, base + TIMER_CTRL); +	integrator_clockevent_init(rate, base, irq); +} + +static struct sys_timer ap_of_timer = { +	.init		= ap_init_timer_of, +}; + +static const struct of_device_id fpga_irq_of_match[] __initconst = { +	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, +	{ /* Sentinel */ } +}; + +static void __init ap_init_irq_of(void) +{ +	/* disable core module IRQs */ +	writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); +	of_irq_init(fpga_irq_of_match); +	integrator_clk_init(false); +} + +/* For the Device Tree, add in the UART callbacks as AUXDATA */ +static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = { +	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE, +		"rtc", NULL), +	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE, +		"uart0", &integrator_uart_data), +	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE, +		"uart1", &integrator_uart_data), +	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE, +		"kmi0", NULL), +	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, +		"kmi1", NULL), +	OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE, +		"physmap-flash", &ap_flash_data), +	{ /* sentinel */ }, +}; + +static void __init ap_init_of(void) +{ +	unsigned long sc_dec; +	int i; + +	of_platform_populate(NULL, of_default_bus_match_table, +			ap_auxdata_lookup, NULL); + +	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET); +	for (i = 0; i < 4; i++) { +		struct lm_device *lmdev; + +		if ((sc_dec & (16 << i)) == 0) +			continue; + +		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL); +		if (!lmdev) +			continue; + +		lmdev->resource.start = 0xc0000000 + 0x10000000 * i; +		lmdev->resource.end = lmdev->resource.start + 0x0fffffff; +		lmdev->resource.flags = IORESOURCE_MEM; +		lmdev->irq = IRQ_AP_EXPINT0 + i; +		lmdev->id = i; + +		lm_device_register(lmdev); +	} +} + +static const char * ap_dt_board_compat[] = { +	"arm,integrator-ap", +	NULL, +}; + +DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)") +	.reserve	= integrator_reserve, +	.map_io		= ap_map_io, +	.nr_irqs	= NR_IRQS_INTEGRATOR_AP, +	.init_early	= ap_init_early, +	.init_irq	= ap_init_irq_of, +	.handle_irq	= fpga_handle_irq, +	.timer		= &ap_of_timer, +	.init_machine	= ap_init_of, +	.restart	= integrator_restart, +	.dt_compat      = ap_dt_board_compat, +MACHINE_END + +#endif + +#ifdef CONFIG_ATAGS +  /* - * Set up timer(s). + * This is where non-devicetree initialization code is collected and stashed + * for eventual deletion.   */ + +static struct resource cfi_flash_resource = { +	.start		= INTEGRATOR_FLASH_BASE, +	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1, +	.flags		= IORESOURCE_MEM, +}; + +static struct platform_device cfi_flash_device = { +	.name		= "physmap-flash", +	.id		= 0, +	.dev		= { +		.platform_data	= &ap_flash_data, +	}, +	.num_resources	= 1, +	.resource	= &cfi_flash_resource, +}; +  static void __init ap_init_timer(void)  {  	struct clk *clk; @@ -456,21 +544,69 @@ static void __init ap_init_timer(void)  	clk = clk_get_sys("ap_timer", NULL);  	BUG_ON(IS_ERR(clk)); -	clk_enable(clk); +	clk_prepare_enable(clk);  	rate = clk_get_rate(clk);  	writel(0, TIMER0_VA_BASE + TIMER_CTRL);  	writel(0, TIMER1_VA_BASE + TIMER_CTRL);  	writel(0, TIMER2_VA_BASE + TIMER_CTRL); -	integrator_clocksource_init(rate); -	integrator_clockevent_init(rate); +	integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE); +	integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE, +				IRQ_TIMERINT1);  }  static struct sys_timer ap_timer = {  	.init		= ap_init_timer,  }; +#define INTEGRATOR_SC_VALID_INT	0x003fffff + +static void __init ap_init_irq(void) +{ +	/* Disable all interrupts initially. */ +	/* Do the core module ones */ +	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); + +	/* do the header card stuff next */ +	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); +	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); + +	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START, +		-1, INTEGRATOR_SC_VALID_INT, NULL); +	integrator_clk_init(false); +} + +static void __init ap_init(void) +{ +	unsigned long sc_dec; +	int i; + +	platform_device_register(&cfi_flash_device); + +	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET); +	for (i = 0; i < 4; i++) { +		struct lm_device *lmdev; + +		if ((sc_dec & (16 << i)) == 0) +			continue; + +		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL); +		if (!lmdev) +			continue; + +		lmdev->resource.start = 0xc0000000 + 0x10000000 * i; +		lmdev->resource.end = lmdev->resource.start + 0x0fffffff; +		lmdev->resource.flags = IORESOURCE_MEM; +		lmdev->irq = IRQ_AP_EXPINT0 + i; +		lmdev->id = i; + +		lm_device_register(lmdev); +	} + +	integrator_init(false); +} +  MACHINE_START(INTEGRATOR, "ARM-Integrator")  	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */  	.atag_offset	= 0x100, @@ -484,3 +620,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")  	.init_machine	= ap_init,  	.restart	= integrator_restart,  MACHINE_END + +#endif  |