h3600.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Hardware definitions for Compaq iPAQ H3xxx Handheld Computers
  3. *
  4. * Copyright 2000,1 Compaq Computer Corporation.
  5. *
  6. * Use consistent with the GNU GPL is permitted,
  7. * provided that this copyright notice is
  8. * preserved in its entirety in all copies and derived works.
  9. *
  10. * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
  11. * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
  12. * FITNESS FOR ANY PARTICULAR PURPOSE.
  13. *
  14. * Author: Jamey Hicks.
  15. *
  16. * History:
  17. *
  18. * 2001-10-?? Andrew Christian Added support for iPAQ H3800
  19. * and abstracted EGPIO interface.
  20. *
  21. */
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/kernel.h>
  25. #include <linux/tty.h>
  26. #include <linux/pm.h>
  27. #include <linux/device.h>
  28. #include <linux/mtd/mtd.h>
  29. #include <linux/mtd/partitions.h>
  30. #include <linux/serial_core.h>
  31. #include <asm/irq.h>
  32. #include <mach/hardware.h>
  33. #include <asm/mach-types.h>
  34. #include <asm/setup.h>
  35. #include <asm/mach/irq.h>
  36. #include <asm/mach/arch.h>
  37. #include <asm/mach/flash.h>
  38. #include <asm/mach/irda.h>
  39. #include <asm/mach/map.h>
  40. #include <asm/mach/serial_sa1100.h>
  41. #include <mach/h3600.h>
  42. #include <mach/h3600_gpio.h>
  43. #include "generic.h"
  44. struct ipaq_model_ops ipaq_model_ops;
  45. EXPORT_SYMBOL(ipaq_model_ops);
  46. static struct mtd_partition h3xxx_partitions[] = {
  47. {
  48. .name = "H3XXX boot firmware",
  49. .size = 0x00040000,
  50. .offset = 0,
  51. .mask_flags = MTD_WRITEABLE, /* force read-only */
  52. }, {
  53. .name = "H3XXX rootfs",
  54. .size = MTDPART_SIZ_FULL,
  55. .offset = 0x00040000,
  56. }
  57. };
  58. static void h3xxx_set_vpp(int vpp)
  59. {
  60. assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
  61. }
  62. static struct flash_platform_data h3xxx_flash_data = {
  63. .map_name = "cfi_probe",
  64. .set_vpp = h3xxx_set_vpp,
  65. .parts = h3xxx_partitions,
  66. .nr_parts = ARRAY_SIZE(h3xxx_partitions),
  67. };
  68. static struct resource h3xxx_flash_resource = {
  69. .start = SA1100_CS0_PHYS,
  70. .end = SA1100_CS0_PHYS + SZ_32M - 1,
  71. .flags = IORESOURCE_MEM,
  72. };
  73. /*
  74. * This turns the IRDA power on or off on the Compaq H3600
  75. */
  76. static int h3600_irda_set_power(struct device *dev, unsigned int state)
  77. {
  78. assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
  79. return 0;
  80. }
  81. static void h3600_irda_set_speed(struct device *dev, unsigned int speed)
  82. {
  83. if (speed < 4000000) {
  84. clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
  85. } else {
  86. set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
  87. }
  88. }
  89. static struct irda_platform_data h3600_irda_data = {
  90. .set_power = h3600_irda_set_power,
  91. .set_speed = h3600_irda_set_speed,
  92. };
  93. static void h3xxx_mach_init(void)
  94. {
  95. sa11x0_set_flash_data(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
  96. sa11x0_set_irda_data(&h3600_irda_data);
  97. }
  98. /*
  99. * low-level UART features
  100. */
  101. static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
  102. {
  103. if (port->mapbase == _Ser3UTCR0) {
  104. if (mctrl & TIOCM_RTS)
  105. GPCR = GPIO_H3600_COM_RTS;
  106. else
  107. GPSR = GPIO_H3600_COM_RTS;
  108. }
  109. }
  110. static u_int h3600_uart_get_mctrl(struct uart_port *port)
  111. {
  112. u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
  113. if (port->mapbase == _Ser3UTCR0) {
  114. int gplr = GPLR;
  115. /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
  116. if (gplr & GPIO_H3600_COM_DCD)
  117. ret &= ~TIOCM_CD;
  118. if (gplr & GPIO_H3600_COM_CTS)
  119. ret &= ~TIOCM_CTS;
  120. }
  121. return ret;
  122. }
  123. static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
  124. {
  125. if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
  126. assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state);
  127. } else if (port->mapbase == _Ser3UTCR0) {
  128. assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state);
  129. }
  130. }
  131. /*
  132. * Enable/Disable wake up events for this serial port.
  133. * Obviously, we only support this on the normal COM port.
  134. */
  135. static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
  136. {
  137. int err = -EINVAL;
  138. if (port->mapbase == _Ser3UTCR0) {
  139. if (enable)
  140. PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
  141. else
  142. PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
  143. err = 0;
  144. }
  145. return err;
  146. }
  147. static struct sa1100_port_fns h3600_port_fns __initdata = {
  148. .set_mctrl = h3600_uart_set_mctrl,
  149. .get_mctrl = h3600_uart_get_mctrl,
  150. .pm = h3600_uart_pm,
  151. .set_wake = h3600_uart_set_wake,
  152. };
  153. /*
  154. * helper for sa1100fb
  155. */
  156. static void h3xxx_lcd_power(int enable)
  157. {
  158. assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable);
  159. }
  160. static struct map_desc h3600_io_desc[] __initdata = {
  161. { /* static memory bank 2 CS#2 */
  162. .virtual = H3600_BANK_2_VIRT,
  163. .pfn = __phys_to_pfn(SA1100_CS2_PHYS),
  164. .length = 0x02800000,
  165. .type = MT_DEVICE
  166. }, { /* static memory bank 4 CS#4 */
  167. .virtual = H3600_BANK_4_VIRT,
  168. .pfn = __phys_to_pfn(SA1100_CS4_PHYS),
  169. .length = 0x00800000,
  170. .type = MT_DEVICE
  171. }, { /* EGPIO 0 CS#5 */
  172. .virtual = H3600_EGPIO_VIRT,
  173. .pfn = __phys_to_pfn(H3600_EGPIO_PHYS),
  174. .length = 0x01000000,
  175. .type = MT_DEVICE
  176. }
  177. };
  178. /*
  179. * Common map_io initialization
  180. */
  181. static void __init h3xxx_map_io(void)
  182. {
  183. sa1100_map_io();
  184. iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
  185. sa1100_register_uart_fns(&h3600_port_fns);
  186. sa1100_register_uart(0, 3); /* Common serial port */
  187. // sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
  188. /* Ensure those pins are outputs and driving low */
  189. PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
  190. PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
  191. /* Configure suspend conditions */
  192. PGSR = 0;
  193. PWER = PWER_GPIO0 | PWER_RTC;
  194. PCFR = PCFR_OPDE;
  195. PSDR = 0;
  196. sa1100fb_lcd_power = h3xxx_lcd_power;
  197. }
  198. static __inline__ void do_blank(int setp)
  199. {
  200. if (ipaq_model_ops.blank_callback)
  201. ipaq_model_ops.blank_callback(1-setp);
  202. }
  203. /************************* H3100 *************************/
  204. #ifdef CONFIG_SA1100_H3100
  205. #define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
  206. static unsigned int h3100_egpio = 0;
  207. static void h3100_control_egpio(enum ipaq_egpio_type x, int setp)
  208. {
  209. unsigned int egpio = 0;
  210. long gpio = 0;
  211. unsigned long flags;
  212. switch (x) {
  213. case IPAQ_EGPIO_LCD_POWER:
  214. egpio |= EGPIO_H3600_LCD_ON;
  215. gpio |= GPIO_H3100_LCD_3V_ON;
  216. do_blank(setp);
  217. break;
  218. case IPAQ_EGPIO_LCD_ENABLE:
  219. break;
  220. case IPAQ_EGPIO_CODEC_NRESET:
  221. egpio |= EGPIO_H3600_CODEC_NRESET;
  222. break;
  223. case IPAQ_EGPIO_AUDIO_ON:
  224. gpio |= GPIO_H3100_AUD_PWR_ON
  225. | GPIO_H3100_AUD_ON;
  226. break;
  227. case IPAQ_EGPIO_QMUTE:
  228. gpio |= GPIO_H3100_QMUTE;
  229. break;
  230. case IPAQ_EGPIO_OPT_NVRAM_ON:
  231. egpio |= EGPIO_H3600_OPT_NVRAM_ON;
  232. break;
  233. case IPAQ_EGPIO_OPT_ON:
  234. egpio |= EGPIO_H3600_OPT_ON;
  235. break;
  236. case IPAQ_EGPIO_CARD_RESET:
  237. egpio |= EGPIO_H3600_CARD_RESET;
  238. break;
  239. case IPAQ_EGPIO_OPT_RESET:
  240. egpio |= EGPIO_H3600_OPT_RESET;
  241. break;
  242. case IPAQ_EGPIO_IR_ON:
  243. gpio |= GPIO_H3100_IR_ON;
  244. break;
  245. case IPAQ_EGPIO_IR_FSEL:
  246. gpio |= GPIO_H3100_IR_FSEL;
  247. break;
  248. case IPAQ_EGPIO_RS232_ON:
  249. egpio |= EGPIO_H3600_RS232_ON;
  250. break;
  251. case IPAQ_EGPIO_VPP_ON:
  252. egpio |= EGPIO_H3600_VPP_ON;
  253. break;
  254. }
  255. if (egpio || gpio) {
  256. local_irq_save(flags);
  257. if (setp) {
  258. h3100_egpio |= egpio;
  259. GPSR = gpio;
  260. } else {
  261. h3100_egpio &= ~egpio;
  262. GPCR = gpio;
  263. }
  264. H3100_EGPIO = h3100_egpio;
  265. local_irq_restore(flags);
  266. }
  267. }
  268. static unsigned long h3100_read_egpio(void)
  269. {
  270. return h3100_egpio;
  271. }
  272. static int h3100_pm_callback(int req)
  273. {
  274. if (ipaq_model_ops.pm_callback_aux)
  275. return ipaq_model_ops.pm_callback_aux(req);
  276. return 0;
  277. }
  278. static struct ipaq_model_ops h3100_model_ops __initdata = {
  279. .generic_name = "3100",
  280. .control = h3100_control_egpio,
  281. .read = h3100_read_egpio,
  282. .pm_callback = h3100_pm_callback
  283. };
  284. #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \
  285. | GPIO_H3100_GPIO3 \
  286. | GPIO_H3100_QMUTE \
  287. | GPIO_H3100_LCD_3V_ON \
  288. | GPIO_H3100_AUD_ON \
  289. | GPIO_H3100_AUD_PWR_ON \
  290. | GPIO_H3100_IR_ON \
  291. | GPIO_H3100_IR_FSEL)
  292. static void __init h3100_map_io(void)
  293. {
  294. h3xxx_map_io();
  295. /* Initialize h3100-specific values here */
  296. GPCR = 0x0fffffff; /* All outputs are set low by default */
  297. GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
  298. GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
  299. GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
  300. H3100_DIRECT_EGPIO;
  301. /* Older bootldrs put GPIO2-9 in alternate mode on the
  302. assumption that they are used for video */
  303. GAFR &= ~H3100_DIRECT_EGPIO;
  304. H3100_EGPIO = h3100_egpio;
  305. ipaq_model_ops = h3100_model_ops;
  306. }
  307. MACHINE_START(H3100, "Compaq iPAQ H3100")
  308. .phys_io = 0x80000000,
  309. .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
  310. .boot_params = 0xc0000100,
  311. .map_io = h3100_map_io,
  312. .init_irq = sa1100_init_irq,
  313. .timer = &sa1100_timer,
  314. .init_machine = h3xxx_mach_init,
  315. MACHINE_END
  316. #endif /* CONFIG_SA1100_H3100 */
  317. /************************* H3600 *************************/
  318. #ifdef CONFIG_SA1100_H3600
  319. #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
  320. static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON;
  321. static void h3600_control_egpio(enum ipaq_egpio_type x, int setp)
  322. {
  323. unsigned int egpio = 0;
  324. unsigned long flags;
  325. switch (x) {
  326. case IPAQ_EGPIO_LCD_POWER:
  327. egpio |= EGPIO_H3600_LCD_ON |
  328. EGPIO_H3600_LCD_PCI |
  329. EGPIO_H3600_LCD_5V_ON |
  330. EGPIO_H3600_LVDD_ON;
  331. do_blank(setp);
  332. break;
  333. case IPAQ_EGPIO_LCD_ENABLE:
  334. break;
  335. case IPAQ_EGPIO_CODEC_NRESET:
  336. egpio |= EGPIO_H3600_CODEC_NRESET;
  337. break;
  338. case IPAQ_EGPIO_AUDIO_ON:
  339. egpio |= EGPIO_H3600_AUD_AMP_ON |
  340. EGPIO_H3600_AUD_PWR_ON;
  341. break;
  342. case IPAQ_EGPIO_QMUTE:
  343. egpio |= EGPIO_H3600_QMUTE;
  344. break;
  345. case IPAQ_EGPIO_OPT_NVRAM_ON:
  346. egpio |= EGPIO_H3600_OPT_NVRAM_ON;
  347. break;
  348. case IPAQ_EGPIO_OPT_ON:
  349. egpio |= EGPIO_H3600_OPT_ON;
  350. break;
  351. case IPAQ_EGPIO_CARD_RESET:
  352. egpio |= EGPIO_H3600_CARD_RESET;
  353. break;
  354. case IPAQ_EGPIO_OPT_RESET:
  355. egpio |= EGPIO_H3600_OPT_RESET;
  356. break;
  357. case IPAQ_EGPIO_IR_ON:
  358. egpio |= EGPIO_H3600_IR_ON;
  359. break;
  360. case IPAQ_EGPIO_IR_FSEL:
  361. egpio |= EGPIO_H3600_IR_FSEL;
  362. break;
  363. case IPAQ_EGPIO_RS232_ON:
  364. egpio |= EGPIO_H3600_RS232_ON;
  365. break;
  366. case IPAQ_EGPIO_VPP_ON:
  367. egpio |= EGPIO_H3600_VPP_ON;
  368. break;
  369. }
  370. if (egpio) {
  371. local_irq_save(flags);
  372. if (setp)
  373. h3600_egpio |= egpio;
  374. else
  375. h3600_egpio &= ~egpio;
  376. H3600_EGPIO = h3600_egpio;
  377. local_irq_restore(flags);
  378. }
  379. }
  380. static unsigned long h3600_read_egpio(void)
  381. {
  382. return h3600_egpio;
  383. }
  384. static int h3600_pm_callback(int req)
  385. {
  386. if (ipaq_model_ops.pm_callback_aux)
  387. return ipaq_model_ops.pm_callback_aux(req);
  388. return 0;
  389. }
  390. static struct ipaq_model_ops h3600_model_ops __initdata = {
  391. .generic_name = "3600",
  392. .control = h3600_control_egpio,
  393. .read = h3600_read_egpio,
  394. .pm_callback = h3600_pm_callback
  395. };
  396. static void __init h3600_map_io(void)
  397. {
  398. h3xxx_map_io();
  399. /* Initialize h3600-specific values here */
  400. GPCR = 0x0fffffff; /* All outputs are set low by default */
  401. GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK |
  402. GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA |
  403. GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
  404. GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
  405. GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
  406. H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */
  407. ipaq_model_ops = h3600_model_ops;
  408. }
  409. MACHINE_START(H3600, "Compaq iPAQ H3600")
  410. .phys_io = 0x80000000,
  411. .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
  412. .boot_params = 0xc0000100,
  413. .map_io = h3600_map_io,
  414. .init_irq = sa1100_init_irq,
  415. .timer = &sa1100_timer,
  416. .init_machine = h3xxx_mach_init,
  417. MACHINE_END
  418. #endif /* CONFIG_SA1100_H3600 */