当前位置:   article > 正文

交换机进行读写rtl8306.c驱动源码_rtl836 驱动

rtl836 驱动

应用端读写

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <error.h>
  8. #include <stdint.h>
  9. #include <sys/ioctl.h>
  10. #define SET_ADDR_CMD _IOW('S', 0x01, int)
  11. #define SET_REGNUM_CMD _IOW('S', 0x02, uint32_t)
  12. int main(int argc, char **argv)
  13. {
  14. int fd = open("/dev/switch-dev", O_RDWR);
  15. if (fd < 0)
  16. {
  17. perror("Failed to open device");
  18. return -1;
  19. }
  20. // 设置addr和regnum
  21. int ret = ioctl(fd, SET_ADDR_CMD, 0x04);
  22. ioctl(fd, SET_REGNUM_CMD, 0x01);
  23. printf("ret: %d\n", ret);
  24. // 读取上面设置addr和regnum下寄存器的值
  25. int val;
  26. ret = read(fd, &val, sizeof(val));
  27. printf("val: 0x%x, ret: %d\n", val, ret);
  28. val = 0x12;
  29. write(fd, &val, sizeof(val));
  30. close(fd);
  31. return 0;
  32. }

  1. #include <linux/module.h>
  2. #include <linux/platform_device.h>
  3. #include <linux/fs.h>
  4. #include <linux/cdev.h>
  5. #include <linux/device.h>
  6. #include <linux/mdio.h>
  7. #include <linux/of.h>
  8. #include <linux/of_mdio.h>
  9. #define DRIVER_NAME "rtl8306"
  10. #define DEVICE_NAME "switch-dev"
  11. #define NUM_MINORS 1
  12. #define MAGIC_DATA 'S'
  13. #define SET_ADDR_CMD _IOW(MAGIC_DATA, 0x01, int)
  14. #define SET_REGNUM_CMD _IOW(MAGIC_DATA, 0x02, u32)
  15. struct rtl8306_switch_phy_data {
  16. int addr;
  17. u32 regnum;
  18. u16 val;
  19. };
  20. struct rtl8306_switch_data {
  21. struct cdev cdev;
  22. struct device *device;
  23. struct mii_bus *bus;
  24. struct rtl8306_switch_phy_data phy;
  25. };
  26. static struct class *rtl8306_switch_class;
  27. static dev_t rtl8306_switch_dev_number;
  28. static struct rtl8306_switch_data rtl8306_switch;
  29. static int rtl8306_switch_open(struct inode *inode, struct file *filp)
  30. {
  31. struct rtl8306_switch_data *data;
  32. data = container_of(inode->i_cdev, struct rtl8306_switch_data, cdev);
  33. filp->private_data = data;
  34. return 0;
  35. }
  36. static ssize_t rtl8306_switch_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
  37. {
  38. struct rtl8306_switch_data *data = filp->private_data;
  39. struct mii_bus *bus = data->bus;
  40. struct rtl8306_switch_phy_data *phy = &data->phy;
  41. u16 val;
  42. // printk("+++ func: %s, line: %d +++, phy->addr: 0x%x, phy->regnum: 0x%x\n", __func__, __LINE__, phy->addr, phy->regnum);
  43. val = mdiobus_read(bus, phy->addr, phy->regnum);
  44. if (val < 0)
  45. return val;
  46. if (copy_to_user(buf, &val, sizeof(val)))
  47. return -EFAULT;
  48. return sizeof(val);
  49. }
  50. static ssize_t rtl8306_switch_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
  51. {
  52. struct rtl8306_switch_data *data = filp->private_data;
  53. struct mii_bus *bus = data->bus;
  54. struct rtl8306_switch_phy_data *phy = &data->phy;
  55. u16 val;
  56. if (copy_from_user(&val, buf, sizeof(val)))
  57. return -EFAULT;
  58. // printk("+++ func: %s, line: %d +++, val: 0x%x\n", __func__, __LINE__, val);
  59. return mdiobus_write(bus, phy->addr, phy->regnum, val);
  60. }
  61. static long rtl8306_switch_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  62. {
  63. struct rtl8306_switch_data *data = filp->private_data;
  64. struct rtl8306_switch_phy_data *phy = &data->phy;
  65. switch (cmd) {
  66. case SET_ADDR_CMD:
  67. phy->addr = arg;
  68. // printk("+++ func: %s, line: %d +++, phy->addr: 0x%x\n", __func__,__LINE__, phy->addr);
  69. break;
  70. case SET_REGNUM_CMD:
  71. phy->regnum = arg;
  72. // printk("+++ func: %s, line: %d +++, phy->regnum: 0x%x\n", __func__, __LINE__, phy->regnum);
  73. break;
  74. default:
  75. return -EINVAL;
  76. }
  77. return 0;
  78. }
  79. static struct file_operations rtl8306_switch_fops = {
  80. .owner = THIS_MODULE,
  81. .open = rtl8306_switch_open,
  82. .read = rtl8306_switch_read,
  83. .write = rtl8306_switch_write,
  84. .unlocked_ioctl = rtl8306_switch_ioctl,
  85. };
  86. static int rtl8306_switch_probe(struct platform_device *pdev)
  87. {
  88. struct device *dev = &pdev->dev;
  89. struct device_node *mdio_np;
  90. int ret;
  91. // printk("+++ func: %s, line: %d +++\n", __func__, __LINE__);
  92. mdio_np = of_parse_phandle(dev->of_node, "mdio-bus", 0);
  93. if (!mdio_np) {
  94. dev_err(dev, "Failed to get MDIO bus node\n");
  95. return -ENODEV;
  96. }
  97. rtl8306_switch.bus = of_mdio_find_bus(mdio_np);
  98. of_node_put(mdio_np);
  99. if (!rtl8306_switch.bus) {
  100. dev_err(dev, "Failed to find MDIO bus\n");
  101. return -ENODEV;
  102. }
  103. // Initialize character device
  104. cdev_init(&rtl8306_switch.cdev, &rtl8306_switch_fops);
  105. rtl8306_switch.cdev.owner = THIS_MODULE;
  106. // Allocate device numbers
  107. ret = alloc_chrdev_region(&rtl8306_switch_dev_number, 0, NUM_MINORS, DRIVER_NAME);
  108. if (ret < 0) {
  109. dev_err(dev, "Failed to allocate device numbers\n");
  110. return ret;
  111. }
  112. // Create device class
  113. rtl8306_switch.device = device_create(rtl8306_switch_class, dev, rtl8306_switch_dev_number, NULL, DEVICE_NAME);
  114. if (IS_ERR(rtl8306_switch.device)) {
  115. class_destroy(rtl8306_switch_class);
  116. unregister_chrdev_region(rtl8306_switch_dev_number, NUM_MINORS);
  117. dev_err(dev, "Failed to create device\n");
  118. return PTR_ERR(rtl8306_switch.device);
  119. }
  120. // Add character device to the system
  121. ret = cdev_add(&rtl8306_switch.cdev, rtl8306_switch_dev_number, NUM_MINORS);
  122. if (ret < 0) {
  123. device_destroy(rtl8306_switch_class, rtl8306_switch_dev_number);
  124. class_destroy(rtl8306_switch_class);
  125. unregister_chrdev_region(rtl8306_switch_dev_number, NUM_MINORS);
  126. dev_err(dev, "Failed to add character device\n");
  127. return ret;
  128. }
  129. dev_info(dev, "My Switch driver initialized\n");
  130. return 0;
  131. }
  132. static int rtl8306_switch_remove(struct platform_device *pdev)
  133. {
  134. cdev_del(&rtl8306_switch.cdev);
  135. device_destroy(rtl8306_switch_class, rtl8306_switch_dev_number);
  136. class_destroy(rtl8306_switch_class);
  137. unregister_chrdev_region(rtl8306_switch_dev_number, NUM_MINORS);
  138. dev_info(&pdev->dev, "My Switch driver removed\n");
  139. return 0;
  140. }
  141. static const struct of_device_id rtl8306_switch_of_match[] = {
  142. { .compatible = DRIVER_NAME, },
  143. { },
  144. };
  145. MODULE_DEVICE_TABLE(of, rtl8306_switch_of_match);
  146. static struct platform_driver rtl8306_switch_driver = {
  147. .probe = rtl8306_switch_probe,
  148. .remove = rtl8306_switch_remove,
  149. .driver = {
  150. .name = DRIVER_NAME,
  151. .of_match_table = rtl8306_switch_of_match,
  152. },
  153. };
  154. module_platform_driver(rtl8306_switch_driver);
  155. MODULE_AUTHOR("linshuoquan@126.com");
  156. MODULE_DESCRIPTION("RTL8306 Switch driver");
  157. MODULE_LICENSE("GPL");
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/311869
推荐阅读
相关标签
  

闽ICP备14008679号