h3600.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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/sched.h>
  27. #include <asm/irq.h>
  28. #include <asm/hardware.h>
  29. #include <asm/setup.h>
  30. #include <asm/mach/arch.h>
  31. #include <asm/mach/map.h>
  32. #include <asm/mach/serial_sa1100.h>
  33. #include <linux/serial_core.h>
  34. #include <asm/arch/h3600_gpio.h>
  35. #include "generic.h"
  36. /*
  37.  * H3600 has extended, write-only memory-mapped GPIO's
  38.  * H3100 has 1/2 extended, write-only GPIO and 1/2 on
  39.  *  regular GPIO lines.
  40.  * H3800 has memory-mapped GPIO through ASIC1 & 2
  41.  */
  42. #define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT)
  43. static unsigned int h3600_egpio;
  44. /************************* H3100 *************************/
  45. #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON   
  46.   | GPIO_H3100_GPIO3   
  47.   | GPIO_H3100_QMUTE   
  48.   | GPIO_H3100_LCD_3V_ON  
  49.   | GPIO_H3100_AUD_ON   
  50.   | GPIO_H3100_AUD_PWR_ON 
  51.   | GPIO_H3100_IR_ON   
  52.   | GPIO_H3100_IR_FSEL)
  53. static void h3100_init_egpio( void )
  54. {
  55. GPDR |= H3100_DIRECT_EGPIO;
  56. GPCR = H3100_DIRECT_EGPIO;   /* Initially all off */
  57. /* Older bootldrs put GPIO2-9 in alternate mode on the
  58.    assumption that they are used for video */
  59. GAFR &= ~H3100_DIRECT_EGPIO;
  60. h3600_egpio = EGPIO_H3600_RS232_ON;
  61. H3600_EGPIO = h3600_egpio;
  62. }
  63. static void h3100_control_egpio( enum ipaq_egpio_type x, int setp )
  64. {
  65. unsigned int egpio = 0;
  66. long      gpio = 0;
  67. unsigned long flags;
  68. switch (x) {
  69. case IPAQ_EGPIO_LCD_ON:
  70. egpio |= EGPIO_H3600_LCD_ON;
  71. gpio  |= GPIO_H3100_LCD_3V_ON;
  72. break;
  73. case IPAQ_EGPIO_CODEC_NRESET:
  74. egpio |= EGPIO_H3600_CODEC_NRESET;
  75. break;
  76. case IPAQ_EGPIO_AUDIO_ON:
  77. gpio |= GPIO_H3100_AUD_PWR_ON
  78. | GPIO_H3100_AUD_ON;
  79. break;
  80. case IPAQ_EGPIO_QMUTE:
  81. gpio |= GPIO_H3100_QMUTE;
  82. break;
  83. case IPAQ_EGPIO_OPT_NVRAM_ON:
  84. egpio |= EGPIO_H3600_OPT_NVRAM_ON;
  85. break;
  86. case IPAQ_EGPIO_OPT_ON:
  87. egpio |= EGPIO_H3600_OPT_ON;
  88. break;
  89. case IPAQ_EGPIO_CARD_RESET:
  90. egpio |= EGPIO_H3600_CARD_RESET;
  91. break;
  92. case IPAQ_EGPIO_OPT_RESET:
  93. egpio |= EGPIO_H3600_OPT_RESET;
  94. break;
  95. case IPAQ_EGPIO_IR_ON:
  96. gpio |= GPIO_H3100_IR_ON;
  97. break;
  98. case IPAQ_EGPIO_IR_FSEL:
  99. gpio |= GPIO_H3100_IR_FSEL;
  100. break;
  101. case IPAQ_EGPIO_RS232_ON:
  102. egpio |= EGPIO_H3600_RS232_ON;
  103. break;
  104. case IPAQ_EGPIO_VPP_ON:
  105. egpio |= EGPIO_H3600_VPP_ON;
  106. break;
  107. }
  108. local_irq_save(flags);
  109. if ( setp ) {
  110. h3600_egpio |= egpio;
  111. GPSR = gpio;
  112. } else {
  113. h3600_egpio &= ~egpio;
  114. GPCR = gpio;
  115. }
  116. H3600_EGPIO = h3600_egpio;
  117. local_irq_restore(flags);
  118. /*
  119. if ( x != IPAQ_EGPIO_VPP_ON ) {
  120. printk(__FUNCTION__ " : type=%d (%s) gpio=0x%x (0x%x) egpio=0x%x (0x%x) setp=%dn",
  121.        x, egpio_names[x], GPLR, gpio, h3600_egpio, egpio, setp );
  122. }
  123. */
  124. }
  125. static unsigned long h3100_read_egpio( void )
  126. {
  127. return h3600_egpio;
  128. }
  129. static struct ipaq_model_ops h3100_model_ops __initdata = {
  130. model      : IPAQ_H3100,
  131. generic_name : "3100",
  132. initialize   : h3100_init_egpio,
  133. control      : h3100_control_egpio,
  134. read      : h3100_read_egpio
  135. };
  136. /************************* H3600 *************************/
  137. static void h3600_init_egpio( void )
  138. {
  139. h3600_egpio = EGPIO_H3600_RS232_ON;
  140. H3600_EGPIO = h3600_egpio;
  141. }
  142. static void h3600_control_egpio( enum ipaq_egpio_type x, int setp )
  143. {
  144. unsigned int egpio = 0;
  145. unsigned long flags;
  146. switch (x) {
  147. case IPAQ_EGPIO_LCD_ON:
  148. egpio |= EGPIO_H3600_LCD_ON |
  149.  EGPIO_H3600_LCD_PCI |
  150.  EGPIO_H3600_LCD_5V_ON |
  151.  EGPIO_H3600_LVDD_ON;
  152. break;
  153. case IPAQ_EGPIO_CODEC_NRESET:
  154. egpio |= EGPIO_H3600_CODEC_NRESET;
  155. break;
  156. case IPAQ_EGPIO_AUDIO_ON:
  157. egpio |= EGPIO_H3600_AUD_AMP_ON |
  158. EGPIO_H3600_AUD_PWR_ON;
  159. break;
  160. case IPAQ_EGPIO_QMUTE:
  161. egpio |= EGPIO_H3600_QMUTE;
  162. break;
  163. case IPAQ_EGPIO_OPT_NVRAM_ON:
  164. egpio |= EGPIO_H3600_OPT_NVRAM_ON;
  165. break;
  166. case IPAQ_EGPIO_OPT_ON:
  167. egpio |= EGPIO_H3600_OPT_ON;
  168. break;
  169. case IPAQ_EGPIO_CARD_RESET:
  170. egpio |= EGPIO_H3600_CARD_RESET;
  171. break;
  172. case IPAQ_EGPIO_OPT_RESET:
  173. egpio |= EGPIO_H3600_OPT_RESET;
  174. break;
  175. case IPAQ_EGPIO_IR_ON:
  176. egpio |= EGPIO_H3600_IR_ON;
  177. break;
  178. case IPAQ_EGPIO_IR_FSEL:
  179. egpio |= EGPIO_H3600_IR_FSEL;
  180. break;
  181. case IPAQ_EGPIO_RS232_ON:
  182. egpio |= EGPIO_H3600_RS232_ON;
  183. break;
  184. case IPAQ_EGPIO_VPP_ON:
  185. egpio |= EGPIO_H3600_VPP_ON;
  186. break;
  187. }
  188. local_irq_save(flags);
  189. if ( setp )
  190. h3600_egpio |= egpio;
  191. else
  192. h3600_egpio &= ~egpio;
  193. H3600_EGPIO = h3600_egpio;
  194. local_irq_restore(flags);
  195. }
  196. static unsigned long h3600_read_egpio( void )
  197. {
  198. return h3600_egpio;
  199. }
  200. static struct ipaq_model_ops h3600_model_ops __initdata = {
  201. model      : IPAQ_H3600,
  202. generic_name : "3600",
  203. initialize   : h3600_init_egpio,
  204. control      : h3600_control_egpio,
  205. read      : h3600_read_egpio
  206. };
  207. /************************* H3800 *************************/
  208. #define ASIC1_OUTPUTS  0x7fff   /* First 15 bits are used */
  209. static unsigned int h3800_asic1_gpio;
  210. static unsigned int h3800_asic2_gpio;
  211. static void h3800_init_egpio(void)
  212. {
  213. /* Set up ASIC #1 */
  214. H3800_ASIC1_GPIO_Direction    = ASIC1_OUTPUTS;   /* All outputs */
  215. H3800_ASIC1_GPIO_Mask       = ASIC1_OUTPUTS;   /* No interrupts */
  216. H3800_ASIC1_GPIO_SleepMask    = ASIC1_OUTPUTS;
  217. H3800_ASIC1_GPIO_SleepDir     = ASIC1_OUTPUTS;
  218. H3800_ASIC1_GPIO_SleepOut     = GPIO_H3800_ASIC1_EAR_ON_N;
  219. H3800_ASIC1_GPIO_BattFaultDir = ASIC1_OUTPUTS;
  220. H3800_ASIC1_GPIO_BattFaultOut = GPIO_H3800_ASIC1_EAR_ON_N;
  221. h3800_asic1_gpio = GPIO_H3800_ASIC1_IR_ON_N   /* TODO: Check IR level */
  222. | GPIO_H3800_ASIC1_RS232_ON
  223. | GPIO_H3800_ASIC1_EAR_ON_N;
  224. H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
  225. /* Set up ASIC #2 */
  226. H3800_ASIC2_GPIO_Direction = GPIO_H3800_ASIC2_PEN_IRQ
  227. | GPIO_H3800_ASIC2_SD_DETECT
  228. | GPIO_H3800_ASIC2_EAR_IN_N
  229. | GPIO_H3800_ASIC2_USB_DETECT_N
  230. | GPIO_H3800_ASIC2_SD_CON_SLT;
  231. h3800_asic2_gpio = GPIO_H3800_ASIC2_IN_Y1_N | GPIO_H3800_ASIC2_IN_X1_N;
  232. H3800_ASIC2_GPIO_Data       = h3800_asic2_gpio;
  233. H3800_ASIC2_GPIO_BattFaultOut = h3800_asic2_gpio;
  234. /* TODO : Set sleep states & battery fault states */
  235. /* Clear VPP Enable */
  236. H3800_ASIC1_FlashWP_VPP_ON = 0;
  237. }
  238. static void h3800_control_egpio( enum ipaq_egpio_type x, int setp )
  239. {
  240. unsigned int set_asic1_egpio = 0;
  241. unsigned int clear_asic1_egpio = 0;
  242. unsigned long flags;
  243. switch (x) {
  244. case IPAQ_EGPIO_LCD_ON:
  245. set_asic1_egpio |= GPIO_H3800_ASIC1_LCD_5V_ON
  246. | GPIO_H3800_ASIC1_LCD_ON
  247. | GPIO_H3800_ASIC1_LCD_PCI
  248. | GPIO_H3800_ASIC1_VGH_ON
  249. | GPIO_H3800_ASIC1_VGL_ON;
  250. break;
  251. case IPAQ_EGPIO_CODEC_NRESET:
  252. break;
  253. case IPAQ_EGPIO_AUDIO_ON:
  254. break;
  255. case IPAQ_EGPIO_QMUTE:
  256. break;
  257. case IPAQ_EGPIO_OPT_NVRAM_ON:
  258. break;
  259. case IPAQ_EGPIO_OPT_ON:
  260. break;
  261. case IPAQ_EGPIO_CARD_RESET:
  262. break;
  263. case IPAQ_EGPIO_OPT_RESET:
  264. break;
  265. case IPAQ_EGPIO_IR_ON:
  266. clear_asic1_egpio |= GPIO_H3800_ASIC1_IR_ON_N;  /* TODO : This is backwards? */
  267. break;
  268. case IPAQ_EGPIO_IR_FSEL:
  269. break;
  270. case IPAQ_EGPIO_RS232_ON:
  271. set_asic1_egpio |= GPIO_H3800_ASIC1_RS232_ON;
  272. break;
  273. case IPAQ_EGPIO_VPP_ON:
  274. H3800_ASIC1_FlashWP_VPP_ON = setp;
  275. break;
  276. }
  277. local_irq_save(flags);
  278. if ( setp ) {
  279. h3800_asic1_gpio |= set_asic1_egpio;
  280. h3800_asic1_gpio &= ~clear_asic1_egpio;
  281. }
  282. else {
  283. h3800_asic1_gpio &= ~set_asic1_egpio;
  284. h3800_asic1_gpio |= clear_asic1_egpio;
  285. }
  286. H3800_ASIC1_GPIO_Out = h3800_asic1_gpio;
  287. local_irq_restore(flags);
  288. }
  289. static unsigned long h3800_read_egpio( void )
  290. {
  291. return h3800_asic1_gpio | (h3800_asic2_gpio << 16);
  292. }
  293. static struct ipaq_model_ops h3800_model_ops __initdata = {
  294. model      : IPAQ_H3800,
  295. generic_name : "3800",
  296. initialize   : h3800_init_egpio,
  297. control      : h3800_control_egpio,
  298. read      : h3800_read_egpio
  299. };
  300. /*
  301.  * Use command line argument to choose between ipaq handheld model numbers
  302.  */
  303. struct ipaq_model_ops ipaq_model_ops;
  304. EXPORT_SYMBOL(ipaq_model_ops);
  305. static int __init h3600_init_model_ops(void)
  306. {
  307. if (machine_is_h3xxx()) {
  308. if (machine_is_h3100()) {
  309. ipaq_model_ops = h3100_model_ops;
  310. } else if (machine_is_h3600()) {
  311. ipaq_model_ops = h3600_model_ops;
  312. } else if (machine_is_h3800()) {
  313. ipaq_model_ops = h3800_model_ops;
  314. }
  315. init_h3600_egpio();
  316. }
  317. return 0;
  318. }
  319. __initcall(h3600_init_model_ops);
  320. /*
  321.  * low-level UART features
  322.  */
  323. static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl)
  324. {
  325. if (port->mapbase == _Ser3UTCR0) {
  326. if (mctrl & TIOCM_RTS)
  327. GPCR = GPIO_H3600_COM_RTS;
  328. else
  329. GPSR = GPIO_H3600_COM_RTS;
  330. }
  331. }
  332. static u_int h3600_uart_get_mctrl(struct uart_port *port)
  333. {
  334. u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
  335. if (port->mapbase == _Ser3UTCR0) {
  336. int gplr = GPLR;
  337. if (gplr & GPIO_H3600_COM_DCD)
  338. ret &= ~TIOCM_CD;
  339. if (gplr & GPIO_H3600_COM_CTS)
  340. ret &= ~TIOCM_CTS;
  341. }
  342. return ret;
  343. }
  344. static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
  345. {
  346. struct uart_info *info = dev_id;
  347. /* Note: should only call this if something has changed */
  348. uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD));
  349. }
  350. static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
  351. {
  352. struct uart_info *info = dev_id;
  353. /* Note: should only call this if something has changed */
  354. uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS));
  355. }
  356. static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
  357. {
  358. if (port->mapbase == _Ser2UTCR0) {
  359. assign_h3600_egpio( IPAQ_EGPIO_IR_ON, !state );
  360. } else if (port->mapbase == _Ser3UTCR0) {
  361. assign_h3600_egpio( IPAQ_EGPIO_RS232_ON, !state );
  362. }
  363. }
  364. /*
  365.  * Enable/Disable wake up events for this serial port.
  366.  * Obviously, we only support this on the normal COM port.
  367.  */
  368. static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
  369. {
  370. int err = -EINVAL;
  371. if (port->mapbase == _Ser3UTCR0) {
  372. if (enable)
  373. PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
  374. else
  375. PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
  376. err = 0;
  377. }
  378. return err;
  379. }
  380. static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
  381. {
  382. int ret = 0;
  383. if (port->mapbase == _Ser2UTCR0) {
  384. Ser2UTCR4 = UTCR4_HSE;
  385. Ser2HSCR0 = 0;
  386. Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
  387.     HSSR0_RAB | HSSR0_FRE;
  388. } else if (port->mapbase == _Ser3UTCR0) {
  389. set_GPIO_IRQ_edge(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS,
  390.   GPIO_BOTH_EDGES);
  391. ret = request_irq(IRQ_GPIO_H3600_COM_DCD, h3600_dcd_intr,
  392.   0, "RS232 DCD", info);
  393. if (ret)
  394. return ret;
  395. ret = request_irq(IRQ_GPIO_H3600_COM_CTS, h3600_cts_intr,
  396.   0, "RS232 CTS", info);
  397. if (ret)
  398. free_irq(IRQ_GPIO_H3600_COM_DCD, info);
  399. }
  400. return ret;
  401. }
  402. static void h3600_uart_close(struct uart_port *port, struct uart_info *info)
  403. {
  404. if (port->mapbase == _Ser3UTCR0) {
  405. free_irq(IRQ_GPIO_H3600_COM_DCD, info);
  406. free_irq(IRQ_GPIO_H3600_COM_CTS, info);
  407. }
  408. }
  409. static struct sa1100_port_fns h3600_port_fns __initdata = {
  410. set_mctrl: h3600_uart_set_mctrl,
  411. get_mctrl: h3600_uart_get_mctrl,
  412. pm: h3600_uart_pm,
  413. set_wake: h3600_uart_set_wake,
  414. open: h3600_uart_open,
  415. close: h3600_uart_close,
  416. };
  417. static struct map_desc h3600_io_desc[] __initdata = {
  418.  /* virtual        physical    length      domain   r  w c  b */
  419.   { 0xe8000000,        0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0   CS#0 */
  420.   { H3600_EGPIO_VIRT,  0x49000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0  CS#5 */
  421.   { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 2  CS#2 */
  422.   { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 4  CS#4 */
  423.   LAST_DESC
  424. };
  425. static void __init h3600_map_io(void)
  426. {
  427. sa1100_map_io();
  428. iotable_init(h3600_io_desc);
  429. sa1100_register_uart_fns(&h3600_port_fns);
  430. sa1100_register_uart(0, 3);
  431. sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */
  432. /*
  433.  * Default GPIO settings.  Should be set by machine
  434.  */
  435. GPCR = 0x0fffffff;
  436. // GPDR = 0x0401f3fc;
  437. GPDR = GPIO_H3600_COM_RTS  | GPIO_H3600_L3_CLOCK |
  438.        GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
  439.        GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
  440.        GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
  441.        GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
  442. init_h3600_egpio();
  443. /*
  444.  * Ensure those pins are outputs and driving low.
  445.  */
  446. PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
  447. PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
  448. /* Configure suspend conditions */
  449. PGSR = 0;
  450. PWER = PWER_GPIO0 | PWER_RTC;
  451. PCFR = PCFR_OPDE;
  452. PSDR = 0;
  453. }
  454. MACHINE_START(H3600, "Compaq iPAQ H3600")
  455. BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
  456. BOOT_PARAMS(0xc0000100)
  457. MAPIO(h3600_map_io)
  458. INITIRQ(sa1100_init_irq)
  459. MACHINE_END
  460. MACHINE_START(H3100, "Compaq iPAQ H3100")
  461. BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
  462. BOOT_PARAMS(0xc0000100)
  463. MAPIO(h3600_map_io)
  464. INITIRQ(sa1100_init_irq)
  465. MACHINE_END
  466. MACHINE_START(H3800, "Compaq iPAQ H3800")
  467. BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
  468. BOOT_PARAMS(0xc0000100)
  469. MAPIO(h3600_map_io)
  470. INITIRQ(sa1100_init_irq)
  471. MACHINE_END