misc: Initial NCT1008 driver
[linux-2.6.git] / drivers / misc / nct1008.c
1 /*
2  * Copyright (C) 2010 Motorola, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
16  * 02111-1307, USA
17  */
18
19 #include <linux/i2c.h>
20 #include <linux/irq.h>
21 #include <linux/input.h>
22 #include <linux/interrupt.h>
23 #include <linux/nct1008.h>
24 #include <linux/platform_device.h>
25 #include <linux/slab.h>
26 #include <linux/types.h>
27 #include <linux/uaccess.h>
28
29 #define NCT_BIT_CONFIG_RUN_STOP 6
30
31 struct nct1008_data {
32         struct i2c_client *client;
33 };
34
35 static uint32_t nct1008_debug;
36 module_param_named(temp_debug, nct1008_debug, uint, 0664);
37
38 static int nct1008_run(struct nct1008_data *nct, u8 run)
39 {
40         int err;
41         u8 rd_val;
42         u8 wr_val;
43
44         rd_val = i2c_smbus_read_byte_data(nct->client, NCT_CONFIG_RD);
45         if (rd_val < 0) {
46                 pr_err("%s: config register read fail: %d\n", __func__, rd_val);
47                 return rd_val;
48         }
49
50         if (nct1008_debug)
51                 pr_info("%s: Previous config is 0x%02x\n", __func__, rd_val);
52
53         if (run)
54                 wr_val = rd_val & ~(1 << NCT_BIT_CONFIG_RUN_STOP);
55         else
56                 wr_val = rd_val | (1 << NCT_BIT_CONFIG_RUN_STOP);
57         err = i2c_smbus_write_byte_data(nct->client, NCT_CONFIG_WR, wr_val);
58         if (err)
59                 pr_err("%s: setting RUN/STOP failed: %d\n", __func__, err);
60
61         return err;
62 }
63
64 static int nct1008_probe(struct i2c_client *client,
65                          const struct i2c_device_id *id)
66 {
67         struct nct1008_data *nct;
68
69         nct = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
70         if (nct == NULL)
71                 return -ENOMEM;
72
73         nct->client = client;
74         i2c_set_clientdata(client, nct);
75
76         return 0;
77 }
78
79 static int nct1008_remove(struct i2c_client *client)
80 {
81         struct nct1008_data *nct = i2c_get_clientdata(client);
82
83         kfree(nct);
84         return 0;
85 }
86
87 static int nct1008_suspend(struct i2c_client *client, pm_message_t mesg)
88 {
89         struct nct1008_data *nct = i2c_get_clientdata(client);
90
91         if (nct1008_debug)
92                 pr_info("%s: Suspending\n", __func__);
93
94         return nct1008_run(nct, 0);
95 }
96
97 static int nct1008_resume(struct i2c_client *client)
98 {
99         struct nct1008_data *nct = i2c_get_clientdata(client);
100
101         if (nct1008_debug)
102                 pr_info("%s: Resuming\n", __func__);
103
104         return nct1008_run(nct, 1);
105 }
106
107 static const struct i2c_device_id nct1008_id[] = {
108         {"nct1008", 0},
109         {}
110 };
111
112 static struct i2c_driver nct1008_i2c_driver = {
113         .probe = nct1008_probe,
114         .remove = nct1008_remove,
115         .suspend = nct1008_suspend,
116         .resume = nct1008_resume,
117         .id_table = nct1008_id,
118         .driver = {
119                 .name = "nct1008",
120                 .owner = THIS_MODULE,
121         },
122 };
123
124 static int __init nct1008_init(void)
125 {
126         return i2c_add_driver(&nct1008_i2c_driver);
127 }
128
129 static void __exit nct1008_exit(void)
130 {
131         i2c_del_driver(&nct1008_i2c_driver);
132 }
133
134 module_init(nct1008_init);
135 module_exit(nct1008_exit);
136
137 MODULE_DESCRIPTION("Temperature sensor driver for OnSemi NCT1008");
138 MODULE_AUTHOR("Motorola");
139 MODULE_LICENSE("GPL");