2 * Support for Compaq iPAQ H3100 and H3600 handheld computers (common code)
4 * Copyright (c) 2000,1 Compaq Computer Corporation. (Author: Jamey Hicks)
5 * Copyright (c) 2009 Dmitry Artamonow <mad_soft@inbox.ru>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
13 #include <linux/kernel.h>
14 #include <linux/gpio.h>
15 #include <linux/gpio_keys.h>
16 #include <linux/input.h>
17 #include <linux/mfd/htc-egpio.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/mtd/partitions.h>
20 #include <linux/platform_data/sa11x0-serial.h>
21 #include <linux/platform_device.h>
22 #include <linux/serial_core.h>
24 #include <asm/mach/flash.h>
25 #include <asm/mach/map.h>
27 #include <mach/h3xxx.h>
34 static struct mtd_partition h3xxx_partitions
[] = {
36 .name
= "H3XXX boot firmware",
39 .mask_flags
= MTD_WRITEABLE
, /* force read-only */
41 .name
= "H3XXX rootfs",
42 .size
= MTDPART_SIZ_FULL
,
47 static void h3xxx_set_vpp(int vpp
)
49 gpio_set_value(H3XXX_EGPIO_VPP_ON
, vpp
);
52 static int h3xxx_flash_init(void)
54 int err
= gpio_request(H3XXX_EGPIO_VPP_ON
, "Flash Vpp");
56 pr_err("%s: can't request H3XXX_EGPIO_VPP_ON\n", __func__
);
60 err
= gpio_direction_output(H3XXX_EGPIO_VPP_ON
, 0);
62 gpio_free(H3XXX_EGPIO_VPP_ON
);
67 static void h3xxx_flash_exit(void)
69 gpio_free(H3XXX_EGPIO_VPP_ON
);
72 static struct flash_platform_data h3xxx_flash_data
= {
73 .map_name
= "cfi_probe",
74 .set_vpp
= h3xxx_set_vpp
,
75 .init
= h3xxx_flash_init
,
76 .exit
= h3xxx_flash_exit
,
77 .parts
= h3xxx_partitions
,
78 .nr_parts
= ARRAY_SIZE(h3xxx_partitions
),
81 static struct resource h3xxx_flash_resource
=
82 DEFINE_RES_MEM(SA1100_CS0_PHYS
, SZ_32M
);
88 static struct gpio h3xxx_uart_gpio
[] = {
89 { H3XXX_GPIO_COM_DCD
, GPIOF_IN
, "COM DCD" },
90 { H3XXX_GPIO_COM_CTS
, GPIOF_IN
, "COM CTS" },
91 { H3XXX_GPIO_COM_RTS
, GPIOF_OUT_INIT_LOW
, "COM RTS" },
94 static bool h3xxx_uart_request_gpios(void)
96 static bool h3xxx_uart_gpio_ok
;
99 if (h3xxx_uart_gpio_ok
)
102 rc
= gpio_request_array(h3xxx_uart_gpio
, ARRAY_SIZE(h3xxx_uart_gpio
));
104 pr_err("h3xxx_uart_request_gpios: error %d\n", rc
);
106 h3xxx_uart_gpio_ok
= true;
108 return h3xxx_uart_gpio_ok
;
111 static void h3xxx_uart_set_mctrl(struct uart_port
*port
, u_int mctrl
)
113 if (port
->mapbase
== _Ser3UTCR0
) {
114 if (!h3xxx_uart_request_gpios())
116 gpio_set_value(H3XXX_GPIO_COM_RTS
, !(mctrl
& TIOCM_RTS
));
120 static u_int
h3xxx_uart_get_mctrl(struct uart_port
*port
)
122 u_int ret
= TIOCM_CD
| TIOCM_CTS
| TIOCM_DSR
;
124 if (port
->mapbase
== _Ser3UTCR0
) {
125 if (!h3xxx_uart_request_gpios())
128 * DCD and CTS bits are inverted in GPLR by RS232 transceiver
130 if (gpio_get_value(H3XXX_GPIO_COM_DCD
))
132 if (gpio_get_value(H3XXX_GPIO_COM_CTS
))
139 static void h3xxx_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
141 if (port
->mapbase
== _Ser3UTCR0
) {
142 if (!gpio_request(H3XXX_EGPIO_RS232_ON
, "RS232 transceiver")) {
143 gpio_direction_output(H3XXX_EGPIO_RS232_ON
, !state
);
144 gpio_free(H3XXX_EGPIO_RS232_ON
);
146 pr_err("%s: can't request H3XXX_EGPIO_RS232_ON\n",
153 * Enable/Disable wake up events for this serial port.
154 * Obviously, we only support this on the normal COM port.
156 static int h3xxx_uart_set_wake(struct uart_port
*port
, u_int enable
)
160 if (port
->mapbase
== _Ser3UTCR0
) {
162 PWER
|= PWER_GPIO23
| PWER_GPIO25
; /* DCD and CTS */
164 PWER
&= ~(PWER_GPIO23
| PWER_GPIO25
); /* DCD and CTS */
170 static struct sa1100_port_fns h3xxx_port_fns __initdata
= {
171 .set_mctrl
= h3xxx_uart_set_mctrl
,
172 .get_mctrl
= h3xxx_uart_get_mctrl
,
174 .set_wake
= h3xxx_uart_set_wake
,
181 static struct resource egpio_resources
[] = {
182 [0] = DEFINE_RES_MEM(H3600_EGPIO_PHYS
, 0x4),
185 static struct htc_egpio_chip egpio_chips
[] = {
188 .gpio_base
= H3XXX_EGPIO_BASE
,
190 .direction
= HTC_EGPIO_OUTPUT
,
191 .initial_values
= 0x0080, /* H3XXX_EGPIO_RS232_ON */
195 static struct htc_egpio_platform_data egpio_info
= {
199 .num_chips
= ARRAY_SIZE(egpio_chips
),
202 static struct platform_device h3xxx_egpio
= {
205 .resource
= egpio_resources
,
206 .num_resources
= ARRAY_SIZE(egpio_resources
),
208 .platform_data
= &egpio_info
,
216 static struct gpio_keys_button h3xxx_button_table
[] = {
219 .gpio
= H3XXX_GPIO_PWR_BUTTON
,
220 .desc
= "Power Button",
226 .gpio
= H3XXX_GPIO_ACTION_BUTTON
,
228 .desc
= "Action button",
234 static struct gpio_keys_platform_data h3xxx_keys_data
= {
235 .buttons
= h3xxx_button_table
,
236 .nbuttons
= ARRAY_SIZE(h3xxx_button_table
),
239 static struct platform_device h3xxx_keys
= {
243 .platform_data
= &h3xxx_keys_data
,
247 static struct platform_device
*h3xxx_devices
[] = {
252 void __init
h3xxx_mach_init(void)
254 sa1100_register_uart_fns(&h3xxx_port_fns
);
255 sa11x0_register_mtd(&h3xxx_flash_data
, &h3xxx_flash_resource
, 1);
256 platform_add_devices(h3xxx_devices
, ARRAY_SIZE(h3xxx_devices
));
259 static struct map_desc h3600_io_desc
[] __initdata
= {
260 { /* static memory bank 2 CS#2 */
261 .virtual = H3600_BANK_2_VIRT
,
262 .pfn
= __phys_to_pfn(SA1100_CS2_PHYS
),
263 .length
= 0x02800000,
265 }, { /* static memory bank 4 CS#4 */
266 .virtual = H3600_BANK_4_VIRT
,
267 .pfn
= __phys_to_pfn(SA1100_CS4_PHYS
),
268 .length
= 0x00800000,
270 }, { /* EGPIO 0 CS#5 */
271 .virtual = H3600_EGPIO_VIRT
,
272 .pfn
= __phys_to_pfn(H3600_EGPIO_PHYS
),
273 .length
= 0x01000000,
279 * Common map_io initialization
282 void __init
h3xxx_map_io(void)
285 iotable_init(h3600_io_desc
, ARRAY_SIZE(h3600_io_desc
));
287 sa1100_register_uart(0, 3); /* Common serial port */
288 // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
290 /* Ensure those pins are outputs and driving low */
291 PPDR
|= PPC_TXD4
| PPC_SCLK
| PPC_SFRM
;
292 PPSR
&= ~(PPC_TXD4
| PPC_SCLK
| PPC_SFRM
);
294 /* Configure suspend conditions */
299 GPCR
= 0x0fffffff; /* All outputs are set low by default */
300 GPDR
= 0; /* Configure all GPIOs as input */