blob: 612214dc87570ea4f5dcacc3050e5e699607cc6e [file] [log] [blame]
adamliyi948eb5e2015-11-25 00:31:34 +08001diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
2index e13c902..38aff0c 100644
3--- a/drivers/hwmon/Kconfig
4+++ b/drivers/hwmon/Kconfig
5@@ -1167,6 +1167,13 @@ config SENSORS_NCT7904
6 This driver can also be built as a module. If so, the module
7 will be called nct7904.
8
9+config SENSORS_OCC
10+ tristate "OCC sensor driver for IBM Power CPU"
11+ depends on I2C
12+ help
13+ If you say yes here you get support for driver to read sensors in
14+ IBM Power CPU On-Chip-Controller. module will be called occ.
15+
16 config SENSORS_PCF8591
17 tristate "Philips PCF8591 ADC/DAC"
18 depends on I2C
19diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
20index 9e0f3dd..53dc3b3 100644
21--- a/drivers/hwmon/Makefile
22+++ b/drivers/hwmon/Makefile
23@@ -123,6 +123,7 @@ obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
24 obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o
25 obj-$(CONFIG_SENSORS_NCT7904) += nct7904.o
26 obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
27+obj-$(CONFIG_SENSORS_OCC) += occ.o
28 obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
29 obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
30 obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
31diff --git a/drivers/hwmon/occ.c b/drivers/hwmon/occ.c
32new file mode 100644
33index 0000000..f265ff3
34--- /dev/null
35+++ b/drivers/hwmon/occ.c
36@@ -0,0 +1,1529 @@
37+/*
38+ * Open BMC OCC HWMON driver - read Power8 OCC (On Chip Controller) sensor data via i2c.
39+ *
40+ * Copyright (c) 2015 IBM (Alvin Wang, Li Yi)
41+ *
42+ * This program is free software; you can redistribute it and/or modify
43+ * it under the terms of the GNU General Public License as published by
44+ * the Free Software Foundation; either version 2 of the License, or
45+ * (at your option) any later version.
46+ *
47+ * This program is distributed in the hope that it will be useful,
48+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50+ * GNU General Public License for more details.
51+ *
52+ * You should have received a copy of the GNU General Public License
53+ * along with this program; if not, write to the Free Software
54+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
55+ */
56+
57+#include <linux/module.h>
58+#include <linux/init.h>
59+#include <linux/slab.h>
60+#include <linux/jiffies.h>
61+#include <linux/i2c.h>
62+#include <linux/hwmon.h>
63+#include <linux/hwmon-sysfs.h>
64+#include <linux/err.h>
65+#include <linux/mutex.h>
66+#include <linux/of.h>
67+#include <linux/delay.h>
68+
69+//#define DEBUG 1
70+
71+/* ------------------------------------------------------------*/
72+/* OCC sensor data format */
73+typedef struct {
74+ uint16_t sensor_id;
75+ uint16_t value;
76+} occ_sensor;
77+
78+typedef struct {
79+ uint16_t sensor_id;
80+ uint32_t update_tag;
81+ uint32_t accumulator;
82+ uint16_t value;
83+} powr_sensor;
84+
85+typedef struct {
86+ uint16_t curr_powercap;
87+ uint16_t curr_powerreading;
88+ uint16_t norm_powercap;
89+ uint16_t max_powercap;
90+ uint16_t min_powercap;
91+ uint16_t user_powerlimit;
92+} caps_sensor;
93+
94+typedef struct {
95+ char sensor_type[5];
96+ uint8_t reserved0;
97+ uint8_t sensor_format;
98+ uint8_t sensor_length;
99+ uint8_t num_of_sensors;
100+ occ_sensor *sensor;
101+ powr_sensor *powr;
102+ caps_sensor *caps;
103+} sensor_data_block;
104+
105+typedef struct {
106+ uint8_t status;
107+ uint8_t ext_status;
108+ uint8_t occs_present;
109+ uint8_t config;
110+ uint8_t occ_state;
111+ uint8_t reserved0;
112+ uint8_t reserved1;
113+ uint8_t error_log_id;
114+ uint32_t error_log_addr_start;
115+ uint16_t error_log_length;
116+ uint8_t reserved2;
117+ uint8_t reserved3;
118+ char occ_code_level[17];
119+ char sensor_eye_catcher[7];
120+ uint8_t num_of_sensor_blocks;
121+ uint8_t sensor_data_version;
122+ sensor_data_block* blocks;
123+} occ_poll_data;
124+
125+typedef struct {
126+ uint8_t sequence_num;
127+ uint8_t cmd_type;
128+ uint8_t rtn_status;
129+ uint16_t data_length;
130+ occ_poll_data data;
131+ uint16_t chk_sum;
132+ int temp_block_id;
133+ int freq_block_id;
134+ int power_block_id;
135+ int caps_block_id;
136+} occ_response_t;
137+
138+//static occ_response_t occ_resp;
139+
140+/* Each client has this additional data */
141+struct occ_drv_data {
142+ struct i2c_client *client;
143+ struct device *hwmon_dev;
144+ struct mutex update_lock;
145+ char valid; /* !=0 if sensor data are valid */
146+ unsigned long last_updated; /* In jiffies */
147+ unsigned long sample_time; /* Mininum timer interval for sampling In jiffies */
148+ occ_response_t occ_resp;
149+};
150+
151+/*-----------------------------------------------------------------------*/
152+/* i2c read and write occ sensors */
153+
154+#define OCC_DATA_MAX 4096 /* 4KB at most */
155+#define I2C_STATUS_REG 0x000d0001
156+#define I2C_ERROR_REG 0x000d0002
157+#define I2C_READ_ERROR 1
158+#define I2C_WRITE_ERROR 2
159+#define I2C_DATABUFFER_SIZE_ERROR 3
160+
161+/*
162+#define SCOM_OCC_SRAM_WOX 0x0006B013
163+#define SCOM_OCC_SRAM_WAND 0x0006B012
164+#define SCOM_OCC_SRAM_ADDR 0x0006B010
165+#define SCOM_OCC_SRAM_DATA 0x0006B015
166+*/
167+
168+// To generate attn to OCC
169+#define ATTN_DATA 0x0006B035
170+
171+// For BMC to read/write SRAM
172+#define OCB_ADDRESS 0x0006B070
173+#define OCB_DATA 0x0006B075
174+#define OCB_STATUS_CONTROL_AND 0x0006B072
175+#define OCB_STATUS_CONTROL_OR 0x0006B073
176+
177+#define OCC_COMMAND_ADDR 0xFFFF6000
178+#define OCC_RESPONSE_ADDR 0xFFFF7000
179+
180+static int deinit_occ_resp_buf(occ_response_t *p)
181+{
182+ int b;
183+
184+ if (p == NULL)
185+ return 0;
186+
187+ if (p->data.blocks == NULL)
188+ return 0;
189+
190+ for(b = 0; b < p->data.num_of_sensor_blocks; b++) {
191+ if (!p->data.blocks[b].sensor)
192+ kfree(p->data.blocks[b].sensor);
193+ if (!p->data.blocks[b].powr)
194+ kfree(p->data.blocks[b].powr);
195+ if (!p->data.blocks[b].caps)
196+ kfree(p->data.blocks[b].caps);
197+ }
198+
199+ kfree(p->data.blocks);
200+
201+ memset(p, 0, sizeof(*p));
202+
203+
204+ return 0;
205+}
206+
207+static ssize_t occ_i2c_read(struct i2c_client *client, char *buf, size_t count)
208+{
209+ int ret = 0;
210+
211+ if (count > 8192)
212+ count = 8192;
213+
214+ //printk("i2c_read: reading %zu bytes @0x%x.\n", count, client->addr);
215+ ret = i2c_master_recv(client, buf, count);
216+ return ret;
217+}
218+
219+static ssize_t occ_i2c_write(struct i2c_client *client, const char *buf, size_t count)
220+{
221+ int ret = 0;
222+
223+ if (count > 8192)
224+ count = 8192;
225+
226+ //printk("i2c_write: writing %zu bytes @0x%x.\n", count, client->addr);
227+ ret = i2c_master_send(client, buf, count);
228+ return ret;
229+}
230+
231+/* read two 4-byte value */
232+static int occ_getscom(struct i2c_client *client, uint32_t address, uint32_t *value0, uint32_t *value1)
233+{
234+ uint32_t ret = 0;
235+ char buf[8];
236+ const char* address_buf = (const char*)&address;
237+
238+ //P8 i2c slave requires address to be shifted by 1
239+ address = address << 1;
240+
241+ ret = occ_i2c_write(client, address_buf, sizeof(address));
242+ /* FIXME: ast i2c driver does not read corret value */
243+ //if (ret != sizeof(address))
244+ // return -I2C_WRITE_ERROR;
245+
246+ ret = occ_i2c_read(client, buf, sizeof(buf));
247+ //if (ret != sizeof(buf))
248+ // return -I2C_READ_ERROR;
249+
250+ memcpy(value1, &buf[0], sizeof(*value1));
251+ memcpy(value0, &buf[4], sizeof(*value0));
252+
253+ return 0;
254+}
255+
256+/* read 8-byte value and put into data[offset] */
257+static int occ_getscomb(struct i2c_client *client, uint32_t address, char* data, int offset)
258+{
259+ uint32_t ret = 0;
260+ const char* address_buf = (const char*)&address;
261+ char buf[8];
262+ int b = 0;
263+
264+ //P8 i2c slave requires address to be shifted by 1
265+ address = address << 1;
266+
267+ ret = occ_i2c_write(client, address_buf, sizeof(address));
268+ //if (ret != sizeof(address))
269+ // return -I2C_WRITE_ERROR;
270+
271+ ret = occ_i2c_read(client, buf, sizeof(buf));
272+ //if (ret != sizeof(buf))
273+ // return -I2C_READ_ERROR;
274+
275+ for (b = 0; b < 8; b++) {
276+ data[offset + b] = buf[7 - b];
277+ }
278+
279+ return 0;
280+}
281+
282+static int occ_putscom(struct i2c_client *client, uint32_t address, uint32_t data0, uint32_t data1)
283+{
284+ const char* address_buf = (const char*)&address;
285+ const char* d0 = (const char*)&data0;
286+ const char* d1 = (const char*)&data1;
287+ char buf[12];
288+ uint32_t ret = 0;
289+
290+ //P8 i2c slave requires address to be shifted by 1
291+ address = address << 1;
292+
293+ memcpy(&buf[0], address_buf, sizeof(address));
294+ memcpy(&buf[4], d1, sizeof(data1));
295+ memcpy(&buf[8], d0, sizeof(data0));
296+
297+ ret = occ_i2c_write(client, buf, sizeof(buf));
298+ //if (ret != sizeof(buf))
299+ // return I2C_WRITE_ERROR;
300+
301+ return 0;
302+}
303+
304+static int occ_check_i2c_errors(struct i2c_client *client)
305+{
306+ uint32_t v0;
307+ uint32_t v1;
308+
309+ occ_getscom(client, I2C_STATUS_REG, &v0, &v1);
310+ if (v0 != 0x80000000) {
311+ printk("ERROR present in P8 I2C Slave. Clearing...\n");
312+ occ_putscom(client, I2C_ERROR_REG, 0x00000000, 0x00000000);
313+ occ_putscom(client, I2C_STATUS_REG, 0x00000000, 0x00000000);
314+ return -1;
315+ }
316+
317+ return 0;
318+}
319+
320+
321+static inline uint16_t get_occdata_length(char* d)
322+{
323+ uint16_t data_length = 0;
324+
325+ data_length = d[3] << 8;
326+ data_length = data_length | d[4];
327+ return data_length;
328+}
329+
330+
331+static int parse_occ_response(char* d, occ_response_t* o)
332+{
333+ int b = 0;
334+ int s = 0;
335+ int ret = 0;
336+ int dnum = 45;
337+
338+ o->sequence_num = d[0];
339+ o->cmd_type = d[1];
340+ o->rtn_status = d[2];
341+ o->data_length = d[3] << 8;
342+ o->data_length = o->data_length | d[4];
343+ o->data.status = d[5];
344+ o->data.ext_status = d[6];
345+ o->data.occs_present = d[7];
346+ o->data.config = d[8];
347+ o->data.occ_state = d[9];
348+ o->data.reserved0 = d[10];
349+ o->data.reserved1 = d[11];
350+ o->data.error_log_id = d[12];
351+ o->data.error_log_addr_start = d[13] << 24;
352+ o->data.error_log_addr_start = o->data.error_log_addr_start | d[14] << 16;
353+ o->data.error_log_addr_start = o->data.error_log_addr_start | d[15] << 8;
354+ o->data.error_log_addr_start = o->data.error_log_addr_start | d[16];
355+ o->data.error_log_length = d[17] << 8;
356+ o->data.error_log_length = o->data.error_log_length | d[18];
357+ o->data.reserved2 = d[19];
358+ o->data.reserved3 = d[20];
359+ strncpy(&o->data.occ_code_level[0], (const char*)&d[21], 16);
360+ strncpy(&o->data.sensor_eye_catcher[0], (const char*)&d[37], 6);
361+ o->data.sensor_eye_catcher[6]='\0';
362+ o->data.num_of_sensor_blocks=d[43];
363+ o->data.sensor_data_version = d[44];
364+
365+ if (strcmp(o->data.sensor_eye_catcher, "SENSOR") != 0) {
366+ printk("ERROR: SENSOR not found at byte 37 (%s)\n",o->data.sensor_eye_catcher);
367+ return -1;
368+ }
369+
370+ if (o->data.num_of_sensor_blocks == 0) {
371+ printk("ERROR: SENSOR block num is 0\n");
372+ return -1;
373+ }
374+
375+ o->data.blocks = kzalloc(sizeof(sensor_data_block) * o->data.num_of_sensor_blocks, GFP_KERNEL);
376+ if (o->data.blocks == NULL)
377+ return -ENOMEM;
378+
379+ //printk("Reading %d sensor blocks\n", o->data.num_of_sensor_blocks);
380+ o->temp_block_id = -1;
381+ o->freq_block_id = -1;
382+ o->power_block_id = -1;
383+ o->caps_block_id = -1;
384+ for(b = 0; b < o->data.num_of_sensor_blocks; b++) {
385+ /* 8-byte sensor block head */
386+ strncpy(&o->data.blocks[b].sensor_type[0], (const char*)&d[dnum], 4);
387+ o->data.blocks[b].reserved0 = d[dnum+4];
388+ o->data.blocks[b].sensor_format = d[dnum+5];
389+ o->data.blocks[b].sensor_length = d[dnum+6];
390+ o->data.blocks[b].num_of_sensors = d[dnum+7];
391+ dnum = dnum + 8;
392+
393+ //printk("sensor block[%d]: type: %s, num_of_sensors: %d, sensor_length: %u\n",
394+ //b, o->data.blocks[b].sensor_type, o->data.blocks[b].num_of_sensors,
395+ //o->data.blocks[b].sensor_length);
396+
397+ /* empty sensor block */
398+ if (o->data.blocks[b].num_of_sensors <= 0)
399+ continue;
400+ if (o->data.blocks[b].sensor_length == 0)
401+ continue;
402+
403+ if (strcmp(o->data.blocks[b].sensor_type, "FREQ") == 0) {
404+ o->data.blocks[b].sensor =
405+ kzalloc(sizeof(occ_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
406+
407+ if (o->data.blocks[b].sensor == NULL) {
408+ ret = -ENOMEM;
409+ goto abort;
410+ }
411+ o->freq_block_id = b;
412+ for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
413+ o->data.blocks[b].sensor[s].sensor_id = d[dnum] << 8;
414+ o->data.blocks[b].sensor[s].sensor_id =
415+ o->data.blocks[b].sensor[s].sensor_id | d[dnum+1];
416+ o->data.blocks[b].sensor[s].value = d[dnum+2] << 8;
417+ o->data.blocks[b].sensor[s].value = o->data.blocks[b].sensor[s].value | d[dnum+3];
418+ //printk("sensor[%d]-[%d]: id: %u, value: %u\n",
419+ // b, s, o->data.blocks[b].sensor[s].sensor_id, o->data.blocks[b].sensor[s].value);
420+ dnum = dnum + o->data.blocks[b].sensor_length;
421+ }
422+ }
423+ else if (strcmp(o->data.blocks[b].sensor_type, "TEMP") == 0) {
424+
425+ o->data.blocks[b].sensor =
426+ kzalloc(sizeof(occ_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
427+
428+ if (o->data.blocks[b].sensor == NULL) {
429+ ret = -ENOMEM;
430+ goto abort;
431+ }
432+
433+ o->temp_block_id = b;
434+ for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
435+ o->data.blocks[b].sensor[s].sensor_id = d[dnum] << 8;
436+ o->data.blocks[b].sensor[s].sensor_id =
437+ o->data.blocks[b].sensor[s].sensor_id | d[dnum+1];
438+ o->data.blocks[b].sensor[s].value = d[dnum+2] << 8;
439+ o->data.blocks[b].sensor[s].value = o->data.blocks[b].sensor[s].value | d[dnum+3];
440+ //printk("sensor[%d]-[%d]: id: %u, value: %u\n",
441+ // b, s, o->data.blocks[b].sensor[s].sensor_id, o->data.blocks[b].sensor[s].value);
442+ dnum = dnum + o->data.blocks[b].sensor_length;
443+ }
444+ }
445+ else if (strcmp(o->data.blocks[b].sensor_type, "POWR") == 0) {
446+
447+ o->data.blocks[b].powr =
448+ kzalloc(sizeof(powr_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
449+
450+ if (o->data.blocks[b].powr == NULL) {
451+ ret = -ENOMEM;
452+ goto abort;
453+ }
454+ o->power_block_id = b;
455+ for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
456+ o->data.blocks[b].powr[s].sensor_id = d[dnum] << 8;
457+ o->data.blocks[b].powr[s].sensor_id = o->data.blocks[b].powr[s].sensor_id | d[dnum+1];
458+ o->data.blocks[b].powr[s].update_tag = d[dnum+2] << 24;
459+ o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+3] << 16;
460+ o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+4] << 8;
461+ o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+5];
462+ o->data.blocks[b].powr[s].accumulator = d[dnum+6] << 24;
463+ o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+7] << 16;
464+ o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+8] << 8;
465+ o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+9];
466+ o->data.blocks[b].powr[s].value = d[dnum+10] << 8;
467+ o->data.blocks[b].powr[s].value = o->data.blocks[b].powr[s].value | d[dnum+11];
468+
469+ //printk("sensor[%d]-[%d]: id: %u, value: %u\n",
470+ // b, s, o->data.blocks[b].powr[s].sensor_id, o->data.blocks[b].powr[s].value);
471+
472+ dnum = dnum + o->data.blocks[b].sensor_length;
473+ }
474+ }
475+ else if (strcmp(o->data.blocks[b].sensor_type, "CAPS") == 0) {
476+
477+ o->data.blocks[b].caps =
478+ kzalloc(sizeof(caps_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
479+
480+ if (o->data.blocks[b].caps == NULL) {
481+ ret = -ENOMEM;
482+ goto abort;
483+ }
484+ o->caps_block_id = b;
485+ for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
486+ o->data.blocks[b].caps[s].curr_powercap = d[dnum] << 8;
487+ o->data.blocks[b].caps[s].curr_powercap = o->data.blocks[b].caps[s].curr_powercap | d[dnum+1];
488+ o->data.blocks[b].caps[s].curr_powerreading = d[dnum+2] << 8;
489+ o->data.blocks[b].caps[s].curr_powerreading = o->data.blocks[b].caps[s].curr_powerreading | d[dnum+3];
490+ o->data.blocks[b].caps[s].norm_powercap = d[dnum+4] << 8;
491+ o->data.blocks[b].caps[s].norm_powercap = o->data.blocks[b].caps[s].norm_powercap | d[dnum+5];
492+ o->data.blocks[b].caps[s].max_powercap = d[dnum+6] << 8;
493+ o->data.blocks[b].caps[s].max_powercap = o->data.blocks[b].caps[s].max_powercap| d[dnum+7];
494+ o->data.blocks[b].caps[s].min_powercap = d[dnum+8] << 8;
495+ o->data.blocks[b].caps[s].min_powercap = o->data.blocks[b].caps[s].min_powercap| d[dnum+9];
496+ o->data.blocks[b].caps[s].user_powerlimit = d[dnum+10] << 8;
497+ o->data.blocks[b].caps[s].user_powerlimit = o->data.blocks[b].caps[s].user_powerlimit| d[dnum+11];
498+
499+ dnum = dnum + o->data.blocks[b].sensor_length;
500+ //printk("CAPS sensor #%d:\n", s);
501+ //printk("curr_powercap is %x \n", o->data.blocks[b].caps[s].curr_powercap);
502+ //printk("curr_powerreading is %x \n", o->data.blocks[b].caps[s].curr_powerreading);
503+ //printk("norm_powercap is %x \n", o->data.blocks[b].caps[s].norm_powercap);
504+ //printk("max_powercap is %x \n", o->data.blocks[b].caps[s].max_powercap);
505+ //printk("min_powercap is %x \n", o->data.blocks[b].caps[s].min_powercap);
506+ //printk("user_powerlimit is %x \n", o->data.blocks[b].caps[s].user_powerlimit);
507+ }
508+
509+ }
510+ else {
511+ printk("ERROR: sensor type %s not supported\n", o->data.blocks[b].sensor_type);
512+ ret = -1;
513+ goto abort;
514+ }
515+ }
516+
517+ return 0;
518+abort:
519+ deinit_occ_resp_buf(o);
520+ return ret;
521+}
522+
523+/* used for testing */
524+char fake_occ_rsp[OCC_DATA_MAX] = {
525+0x69, 0x00, 0x00, 0x00, 0xa4, 0xc3, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526+0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x5f, 0x6f, 0x63, 0x63, 0x5f, 0x31, 0x35, 0x30, 0x37,
527+0x31, 0x36, 0x61, 0x00, 0x00, 0x53, 0x45, 0x4e, 0x53, 0x4f, 0x52, 0x04, 0x01, 0x54, 0x45, 0x4d,
528+0x50, 0x00, 0x01, 0x04, 0x0a, 0x00 ,0x6a, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6d, 0x00,
529+0x00,0x00,0x6e,0x00, 0x00,0x00,0x6f,0x00, 0x00,0x00,0x70,0x00, 0x00,0x00,0x71,0x00,
530+0x00,0x00,0x73,0x00, 0x00,0x00,0x74,0x00, 0x00,0x00,0x75,0x00, 0x00,0x46,0x52,0x45,
531+0x51,0x00,0x01,0x04, 0x0a,0x00,0x76,0x00, 0x00,0x00,0x78,0x00, 0x00,0x00,0x79,0x00,
532+0x00,0x00,0x7a,0x00, 0x00,0x00,0x7b,0x00, 0x00,0x00,0x7c,0x00, 0x00,0x00,0x7d,0x00,
533+0x00,0x00,0x7f,0x00, 0x00,0x00,0x80,0x00, 0x00,0x00,0x81,0x00, 0x00,0x50,0x4f,0x57,
534+0x52,0x00,0x01,0x0c, 0x00,0x43,0x41,0x50, 0x53,0x00,0x01,0x0c, 0x01,0x00,0x00,0x00,
535+0x00,0x04,0xb0,0x09, 0x60,0x04,0x4c,0x00, 0x00,0x17,0xc5,};
536+
537+//#define DUMP_RAW 1
538+
539+static int occ_get_all(struct i2c_client *client, occ_response_t *occ_resp)
540+{
541+ char occ_data[OCC_DATA_MAX];
542+ uint16_t num_bytes = 0;
543+ int b = 0;
544+ int ret = 0;
545+/*
546+ //Procedure to access SRAM where OCC data is located
547+ occ_putscom(client, SCOM_OCC_SRAM_WOX, 0x08000000, 0x00000000);
548+ occ_putscom(client, SCOM_OCC_SRAM_WAND, 0xFBFFFFFF, 0xFFFFFFFF);
549+ occ_putscom(client, SCOM_OCC_SRAM_ADDR, OCC_RESPONSE_ADDR, 0x00000000);
550+ occ_putscom(client, SCOM_OCC_SRAM_ADDR, OCC_RESPONSE_ADDR, 0x00000000);
551+
552+ occ_getscomb(client, SCOM_OCC_SRAM_DATA, occ_data, 0);
553+
554+*/
555+
556+ // Init OCB
557+ occ_putscom(client, OCB_STATUS_CONTROL_OR, 0x08000000, 0x00000000);
558+ occ_putscom(client, OCB_STATUS_CONTROL_AND, 0xFBFFFFFF, 0xFFFFFFFF);
559+
560+ // Send poll command to OCC
561+ occ_putscom(client, OCB_ADDRESS, OCC_COMMAND_ADDR, 0x00000000);
562+ occ_putscom(client, OCB_ADDRESS, OCC_COMMAND_ADDR, 0x00000000);
563+ occ_putscom(client, OCB_DATA, 0x00000001, 0x10001100);
564+
565+ // Trigger ATTN
566+ occ_putscom(client, ATTN_DATA, 0x01010000, 0x00000000);
567+
568+ // TODO: check command status Refere to
569+ // "1.6.2 OCC Command/Response Sequence" in OCC_OpenPwr_FW_Interfaces1.2.pdf
570+ // Use sleep as workaround
571+ //msleep(2000);
572+
573+ // Get response data
574+ occ_putscom(client, OCB_ADDRESS, OCC_RESPONSE_ADDR, 0x00000000);
575+ occ_getscomb(client, OCB_DATA, occ_data, 0);
576+
577+ /* FIXME: use fake data to test driver without hw */
578+ //printk("i2c-occ: using FAKE occ data\n");
579+ //memcpy(&occ_data[0], &fake_occ_rsp[0], sizeof(occ_data));
580+
581+ num_bytes = get_occdata_length(occ_data);
582+
583+ //printk("OCC data length: %d\n", num_bytes);
584+
585+#ifdef DUMP_RAW
586+ int i = 0;
587+ printk("\nRAW data\n==================\n");
588+ for (i = 0; i < 8; i++) {
589+ if(i == 4) printk(" ");
590+ printk("%02x", occ_data[i]);
591+ }
592+ printk("\n");
593+#endif
594+
595+ if (num_bytes > OCC_DATA_MAX) {
596+ printk("ERROR: OCC data length must be < 4KB\n");
597+ return -1;
598+ }
599+
600+ if (num_bytes <= 0) {
601+ printk("ERROR: OCC data length is zero\n");
602+ return -1;
603+ }
604+
605+ for (b = 8; b < num_bytes + 8; b = b + 8) {
606+ //occ_getscomb(client, SCOM_OCC_SRAM_DATA, occ_data, b);
607+ occ_getscomb(client, OCB_DATA, occ_data, b);
608+#ifdef DUMP_RAW
609+ for (i = 0; i < 8; i++) {
610+ if(i == 4) printk(" ");
611+ printk("%02x", occ_data[b+i]);
612+ }
613+ printk("\n");
614+#endif
615+
616+ }
617+
618+ /* FIXME: use fake data to test driver without hw */
619+ //memcpy(&occ_data[0], &fake_occ_rsp[0], sizeof(occ_data));
620+
621+ ret = parse_occ_response(occ_data, occ_resp);
622+
623+ return ret;
624+}
625+
626+
627+static int occ_update_device(struct device *dev)
628+{
629+ struct occ_drv_data *data = dev_get_drvdata(dev);
630+ struct i2c_client *client = data->client;
631+ int ret = 0;
632+
633+ mutex_lock(&data->update_lock);
634+
635+ if (time_after(jiffies, data->last_updated + data->sample_time)
636+ || !data->valid) {
637+ deinit_occ_resp_buf(&data->occ_resp);
638+
639+ ret = occ_get_all(client, &data->occ_resp);
640+
641+ data->last_updated = jiffies;
642+ data->valid = 1;
643+ }
644+ mutex_unlock(&data->update_lock);
645+
646+ return ret;
647+}
648+
649+/* ----------------------------------------------------------------------*/
650+/* sysfs attributes for hwmon */
651+
652+static ssize_t show_occ_temp_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
653+{
654+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
655+ int n = attr->index;
656+ struct device * dev = hwmon_dev->parent;
657+ struct occ_drv_data *data = dev_get_drvdata(dev);
658+ int ret = 0;
659+ occ_sensor *sensor;
660+ int val = 0;
661+
662+ ret = occ_update_device(dev);
663+
664+ if (ret != 0)
665+ {
666+ /* FIXME: to test fake data */
667+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
668+ return ret;
669+ }
670+
671+ if (data->occ_resp.data.blocks == NULL ||
672+ data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor == NULL)
673+ return -1;
674+
675+ //printk("block_id: %d, sensor: %d\n", data->occ_resp.temp_block_id, n -1);
676+ sensor = &data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor[n - 1];
677+ /* in millidegree Celsius */
678+ val = sensor->value * 1000;
679+ //printk("temp%d sensor value: %d\n", n, val);
680+
681+ //printk("------------- above are debug message, bellow is real output------------\n");
682+ return sprintf(buf, "%d\n", val);
683+}
684+
685+static ssize_t show_occ_temp_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
686+{
687+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
688+ int n = attr->index;
689+ struct device *dev = hwmon_dev->parent;
690+ struct occ_drv_data *data = dev_get_drvdata(dev);
691+ int ret = 0;
692+ occ_sensor *sensor;
693+ int val = 0;
694+
695+ ret = occ_update_device(dev);
696+
697+ if (ret != 0)
698+ {
699+ /* FIXME: to test fake data */
700+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
701+ return ret;
702+ }
703+
704+ if (data->occ_resp.data.blocks == NULL ||
705+ data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor == NULL)
706+ return -1;
707+
708+ //printk("temp_block_id: %d, sensor: %d\n", data->occ_resp.temp_block_id, n -1);
709+ sensor = &data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor[n - 1];
710+ val = sensor->sensor_id;
711+ //printk("temp%d sensor id: %d\n", n, val);
712+
713+ //printk("------------- above are debug message, bellow is real output------------\n");
714+ return sprintf(buf, "%d\n", val);
715+}
716+
717+static ssize_t show_occ_power_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
718+{
719+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
720+ int n = attr->index;
721+ struct device *dev = hwmon_dev->parent;
722+ struct occ_drv_data *data = dev_get_drvdata(dev);
723+ int ret = 0;
724+ powr_sensor *sensor;
725+ int val = 0;
726+
727+ ret = occ_update_device(dev);
728+
729+ if (ret != 0)
730+ {
731+ /* FIXME: to test fake data */
732+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
733+ return ret;
734+ }
735+
736+ //printk("power_block_id: %d, sensor: %d\n", data->occ_resp.power_block_id, n -1);
737+
738+ if (data->occ_resp.data.blocks == NULL ||
739+ data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr == NULL)
740+ return -1;
741+
742+ sensor = &data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr[n - 1];
743+ val = sensor->sensor_id;
744+ //printk("power%d sensor id: %d\n", n, val);
745+
746+ //printk("------------- above are debug message, bellow is real output------------\n");
747+ return sprintf(buf, "%d\n", val);
748+}
749+
750+
751+static ssize_t show_occ_power_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
752+{
753+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
754+ int n = attr->index;
755+ struct device *dev = hwmon_dev->parent;
756+ struct occ_drv_data *data = dev_get_drvdata(dev);
757+ int ret = 0;
758+ powr_sensor *sensor;
759+ int val = 0;
760+
761+ ret = occ_update_device(dev);
762+
763+ if (ret != 0)
764+ {
765+ /* FIXME: to test fake data */
766+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
767+ return ret;
768+ }
769+
770+ //printk("power block_id: %d, sensor: %d\n", data->occ_resp.power_block_id, n -1);
771+
772+ if (data->occ_resp.data.blocks == NULL ||
773+ data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr == NULL)
774+ return -1;
775+
776+
777+ sensor = &data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr[n - 1];
778+ val = sensor->value;
779+ //printk("power%d sensor value: %d\n", n, val);
780+
781+ //printk("------------- above are debug message, bellow is real output------------\n");
782+ return sprintf(buf, "%d\n", val);
783+}
784+
785+
786+static ssize_t show_occ_freq_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
787+{
788+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
789+ int n = attr->index;
790+ struct device *dev = hwmon_dev->parent;
791+ struct occ_drv_data *data = dev_get_drvdata(dev);
792+ int ret = 0;
793+ occ_sensor *sensor;
794+ int val = 0;
795+
796+ ret = occ_update_device(dev);
797+
798+ if (ret != 0)
799+ {
800+ /* FIXME: to test fake data */
801+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
802+ return ret;
803+ }
804+
805+ if (data->occ_resp.data.blocks == NULL ||
806+ data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor == NULL)
807+ return -1;
808+
809+ //printk("freq_block_id: %d, sensor: %d\n", data->occ_resp.freq_block_id, n -1);
810+ sensor = &data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor[n - 1];
811+ val = sensor->sensor_id;
812+ //printk("freq%d sensor id: %d\n", n, val);
813+
814+ //printk("------------- above are debug message, bellow is real output------------\n");
815+ return sprintf(buf, "%d\n", val);
816+}
817+
818+
819+static ssize_t show_occ_freq_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
820+{
821+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
822+ int n = attr->index;
823+ struct device *dev = hwmon_dev->parent;
824+ struct occ_drv_data *data = dev_get_drvdata(dev);
825+ int ret = 0;
826+ occ_sensor *sensor;
827+ int val = 0;
828+
829+ ret = occ_update_device(dev);
830+
831+ if (ret != 0)
832+ {
833+ /* FIXME: to test fake data */
834+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
835+ return ret;
836+ }
837+
838+ if (data->occ_resp.data.blocks == NULL ||
839+ data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor == NULL)
840+ return -1;
841+
842+ //printk("block_id: %d, sensor: %d\n", data->occ_resp.freq_block_id, n -1);
843+ sensor = &data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor[n - 1];
844+ val = sensor->value;
845+ //printk("freq%d sensor value: %d\n", n, val);
846+
847+ //printk("------------- above are debug message, bellow is real output------------\n");
848+ return sprintf(buf, "%d\n", val);
849+}
850+
851+static ssize_t show_occ_caps(struct device *hwmon_dev, struct device_attribute *da, char *buf)
852+{
853+ struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
854+ int nr = attr->nr;
855+ int n = attr->index;
856+ struct device *dev = hwmon_dev->parent;
857+ struct occ_drv_data *data = dev_get_drvdata(dev);
858+ int ret = 0;
859+ caps_sensor *sensor;
860+ int val = 0;
861+
862+ ret = occ_update_device(dev);
863+ if (ret != 0)
864+ {
865+ /* FIXME: to test fake data */
866+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
867+ return ret;
868+ }
869+
870+ //printk("block_id: %d, sensor: %d, nr: %d\n", data->occ_resp.caps_block_id, n - 1, nr);
871+ if (data->occ_resp.data.blocks == NULL ||
872+ data->occ_resp.data.blocks[data->occ_resp.caps_block_id].caps == NULL)
873+ return -1;
874+
875+ sensor = &data->occ_resp.data.blocks[data->occ_resp.caps_block_id].caps[n - 1];
876+
877+ switch (nr) {
878+ case 0:
879+ val = sensor->curr_powercap;
880+ break;
881+ case 1:
882+ val = sensor->curr_powerreading;
883+ break;
884+ case 2:
885+ val = sensor->norm_powercap;
886+ break;
887+ case 3:
888+ val = sensor->max_powercap;
889+ break;
890+ case 4:
891+ val = sensor->min_powercap;
892+ break;
893+ case 5:
894+ val = sensor->user_powerlimit;
895+ break;
896+ default:
897+ val = 0;
898+ }
899+
900+ //printk("caps%d sensor value: %d, nr: %d\n", n, val, nr);
901+
902+ //printk("------------- above are debug message, bellow is real output------------\n");
903+ return sprintf(buf, "%d\n", val);
904+}
905+
906+#if 0
907+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_occ_temp_input, NULL, 1);
908+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_occ_temp_input, NULL, 2);
909+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_occ_temp_input, NULL, 3);
910+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_occ_temp_input, NULL, 4);
911+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_occ_temp_input, NULL, 5);
912+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_occ_temp_input, NULL, 6);
913+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_occ_temp_input, NULL, 7);
914+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_occ_temp_input, NULL, 8);
915+static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_occ_temp_input, NULL, 9);
916+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_occ_temp_label, NULL, 1);
917+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_occ_temp_label, NULL, 2);
918+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_occ_temp_label, NULL, 3);
919+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_occ_temp_label, NULL, 4);
920+static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_occ_temp_label, NULL, 5);
921+static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, show_occ_temp_label, NULL, 6);
922+static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, show_occ_temp_label, NULL, 7);
923+static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_occ_temp_label, NULL, 8);
924+static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, show_occ_temp_label, NULL, 9);
925+
926+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_occ_power_input, NULL, 1);
927+static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, show_occ_power_label, NULL, 1);
928+static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_occ_power_input, NULL, 2);
929+static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, show_occ_power_label, NULL, 2);
930+static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_occ_power_input, NULL, 3);
931+static SENSOR_DEVICE_ATTR(power3_label, S_IRUGO, show_occ_power_label, NULL, 3);
932+static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_occ_power_input, NULL, 4);
933+static SENSOR_DEVICE_ATTR(power4_label, S_IRUGO, show_occ_power_label, NULL, 4);
934+
935+static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, show_occ_freq_input, NULL, 1);
936+static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, show_occ_freq_label, NULL, 1);
937+static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, show_occ_freq_input, NULL, 2);
938+static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, show_occ_freq_label, NULL, 2);
939+static SENSOR_DEVICE_ATTR(freq3_input, S_IRUGO, show_occ_freq_input, NULL, 3);
940+static SENSOR_DEVICE_ATTR(freq3_label, S_IRUGO, show_occ_freq_label, NULL, 3);
941+static SENSOR_DEVICE_ATTR(freq4_input, S_IRUGO, show_occ_freq_input, NULL, 4);
942+static SENSOR_DEVICE_ATTR(freq4_label, S_IRUGO, show_occ_freq_label, NULL, 4);
943+
944+static struct attribute *occ_attrs[] = {
945+ &sensor_dev_attr_temp1_input.dev_attr.attr,
946+ &sensor_dev_attr_temp2_input.dev_attr.attr,
947+ &sensor_dev_attr_temp3_input.dev_attr.attr,
948+ &sensor_dev_attr_temp4_input.dev_attr.attr,
949+ &sensor_dev_attr_temp5_input.dev_attr.attr,
950+ &sensor_dev_attr_temp6_input.dev_attr.attr,
951+ &sensor_dev_attr_temp7_input.dev_attr.attr,
952+ &sensor_dev_attr_temp8_input.dev_attr.attr,
953+ &sensor_dev_attr_temp9_input.dev_attr.attr,
954+ &sensor_dev_attr_temp1_label.dev_attr.attr,
955+ &sensor_dev_attr_temp2_label.dev_attr.attr,
956+ &sensor_dev_attr_temp3_label.dev_attr.attr,
957+ &sensor_dev_attr_temp4_label.dev_attr.attr,
958+ &sensor_dev_attr_temp5_label.dev_attr.attr,
959+ &sensor_dev_attr_temp6_label.dev_attr.attr,
960+ &sensor_dev_attr_temp7_label.dev_attr.attr,
961+ &sensor_dev_attr_temp8_label.dev_attr.attr,
962+ &sensor_dev_attr_temp9_label.dev_attr.attr,
963+ &sensor_dev_attr_power1_input.dev_attr.attr,
964+ &sensor_dev_attr_power2_input.dev_attr.attr,
965+ &sensor_dev_attr_power3_input.dev_attr.attr,
966+ &sensor_dev_attr_power4_input.dev_attr.attr,
967+ &sensor_dev_attr_power1_label.dev_attr.attr,
968+ &sensor_dev_attr_power2_label.dev_attr.attr,
969+ &sensor_dev_attr_power3_label.dev_attr.attr,
970+ &sensor_dev_attr_power4_label.dev_attr.attr,
971+ &sensor_dev_attr_freq1_input.dev_attr.attr,
972+ &sensor_dev_attr_freq2_input.dev_attr.attr,
973+ &sensor_dev_attr_freq3_input.dev_attr.attr,
974+ &sensor_dev_attr_freq4_input.dev_attr.attr,
975+ &sensor_dev_attr_freq1_label.dev_attr.attr,
976+ &sensor_dev_attr_freq2_label.dev_attr.attr,
977+ &sensor_dev_attr_freq3_label.dev_attr.attr,
978+ &sensor_dev_attr_freq4_label.dev_attr.attr,
979+
980+ NULL
981+};
982+ATTRIBUTE_GROUPS(occ);
983+
984+#endif
985+
986+static struct sensor_device_attribute temp_input[] = {
987+ SENSOR_ATTR(temp1_input, S_IRUGO, show_occ_temp_input, NULL, 1),
988+ SENSOR_ATTR(temp2_input, S_IRUGO, show_occ_temp_input, NULL, 2),
989+ SENSOR_ATTR(temp3_input, S_IRUGO, show_occ_temp_input, NULL, 3),
990+ SENSOR_ATTR(temp4_input, S_IRUGO, show_occ_temp_input, NULL, 4),
991+ SENSOR_ATTR(temp5_input, S_IRUGO, show_occ_temp_input, NULL, 5),
992+ SENSOR_ATTR(temp6_input, S_IRUGO, show_occ_temp_input, NULL, 6),
993+ SENSOR_ATTR(temp7_input, S_IRUGO, show_occ_temp_input, NULL, 7),
994+ SENSOR_ATTR(temp8_input, S_IRUGO, show_occ_temp_input, NULL, 8),
995+ SENSOR_ATTR(temp9_input, S_IRUGO, show_occ_temp_input, NULL, 9),
996+ SENSOR_ATTR(temp10_input, S_IRUGO, show_occ_temp_input, NULL, 10),
997+ SENSOR_ATTR(temp11_input, S_IRUGO, show_occ_temp_input, NULL, 11),
998+ SENSOR_ATTR(temp12_input, S_IRUGO, show_occ_temp_input, NULL, 12),
999+ SENSOR_ATTR(temp13_input, S_IRUGO, show_occ_temp_input, NULL, 13),
1000+ SENSOR_ATTR(temp14_input, S_IRUGO, show_occ_temp_input, NULL, 14),
1001+ SENSOR_ATTR(temp15_input, S_IRUGO, show_occ_temp_input, NULL, 15),
1002+ SENSOR_ATTR(temp16_input, S_IRUGO, show_occ_temp_input, NULL, 16),
1003+ SENSOR_ATTR(temp17_input, S_IRUGO, show_occ_temp_input, NULL, 17),
1004+ SENSOR_ATTR(temp18_input, S_IRUGO, show_occ_temp_input, NULL, 18),
1005+ SENSOR_ATTR(temp19_input, S_IRUGO, show_occ_temp_input, NULL, 19),
1006+ SENSOR_ATTR(temp20_input, S_IRUGO, show_occ_temp_input, NULL, 20),
1007+ SENSOR_ATTR(temp21_input, S_IRUGO, show_occ_temp_input, NULL, 21),
1008+ SENSOR_ATTR(temp22_input, S_IRUGO, show_occ_temp_input, NULL, 22),
1009+};
1010+
1011+static struct sensor_device_attribute temp_label[] = {
1012+ SENSOR_ATTR(temp1_label, S_IRUGO, show_occ_temp_label, NULL, 1),
1013+ SENSOR_ATTR(temp2_label, S_IRUGO, show_occ_temp_label, NULL, 2),
1014+ SENSOR_ATTR(temp3_label, S_IRUGO, show_occ_temp_label, NULL, 3),
1015+ SENSOR_ATTR(temp4_label, S_IRUGO, show_occ_temp_label, NULL, 4),
1016+ SENSOR_ATTR(temp5_label, S_IRUGO, show_occ_temp_label, NULL, 5),
1017+ SENSOR_ATTR(temp6_label, S_IRUGO, show_occ_temp_label, NULL, 6),
1018+ SENSOR_ATTR(temp7_label, S_IRUGO, show_occ_temp_label, NULL, 7),
1019+ SENSOR_ATTR(temp8_label, S_IRUGO, show_occ_temp_label, NULL, 8),
1020+ SENSOR_ATTR(temp9_label, S_IRUGO, show_occ_temp_label, NULL, 9),
1021+ SENSOR_ATTR(temp10_label, S_IRUGO, show_occ_temp_label, NULL, 10),
1022+ SENSOR_ATTR(temp11_label, S_IRUGO, show_occ_temp_label, NULL, 11),
1023+ SENSOR_ATTR(temp12_label, S_IRUGO, show_occ_temp_label, NULL, 12),
1024+ SENSOR_ATTR(temp13_label, S_IRUGO, show_occ_temp_label, NULL, 13),
1025+ SENSOR_ATTR(temp14_label, S_IRUGO, show_occ_temp_label, NULL, 14),
1026+ SENSOR_ATTR(temp15_label, S_IRUGO, show_occ_temp_label, NULL, 15),
1027+ SENSOR_ATTR(temp16_label, S_IRUGO, show_occ_temp_label, NULL, 16),
1028+ SENSOR_ATTR(temp17_label, S_IRUGO, show_occ_temp_label, NULL, 17),
1029+ SENSOR_ATTR(temp18_label, S_IRUGO, show_occ_temp_label, NULL, 18),
1030+ SENSOR_ATTR(temp19_label, S_IRUGO, show_occ_temp_label, NULL, 19),
1031+ SENSOR_ATTR(temp20_label, S_IRUGO, show_occ_temp_label, NULL, 20),
1032+ SENSOR_ATTR(temp21_label, S_IRUGO, show_occ_temp_label, NULL, 21),
1033+ SENSOR_ATTR(temp22_label, S_IRUGO, show_occ_temp_label, NULL, 22),
1034+
1035+};
1036+
1037+#define TEMP_UNIT_ATTRS(X) \
1038+{ &temp_input[X].dev_attr.attr, \
1039+ &temp_label[X].dev_attr.attr, \
1040+ NULL \
1041+}
1042+
1043+/* 10-core CPU, occ has 22 temp sensors, more socket, more sensors */
1044+static struct attribute *occ_temp_attr[][3] = {
1045+ TEMP_UNIT_ATTRS(0),
1046+ TEMP_UNIT_ATTRS(1),
1047+ TEMP_UNIT_ATTRS(2),
1048+ TEMP_UNIT_ATTRS(3),
1049+ TEMP_UNIT_ATTRS(4),
1050+ TEMP_UNIT_ATTRS(5),
1051+ TEMP_UNIT_ATTRS(6),
1052+ TEMP_UNIT_ATTRS(7),
1053+ TEMP_UNIT_ATTRS(8),
1054+ TEMP_UNIT_ATTRS(9),
1055+ TEMP_UNIT_ATTRS(10),
1056+ TEMP_UNIT_ATTRS(11),
1057+ TEMP_UNIT_ATTRS(12),
1058+ TEMP_UNIT_ATTRS(13),
1059+ TEMP_UNIT_ATTRS(14),
1060+ TEMP_UNIT_ATTRS(15),
1061+ TEMP_UNIT_ATTRS(16),
1062+ TEMP_UNIT_ATTRS(17),
1063+ TEMP_UNIT_ATTRS(18),
1064+ TEMP_UNIT_ATTRS(19),
1065+ TEMP_UNIT_ATTRS(20),
1066+ TEMP_UNIT_ATTRS(21),
1067+};
1068+
1069+static const struct attribute_group occ_temp_attr_group[] = {
1070+ { .attrs = occ_temp_attr[0] },
1071+ { .attrs = occ_temp_attr[1] },
1072+ { .attrs = occ_temp_attr[2] },
1073+ { .attrs = occ_temp_attr[3] },
1074+ { .attrs = occ_temp_attr[4] },
1075+ { .attrs = occ_temp_attr[5] },
1076+ { .attrs = occ_temp_attr[6] },
1077+ { .attrs = occ_temp_attr[7] },
1078+ { .attrs = occ_temp_attr[8] },
1079+ { .attrs = occ_temp_attr[9] },
1080+ { .attrs = occ_temp_attr[10] },
1081+ { .attrs = occ_temp_attr[11] },
1082+ { .attrs = occ_temp_attr[12] },
1083+ { .attrs = occ_temp_attr[13] },
1084+ { .attrs = occ_temp_attr[14] },
1085+ { .attrs = occ_temp_attr[15] },
1086+ { .attrs = occ_temp_attr[16] },
1087+ { .attrs = occ_temp_attr[17] },
1088+ { .attrs = occ_temp_attr[18] },
1089+ { .attrs = occ_temp_attr[19] },
1090+ { .attrs = occ_temp_attr[20] },
1091+ { .attrs = occ_temp_attr[21] },
1092+};
1093+
1094+
1095+static struct sensor_device_attribute freq_input[] = {
1096+ SENSOR_ATTR(freq1_input, S_IRUGO, show_occ_freq_input, NULL, 1),
1097+ SENSOR_ATTR(freq2_input, S_IRUGO, show_occ_freq_input, NULL, 2),
1098+ SENSOR_ATTR(freq3_input, S_IRUGO, show_occ_freq_input, NULL, 3),
1099+ SENSOR_ATTR(freq4_input, S_IRUGO, show_occ_freq_input, NULL, 4),
1100+ SENSOR_ATTR(freq5_input, S_IRUGO, show_occ_freq_input, NULL, 5),
1101+ SENSOR_ATTR(freq6_input, S_IRUGO, show_occ_freq_input, NULL, 6),
1102+ SENSOR_ATTR(freq7_input, S_IRUGO, show_occ_freq_input, NULL, 7),
1103+ SENSOR_ATTR(freq8_input, S_IRUGO, show_occ_freq_input, NULL, 8),
1104+ SENSOR_ATTR(freq9_input, S_IRUGO, show_occ_freq_input, NULL, 9),
1105+ SENSOR_ATTR(freq10_input, S_IRUGO, show_occ_freq_input, NULL, 10),
1106+};
1107+
1108+static struct sensor_device_attribute freq_label[] = {
1109+ SENSOR_ATTR(freq1_label, S_IRUGO, show_occ_freq_label, NULL, 1),
1110+ SENSOR_ATTR(freq2_label, S_IRUGO, show_occ_freq_label, NULL, 2),
1111+ SENSOR_ATTR(freq3_label, S_IRUGO, show_occ_freq_label, NULL, 3),
1112+ SENSOR_ATTR(freq4_label, S_IRUGO, show_occ_freq_label, NULL, 4),
1113+ SENSOR_ATTR(freq5_label, S_IRUGO, show_occ_freq_label, NULL, 5),
1114+ SENSOR_ATTR(freq6_label, S_IRUGO, show_occ_freq_label, NULL, 6),
1115+ SENSOR_ATTR(freq7_label, S_IRUGO, show_occ_freq_label, NULL, 7),
1116+ SENSOR_ATTR(freq8_label, S_IRUGO, show_occ_freq_label, NULL, 8),
1117+ SENSOR_ATTR(freq9_label, S_IRUGO, show_occ_freq_label, NULL, 9),
1118+ SENSOR_ATTR(freq10_label, S_IRUGO, show_occ_freq_label, NULL, 10),
1119+
1120+};
1121+
1122+#define FREQ_UNIT_ATTRS(X) \
1123+{ &freq_input[X].dev_attr.attr, \
1124+ &freq_label[X].dev_attr.attr, \
1125+ NULL \
1126+}
1127+
1128+/* 10-core CPU, occ has 22 freq sensors, more socket, more sensors */
1129+static struct attribute *occ_freq_attr[][3] = {
1130+ FREQ_UNIT_ATTRS(0),
1131+ FREQ_UNIT_ATTRS(1),
1132+ FREQ_UNIT_ATTRS(2),
1133+ FREQ_UNIT_ATTRS(3),
1134+ FREQ_UNIT_ATTRS(4),
1135+ FREQ_UNIT_ATTRS(5),
1136+ FREQ_UNIT_ATTRS(6),
1137+ FREQ_UNIT_ATTRS(7),
1138+ FREQ_UNIT_ATTRS(8),
1139+ FREQ_UNIT_ATTRS(9),
1140+};
1141+
1142+static const struct attribute_group occ_freq_attr_group[] = {
1143+ { .attrs = occ_freq_attr[0] },
1144+ { .attrs = occ_freq_attr[1] },
1145+ { .attrs = occ_freq_attr[2] },
1146+ { .attrs = occ_freq_attr[3] },
1147+ { .attrs = occ_freq_attr[4] },
1148+ { .attrs = occ_freq_attr[5] },
1149+ { .attrs = occ_freq_attr[6] },
1150+ { .attrs = occ_freq_attr[7] },
1151+ { .attrs = occ_freq_attr[8] },
1152+ { .attrs = occ_freq_attr[9] },
1153+};
1154+
1155+static struct sensor_device_attribute_2 caps_curr_powercap[] = {
1156+ SENSOR_ATTR_2(caps_curr_powercap, S_IRUGO, show_occ_caps, NULL, 0, 1),
1157+};
1158+static struct sensor_device_attribute_2 caps_curr_powerreading[] = {
1159+ SENSOR_ATTR_2(caps_curr_powerreading, S_IRUGO, show_occ_caps, NULL, 1, 1),
1160+};
1161+static struct sensor_device_attribute_2 caps_norm_powercap[] = {
1162+ SENSOR_ATTR_2(caps_norm_powercap, S_IRUGO, show_occ_caps, NULL, 2, 1),
1163+};
1164+static struct sensor_device_attribute_2 caps_max_powercap[] = {
1165+ SENSOR_ATTR_2(caps_max_powercap, S_IRUGO, show_occ_caps, NULL, 3, 1),
1166+};
1167+static struct sensor_device_attribute_2 caps_min_powercap[] = {
1168+ SENSOR_ATTR_2(caps_min_powercap, S_IRUGO, show_occ_caps, NULL, 4, 1),
1169+};
1170+static struct sensor_device_attribute_2 caps_user_powerlimit[] = {
1171+ SENSOR_ATTR_2(caps_user_powerlimit, S_IRUGO, show_occ_caps, NULL, 5, 1),
1172+};
1173+#define CAPS_UNIT_ATTRS(X) \
1174+{ &caps_curr_powercap[X].dev_attr.attr, \
1175+ &caps_curr_powerreading[X].dev_attr.attr, \
1176+ &caps_norm_powercap[X].dev_attr.attr, \
1177+ &caps_max_powercap[X].dev_attr.attr, \
1178+ &caps_min_powercap[X].dev_attr.attr, \
1179+ &caps_user_powerlimit[X].dev_attr.attr, \
1180+ NULL \
1181+}
1182+
1183+/* 10-core CPU, occ has 1 caps sensors */
1184+static struct attribute *occ_caps_attr[][7] = {
1185+ CAPS_UNIT_ATTRS(0),
1186+};
1187+static const struct attribute_group occ_caps_attr_group[] = {
1188+ { .attrs = occ_caps_attr[0] },
1189+};
1190+
1191+static struct sensor_device_attribute power_input[] = {
1192+ SENSOR_ATTR(power1_input, S_IRUGO, show_occ_power_input, NULL, 1),
1193+ SENSOR_ATTR(power2_input, S_IRUGO, show_occ_power_input, NULL, 2),
1194+ SENSOR_ATTR(power3_input, S_IRUGO, show_occ_power_input, NULL, 3),
1195+ SENSOR_ATTR(power4_input, S_IRUGO, show_occ_power_input, NULL, 4),
1196+ SENSOR_ATTR(power5_input, S_IRUGO, show_occ_power_input, NULL, 5),
1197+ SENSOR_ATTR(power6_input, S_IRUGO, show_occ_power_input, NULL, 6),
1198+ SENSOR_ATTR(power7_input, S_IRUGO, show_occ_power_input, NULL, 7),
1199+ SENSOR_ATTR(power8_input, S_IRUGO, show_occ_power_input, NULL, 8),
1200+ SENSOR_ATTR(power9_input, S_IRUGO, show_occ_power_input, NULL, 9),
1201+ SENSOR_ATTR(power10_input, S_IRUGO, show_occ_power_input, NULL, 10),
1202+ SENSOR_ATTR(power11_input, S_IRUGO, show_occ_power_input, NULL, 11),
1203+};
1204+
1205+static struct sensor_device_attribute power_label[] = {
1206+ SENSOR_ATTR(power1_label, S_IRUGO, show_occ_power_label, NULL, 1),
1207+ SENSOR_ATTR(power2_label, S_IRUGO, show_occ_power_label, NULL, 2),
1208+ SENSOR_ATTR(power3_label, S_IRUGO, show_occ_power_label, NULL, 3),
1209+ SENSOR_ATTR(power4_label, S_IRUGO, show_occ_power_label, NULL, 4),
1210+ SENSOR_ATTR(power5_label, S_IRUGO, show_occ_power_label, NULL, 5),
1211+ SENSOR_ATTR(power6_label, S_IRUGO, show_occ_power_label, NULL, 6),
1212+ SENSOR_ATTR(power7_label, S_IRUGO, show_occ_power_label, NULL, 7),
1213+ SENSOR_ATTR(power8_label, S_IRUGO, show_occ_power_label, NULL, 8),
1214+ SENSOR_ATTR(power9_label, S_IRUGO, show_occ_power_label, NULL, 9),
1215+ SENSOR_ATTR(power10_label, S_IRUGO, show_occ_power_label, NULL, 10),
1216+ SENSOR_ATTR(power11_label, S_IRUGO, show_occ_power_label, NULL, 11),
1217+};
1218+
1219+#define POWER_UNIT_ATTRS(X) \
1220+{ &power_input[X].dev_attr.attr, \
1221+ &power_label[X].dev_attr.attr, \
1222+ NULL \
1223+}
1224+
1225+/* 10-core CPU, occ has 11 power sensors, more socket, more sensors */
1226+static struct attribute *occ_power_attr[][3] = {
1227+ POWER_UNIT_ATTRS(0),
1228+ POWER_UNIT_ATTRS(1),
1229+ POWER_UNIT_ATTRS(2),
1230+ POWER_UNIT_ATTRS(3),
1231+ POWER_UNIT_ATTRS(4),
1232+ POWER_UNIT_ATTRS(5),
1233+ POWER_UNIT_ATTRS(6),
1234+ POWER_UNIT_ATTRS(7),
1235+ POWER_UNIT_ATTRS(8),
1236+ POWER_UNIT_ATTRS(9),
1237+ POWER_UNIT_ATTRS(10),
1238+};
1239+
1240+static const struct attribute_group occ_power_attr_group[] = {
1241+ { .attrs = occ_power_attr[0] },
1242+ { .attrs = occ_power_attr[1] },
1243+ { .attrs = occ_power_attr[2] },
1244+ { .attrs = occ_power_attr[3] },
1245+ { .attrs = occ_power_attr[4] },
1246+ { .attrs = occ_power_attr[5] },
1247+ { .attrs = occ_power_attr[6] },
1248+ { .attrs = occ_power_attr[7] },
1249+ { .attrs = occ_power_attr[8] },
1250+ { .attrs = occ_power_attr[9] },
1251+ { .attrs = occ_power_attr[10] },
1252+};
1253+
1254+static void occ_remove_sysfs_files(struct device *dev)
1255+{
1256+ int i = 0;
1257+
1258+ for (i = 0; i < ARRAY_SIZE(occ_temp_attr_group); i++)
1259+ sysfs_remove_group(&dev->kobj, &occ_temp_attr_group[i]);
1260+
1261+ for (i = 0; i < ARRAY_SIZE(occ_freq_attr_group); i++)
1262+ sysfs_remove_group(&dev->kobj, &occ_freq_attr_group[i]);
1263+
1264+ for (i = 0; i < ARRAY_SIZE(occ_power_attr_group); i++)
1265+ sysfs_remove_group(&dev->kobj, &occ_power_attr_group[i]);
1266+
1267+ for (i = 0; i < ARRAY_SIZE(occ_caps_attr_group); i++)
1268+ sysfs_remove_group(&dev->kobj, &occ_caps_attr_group[i]);
1269+}
1270+
1271+
1272+static int occ_create_sysfs_attribute(struct device *dev)
1273+{
1274+ /* The sensor number varies for different
1275+ * platform depending on core number. We'd better
1276+ * create them dynamically */
1277+ struct occ_drv_data *data = dev_get_drvdata(dev);
1278+ int i = 0;
1279+ int num_of_sensors = 0;
1280+ int ret = 0;
1281+
1282+ /* get sensor number from occ. */
1283+ ret = occ_update_device(dev);
1284+ if (ret != 0)
1285+ {
1286+ /* FIXME: to test fake data */
1287+ printk("ERROR: cannot get occ sensor data: %d\n", ret);
1288+ return ret;
1289+ }
1290+
1291+ if (data->occ_resp.data.blocks == NULL)
1292+ return -1;
1293+
1294+ /* temp sensors */
1295+ if (data->occ_resp.temp_block_id >= 0)
1296+ {
1297+ num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.temp_block_id].num_of_sensors;
1298+ for (i = 0; i < num_of_sensors; i++)
1299+ {
1300+ //printk("create temp group: %d\n", i);
1301+ //ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
1302+ ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_temp_attr_group[i]);
1303+ if (ret)
1304+ {
1305+ dev_err(dev, "error create temp sysfs entry\n");
1306+ goto error;
1307+ }
1308+ }
1309+ }
1310+
1311+ /* freq sensors */
1312+ if (data->occ_resp.freq_block_id >= 0)
1313+ {
1314+ num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.freq_block_id].num_of_sensors;
1315+ for (i = 0; i < num_of_sensors; i++)
1316+ {
1317+ //printk("create freq group: %d\n", i);
1318+ //ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
1319+ ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_freq_attr_group[i]);
1320+ if (ret)
1321+ {
1322+ dev_err(dev, "error create freq sysfs entry\n");
1323+ goto error;
1324+ }
1325+ }
1326+ }
1327+
1328+ /* power sensors */
1329+ //printk("power_block_id: %d\n", data->occ_resp.power_block_id);
1330+ if (data->occ_resp.power_block_id >= 0)
1331+ {
1332+ num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.power_block_id].num_of_sensors;
1333+ for (i = 0; i < num_of_sensors; i++)
1334+ {
1335+ //printk("create power group: %d\n", i);
1336+ //ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
1337+ ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_power_attr_group[i]);
1338+ if (ret)
1339+ {
1340+ dev_err(dev, "error create power sysfs entry\n");
1341+ goto error;
1342+ }
1343+ }
1344+ }
1345+
1346+ /* caps sensors */
1347+ //printk("caps_block_id: %d\n", data->occ_resp.caps_block_id);
1348+ if (data->occ_resp.caps_block_id >= 0)
1349+ {
1350+ num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.caps_block_id].num_of_sensors;
1351+ for (i = 0; i < num_of_sensors; i++)
1352+ {
1353+ //printk("create caps group: %d\n", i);
1354+ //ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
1355+ ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_caps_attr_group[i]);
1356+ if (ret)
1357+ {
1358+ dev_err(dev, "error create caps sysfs entry\n");
1359+ goto error;
1360+ }
1361+ }
1362+ }
1363+
1364+ return 0;
1365+error:
1366+ occ_remove_sysfs_files(data->hwmon_dev);
1367+ return ret;
1368+}
1369+
1370+/*-----------------------------------------------------------------------*/
1371+/* device probe and removal */
1372+
1373+#define OCC_I2C_ADDR 0x50
1374+#define OCC_I2C_NAME "occ-i2c"
1375+
1376+enum occ_type {
1377+ occ_id,
1378+};
1379+
1380+static int occ_probe(struct i2c_client *client, const struct i2c_device_id *id)
1381+{
1382+ struct device *dev = &client->dev;
1383+ struct occ_drv_data *data;
1384+ unsigned long funcs;
1385+ struct device_node *np = dev->of_node;
1386+ //u32 pval = 0;
1387+ int ret = 0;
1388+
1389+ data = devm_kzalloc(dev, sizeof(struct occ_drv_data), GFP_KERNEL);
1390+ if (!data)
1391+ return -ENOMEM;
1392+
1393+ data->client = client;
1394+ i2c_set_clientdata(client, data);
1395+ mutex_init(&data->update_lock);
1396+ data->sample_time = HZ;
1397+
1398+ /* Yi: i2c-core should assign address to
1399+ * client when detection - but it does not work FIXME */
1400+ //client->addr = OCC_I2C_ADDR;
1401+
1402+ /* Yi: read address from device table */
1403+ //if (of_property_read_u32(np, "reg", &pval)) {
1404+ // dev_err(&client->dev, "invalid reg\n");
1405+ //}
1406+ //client->addr = pval;
1407+
1408+ /* configure the driver */
1409+ //dev_dbg(dev, "occ register hwmon @0x%x\n", client->addr);
1410+ //data->hwmon_dev = hwmon_device_register_with_groups(dev, "occ",
1411+ // data, occ_groups);
1412+
1413+ /* Yi: try to create sysfs attributes dynamically */
1414+ data->hwmon_dev = hwmon_device_register(dev);
1415+ if (IS_ERR(data->hwmon_dev))
1416+ return PTR_ERR(data->hwmon_dev);
1417+
1418+ ret = occ_create_sysfs_attribute(dev);
1419+ if (ret)
1420+ {
1421+ hwmon_device_unregister(data->hwmon_dev);
1422+ return ret;
1423+ }
1424+
1425+ data->hwmon_dev->parent = dev;
1426+
1427+ //dev_dbg(dev, "%s: sensor '%s'\n",
1428+ // dev_name(data->hwmon_dev), client->name);
1429+
1430+ funcs = i2c_get_functionality(client->adapter);
1431+ //dev_info(dev, "i2c adaptor supports function: 0x%lx\n", funcs);
1432+
1433+ /* Yi: seems always error? disable for now */
1434+ //occ_check_i2c_errors(client);
1435+
1436+ //dev_info(dev, "occ i2c driver ready: i2c addr@0x%x\n", client->addr);
1437+ printk("occ i2c driver ready: i2c addr@0x%x\n", client->addr);
1438+
1439+ return 0;
1440+}
1441+
1442+static int occ_remove(struct i2c_client *client)
1443+{
1444+ struct occ_drv_data *data = i2c_get_clientdata(client);
1445+
1446+ /* free allocated sensor memory */
1447+ deinit_occ_resp_buf(&data->occ_resp);
1448+
1449+ //occ_remove_sysfs_files(&client->dev);
1450+ occ_remove_sysfs_files(data->hwmon_dev);
1451+ hwmon_device_unregister(data->hwmon_dev);
1452+ return 0;
1453+}
1454+
1455+/* used for old-style board info */
1456+static const struct i2c_device_id occ_ids[] = {
1457+ { OCC_I2C_NAME, occ_id, },
1458+ { /* LIST END */ }
1459+};
1460+MODULE_DEVICE_TABLE(i2c, occ_ids);
1461+
1462+static const struct of_device_id i2c_occ_of_match[] = {
1463+ {.compatible = "ibm,occ-i2c"},
1464+ {},
1465+};
1466+
1467+MODULE_DEVICE_TABLE(of, i2c_occ_of_match);
1468+
1469+#ifdef CONFIG_PM
1470+static int occ_suspend(struct device *dev)
1471+{
1472+ //struct i2c_client *client = to_i2c_client(dev);
1473+ /* TODO */
1474+ return 0;
1475+}
1476+
1477+static int occ_resume(struct device *dev)
1478+{
1479+ //struct i2c_client *client = to_i2c_client(dev);
1480+ /* TODO */
1481+ return 0;
1482+}
1483+
1484+static const struct dev_pm_ops occ_dev_pm_ops = {
1485+ .suspend = occ_suspend,
1486+ .resume = occ_resume,
1487+};
1488+#define OCC_DEV_PM_OPS (&occ_dev_pm_ops)
1489+#else
1490+#define OCC_DEV_PM_OPS NULL
1491+#endif /* CONFIG_PM */
1492+
1493+/* Yi: i2c-core uses i2c-detect() to detect device in bellow address list.
1494+ If exists, address will be assigned to client.
1495+ * It is also possible to read address from device table. */
1496+static const unsigned short normal_i2c[] = {0x50, 0x51, I2C_CLIENT_END };
1497+
1498+/* Return 0 if detection is successful, -ENODEV otherwise */
1499+static int occ_detect(struct i2c_client *new_client,
1500+ struct i2c_board_info *info)
1501+{
1502+ /* i2c-core need this function to create new device */
1503+ strncpy(info->type, OCC_I2C_NAME, sizeof(OCC_I2C_NAME));
1504+ return 0;
1505+}
1506+
1507+static struct i2c_driver occ_driver = {
1508+ .class = I2C_CLASS_HWMON,
1509+ .driver = {
1510+ .name = OCC_I2C_NAME,
1511+ .pm = OCC_DEV_PM_OPS,
1512+ .of_match_table = i2c_occ_of_match,
1513+ },
1514+ .probe = occ_probe,
1515+ .remove = occ_remove,
1516+ .id_table = occ_ids,
1517+ .address_list = normal_i2c,
1518+ .detect = occ_detect,
1519+};
1520+
1521+module_i2c_driver(occ_driver);
1522+
1523+#if 0
1524+/* Create new i2c device */
1525+static struct i2c_board_info my_dev_info[] __initdata = {
1526+ {
1527+ I2C_BOARD_INFO(OCC_I2C_NAME, 0x50),
1528+ },
1529+};
1530+
1531+static struct i2c_client *my_client;
1532+
1533+static int occ_init(void)
1534+{
1535+ static int sys_adap_bus_num = 3;
1536+ struct i2c_adapter* adap = i2c_get_adapter(sys_adap_bus_num);
1537+
1538+ if(adap==NULL) {
1539+ printk("[OCC-DEBUG] i2c_get_adapter fail!\n");
1540+ return -1;
1541+ }
1542+
1543+ my_client = i2c_new_device(adap, &my_dev_info[0]);
1544+ if( my_client==NULL ){
1545+ printk("[OCC-DEBUG] i2c_new_device fail!\n");
1546+ return -1;
1547+ }
1548+ i2c_put_adapter(adap);
1549+ return i2c_add_driver(&occ_driver);
1550+}
1551+
1552+static void __exit occ_exit(void)
1553+{
1554+ i2c_unregister_device(my_client);
1555+ i2c_del_driver(&occ_driver);
1556+}
1557+
1558+module_init(occ_init);
1559+module_exit(occ_exit);
1560+
1561+#endif
1562+
1563+MODULE_AUTHOR("Li Yi <shliyi@cn.ibm.com>");
1564+MODULE_DESCRIPTION("BMC OCC monitor driver");
1565+MODULE_LICENSE("GPL");