微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S3C2440驱动简析——串口驱动

S3C2440驱动简析——串口驱动

时间:11-21 来源:互联网 点击:
对于驱动的学习停歇了几乎一周的时间,期间忙于补习Linux应用编程和搜索驱动、内核相关书籍,以便之后更进一步地学习。在之前友善提供的驱动例程里面,涉及的知识面非常有限,需要研究更多的驱动源码,了解更多的驱动知识,是当务之急。研究别人代码的同时,当然不忘自己也要动手练习。以下贴出串口驱动程序,并在程序里附上简要注释。

[c-sharp]view plaincopy

  1. // linux/drivers/serial/s3c2440.c
  2. *
  3. *DriverforSamsungS3C2440andS3C2442SoConboardUARTs.
  4. *
  5. *BenDooks,Copyright(c)2003-2005,2008SimtecElectronics
  6. *http://armlinux.simtec.co.uk/
  7. *
  8. *Thisprogramisfreesoftware;youcanredistributeitand/ormodify
  9. *itunderthetermsoftheGNUGeneralPublicLicenseversion2as
  10. *publishedbytheFreeSoftwareFoundation.
  11. //
  12. #include"linux/module.h"
  13. #include"linux/ioport.h"
  14. #include"linux/io.h"
  15. #include"linux/platform_device.h"
  16. #include"linux/init.h"
  17. #include"linux/serial_core.h"
  18. #include"linux/serial.h"
  19. #include"asm/irq.h"
  20. #include"mach/hardware.h"
  21. #include"plat/regs-serial.h"
  22. #include"mach/regs-gpio.h"
  23. #include"samsung.h"
  24. staticints3c2440_serial_setsource(structuart_port*port,
  25. structs3c24xx_uart_clksrc*clk)
  26. {//本函数选定串口端口和时钟源
  27. unsignedlongucon=rd_regl(port,S3C2410_UCON);//读取寄存器UCON
  28. // todo-properfclk<>nonfclkswitch.//
  29. ucon&=~S3C2440_UCON_CLKMASK;//#defineS3C2440_UCON_CLKMASK(3<10)
  30. if(strcmp(clk->name,"uclk")==0)//选择时钟源
  31. ucon|=S3C2440_UCON_UCLK;
  32. elseif(strcmp(clk->name,"pclk")==0)
  33. ucon|=S3C2440_UCON_PCLK;
  34. elseif(strcmp(clk->name,"fclk")==0)
  35. ucon|=S3C2440_UCON_FCLK;
  36. else{
  37. printk(KERN_ERR"unknownclocksource%s/n",clk->name);
  38. return-EINVAL;
  39. }
  40. wr_regl(port,S3C2410_UCON,ucon);//把设置过的ucon写回串口控制寄存器
  41. return0;
  42. }
  43. staticints3c2440_serial_getsource(structuart_port*port,
  44. structs3c24xx_uart_clksrc*clk)
  45. {//设置时钟源和对应预分频值
  46. unsignedlongucon=rd_regl(port,S3C2410_UCON);
  47. unsignedlongucon0,ucon1,ucon2;
  48. switch(ucon&S3C2440_UCON_CLKMASK){
  49. caseS3C2440_UCON_UCLK:
  50. clk->divisor=1;
  51. clk->name="uclk";
  52. break;
  53. caseS3C2440_UCON_PCLK:
  54. caseS3C2440_UCON_PCLK2:
  55. clk->divisor=1;
  56. clk->name="pclk";
  57. break;
  58. caseS3C2440_UCON_FCLK:
  59. //thefunofcalculatingtheuartdivisorson
  60. *thes3c2440//
  61. ucon0=__raw_readl(S3C24XX_VA_UART0+S3C2410_UCON);
  62. ucon1=__raw_readl(S3C24XX_VA_UART1+S3C2410_UCON);
  63. ucon2=__raw_readl(S3C24XX_VA_UART2+S3C2410_UCON);
  64. printk("ucons:lx,lx,lx/n",ucon0,ucon1,ucon2);
  65. ucon0&=S3C2440_UCON0_divMASK;
  66. ucon1&=S3C2440_UCON1_divMASK;
  67. ucon2&=S3C2440_UCON2_divMASK;
  68. if(ucon0!=0){
  69. clk->divisor=ucon0>>S3C2440_UCON_divSHIFT;
  70. clk->divisor+=6;
  71. }elseif(ucon1!=0){
  72. clk->divisor=ucon1>>S3C2440_UCON_divSHIFT;
  73. clk->divisor+=21;
  74. }elseif(ucon2!=0){
  75. clk->divisor=ucon2>>S3C2440_UCON_divSHIFT;
  76. clk->divisor+=36;
  77. }else{
  78. //manualcalims44,seemstobe9//
  79. clk->divisor=9;
  80. }
  81. clk->name="fclk";
  82. break;
  83. }
  84. return0;
  85. }
  86. staticints3c2440_serial_resetport(structuart_port*port,
  87. structs3c2410_uartcfg*cfg)
  88. {//重设串口
  89. unsignedlongucon=rd_regl(port,S3C2410_UCON);
  90. dbg("s3c2440_serial_resetport:port=%p(lx),cfg=%p/n",
  91. port,port->mapbase,cfg);
  92. //ensurewedontchangetheclocksettings...//
  93. ucon&=(S3C2440_UCON0_divMASK|(3<10));
  94. wr_regl(port,S3C2410_UCON,ucon|cfg->ucon);//重新设置寄存器UCON
  95. wr_regl(port,S3C2410_ULCON,cfg->ulcon);//重新设置寄存器ULCON
  96. //resetbothfifos//
  97. wr_regl(port,S3C2410_UFCON,cfg->ufcon|S3C2410_UFCON_RESETBOTH);//重启fifo
  98. wr_regl(port,S3C2410_UFCON,cfg->ufcon);//重新设定寄存器UFCON
  99. return0;
  100. }
  101. staticstructs3c24xx_uart_infos3c2440_uart_inf={//串口设备环境信息和提供的操作函数
  102. .name="SamsungS3C2440UART",
  103. .type=PORT_S3C2440,
  104. .fifosize=64,
  105. .rx_fifomask=S3C2440_UFSTAT_RXMASK,
  106. .rx_fifoshift=S3C2440_UFSTAT_RXSHIFT,
  107. .rx_fifofull=S3C2440_UFSTAT_RXFULL,
  108. .tx_fifofull=S3C2440_UFSTAT_TXFULL,
  109. .tx_fifomask=S3C2440_UFSTAT_TXMASK,
  110. .tx_fifoshift=S3C2440_UFSTAT_TXSHIFT,
  111. .get_clksrc=s3c2440_serial_getsource,
  112. .set_clksrc=s3c2440_serial_setsource,
  113. .reset_port=s3c2440_serial_resetport,

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top