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>
21 #include <linux/gpio/machine.h>
23 #include <mach/hardware.h>
24 #include <asm/setup.h>
27 #include <asm/mach-types.h>
28 #include <asm/mach/arch.h>
29 #include <asm/mach/flash.h>
30 #include <asm/mach/map.h>
31 #include <linux/platform_data/mfd-mcp-sa11x0.h>
32 #include <mach/simpad.h>
33 #include <mach/irqs.h>
35 #include <linux/serial_core.h>
36 #include <linux/ioport.h>
37 #include <linux/input.h>
38 #include <linux/gpio_keys.h>
39 #include <linux/leds.h>
40 #include <linux/platform_data/i2c-gpio.h>
48 static long cs3_shadow
;
49 static spinlock_t cs3_lock
;
50 static struct gpio_chip cs3_gpio
;
52 long simpad_get_cs3_ro(void)
54 return readl(CS3_BASE
);
56 EXPORT_SYMBOL(simpad_get_cs3_ro
);
58 long simpad_get_cs3_shadow(void)
62 EXPORT_SYMBOL(simpad_get_cs3_shadow
);
64 static void __simpad_write_cs3(void)
66 writel(cs3_shadow
, CS3_BASE
);
69 void simpad_set_cs3_bit(int value
)
73 spin_lock_irqsave(&cs3_lock
, flags
);
76 spin_unlock_irqrestore(&cs3_lock
, flags
);
78 EXPORT_SYMBOL(simpad_set_cs3_bit
);
80 void simpad_clear_cs3_bit(int value
)
84 spin_lock_irqsave(&cs3_lock
, flags
);
87 spin_unlock_irqrestore(&cs3_lock
, flags
);
89 EXPORT_SYMBOL(simpad_clear_cs3_bit
);
91 static void cs3_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
96 simpad_set_cs3_bit(1 << offset
);
98 simpad_clear_cs3_bit(1 << offset
);
101 static int cs3_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
104 return !!(simpad_get_cs3_ro() & (1 << (offset
- 16)));
105 return !!(simpad_get_cs3_shadow() & (1 << offset
));
108 static int cs3_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
115 static int cs3_gpio_direction_output(struct gpio_chip
*chip
, unsigned offset
,
120 cs3_gpio_set(chip
, offset
, value
);
124 static struct map_desc simpad_io_desc
[] __initdata
= {
126 .virtual = 0xf2800000,
127 .pfn
= __phys_to_pfn(0x4b800000),
128 .length
= 0x00800000,
130 }, { /* Simpad CS3 */
131 .virtual = (unsigned long)CS3_BASE
,
132 .pfn
= __phys_to_pfn(SA1100_CS3_PHYS
),
133 .length
= 0x00100000,
139 static void simpad_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
141 if (port
->mapbase
== (u_int
)&Ser1UTCR0
) {
144 simpad_clear_cs3_bit(RS232_ON
);
145 simpad_clear_cs3_bit(DECT_POWER_ON
);
148 simpad_set_cs3_bit(RS232_ON
);
149 simpad_set_cs3_bit(DECT_POWER_ON
);
154 static struct sa1100_port_fns simpad_port_fns __initdata
= {
155 .pm
= simpad_uart_pm
,
159 static struct mtd_partition simpad_partitions
[] = {
161 .name
= "SIMpad boot firmware",
164 .mask_flags
= MTD_WRITEABLE
,
166 .name
= "SIMpad kernel",
168 .offset
= MTDPART_OFS_APPEND
,
170 .name
= "SIMpad root jffs2",
171 .size
= MTDPART_SIZ_FULL
,
172 .offset
= MTDPART_OFS_APPEND
,
176 static struct flash_platform_data simpad_flash_data
= {
177 .map_name
= "cfi_probe",
178 .parts
= simpad_partitions
,
179 .nr_parts
= ARRAY_SIZE(simpad_partitions
),
183 static struct resource simpad_flash_resources
[] = {
184 DEFINE_RES_MEM(SA1100_CS0_PHYS
, SZ_16M
),
185 DEFINE_RES_MEM(SA1100_CS1_PHYS
, SZ_16M
),
188 static struct ucb1x00_plat_data simpad_ucb1x00_data
= {
189 .gpio_base
= SIMPAD_UCB1X00_GPIO_BASE
,
192 static struct mcp_plat_data simpad_mcp_data
= {
194 .sclk_rate
= 11981000,
195 .codec_pdata
= &simpad_ucb1x00_data
,
200 static void __init
simpad_map_io(void)
204 iotable_init(simpad_io_desc
, ARRAY_SIZE(simpad_io_desc
));
207 cs3_shadow
= (EN1
| EN0
| LED2_ON
| DISPLAY_ON
|
208 RS232_ON
| ENABLE_5V
| RESET_SIMCARD
| DECT_POWER_ON
);
209 __simpad_write_cs3(); /* Spinlocks not yet initialized */
211 sa1100_register_uart_fns(&simpad_port_fns
);
212 sa1100_register_uart(0, 3); /* serial interface */
213 sa1100_register_uart(1, 1); /* DECT */
215 // Reassign UART 1 pins
216 GAFR
|= GPIO_UART_TXD
| GPIO_UART_RXD
;
217 GPDR
|= GPIO_UART_TXD
| GPIO_LDD13
| GPIO_LDD15
;
218 GPDR
&= ~GPIO_UART_RXD
;
222 * Set up registers for sleep mode.
226 PWER
= PWER_GPIO0
| PWER_RTC
;
233 static void simpad_power_off(void)
236 cs3_shadow
= SD_MEDIAQ
;
237 __simpad_write_cs3(); /* Bypass spinlock here */
239 /* disable internal oscillator, float CS lines */
240 PCFR
= (PCFR_OPDE
| PCFR_FP
| PCFR_FS
);
241 /* enable wake-up on GPIO0 */
242 PWER
= GFER
= GRER
= PWER_GPIO0
;
244 * set scratchpad to zero, just in case it is used as a
245 * restart address by the bootloader.
249 /* enter sleep mode */
253 local_irq_enable(); /* we won't ever call it */
262 static struct gpio_keys_button simpad_button_table
[] = {
263 { KEY_POWER
, IRQ_GPIO_POWER_BUTTON
, 1, "power button" },
266 static struct gpio_keys_platform_data simpad_keys_data
= {
267 .buttons
= simpad_button_table
,
268 .nbuttons
= ARRAY_SIZE(simpad_button_table
),
271 static struct platform_device simpad_keys
= {
274 .platform_data
= &simpad_keys_data
,
278 static struct gpio_keys_button simpad_polled_button_table
[] = {
279 { KEY_PROG1
, SIMPAD_UCB1X00_GPIO_PROG1
, 1, "prog1 button" },
280 { KEY_PROG2
, SIMPAD_UCB1X00_GPIO_PROG2
, 1, "prog2 button" },
281 { KEY_UP
, SIMPAD_UCB1X00_GPIO_UP
, 1, "up button" },
282 { KEY_DOWN
, SIMPAD_UCB1X00_GPIO_DOWN
, 1, "down button" },
283 { KEY_LEFT
, SIMPAD_UCB1X00_GPIO_LEFT
, 1, "left button" },
284 { KEY_RIGHT
, SIMPAD_UCB1X00_GPIO_RIGHT
, 1, "right button" },
287 static struct gpio_keys_platform_data simpad_polled_keys_data
= {
288 .buttons
= simpad_polled_button_table
,
289 .nbuttons
= ARRAY_SIZE(simpad_polled_button_table
),
293 static struct platform_device simpad_polled_keys
= {
294 .name
= "gpio-keys-polled",
296 .platform_data
= &simpad_polled_keys_data
,
304 static struct gpio_led simpad_leds
[] = {
306 .name
= "simpad:power",
307 .gpio
= SIMPAD_CS3_LED2_ON
,
309 .default_trigger
= "default-on",
313 static struct gpio_led_platform_data simpad_led_data
= {
314 .num_leds
= ARRAY_SIZE(simpad_leds
),
318 static struct platform_device simpad_gpio_leds
= {
322 .platform_data
= &simpad_led_data
,
329 static struct gpiod_lookup_table simpad_i2c_gpiod_table
= {
330 .dev_id
= "i2c-gpio.0",
332 GPIO_LOOKUP_IDX("gpio", 21, NULL
, 0,
333 GPIO_ACTIVE_HIGH
| GPIO_OPEN_DRAIN
),
334 GPIO_LOOKUP_IDX("gpio", 25, NULL
, 1,
335 GPIO_ACTIVE_HIGH
| GPIO_OPEN_DRAIN
),
339 static struct i2c_gpio_platform_data simpad_i2c_data
= {
344 static struct platform_device simpad_i2c
= {
348 .platform_data
= &simpad_i2c_data
,
353 * MediaQ Video Device
355 static struct platform_device simpad_mq200fb
= {
356 .name
= "simpad-mq200",
360 static struct platform_device
*devices
[] __initdata
= {
369 static struct gpiod_lookup_table simpad_cf_gpio_table
= {
370 .dev_id
= "sa11x0-pcmcia",
372 GPIO_LOOKUP("gpio", GPIO_CF_IRQ
, "cf-ready", GPIO_ACTIVE_HIGH
),
373 GPIO_LOOKUP("gpio", GPIO_CF_CD
, "cf-detect", GPIO_ACTIVE_HIGH
),
379 static int __init
simpad_init(void)
383 spin_lock_init(&cs3_lock
);
385 cs3_gpio
.label
= "simpad_cs3";
386 cs3_gpio
.base
= SIMPAD_CS3_GPIO_BASE
;
388 cs3_gpio
.set
= cs3_gpio_set
;
389 cs3_gpio
.get
= cs3_gpio_get
;
390 cs3_gpio
.direction_input
= cs3_gpio_direction_input
;
391 cs3_gpio
.direction_output
= cs3_gpio_direction_output
;
392 ret
= gpiochip_add_data(&cs3_gpio
, NULL
);
394 printk(KERN_WARNING
"simpad: Unable to register cs3 GPIO device");
396 pm_power_off
= simpad_power_off
;
398 sa11x0_register_pcmcia(-1, &simpad_cf_gpio_table
);
399 sa11x0_ppc_configure_mcp();
400 sa11x0_register_mtd(&simpad_flash_data
, simpad_flash_resources
,
401 ARRAY_SIZE(simpad_flash_resources
));
402 sa11x0_register_mcp(&simpad_mcp_data
);
404 gpiod_add_lookup_table(&simpad_i2c_gpiod_table
);
405 ret
= platform_add_devices(devices
, ARRAY_SIZE(devices
));
407 printk(KERN_WARNING
"simpad: Unable to register mq200 framebuffer device");
412 arch_initcall(simpad_init
);
415 MACHINE_START(SIMPAD
, "Simpad")
416 /* Maintainer: Holger Freyther */
417 .atag_offset
= 0x100,
418 .map_io
= simpad_map_io
,
419 .nr_irqs
= SA1100_NR_IRQS
,
420 .init_irq
= sa1100_init_irq
,
421 .init_late
= sa11x0_init_late
,
422 .init_time
= sa1100_timer_init
,
423 .restart
= sa11x0_restart
,