Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * i.mx233 external temperature sensing with a diode
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/sysfs.h>
- #include <linux/hwmon.h>
- #include <linux/mutex.h>
- #include <linux/io.h>
- #include <linux/platform_device.h>
- #include <asm/processor.h> /* cpu_relax */
- #include <mach/hardware.h>
- #include <mach/lradc.h>
- #include <mach/regs-power.h>
- #include <mach/regs-lradc.h>
- #define REGS_LRADC_BASE IO_ADDRESS(LRADC_PHYS_ADDR)
- #define THERM_CHANNEL 0
- #define LRADC_IRQ_MASK (1 << THERM_CHANNEL)
- #define KELVIN_TO_CELSIUS_CONST (273*1000)
- struct mxs_therm {
- struct device *hwmon_dev;
- struct mutex lock;
- };
- static uint32_t get_codevalue(void)
- {
- int i;
- uint32_t codevalue;
- codevalue = 0;
- for (i = 0; i < 8; i++) {
- __raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << THERM_CHANNEL),
- REGS_LRADC_BASE + HW_LRADC_CTRL0_SET);
- /* Wait for conversion complete*/
- while (!(__raw_readl(REGS_LRADC_BASE + HW_LRADC_CTRL1)
- & LRADC_IRQ_MASK))
- cpu_relax();
- /* Clear the interrupt flag */
- __raw_writel(LRADC_IRQ_MASK,
- REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR);
- /* read temperature value and clr lradc */
- codevalue += __raw_readl(REGS_LRADC_BASE +
- HW_LRADC_CHn(THERM_CHANNEL)) & BM_LRADC_CHn_VALUE;
- __raw_writel(BM_LRADC_CHn_VALUE,
- REGS_LRADC_BASE + HW_LRADC_CHn_CLR(THERM_CHANNEL));
- }
- return (codevalue >> 3);
- }
- /*
- * Use the the lradc0 channel
- *
- */
- static int measure_temperature(void)
- {
- int code1, code2, ret_temp, i;
- /* Enable temperature sensor current source */
- __raw_writel(BM_LRADC_CTRL2_TEMP_SENSOR_IENABLE0,
- REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
- /* mux to the lradc 0th temp channe0 */
- __raw_writel((0xF << (4 * THERM_CHANNEL)),
- REGS_LRADC_BASE + HW_LRADC_CTRL4_CLR);
- /* Clear the interrupt flag */
- __raw_writel(LRADC_IRQ_MASK,
- REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR);
- ret_temp = 0;
- for (i = 0; i < 8; i++) {
- __raw_writel(BM_LRADC_CTRL2_TEMP_ISRC0,
- REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
- __raw_writel(BF_LRADC_CTRL2_TEMP_ISRC0(BV_LRADC_CTRL2_TEMP_ISRC0__300),
- REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
- code1 = get_codevalue();
- __raw_writel(BM_LRADC_CTRL2_TEMP_ISRC0,
- REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
- __raw_writel(BF_LRADC_CTRL2_TEMP_ISRC0(BV_LRADC_CTRL2_TEMP_ISRC0__20),
- REGS_LRADC_BASE + HW_LRADC_CTRL2_SET);
- code2 = get_codevalue();
- /* degrees Kelvin = (Codemax – Codemin) * 1.104 */
- ret_temp += (code1 - code2) * 1104;
- }
- /* Disable temperature sensor current source */
- __raw_writel(BM_LRADC_CTRL2_TEMP_SENSOR_IENABLE0,
- REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR);
- return ((ret_temp >> 3) - KELVIN_TO_CELSIUS_CONST);
- }
- static ssize_t mxs_therm_sense_temp(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct mxs_therm *mxs_therm_data = dev_get_drvdata(dev);
- int status;
- int val;
- if (mutex_lock_interruptible(&mxs_therm_data->lock))
- return -ERESTARTSYS;
- val = measure_temperature();
- status = sprintf(buf, "%d\n", val);
- mutex_unlock(&mxs_therm_data->lock);
- return status;
- }
- static DEVICE_ATTR(temp1_input, S_IRUGO, mxs_therm_sense_temp, NULL);
- static ssize_t mxs_therm_show_name(struct device *dev, struct device_attribute
- *devattr, char *buf)
- {
- return sprintf(buf, "%s\n", "mxs_therm");
- }
- static DEVICE_ATTR(name, S_IRUGO, mxs_therm_show_name, NULL);
- static int __init mxs_therm_probe(struct platform_device *pdev)
- {
- struct mxs_therm *mxs_therm_data;
- int status;
- mxs_therm_data = kzalloc(sizeof *mxs_therm_data, GFP_KERNEL);
- if (!mxs_therm_data)
- return -ENOMEM;
- mutex_init(&mxs_therm_data->lock);
- /* sysfs hook */
- mxs_therm_data->hwmon_dev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(mxs_therm_data->hwmon_dev)) {
- dev_dbg(&pdev->dev, "hwmon_device_register failed.\n");
- status = PTR_ERR(mxs_therm_data->hwmon_dev);
- goto out_dev_reg_failed;
- }
- platform_set_drvdata(pdev, mxs_therm_data);
- if ((status = device_create_file(&pdev->dev, &dev_attr_temp1_input))
- || (status = device_create_file(&pdev->dev, &dev_attr_name))) {
- dev_dbg(&pdev->dev, "device_create_file failure.\n");
- goto out_dev_create_file_failed;
- }
- return 0;
- out_dev_create_file_failed:
- device_remove_file(&pdev->dev, &dev_attr_temp1_input);
- hwmon_device_unregister(mxs_therm_data->hwmon_dev);
- out_dev_reg_failed:
- platform_set_drvdata(pdev, NULL);
- kfree(mxs_therm_data);
- return status;
- }
- static int mxs_therm_remove(struct platform_device *pdev)
- {
- struct mxs_therm *mxs_therm_data = platform_get_drvdata(pdev);
- hwmon_device_unregister(mxs_therm_data->hwmon_dev);
- device_remove_file(&pdev->dev, &dev_attr_temp1_input);
- device_remove_file(&pdev->dev, &dev_attr_name);
- platform_set_drvdata(pdev, NULL);
- kfree(mxs_therm_data);
- return 0;
- }
- static struct platform_driver mxs_therm_driver = {
- .driver = {
- .name = "mxs_therm",
- },
- .probe = mxs_therm_probe,
- .remove = mxs_therm_remove,
- };
- static struct platform_device *mxs_therm_device;
- static int __init mxs_therm_init(void)
- {
- int ret = 0;
- ret = platform_driver_register(&mxs_therm_driver);
- if (!ret) {
- mxs_therm_device = platform_device_alloc("mxs_therm", 0);
- if (mxs_therm_device)
- ret = platform_device_add(mxs_therm_device);
- else
- ret = -ENOMEM;
- if (ret) {
- platform_device_put(mxs_therm_device);
- platform_driver_unregister(&mxs_therm_driver);
- }
- }
- return ret;
- }
- static void __exit mxs_therm_exit(void)
- {
- platform_device_unregister(mxs_therm_device);
- platform_driver_unregister(&mxs_therm_driver);
- }
- module_init(mxs_therm_init);
- module_exit(mxs_therm_exit);
- MODULE_AUTHOR("starterkit");
- MODULE_DESCRIPTION("External temperature sensing with a diode");
- MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment