1352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/*
2352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  linux/arch/arm/mach-pxa/viper.c
3352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
4352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Support for the Arcom VIPER SBC.
5352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
6352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Author:	Ian Campbell
7352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Created:    Feb 03, 2003
8352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Copyright:  Arcom Control Systems
9352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
10352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Maintained by Marc Zyngier <maz@misterjones.org>
11352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *                             <marc.zyngier@altran.com>
12352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
13352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * Based on lubbock.c:
14352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Author:	Nicolas Pitre
15352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Created:	Jun 15, 2001
16352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  Copyright:	MontaVista Software Inc.
17352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
18352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  This program is free software; you can redistribute it and/or modify
19352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  it under the terms of the GNU General Public License version 2 as
20352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *  published by the Free Software Foundation.
21352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier */
22352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
23352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/types.h>
24352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/memory.h>
25352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/cpu.h>
26352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/cpufreq.h>
27352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/delay.h>
28352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/fs.h>
29352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/init.h>
305a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
31352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/interrupt.h>
32352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/major.h>
33352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/module.h>
34352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/pm.h>
35352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/sched.h>
36352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/gpio.h>
376ae87fe219ce32ea226254ee72e1d38ad35d9debWolfram Sang#include <linux/jiffies.h>
38352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/i2c-gpio.h>
39b459396ee9398bdf61e3118ca730394f58e90c9cSebastian Andrzej Siewior#include <linux/i2c/pxa-i2c.h>
40352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/serial_8250.h>
41352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/smc91x.h>
42352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/pwm_backlight.h>
43352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/usb/isp116x.h>
44352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/mtd/mtd.h>
45352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/mtd/partitions.h>
46352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <linux/mtd/physmap.h>
472eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysocki#include <linux/syscore_ops.h>
48352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
4951c62982a33d9086fd8876293411d28a5f97247aEric Miao#include <mach/pxa25x.h>
50352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <mach/audio.h>
51293b2da1b61136813fc2764f43304c66ff8040e9Arnd Bergmann#include <linux/platform_data/video-pxafb.h>
52776abac81764847338a6a02c34609d4b8dfb4918Ricardo Martins#include <mach/regs-uart.h>
53293b2da1b61136813fc2764f43304c66ff8040e9Arnd Bergmann#include <linux/platform_data/pcmcia-pxa2xx_viper.h>
54352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <mach/viper.h>
55352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
56352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/setup.h>
57352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/mach-types.h>
58352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/irq.h>
59352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/sizes.h>
609f97da78bf018206fb623cd351d454af2f105fe0David Howells#include <asm/system_info.h>
61352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
62352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/mach/arch.h>
63352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/mach/map.h>
64352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include <asm/mach/irq.h>
65352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
66352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include "generic.h"
67352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#include "devices.h"
68352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
69352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic unsigned int icr;
70352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
71352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_icr_set_bit(unsigned int bit)
72352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
73352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	icr |= bit;
74352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	VIPER_ICR = icr;
75352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
76352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
77352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_icr_clear_bit(unsigned int bit)
78352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
79352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	icr &= ~bit;
80352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	VIPER_ICR = icr;
81352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
82352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
83352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* This function is used from the pcmcia module to reset the CF */
84c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngierstatic void viper_cf_reset(int state)
85352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
86352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (state)
87352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		viper_icr_set_bit(VIPER_ICR_CF_RST);
88352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	else
89352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		viper_icr_clear_bit(VIPER_ICR_CF_RST);
90352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
91c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier
92c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngierstatic struct arcom_pcmcia_pdata viper_pcmcia_info = {
93c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.cd_gpio	= VIPER_CF_CD_GPIO,
94c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.rdy_gpio	= VIPER_CF_RDY_GPIO,
95c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.pwr_gpio	= VIPER_CF_POWER_GPIO,
96c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.reset		= viper_cf_reset,
97c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier};
98c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier
99c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngierstatic struct platform_device viper_pcmcia_device = {
100c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.name		= "viper-pcmcia",
101c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.id		= -1,
102c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	.dev		= {
103c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier		.platform_data	= &viper_pcmcia_info,
104c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	},
105c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier};
106352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
107352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/*
108352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * The CPLD version register was not present on VIPER boards prior to
109352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * v2i1. On v1 boards where the version register is not present we
110352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * will just read back the previous value from the databus.
111352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
112352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * Therefore we do two reads. The first time we write 0 to the
113352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * (read-only) register before reading and the second time we write
114352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * 0xff first. If the two reads do not match or they read back as 0xff
115352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * or 0x00 then we have version 1 hardware.
116352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier */
117352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic u8 viper_hw_version(void)
118352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
119352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	u8 v1, v2;
120352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	unsigned long flags;
121352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
122352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	local_irq_save(flags);
123352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
124352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	VIPER_VERSION = 0;
125352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	v1 = VIPER_VERSION;
126352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	VIPER_VERSION = 0xff;
127352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	v2 = VIPER_VERSION;
128352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
129352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	v1 = (v1 != v2 || v1 == 0xff) ? 0 : v1;
130352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
131352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	local_irq_restore(flags);
132352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return v1;
133352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
134352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
1352eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysocki/* CPU system core operations. */
1362eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysockistatic int viper_cpu_suspend(void)
137352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
138352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_icr_set_bit(VIPER_ICR_R_DIS);
139352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return 0;
140352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
141352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
1422eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysockistatic void viper_cpu_resume(void)
143352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
144352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_icr_clear_bit(VIPER_ICR_R_DIS);
145352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
146352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
1472eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysockistatic struct syscore_ops viper_cpu_syscore_ops = {
148352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.suspend	= viper_cpu_suspend,
149352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.resume		= viper_cpu_resume,
150352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
151352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
152352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic unsigned int current_voltage_divisor;
153352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
154352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/*
155352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * If force is not true then step from existing to new divisor. If
156352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * force is true then jump straight to the new divisor. Stepping is
157352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * used because if the jump in voltage is too large, the VCC can dip
158352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * too low and the regulator cuts out.
159352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier *
160352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * force can be used to initialize the divisor to a know state by
161352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * setting the value for the current clock speed, since we are already
162352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * running at that speed we know the voltage should be pretty close so
163352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * the jump won't be too large
164352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier */
165352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_set_core_cpu_voltage(unsigned long khz, int force)
166352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
167352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	int i = 0;
168352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	unsigned int divisor = 0;
169352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	const char *v;
170352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
171352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (khz < 200000) {
172352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		v = "1.0"; divisor = 0xfff;
173352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} else if (khz < 300000) {
174352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		v = "1.1"; divisor = 0xde5;
175352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} else {
176352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		v = "1.3"; divisor = 0x325;
177352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
178352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
179352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pr_debug("viper: setting CPU core voltage to %sV at %d.%03dMHz\n",
180352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		 v, (int)khz / 1000, (int)khz % 1000);
181352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
182352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#define STEP 0x100
183352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	do {
184352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		int step;
185352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
186352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		if (force)
187352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			step = divisor;
188352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		else if (current_voltage_divisor < divisor - STEP)
189352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			step = current_voltage_divisor + STEP;
190352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		else if (current_voltage_divisor > divisor + STEP)
191352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			step = current_voltage_divisor - STEP;
192352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		else
193352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			step = divisor;
194352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		force = 0;
195352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
196352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		gpio_set_value(VIPER_PSU_CLK_GPIO, 0);
197352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		gpio_set_value(VIPER_PSU_nCS_LD_GPIO, 0);
198352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
199352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		for (i = 1 << 11 ; i > 0 ; i >>= 1) {
200352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			udelay(1);
201352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
202352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			gpio_set_value(VIPER_PSU_DATA_GPIO, step & i);
203352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			udelay(1);
204352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
205352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			gpio_set_value(VIPER_PSU_CLK_GPIO, 1);
206352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			udelay(1);
207352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
208352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			gpio_set_value(VIPER_PSU_CLK_GPIO, 0);
209352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		}
210352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		udelay(1);
211352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
212352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		gpio_set_value(VIPER_PSU_nCS_LD_GPIO, 1);
213352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		udelay(1);
214352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
215352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		gpio_set_value(VIPER_PSU_nCS_LD_GPIO, 0);
216352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
217352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		current_voltage_divisor = step;
218352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} while (current_voltage_divisor != divisor);
219352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
220352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
221352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* Interrupt handling */
222352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic unsigned long viper_irq_enabled_mask;
223a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngierstatic const int viper_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 };
224a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngierstatic const int viper_isa_irq_map[] = {
225a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	0,		/* ISA irq #0, invalid */
226a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	0,		/* ISA irq #1, invalid */
227a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	0,		/* ISA irq #2, invalid */
228a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 0,		/* ISA irq #3 */
229a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 1,		/* ISA irq #4 */
230a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 2,		/* ISA irq #5 */
231a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 3,		/* ISA irq #6 */
232a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 4,		/* ISA irq #7 */
233a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	0,		/* ISA irq #8, invalid */
234a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 8,		/* ISA irq #9 */
235a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 5,		/* ISA irq #10 */
236a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 6,		/* ISA irq #11 */
237a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 7,		/* ISA irq #12 */
238a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	0,		/* ISA irq #13, invalid */
239a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 9,		/* ISA irq #14 */
240a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	1 << 10,	/* ISA irq #15 */
241a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier};
242a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier
243a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngierstatic inline int viper_irq_to_bitmask(unsigned int irq)
244a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier{
245a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	return viper_isa_irq_map[irq - PXA_ISA_IRQ(0)];
246a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier}
247a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier
248a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngierstatic inline int viper_bit_to_irq(int bit)
249a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier{
250a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	return viper_isa_irqs[bit] + PXA_ISA_IRQ(0);
251a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier}
252352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
253a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhekstatic void viper_ack_irq(struct irq_data *d)
254352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
255a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	int viper_irq = viper_irq_to_bitmask(d->irq);
256352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
257a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	if (viper_irq & 0xff)
258a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier		VIPER_LO_IRQ_STATUS = viper_irq;
259352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	else
260a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier		VIPER_HI_IRQ_STATUS = (viper_irq >> 8);
261352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
262352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
263a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhekstatic void viper_mask_irq(struct irq_data *d)
264352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
265a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(d->irq));
266352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
267352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
268a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhekstatic void viper_unmask_irq(struct irq_data *d)
269352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
270a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	viper_irq_enabled_mask |= viper_irq_to_bitmask(d->irq);
271352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
272352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
273352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic inline unsigned long viper_irq_pending(void)
274352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
275352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return (VIPER_HI_IRQ_STATUS << 8 | VIPER_LO_IRQ_STATUS) &
276352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			viper_irq_enabled_mask;
277352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
278352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
279352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_irq_handler(unsigned int irq, struct irq_desc *desc)
280352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
281352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	unsigned long pending;
282352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
283352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pending = viper_irq_pending();
284352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	do {
285a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier		/* we're in a chained irq handler,
286a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier		 * so ack the interrupt by hand */
287a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek		desc->irq_data.chip->irq_ack(&desc->irq_data);
288a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier
289352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		if (likely(pending)) {
290a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier			irq = viper_bit_to_irq(__ffs(pending));
291352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			generic_handle_irq(irq);
292352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		}
293352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		pending = viper_irq_pending();
294352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} while (pending);
295352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
296352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
297352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct irq_chip viper_irq_chip = {
298a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	.name		= "ISA",
299a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	.irq_ack	= viper_ack_irq,
300a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	.irq_mask	= viper_mask_irq,
301a3f4c927d379cfaa597bc8ff75dc9d28f8d9200eLennert Buytenhek	.irq_unmask	= viper_unmask_irq
302352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
303352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
304352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_init_irq(void)
305352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
306a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	int level;
307352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	int isa_irq;
308352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
309352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pxa25x_init_irq();
310352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
311352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* setup ISA IRQs */
312a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier	for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) {
313a9ff8f6462635c8d9f8d64b7b10ddcea8404d77bMarc Zyngier		isa_irq = viper_bit_to_irq(level);
314f38c02f3b338651e145aac2889ba976baf6b28b3Thomas Gleixner		irq_set_chip_and_handler(isa_irq, &viper_irq_chip,
315f38c02f3b338651e145aac2889ba976baf6b28b3Thomas Gleixner					 handle_edge_irq);
316352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
317352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
318352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
3196845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner	irq_set_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO),
320352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				viper_irq_handler);
3216845664a6a7d443f03883db59d10749d38d98b8eThomas Gleixner	irq_set_irq_type(gpio_to_irq(VIPER_CPLD_GPIO), IRQ_TYPE_EDGE_BOTH);
322352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
323352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
324352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* Flat Panel */
325352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct pxafb_mode_info fb_mode_info[] = {
326352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
327352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.pixclock	= 157500,
328352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
329352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.xres		= 320,
330352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.yres		= 240,
331352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
332352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.bpp		= 16,
333352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
334352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.hsync_len	= 63,
335352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.left_margin	= 7,
336352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.right_margin	= 13,
337352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
338352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.vsync_len	= 20,
339352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.upper_margin	= 0,
340352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.lower_margin	= 0,
341352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
342352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.sync		= 0,
343352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
344352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
345352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
346352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct pxafb_mach_info fb_info = {
347352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.modes			= fb_mode_info,
348352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.num_modes		= 1,
349352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.lcd_conn		= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
350352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
351352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
352352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic int viper_backlight_init(struct device *dev)
353352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
354352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	int ret;
355352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
356352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* GPIO9 and 10 control FB backlight. Initialise to off */
357352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	ret = gpio_request(VIPER_BCKLIGHT_EN_GPIO, "Backlight");
358352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (ret)
359352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request_bckl;
360352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
361352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	ret = gpio_request(VIPER_LCD_EN_GPIO, "LCD");
362352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (ret)
363352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request_lcd;
364352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
365352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	ret = gpio_direction_output(VIPER_BCKLIGHT_EN_GPIO, 0);
366352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (ret)
367352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_dir;
368352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
369352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	ret = gpio_direction_output(VIPER_LCD_EN_GPIO, 0);
370352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (ret)
371352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_dir;
372352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
373352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return 0;
374352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
375352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_dir:
376352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_LCD_EN_GPIO);
377352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request_lcd:
378352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_BCKLIGHT_EN_GPIO);
379352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request_bckl:
380352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	dev_err(dev, "Failed to setup LCD GPIOs\n");
381352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
382352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return ret;
383352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
384352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
3852d51a521e64f91e42424b291fcae49d4d3f63d88Eric Miaostatic int viper_backlight_notify(struct device *dev, int brightness)
386352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
387352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_set_value(VIPER_LCD_EN_GPIO, !!brightness);
388352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_set_value(VIPER_BCKLIGHT_EN_GPIO, !!brightness);
389352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
390352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return brightness;
391352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
392352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
393352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_backlight_exit(struct device *dev)
394352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
395352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_LCD_EN_GPIO);
396352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_BCKLIGHT_EN_GPIO);
397352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
398352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
399352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_pwm_backlight_data viper_backlight_data = {
400352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.pwm_id		= 0,
401352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.max_brightness	= 100,
402352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dft_brightness	= 100,
403352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.pwm_period_ns	= 1000000,
404db01120c5f6cb1d8c6533a49b009f08a73852498Thierry Reding	.enable_gpio	= -1,
405352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.init		= viper_backlight_init,
406352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.notify		= viper_backlight_notify,
407352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.exit		= viper_backlight_exit,
408352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
409352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
410352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device viper_backlight_device = {
411352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name		= "pwm-backlight",
412352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dev		= {
413352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.parent		= &pxa25x_device_pwm0.dev,
414352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.platform_data	= &viper_backlight_data,
415352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
416352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
417352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
418352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* Ethernet */
419352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct resource smc91x_resources[] = {
420352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[0] = {
421352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.name	= "smc91x-regs",
422352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start  = VIPER_ETH_PHYS + 0x300,
423352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end    = VIPER_ETH_PHYS + 0x30f,
424352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_MEM,
425352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
426352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[1] = {
4274929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.start  = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO),
4284929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.end    = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO),
429352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
430352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
431352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[2] = {
432352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.name	= "smc91x-data32",
433352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start  = VIPER_ETH_DATA_PHYS,
434352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end    = VIPER_ETH_DATA_PHYS + 3,
435352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_MEM,
436352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
437352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
438352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
439352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct smc91x_platdata viper_smc91x_info = {
440352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
441352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.leda	= RPC_LED_100_10,
442352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.ledb	= RPC_LED_TX_RX,
443352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
444352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
445352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device smc91x_device = {
446352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name		= "smc91x",
447352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.id		= -1,
448352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.num_resources  = ARRAY_SIZE(smc91x_resources),
449352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.resource       = smc91x_resources,
450352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dev		= {
451352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.platform_data	= &viper_smc91x_info,
452352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
453352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
454352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
455352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* i2c */
456352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct i2c_gpio_platform_data i2c_bus_data = {
457352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.sda_pin = VIPER_RTC_I2C_SDA_GPIO,
458352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.scl_pin = VIPER_RTC_I2C_SCL_GPIO,
459352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.udelay  = 10,
4606ae87fe219ce32ea226254ee72e1d38ad35d9debWolfram Sang	.timeout = HZ,
461352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
462352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
463352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device i2c_bus_device = {
464352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name		= "i2c-gpio",
465352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.id		= 1, /* pxa2xx-i2c is bus 0, so start at 1 */
466352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dev = {
467352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.platform_data = &i2c_bus_data,
468352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
469352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
470352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
471352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct i2c_board_info __initdata viper_i2c_devices[] = {
472352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
473352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		I2C_BOARD_INFO("ds1338", 0x68),
474352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
475352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
476352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
477352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/*
478352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * Serial configuration:
479352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * You can either have the standard PXA ports driven by the PXA driver,
480352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * or all the ports (PXA + 16850) driven by the 8250 driver.
481352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier * Choose your poison.
482352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier */
483352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
484352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct resource viper_serial_resources[] = {
485352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#ifndef CONFIG_SERIAL_PXA
486352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
487352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= 0x40100000,
488352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= 0x4010001f,
489352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
490352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
491352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
492352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= 0x40200000,
493352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= 0x4020001f,
494352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
495352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
496352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
497352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= 0x40700000,
498352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= 0x4070001f,
499352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
500352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
501352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
502352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= VIPER_UARTA_PHYS,
503352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= VIPER_UARTA_PHYS + 0xf,
504352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
505352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
506352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
507352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= VIPER_UARTB_PHYS,
508352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= VIPER_UARTB_PHYS + 0xf,
509352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
510352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
511352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#else
512352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
513352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		0,
514352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
515352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#endif
516352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
517352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
518352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct plat_serial8250_port serial_platform_data[] = {
519352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#ifndef CONFIG_SERIAL_PXA
520352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Internal UARTs */
521352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
522352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.membase	= (void *)&FFUART,
523352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.mapbase	= __PREG(FFUART),
524352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.irq		= IRQ_FFUART,
525352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.uartclk	= 921600 * 16,
526352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.regshift	= 2,
527352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
528352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.iotype		= UPIO_MEM,
529352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
530352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
531352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.membase	= (void *)&BTUART,
532352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.mapbase	= __PREG(BTUART),
533352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.irq		= IRQ_BTUART,
534352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.uartclk	= 921600 * 16,
535352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.regshift	= 2,
536352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
537352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.iotype		= UPIO_MEM,
538352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
539352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
540352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.membase	= (void *)&STUART,
541352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.mapbase	= __PREG(STUART),
542352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.irq		= IRQ_STUART,
543352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.uartclk	= 921600 * 16,
544352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.regshift	= 2,
545352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
546352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.iotype		= UPIO_MEM,
547352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
548352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* External UARTs */
549352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
550352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.mapbase	= VIPER_UARTA_PHYS,
5514929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.irq		= PXA_GPIO_TO_IRQ(VIPER_UARTA_GPIO),
5523fe6ccffcbc6c79512fe9bea5c10de75ae0c497eMarc Zyngier		.irqflags	= IRQF_TRIGGER_RISING,
553352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.uartclk	= 1843200,
554352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.regshift	= 1,
555352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.iotype		= UPIO_MEM,
556352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP |
557352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				  UPF_SKIP_TEST,
558352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
559352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
560352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.mapbase	= VIPER_UARTB_PHYS,
5614929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.irq		= PXA_GPIO_TO_IRQ(VIPER_UARTB_GPIO),
5623fe6ccffcbc6c79512fe9bea5c10de75ae0c497eMarc Zyngier		.irqflags	= IRQF_TRIGGER_RISING,
563352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.uartclk	= 1843200,
564352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.regshift	= 1,
565352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.iotype		= UPIO_MEM,
566352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP |
567352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				  UPF_SKIP_TEST,
568352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
569352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#endif
570352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{ },
571352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
572352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
573352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device serial_device = {
574352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name			= "serial8250",
575352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.id			= 0,
576352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dev			= {
577352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.platform_data	= serial_platform_data,
578352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
579352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.num_resources		= ARRAY_SIZE(viper_serial_resources),
580352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.resource		= viper_serial_resources,
581352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
582352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
583352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* USB */
584352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void isp116x_delay(struct device *dev, int delay)
585352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
586352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	ndelay(delay);
587352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
588352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
589352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct resource isp116x_resources[] = {
590352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[0] = { /* DATA */
591352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start  = VIPER_USB_PHYS + 0,
592352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end    = VIPER_USB_PHYS + 1,
593352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_MEM,
594352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
595352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[1] = { /* ADDR */
596352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start  = VIPER_USB_PHYS + 2,
597352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end    = VIPER_USB_PHYS + 3,
598352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_MEM,
599352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
600352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[2] = {
6014929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.start  = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO),
6024929f5a8a99f64378659c5658621e45c90c2aaa9Haojian Zhuang		.end    = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO),
603352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
604352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
605352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
606352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
607352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* (DataBusWidth16|AnalogOCEnable|DREQOutputPolarity|DownstreamPort15KRSel ) */
608352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct isp116x_platform_data isp116x_platform_data = {
609352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Enable internal resistors on downstream ports */
610352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.sel15Kres		= 1,
611352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* On-chip overcurrent protection */
612352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.oc_enable		= 1,
613352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* INT output polarity */
614352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.int_act_high		= 1,
615352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* INT edge or level triggered */
616352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.int_edge_triggered	= 0,
617352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
618352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* WAKEUP pin connected - NOT SUPPORTED  */
619352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* .remote_wakeup_connected = 0, */
620352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Wakeup by devices on usb bus enabled */
621352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.remote_wakeup_enable	= 0,
622352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.delay			= isp116x_delay,
623352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
624352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
625352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device isp116x_device = {
626352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name			= "isp116x-hcd",
627352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.id			= -1,
628352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.num_resources  	= ARRAY_SIZE(isp116x_resources),
629352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.resource       	= isp116x_resources,
630352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.dev			= {
631352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.platform_data	= &isp116x_platform_data,
632352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
633352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
634352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
635352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
636352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier/* MTD */
637352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct resource mtd_resources[] = {
638352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[0] = {	/* RedBoot config + filesystem flash */
639352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= VIPER_FLASH_PHYS,
640352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= VIPER_FLASH_PHYS + SZ_32M - 1,
641352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
642352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
643352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[1] = {	/* Boot flash */
644352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= VIPER_BOOT_PHYS,
645352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= VIPER_BOOT_PHYS + SZ_1M - 1,
646352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
647352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
648352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[2] = { /*
649352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		 * SRAM size is actually 256KB, 8bits, with a sparse mapping
650352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		 * (each byte is on a 16bit boundary).
651352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		 */
652352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.start	= _VIPER_SRAM_BASE,
653352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.end	= _VIPER_SRAM_BASE + SZ_512K - 1,
654352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.flags	= IORESOURCE_MEM,
655352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
656352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
657352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
658352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct mtd_partition viper_boot_flash_partition = {
659352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.name		= "RedBoot",
660352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.size		= SZ_1M,
661352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.offset		= 0,
662352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.mask_flags	= MTD_WRITEABLE,	/* force R/O */
663352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
664352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
665352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct physmap_flash_data viper_flash_data[] = {
666352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[0] = {
667352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.width		= 2,
668352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.parts		= NULL,
669352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.nr_parts	= 0,
670352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
671352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[1] = {
672352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.width		= 2,
673352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.parts		= &viper_boot_flash_partition,
674352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.nr_parts	= 1,
675352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
676352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
677352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
678352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device viper_mtd_devices[] = {
679352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[0] = {
680352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.name		= "physmap-flash",
681352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.id		= 0,
682352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.dev		= {
683352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			.platform_data	= &viper_flash_data[0],
684352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		},
685352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.resource	= &mtd_resources[0],
686352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.num_resources	= 1,
687352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
688352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	[1] = {
689352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.name		= "physmap-flash",
690352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.id		= 1,
691352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.dev		= {
692352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			.platform_data	= &viper_flash_data[1],
693352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		},
694352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.resource	= &mtd_resources[1],
695352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.num_resources	= 1,
696352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
697352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
698352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
699352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct platform_device *viper_devs[] __initdata = {
700352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&smc91x_device,
701352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&i2c_bus_device,
702352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&serial_device,
703352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&isp116x_device,
704352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&viper_mtd_devices[0],
705352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&viper_mtd_devices[1],
706352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	&viper_backlight_device,
707c2de1c382933fd9ef0a3db13b6747115e1e32c56Marc Zyngier	&viper_pcmcia_device,
708352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
709352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
710352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic mfp_cfg_t viper_pin_config[] __initdata = {
711352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Chip selects */
712352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO15_nCS_1,
713352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO78_nCS_2,
714352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO79_nCS_3,
715352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO80_nCS_4,
716352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO33_nCS_5,
717352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
718c11b6a420b092a576e003bbb520392268338d97bEric Miao	/* AC97 */
719c11b6a420b092a576e003bbb520392268338d97bEric Miao	GPIO28_AC97_BITCLK,
720c11b6a420b092a576e003bbb520392268338d97bEric Miao	GPIO29_AC97_SDATA_IN_0,
721c11b6a420b092a576e003bbb520392268338d97bEric Miao	GPIO30_AC97_SDATA_OUT,
722c11b6a420b092a576e003bbb520392268338d97bEric Miao	GPIO31_AC97_SYNC,
723c11b6a420b092a576e003bbb520392268338d97bEric Miao
724352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* FP Backlight */
725352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO9_GPIO, 				/* VIPER_BCKLIGHT_EN_GPIO */
726352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO10_GPIO,				/* VIPER_LCD_EN_GPIO */
727352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO16_PWM0_OUT,
728352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
729352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Ethernet PHY Ready */
730352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO18_RDY,
731352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
732352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Serial shutdown */
733352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO12_GPIO | MFP_LPM_DRIVE_HIGH,	/* VIPER_UART_SHDN_GPIO */
734352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
735352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Compact-Flash / PC104 */
736352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO48_nPOE,
737352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO49_nPWE,
738352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO50_nPIOR,
739352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO51_nPIOW,
740352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO52_nPCE_1,
741352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO53_nPCE_2,
742352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO54_nPSKTSEL,
743352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO55_nPREG,
744352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO56_nPWAIT,
745352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO57_nIOIS16,
746352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO8_GPIO,				/* VIPER_CF_RDY_GPIO */
747352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO32_GPIO,				/* VIPER_CF_CD_GPIO */
748352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO82_GPIO,				/* VIPER_CF_POWER_GPIO */
749352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
750352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Integrated UPS control */
751352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO20_GPIO,				/* VIPER_UPS_GPIO */
752352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
753352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Vcc regulator control */
754352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO6_GPIO,				/* VIPER_PSU_DATA_GPIO */
755352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO11_GPIO,				/* VIPER_PSU_CLK_GPIO */
756352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO19_GPIO,				/* VIPER_PSU_nCS_LD_GPIO */
757352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
758352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* i2c busses */
759352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO26_GPIO,				/* VIPER_TPM_I2C_SDA_GPIO */
760352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO27_GPIO,				/* VIPER_TPM_I2C_SCL_GPIO */
761352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO83_GPIO,				/* VIPER_RTC_I2C_SDA_GPIO */
762352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO84_GPIO,				/* VIPER_RTC_I2C_SCL_GPIO */
763352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
764352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* PC/104 Interrupt */
765352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	GPIO1_GPIO | WAKEUP_ON_EDGE_RISE,	/* VIPER_CPLD_GPIO */
766352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
767352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
768352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic unsigned long viper_tpm;
769352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
770352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic int __init viper_tpm_setup(char *str)
771352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
7724fce45b44bdbf293bc1aed5526e4da90f32eb8ebDaniel Walter	return kstrtoul(str, 10, &viper_tpm) >= 0;
773352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
774352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
775352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier__setup("tpm=", viper_tpm_setup);
776352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
777352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_tpm_init(void)
778352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
779352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	struct platform_device *tpm_device;
780352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	struct i2c_gpio_platform_data i2c_tpm_data = {
781352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.sda_pin = VIPER_TPM_I2C_SDA_GPIO,
782352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.scl_pin = VIPER_TPM_I2C_SCL_GPIO,
783352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.udelay  = 10,
7846ae87fe219ce32ea226254ee72e1d38ad35d9debWolfram Sang		.timeout = HZ,
785352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	};
786352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	char *errstr;
787352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
788352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Allocate TPM i2c bus if requested */
789352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (!viper_tpm)
790352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		return;
791352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
792352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	tpm_device = platform_device_alloc("i2c-gpio", 2);
793352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (tpm_device) {
794352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		if (!platform_device_add_data(tpm_device,
795352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier					      &i2c_tpm_data,
796352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier					      sizeof(i2c_tpm_data))) {
797352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			if (platform_device_add(tpm_device)) {
798352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				errstr = "register TPM i2c bus";
799352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				goto error_free_tpm;
800352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			}
801352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		} else {
802352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			errstr = "allocate TPM i2c bus data";
803352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			goto error_free_tpm;
804352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		}
805352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} else {
806352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		errstr = "allocate TPM i2c device";
807352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto error_tpm;
808352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
809352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
810352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return;
811352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
812352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererror_free_tpm:
813352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	kfree(tpm_device);
814352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererror_tpm:
815352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pr_err("viper: Couldn't %s, giving up\n", errstr);
816352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
817352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
818352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_init_vcore_gpios(void)
819352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
820352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_request(VIPER_PSU_DATA_GPIO, "PSU data"))
821352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request_data;
822352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
823352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_request(VIPER_PSU_CLK_GPIO, "PSU clock"))
824352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request_clk;
825352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
826352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_request(VIPER_PSU_nCS_LD_GPIO, "PSU cs"))
827352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request_cs;
828352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
829352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_direction_output(VIPER_PSU_DATA_GPIO, 0) ||
830352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	    gpio_direction_output(VIPER_PSU_CLK_GPIO, 0) ||
831352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	    gpio_direction_output(VIPER_PSU_nCS_LD_GPIO, 0))
832352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_dir;
833352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
834352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* c/should assume redboot set the correct level ??? */
835352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_set_core_cpu_voltage(get_clk_frequency_khz(0), 1);
836352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
837352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return;
838352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
839352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_dir:
840352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_PSU_nCS_LD_GPIO);
841352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request_cs:
842352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_PSU_CLK_GPIO);
843352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request_clk:
844352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_PSU_DATA_GPIO);
845352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request_data:
846352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pr_err("viper: Failed to setup vcore control GPIOs\n");
847352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
848352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
849352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_init_serial_gpio(void)
850352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
851352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_request(VIPER_UART_SHDN_GPIO, "UARTs shutdown"))
852352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_request;
853352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
854352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (gpio_direction_output(VIPER_UART_SHDN_GPIO, 0))
855352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		goto err_dir;
856352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
857352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return;
858352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
859352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_dir:
860352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_free(VIPER_UART_SHDN_GPIO);
861352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngiererr_request:
862352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pr_err("viper: Failed to setup UART shutdown GPIO\n");
863352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
864352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
865352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#ifdef CONFIG_CPU_FREQ
866352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic int viper_cpufreq_notifier(struct notifier_block *nb,
867352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				  unsigned long val, void *data)
868352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
869352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	struct cpufreq_freqs *freq = data;
870352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
871352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* TODO: Adjust timings??? */
872352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
873352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	switch (val) {
874352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	case CPUFREQ_PRECHANGE:
875352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		if (freq->old < freq->new) {
876352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			/* we are getting faster so raise the voltage
877352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			 * before we change freq */
878352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			viper_set_core_cpu_voltage(freq->new, 0);
879352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		}
880352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		break;
881352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	case CPUFREQ_POSTCHANGE:
882352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		if (freq->old > freq->new) {
883352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			/* we are slowing down so drop the power
884352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			 * after we change freq */
885352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			viper_set_core_cpu_voltage(freq->new, 0);
886352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		}
887352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		break;
888352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	default:
889352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		/* ignore */
890352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		break;
891352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
892352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
893352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	return 0;
894352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
895352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
896352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct notifier_block viper_cpufreq_notifier_block = {
897352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.notifier_call  = viper_cpufreq_notifier
898352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
899352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
900352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_init_cpufreq(void)
901352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
902352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (cpufreq_register_notifier(&viper_cpufreq_notifier_block,
903352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier				      CPUFREQ_TRANSITION_NOTIFIER))
904352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		pr_err("viper: Failed to setup cpufreq notifier\n");
905352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
906352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#else
907352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic inline void viper_init_cpufreq(void) {}
908352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier#endif
909352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
910352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void viper_power_off(void)
911352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
912352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pr_notice("Shutting off UPS\n");
913352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	gpio_set_value(VIPER_UPS_GPIO, 1);
914352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Spin to death... */
915352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	while (1);
916352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
917352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
918352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_init(void)
919352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
920352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	u8 version;
921352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
922352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pm_power_off = viper_power_off;
923352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
924352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pxa2xx_mfp_config(ARRAY_AND_SIZE(viper_pin_config));
925352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
926cc155c6f2cc705cb082ed676044368424e4b9121Russell King	pxa_set_ffuart_info(NULL);
927cc155c6f2cc705cb082ed676044368424e4b9121Russell King	pxa_set_btuart_info(NULL);
928cc155c6f2cc705cb082ed676044368424e4b9121Russell King	pxa_set_stuart_info(NULL);
929cc155c6f2cc705cb082ed676044368424e4b9121Russell King
930352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Wake-up serial console */
931352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_init_serial_gpio();
932352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
9334321e1a12b811c02441240aa6183156791204f3fRussell King - ARM Linux	pxa_set_fb_info(NULL, &fb_info);
934352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
935352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* v1 hardware cannot use the datacs line */
936352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	version = viper_hw_version();
937352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (version == 0)
938352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		smc91x_device.num_resources--;
939352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
940352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pxa_set_i2c_info(NULL);
941352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs));
942352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
943352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_init_vcore_gpios();
944352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_init_cpufreq();
945352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
9462eaa03b5bebd1e80014f780d7bf27c3e66daefd6Rafael J. Wysocki	register_syscore_ops(&viper_cpu_syscore_ops);
947352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
948352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	if (version) {
949352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		pr_info("viper: hardware v%di%d detected. "
950352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			"CPLD revision %d.\n",
951352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			VIPER_BOARD_VERSION(version),
952352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			VIPER_BOARD_ISSUE(version),
953352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			VIPER_CPLD_REVISION(version));
954352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		system_rev = (VIPER_BOARD_VERSION(version) << 8) |
955352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			     (VIPER_BOARD_ISSUE(version) << 4) |
956352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier			     VIPER_CPLD_REVISION(version);
957352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	} else {
958352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		pr_info("viper: No version register.\n");
959352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	}
960352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
961352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	i2c_register_board_info(1, ARRAY_AND_SIZE(viper_i2c_devices));
962352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
963352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	viper_tpm_init();
964352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	pxa_set_ac97_info(NULL);
965352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
966352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
967352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic struct map_desc viper_io_desc[] __initdata = {
968352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
969352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.virtual = VIPER_CPLD_BASE,
970352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.pfn     = __phys_to_pfn(VIPER_CPLD_PHYS),
971352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.length  = 0x00300000,
972352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.type    = MT_DEVICE,
973352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
974352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	{
975352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.virtual = VIPER_PC104IO_BASE,
976b393c69652333be31ad7a8205761c0d5b7f3e167Eric Miao		.pfn     = __phys_to_pfn(0x30000000),
977352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.length  = 0x00800000,
978352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier		.type    = MT_DEVICE,
979352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	},
980352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier};
981352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
982352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngierstatic void __init viper_map_io(void)
983352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier{
984851982c1b6ca18cedf6d01e4529a0c1ddb30771eMarek Vasut	pxa25x_map_io();
985352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
986352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	iotable_init(viper_io_desc, ARRAY_SIZE(viper_io_desc));
987352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
988352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	PCFR |= PCFR_OPDE;
989352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier}
990352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier
991352699a3d7ccb027e0139a7a67931e7907af6249Marc ZyngierMACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
992352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
9937375aba6737419db5a17b4a8540ffe7b4452ff40Nicolas Pitre	.atag_offset	= 0x100,
994352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.map_io		= viper_map_io,
9954e611091f859906c28921cf8d3c75a848fd249bdRob Herring	.nr_irqs	= PXA_NR_IRQS,
996352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.init_irq	= viper_init_irq,
9978a97ae2f554d762a4bc67b5d13b52ef39c8d6baaEric Miao	.handle_irq	= pxa25x_handle_irq,
9986bb27d7349db51b50c40534710fe164ca0d58902Stephen Warren	.init_time	= pxa_timer_init,
999352699a3d7ccb027e0139a7a67931e7907af6249Marc Zyngier	.init_machine	= viper_init,
1000271a74fc875210d3dfcc03d557fb5d86d3990a0fRussell King	.restart	= pxa_restart,
1001352699a3d7ccb027e0139a7a67931e7907af6249Marc ZyngierMACHINE_END
1002