devinfo.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/types.h>
  4. #include <linux/kernel.h>
  5. #include <linux/proc_fs.h>
  6. #include <linux/cdev.h>
  7. #include <linux/mm.h>
  8. #include <asm/io.h>
  9. #include <asm/uaccess.h>
  10. #include <linux/ioctl.h>
  11. #include <linux/device.h>
  12. #ifdef CONFIG_OF
  13. #include <linux/of_fdt.h>
  14. #endif
  15. #include <asm/setup.h>
  16. #include "devinfo.h"
  17. u32 g_devinfo_data[DEVINFO_MAX_SIZE];
  18. static struct cdev devinfo_cdev;
  19. static struct class *devinfo_class;
  20. static dev_t devinfo_dev;
  21. /*****************************************************************************
  22. *FUNCTION DEFINITION
  23. *****************************************************************************/
  24. static int devinfo_open(struct inode *inode, struct file *filp);
  25. static int devinfo_release(struct inode *inode, struct file *filp);
  26. static long devinfo_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
  27. /**************************************************************************
  28. *EXTERN FUNCTION
  29. **************************************************************************/
  30. u32 devinfo_get_size(void)
  31. {
  32. u32 data_size = 0;
  33. data_size = ARRAY_SIZE(g_devinfo_data);
  34. return data_size;
  35. }
  36. u32 get_devinfo_with_index(u32 index)
  37. {
  38. int size = devinfo_get_size();
  39. u32 ret = 0;
  40. if ((index >= 0) && (index < size))
  41. ret = g_devinfo_data[index];
  42. else {
  43. pr_warn("devinfo data index out of range:%d\n", index);
  44. pr_warn("devinfo data size:%d\n", size);
  45. ret = 0xFFFFFFFF;
  46. }
  47. return ret;
  48. }
  49. /**************************************************************************
  50. *STATIC FUNCTION
  51. **************************************************************************/
  52. static const struct file_operations devinfo_fops = {
  53. .open = devinfo_open,
  54. .release = devinfo_release,
  55. .unlocked_ioctl = devinfo_ioctl,
  56. #ifdef CONFIG_COMPAT
  57. .compat_ioctl = devinfo_ioctl,
  58. #endif
  59. .owner = THIS_MODULE,
  60. };
  61. static int devinfo_open(struct inode *inode, struct file *filp)
  62. {
  63. return 0;
  64. }
  65. static int devinfo_release(struct inode *inode, struct file *filp)
  66. {
  67. return 0;
  68. }
  69. /**************************************************************************
  70. * DEV DRIVER IOCTL
  71. **************************************************************************/
  72. static long devinfo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  73. {
  74. u32 index = 0;
  75. int err = 0;
  76. int ret = 0;
  77. u32 data_size = ARRAY_SIZE(g_devinfo_data);
  78. u32 data_read = 0;
  79. /* ---------------------------------- */
  80. /* IOCTL */
  81. /* ---------------------------------- */
  82. if (_IOC_TYPE(cmd) != DEV_IOC_MAGIC)
  83. return -ENOTTY;
  84. if (_IOC_NR(cmd) > DEV_IOC_MAXNR)
  85. return -ENOTTY;
  86. if (_IOC_DIR(cmd) & _IOC_READ)
  87. err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  88. if (_IOC_DIR(cmd) & _IOC_WRITE)
  89. err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  90. if (err)
  91. return -EFAULT;
  92. switch (cmd) {
  93. /* ---------------------------------- */
  94. /* get dev info data */
  95. /* ---------------------------------- */
  96. case READ_DEV_DATA:
  97. if (copy_from_user((void *)&index, (void __user *)arg, sizeof(u32)))
  98. return -1;
  99. if (index < data_size) {
  100. data_read = get_devinfo_with_index(index);
  101. ret = copy_to_user((void __user *)arg, (void *)&(data_read), sizeof(u32));
  102. } else {
  103. pr_warn("%s Error! Data index larger than data size. index:%d, size:%d\n", MODULE_NAME,
  104. index, data_size);
  105. return -2;
  106. }
  107. break;
  108. }
  109. return 0;
  110. }
  111. /******************************************************************************
  112. * devinfo_init
  113. *
  114. * DESCRIPTION:
  115. * Init the device driver !
  116. *
  117. * PARAMETERS:
  118. * None
  119. *
  120. * RETURNS:
  121. * 0 for success
  122. *
  123. * NOTES:
  124. * None
  125. *
  126. ******************************************************************************/
  127. static int __init devinfo_init(void)
  128. {
  129. int ret = 0;
  130. struct device *device;
  131. devinfo_dev = MKDEV(MAJOR_DEV_NUM, 0);
  132. pr_debug("[%s]init\n", MODULE_NAME);
  133. ret = register_chrdev_region(devinfo_dev, 1, DEV_NAME);
  134. if (ret) {
  135. pr_warn("[%s] register device failed, ret:%d\n", MODULE_NAME, ret);
  136. return ret;
  137. }
  138. /*create class*/
  139. devinfo_class = class_create(THIS_MODULE, DEV_NAME);
  140. if (IS_ERR(devinfo_class)) {
  141. ret = PTR_ERR(devinfo_class);
  142. pr_warn("[%s] register class failed, ret:%d\n", MODULE_NAME, ret);
  143. unregister_chrdev_region(devinfo_dev, 1);
  144. return ret;
  145. }
  146. /* initialize the device structure and register the device */
  147. cdev_init(&devinfo_cdev, &devinfo_fops);
  148. devinfo_cdev.owner = THIS_MODULE;
  149. ret = cdev_add(&devinfo_cdev, devinfo_dev, 1);
  150. if (ret < 0) {
  151. pr_warn("[%s] could not allocate chrdev for the device, ret:%d\n", MODULE_NAME, ret);
  152. class_destroy(devinfo_class);
  153. unregister_chrdev_region(devinfo_dev, 1);
  154. return ret;
  155. }
  156. /*create device*/
  157. device = device_create(devinfo_class, NULL, devinfo_dev, NULL, "devmap");
  158. if (IS_ERR(device)) {
  159. ret = PTR_ERR(device);
  160. pr_warn("[%s]device create fail\n", MODULE_NAME);
  161. cdev_del(&devinfo_cdev);
  162. class_destroy(devinfo_class);
  163. unregister_chrdev_region(devinfo_dev, 1);
  164. return ret;
  165. }
  166. return 0;
  167. }
  168. #ifdef CONFIG_OF
  169. static int __init devinfo_parse_dt(unsigned long node, const char *uname, int depth, void *data)
  170. {
  171. struct devinfo_tag *tags;
  172. int i;
  173. u32 size = 0;
  174. if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
  175. return 0;
  176. tags = (struct devinfo_tag *) of_get_flat_dt_prop(node, "atag,devinfo", NULL);
  177. if (tags) {
  178. size = tags->data_size;
  179. if (size == DEVINFO_MAX_SIZE)
  180. for (i = 0; i < size; i++)
  181. g_devinfo_data[i] = tags->data[i];
  182. else {
  183. for (i = 0; i < 50; i++)
  184. pr_err("[ERROR][devinfo size mismatch] devinfo size:%d, atag size:%d\n",
  185. DEVINFO_MAX_SIZE, size);
  186. for (i = 0; i < DEVINFO_MAX_SIZE; i++)
  187. g_devinfo_data[i] = (u32)0;
  188. }
  189. /* print chip id for debugging purpose */
  190. pr_debug("tag_devinfo_data size:%d\n", size);
  191. }
  192. return 1;
  193. }
  194. static int __init devinfo_of_init(void)
  195. {
  196. of_scan_flat_dt(devinfo_parse_dt, NULL);
  197. return 0;
  198. }
  199. #endif
  200. /******************************************************************************
  201. * devinfo_exit
  202. *
  203. * DESCRIPTION:
  204. * Free the device driver !
  205. *
  206. * PARAMETERS:
  207. * None
  208. *
  209. * RETURNS:
  210. * None
  211. *
  212. * NOTES:
  213. * None
  214. *
  215. ******************************************************************************/
  216. static void __exit devinfo_exit(void)
  217. {
  218. cdev_del(&devinfo_cdev);
  219. class_destroy(devinfo_class);
  220. unregister_chrdev_region(devinfo_dev, 1);
  221. }
  222. #ifdef CONFIG_OF
  223. early_initcall(devinfo_of_init);
  224. #endif
  225. module_init(devinfo_init);
  226. module_exit(devinfo_exit);
  227. MODULE_LICENSE("GPL");