ohci-s3c2410代码注释解析

  1.    
  2. /*   
  3. * OHCI HCD (Host Controller Driver) for USB  
  4. 该程序主要完成s3c2410 USB 主机控制器的初始化工作,包括电源,时钟等  
  5. */   
  6. //需要用到的头文件    
  7. #include <ASM hardware.h>     
  8. #include <ASM mach-types.h>     
  9. #include <ASM hardware clock.h>     
  10. #include <ASM arch usb-control.h>     
  11. //定义主机控制器的有效端口数    
  12. #define valid_port(idx) ((idx) == 1 || (idx) == 2)     
  13.    
  14. /* 主机控制器的时钟,在clock.h中有它的定义 */   
  15.    
  16. static struct clk *clk;    
  17.    
  18. /* 预定义,s3c2410_hcd_oc   主机端口的过流保护函数*/   
  19.    
  20. static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);    
  21.    
  22. /* 该函数返回总线上的当前的平台信息  
  23.     该函数的返回结构: (具体的定义在usb_control.h中)  
  24.     struct s3c2410_hcd_info{  
  25.             struct usb_hcd  *hcd;  
  26.             struct s3c2410_hcd_port port[2];  
  27.             void  (*power_control)(int port,int to);  
  28.             void  (*enable_oc)(struct s3c2410_hcd_info *,int on);  
  29.             void  (*report_oc)(struct s3c2410_hcd_info *,int ports);  
  30.     };  
  31.   
  32.   
  33.  */   
  34.    
  35. struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)    
  36. {    
  37. return hcd->self.controller->platform_data;    
  38. }    
  39.  /* s3c2410_start_hc  该函数启动主机控制器,主要是启动时钟,对打开对端口的过流保护  
  40.  */   
  41. static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)    
  42. {    
  43. struct s3c2410_hcd_info *info = dev->dev.platform_data;    
  44.    
  45. dev_dbg(&dev->dev, "s3c2410_start_hc:/n");    
  46. clk_enable(clk);    
  47.    
  48. if (info != NULL) {    
  49. info->hcd = hcd;    
  50. info->report_oc = s3c2410_hcd_oc;    
  51.    
  52. if (info->enable_oc != NULL) {    
  53. (info->enable_oc)(info, 1);    
  54. }    
  55. }    
  56. }    
  57.  /* s3c2410_stop_hc  该函数停止主机控制器,关闭时钟  
  58.  */   
  59. static void s3c2410_stop_hc(struct platform_device *dev)    
  60. {    
  61. struct s3c2410_hcd_info *info = dev->dev.platform_data;    
  62.    
  63. dev_dbg(&dev->dev, "s3c2410_stop_hc:/n");    
  64.    
  65. if (info != NULL) {    
  66. info->report_oc = NULL;    
  67. info->hcd = NULL;    
  68.    
  69. if (info->enable_oc != NULL) {    
  70. (info->enable_oc)(info, 0);    
  71. }    
  72. }    
  73.    
  74. clk_disable(clk);    
  75. }    
  76.    
  77. /* ohci_s3c2410_hub_status_data  该函数是集线器的状态函数,  
  78. 扫描集线器的两个下行端口,检测是否连接USB设备,若有返回1,无,返回0  
  79.   
  80. */    
  81.    
  82. static int    
  83. ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf)    
  84. {    
  85. struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);    
  86. struct s3c2410_hcd_port *port;    
  87. int orig;    
  88. int portno;    
  89.    
  90. orig = ohci_hub_status_data (hcd, buf);    
  91.    
  92. if (info == NULL)    
  93. return orig;    
  94.    
  95. port = &info->port[0];    
  96.    
  97. /*扫描两个端口*/   
  98.    
  99. for (portno = 0; portno < 2; port++, portno++) {    
  100. if (port->oc_changed == 1 &&    
  101. port->flags & S3C_HCDFLG_USED) {    
  102. dev_dbg(hcd->self.controller,    
  103. "oc change on port %d/n", portno);    
  104.    
  105. if (orig < 1)    
  106. orig = 1;    
  107.    
  108. buf[0] |= 1<<(portno+1);    
  109. }    
  110. }    
  111.    
  112. return orig;    
  113. }    
  114.    
  115. /* s3c2410_usb_set_power 该函数实现对端口的电源配置  
  116.   
  117. */    
  118.    
  119. static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info,    
  120. int port, int to)    
  121. {    
  122. if (info == NULL)    
  123. return;    
  124.    
  125. if (info->power_control != NULL) {    
  126. info->port[port-1].power = to;    
  127. (info->power_control)(port, to);    
  128. }    
  129. }    
  130.    
  131. /* ohci_s3c2410_hub_control  该函数是集线器的控制函数  
  132.  处理一些对 集线器的控制请求  
  133.  具体参数:  
  134. typeReq 控制请求类别  
  135.  wValue 请求值  
  136. */    
  137.    
  138. static int ohci_s3c2410_hub_control (   
  139. struct usb_hcd *hcd,    
  140. u16 typeReq,    
  141. u16 wValue,    
  142. u16 wIndex,    
  143. char *buf,    
  144. u16 wLength)    
  145. {    
  146. struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);    
  147. struct usb_hub_descriptor *desc;    
  148. int ret = -EINVAL;    
  149. u32 *data = (u32 *)buf;    
  150.    
  151. dev_dbg(hcd->self.controller,    
  152. "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)/n",    
  153. hcd, typeReq, wValue, wIndex, buf, wLength);    
  154.    
  155.    
  156. if (info == NULL) {    
  157. ret = ohci_hub_control(hcd, typeReq, wValue,    
  158. wIndex, buf, wLength);    
  159. goto out;    
  160. }    
  161.    
  162. /* 检测HUB的请求类别,并且处理相关请求  
  163. */   
  164.    
  165. switch (typeReq) {    
  166. /*集线器启用端口的请求  */   
  167. case SetPortFeature:    
  168. if (wValue == USB_PORT_FEAT_POWER) {    
  169. dev_dbg(hcd->self.controller, "SetPortFeat: POWER/n");    
  170. s3c2410_usb_set_power(info, wIndex, 1);    
  171. goto out;    
  172. }    
  173. break;    
  174. /* 消除端口的请求*/   
  175. case ClearPortFeature:    
  176. /*具体的请求值*/   
  177. switch (wValue) {    
  178. case USB_PORT_FEAT_C_OVER_CURRENT:    
  179. dev_dbg(hcd->self.controller,    
  180. "ClearPortFeature: C_OVER_CURRENT/n");    
  181.    
  182. if (valid_port(wIndex)) {    
  183. info->port[wIndex-1].oc_changed = 0;    
  184. info->port[wIndex-1].oc_status = 0;    
  185. }    
  186.    
  187. goto out;    
  188.    
  189. case USB_PORT_FEAT_OVER_CURRENT:    
  190. dev_dbg(hcd->self.controller,    
  191. "ClearPortFeature: OVER_CURRENT/n");    
  192.    
  193. if (valid_port(wIndex)) {    
  194. info->port[wIndex-1].oc_status = 0;    
  195. }    
  196.    
  197. goto out;    
  198.    
  199. case USB_PORT_FEAT_POWER:    
  200. dev_dbg(hcd->self.controller,    
  201. "ClearPortFeature: POWER/n");    
  202.    
  203. if (valid_port(wIndex)) {    
  204. s3c2410_usb_set_power(info, wIndex, 0);    
  205. return 0;    
  206. }    
  207. }    
  208. break;    
  209. }    
  210.    
  211. ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);    
  212. if (ret)    
  213. goto out;    
  214.    
  215. switch (typeReq) {    
  216. /*获取集线器特定的描述符*/   
  217. case GetHubDescriptor:    
  218.    
  219. /* 更新集线器的描述符*/   
  220.    
  221. desc = (struct usb_hub_descriptor *)buf;    
  222.    
  223. if (info->power_control == NULL)    
  224. return ret;    
  225.    
  226. dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x/n",    
  227. desc->wHubCharacteristics);    
  228.    
  229. /* 更新集线器的配置,包括HUB电源和过流保护的配置  
  230. */    
  231.    
  232. desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM);    
  233. desc->wHubCharacteristics |= cpu_to_le16(0x0001);    
  234.    
  235. if (info->enable_oc) {    
  236. desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM);    
  237. desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001);    
  238. }    
  239.    
  240. dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x/n",    
  241. desc->wHubCharacteristics);    
  242.    
  243. return ret;    
  244. /* 获取端口的状态 */   
  245. case GetPortStatus:    
  246.    
  247. dev_dbg(hcd->self.controller, "GetPortStatus(%d)/n", wIndex);    
  248.    
  249. if (valid_port(wIndex)) {    
  250. if (info->port[wIndex-1].oc_changed) {    
  251. *data |= cpu_to_le32(RH_PS_OCIC);    
  252. }    
  253.    
  254. if (info->port[wIndex-1].oc_status) {    
  255. *data |= cpu_to_le32(RH_PS_POCI);    
  256. }    
  257. }    
  258. }    
  259.    
  260. out:    
  261. return ret;    
  262. }    
  263.    
  264. /* s3c2410_hcd_oc  该函数是主机控制器对端口的过流保护  
  265.   
  266. */    
  267.    
  268. static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)    
  269. {    
  270. struct s3c2410_hcd_port *port;    
  271. struct usb_hcd *hcd;    
  272. unsigned long flags;    
  273. int portno;    
  274.    
  275. if (info == NULL)    
  276. return;    
  277.    
  278. port = &info->port[0];    
  279. hcd = info->hcd;    
  280.    
  281. local_irq_save(flags);    
  282.    
  283. for (portno = 0; portno < 2; port++, portno++) {    
  284. if (port_oc & (1<<PORTNO) && port->flags & S3C_HCDFLG_USED) {    
  285. port->oc_status = 1;    
  286. port->oc_changed = 1;    
  287.    
  288. /* 停止该端口的供电 */   
  289. s3c2410_usb_set_power(info, portno+1, 0);    
  290. }    
  291. }    
  292.    
  293. local_irq_restore(flags);    
  294. }    
  295.    
  296. /*  usb_hcd_s3c2410_remove  主机控制器的卸载  
  297. 停止主机控制器,释放内存资源  
  298.   
  299. *   
  300. */    
  301.    
  302. void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)    
  303. {    
  304. usb_remove_hcd(hcd);    
  305. s3c2410_stop_hc(dev);    
  306. iounmap(hcd->regs);  //解除与内存映射的关系函数    
  307. release_mem_region(hcd->rsrc_start, hcd->rsrc_len);    
  308. usb_put_hcd(hcd);    
  309. }    
  310.    
  311. /**  usb_hcd_s3c2410_probe    USB 主机控制器的探测函数.  
  312.   主要实现对主机控制器进行分配资源,并启动主机控制器等  
  313. */    
  314. int usb_hcd_s3c2410_probe (const struct hc_driver *driver,    
  315. struct platform_device *dev)    
  316. {    
  317. struct usb_hcd *hcd = NULL;    
  318. int retval;    
  319. /** 给端口进行供电*/   
  320. s3c2410_usb_set_power(dev->dev.platform_data, 0, 1);    
  321. s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);    
  322. /** usb_create_hcd() 函数初始化主机控制器*/   
  323. hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");    
  324. if (hcd == NULL)    
  325. return -ENOMEM; //系统错误,没有相应的内存空间    
  326.  /*主机控制器的资源节点*/   
  327. hcd->rsrc_start = dev->resource[0].start;    
  328. hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;    
  329.  /*请求分配内存资源*/   
  330. if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {    
  331. dev_err(&dev->dev, "request_mem_region failed");    
  332. retval = -EBUSY;   //系统错误,表示要分配的内存资源已经被占用    
  333. goto err0;    
  334. }    
  335.    
  336. clk = clk_get(NULL, "usb-host");    
  337. if (IS_ERR(clk)) {    
  338. dev_err(&dev->dev, "cannot get usb-host clock/n");    
  339. retval = -ENOENT;    
  340. goto err1;    
  341. }    
  342. /*启动始终,并启动主机控制器*/   
  343. clk_use(clk);    
  344. s3c2410_start_hc(dev, hcd);    
  345. /*ioremap()作用是将物理地址映射成相应的虚拟地址*/   
  346. hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);    
  347. if (!hcd->regs) {    
  348. dev_err(&dev->dev, "ioremap failed/n");    
  349. retval = -ENOMEM;    
  350. goto err2;    
  351. }    
  352.    
  353. ohci_hcd_init(hcd_to_ohci(hcd));    
  354.    
  355. retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);    
  356. if (retval != 0)    
  357. goto err2;    
  358.    
  359. return 0;    
  360.    
  361. err2:    
  362. s3c2410_stop_hc(dev);    
  363. iounmap(hcd->regs);    
  364. clk_unuse(clk);    
  365. clk_put(clk);    
  366.    
  367. err1:    
  368. release_mem_region(hcd->rsrc_start, hcd->rsrc_len);    
  369.    
  370. err0:    
  371. usb_put_hcd(hcd);    
  372. return retval;    
  373. }    
  374. /* ohci_s3c2410_start 开放式主机控制器接口的启动函数  
  375.   调用上层的 ohci_run()函数来实现该功能  
  376. */   
  377.    
  378. static int    
  379. ohci_s3c2410_start (struct usb_hcd *hcd)    
  380. {    
  381. struct ohci_hcd *ohci = hcd_to_ohci (hcd);    
  382. int ret;    
  383.    
  384. if ((ret = ohci_init(ohci)) < 0)    
  385. return ret;    
  386.    
  387. if ((ret = ohci_run (ohci)) < 0) {    
  388. err ("can't start %s", hcd->self.bus_name);    
  389. ohci_stop (hcd);    
  390. return ret;    
  391. }    
  392.    
  393. return 0;    
  394. }    
  395. /*节点操作函数的实例  
  396. 定义了2410 USB主机控制器的具体操作函数实例  
  397. */   
  398.    
  399. static const struct hc_driver ohci_s3c2410_hc_driver = {    
  400. .description = hcd_name,    
  401. .product_desc = "S3C24XX OHCI",    
  402. .hcd_priv_size = sizeof(struct ohci_hcd),    
  403.    
  404.    
  405. .irq = ohci_irq,    
  406. .flags = HCD_USB11 | HCD_MEMORY,    
  407.    
  408. .start = ohci_s3c2410_start,    
  409. .stop = ohci_stop,    
  410.    
  411. /*   
  412. * 管理I/O请求&相关的设备资源  
  413. */    
  414. .urb_enqueue = ohci_urb_enqueue, //提交URB的具体处理函数    
  415. .urb_dequeue = ohci_urb_dequeue,    
  416. .endpoint_disable = ohci_endpoint_disable,    
  417.    
  418. /*   
  419. *调度支持,获取当前总线帧号  
  420. */    
  421. .get_frame_number = ohci_get_frame,    
  422.    
  423. /*   
  424. * 根集线器的控制实例  
  425. */    
  426. .hub_status_data = ohci_s3c2410_hub_status_data,    
  427. .hub_control = ohci_s3c2410_hub_control,    
  428.    
  429. #if defined(CONFIG_USB_SUSPEND) && 0     
  430. .hub_suspend = ohci_hub_suspend,    
  431. .hub_resume = ohci_hub_resume,    
  432. #endif     
  433. };    
  434.    
  435. /*ohci_hcd_s3c2410_drv_probe  主机控制器驱动的探测函数   */   
  436.    
  437. static int ohci_hcd_s3c2410_drv_probe(struct device *dev)    
  438. {    
  439. struct platform_device *pdev = to_platform_device(dev);    
  440. return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);    
  441. }    
  442. /*ohci_hcd_s3c2410_drv_remove  主机控制器驱动的卸载函数   */   
  443. static int ohci_hcd_s3c2410_drv_remove(struct device *dev)    
  444. {    
  445. struct platform_device *pdev = to_platform_device(dev);    
  446. struct usb_hcd *hcd = dev_get_drvdata(dev);    
  447.    
  448. usb_hcd_s3c2410_remove(hcd, pdev);    
  449. return 0;    
  450. }    
  451. /*  
  452. *s3c2410 主机控制驱动的结构实例  
  453. ***/   
  454. static struct device_driver ohci_hcd_s3c2410_driver = {    
  455. .name = "s3c2410-ohci",   //驱动名称    
  456. .bus = &platform_bus_type,  //总线类型    
  457. .probe = ohci_hcd_s3c2410_drv_probe,  //驱动的探测    
  458. .remove = ohci_hcd_s3c2410_drv_remove,  //驱动的卸载    
  459.    
  460. };    
  461. /*s3c2410主机控制器的初始,系统调用,注册主机设备  */   
  462. static int __init ohci_hcd_s3c2410_init (void)    
  463. {    
  464. return driver_register(&ohci_hcd_s3c2410_driver);    
  465. }    
  466.  /* s3c2410主机控制器的注销,从Linux内核中注销驱动程序 */   
  467. static void __exit ohci_hcd_s3c2410_cleanup (void)    
  468. {    
  469. driver_unregister(&ohci_hcd_s3c2410_driver);    
  470. }    
  471. /*  初始&卸载 s3c2410主机控制模块   */   
  472. module_init (ohci_hcd_s3c2410_init);    
  473. module_exit (ohci_hcd_s3c2410_cleanup);    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值