Guest User

Untitled

a guest
Jul 25th, 2013
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.63 KB | None | 0 0
  1. /*
  2.  * i.mx233 external temperature sensing with a diode
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify it
  5.  * under the terms of the GNU General Public License version 2 as published by
  6.  * the Free Software Foundation.
  7.  */
  8.  
  9.  
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/device.h>
  14. #include <linux/err.h>
  15. #include <linux/sysfs.h>
  16. #include <linux/hwmon.h>
  17. #include <linux/mutex.h>
  18. #include <linux/io.h>
  19. #include <linux/platform_device.h>
  20. #include <asm/processor.h> /* cpu_relax */
  21. #include <mach/hardware.h>
  22. #include <mach/lradc.h>
  23. #include <mach/regs-power.h>
  24. #include <mach/regs-lradc.h>
  25.  
  26. #define REGS_LRADC_BASE IO_ADDRESS(LRADC_PHYS_ADDR)
  27. #define THERM_CHANNEL    0
  28. #define LRADC_IRQ_MASK  (1 << THERM_CHANNEL)
  29. #define KELVIN_TO_CELSIUS_CONST (273*1000)
  30.  
  31. struct mxs_therm {
  32.     struct device *hwmon_dev;
  33.     struct mutex lock;
  34. };
  35.  
  36. static uint32_t get_codevalue(void)
  37. {
  38.     int i;
  39.     uint32_t codevalue;
  40.  
  41.     codevalue = 0;
  42.  
  43.     for (i = 0; i < 8; i++) {
  44.         __raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << THERM_CHANNEL),
  45.                     REGS_LRADC_BASE + HW_LRADC_CTRL0_SET);
  46.  
  47.         /* Wait for conversion complete*/
  48.         while (!(__raw_readl(REGS_LRADC_BASE + HW_LRADC_CTRL1)
  49.                 & LRADC_IRQ_MASK))
  50.             cpu_relax();
  51.  
  52.         /* Clear the interrupt flag */
  53.         __raw_writel(LRADC_IRQ_MASK,
  54.                     REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR);
  55.  
  56.         /* read temperature value and clr lradc */
  57.         codevalue += __raw_readl(REGS_LRADC_BASE +
  58.                     HW_LRADC_CHn(THERM_CHANNEL)) & BM_LRADC_CHn_VALUE;
  59.  
  60.         __raw_writel(BM_LRADC_CHn_VALUE,
  61.                     REGS_LRADC_BASE + HW_LRADC_CHn_CLR(THERM_CHANNEL));
  62.     }
  63.  
  64.     return (codevalue >> 3);
  65. }
  66.  
  67. /*
  68.  * Use the the lradc0 channel
  69.  *
  70.  */
  71. static int measure_temperature(void)
  72. {
  73.     int code1, code2, ret_temp, i;
  74.  
  75.     /* Enable temperature sensor current source */
  76.     __raw_writel(BM_LRADC_CTRL2_TEMP_SENSOR_IENABLE0,
  77.             REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
  78.  
  79.     /* mux to the lradc 0th temp channe0 */
  80.     __raw_writel((0xF << (4 * THERM_CHANNEL)),
  81.             REGS_LRADC_BASE + HW_LRADC_CTRL4_CLR);
  82.  
  83.     /* Clear the interrupt flag */
  84.     __raw_writel(LRADC_IRQ_MASK,
  85.             REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR);
  86.  
  87.     ret_temp = 0;
  88.  
  89.     for (i = 0; i < 8; i++) {
  90.         __raw_writel(BM_LRADC_CTRL2_TEMP_ISRC0,
  91.                     REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
  92.  
  93.         __raw_writel(BF_LRADC_CTRL2_TEMP_ISRC0(BV_LRADC_CTRL2_TEMP_ISRC0__300),
  94.                     REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
  95.  
  96.         code1 = get_codevalue();
  97.  
  98.         __raw_writel(BM_LRADC_CTRL2_TEMP_ISRC0,
  99.                     REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
  100.  
  101.         __raw_writel(BF_LRADC_CTRL2_TEMP_ISRC0(BV_LRADC_CTRL2_TEMP_ISRC0__20),
  102.                     REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
  103.  
  104.         code2 = get_codevalue();
  105.  
  106.         /* degrees Kelvin = (Codemax – Codemin) * 1.104 */
  107.         ret_temp += (code1 - code2) * 1104;
  108.     }
  109.  
  110.     /* Disable temperature sensor current source */
  111.     __raw_writel(BM_LRADC_CTRL2_TEMP_SENSOR_IENABLE0,
  112.                 REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
  113.  
  114.     return  ((ret_temp >> 3) - KELVIN_TO_CELSIUS_CONST);
  115. }
  116.  
  117. static ssize_t mxs_therm_sense_temp(struct device *dev,
  118.         struct device_attribute *attr, char *buf)
  119. {
  120.     struct mxs_therm *mxs_therm_data = dev_get_drvdata(dev);
  121.     int status;
  122.     int val;
  123.  
  124.     if (mutex_lock_interruptible(&mxs_therm_data->lock))
  125.         return -ERESTARTSYS;
  126.  
  127.     val = measure_temperature();
  128.     status = sprintf(buf, "%d\n", val);
  129.  
  130.     mutex_unlock(&mxs_therm_data->lock);
  131.     return status;
  132. }
  133.  
  134. static DEVICE_ATTR(temp1_input, S_IRUGO, mxs_therm_sense_temp, NULL);
  135.  
  136. static ssize_t mxs_therm_show_name(struct device *dev, struct device_attribute
  137.                   *devattr, char *buf)
  138. {
  139.  
  140.     return sprintf(buf, "%s\n", "mxs_therm");
  141. }
  142.  
  143. static DEVICE_ATTR(name, S_IRUGO, mxs_therm_show_name, NULL);
  144.  
  145. static int __init mxs_therm_probe(struct platform_device *pdev)
  146. {
  147.     struct mxs_therm *mxs_therm_data;
  148.     int status;
  149.  
  150.     mxs_therm_data = kzalloc(sizeof *mxs_therm_data, GFP_KERNEL);
  151.     if (!mxs_therm_data)
  152.         return -ENOMEM;
  153.  
  154.     mutex_init(&mxs_therm_data->lock);
  155.  
  156.     /* sysfs hook */
  157.     mxs_therm_data->hwmon_dev = hwmon_device_register(&pdev->dev);
  158.     if (IS_ERR(mxs_therm_data->hwmon_dev)) {
  159.         dev_dbg(&pdev->dev, "hwmon_device_register failed.\n");
  160.         status = PTR_ERR(mxs_therm_data->hwmon_dev);
  161.         goto out_dev_reg_failed;
  162.     }
  163.     platform_set_drvdata(pdev, mxs_therm_data);
  164.  
  165.     if ((status = device_create_file(&pdev->dev, &dev_attr_temp1_input))
  166.      || (status = device_create_file(&pdev->dev, &dev_attr_name))) {
  167.         dev_dbg(&pdev->dev, "device_create_file failure.\n");
  168.         goto out_dev_create_file_failed;
  169.     }
  170.  
  171.     return 0;
  172.  
  173. out_dev_create_file_failed:
  174.     device_remove_file(&pdev->dev, &dev_attr_temp1_input);
  175.     hwmon_device_unregister(mxs_therm_data->hwmon_dev);
  176. out_dev_reg_failed:
  177.     platform_set_drvdata(pdev, NULL);
  178.     kfree(mxs_therm_data);
  179.  
  180.     return status;
  181. }
  182.  
  183. static int mxs_therm_remove(struct platform_device *pdev)
  184. {
  185.     struct mxs_therm *mxs_therm_data = platform_get_drvdata(pdev);
  186.  
  187.     hwmon_device_unregister(mxs_therm_data->hwmon_dev);
  188.     device_remove_file(&pdev->dev, &dev_attr_temp1_input);
  189.     device_remove_file(&pdev->dev, &dev_attr_name);
  190.     platform_set_drvdata(pdev, NULL);
  191.     kfree(mxs_therm_data);
  192.  
  193.     return 0;
  194. }
  195.  
  196. static struct platform_driver mxs_therm_driver = {
  197.     .driver     = {
  198.         .name   = "mxs_therm",
  199.     },
  200.     .probe      = mxs_therm_probe,
  201.     .remove     = mxs_therm_remove,
  202. };
  203.  
  204. static struct platform_device *mxs_therm_device;
  205.  
  206. static int __init mxs_therm_init(void)
  207. {
  208.     int ret = 0;
  209.  
  210.     ret = platform_driver_register(&mxs_therm_driver);
  211.  
  212.     if (!ret) {
  213.         mxs_therm_device = platform_device_alloc("mxs_therm", 0);
  214.  
  215.         if (mxs_therm_device)
  216.             ret = platform_device_add(mxs_therm_device);
  217.         else
  218.             ret = -ENOMEM;
  219.  
  220.         if (ret) {
  221.             platform_device_put(mxs_therm_device);
  222.             platform_driver_unregister(&mxs_therm_driver);
  223.         }
  224.     }
  225.  
  226.     return ret;
  227. }
  228.  
  229. static void __exit mxs_therm_exit(void)
  230. {
  231.     platform_device_unregister(mxs_therm_device);
  232.     platform_driver_unregister(&mxs_therm_driver);
  233. }
  234.  
  235. module_init(mxs_therm_init);
  236. module_exit(mxs_therm_exit);
  237.  
  238.  
  239. MODULE_AUTHOR("starterkit");
  240. MODULE_DESCRIPTION("External temperature sensing with a diode");
  241. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment