blob: c3c66b0d6b6efb3b32392688e76f2f299a14aa7e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/arm/mach-sa1100/simpad.c
3 */
4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/module.h>
6#include <linux/init.h>
7#include <linux/kernel.h>
8#include <linux/tty.h>
9#include <linux/proc_fs.h>
10#include <linux/string.h>
11#include <linux/pm.h>
Russell Kingd052d1b2005-10-29 19:07:23 +010012#include <linux/platform_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/mtd/mtd.h>
14#include <linux/mtd/partitions.h>
Russell Kingfced80c2008-09-06 12:10:45 +010015#include <linux/io.h>
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010016#include <linux/gpio.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017
18#include <asm/irq.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010019#include <mach/hardware.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <asm/setup.h>
21
22#include <asm/mach-types.h>
23#include <asm/mach/arch.h>
24#include <asm/mach/flash.h>
25#include <asm/mach/map.h>
26#include <asm/mach/serial_sa1100.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010027#include <mach/mcp.h>
28#include <mach/simpad.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
30#include <linux/serial_core.h>
31#include <linux/ioport.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#include "generic.h"
34
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010035/*
36 * CS3 support
37 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010039static long cs3_shadow;
40static spinlock_t cs3_lock;
41static struct gpio_chip cs3_gpio;
42
43long simpad_get_cs3_ro(void)
44{
45 return readl(CS3_BASE);
46}
47EXPORT_SYMBOL(simpad_get_cs3_ro);
48
49long simpad_get_cs3_shadow(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
51 return cs3_shadow;
52}
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010053EXPORT_SYMBOL(simpad_get_cs3_shadow);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010055static void __simpad_write_cs3(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010057 writel(cs3_shadow, CS3_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058}
59
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010060void simpad_set_cs3_bit(int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061{
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010062 unsigned long flags;
63
64 spin_lock_irqsave(&cs3_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 cs3_shadow |= value;
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010066 __simpad_write_cs3();
67 spin_unlock_irqrestore(&cs3_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010069EXPORT_SYMBOL(simpad_set_cs3_bit);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010071void simpad_clear_cs3_bit(int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010073 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +010075 spin_lock_irqsave(&cs3_lock, flags);
76 cs3_shadow &= ~value;
77 __simpad_write_cs3();
78 spin_unlock_irqrestore(&cs3_lock, flags);
79}
80EXPORT_SYMBOL(simpad_clear_cs3_bit);
81
82static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
83{
84 if (offset > 15)
85 return;
86 if (value)
87 simpad_set_cs3_bit(1 << offset);
88 else
89 simpad_clear_cs3_bit(1 << offset);
90};
91
92static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
93{
94 if (offset > 15)
95 return simpad_get_cs3_ro() & (1 << (offset - 16));
96 return simpad_get_cs3_shadow() & (1 << offset);
97};
98
99static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
100{
101 if (offset > 15)
102 return 0;
103 return -EINVAL;
104};
105
106static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
107 int value)
108{
109 if (offset > 15)
110 return -EINVAL;
111 cs3_gpio_set(chip, offset, value);
112 return 0;
113};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
115static struct map_desc simpad_io_desc[] __initdata = {
Deepak Saxena92519d82005-10-28 15:19:04 +0100116 { /* MQ200 */
117 .virtual = 0xf2800000,
118 .pfn = __phys_to_pfn(0x4b800000),
119 .length = 0x00800000,
120 .type = MT_DEVICE
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100121 }, { /* Simpad CS3 */
122 .virtual = CS3_BASE,
123 .pfn = __phys_to_pfn(SA1100_CS3_PHYS),
Deepak Saxena92519d82005-10-28 15:19:04 +0100124 .length = 0x00100000,
125 .type = MT_DEVICE
126 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127};
128
129
130static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
131{
132 if (port->mapbase == (u_int)&Ser1UTCR0) {
133 if (state)
134 {
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100135 simpad_clear_cs3_bit(RS232_ON);
136 simpad_clear_cs3_bit(DECT_POWER_ON);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 }else
138 {
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100139 simpad_set_cs3_bit(RS232_ON);
140 simpad_set_cs3_bit(DECT_POWER_ON);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 }
142 }
143}
144
145static struct sa1100_port_fns simpad_port_fns __initdata = {
146 .pm = simpad_uart_pm,
147};
148
149
150static struct mtd_partition simpad_partitions[] = {
151 {
152 .name = "SIMpad boot firmware",
153 .size = 0x00080000,
154 .offset = 0,
155 .mask_flags = MTD_WRITEABLE,
156 }, {
157 .name = "SIMpad kernel",
158 .size = 0x0010000,
159 .offset = MTDPART_OFS_APPEND,
160 }, {
161 .name = "SIMpad root jffs2",
162 .size = MTDPART_SIZ_FULL,
163 .offset = MTDPART_OFS_APPEND,
164 }
165};
166
167static struct flash_platform_data simpad_flash_data = {
168 .map_name = "cfi_probe",
169 .parts = simpad_partitions,
170 .nr_parts = ARRAY_SIZE(simpad_partitions),
171};
172
173
174static struct resource simpad_flash_resources [] = {
175 {
176 .start = SA1100_CS0_PHYS,
177 .end = SA1100_CS0_PHYS + SZ_16M -1,
178 .flags = IORESOURCE_MEM,
179 }, {
180 .start = SA1100_CS1_PHYS,
181 .end = SA1100_CS1_PHYS + SZ_16M -1,
182 .flags = IORESOURCE_MEM,
183 }
184};
185
Russell King323cdfc2005-08-18 10:10:46 +0100186static struct mcp_plat_data simpad_mcp_data = {
187 .mccr0 = MCCR0_ADM,
188 .sclk_rate = 11981000,
Jochen Friedrichf24dec92011-08-18 21:53:57 +0100189 .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
Russell King323cdfc2005-08-18 10:10:46 +0100190};
191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193
194static void __init simpad_map_io(void)
195{
196 sa1100_map_io();
197
198 iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc));
199
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100200 /* Initialize CS3 */
201 cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON |
202 RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
203 __simpad_write_cs3(); /* Spinlocks not yet initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 sa1100_register_uart_fns(&simpad_port_fns);
206 sa1100_register_uart(0, 3); /* serial interface */
207 sa1100_register_uart(1, 1); /* DECT */
208
209 // Reassign UART 1 pins
210 GAFR |= GPIO_UART_TXD | GPIO_UART_RXD;
211 GPDR |= GPIO_UART_TXD | GPIO_LDD13 | GPIO_LDD15;
212 GPDR &= ~GPIO_UART_RXD;
213 PPAR |= PPAR_UPR;
214
215 /*
216 * Set up registers for sleep mode.
217 */
218
219
220 PWER = PWER_GPIO0| PWER_RTC;
221 PGSR = 0x818;
222 PCFR = 0;
223 PSDR = 0;
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225}
226
227static void simpad_power_off(void)
228{
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100229 local_irq_disable();
230 cs3_shadow = SD_MEDIAQ;
231 __simpad_write_cs3(); /* Bypass spinlock here */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
233 /* disable internal oscillator, float CS lines */
234 PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100235 /* enable wake-up on GPIO0 */
236 PWER = GFER = GRER = PWER_GPIO0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 /*
238 * set scratchpad to zero, just in case it is used as a
239 * restart address by the bootloader.
240 */
241 PSPR = 0;
242 PGSR = 0;
243 /* enter sleep mode */
244 PMCR = PMCR_SF;
245 while(1);
246
247 local_irq_enable(); /* we won't ever call it */
248
249
250}
251
252
253/*
254 * MediaQ Video Device
255 */
256static struct platform_device simpad_mq200fb = {
257 .name = "simpad-mq200",
258 .id = 0,
259};
260
261static struct platform_device *devices[] __initdata = {
262 &simpad_mq200fb
263};
264
265
266
267static int __init simpad_init(void)
268{
269 int ret;
270
Jochen Friedrichde0bc0d2011-08-18 21:50:31 +0100271 spin_lock_init(&cs3_lock);
272
273 cs3_gpio.label = "simpad_cs3";
274 cs3_gpio.base = SIMPAD_CS3_GPIO_BASE;
275 cs3_gpio.ngpio = 24;
276 cs3_gpio.set = cs3_gpio_set;
277 cs3_gpio.get = cs3_gpio_get;
278 cs3_gpio.direction_input = cs3_gpio_direction_input;
279 cs3_gpio.direction_output = cs3_gpio_direction_output;
280 ret = gpiochip_add(&cs3_gpio);
281 if (ret)
282 printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 pm_power_off = simpad_power_off;
285
Jochen Friedrich4f444e22011-01-03 12:09:05 +0100286 sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
287 ARRAY_SIZE(simpad_flash_resources));
288 sa11x0_register_mcp(&simpad_mcp_data);
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
291 if(ret)
292 printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
293
294 return 0;
295}
296
297arch_initcall(simpad_init);
298
299
300MACHINE_START(SIMPAD, "Simpad")
Russell Kinge9dea0c2005-07-03 17:38:58 +0100301 /* Maintainer: Holger Freyther */
Russell Kinge9dea0c2005-07-03 17:38:58 +0100302 .boot_params = 0xc0000100,
303 .map_io = simpad_map_io,
304 .init_irq = sa1100_init_irq,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 .timer = &sa1100_timer,
306MACHINE_END