• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/arm/plat-brcm/
1/*
2 * Northstar SoC main platform file.
3 *
4 */
5
6#include <linux/types.h>
7#include <linux/init.h>
8#include <linux/kernel.h>
9#include <linux/io.h>
10#include <linux/ioport.h>
11#include <linux/platform_device.h>
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/serial_8250.h>
15#include <linux/proc_fs.h>
16#include <asm/hardware/cache-l2x0.h>
17#include <asm/mach/map.h>
18#include <asm/clkdev.h>
19#include <asm/uaccess.h>
20#include <mach/clkdev.h>
21#include <mach/io_map.h>
22#include <plat/bsp.h>
23#include <plat/mpcore.h>
24#include <plat/plat-bcm5301x.h>
25
26#ifdef	CONFIG_SMP
27#include <asm/spinlock.h>
28#endif
29
30static struct clk * _soc_refclk = NULL;
31
32static struct plat_serial8250_port uart_ports[] = {
33	{
34	.type       = PORT_16550,
35	.flags      = UPF_FIXED_TYPE | UPF_SHARE_IRQ,
36	.regshift   = 0,
37	.iotype     = UPIO_MEM,
38	.mapbase    = (resource_size_t)(PLAT_UART1_PA),
39	.membase    = (void __iomem *) PLAT_UART1_VA,
40	.irq        = IRQ_CCA,
41	},
42	{
43	.type       = PORT_16550,
44	.flags      = UPF_FIXED_TYPE | UPF_SHARE_IRQ,
45	.regshift   = 0,
46	.iotype     = UPIO_MEM,
47	.mapbase    = (resource_size_t)(PLAT_UART2_PA),
48	.membase    = (void __iomem *) PLAT_UART2_VA,
49	.irq        = IRQ_CCA,
50	},
51	{ .flags = 0, },	/* List terminatoir */
52};
53
54static struct platform_device platform_serial_devices = {
55	.name = "serial8250",
56	.id = PLAT8250_DEV_PLATFORM,	/* <linux/serial_8250.h> */
57	.dev = {
58		.platform_data = uart_ports,
59	},
60};
61
62/*
63 * Map fix-mapped I/O that is needed before full MMU operation
64 */
65void __init soc_map_io( struct clk * refclk )
66{
67	struct map_desc desc[2] ;
68
69	/*
70	* Map Chipcommon A & B to a fixed virtual location
71	* as these contain all the system UARTs, which are
72	* needed for low-level debugging,
73	* it have already been mapped from mach_desc earlier
74	* but that is undone from page_init()
75	*/
76
77	desc[0].virtual = IO_BASE_VA;
78	desc[0].pfn = __phys_to_pfn( IO_BASE_PA );
79	desc[0].length = SZ_16M ;	/* CCA+CCB: 0x18000000-0x18ffffff */
80	desc[0].type = MT_DEVICE ;
81
82	iotable_init( desc, 1);
83
84	mpcore_map_io( );
85	/* Save refclk for later use */
86	_soc_refclk = refclk ;
87}
88
89static int soc_abort_handler(unsigned long addr, unsigned int fsr,
90                                      struct pt_regs *regs)
91{
92	/*
93	 * These happen for no good reason
94	 * possibly left over from CFE
95	 */
96	printk( KERN_WARNING
97		"External imprecise Data abort at "
98		"addr=%#lx, fsr=%#x ignored.\n",
99		addr, fsr );
100
101	/* Returning non-zero causes fault display and panic */
102        return 0;
103}
104
105static void soc_aborts_enable(void)
106{
107	u32 x;
108
109	/* Install our hook */
110        hook_fault_code(16 + 6, soc_abort_handler, SIGBUS, 0,
111                        "imprecise external abort");
112
113	/* Enable external aborts - clear "A" bit in CPSR */
114
115	/* Read CPSR */
116	asm( "mrs	%0,cpsr": "=&r" (x) : : );
117
118	x &= ~ PSR_A_BIT ;
119
120	/* Update CPSR, affect bits 8-15 */
121	asm( "msr	cpsr_x,%0; nop; nop": : "r" (x) : "cc" );
122
123}
124
125/*
126 * This SoC relies on MPCORE GIC interrupt controller
127 */
128void __init soc_init_irq( void )
129{
130	mpcore_init_gic();
131	soc_aborts_enable();
132
133}
134
135/*
136 * Initialize SoC timers
137 */
138void __init soc_init_timer( void )
139{
140	unsigned long periphclk_freq;
141	struct clk * clk ;
142
143	/* Clocks need to be setup early */
144	soc_dmu_init( _soc_refclk );
145	soc_cru_init( _soc_refclk );
146
147	/* get mpcore PERIPHCLK from clock modules */
148	clk = clk_get_sys( NULL, "periph_clk");
149	BUG_ON( IS_ERR_OR_NULL (clk) );
150	periphclk_freq = clk_get_rate( clk );
151	BUG_ON( !periphclk_freq );
152
153	/* Fire up the global MPCORE timer */
154	mpcore_init_timer( periphclk_freq );
155
156}
157
158
159/*
160 * Install all other SoC device drivers
161 * that are not automatically discoverable.
162 */
163void __init soc_add_devices( void )
164{
165	u32 i, clk_rate = 0;
166	u8 UARTClkSel, UARTClkOvr;
167	u16 UARTClkDiv ;
168	struct clk * clk = NULL ;
169
170	i = readl( SOC_CHIPCOMON_A_BASE_VA + 0x04 );
171	/* UARTClkSel ChipcommonA_CoreCapabilities bit 4..3 */
172	UARTClkSel = ( i >> 3 ) & 0x3 ;
173	/* UARTClkOvr ChipcommonA_CoreCtrl bit 0 */
174	UARTClkOvr = 1 &  readl( SOC_CHIPCOMON_A_BASE_VA + 0x08 );
175	/* UARTClkDiv: ChipcommonA_ClkDiv bits 0..7 */
176	UARTClkDiv =  0xff & readl( SOC_CHIPCOMON_A_BASE_VA + 0xa4 );
177	if( UARTClkDiv == 0 ) UARTClkDiv = 0x100 ;
178
179	if( UARTClkSel == 0 )
180		{
181		/* UARTClkSel = 0 -> external reference clock source */
182		clk = _soc_refclk ;
183		BUG_ON( !clk );
184		clk_rate = clk_get_rate(clk);
185		}
186	else if( UARTClkSel == 1 )
187		{
188		/* UARTClkSel = 1 -> Internal clock optionally divided */
189		clk = clk_get_sys( NULL, "iproc_slow_clk");
190		BUG_ON( !clk );
191		clk_rate = clk_get_rate(clk) ;
192		if( ! UARTClkOvr )
193			clk_rate /= UARTClkDiv;
194		}
195
196	printk( KERN_INFO "CCA UART Clock Config: Sel=%d Ovr=%d Div=%d\n",
197		UARTClkSel, UARTClkOvr, UARTClkDiv );
198	printk( KERN_INFO "CCA UART Clock rate %uHz\n", clk_rate );
199
200	/* fixup UART port structure */
201	for(i = 0; i < ARRAY_SIZE(uart_ports); i++ )
202		{
203		if( uart_ports[i].flags == 0 )
204			break;
205		if( uart_ports[i].irq == 0 )
206			uart_ports[i].flags |= UPF_AUTO_IRQ;
207
208		/* UART input clock source and rate */
209		uart_ports[i].uartclk = clk_rate ;
210		}
211
212	/* Install SoC devices in the system: uarts */
213	platform_device_register( & platform_serial_devices );
214
215	/* Enable UART interrupt in ChipcommonA */
216	i = readl( SOC_CHIPCOMON_A_BASE_VA + 0x24 );
217	i |= 1 << 6;
218	writel( i, SOC_CHIPCOMON_A_BASE_VA + 0x24 );
219
220}
221
222void plat_wake_secondary_cpu( unsigned cpu, void (* _sec_entry_va)(void) )
223{
224	void __iomem * rombase = NULL;
225	phys_addr_t lut_pa;
226	u32 offset, mask;
227	u32 val ;
228
229	mask = ( 1UL << PAGE_SHIFT) -1 ;
230
231	lut_pa = SOC_ROM_BASE_PA & ~mask ;
232	offset = SOC_ROM_BASE_PA &  mask ;
233	offset += SOC_ROM_LUT_OFF;
234
235	rombase = ioremap( lut_pa, PAGE_SIZE );
236	if( rombase == NULL )
237		return;
238	val = virt_to_phys( _sec_entry_va );
239
240	writel( val, rombase + offset );
241
242	smp_wmb();	/* probably not needed - io regs are not cached */
243
244#ifdef	CONFIG_SMP
245	dsb_sev();	/* Exit WFI */
246#endif
247	mb();
248
249	iounmap( rombase );
250}
251
252#ifdef CONFIG_CACHE_L310
253/*
254 * SoC initialization that need to be done early,
255 * e.g. L2 cache, clock, I/O pin mux, power management
256 */
257static int  __init bcm5301_pl310_init( void )
258{
259	void __iomem *l2cache_base;
260	u32 auxctl_val, auxctl_msk ;
261	extern void __init l310_init( void __iomem *, u32, u32, int );
262
263	/* Default AUXCTL modifiers */
264	auxctl_val = 0UL;
265	auxctl_msk = ~0UL ;
266
267	/* Customize AUXCTL */
268	auxctl_val |= 0 << 0 ;	/* Full line of zero Enable - requires A9 cfg */
269	auxctl_val |= 1 << 25;	/* Cache replacement policy - round robin */
270	auxctl_val |= 1 << 29;	/* Instruction prefetch enable */
271	auxctl_val |= 1 << 28;	/* Data prefetch enable */
272	auxctl_val |= 1 << 30;	/* Early BRESP enable */
273
274	l2cache_base = ioremap( L2CC_BASE_PA, SZ_4K );
275
276	/* Configure using default aux control value */
277	if( l2cache_base != NULL )
278		l310_init( l2cache_base, auxctl_val, auxctl_msk, 32 );
279
280	return 0;
281}
282early_initcall( bcm5301_pl310_init );
283#endif
284