| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  linux/arch/arm/mach-integrator/integrator_ap.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/list.h>
 | 
					
						
							| 
									
										
										
										
											2005-10-29 19:07:23 +01:00
										 |  |  | #include <linux/platform_device.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | #include <linux/syscore_ops.h>
 | 
					
						
							| 
									
										
										
										
											2006-01-07 13:52:45 +00:00
										 |  |  | #include <linux/amba/bus.h>
 | 
					
						
							|  |  |  | #include <linux/amba/kmi.h>
 | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | #include <linux/clocksource.h>
 | 
					
						
							|  |  |  | #include <linux/clockchips.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							| 
									
										
										
										
											2008-09-06 12:10:45 +01:00
										 |  |  | #include <linux/io.h>
 | 
					
						
							| 
									
										
										
										
											2012-10-31 22:04:31 +01:00
										 |  |  | #include <linux/irqchip/versatile-fpga.h>
 | 
					
						
							| 
									
										
										
										
											2011-05-18 10:51:52 +01:00
										 |  |  | #include <linux/mtd/physmap.h>
 | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | #include <linux/clk.h>
 | 
					
						
							| 
									
										
										
										
											2012-06-11 17:33:12 +02:00
										 |  |  | #include <linux/platform_data/clk-integrator.h>
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | #include <linux/of_irq.h>
 | 
					
						
							|  |  |  | #include <linux/of_address.h>
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | #include <linux/of_platform.h>
 | 
					
						
							| 
									
										
										
										
											2012-11-02 01:31:10 +01:00
										 |  |  | #include <linux/stat.h>
 | 
					
						
							|  |  |  | #include <linux/sys_soc.h>
 | 
					
						
							| 
									
										
										
										
											2012-11-17 19:24:23 +01:00
										 |  |  | #include <linux/termios.h>
 | 
					
						
							| 
									
										
										
										
											2011-09-04 23:40:08 +02:00
										 |  |  | #include <video/vga.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 16:14:15 +01:00
										 |  |  | #include <mach/hardware.h>
 | 
					
						
							| 
									
										
										
										
											2010-01-14 19:59:37 +00:00
										 |  |  | #include <mach/platform.h>
 | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | #include <asm/hardware/arm_timer.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/setup.h>
 | 
					
						
							| 
									
										
										
										
											2005-10-30 15:03:48 -08:00
										 |  |  | #include <asm/param.h>		/* HZ */
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/mach-types.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-31 23:38:23 +01:00
										 |  |  | #include <asm/sched_clock.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 16:14:15 +01:00
										 |  |  | #include <mach/lm.h>
 | 
					
						
							| 
									
										
										
										
											2012-02-26 10:46:48 +01:00
										 |  |  | #include <mach/irqs.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <asm/mach/arch.h>
 | 
					
						
							|  |  |  | #include <asm/mach/irq.h>
 | 
					
						
							|  |  |  | #include <asm/mach/map.h>
 | 
					
						
							| 
									
										
										
										
											2012-07-13 16:27:22 -05:00
										 |  |  | #include <asm/mach/pci.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/mach/time.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-22 18:18:57 +01:00
										 |  |  | #include "common.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | /* Base address to the AP system controller */ | 
					
						
							| 
									
										
										
										
											2012-11-17 19:24:23 +01:00
										 |  |  | void __iomem *ap_syscon_base; | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx | 
					
						
							|  |  |  |  * is the (PA >> 12). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Setup a VA for the Integrator interrupt controller (for header #0, | 
					
						
							|  |  |  |  * just for now). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-01-19 15:32:15 +00:00
										 |  |  | #define VA_IC_BASE	__io_address(INTEGRATOR_IC_BASE)
 | 
					
						
							|  |  |  | #define VA_EBI_BASE	__io_address(INTEGRATOR_EBI_BASE)
 | 
					
						
							|  |  |  | #define VA_CMIC_BASE	__io_address(INTEGRATOR_HDR_IC)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Logical      Physical | 
					
						
							|  |  |  |  * e8000000	40000000	PCI memory		PHYS_PCI_MEM_BASE	(max 512M) | 
					
						
							|  |  |  |  * ec000000	61000000	PCI config space	PHYS_PCI_CONFIG_BASE	(max 16M) | 
					
						
							|  |  |  |  * ed000000	62000000	PCI V3 regs		PHYS_PCI_V3_BASE	(max 64k) | 
					
						
							| 
									
										
										
										
											2012-07-13 16:27:22 -05:00
										 |  |  |  * fee00000	60000000	PCI IO			PHYS_PCI_IO_BASE	(max 16M) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * ef000000			Cache flush | 
					
						
							|  |  |  |  * f1000000	10000000	Core module registers | 
					
						
							|  |  |  |  * f1100000	11000000	System controller registers | 
					
						
							|  |  |  |  * f1200000	12000000	EBI registers | 
					
						
							|  |  |  |  * f1300000	13000000	Counter/Timer | 
					
						
							|  |  |  |  * f1400000	14000000	Interrupt controller | 
					
						
							|  |  |  |  * f1600000	16000000	UART 0 | 
					
						
							|  |  |  |  * f1700000	17000000	UART 1 | 
					
						
							|  |  |  |  * f1a00000	1a000000	Debug LEDs | 
					
						
							|  |  |  |  * f1b00000	1b000000	GPIO | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-14 13:50:57 +01:00
										 |  |  | static struct map_desc ap_io_desc[] __initdata __maybe_unused = { | 
					
						
							| 
									
										
										
										
											2005-10-28 15:19:10 +01:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_HDR_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_HDR_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_CT_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_CT_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_IC_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_IC_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_UART0_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_UART0_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2010-01-17 19:59:58 +00:00
										 |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_AP_GPIO_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE), | 
					
						
							| 
									
										
										
										
											2005-10-28 15:19:10 +01:00
										 |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2012-09-14 20:16:39 +00:00
										 |  |  | 		.virtual	= (unsigned long)PCI_MEMORY_VADDR, | 
					
						
							| 
									
										
										
										
											2005-10-28 15:19:10 +01:00
										 |  |  | 		.pfn		= __phys_to_pfn(PHYS_PCI_MEM_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_16M, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2012-09-14 20:16:39 +00:00
										 |  |  | 		.virtual	= (unsigned long)PCI_CONFIG_VADDR, | 
					
						
							| 
									
										
										
										
											2005-10-28 15:19:10 +01:00
										 |  |  | 		.pfn		= __phys_to_pfn(PHYS_PCI_CONFIG_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_16M, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, { | 
					
						
							| 
									
										
										
										
											2012-09-14 20:16:39 +00:00
										 |  |  | 		.virtual	= (unsigned long)PCI_V3_VADDR, | 
					
						
							| 
									
										
										
										
											2005-10-28 15:19:10 +01:00
										 |  |  | 		.pfn		= __phys_to_pfn(PHYS_PCI_V3_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_64K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __init ap_map_io(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc)); | 
					
						
							| 
									
										
										
										
											2012-09-24 07:22:02 +00:00
										 |  |  | 	vga_base = (unsigned long)PCI_MEMORY_VADDR; | 
					
						
							| 
									
										
										
										
											2012-07-13 16:27:22 -05:00
										 |  |  | 	pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE)); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_PM
 | 
					
						
							|  |  |  | static unsigned long ic_irq_enable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | static int irq_suspend(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | static void irq_resume(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* disable all irq sources */ | 
					
						
							|  |  |  | 	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); | 
					
						
							|  |  |  | 	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); | 
					
						
							|  |  |  | 	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define irq_suspend NULL
 | 
					
						
							|  |  |  | #define irq_resume NULL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | static struct syscore_ops irq_syscore_ops = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.suspend	= irq_suspend, | 
					
						
							|  |  |  | 	.resume		= irq_resume, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | static int __init irq_syscore_init(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | 	register_syscore_ops(&irq_syscore_ops); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-22 22:02:55 +02:00
										 |  |  | device_initcall(irq_syscore_init); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Flash handling. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
 | 
					
						
							|  |  |  | #define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 10:51:52 +01:00
										 |  |  | static int ap_flash_init(struct platform_device *dev) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	u32 tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, | 
					
						
							|  |  |  | 	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE; | 
					
						
							|  |  |  | 	writel(tmp, EBI_CSR1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) { | 
					
						
							|  |  |  | 		writel(0xa05f, EBI_LOCK); | 
					
						
							|  |  |  | 		writel(tmp, EBI_CSR1); | 
					
						
							|  |  |  | 		writel(0, EBI_LOCK); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 10:51:52 +01:00
										 |  |  | static void ap_flash_exit(struct platform_device *dev) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	u32 tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, | 
					
						
							|  |  |  | 	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE; | 
					
						
							|  |  |  | 	writel(tmp, EBI_CSR1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) { | 
					
						
							|  |  |  | 		writel(0xa05f, EBI_LOCK); | 
					
						
							|  |  |  | 		writel(tmp, EBI_CSR1); | 
					
						
							|  |  |  | 		writel(0, EBI_LOCK); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 10:51:55 +01:00
										 |  |  | static void ap_flash_set_vpp(struct platform_device *pdev, int on) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	if (on) | 
					
						
							|  |  |  | 		writel(INTEGRATOR_SC_CTRL_nFLVPPEN, | 
					
						
							|  |  |  | 		       ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		writel(INTEGRATOR_SC_CTRL_nFLVPPEN, | 
					
						
							|  |  |  | 		       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 10:51:52 +01:00
										 |  |  | static struct physmap_flash_data ap_flash_data = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.width		= 4, | 
					
						
							|  |  |  | 	.init		= ap_flash_init, | 
					
						
							|  |  |  | 	.exit		= ap_flash_exit, | 
					
						
							|  |  |  | 	.set_vpp	= ap_flash_set_vpp, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-17 19:24:23 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * For the PL010 found in the Integrator/AP some of the UART control is | 
					
						
							|  |  |  |  * implemented in the system controller and accessed using a callback | 
					
						
							|  |  |  |  * from the driver. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void integrator_uart_set_mctrl(struct amba_device *dev, | 
					
						
							|  |  |  | 				void __iomem *base, unsigned int mctrl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; | 
					
						
							|  |  |  | 	u32 phybase = dev->res.start; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (phybase == INTEGRATOR_UART0_BASE) { | 
					
						
							|  |  |  | 		/* UART0 */ | 
					
						
							|  |  |  | 		rts_mask = 1 << 4; | 
					
						
							|  |  |  | 		dtr_mask = 1 << 5; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* UART1 */ | 
					
						
							|  |  |  | 		rts_mask = 1 << 6; | 
					
						
							|  |  |  | 		dtr_mask = 1 << 7; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mctrl & TIOCM_RTS) | 
					
						
							|  |  |  | 		ctrlc |= rts_mask; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ctrls |= rts_mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mctrl & TIOCM_DTR) | 
					
						
							|  |  |  | 		ctrlc |= dtr_mask; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ctrls |= dtr_mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET); | 
					
						
							|  |  |  | 	__raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct amba_pl010_data ap_uart_data = { | 
					
						
							|  |  |  | 	.set_mctrl = integrator_uart_set_mctrl, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Where is the timer (VA)? | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-09-14 20:16:39 +00:00
										 |  |  | #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
 | 
					
						
							|  |  |  | #define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
 | 
					
						
							|  |  |  | #define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
 | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static unsigned long timer_reload; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-31 23:38:23 +01:00
										 |  |  | static u32 notrace integrator_read_sched_clock(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | static void integrator_clocksource_init(unsigned long inrate, | 
					
						
							|  |  |  | 					void __iomem *base) | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-06 08:08:13 +01:00
										 |  |  | 	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	unsigned long rate = inrate; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	if (rate >= 1500000) { | 
					
						
							|  |  |  | 		rate /= 16; | 
					
						
							| 
									
										
										
										
											2011-09-06 08:08:13 +01:00
										 |  |  | 		ctrl |= TIMER_CTRL_DIV16; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writel(0xffff, base + TIMER_LOAD); | 
					
						
							| 
									
										
										
										
											2011-09-06 08:08:13 +01:00
										 |  |  | 	writel(ctrl, base + TIMER_CTRL); | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-08 15:35:22 +01:00
										 |  |  | 	clocksource_mmio_init(base + TIMER_VALUE, "timer2", | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 			rate, 200, 16, clocksource_mmio_readl_down); | 
					
						
							| 
									
										
										
										
											2012-01-31 23:38:23 +01:00
										 |  |  | 	setup_sched_clock(integrator_read_sched_clock, 16, rate); | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | static void __iomem * clkevt_base; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * IRQ handler for the timer | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct clock_event_device *evt = dev_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clear the interrupt */ | 
					
						
							|  |  |  | 	writel(1, clkevt_base + TIMER_INTCLR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	evt->event_handler(evt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return IRQ_HANDLED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 21:21:42 +01:00
										 |  |  | 	/* Disable timer */ | 
					
						
							|  |  |  | 	writel(ctrl, clkevt_base + TIMER_CTRL); | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 21:21:42 +01:00
										 |  |  | 	switch (mode) { | 
					
						
							|  |  |  | 	case CLOCK_EVT_MODE_PERIODIC: | 
					
						
							|  |  |  | 		/* Enable the timer and start the periodic tick */ | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 		writel(timer_reload, clkevt_base + TIMER_LOAD); | 
					
						
							|  |  |  | 		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; | 
					
						
							| 
									
										
										
										
											2011-09-08 21:21:42 +01:00
										 |  |  | 		writel(ctrl, clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case CLOCK_EVT_MODE_ONESHOT: | 
					
						
							|  |  |  | 		/* Leave the timer disabled, .set_next_event will enable it */ | 
					
						
							|  |  |  | 		ctrl &= ~TIMER_CTRL_PERIODIC; | 
					
						
							|  |  |  | 		writel(ctrl, clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case CLOCK_EVT_MODE_UNUSED: | 
					
						
							|  |  |  | 	case CLOCK_EVT_MODE_SHUTDOWN: | 
					
						
							|  |  |  | 	case CLOCK_EVT_MODE_RESUME: | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		/* Just leave in disabled state */ | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 	writel(next, clkevt_base + TIMER_LOAD); | 
					
						
							|  |  |  | 	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct clock_event_device integrator_clockevent = { | 
					
						
							|  |  |  | 	.name		= "timer1", | 
					
						
							| 
									
										
										
										
											2011-09-08 21:21:42 +01:00
										 |  |  | 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 	.set_mode	= clkevt_set_mode, | 
					
						
							|  |  |  | 	.set_next_event	= clkevt_set_next_event, | 
					
						
							|  |  |  | 	.rating		= 300, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct irqaction integrator_timer_irq = { | 
					
						
							|  |  |  | 	.name		= "timer", | 
					
						
							|  |  |  | 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 
					
						
							|  |  |  | 	.handler	= integrator_timer_interrupt, | 
					
						
							|  |  |  | 	.dev_id		= &integrator_clockevent, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | static void integrator_clockevent_init(unsigned long inrate, | 
					
						
							|  |  |  | 				void __iomem *base, int irq) | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	unsigned long rate = inrate; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 	unsigned int ctrl = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 	clkevt_base = base; | 
					
						
							| 
									
										
										
										
											2011-09-08 21:22:32 +01:00
										 |  |  | 	/* Calculate and program a divisor */ | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	if (rate > 0x100000 * HZ) { | 
					
						
							|  |  |  | 		rate /= 256; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 		ctrl |= TIMER_CTRL_DIV256; | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	} else if (rate > 0x10000 * HZ) { | 
					
						
							|  |  |  | 		rate /= 16; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 		ctrl |= TIMER_CTRL_DIV16; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	timer_reload = rate / HZ; | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 	writel(ctrl, clkevt_base + TIMER_CTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 	setup_irq(irq, &integrator_timer_irq); | 
					
						
							| 
									
										
										
										
											2011-09-08 21:22:32 +01:00
										 |  |  | 	clockevents_config_and_register(&integrator_clockevent, | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 					rate, | 
					
						
							| 
									
										
										
										
											2011-09-08 21:22:32 +01:00
										 |  |  | 					1, | 
					
						
							|  |  |  | 					0xffffU); | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-11 17:33:12 +02:00
										 |  |  | void __init ap_init_early(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | #ifdef CONFIG_OF
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-08 12:40:59 -07:00
										 |  |  | static void __init ap_of_timer_init(void) | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	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 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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | /* 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, | 
					
						
							| 
									
										
										
										
											2012-11-17 19:24:23 +01:00
										 |  |  | 		"uart0", &ap_uart_data), | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE, | 
					
						
							| 
									
										
										
										
											2012-11-17 19:24:23 +01:00
										 |  |  | 		"uart1", &ap_uart_data), | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE, | 
					
						
							|  |  |  | 		"kmi0", NULL), | 
					
						
							|  |  |  | 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE, | 
					
						
							|  |  |  | 		"kmi1", NULL), | 
					
						
							| 
									
										
										
										
											2012-09-06 09:09:11 +01:00
										 |  |  | 	OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE, | 
					
						
							|  |  |  | 		"physmap-flash", &ap_flash_data), | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	{ /* sentinel */ }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __init ap_init_of(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long sc_dec; | 
					
						
							| 
									
										
										
										
											2012-11-02 01:31:10 +01:00
										 |  |  | 	struct device_node *root; | 
					
						
							|  |  |  | 	struct device_node *syscon; | 
					
						
							|  |  |  | 	struct device *parent; | 
					
						
							|  |  |  | 	struct soc_device *soc_dev; | 
					
						
							|  |  |  | 	struct soc_device_attribute *soc_dev_attr; | 
					
						
							|  |  |  | 	u32 ap_sc_id; | 
					
						
							|  |  |  | 	int err; | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-02 01:31:10 +01:00
										 |  |  | 	/* Here we create an SoC device for the root node */ | 
					
						
							|  |  |  | 	root = of_find_node_by_path("/"); | 
					
						
							|  |  |  | 	if (!root) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	syscon = of_find_node_by_path("/syscon"); | 
					
						
							|  |  |  | 	if (!syscon) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ap_syscon_base = of_iomap(syscon, 0); | 
					
						
							|  |  |  | 	if (!ap_syscon_base) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ap_sc_id = readl(ap_syscon_base); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!soc_dev_attr) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = of_property_read_string(root, "compatible", | 
					
						
							|  |  |  | 				      &soc_dev_attr->soc_id); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	err = of_property_read_string(root, "model", &soc_dev_attr->machine); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	soc_dev_attr->family = "Integrator"; | 
					
						
							|  |  |  | 	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c", | 
					
						
							|  |  |  | 					   'A' + (ap_sc_id & 0x0f)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	soc_dev = soc_device_register(soc_dev_attr); | 
					
						
							|  |  |  | 	if (IS_ERR_OR_NULL(soc_dev)) { | 
					
						
							|  |  |  | 		kfree(soc_dev_attr->revision); | 
					
						
							|  |  |  | 		kfree(soc_dev_attr); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parent = soc_device_to_device(soc_dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!IS_ERR_OR_NULL(parent)) | 
					
						
							|  |  |  | 		integrator_init_sysfs(parent, ap_sc_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	of_platform_populate(root, of_default_bus_match_table, | 
					
						
							|  |  |  | 			ap_auxdata_lookup, parent); | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET); | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 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, | 
					
						
							|  |  |  | 	.init_early	= ap_init_early, | 
					
						
							|  |  |  | 	.init_irq	= ap_init_irq_of, | 
					
						
							|  |  |  | 	.handle_irq	= fpga_handle_irq, | 
					
						
							| 
									
										
										
										
											2012-11-08 12:40:59 -07:00
										 |  |  | 	.init_time	= ap_of_timer_init, | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	.init_machine	= ap_init_of, | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 	.restart	= integrator_restart, | 
					
						
							|  |  |  | 	.dt_compat      = ap_dt_board_compat, | 
					
						
							|  |  |  | MACHINE_END | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_ATAGS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * For the ATAG boot some static mappings are needed. This will | 
					
						
							|  |  |  |  * go away with the ATAG support down the road. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct map_desc ap_io_desc_atag[] __initdata = { | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE), | 
					
						
							|  |  |  | 		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE), | 
					
						
							|  |  |  | 		.length		= SZ_4K, | 
					
						
							|  |  |  | 		.type		= MT_DEVICE | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __init ap_map_io_atag(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	iotable_init(ap_io_desc_atag, ARRAY_SIZE(ap_io_desc_atag)); | 
					
						
							|  |  |  | 	ap_map_io(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  |  * This is where non-devicetree initialization code is collected and stashed | 
					
						
							|  |  |  |  * for eventual deletion. | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:09:11 +01:00
										 |  |  | 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, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-08 12:40:59 -07:00
										 |  |  | static void __init ap_timer_init(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	struct clk *clk; | 
					
						
							|  |  |  | 	unsigned long rate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	clk = clk_get_sys("ap_timer", NULL); | 
					
						
							|  |  |  | 	BUG_ON(IS_ERR(clk)); | 
					
						
							| 
									
										
										
										
											2012-08-05 22:37:55 +02:00
										 |  |  | 	clk_prepare_enable(clk); | 
					
						
							| 
									
										
										
										
											2011-09-08 21:23:15 +01:00
										 |  |  | 	rate = clk_get_rate(clk); | 
					
						
							| 
									
										
										
										
											2010-01-17 16:20:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	writel(0, TIMER0_VA_BASE + TIMER_CTRL); | 
					
						
							|  |  |  | 	writel(0, TIMER1_VA_BASE + TIMER_CTRL); | 
					
						
							|  |  |  | 	writel(0, TIMER2_VA_BASE + TIMER_CTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 	integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE); | 
					
						
							|  |  |  | 	integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE, | 
					
						
							|  |  |  | 				IRQ_TIMERINT1); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | #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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | static void __init ap_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long sc_dec; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	platform_device_register(&cfi_flash_device); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-06 18:25:12 +00:00
										 |  |  | 	ap_syscon_base = __io_address(INTEGRATOR_SC_BASE); | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET); | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:47 +01:00
										 |  |  | 	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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | MACHINE_START(INTEGRATOR, "ARM-Integrator") | 
					
						
							| 
									
										
										
										
											2005-07-03 17:38:58 +01:00
										 |  |  | 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ | 
					
						
							| 
									
										
										
										
											2011-07-05 22:38:12 -04:00
										 |  |  | 	.atag_offset	= 0x100, | 
					
						
							| 
									
										
										
										
											2010-05-22 18:18:57 +01:00
										 |  |  | 	.reserve	= integrator_reserve, | 
					
						
							| 
									
										
										
										
											2012-11-04 20:49:15 +01:00
										 |  |  | 	.map_io		= ap_map_io_atag, | 
					
						
							| 
									
										
										
										
											2012-06-11 17:33:12 +02:00
										 |  |  | 	.init_early	= ap_init_early, | 
					
						
							| 
									
										
										
										
											2005-07-03 17:38:58 +01:00
										 |  |  | 	.init_irq	= ap_init_irq, | 
					
						
							| 
									
										
										
										
											2012-04-28 14:33:47 +01:00
										 |  |  | 	.handle_irq	= fpga_handle_irq, | 
					
						
							| 
									
										
										
										
											2012-11-08 12:40:59 -07:00
										 |  |  | 	.init_time	= ap_timer_init, | 
					
						
							| 
									
										
										
										
											2005-07-03 17:38:58 +01:00
										 |  |  | 	.init_machine	= ap_init, | 
					
						
							| 
									
										
										
										
											2011-11-03 19:54:37 +00:00
										 |  |  | 	.restart	= integrator_restart, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | MACHINE_END | 
					
						
							| 
									
										
										
										
											2012-09-06 09:08:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif
 |