pc87360.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. /*
  2. * pc87360.c - Part of lm_sensors, Linux kernel modules
  3. * for hardware monitoring
  4. * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
  5. *
  6. * Copied from smsc47m1.c:
  7. * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. *
  23. * Supports the following chips:
  24. *
  25. * Chip #vin #fan #pwm #temp devid
  26. * PC87360 - 2 2 - 0xE1
  27. * PC87363 - 2 2 - 0xE8
  28. * PC87364 - 3 3 - 0xE4
  29. * PC87365 11 3 3 2 0xE5
  30. * PC87366 11 3 3 3-4 0xE9
  31. *
  32. * This driver assumes that no more than one chip is present, and one of
  33. * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
  34. */
  35. #include <linux/module.h>
  36. #include <linux/init.h>
  37. #include <linux/slab.h>
  38. #include <linux/jiffies.h>
  39. #include <linux/i2c.h>
  40. #include <linux/i2c-isa.h>
  41. #include <linux/i2c-vid.h>
  42. #include <linux/hwmon.h>
  43. #include <linux/err.h>
  44. #include <asm/io.h>
  45. static u8 devid;
  46. static unsigned short address;
  47. static unsigned short extra_isa[3];
  48. static u8 confreg[4];
  49. enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
  50. static int init = 1;
  51. module_param(init, int, 0);
  52. MODULE_PARM_DESC(init,
  53. "Chip initialization level:\n"
  54. " 0: None\n"
  55. "*1: Forcibly enable internal voltage and temperature channels, except in9\n"
  56. " 2: Forcibly enable all voltage and temperature channels, except in9\n"
  57. " 3: Forcibly enable all voltage and temperature channels, including in9");
  58. /*
  59. * Super-I/O registers and operations
  60. */
  61. #define DEV 0x07 /* Register: Logical device select */
  62. #define DEVID 0x20 /* Register: Device ID */
  63. #define ACT 0x30 /* Register: Device activation */
  64. #define BASE 0x60 /* Register: Base address */
  65. #define FSCM 0x09 /* Logical device: fans */
  66. #define VLM 0x0d /* Logical device: voltages */
  67. #define TMS 0x0e /* Logical device: temperatures */
  68. static const u8 logdev[3] = { FSCM, VLM, TMS };
  69. #define LD_FAN 0
  70. #define LD_IN 1
  71. #define LD_TEMP 2
  72. static inline void superio_outb(int sioaddr, int reg, int val)
  73. {
  74. outb(reg, sioaddr);
  75. outb(val, sioaddr+1);
  76. }
  77. static inline int superio_inb(int sioaddr, int reg)
  78. {
  79. outb(reg, sioaddr);
  80. return inb(sioaddr+1);
  81. }
  82. static inline void superio_exit(int sioaddr)
  83. {
  84. outb(0x02, sioaddr);
  85. outb(0x02, sioaddr+1);
  86. }
  87. /*
  88. * Logical devices
  89. */
  90. #define PC87360_EXTENT 0x10
  91. #define PC87365_REG_BANK 0x09
  92. #define NO_BANK 0xff
  93. /*
  94. * Fan registers and conversions
  95. */
  96. /* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */
  97. #define PC87360_REG_PRESCALE(nr) (0x00 + 2 * (nr))
  98. #define PC87360_REG_PWM(nr) (0x01 + 2 * (nr))
  99. #define PC87360_REG_FAN_MIN(nr) (0x06 + 3 * (nr))
  100. #define PC87360_REG_FAN(nr) (0x07 + 3 * (nr))
  101. #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr))
  102. #define FAN_FROM_REG(val,div) ((val) == 0 ? 0: \
  103. 480000 / ((val)*(div)))
  104. #define FAN_TO_REG(val,div) ((val) <= 100 ? 0 : \
  105. 480000 / ((val)*(div)))
  106. #define FAN_DIV_FROM_REG(val) (1 << ((val >> 5) & 0x03))
  107. #define FAN_STATUS_FROM_REG(val) ((val) & 0x07)
  108. #define FAN_CONFIG_MONITOR(val,nr) (((val) >> (2 + nr * 3)) & 1)
  109. #define FAN_CONFIG_CONTROL(val,nr) (((val) >> (3 + nr * 3)) & 1)
  110. #define FAN_CONFIG_INVERT(val,nr) (((val) >> (4 + nr * 3)) & 1)
  111. #define PWM_FROM_REG(val,inv) ((inv) ? 255 - (val) : (val))
  112. static inline u8 PWM_TO_REG(int val, int inv)
  113. {
  114. if (inv)
  115. val = 255 - val;
  116. if (val < 0)
  117. return 0;
  118. if (val > 255)
  119. return 255;
  120. return val;
  121. }
  122. /*
  123. * Voltage registers and conversions
  124. */
  125. #define PC87365_REG_IN_CONVRATE 0x07
  126. #define PC87365_REG_IN_CONFIG 0x08
  127. #define PC87365_REG_IN 0x0B
  128. #define PC87365_REG_IN_MIN 0x0D
  129. #define PC87365_REG_IN_MAX 0x0C
  130. #define PC87365_REG_IN_STATUS 0x0A
  131. #define PC87365_REG_IN_ALARMS1 0x00
  132. #define PC87365_REG_IN_ALARMS2 0x01
  133. #define PC87365_REG_VID 0x06
  134. #define IN_FROM_REG(val,ref) (((val) * (ref) + 128) / 256)
  135. #define IN_TO_REG(val,ref) ((val) < 0 ? 0 : \
  136. (val)*256 >= (ref)*255 ? 255: \
  137. ((val) * 256 + (ref)/2) / (ref))
  138. /*
  139. * Temperature registers and conversions
  140. */
  141. #define PC87365_REG_TEMP_CONFIG 0x08
  142. #define PC87365_REG_TEMP 0x0B
  143. #define PC87365_REG_TEMP_MIN 0x0D
  144. #define PC87365_REG_TEMP_MAX 0x0C
  145. #define PC87365_REG_TEMP_CRIT 0x0E
  146. #define PC87365_REG_TEMP_STATUS 0x0A
  147. #define PC87365_REG_TEMP_ALARMS 0x00
  148. #define TEMP_FROM_REG(val) ((val) * 1000)
  149. #define TEMP_TO_REG(val) ((val) < -55000 ? -55 : \
  150. (val) > 127000 ? 127 : \
  151. (val) < 0 ? ((val) - 500) / 1000 : \
  152. ((val) + 500) / 1000)
  153. /*
  154. * Client data (each client gets its own)
  155. */
  156. struct pc87360_data {
  157. struct i2c_client client;
  158. struct class_device *class_dev;
  159. struct semaphore lock;
  160. struct semaphore update_lock;
  161. char valid; /* !=0 if following fields are valid */
  162. unsigned long last_updated; /* In jiffies */
  163. int address[3];
  164. u8 fannr, innr, tempnr;
  165. u8 fan[3]; /* Register value */
  166. u8 fan_min[3]; /* Register value */
  167. u8 fan_status[3]; /* Register value */
  168. u8 pwm[3]; /* Register value */
  169. u16 fan_conf; /* Configuration register values, combined */
  170. u16 in_vref; /* 1 mV/bit */
  171. u8 in[14]; /* Register value */
  172. u8 in_min[14]; /* Register value */
  173. u8 in_max[14]; /* Register value */
  174. u8 in_crit[3]; /* Register value */
  175. u8 in_status[14]; /* Register value */
  176. u16 in_alarms; /* Register values, combined, masked */
  177. u8 vid_conf; /* Configuration register value */
  178. u8 vrm;
  179. u8 vid; /* Register value */
  180. s8 temp[3]; /* Register value */
  181. s8 temp_min[3]; /* Register value */
  182. s8 temp_max[3]; /* Register value */
  183. s8 temp_crit[3]; /* Register value */
  184. u8 temp_status[3]; /* Register value */
  185. u8 temp_alarms; /* Register value, masked */
  186. };
  187. /*
  188. * Functions declaration
  189. */
  190. static int pc87360_detect(struct i2c_adapter *adapter);
  191. static int pc87360_detach_client(struct i2c_client *client);
  192. static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
  193. u8 reg);
  194. static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
  195. u8 reg, u8 value);
  196. static void pc87360_init_client(struct i2c_client *client, int use_thermistors);
  197. static struct pc87360_data *pc87360_update_device(struct device *dev);
  198. /*
  199. * Driver data (common to all clients)
  200. */
  201. static struct i2c_driver pc87360_driver = {
  202. .owner = THIS_MODULE,
  203. .name = "pc87360",
  204. .attach_adapter = pc87360_detect,
  205. .detach_client = pc87360_detach_client,
  206. };
  207. /*
  208. * Sysfs stuff
  209. */
  210. static ssize_t set_fan_min(struct device *dev, const char *buf,
  211. size_t count, int nr)
  212. {
  213. struct i2c_client *client = to_i2c_client(dev);
  214. struct pc87360_data *data = i2c_get_clientdata(client);
  215. long fan_min = simple_strtol(buf, NULL, 10);
  216. down(&data->update_lock);
  217. fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[nr]));
  218. /* If it wouldn't fit, change clock divisor */
  219. while (fan_min > 255
  220. && (data->fan_status[nr] & 0x60) != 0x60) {
  221. fan_min >>= 1;
  222. data->fan[nr] >>= 1;
  223. data->fan_status[nr] += 0x20;
  224. }
  225. data->fan_min[nr] = fan_min > 255 ? 255 : fan_min;
  226. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(nr),
  227. data->fan_min[nr]);
  228. /* Write new divider, preserve alarm bits */
  229. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(nr),
  230. data->fan_status[nr] & 0xF9);
  231. up(&data->update_lock);
  232. return count;
  233. }
  234. #define show_and_set_fan(offset) \
  235. static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
  236. { \
  237. struct pc87360_data *data = pc87360_update_device(dev); \
  238. return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
  239. FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
  240. } \
  241. static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
  242. { \
  243. struct pc87360_data *data = pc87360_update_device(dev); \
  244. return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
  245. FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
  246. } \
  247. static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
  248. { \
  249. struct pc87360_data *data = pc87360_update_device(dev); \
  250. return sprintf(buf, "%u\n", \
  251. FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
  252. } \
  253. static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
  254. { \
  255. struct pc87360_data *data = pc87360_update_device(dev); \
  256. return sprintf(buf, "%u\n", \
  257. FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
  258. } \
  259. static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
  260. size_t count) \
  261. { \
  262. return set_fan_min(dev, buf, count, offset-1); \
  263. } \
  264. static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
  265. show_fan##offset##_input, NULL); \
  266. static DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
  267. show_fan##offset##_min, set_fan##offset##_min); \
  268. static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
  269. show_fan##offset##_div, NULL); \
  270. static DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
  271. show_fan##offset##_status, NULL);
  272. show_and_set_fan(1)
  273. show_and_set_fan(2)
  274. show_and_set_fan(3)
  275. #define show_and_set_pwm(offset) \
  276. static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
  277. { \
  278. struct pc87360_data *data = pc87360_update_device(dev); \
  279. return sprintf(buf, "%u\n", \
  280. PWM_FROM_REG(data->pwm[offset-1], \
  281. FAN_CONFIG_INVERT(data->fan_conf, \
  282. offset-1))); \
  283. } \
  284. static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
  285. size_t count) \
  286. { \
  287. struct i2c_client *client = to_i2c_client(dev); \
  288. struct pc87360_data *data = i2c_get_clientdata(client); \
  289. long val = simple_strtol(buf, NULL, 10); \
  290. \
  291. down(&data->update_lock); \
  292. data->pwm[offset-1] = PWM_TO_REG(val, \
  293. FAN_CONFIG_INVERT(data->fan_conf, offset-1)); \
  294. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(offset-1), \
  295. data->pwm[offset-1]); \
  296. up(&data->update_lock); \
  297. return count; \
  298. } \
  299. static DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
  300. show_pwm##offset, set_pwm##offset);
  301. show_and_set_pwm(1)
  302. show_and_set_pwm(2)
  303. show_and_set_pwm(3)
  304. #define show_and_set_in(offset) \
  305. static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
  306. { \
  307. struct pc87360_data *data = pc87360_update_device(dev); \
  308. return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
  309. data->in_vref)); \
  310. } \
  311. static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
  312. { \
  313. struct pc87360_data *data = pc87360_update_device(dev); \
  314. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
  315. data->in_vref)); \
  316. } \
  317. static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
  318. { \
  319. struct pc87360_data *data = pc87360_update_device(dev); \
  320. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
  321. data->in_vref)); \
  322. } \
  323. static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
  324. { \
  325. struct pc87360_data *data = pc87360_update_device(dev); \
  326. return sprintf(buf, "%u\n", data->in_status[offset]); \
  327. } \
  328. static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
  329. size_t count) \
  330. { \
  331. struct i2c_client *client = to_i2c_client(dev); \
  332. struct pc87360_data *data = i2c_get_clientdata(client); \
  333. long val = simple_strtol(buf, NULL, 10); \
  334. \
  335. down(&data->update_lock); \
  336. data->in_min[offset] = IN_TO_REG(val, data->in_vref); \
  337. pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MIN, \
  338. data->in_min[offset]); \
  339. up(&data->update_lock); \
  340. return count; \
  341. } \
  342. static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
  343. size_t count) \
  344. { \
  345. struct i2c_client *client = to_i2c_client(dev); \
  346. struct pc87360_data *data = i2c_get_clientdata(client); \
  347. long val = simple_strtol(buf, NULL, 10); \
  348. \
  349. down(&data->update_lock); \
  350. data->in_max[offset] = IN_TO_REG(val, \
  351. data->in_vref); \
  352. pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MAX, \
  353. data->in_max[offset]); \
  354. up(&data->update_lock); \
  355. return count; \
  356. } \
  357. static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
  358. show_in##offset##_input, NULL); \
  359. static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
  360. show_in##offset##_min, set_in##offset##_min); \
  361. static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
  362. show_in##offset##_max, set_in##offset##_max); \
  363. static DEVICE_ATTR(in##offset##_status, S_IRUGO, \
  364. show_in##offset##_status, NULL);
  365. show_and_set_in(0)
  366. show_and_set_in(1)
  367. show_and_set_in(2)
  368. show_and_set_in(3)
  369. show_and_set_in(4)
  370. show_and_set_in(5)
  371. show_and_set_in(6)
  372. show_and_set_in(7)
  373. show_and_set_in(8)
  374. show_and_set_in(9)
  375. show_and_set_in(10)
  376. #define show_and_set_therm(offset) \
  377. static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
  378. { \
  379. struct pc87360_data *data = pc87360_update_device(dev); \
  380. return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
  381. data->in_vref)); \
  382. } \
  383. static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
  384. { \
  385. struct pc87360_data *data = pc87360_update_device(dev); \
  386. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
  387. data->in_vref)); \
  388. } \
  389. static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
  390. { \
  391. struct pc87360_data *data = pc87360_update_device(dev); \
  392. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
  393. data->in_vref)); \
  394. } \
  395. static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
  396. { \
  397. struct pc87360_data *data = pc87360_update_device(dev); \
  398. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
  399. data->in_vref)); \
  400. } \
  401. static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
  402. { \
  403. struct pc87360_data *data = pc87360_update_device(dev); \
  404. return sprintf(buf, "%u\n", data->in_status[offset+7]); \
  405. } \
  406. static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
  407. size_t count) \
  408. { \
  409. struct i2c_client *client = to_i2c_client(dev); \
  410. struct pc87360_data *data = i2c_get_clientdata(client); \
  411. long val = simple_strtol(buf, NULL, 10); \
  412. \
  413. down(&data->update_lock); \
  414. data->in_min[offset+7] = IN_TO_REG(val, data->in_vref); \
  415. pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MIN, \
  416. data->in_min[offset+7]); \
  417. up(&data->update_lock); \
  418. return count; \
  419. } \
  420. static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
  421. size_t count) \
  422. { \
  423. struct i2c_client *client = to_i2c_client(dev); \
  424. struct pc87360_data *data = i2c_get_clientdata(client); \
  425. long val = simple_strtol(buf, NULL, 10); \
  426. \
  427. down(&data->update_lock); \
  428. data->in_max[offset+7] = IN_TO_REG(val, data->in_vref); \
  429. pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MAX, \
  430. data->in_max[offset+7]); \
  431. up(&data->update_lock); \
  432. return count; \
  433. } \
  434. static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
  435. size_t count) \
  436. { \
  437. struct i2c_client *client = to_i2c_client(dev); \
  438. struct pc87360_data *data = i2c_get_clientdata(client); \
  439. long val = simple_strtol(buf, NULL, 10); \
  440. \
  441. down(&data->update_lock); \
  442. data->in_crit[offset-4] = IN_TO_REG(val, data->in_vref); \
  443. pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_CRIT, \
  444. data->in_crit[offset-4]); \
  445. up(&data->update_lock); \
  446. return count; \
  447. } \
  448. static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
  449. show_temp##offset##_input, NULL); \
  450. static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
  451. show_temp##offset##_min, set_temp##offset##_min); \
  452. static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
  453. show_temp##offset##_max, set_temp##offset##_max); \
  454. static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
  455. show_temp##offset##_crit, set_temp##offset##_crit); \
  456. static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
  457. show_temp##offset##_status, NULL);
  458. show_and_set_therm(4)
  459. show_and_set_therm(5)
  460. show_and_set_therm(6)
  461. static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
  462. {
  463. struct pc87360_data *data = pc87360_update_device(dev);
  464. return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
  465. }
  466. static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
  467. static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
  468. {
  469. struct pc87360_data *data = pc87360_update_device(dev);
  470. return sprintf(buf, "%u\n", data->vrm);
  471. }
  472. static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  473. {
  474. struct i2c_client *client = to_i2c_client(dev);
  475. struct pc87360_data *data = i2c_get_clientdata(client);
  476. data->vrm = simple_strtoul(buf, NULL, 10);
  477. return count;
  478. }
  479. static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
  480. static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
  481. {
  482. struct pc87360_data *data = pc87360_update_device(dev);
  483. return sprintf(buf, "%u\n", data->in_alarms);
  484. }
  485. static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
  486. #define show_and_set_temp(offset) \
  487. static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
  488. { \
  489. struct pc87360_data *data = pc87360_update_device(dev); \
  490. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
  491. } \
  492. static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
  493. { \
  494. struct pc87360_data *data = pc87360_update_device(dev); \
  495. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
  496. } \
  497. static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
  498. { \
  499. struct pc87360_data *data = pc87360_update_device(dev); \
  500. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
  501. }\
  502. static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
  503. { \
  504. struct pc87360_data *data = pc87360_update_device(dev); \
  505. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
  506. }\
  507. static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
  508. { \
  509. struct pc87360_data *data = pc87360_update_device(dev); \
  510. return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
  511. }\
  512. static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
  513. size_t count) \
  514. { \
  515. struct i2c_client *client = to_i2c_client(dev); \
  516. struct pc87360_data *data = i2c_get_clientdata(client); \
  517. long val = simple_strtol(buf, NULL, 10); \
  518. \
  519. down(&data->update_lock); \
  520. data->temp_min[offset-1] = TEMP_TO_REG(val); \
  521. pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MIN, \
  522. data->temp_min[offset-1]); \
  523. up(&data->update_lock); \
  524. return count; \
  525. } \
  526. static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
  527. size_t count) \
  528. { \
  529. struct i2c_client *client = to_i2c_client(dev); \
  530. struct pc87360_data *data = i2c_get_clientdata(client); \
  531. long val = simple_strtol(buf, NULL, 10); \
  532. \
  533. down(&data->update_lock); \
  534. data->temp_max[offset-1] = TEMP_TO_REG(val); \
  535. pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MAX, \
  536. data->temp_max[offset-1]); \
  537. up(&data->update_lock); \
  538. return count; \
  539. } \
  540. static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
  541. size_t count) \
  542. { \
  543. struct i2c_client *client = to_i2c_client(dev); \
  544. struct pc87360_data *data = i2c_get_clientdata(client); \
  545. long val = simple_strtol(buf, NULL, 10); \
  546. \
  547. down(&data->update_lock); \
  548. data->temp_crit[offset-1] = TEMP_TO_REG(val); \
  549. pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_CRIT, \
  550. data->temp_crit[offset-1]); \
  551. up(&data->update_lock); \
  552. return count; \
  553. } \
  554. static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
  555. show_temp##offset##_input, NULL); \
  556. static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
  557. show_temp##offset##_min, set_temp##offset##_min); \
  558. static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
  559. show_temp##offset##_max, set_temp##offset##_max); \
  560. static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
  561. show_temp##offset##_crit, set_temp##offset##_crit); \
  562. static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
  563. show_temp##offset##_status, NULL);
  564. show_and_set_temp(1)
  565. show_and_set_temp(2)
  566. show_and_set_temp(3)
  567. static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
  568. {
  569. struct pc87360_data *data = pc87360_update_device(dev);
  570. return sprintf(buf, "%u\n", data->temp_alarms);
  571. }
  572. static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
  573. /*
  574. * Device detection, registration and update
  575. */
  576. static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
  577. {
  578. u16 val;
  579. int i;
  580. int nrdev; /* logical device count */
  581. /* No superio_enter */
  582. /* Identify device */
  583. val = superio_inb(sioaddr, DEVID);
  584. switch (val) {
  585. case 0xE1: /* PC87360 */
  586. case 0xE8: /* PC87363 */
  587. case 0xE4: /* PC87364 */
  588. nrdev = 1;
  589. break;
  590. case 0xE5: /* PC87365 */
  591. case 0xE9: /* PC87366 */
  592. nrdev = 3;
  593. break;
  594. default:
  595. superio_exit(sioaddr);
  596. return -ENODEV;
  597. }
  598. /* Remember the device id */
  599. *devid = val;
  600. for (i = 0; i < nrdev; i++) {
  601. /* select logical device */
  602. superio_outb(sioaddr, DEV, logdev[i]);
  603. val = superio_inb(sioaddr, ACT);
  604. if (!(val & 0x01)) {
  605. printk(KERN_INFO "pc87360: Device 0x%02x not "
  606. "activated\n", logdev[i]);
  607. continue;
  608. }
  609. val = (superio_inb(sioaddr, BASE) << 8)
  610. | superio_inb(sioaddr, BASE + 1);
  611. if (!val) {
  612. printk(KERN_INFO "pc87360: Base address not set for "
  613. "device 0x%02x\n", logdev[i]);
  614. continue;
  615. }
  616. addresses[i] = val;
  617. if (i==0) { /* Fans */
  618. confreg[0] = superio_inb(sioaddr, 0xF0);
  619. confreg[1] = superio_inb(sioaddr, 0xF1);
  620. #ifdef DEBUG
  621. printk(KERN_DEBUG "pc87360: Fan 1: mon=%d "
  622. "ctrl=%d inv=%d\n", (confreg[0]>>2)&1,
  623. (confreg[0]>>3)&1, (confreg[0]>>4)&1);
  624. printk(KERN_DEBUG "pc87360: Fan 2: mon=%d "
  625. "ctrl=%d inv=%d\n", (confreg[0]>>5)&1,
  626. (confreg[0]>>6)&1, (confreg[0]>>7)&1);
  627. printk(KERN_DEBUG "pc87360: Fan 3: mon=%d "
  628. "ctrl=%d inv=%d\n", confreg[1]&1,
  629. (confreg[1]>>1)&1, (confreg[1]>>2)&1);
  630. #endif
  631. } else if (i==1) { /* Voltages */
  632. /* Are we using thermistors? */
  633. if (*devid == 0xE9) { /* PC87366 */
  634. /* These registers are not logical-device
  635. specific, just that we won't need them if
  636. we don't use the VLM device */
  637. confreg[2] = superio_inb(sioaddr, 0x2B);
  638. confreg[3] = superio_inb(sioaddr, 0x25);
  639. if (confreg[2] & 0x40) {
  640. printk(KERN_INFO "pc87360: Using "
  641. "thermistors for temperature "
  642. "monitoring\n");
  643. }
  644. if (confreg[3] & 0xE0) {
  645. printk(KERN_INFO "pc87360: VID "
  646. "inputs routed (mode %u)\n",
  647. confreg[3] >> 5);
  648. }
  649. }
  650. }
  651. }
  652. superio_exit(sioaddr);
  653. return 0;
  654. }
  655. static int pc87360_detect(struct i2c_adapter *adapter)
  656. {
  657. int i;
  658. struct i2c_client *new_client;
  659. struct pc87360_data *data;
  660. int err = 0;
  661. const char *name = "pc87360";
  662. int use_thermistors = 0;
  663. if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
  664. return -ENOMEM;
  665. memset(data, 0x00, sizeof(struct pc87360_data));
  666. new_client = &data->client;
  667. i2c_set_clientdata(new_client, data);
  668. new_client->addr = address;
  669. init_MUTEX(&data->lock);
  670. new_client->adapter = adapter;
  671. new_client->driver = &pc87360_driver;
  672. new_client->flags = 0;
  673. data->fannr = 2;
  674. data->innr = 0;
  675. data->tempnr = 0;
  676. switch (devid) {
  677. case 0xe8:
  678. name = "pc87363";
  679. break;
  680. case 0xe4:
  681. name = "pc87364";
  682. data->fannr = 3;
  683. break;
  684. case 0xe5:
  685. name = "pc87365";
  686. data->fannr = extra_isa[0] ? 3 : 0;
  687. data->innr = extra_isa[1] ? 11 : 0;
  688. data->tempnr = extra_isa[2] ? 2 : 0;
  689. break;
  690. case 0xe9:
  691. name = "pc87366";
  692. data->fannr = extra_isa[0] ? 3 : 0;
  693. data->innr = extra_isa[1] ? 14 : 0;
  694. data->tempnr = extra_isa[2] ? 3 : 0;
  695. break;
  696. }
  697. strcpy(new_client->name, name);
  698. data->valid = 0;
  699. init_MUTEX(&data->update_lock);
  700. for (i = 0; i < 3; i++) {
  701. if (((data->address[i] = extra_isa[i]))
  702. && !request_region(extra_isa[i], PC87360_EXTENT,
  703. pc87360_driver.name)) {
  704. dev_err(&new_client->dev, "Region 0x%x-0x%x already "
  705. "in use!\n", extra_isa[i],
  706. extra_isa[i]+PC87360_EXTENT-1);
  707. for (i--; i >= 0; i--)
  708. release_region(extra_isa[i], PC87360_EXTENT);
  709. err = -EBUSY;
  710. goto ERROR1;
  711. }
  712. }
  713. /* Retrieve the fans configuration from Super-I/O space */
  714. if (data->fannr)
  715. data->fan_conf = confreg[0] | (confreg[1] << 8);
  716. if ((err = i2c_attach_client(new_client)))
  717. goto ERROR2;
  718. /* Use the correct reference voltage
  719. Unless both the VLM and the TMS logical devices agree to
  720. use an external Vref, the internal one is used. */
  721. if (data->innr) {
  722. i = pc87360_read_value(data, LD_IN, NO_BANK,
  723. PC87365_REG_IN_CONFIG);
  724. if (data->tempnr) {
  725. i &= pc87360_read_value(data, LD_TEMP, NO_BANK,
  726. PC87365_REG_TEMP_CONFIG);
  727. }
  728. data->in_vref = (i&0x02) ? 3025 : 2966;
  729. dev_dbg(&new_client->dev, "Using %s reference voltage\n",
  730. (i&0x02) ? "external" : "internal");
  731. data->vid_conf = confreg[3];
  732. data->vrm = 90;
  733. }
  734. /* Fan clock dividers may be needed before any data is read */
  735. for (i = 0; i < data->fannr; i++) {
  736. if (FAN_CONFIG_MONITOR(data->fan_conf, i))
  737. data->fan_status[i] = pc87360_read_value(data,
  738. LD_FAN, NO_BANK,
  739. PC87360_REG_FAN_STATUS(i));
  740. }
  741. if (init > 0) {
  742. if (devid == 0xe9 && data->address[1]) /* PC87366 */
  743. use_thermistors = confreg[2] & 0x40;
  744. pc87360_init_client(new_client, use_thermistors);
  745. }
  746. /* Register sysfs hooks */
  747. data->class_dev = hwmon_device_register(&new_client->dev);
  748. if (IS_ERR(data->class_dev)) {
  749. err = PTR_ERR(data->class_dev);
  750. goto ERROR3;
  751. }
  752. if (data->innr) {
  753. device_create_file(&new_client->dev, &dev_attr_in0_input);
  754. device_create_file(&new_client->dev, &dev_attr_in1_input);
  755. device_create_file(&new_client->dev, &dev_attr_in2_input);
  756. device_create_file(&new_client->dev, &dev_attr_in3_input);
  757. device_create_file(&new_client->dev, &dev_attr_in4_input);
  758. device_create_file(&new_client->dev, &dev_attr_in5_input);
  759. device_create_file(&new_client->dev, &dev_attr_in6_input);
  760. device_create_file(&new_client->dev, &dev_attr_in7_input);
  761. device_create_file(&new_client->dev, &dev_attr_in8_input);
  762. device_create_file(&new_client->dev, &dev_attr_in9_input);
  763. device_create_file(&new_client->dev, &dev_attr_in10_input);
  764. device_create_file(&new_client->dev, &dev_attr_in0_min);
  765. device_create_file(&new_client->dev, &dev_attr_in1_min);
  766. device_create_file(&new_client->dev, &dev_attr_in2_min);
  767. device_create_file(&new_client->dev, &dev_attr_in3_min);
  768. device_create_file(&new_client->dev, &dev_attr_in4_min);
  769. device_create_file(&new_client->dev, &dev_attr_in5_min);
  770. device_create_file(&new_client->dev, &dev_attr_in6_min);
  771. device_create_file(&new_client->dev, &dev_attr_in7_min);
  772. device_create_file(&new_client->dev, &dev_attr_in8_min);
  773. device_create_file(&new_client->dev, &dev_attr_in9_min);
  774. device_create_file(&new_client->dev, &dev_attr_in10_min);
  775. device_create_file(&new_client->dev, &dev_attr_in0_max);
  776. device_create_file(&new_client->dev, &dev_attr_in1_max);
  777. device_create_file(&new_client->dev, &dev_attr_in2_max);
  778. device_create_file(&new_client->dev, &dev_attr_in3_max);
  779. device_create_file(&new_client->dev, &dev_attr_in4_max);
  780. device_create_file(&new_client->dev, &dev_attr_in5_max);
  781. device_create_file(&new_client->dev, &dev_attr_in6_max);
  782. device_create_file(&new_client->dev, &dev_attr_in7_max);
  783. device_create_file(&new_client->dev, &dev_attr_in8_max);
  784. device_create_file(&new_client->dev, &dev_attr_in9_max);
  785. device_create_file(&new_client->dev, &dev_attr_in10_max);
  786. device_create_file(&new_client->dev, &dev_attr_in0_status);
  787. device_create_file(&new_client->dev, &dev_attr_in1_status);
  788. device_create_file(&new_client->dev, &dev_attr_in2_status);
  789. device_create_file(&new_client->dev, &dev_attr_in3_status);
  790. device_create_file(&new_client->dev, &dev_attr_in4_status);
  791. device_create_file(&new_client->dev, &dev_attr_in5_status);
  792. device_create_file(&new_client->dev, &dev_attr_in6_status);
  793. device_create_file(&new_client->dev, &dev_attr_in7_status);
  794. device_create_file(&new_client->dev, &dev_attr_in8_status);
  795. device_create_file(&new_client->dev, &dev_attr_in9_status);
  796. device_create_file(&new_client->dev, &dev_attr_in10_status);
  797. device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
  798. device_create_file(&new_client->dev, &dev_attr_vrm);
  799. device_create_file(&new_client->dev, &dev_attr_alarms_in);
  800. }
  801. if (data->tempnr) {
  802. device_create_file(&new_client->dev, &dev_attr_temp1_input);
  803. device_create_file(&new_client->dev, &dev_attr_temp2_input);
  804. device_create_file(&new_client->dev, &dev_attr_temp1_min);
  805. device_create_file(&new_client->dev, &dev_attr_temp2_min);
  806. device_create_file(&new_client->dev, &dev_attr_temp1_max);
  807. device_create_file(&new_client->dev, &dev_attr_temp2_max);
  808. device_create_file(&new_client->dev, &dev_attr_temp1_crit);
  809. device_create_file(&new_client->dev, &dev_attr_temp2_crit);
  810. device_create_file(&new_client->dev, &dev_attr_temp1_status);
  811. device_create_file(&new_client->dev, &dev_attr_temp2_status);
  812. device_create_file(&new_client->dev, &dev_attr_alarms_temp);
  813. }
  814. if (data->tempnr == 3) {
  815. device_create_file(&new_client->dev, &dev_attr_temp3_input);
  816. device_create_file(&new_client->dev, &dev_attr_temp3_min);
  817. device_create_file(&new_client->dev, &dev_attr_temp3_max);
  818. device_create_file(&new_client->dev, &dev_attr_temp3_crit);
  819. device_create_file(&new_client->dev, &dev_attr_temp3_status);
  820. }
  821. if (data->innr == 14) {
  822. device_create_file(&new_client->dev, &dev_attr_temp4_input);
  823. device_create_file(&new_client->dev, &dev_attr_temp5_input);
  824. device_create_file(&new_client->dev, &dev_attr_temp6_input);
  825. device_create_file(&new_client->dev, &dev_attr_temp4_min);
  826. device_create_file(&new_client->dev, &dev_attr_temp5_min);
  827. device_create_file(&new_client->dev, &dev_attr_temp6_min);
  828. device_create_file(&new_client->dev, &dev_attr_temp4_max);
  829. device_create_file(&new_client->dev, &dev_attr_temp5_max);
  830. device_create_file(&new_client->dev, &dev_attr_temp6_max);
  831. device_create_file(&new_client->dev, &dev_attr_temp4_crit);
  832. device_create_file(&new_client->dev, &dev_attr_temp5_crit);
  833. device_create_file(&new_client->dev, &dev_attr_temp6_crit);
  834. device_create_file(&new_client->dev, &dev_attr_temp4_status);
  835. device_create_file(&new_client->dev, &dev_attr_temp5_status);
  836. device_create_file(&new_client->dev, &dev_attr_temp6_status);
  837. }
  838. if (data->fannr) {
  839. if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) {
  840. device_create_file(&new_client->dev,
  841. &dev_attr_fan1_input);
  842. device_create_file(&new_client->dev,
  843. &dev_attr_fan1_min);
  844. device_create_file(&new_client->dev,
  845. &dev_attr_fan1_div);
  846. device_create_file(&new_client->dev,
  847. &dev_attr_fan1_status);
  848. }
  849. if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) {
  850. device_create_file(&new_client->dev,
  851. &dev_attr_fan2_input);
  852. device_create_file(&new_client->dev,
  853. &dev_attr_fan2_min);
  854. device_create_file(&new_client->dev,
  855. &dev_attr_fan2_div);
  856. device_create_file(&new_client->dev,
  857. &dev_attr_fan2_status);
  858. }
  859. if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
  860. device_create_file(&new_client->dev, &dev_attr_pwm1);
  861. if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
  862. device_create_file(&new_client->dev, &dev_attr_pwm2);
  863. }
  864. if (data->fannr == 3) {
  865. if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
  866. device_create_file(&new_client->dev,
  867. &dev_attr_fan3_input);
  868. device_create_file(&new_client->dev,
  869. &dev_attr_fan3_min);
  870. device_create_file(&new_client->dev,
  871. &dev_attr_fan3_div);
  872. device_create_file(&new_client->dev,
  873. &dev_attr_fan3_status);
  874. }
  875. if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
  876. device_create_file(&new_client->dev, &dev_attr_pwm3);
  877. }
  878. return 0;
  879. ERROR3:
  880. i2c_detach_client(new_client);
  881. ERROR2:
  882. for (i = 0; i < 3; i++) {
  883. if (data->address[i]) {
  884. release_region(data->address[i], PC87360_EXTENT);
  885. }
  886. }
  887. ERROR1:
  888. kfree(data);
  889. return err;
  890. }
  891. static int pc87360_detach_client(struct i2c_client *client)
  892. {
  893. struct pc87360_data *data = i2c_get_clientdata(client);
  894. int i;
  895. hwmon_device_unregister(data->class_dev);
  896. if ((i = i2c_detach_client(client)))
  897. return i;
  898. for (i = 0; i < 3; i++) {
  899. if (data->address[i]) {
  900. release_region(data->address[i], PC87360_EXTENT);
  901. }
  902. }
  903. kfree(data);
  904. return 0;
  905. }
  906. /* ldi is the logical device index
  907. bank is for voltages and temperatures only */
  908. static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
  909. u8 reg)
  910. {
  911. int res;
  912. down(&(data->lock));
  913. if (bank != NO_BANK)
  914. outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
  915. res = inb_p(data->address[ldi] + reg);
  916. up(&(data->lock));
  917. return res;
  918. }
  919. static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
  920. u8 reg, u8 value)
  921. {
  922. down(&(data->lock));
  923. if (bank != NO_BANK)
  924. outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
  925. outb_p(value, data->address[ldi] + reg);
  926. up(&(data->lock));
  927. }
  928. static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
  929. {
  930. struct pc87360_data *data = i2c_get_clientdata(client);
  931. int i, nr;
  932. const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 };
  933. const u8 init_temp[3] = { 2, 2, 1 };
  934. u8 reg;
  935. if (init >= 2 && data->innr) {
  936. reg = pc87360_read_value(data, LD_IN, NO_BANK,
  937. PC87365_REG_IN_CONVRATE);
  938. dev_info(&client->dev, "VLM conversion set to "
  939. "1s period, 160us delay\n");
  940. pc87360_write_value(data, LD_IN, NO_BANK,
  941. PC87365_REG_IN_CONVRATE,
  942. (reg & 0xC0) | 0x11);
  943. }
  944. nr = data->innr < 11 ? data->innr : 11;
  945. for (i=0; i<nr; i++) {
  946. if (init >= init_in[i]) {
  947. /* Forcibly enable voltage channel */
  948. reg = pc87360_read_value(data, LD_IN, i,
  949. PC87365_REG_IN_STATUS);
  950. if (!(reg & 0x01)) {
  951. dev_dbg(&client->dev, "Forcibly "
  952. "enabling in%d\n", i);
  953. pc87360_write_value(data, LD_IN, i,
  954. PC87365_REG_IN_STATUS,
  955. (reg & 0x68) | 0x87);
  956. }
  957. }
  958. }
  959. /* We can't blindly trust the Super-I/O space configuration bit,
  960. most BIOS won't set it properly */
  961. for (i=11; i<data->innr; i++) {
  962. reg = pc87360_read_value(data, LD_IN, i,
  963. PC87365_REG_TEMP_STATUS);
  964. use_thermistors = use_thermistors || (reg & 0x01);
  965. }
  966. i = use_thermistors ? 2 : 0;
  967. for (; i<data->tempnr; i++) {
  968. if (init >= init_temp[i]) {
  969. /* Forcibly enable temperature channel */
  970. reg = pc87360_read_value(data, LD_TEMP, i,
  971. PC87365_REG_TEMP_STATUS);
  972. if (!(reg & 0x01)) {
  973. dev_dbg(&client->dev, "Forcibly "
  974. "enabling temp%d\n", i+1);
  975. pc87360_write_value(data, LD_TEMP, i,
  976. PC87365_REG_TEMP_STATUS,
  977. 0xCF);
  978. }
  979. }
  980. }
  981. if (use_thermistors) {
  982. for (i=11; i<data->innr; i++) {
  983. if (init >= init_in[i]) {
  984. /* The pin may already be used by thermal
  985. diodes */
  986. reg = pc87360_read_value(data, LD_TEMP,
  987. (i-11)/2, PC87365_REG_TEMP_STATUS);
  988. if (reg & 0x01) {
  989. dev_dbg(&client->dev, "Skipping "
  990. "temp%d, pin already in use "
  991. "by temp%d\n", i-7, (i-11)/2);
  992. continue;
  993. }
  994. /* Forcibly enable thermistor channel */
  995. reg = pc87360_read_value(data, LD_IN, i,
  996. PC87365_REG_IN_STATUS);
  997. if (!(reg & 0x01)) {
  998. dev_dbg(&client->dev, "Forcibly "
  999. "enabling temp%d\n", i-7);
  1000. pc87360_write_value(data, LD_IN, i,
  1001. PC87365_REG_TEMP_STATUS,
  1002. (reg & 0x60) | 0x8F);
  1003. }
  1004. }
  1005. }
  1006. }
  1007. if (data->innr) {
  1008. reg = pc87360_read_value(data, LD_IN, NO_BANK,
  1009. PC87365_REG_IN_CONFIG);
  1010. if (reg & 0x01) {
  1011. dev_dbg(&client->dev, "Forcibly "
  1012. "enabling monitoring (VLM)\n");
  1013. pc87360_write_value(data, LD_IN, NO_BANK,
  1014. PC87365_REG_IN_CONFIG,
  1015. reg & 0xFE);
  1016. }
  1017. }
  1018. if (data->tempnr) {
  1019. reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
  1020. PC87365_REG_TEMP_CONFIG);
  1021. if (reg & 0x01) {
  1022. dev_dbg(&client->dev, "Forcibly enabling "
  1023. "monitoring (TMS)\n");
  1024. pc87360_write_value(data, LD_TEMP, NO_BANK,
  1025. PC87365_REG_TEMP_CONFIG,
  1026. reg & 0xFE);
  1027. }
  1028. if (init >= 2) {
  1029. /* Chip config as documented by National Semi. */
  1030. pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08);
  1031. /* We voluntarily omit the bank here, in case the
  1032. sequence itself matters. It shouldn't be a problem,
  1033. since nobody else is supposed to access the
  1034. device at that point. */
  1035. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04);
  1036. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35);
  1037. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05);
  1038. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xE, 0x05);
  1039. }
  1040. }
  1041. }
  1042. static void pc87360_autodiv(struct i2c_client *client, int nr)
  1043. {
  1044. struct pc87360_data *data = i2c_get_clientdata(client);
  1045. u8 old_min = data->fan_min[nr];
  1046. /* Increase clock divider if needed and possible */
  1047. if ((data->fan_status[nr] & 0x04) /* overflow flag */
  1048. || (data->fan[nr] >= 224)) { /* next to overflow */
  1049. if ((data->fan_status[nr] & 0x60) != 0x60) {
  1050. data->fan_status[nr] += 0x20;
  1051. data->fan_min[nr] >>= 1;
  1052. data->fan[nr] >>= 1;
  1053. dev_dbg(&client->dev, "Increasing "
  1054. "clock divider to %d for fan %d\n",
  1055. FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1);
  1056. }
  1057. } else {
  1058. /* Decrease clock divider if possible */
  1059. while (!(data->fan_min[nr] & 0x80) /* min "nails" divider */
  1060. && data->fan[nr] < 85 /* bad accuracy */
  1061. && (data->fan_status[nr] & 0x60) != 0x00) {
  1062. data->fan_status[nr] -= 0x20;
  1063. data->fan_min[nr] <<= 1;
  1064. data->fan[nr] <<= 1;
  1065. dev_dbg(&client->dev, "Decreasing "
  1066. "clock divider to %d for fan %d\n",
  1067. FAN_DIV_FROM_REG(data->fan_status[nr]),
  1068. nr+1);
  1069. }
  1070. }
  1071. /* Write new fan min if it changed */
  1072. if (old_min != data->fan_min[nr]) {
  1073. pc87360_write_value(data, LD_FAN, NO_BANK,
  1074. PC87360_REG_FAN_MIN(nr),
  1075. data->fan_min[nr]);
  1076. }
  1077. }
  1078. static struct pc87360_data *pc87360_update_device(struct device *dev)
  1079. {
  1080. struct i2c_client *client = to_i2c_client(dev);
  1081. struct pc87360_data *data = i2c_get_clientdata(client);
  1082. u8 i;
  1083. down(&data->update_lock);
  1084. if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
  1085. dev_dbg(&client->dev, "Data update\n");
  1086. /* Fans */
  1087. for (i = 0; i < data->fannr; i++) {
  1088. if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
  1089. data->fan_status[i] =
  1090. pc87360_read_value(data, LD_FAN,
  1091. NO_BANK, PC87360_REG_FAN_STATUS(i));
  1092. data->fan[i] = pc87360_read_value(data, LD_FAN,
  1093. NO_BANK, PC87360_REG_FAN(i));
  1094. data->fan_min[i] = pc87360_read_value(data,
  1095. LD_FAN, NO_BANK,
  1096. PC87360_REG_FAN_MIN(i));
  1097. /* Change clock divider if needed */
  1098. pc87360_autodiv(client, i);
  1099. /* Clear bits and write new divider */
  1100. pc87360_write_value(data, LD_FAN, NO_BANK,
  1101. PC87360_REG_FAN_STATUS(i),
  1102. data->fan_status[i]);
  1103. }
  1104. if (FAN_CONFIG_CONTROL(data->fan_conf, i))
  1105. data->pwm[i] = pc87360_read_value(data, LD_FAN,
  1106. NO_BANK, PC87360_REG_PWM(i));
  1107. }
  1108. /* Voltages */
  1109. for (i = 0; i < data->innr; i++) {
  1110. data->in_status[i] = pc87360_read_value(data, LD_IN, i,
  1111. PC87365_REG_IN_STATUS);
  1112. /* Clear bits */
  1113. pc87360_write_value(data, LD_IN, i,
  1114. PC87365_REG_IN_STATUS,
  1115. data->in_status[i]);
  1116. if ((data->in_status[i] & 0x81) == 0x81) {
  1117. data->in[i] = pc87360_read_value(data, LD_IN,
  1118. i, PC87365_REG_IN);
  1119. }
  1120. if (data->in_status[i] & 0x01) {
  1121. data->in_min[i] = pc87360_read_value(data,
  1122. LD_IN, i,
  1123. PC87365_REG_IN_MIN);
  1124. data->in_max[i] = pc87360_read_value(data,
  1125. LD_IN, i,
  1126. PC87365_REG_IN_MAX);
  1127. if (i >= 11)
  1128. data->in_crit[i-11] =
  1129. pc87360_read_value(data, LD_IN,
  1130. i, PC87365_REG_TEMP_CRIT);
  1131. }
  1132. }
  1133. if (data->innr) {
  1134. data->in_alarms = pc87360_read_value(data, LD_IN,
  1135. NO_BANK, PC87365_REG_IN_ALARMS1)
  1136. | ((pc87360_read_value(data, LD_IN,
  1137. NO_BANK, PC87365_REG_IN_ALARMS2)
  1138. & 0x07) << 8);
  1139. data->vid = (data->vid_conf & 0xE0) ?
  1140. pc87360_read_value(data, LD_IN,
  1141. NO_BANK, PC87365_REG_VID) : 0x1F;
  1142. }
  1143. /* Temperatures */
  1144. for (i = 0; i < data->tempnr; i++) {
  1145. data->temp_status[i] = pc87360_read_value(data,
  1146. LD_TEMP, i,
  1147. PC87365_REG_TEMP_STATUS);
  1148. /* Clear bits */
  1149. pc87360_write_value(data, LD_TEMP, i,
  1150. PC87365_REG_TEMP_STATUS,
  1151. data->temp_status[i]);
  1152. if ((data->temp_status[i] & 0x81) == 0x81) {
  1153. data->temp[i] = pc87360_read_value(data,
  1154. LD_TEMP, i,
  1155. PC87365_REG_TEMP);
  1156. }
  1157. if (data->temp_status[i] & 0x01) {
  1158. data->temp_min[i] = pc87360_read_value(data,
  1159. LD_TEMP, i,
  1160. PC87365_REG_TEMP_MIN);
  1161. data->temp_max[i] = pc87360_read_value(data,
  1162. LD_TEMP, i,
  1163. PC87365_REG_TEMP_MAX);
  1164. data->temp_crit[i] = pc87360_read_value(data,
  1165. LD_TEMP, i,
  1166. PC87365_REG_TEMP_CRIT);
  1167. }
  1168. }
  1169. if (data->tempnr) {
  1170. data->temp_alarms = pc87360_read_value(data, LD_TEMP,
  1171. NO_BANK, PC87365_REG_TEMP_ALARMS)
  1172. & 0x3F;
  1173. }
  1174. data->last_updated = jiffies;
  1175. data->valid = 1;
  1176. }
  1177. up(&data->update_lock);
  1178. return data;
  1179. }
  1180. static int __init pc87360_init(void)
  1181. {
  1182. int i;
  1183. if (pc87360_find(0x2e, &devid, extra_isa)
  1184. && pc87360_find(0x4e, &devid, extra_isa)) {
  1185. printk(KERN_WARNING "pc87360: PC8736x not detected, "
  1186. "module not inserted.\n");
  1187. return -ENODEV;
  1188. }
  1189. /* Arbitrarily pick one of the addresses */
  1190. for (i = 0; i < 3; i++) {
  1191. if (extra_isa[i] != 0x0000) {
  1192. address = extra_isa[i];
  1193. break;
  1194. }
  1195. }
  1196. if (address == 0x0000) {
  1197. printk(KERN_WARNING "pc87360: No active logical device, "
  1198. "module not inserted.\n");
  1199. return -ENODEV;
  1200. }
  1201. return i2c_isa_add_driver(&pc87360_driver);
  1202. }
  1203. static void __exit pc87360_exit(void)
  1204. {
  1205. i2c_isa_del_driver(&pc87360_driver);
  1206. }
  1207. MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
  1208. MODULE_DESCRIPTION("PC8736x hardware monitor");
  1209. MODULE_LICENSE("GPL");
  1210. module_init(pc87360_init);
  1211. module_exit(pc87360_exit);