1 // SPDX-License-Identifier: GPL-2.0
3 * linux/arch/arm/mach-sa1100/simpad.c
6 #include <linux/module.h>
7 #include <linux/gpio/machine.h>
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/tty.h>
11 #include <linux/proc_fs.h>
12 #include <linux/string.h>
14 #include <linux/platform_data/sa11x0-serial.h>
15 #include <linux/platform_device.h>
16 #include <linux/mfd/ucb1x00.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/partitions.h>
20 #include <linux/gpio/driver.h>
22 #include <mach/hardware.h>
23 #include <asm/setup.h>
26 #include <asm/mach-types.h>
27 #include <asm/mach/arch.h>
28 #include <asm/mach/flash.h>
29 #include <asm/mach/map.h>
30 #include <linux/platform_data/mfd-mcp-sa11x0.h>
31 #include <mach/simpad.h>
32 #include <mach/irqs.h>
34 #include <linux/serial_core.h>
35 #include <linux/ioport.h>
36 #include <linux/input.h>
37 #include <linux/gpio_keys.h>
38 #include <linux/leds.h>
39 #include <linux/platform_data/i2c-gpio.h>
47 static long cs3_shadow
;
48 static spinlock_t cs3_lock
;
49 static struct gpio_chip cs3_gpio
;
51 long simpad_get_cs3_ro(void)
53 return readl(CS3_BASE
);
55 EXPORT_SYMBOL(simpad_get_cs3_ro
);
57 long simpad_get_cs3_shadow(void)
61 EXPORT_SYMBOL(simpad_get_cs3_shadow
);
63 static void __simpad_write_cs3(void)
65 writel(cs3_shadow
, CS3_BASE
);
68 void simpad_set_cs3_bit(int value
)
72 spin_lock_irqsave(&cs3_lock
, flags
);
75 spin_unlock_irqrestore(&cs3_lock
, flags
);
77 EXPORT_SYMBOL(simpad_set_cs3_bit
);
79 void simpad_clear_cs3_bit(int value
)
83 spin_lock_irqsave(&cs3_lock
, flags
);
86 spin_unlock_irqrestore(&cs3_lock
, flags
);
88 EXPORT_SYMBOL(simpad_clear_cs3_bit
);
90 static void cs3_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
95 simpad_set_cs3_bit(1 << offset
);
97 simpad_clear_cs3_bit(1 << offset
);
100 static int cs3_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
103 return !!(simpad_get_cs3_ro() & (1 << (offset
- 16)));
104 return !!(simpad_get_cs3_shadow() & (1 << offset
));
107 static int cs3_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
114 static int cs3_gpio_direction_output(struct gpio_chip
*chip
, unsigned offset
,
119 cs3_gpio_set(chip
, offset
, value
);
123 static struct map_desc simpad_io_desc
[] __initdata
= {
125 .virtual = 0xf2800000,
126 .pfn
= __phys_to_pfn(0x4b800000),
127 .length
= 0x00800000,
129 }, { /* Simpad CS3 */
130 .virtual = (unsigned long)CS3_BASE
,
131 .pfn
= __phys_to_pfn(SA1100_CS3_PHYS
),
132 .length
= 0x00100000,
138 static void simpad_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
140 if (port
->mapbase
== (u_int
)&Ser1UTCR0
) {
143 simpad_clear_cs3_bit(RS232_ON
);
144 simpad_clear_cs3_bit(DECT_POWER_ON
);
147 simpad_set_cs3_bit(RS232_ON
);
148 simpad_set_cs3_bit(DECT_POWER_ON
);
153 static struct sa1100_port_fns simpad_port_fns __initdata
= {
154 .pm
= simpad_uart_pm
,
158 static struct mtd_partition simpad_partitions
[] = {
160 .name
= "SIMpad boot firmware",
163 .mask_flags
= MTD_WRITEABLE
,
165 .name
= "SIMpad kernel",
167 .offset
= MTDPART_OFS_APPEND
,
169 .name
= "SIMpad root jffs2",
170 .size
= MTDPART_SIZ_FULL
,
171 .offset
= MTDPART_OFS_APPEND
,
175 static struct flash_platform_data simpad_flash_data
= {
176 .map_name
= "cfi_probe",
177 .parts
= simpad_partitions
,
178 .nr_parts
= ARRAY_SIZE(simpad_partitions
),
182 static struct resource simpad_flash_resources
[] = {
183 DEFINE_RES_MEM(SA1100_CS0_PHYS
, SZ_16M
),
184 DEFINE_RES_MEM(SA1100_CS1_PHYS
, SZ_16M
),
187 static struct ucb1x00_plat_data simpad_ucb1x00_data
= {
188 .gpio_base
= SIMPAD_UCB1X00_GPIO_BASE
,
191 static struct mcp_plat_data simpad_mcp_data
= {
193 .sclk_rate
= 11981000,
194 .codec_pdata
= &simpad_ucb1x00_data
,
199 static void __init
simpad_map_io(void)
203 iotable_init(simpad_io_desc
, ARRAY_SIZE(simpad_io_desc
));
206 cs3_shadow
= (EN1
| EN0
| LED2_ON
| DISPLAY_ON
|
207 RS232_ON
| ENABLE_5V
| RESET_SIMCARD
| DECT_POWER_ON
);
208 __simpad_write_cs3(); /* Spinlocks not yet initialized */
210 sa1100_register_uart_fns(&simpad_port_fns
);
211 sa1100_register_uart(0, 3); /* serial interface */
212 sa1100_register_uart(1, 1); /* DECT */
214 // Reassign UART 1 pins
215 GAFR
|= GPIO_UART_TXD
| GPIO_UART_RXD
;
216 GPDR
|= GPIO_UART_TXD
| GPIO_LDD13
| GPIO_LDD15
;
217 GPDR
&= ~GPIO_UART_RXD
;
221 * Set up registers for sleep mode.
225 PWER
= PWER_GPIO0
| PWER_RTC
;
232 static void simpad_power_off(void)
235 cs3_shadow
= SD_MEDIAQ
;
236 __simpad_write_cs3(); /* Bypass spinlock here */
238 /* disable internal oscillator, float CS lines */
239 PCFR
= (PCFR_OPDE
| PCFR_FP
| PCFR_FS
);
240 /* enable wake-up on GPIO0 */
241 PWER
= GFER
= GRER
= PWER_GPIO0
;
243 * set scratchpad to zero, just in case it is used as a
244 * restart address by the bootloader.
248 /* enter sleep mode */
252 local_irq_enable(); /* we won't ever call it */
261 static struct gpio_keys_button simpad_button_table
[] = {
262 { KEY_POWER
, IRQ_GPIO_POWER_BUTTON
, 1, "power button" },
265 static struct gpio_keys_platform_data simpad_keys_data
= {
266 .buttons
= simpad_button_table
,
267 .nbuttons
= ARRAY_SIZE(simpad_button_table
),
270 static struct platform_device simpad_keys
= {
273 .platform_data
= &simpad_keys_data
,
277 static struct gpio_keys_button simpad_polled_button_table
[] = {
278 { KEY_PROG1
, SIMPAD_UCB1X00_GPIO_PROG1
, 1, "prog1 button" },
279 { KEY_PROG2
, SIMPAD_UCB1X00_GPIO_PROG2
, 1, "prog2 button" },
280 { KEY_UP
, SIMPAD_UCB1X00_GPIO_UP
, 1, "up button" },
281 { KEY_DOWN
, SIMPAD_UCB1X00_GPIO_DOWN
, 1, "down button" },
282 { KEY_LEFT
, SIMPAD_UCB1X00_GPIO_LEFT
, 1, "left button" },
283 { KEY_RIGHT
, SIMPAD_UCB1X00_GPIO_RIGHT
, 1, "right button" },
286 static struct gpio_keys_platform_data simpad_polled_keys_data
= {
287 .buttons
= simpad_polled_button_table
,
288 .nbuttons
= ARRAY_SIZE(simpad_polled_button_table
),
292 static struct platform_device simpad_polled_keys
= {
293 .name
= "gpio-keys-polled",
295 .platform_data
= &simpad_polled_keys_data
,
303 static struct gpio_led simpad_leds
[] = {
305 .name
= "simpad:power",
306 .gpio
= SIMPAD_CS3_LED2_ON
,
308 .default_trigger
= "default-on",
312 static struct gpio_led_platform_data simpad_led_data
= {
313 .num_leds
= ARRAY_SIZE(simpad_leds
),
317 static struct platform_device simpad_gpio_leds
= {
321 .platform_data
= &simpad_led_data
,
328 static struct gpiod_lookup_table simpad_i2c_gpiod_table
= {
329 .dev_id
= "i2c-gpio.0",
331 GPIO_LOOKUP_IDX("gpio", 21, NULL
, 0,
332 GPIO_ACTIVE_HIGH
| GPIO_OPEN_DRAIN
),
333 GPIO_LOOKUP_IDX("gpio", 25, NULL
, 1,
334 GPIO_ACTIVE_HIGH
| GPIO_OPEN_DRAIN
),
338 static struct i2c_gpio_platform_data simpad_i2c_data
= {
343 static struct platform_device simpad_i2c
= {
347 .platform_data
= &simpad_i2c_data
,
352 * MediaQ Video Device
354 static struct platform_device simpad_mq200fb
= {
355 .name
= "simpad-mq200",
359 static struct platform_device
*devices
[] __initdata
= {
368 static struct gpiod_lookup_table simpad_cf_gpio_table
= {
369 .dev_id
= "sa11x0-pcmcia",
371 GPIO_LOOKUP("gpio", GPIO_CF_IRQ
, "cf-ready", GPIO_ACTIVE_HIGH
),
372 GPIO_LOOKUP("gpio", GPIO_CF_CD
, "cf-detect", GPIO_ACTIVE_HIGH
),
378 static int __init
simpad_init(void)
382 spin_lock_init(&cs3_lock
);
384 cs3_gpio
.label
= "simpad_cs3";
385 cs3_gpio
.base
= SIMPAD_CS3_GPIO_BASE
;
387 cs3_gpio
.set
= cs3_gpio_set
;
388 cs3_gpio
.get
= cs3_gpio_get
;
389 cs3_gpio
.direction_input
= cs3_gpio_direction_input
;
390 cs3_gpio
.direction_output
= cs3_gpio_direction_output
;
391 ret
= gpiochip_add_data(&cs3_gpio
, NULL
);
393 printk(KERN_WARNING
"simpad: Unable to register cs3 GPIO device");
395 pm_power_off
= simpad_power_off
;
397 sa11x0_register_pcmcia(-1, &simpad_cf_gpio_table
);
398 sa11x0_ppc_configure_mcp();
399 sa11x0_register_mtd(&simpad_flash_data
, simpad_flash_resources
,
400 ARRAY_SIZE(simpad_flash_resources
));
401 sa11x0_register_mcp(&simpad_mcp_data
);
403 gpiod_add_lookup_table(&simpad_i2c_gpiod_table
);
404 ret
= platform_add_devices(devices
, ARRAY_SIZE(devices
));
406 printk(KERN_WARNING
"simpad: Unable to register mq200 framebuffer device");
411 arch_initcall(simpad_init
);
414 MACHINE_START(SIMPAD
, "Simpad")
415 /* Maintainer: Holger Freyther */
416 .atag_offset
= 0x100,
417 .map_io
= simpad_map_io
,
418 .nr_irqs
= SA1100_NR_IRQS
,
419 .init_irq
= sa1100_init_irq
,
420 .init_late
= sa11x0_init_late
,
421 .init_time
= sa1100_timer_init
,
422 .restart
= sa11x0_restart
,