1/*
2 * linux/arch/arm/mach-sa1100/system3.c
3 *
4 * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
5 *
6 * $Id: system3.c,v 1.1.1.1 2008/10/15 03:26:00 james26_jang Exp $
7 *
8 * This file contains all PT Sytsem 3 tweaks. Based on original work from
9 * Nicolas Pitre's assabet fixes
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * $Log: system3.c,v $
16 * Revision 1.1.1.1  2008/10/15 03:26:00  james26_jang
17 * Initial.
18 *
19 * Revision 1.1.1.1  2008/07/21 09:14:22  james26_jang
20 * New UI, New QoS, New wireless driver(4.151.10.29), ipmonitor.
21 *
22 * Revision 1.1.1.1  2008/07/02 14:38:28  james26_jang
23 * 4.100.10.29, New QoS and New UI.
24 *
25 * Revision 1.1.1.1  2007/02/15 12:10:52  jiahao
26 * initial update
27 *
28 * Revision 1.1.1.1  2007/01/25 12:51:48  jiahao_jhou
29 *
30 *
31 * Revision 1.1.1.1  2003/02/03 22:37:19  mhuang
32 * LINUX_2_4 branch snapshot from linux-mips.org CVS
33 *
34 * Revision 1.1.6.1  2001/12/04 17:28:06  seletz
35 * - merged from previous branch
36 *
37 * Revision 1.1.4.3  2001/12/04 15:16:31  seletz
38 * - merged from linux_2_4_13_ac5_rmk2
39 *
40 * Revision 1.1.4.2  2001/11/19 17:18:57  seletz
41 * - more code cleanups
42 *
43 * Revision 1.1.4.1  2001/11/16 13:52:05  seletz
44 * - PT Digital Board Support Code
45 *
46 * Revision 1.1.2.2  2001/11/05 16:46:18  seletz
47 * - cleanups
48 *
49 * Revision 1.1.2.1  2001/10/15 16:00:43  seletz
50 * - first revision working with new board
51 *
52 *
53 */
54
55#include <linux/config.h>
56#include <linux/init.h>
57#include <linux/kernel.h>
58#include <linux/sched.h>
59#include <linux/tty.h>
60#include <linux/module.h>
61#include <linux/errno.h>
62#include <linux/cpufreq.h>
63
64#include <asm/hardware.h>
65#include <asm/setup.h>
66#include <asm/page.h>
67#include <asm/pgtable.h>
68#include <asm/irq.h>
69
70#include <asm/mach/arch.h>
71#include <asm/mach/map.h>
72#include <asm/mach/irq.h>
73#include <asm/mach/serial_sa1100.h>
74
75#include <asm/arch/irq.h>
76
77#include <linux/serial_core.h>
78
79#include "generic.h"
80#include "sa1111.h"
81
82#define DEBUG 1
83
84#ifdef DEBUG
85#	define DPRINTK( x, args... )	printk( "%s: line %d: "x, __FUNCTION__, __LINE__, ## args  );
86#else
87#	define DPRINTK( x, args... )	/* nix */
88#endif
89
90/**********************************************************************
91 *  prototypes
92 */
93
94/* init funcs */
95static void __init fixup_system3(struct machine_desc *desc,
96		struct param_struct *params, char **cmdline, struct meminfo *mi);
97static void __init get_system3_scr(void);
98static int __init system3_init(void);
99static void __init system3_init_irq(void);
100static void __init system3_map_io(void);
101
102static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
103static int system3_get_mctrl(struct uart_port *port);
104static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
105static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
106static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
107
108extern void convert_to_tag_list(struct param_struct *params, int mem_init);
109
110
111/**********************************************************************
112 *  global data
113 */
114
115/**********************************************************************
116 *  static data
117 */
118
119static struct map_desc system3_io_desc[] __initdata = {
120 /* virtual     physical    length      domain     r  w  c  b */
121  { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
122  { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
123  { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
124  LAST_DESC
125};
126
127static struct sa1100_port_fns system3_port_fns __initdata = {
128	set_mctrl:	system3_set_mctrl,
129	get_mctrl:	system3_get_mctrl,
130	pm:		system3_uart_pm,
131};
132
133static struct irqaction system3_irq = {
134	name:		"PT Digital Board SA1111 IRQ",
135	handler:	system3_IRQ_demux,
136	flags:		SA_INTERRUPT
137};
138
139static struct notifier_block system3_clkchg_block = {
140	notifier_call:	sdram_notifier,
141};
142
143/**********************************************************************
144 *  Static functions
145 */
146
147static void __init system3_map_io(void)
148{
149	DPRINTK( "%s\n", "START" );
150	sa1100_map_io();
151	iotable_init(system3_io_desc);
152
153	sa1100_register_uart_fns(&system3_port_fns);
154	sa1100_register_uart(0, 1);	/* com port */
155	sa1100_register_uart(1, 2);
156	sa1100_register_uart(2, 3);	/* radio module */
157
158	Ser1SDCR0 |= SDCR0_SUS;
159}
160
161
162/*********************************************************************
163 * Install IRQ handler
164 */
165static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
166{
167	u_char irr;
168
169	for(;;){
170		//irr = PTCPLD_REG_IRQSR & (PT_IRQ_LAN | PT_IRQ_USAR | PT_IRQ_SA1111);
171		irr = PT_IRQSR & (PT_IRQ_LAN | PT_IRQ_SA1111);
172
173		irr ^= (PT_IRQ_LAN);
174		if (!irr) break;
175
176		if( irr & PT_IRQ_LAN )
177			do_IRQ(IRQ_SYSTEM3_SMC9196, regs);
178
179
180		if( irr & PT_IRQ_SA1111 )
181			sa1111_IRQ_demux(irq, dev_id, regs);
182	}
183}
184
185
186static void __init system3_init_irq(void)
187{
188	int irq;
189
190	DPRINTK( "%s\n", "START" );
191
192	/* SA1111 IRQ not routed to a GPIO. */
193	sa1111_init_irq(-1);
194
195	/* setup extra IRQs */
196	irq = IRQ_SYSTEM3_SMC9196;
197	irq_desc[irq].valid	= 1;
198	irq_desc[irq].probe_ok	= 1;
199
200
201	/* IRQ by CPLD */
202	set_GPIO_IRQ_edge( GPIO_GPIO(25), GPIO_RISING_EDGE );
203	setup_arm_irq( IRQ_GPIO25, &system3_irq );
204}
205
206/**********************************************************************
207 * On system 3 limit cpu frequency to 206 Mhz
208 */
209static int sdram_notifier(struct notifier_block *nb, unsigned long event,
210		void *data)
211{
212	switch (event) {
213		case CPUFREQ_MINMAX:
214			cpufreq_updateminmax(data, 147500, 206000);
215			break;
216
217	}
218	return 0;
219}
220
221/**
222 *	fixup_system3 - fixup function for system 3 board
223 *	@desc:		machine description
224 *	@param:		kernel params
225 *	@cmdline:	kernel cmdline
226 *	@mi:		memory info struct
227 *
228 */
229static void __init fixup_system3(struct machine_desc *desc,
230		struct param_struct *params, char **cmdline, struct meminfo *mi)
231{
232	DPRINTK( "%s\n", "START" );
233
234	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
235	setup_ramdisk( 1, 0, 0, 8192 );
236	setup_initrd( 0xc0800000, 8*1024*1024 );
237}
238
239
240/**
241 *	system3_uart_pm - powermgmt callback function for system 3 UART
242 *	@port: uart port structure
243 *	@state: pm state
244 *	@oldstate: old pm state
245 *
246 */
247static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
248{
249	/* TODO: switch on/off uart in powersave mode */
250}
251
252static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
253{
254	if (port->mapbase == _Ser1UTCR0) {
255		u_int set = 0, clear = 0;
256
257		if (mctrl & TIOCM_RTS)
258			set |= PT_CTRL2_RS1_RTS;
259		else
260			clear |= PT_CTRL2_RS1_RTS;
261
262		if (mctrl & TIOCM_DTR)
263			set |= PT_CTRL2_RS1_DTR;
264		else
265			clear |= PT_CTRL2_RS1_DTR;
266
267		PTCTRL2_clear(clear);
268		PTCTRL2_set(set);
269	}
270}
271
272static int system3_get_mctrl(struct uart_port *port)
273{
274	u_int ret = 0;
275	u_int irqsr = PT_IRQSR;
276
277	/* need 2 reads to read current value */
278	irqsr = PT_IRQSR;
279
280	/* TODO: check IRQ source register for modem/com
281	 status lines and set them correctly. */
282
283	ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
284
285	return ret;
286}
287
288static int __init system3_init(void)
289{
290	int ret = 0;
291	DPRINTK( "%s\n", "START" );
292
293	if ( !machine_is_pt_system3() ) {
294		ret = -EINVAL;
295		goto DONE;
296	}
297
298	/* init control register */
299	PT_CTRL0 = PT_CTRL0_INIT;
300	PT_CTRL1 = 0x02;
301	PT_CTRL2 = 0x00;
302	DPRINTK( "CTRL[0]=0x%02x\n", PT_CTRL0 );
303	DPRINTK( "CTRL[1]=0x%02x\n", PT_CTRL1 );
304	DPRINTK( "CTRL[2]=0x%02x\n", PT_CTRL2 );
305
306	/*
307	 * Ensure that the memory bus request/grant signals are setup,
308	 * and the grant is held in its inactive state.
309	 */
310	sa1110_mb_disable();
311
312	/*
313	 * Probe for a SA1111.
314	 */
315	ret = sa1111_probe(PT_SA1111_BASE);
316	if (ret < 0) {
317		printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
318		goto DONE;
319	}
320
321	/*
322	 * We found it.  Wake the chip up.
323	 */
324	sa1111_wake();
325
326	/*
327	 * The SDRAM configuration of the SA1110 and the SA1111 must
328	 * match.  This is very important to ensure that SA1111 accesses
329	 * don't corrupt the SDRAM.  Note that this ungates the SA1111's
330	 * MBGNT signal, so we must have called sa1110_mb_disable()
331	 * beforehand.
332	 */
333	sa1111_configure_smc(1,
334			     FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
335			     FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
336
337	/*
338	 * We only need to turn on DCLK whenever we want to use the
339	 * DMA.  It can otherwise be held firmly in the off position.
340	 */
341	SKPCR |= SKPCR_DCLKEN;
342
343	/*
344	 * Enable the SA1110 memory bus request and grant signals.
345	 */
346	sa1110_mb_enable();
347
348	system3_init_irq();
349
350#if defined(CONFIG_CPU_FREQ)
351	ret = cpufreq_register_notifier(&system3_clkchg_block);
352	if ( ret != 0 ) {
353		printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
354		goto DONE;
355	}
356#endif
357
358	ret = 0;
359DONE:
360	DPRINTK( "ret=%d\n", ret );
361	return ret;
362}
363
364/**********************************************************************
365 *  Exported Functions
366 */
367
368/**********************************************************************
369 *  kernel magic macros
370 */
371__initcall(system3_init);
372
373MACHINE_START(PT_SYSTEM3, "PT System 3")
374	BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
375	BOOT_PARAMS(0xc0000100)
376	FIXUP(fixup_system3)
377	MAPIO(system3_map_io)
378	INITIRQ(sa1100_init_irq)
379MACHINE_END
380