1 // SPDX-License-Identifier: GPL-2.0-only
3 * Support for Compaq iPAQ H3100 and H3600 handheld computers (common code)
5 * Copyright (c) 2000,1 Compaq Computer Corporation. (Author: Jamey Hicks)
6 * Copyright (c) 2009 Dmitry Artamonow <mad_soft@inbox.ru>
9 #include <linux/kernel.h>
10 #include <linux/gpio/machine.h>
11 #include <linux/gpio.h>
12 #include <linux/gpio_keys.h>
13 #include <linux/input.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/partitions.h>
16 #include <linux/platform_data/gpio-htc-egpio.h>
17 #include <linux/platform_data/sa11x0-serial.h>
18 #include <linux/platform_device.h>
19 #include <linux/serial_core.h>
21 #include <asm/mach/flash.h>
22 #include <asm/mach/map.h>
24 #include <mach/h3xxx.h>
25 #include <mach/irqs.h>
32 static struct mtd_partition h3xxx_partitions
[] = {
34 .name
= "H3XXX boot firmware",
37 .mask_flags
= MTD_WRITEABLE
, /* force read-only */
39 .name
= "H3XXX rootfs",
40 .size
= MTDPART_SIZ_FULL
,
45 static void h3xxx_set_vpp(int vpp
)
47 gpio_set_value(H3XXX_EGPIO_VPP_ON
, vpp
);
50 static int h3xxx_flash_init(void)
52 int err
= gpio_request(H3XXX_EGPIO_VPP_ON
, "Flash Vpp");
54 pr_err("%s: can't request H3XXX_EGPIO_VPP_ON\n", __func__
);
58 err
= gpio_direction_output(H3XXX_EGPIO_VPP_ON
, 0);
60 gpio_free(H3XXX_EGPIO_VPP_ON
);
65 static void h3xxx_flash_exit(void)
67 gpio_free(H3XXX_EGPIO_VPP_ON
);
70 static struct flash_platform_data h3xxx_flash_data
= {
71 .map_name
= "cfi_probe",
72 .set_vpp
= h3xxx_set_vpp
,
73 .init
= h3xxx_flash_init
,
74 .exit
= h3xxx_flash_exit
,
75 .parts
= h3xxx_partitions
,
76 .nr_parts
= ARRAY_SIZE(h3xxx_partitions
),
79 static struct resource h3xxx_flash_resource
=
80 DEFINE_RES_MEM(SA1100_CS0_PHYS
, SZ_32M
);
86 static void h3xxx_uart_pm(struct uart_port
*port
, u_int state
, u_int oldstate
)
88 if (port
->mapbase
== _Ser3UTCR0
) {
89 if (!gpio_request(H3XXX_EGPIO_RS232_ON
, "RS232 transceiver")) {
90 gpio_direction_output(H3XXX_EGPIO_RS232_ON
, !state
);
91 gpio_free(H3XXX_EGPIO_RS232_ON
);
93 pr_err("%s: can't request H3XXX_EGPIO_RS232_ON\n",
100 * Enable/Disable wake up events for this serial port.
101 * Obviously, we only support this on the normal COM port.
103 static int h3xxx_uart_set_wake(struct uart_port
*port
, u_int enable
)
107 if (port
->mapbase
== _Ser3UTCR0
) {
109 PWER
|= PWER_GPIO23
| PWER_GPIO25
; /* DCD and CTS */
111 PWER
&= ~(PWER_GPIO23
| PWER_GPIO25
); /* DCD and CTS */
117 static struct sa1100_port_fns h3xxx_port_fns __initdata
= {
119 .set_wake
= h3xxx_uart_set_wake
,
122 static struct gpiod_lookup_table h3xxx_uart3_gpio_table
= {
123 .dev_id
= "sa11x0-uart.3",
125 GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_DCD
, "dcd", GPIO_ACTIVE_LOW
),
126 GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_CTS
, "cts", GPIO_ACTIVE_LOW
),
127 GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_RTS
, "rts", GPIO_ACTIVE_LOW
),
136 static struct resource egpio_resources
[] = {
137 [0] = DEFINE_RES_MEM(H3600_EGPIO_PHYS
, 0x4),
140 static struct htc_egpio_chip egpio_chips
[] = {
143 .gpio_base
= H3XXX_EGPIO_BASE
,
145 .direction
= HTC_EGPIO_OUTPUT
,
146 .initial_values
= 0x0080, /* H3XXX_EGPIO_RS232_ON */
150 static struct htc_egpio_platform_data egpio_info
= {
154 .num_chips
= ARRAY_SIZE(egpio_chips
),
157 static struct platform_device h3xxx_egpio
= {
160 .resource
= egpio_resources
,
161 .num_resources
= ARRAY_SIZE(egpio_resources
),
163 .platform_data
= &egpio_info
,
171 static struct gpio_keys_button h3xxx_button_table
[] = {
174 .gpio
= H3XXX_GPIO_PWR_BUTTON
,
175 .desc
= "Power Button",
181 .gpio
= H3XXX_GPIO_ACTION_BUTTON
,
183 .desc
= "Action button",
189 static struct gpio_keys_platform_data h3xxx_keys_data
= {
190 .buttons
= h3xxx_button_table
,
191 .nbuttons
= ARRAY_SIZE(h3xxx_button_table
),
194 static struct platform_device h3xxx_keys
= {
198 .platform_data
= &h3xxx_keys_data
,
202 static struct resource h3xxx_micro_resources
[] = {
203 DEFINE_RES_MEM(0x80010000, SZ_4K
),
204 DEFINE_RES_MEM(0x80020000, SZ_4K
),
205 DEFINE_RES_IRQ(IRQ_Ser1UART
),
208 struct platform_device h3xxx_micro_asic
= {
209 .name
= "ipaq-h3xxx-micro",
211 .resource
= h3xxx_micro_resources
,
212 .num_resources
= ARRAY_SIZE(h3xxx_micro_resources
),
215 static struct platform_device
*h3xxx_devices
[] = {
221 static struct gpiod_lookup_table h3xxx_pcmcia_gpio_table
= {
222 .dev_id
= "sa11x0-pcmcia",
224 GPIO_LOOKUP("gpio", H3XXX_GPIO_PCMCIA_CD0
,
225 "pcmcia0-detect", GPIO_ACTIVE_LOW
),
226 GPIO_LOOKUP("gpio", H3XXX_GPIO_PCMCIA_IRQ0
,
227 "pcmcia0-ready", GPIO_ACTIVE_HIGH
),
228 GPIO_LOOKUP("gpio", H3XXX_GPIO_PCMCIA_CD1
,
229 "pcmcia1-detect", GPIO_ACTIVE_LOW
),
230 GPIO_LOOKUP("gpio", H3XXX_GPIO_PCMCIA_IRQ1
,
231 "pcmcia1-ready", GPIO_ACTIVE_HIGH
),
236 void __init
h3xxx_mach_init(void)
238 gpiod_add_lookup_table(&h3xxx_pcmcia_gpio_table
);
239 gpiod_add_lookup_table(&h3xxx_uart3_gpio_table
);
240 sa1100_register_uart_fns(&h3xxx_port_fns
);
241 sa11x0_register_mtd(&h3xxx_flash_data
, &h3xxx_flash_resource
, 1);
242 platform_add_devices(h3xxx_devices
, ARRAY_SIZE(h3xxx_devices
));
245 static struct map_desc h3600_io_desc
[] __initdata
= {
246 { /* static memory bank 2 CS#2 */
247 .virtual = H3600_BANK_2_VIRT
,
248 .pfn
= __phys_to_pfn(SA1100_CS2_PHYS
),
249 .length
= 0x02800000,
251 }, { /* static memory bank 4 CS#4 */
252 .virtual = H3600_BANK_4_VIRT
,
253 .pfn
= __phys_to_pfn(SA1100_CS4_PHYS
),
254 .length
= 0x00800000,
256 }, { /* EGPIO 0 CS#5 */
257 .virtual = H3600_EGPIO_VIRT
,
258 .pfn
= __phys_to_pfn(H3600_EGPIO_PHYS
),
259 .length
= 0x01000000,
265 * Common map_io initialization
268 void __init
h3xxx_map_io(void)
271 iotable_init(h3600_io_desc
, ARRAY_SIZE(h3600_io_desc
));
273 sa1100_register_uart(0, 3); /* Common serial port */
274 // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
276 /* Ensure those pins are outputs and driving low */
277 PPDR
|= PPC_TXD4
| PPC_SCLK
| PPC_SFRM
;
278 PPSR
&= ~(PPC_TXD4
| PPC_SCLK
| PPC_SFRM
);
280 /* Configure suspend conditions */
285 GPCR
= 0x0fffffff; /* All outputs are set low by default */
286 GPDR
= 0; /* Configure all GPIOs as input */