pc87360.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  1. /*
  2. * pc87360.c - Part of lm_sensors, Linux kernel modules
  3. * for hardware monitoring
  4. * Copyright (C) 2004, 2007 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/platform_device.h>
  40. #include <linux/hwmon.h>
  41. #include <linux/hwmon-sysfs.h>
  42. #include <linux/hwmon-vid.h>
  43. #include <linux/err.h>
  44. #include <linux/mutex.h>
  45. #include <asm/io.h>
  46. static u8 devid;
  47. static struct platform_device *pdev;
  48. static unsigned short extra_isa[3];
  49. static u8 confreg[4];
  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. static unsigned short force_id;
  59. module_param(force_id, ushort, 0);
  60. MODULE_PARM_DESC(force_id, "Override the detected device ID");
  61. /*
  62. * Super-I/O registers and operations
  63. */
  64. #define DEV 0x07 /* Register: Logical device select */
  65. #define DEVID 0x20 /* Register: Device ID */
  66. #define ACT 0x30 /* Register: Device activation */
  67. #define BASE 0x60 /* Register: Base address */
  68. #define FSCM 0x09 /* Logical device: fans */
  69. #define VLM 0x0d /* Logical device: voltages */
  70. #define TMS 0x0e /* Logical device: temperatures */
  71. static const u8 logdev[3] = { FSCM, VLM, TMS };
  72. #define LD_FAN 0
  73. #define LD_IN 1
  74. #define LD_TEMP 2
  75. static inline void superio_outb(int sioaddr, int reg, int val)
  76. {
  77. outb(reg, sioaddr);
  78. outb(val, sioaddr+1);
  79. }
  80. static inline int superio_inb(int sioaddr, int reg)
  81. {
  82. outb(reg, sioaddr);
  83. return inb(sioaddr+1);
  84. }
  85. static inline void superio_exit(int sioaddr)
  86. {
  87. outb(0x02, sioaddr);
  88. outb(0x02, sioaddr+1);
  89. }
  90. /*
  91. * Logical devices
  92. */
  93. #define PC87360_EXTENT 0x10
  94. #define PC87365_REG_BANK 0x09
  95. #define NO_BANK 0xff
  96. /*
  97. * Fan registers and conversions
  98. */
  99. /* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */
  100. #define PC87360_REG_PRESCALE(nr) (0x00 + 2 * (nr))
  101. #define PC87360_REG_PWM(nr) (0x01 + 2 * (nr))
  102. #define PC87360_REG_FAN_MIN(nr) (0x06 + 3 * (nr))
  103. #define PC87360_REG_FAN(nr) (0x07 + 3 * (nr))
  104. #define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr))
  105. #define FAN_FROM_REG(val,div) ((val) == 0 ? 0: \
  106. 480000 / ((val)*(div)))
  107. #define FAN_TO_REG(val,div) ((val) <= 100 ? 0 : \
  108. 480000 / ((val)*(div)))
  109. #define FAN_DIV_FROM_REG(val) (1 << ((val >> 5) & 0x03))
  110. #define FAN_STATUS_FROM_REG(val) ((val) & 0x07)
  111. #define FAN_CONFIG_MONITOR(val,nr) (((val) >> (2 + nr * 3)) & 1)
  112. #define FAN_CONFIG_CONTROL(val,nr) (((val) >> (3 + nr * 3)) & 1)
  113. #define FAN_CONFIG_INVERT(val,nr) (((val) >> (4 + nr * 3)) & 1)
  114. #define PWM_FROM_REG(val,inv) ((inv) ? 255 - (val) : (val))
  115. static inline u8 PWM_TO_REG(int val, int inv)
  116. {
  117. if (inv)
  118. val = 255 - val;
  119. if (val < 0)
  120. return 0;
  121. if (val > 255)
  122. return 255;
  123. return val;
  124. }
  125. /*
  126. * Voltage registers and conversions
  127. */
  128. #define PC87365_REG_IN_CONVRATE 0x07
  129. #define PC87365_REG_IN_CONFIG 0x08
  130. #define PC87365_REG_IN 0x0B
  131. #define PC87365_REG_IN_MIN 0x0D
  132. #define PC87365_REG_IN_MAX 0x0C
  133. #define PC87365_REG_IN_STATUS 0x0A
  134. #define PC87365_REG_IN_ALARMS1 0x00
  135. #define PC87365_REG_IN_ALARMS2 0x01
  136. #define PC87365_REG_VID 0x06
  137. #define IN_FROM_REG(val,ref) (((val) * (ref) + 128) / 256)
  138. #define IN_TO_REG(val,ref) ((val) < 0 ? 0 : \
  139. (val)*256 >= (ref)*255 ? 255: \
  140. ((val) * 256 + (ref)/2) / (ref))
  141. /*
  142. * Temperature registers and conversions
  143. */
  144. #define PC87365_REG_TEMP_CONFIG 0x08
  145. #define PC87365_REG_TEMP 0x0B
  146. #define PC87365_REG_TEMP_MIN 0x0D
  147. #define PC87365_REG_TEMP_MAX 0x0C
  148. #define PC87365_REG_TEMP_CRIT 0x0E
  149. #define PC87365_REG_TEMP_STATUS 0x0A
  150. #define PC87365_REG_TEMP_ALARMS 0x00
  151. #define TEMP_FROM_REG(val) ((val) * 1000)
  152. #define TEMP_TO_REG(val) ((val) < -55000 ? -55 : \
  153. (val) > 127000 ? 127 : \
  154. (val) < 0 ? ((val) - 500) / 1000 : \
  155. ((val) + 500) / 1000)
  156. /*
  157. * Device data
  158. */
  159. struct pc87360_data {
  160. const char *name;
  161. struct device *hwmon_dev;
  162. struct mutex lock;
  163. struct mutex update_lock;
  164. char valid; /* !=0 if following fields are valid */
  165. unsigned long last_updated; /* In jiffies */
  166. int address[3];
  167. u8 fannr, innr, tempnr;
  168. u8 fan[3]; /* Register value */
  169. u8 fan_min[3]; /* Register value */
  170. u8 fan_status[3]; /* Register value */
  171. u8 pwm[3]; /* Register value */
  172. u16 fan_conf; /* Configuration register values, combined */
  173. u16 in_vref; /* 1 mV/bit */
  174. u8 in[14]; /* Register value */
  175. u8 in_min[14]; /* Register value */
  176. u8 in_max[14]; /* Register value */
  177. u8 in_crit[3]; /* Register value */
  178. u8 in_status[14]; /* Register value */
  179. u16 in_alarms; /* Register values, combined, masked */
  180. u8 vid_conf; /* Configuration register value */
  181. u8 vrm;
  182. u8 vid; /* Register value */
  183. s8 temp[3]; /* Register value */
  184. s8 temp_min[3]; /* Register value */
  185. s8 temp_max[3]; /* Register value */
  186. s8 temp_crit[3]; /* Register value */
  187. u8 temp_status[3]; /* Register value */
  188. u8 temp_alarms; /* Register value, masked */
  189. };
  190. /*
  191. * Functions declaration
  192. */
  193. static int pc87360_probe(struct platform_device *pdev);
  194. static int __devexit pc87360_remove(struct platform_device *pdev);
  195. static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
  196. u8 reg);
  197. static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
  198. u8 reg, u8 value);
  199. static void pc87360_init_device(struct platform_device *pdev,
  200. int use_thermistors);
  201. static struct pc87360_data *pc87360_update_device(struct device *dev);
  202. /*
  203. * Driver data
  204. */
  205. static struct platform_driver pc87360_driver = {
  206. .driver = {
  207. .owner = THIS_MODULE,
  208. .name = "pc87360",
  209. },
  210. .probe = pc87360_probe,
  211. .remove = __devexit_p(pc87360_remove),
  212. };
  213. /*
  214. * Sysfs stuff
  215. */
  216. static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
  217. {
  218. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  219. struct pc87360_data *data = pc87360_update_device(dev);
  220. return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
  221. FAN_DIV_FROM_REG(data->fan_status[attr->index])));
  222. }
  223. static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
  224. {
  225. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  226. struct pc87360_data *data = pc87360_update_device(dev);
  227. return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
  228. FAN_DIV_FROM_REG(data->fan_status[attr->index])));
  229. }
  230. static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
  231. {
  232. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  233. struct pc87360_data *data = pc87360_update_device(dev);
  234. return sprintf(buf, "%u\n",
  235. FAN_DIV_FROM_REG(data->fan_status[attr->index]));
  236. }
  237. static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf)
  238. {
  239. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  240. struct pc87360_data *data = pc87360_update_device(dev);
  241. return sprintf(buf, "%u\n",
  242. FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
  243. }
  244. static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf,
  245. size_t count)
  246. {
  247. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  248. struct pc87360_data *data = dev_get_drvdata(dev);
  249. long fan_min = simple_strtol(buf, NULL, 10);
  250. mutex_lock(&data->update_lock);
  251. fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
  252. /* If it wouldn't fit, change clock divisor */
  253. while (fan_min > 255
  254. && (data->fan_status[attr->index] & 0x60) != 0x60) {
  255. fan_min >>= 1;
  256. data->fan[attr->index] >>= 1;
  257. data->fan_status[attr->index] += 0x20;
  258. }
  259. data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
  260. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index),
  261. data->fan_min[attr->index]);
  262. /* Write new divider, preserve alarm bits */
  263. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
  264. data->fan_status[attr->index] & 0xF9);
  265. mutex_unlock(&data->update_lock);
  266. return count;
  267. }
  268. static struct sensor_device_attribute fan_input[] = {
  269. SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0),
  270. SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1),
  271. SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2),
  272. };
  273. static struct sensor_device_attribute fan_status[] = {
  274. SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0),
  275. SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1),
  276. SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2),
  277. };
  278. static struct sensor_device_attribute fan_div[] = {
  279. SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
  280. SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
  281. SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
  282. };
  283. static struct sensor_device_attribute fan_min[] = {
  284. SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0),
  285. SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1),
  286. SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
  287. };
  288. #define FAN_UNIT_ATTRS(X) \
  289. &fan_input[X].dev_attr.attr, \
  290. &fan_status[X].dev_attr.attr, \
  291. &fan_div[X].dev_attr.attr, \
  292. &fan_min[X].dev_attr.attr
  293. static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
  294. {
  295. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  296. struct pc87360_data *data = pc87360_update_device(dev);
  297. return sprintf(buf, "%u\n",
  298. PWM_FROM_REG(data->pwm[attr->index],
  299. FAN_CONFIG_INVERT(data->fan_conf,
  300. attr->index)));
  301. }
  302. static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf,
  303. size_t count)
  304. {
  305. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  306. struct pc87360_data *data = dev_get_drvdata(dev);
  307. long val = simple_strtol(buf, NULL, 10);
  308. mutex_lock(&data->update_lock);
  309. data->pwm[attr->index] = PWM_TO_REG(val,
  310. FAN_CONFIG_INVERT(data->fan_conf, attr->index));
  311. pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
  312. data->pwm[attr->index]);
  313. mutex_unlock(&data->update_lock);
  314. return count;
  315. }
  316. static struct sensor_device_attribute pwm[] = {
  317. SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0),
  318. SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1),
  319. SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
  320. };
  321. static struct attribute * pc8736x_fan_attr_array[] = {
  322. FAN_UNIT_ATTRS(0),
  323. FAN_UNIT_ATTRS(1),
  324. FAN_UNIT_ATTRS(2),
  325. &pwm[0].dev_attr.attr,
  326. &pwm[1].dev_attr.attr,
  327. &pwm[2].dev_attr.attr,
  328. NULL
  329. };
  330. static const struct attribute_group pc8736x_fan_group = {
  331. .attrs = pc8736x_fan_attr_array,
  332. };
  333. static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
  334. {
  335. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  336. struct pc87360_data *data = pc87360_update_device(dev);
  337. return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
  338. data->in_vref));
  339. }
  340. static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
  341. {
  342. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  343. struct pc87360_data *data = pc87360_update_device(dev);
  344. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
  345. data->in_vref));
  346. }
  347. static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
  348. {
  349. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  350. struct pc87360_data *data = pc87360_update_device(dev);
  351. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
  352. data->in_vref));
  353. }
  354. static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf)
  355. {
  356. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  357. struct pc87360_data *data = pc87360_update_device(dev);
  358. return sprintf(buf, "%u\n", data->in_status[attr->index]);
  359. }
  360. static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf,
  361. size_t count)
  362. {
  363. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  364. struct pc87360_data *data = dev_get_drvdata(dev);
  365. long val = simple_strtol(buf, NULL, 10);
  366. mutex_lock(&data->update_lock);
  367. data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
  368. pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
  369. data->in_min[attr->index]);
  370. mutex_unlock(&data->update_lock);
  371. return count;
  372. }
  373. static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
  374. size_t count)
  375. {
  376. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  377. struct pc87360_data *data = dev_get_drvdata(dev);
  378. long val = simple_strtol(buf, NULL, 10);
  379. mutex_lock(&data->update_lock);
  380. data->in_max[attr->index] = IN_TO_REG(val,
  381. data->in_vref);
  382. pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
  383. data->in_max[attr->index]);
  384. mutex_unlock(&data->update_lock);
  385. return count;
  386. }
  387. static struct sensor_device_attribute in_input[] = {
  388. SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0),
  389. SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1),
  390. SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2),
  391. SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3),
  392. SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4),
  393. SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5),
  394. SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6),
  395. SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7),
  396. SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8),
  397. SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9),
  398. SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10),
  399. };
  400. static struct sensor_device_attribute in_status[] = {
  401. SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0),
  402. SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1),
  403. SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2),
  404. SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3),
  405. SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4),
  406. SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5),
  407. SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6),
  408. SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7),
  409. SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8),
  410. SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9),
  411. SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10),
  412. };
  413. static struct sensor_device_attribute in_min[] = {
  414. SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0),
  415. SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1),
  416. SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2),
  417. SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3),
  418. SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4),
  419. SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5),
  420. SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6),
  421. SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7),
  422. SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8),
  423. SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9),
  424. SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10),
  425. };
  426. static struct sensor_device_attribute in_max[] = {
  427. SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0),
  428. SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1),
  429. SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2),
  430. SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3),
  431. SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4),
  432. SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5),
  433. SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6),
  434. SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7),
  435. SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8),
  436. SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9),
  437. SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
  438. };
  439. #define VIN_UNIT_ATTRS(X) \
  440. &in_input[X].dev_attr.attr, \
  441. &in_status[X].dev_attr.attr, \
  442. &in_min[X].dev_attr.attr, \
  443. &in_max[X].dev_attr.attr
  444. static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
  445. {
  446. struct pc87360_data *data = pc87360_update_device(dev);
  447. return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
  448. }
  449. static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
  450. static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
  451. {
  452. struct pc87360_data *data = dev_get_drvdata(dev);
  453. return sprintf(buf, "%u\n", data->vrm);
  454. }
  455. static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  456. {
  457. struct pc87360_data *data = dev_get_drvdata(dev);
  458. data->vrm = simple_strtoul(buf, NULL, 10);
  459. return count;
  460. }
  461. static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
  462. static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
  463. {
  464. struct pc87360_data *data = pc87360_update_device(dev);
  465. return sprintf(buf, "%u\n", data->in_alarms);
  466. }
  467. static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
  468. static struct attribute *pc8736x_vin_attr_array[] = {
  469. VIN_UNIT_ATTRS(0),
  470. VIN_UNIT_ATTRS(1),
  471. VIN_UNIT_ATTRS(2),
  472. VIN_UNIT_ATTRS(3),
  473. VIN_UNIT_ATTRS(4),
  474. VIN_UNIT_ATTRS(5),
  475. VIN_UNIT_ATTRS(6),
  476. VIN_UNIT_ATTRS(7),
  477. VIN_UNIT_ATTRS(8),
  478. VIN_UNIT_ATTRS(9),
  479. VIN_UNIT_ATTRS(10),
  480. &dev_attr_cpu0_vid.attr,
  481. &dev_attr_vrm.attr,
  482. &dev_attr_alarms_in.attr,
  483. NULL
  484. };
  485. static const struct attribute_group pc8736x_vin_group = {
  486. .attrs = pc8736x_vin_attr_array,
  487. };
  488. static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
  489. {
  490. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  491. struct pc87360_data *data = pc87360_update_device(dev);
  492. return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
  493. data->in_vref));
  494. }
  495. static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf)
  496. {
  497. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  498. struct pc87360_data *data = pc87360_update_device(dev);
  499. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
  500. data->in_vref));
  501. }
  502. static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf)
  503. {
  504. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  505. struct pc87360_data *data = pc87360_update_device(dev);
  506. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
  507. data->in_vref));
  508. }
  509. static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf)
  510. {
  511. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  512. struct pc87360_data *data = pc87360_update_device(dev);
  513. return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
  514. data->in_vref));
  515. }
  516. static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf)
  517. {
  518. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  519. struct pc87360_data *data = pc87360_update_device(dev);
  520. return sprintf(buf, "%u\n", data->in_status[attr->index]);
  521. }
  522. static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf,
  523. size_t count)
  524. {
  525. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  526. struct pc87360_data *data = dev_get_drvdata(dev);
  527. long val = simple_strtol(buf, NULL, 10);
  528. mutex_lock(&data->update_lock);
  529. data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
  530. pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
  531. data->in_min[attr->index]);
  532. mutex_unlock(&data->update_lock);
  533. return count;
  534. }
  535. static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
  536. size_t count)
  537. {
  538. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  539. struct pc87360_data *data = dev_get_drvdata(dev);
  540. long val = simple_strtol(buf, NULL, 10);
  541. mutex_lock(&data->update_lock);
  542. data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
  543. pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
  544. data->in_max[attr->index]);
  545. mutex_unlock(&data->update_lock);
  546. return count;
  547. }
  548. static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
  549. size_t count)
  550. {
  551. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  552. struct pc87360_data *data = dev_get_drvdata(dev);
  553. long val = simple_strtol(buf, NULL, 10);
  554. mutex_lock(&data->update_lock);
  555. data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
  556. pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
  557. data->in_crit[attr->index-11]);
  558. mutex_unlock(&data->update_lock);
  559. return count;
  560. }
  561. /* the +11 term below reflects the fact that VLM units 11,12,13 are
  562. used in the chip to measure voltage across the thermistors
  563. */
  564. static struct sensor_device_attribute therm_input[] = {
  565. SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11),
  566. SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11),
  567. SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11),
  568. };
  569. static struct sensor_device_attribute therm_status[] = {
  570. SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11),
  571. SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11),
  572. SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11),
  573. };
  574. static struct sensor_device_attribute therm_min[] = {
  575. SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR,
  576. show_therm_min, set_therm_min, 0+11),
  577. SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR,
  578. show_therm_min, set_therm_min, 1+11),
  579. SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR,
  580. show_therm_min, set_therm_min, 2+11),
  581. };
  582. static struct sensor_device_attribute therm_max[] = {
  583. SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR,
  584. show_therm_max, set_therm_max, 0+11),
  585. SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR,
  586. show_therm_max, set_therm_max, 1+11),
  587. SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR,
  588. show_therm_max, set_therm_max, 2+11),
  589. };
  590. static struct sensor_device_attribute therm_crit[] = {
  591. SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
  592. show_therm_crit, set_therm_crit, 0+11),
  593. SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR,
  594. show_therm_crit, set_therm_crit, 1+11),
  595. SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR,
  596. show_therm_crit, set_therm_crit, 2+11),
  597. };
  598. #define THERM_UNIT_ATTRS(X) \
  599. &therm_input[X].dev_attr.attr, \
  600. &therm_status[X].dev_attr.attr, \
  601. &therm_min[X].dev_attr.attr, \
  602. &therm_max[X].dev_attr.attr, \
  603. &therm_crit[X].dev_attr.attr
  604. static struct attribute * pc8736x_therm_attr_array[] = {
  605. THERM_UNIT_ATTRS(0),
  606. THERM_UNIT_ATTRS(1),
  607. THERM_UNIT_ATTRS(2),
  608. NULL
  609. };
  610. static const struct attribute_group pc8736x_therm_group = {
  611. .attrs = pc8736x_therm_attr_array,
  612. };
  613. static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
  614. {
  615. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  616. struct pc87360_data *data = pc87360_update_device(dev);
  617. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
  618. }
  619. static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf)
  620. {
  621. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  622. struct pc87360_data *data = pc87360_update_device(dev);
  623. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
  624. }
  625. static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf)
  626. {
  627. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  628. struct pc87360_data *data = pc87360_update_device(dev);
  629. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
  630. }
  631. static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf)
  632. {
  633. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  634. struct pc87360_data *data = pc87360_update_device(dev);
  635. return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index]));
  636. }
  637. static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf)
  638. {
  639. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  640. struct pc87360_data *data = pc87360_update_device(dev);
  641. return sprintf(buf, "%d\n", data->temp_status[attr->index]);
  642. }
  643. static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf,
  644. size_t count)
  645. {
  646. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  647. struct pc87360_data *data = dev_get_drvdata(dev);
  648. long val = simple_strtol(buf, NULL, 10);
  649. mutex_lock(&data->update_lock);
  650. data->temp_min[attr->index] = TEMP_TO_REG(val);
  651. pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
  652. data->temp_min[attr->index]);
  653. mutex_unlock(&data->update_lock);
  654. return count;
  655. }
  656. static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
  657. size_t count)
  658. {
  659. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  660. struct pc87360_data *data = dev_get_drvdata(dev);
  661. long val = simple_strtol(buf, NULL, 10);
  662. mutex_lock(&data->update_lock);
  663. data->temp_max[attr->index] = TEMP_TO_REG(val);
  664. pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
  665. data->temp_max[attr->index]);
  666. mutex_unlock(&data->update_lock);
  667. return count;
  668. }
  669. static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
  670. size_t count)
  671. {
  672. struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  673. struct pc87360_data *data = dev_get_drvdata(dev);
  674. long val = simple_strtol(buf, NULL, 10);
  675. mutex_lock(&data->update_lock);
  676. data->temp_crit[attr->index] = TEMP_TO_REG(val);
  677. pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
  678. data->temp_crit[attr->index]);
  679. mutex_unlock(&data->update_lock);
  680. return count;
  681. }
  682. static struct sensor_device_attribute temp_input[] = {
  683. SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0),
  684. SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1),
  685. SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2),
  686. };
  687. static struct sensor_device_attribute temp_status[] = {
  688. SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0),
  689. SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1),
  690. SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2),
  691. };
  692. static struct sensor_device_attribute temp_min[] = {
  693. SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR,
  694. show_temp_min, set_temp_min, 0),
  695. SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR,
  696. show_temp_min, set_temp_min, 1),
  697. SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR,
  698. show_temp_min, set_temp_min, 2),
  699. };
  700. static struct sensor_device_attribute temp_max[] = {
  701. SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
  702. show_temp_max, set_temp_max, 0),
  703. SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
  704. show_temp_max, set_temp_max, 1),
  705. SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
  706. show_temp_max, set_temp_max, 2),
  707. };
  708. static struct sensor_device_attribute temp_crit[] = {
  709. SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
  710. show_temp_crit, set_temp_crit, 0),
  711. SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR,
  712. show_temp_crit, set_temp_crit, 1),
  713. SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR,
  714. show_temp_crit, set_temp_crit, 2),
  715. };
  716. static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
  717. {
  718. struct pc87360_data *data = pc87360_update_device(dev);
  719. return sprintf(buf, "%u\n", data->temp_alarms);
  720. }
  721. static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
  722. #define TEMP_UNIT_ATTRS(X) \
  723. &temp_input[X].dev_attr.attr, \
  724. &temp_status[X].dev_attr.attr, \
  725. &temp_min[X].dev_attr.attr, \
  726. &temp_max[X].dev_attr.attr, \
  727. &temp_crit[X].dev_attr.attr
  728. static struct attribute * pc8736x_temp_attr_array[] = {
  729. TEMP_UNIT_ATTRS(0),
  730. TEMP_UNIT_ATTRS(1),
  731. TEMP_UNIT_ATTRS(2),
  732. /* include the few miscellaneous atts here */
  733. &dev_attr_alarms_temp.attr,
  734. NULL
  735. };
  736. static const struct attribute_group pc8736x_temp_group = {
  737. .attrs = pc8736x_temp_attr_array,
  738. };
  739. static ssize_t show_name(struct device *dev, struct device_attribute
  740. *devattr, char *buf)
  741. {
  742. struct pc87360_data *data = dev_get_drvdata(dev);
  743. return sprintf(buf, "%s\n", data->name);
  744. }
  745. static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
  746. /*
  747. * Device detection, registration and update
  748. */
  749. static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
  750. {
  751. u16 val;
  752. int i;
  753. int nrdev; /* logical device count */
  754. /* No superio_enter */
  755. /* Identify device */
  756. val = force_id ? force_id : superio_inb(sioaddr, DEVID);
  757. switch (val) {
  758. case 0xE1: /* PC87360 */
  759. case 0xE8: /* PC87363 */
  760. case 0xE4: /* PC87364 */
  761. nrdev = 1;
  762. break;
  763. case 0xE5: /* PC87365 */
  764. case 0xE9: /* PC87366 */
  765. nrdev = 3;
  766. break;
  767. default:
  768. superio_exit(sioaddr);
  769. return -ENODEV;
  770. }
  771. /* Remember the device id */
  772. *devid = val;
  773. for (i = 0; i < nrdev; i++) {
  774. /* select logical device */
  775. superio_outb(sioaddr, DEV, logdev[i]);
  776. val = superio_inb(sioaddr, ACT);
  777. if (!(val & 0x01)) {
  778. printk(KERN_INFO "pc87360: Device 0x%02x not "
  779. "activated\n", logdev[i]);
  780. continue;
  781. }
  782. val = (superio_inb(sioaddr, BASE) << 8)
  783. | superio_inb(sioaddr, BASE + 1);
  784. if (!val) {
  785. printk(KERN_INFO "pc87360: Base address not set for "
  786. "device 0x%02x\n", logdev[i]);
  787. continue;
  788. }
  789. addresses[i] = val;
  790. if (i==0) { /* Fans */
  791. confreg[0] = superio_inb(sioaddr, 0xF0);
  792. confreg[1] = superio_inb(sioaddr, 0xF1);
  793. #ifdef DEBUG
  794. printk(KERN_DEBUG "pc87360: Fan 1: mon=%d "
  795. "ctrl=%d inv=%d\n", (confreg[0]>>2)&1,
  796. (confreg[0]>>3)&1, (confreg[0]>>4)&1);
  797. printk(KERN_DEBUG "pc87360: Fan 2: mon=%d "
  798. "ctrl=%d inv=%d\n", (confreg[0]>>5)&1,
  799. (confreg[0]>>6)&1, (confreg[0]>>7)&1);
  800. printk(KERN_DEBUG "pc87360: Fan 3: mon=%d "
  801. "ctrl=%d inv=%d\n", confreg[1]&1,
  802. (confreg[1]>>1)&1, (confreg[1]>>2)&1);
  803. #endif
  804. } else if (i==1) { /* Voltages */
  805. /* Are we using thermistors? */
  806. if (*devid == 0xE9) { /* PC87366 */
  807. /* These registers are not logical-device
  808. specific, just that we won't need them if
  809. we don't use the VLM device */
  810. confreg[2] = superio_inb(sioaddr, 0x2B);
  811. confreg[3] = superio_inb(sioaddr, 0x25);
  812. if (confreg[2] & 0x40) {
  813. printk(KERN_INFO "pc87360: Using "
  814. "thermistors for temperature "
  815. "monitoring\n");
  816. }
  817. if (confreg[3] & 0xE0) {
  818. printk(KERN_INFO "pc87360: VID "
  819. "inputs routed (mode %u)\n",
  820. confreg[3] >> 5);
  821. }
  822. }
  823. }
  824. }
  825. superio_exit(sioaddr);
  826. return 0;
  827. }
  828. static int __devinit pc87360_probe(struct platform_device *pdev)
  829. {
  830. int i;
  831. struct pc87360_data *data;
  832. int err = 0;
  833. const char *name = "pc87360";
  834. int use_thermistors = 0;
  835. struct device *dev = &pdev->dev;
  836. if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
  837. return -ENOMEM;
  838. data->fannr = 2;
  839. data->innr = 0;
  840. data->tempnr = 0;
  841. switch (devid) {
  842. case 0xe8:
  843. name = "pc87363";
  844. break;
  845. case 0xe4:
  846. name = "pc87364";
  847. data->fannr = 3;
  848. break;
  849. case 0xe5:
  850. name = "pc87365";
  851. data->fannr = extra_isa[0] ? 3 : 0;
  852. data->innr = extra_isa[1] ? 11 : 0;
  853. data->tempnr = extra_isa[2] ? 2 : 0;
  854. break;
  855. case 0xe9:
  856. name = "pc87366";
  857. data->fannr = extra_isa[0] ? 3 : 0;
  858. data->innr = extra_isa[1] ? 14 : 0;
  859. data->tempnr = extra_isa[2] ? 3 : 0;
  860. break;
  861. }
  862. data->name = name;
  863. data->valid = 0;
  864. mutex_init(&data->lock);
  865. mutex_init(&data->update_lock);
  866. platform_set_drvdata(pdev, data);
  867. for (i = 0; i < 3; i++) {
  868. if (((data->address[i] = extra_isa[i]))
  869. && !request_region(extra_isa[i], PC87360_EXTENT,
  870. pc87360_driver.driver.name)) {
  871. dev_err(dev, "Region 0x%x-0x%x already "
  872. "in use!\n", extra_isa[i],
  873. extra_isa[i]+PC87360_EXTENT-1);
  874. for (i--; i >= 0; i--)
  875. release_region(extra_isa[i], PC87360_EXTENT);
  876. err = -EBUSY;
  877. goto ERROR1;
  878. }
  879. }
  880. /* Retrieve the fans configuration from Super-I/O space */
  881. if (data->fannr)
  882. data->fan_conf = confreg[0] | (confreg[1] << 8);
  883. /* Use the correct reference voltage
  884. Unless both the VLM and the TMS logical devices agree to
  885. use an external Vref, the internal one is used. */
  886. if (data->innr) {
  887. i = pc87360_read_value(data, LD_IN, NO_BANK,
  888. PC87365_REG_IN_CONFIG);
  889. if (data->tempnr) {
  890. i &= pc87360_read_value(data, LD_TEMP, NO_BANK,
  891. PC87365_REG_TEMP_CONFIG);
  892. }
  893. data->in_vref = (i&0x02) ? 3025 : 2966;
  894. dev_dbg(dev, "Using %s reference voltage\n",
  895. (i&0x02) ? "external" : "internal");
  896. data->vid_conf = confreg[3];
  897. data->vrm = vid_which_vrm();
  898. }
  899. /* Fan clock dividers may be needed before any data is read */
  900. for (i = 0; i < data->fannr; i++) {
  901. if (FAN_CONFIG_MONITOR(data->fan_conf, i))
  902. data->fan_status[i] = pc87360_read_value(data,
  903. LD_FAN, NO_BANK,
  904. PC87360_REG_FAN_STATUS(i));
  905. }
  906. if (init > 0) {
  907. if (devid == 0xe9 && data->address[1]) /* PC87366 */
  908. use_thermistors = confreg[2] & 0x40;
  909. pc87360_init_device(pdev, use_thermistors);
  910. }
  911. /* Register all-or-nothing sysfs groups */
  912. if (data->innr &&
  913. (err = sysfs_create_group(&dev->kobj,
  914. &pc8736x_vin_group)))
  915. goto ERROR3;
  916. if (data->innr == 14 &&
  917. (err = sysfs_create_group(&dev->kobj,
  918. &pc8736x_therm_group)))
  919. goto ERROR3;
  920. /* create device attr-files for varying sysfs groups */
  921. if (data->tempnr) {
  922. for (i = 0; i < data->tempnr; i++) {
  923. if ((err = device_create_file(dev,
  924. &temp_input[i].dev_attr))
  925. || (err = device_create_file(dev,
  926. &temp_min[i].dev_attr))
  927. || (err = device_create_file(dev,
  928. &temp_max[i].dev_attr))
  929. || (err = device_create_file(dev,
  930. &temp_crit[i].dev_attr))
  931. || (err = device_create_file(dev,
  932. &temp_status[i].dev_attr)))
  933. goto ERROR3;
  934. }
  935. if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
  936. goto ERROR3;
  937. }
  938. for (i = 0; i < data->fannr; i++) {
  939. if (FAN_CONFIG_MONITOR(data->fan_conf, i)
  940. && ((err = device_create_file(dev,
  941. &fan_input[i].dev_attr))
  942. || (err = device_create_file(dev,
  943. &fan_min[i].dev_attr))
  944. || (err = device_create_file(dev,
  945. &fan_div[i].dev_attr))
  946. || (err = device_create_file(dev,
  947. &fan_status[i].dev_attr))))
  948. goto ERROR3;
  949. if (FAN_CONFIG_CONTROL(data->fan_conf, i)
  950. && (err = device_create_file(dev, &pwm[i].dev_attr)))
  951. goto ERROR3;
  952. }
  953. if ((err = device_create_file(dev, &dev_attr_name)))
  954. goto ERROR3;
  955. data->hwmon_dev = hwmon_device_register(dev);
  956. if (IS_ERR(data->hwmon_dev)) {
  957. err = PTR_ERR(data->hwmon_dev);
  958. goto ERROR3;
  959. }
  960. return 0;
  961. ERROR3:
  962. device_remove_file(dev, &dev_attr_name);
  963. /* can still remove groups whose members were added individually */
  964. sysfs_remove_group(&dev->kobj, &pc8736x_temp_group);
  965. sysfs_remove_group(&dev->kobj, &pc8736x_fan_group);
  966. sysfs_remove_group(&dev->kobj, &pc8736x_therm_group);
  967. sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
  968. for (i = 0; i < 3; i++) {
  969. if (data->address[i]) {
  970. release_region(data->address[i], PC87360_EXTENT);
  971. }
  972. }
  973. ERROR1:
  974. kfree(data);
  975. return err;
  976. }
  977. static int __devexit pc87360_remove(struct platform_device *pdev)
  978. {
  979. struct pc87360_data *data = platform_get_drvdata(pdev);
  980. int i;
  981. hwmon_device_unregister(data->hwmon_dev);
  982. device_remove_file(&pdev->dev, &dev_attr_name);
  983. sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group);
  984. sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_group);
  985. sysfs_remove_group(&pdev->dev.kobj, &pc8736x_therm_group);
  986. sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group);
  987. for (i = 0; i < 3; i++) {
  988. if (data->address[i]) {
  989. release_region(data->address[i], PC87360_EXTENT);
  990. }
  991. }
  992. kfree(data);
  993. return 0;
  994. }
  995. /* ldi is the logical device index
  996. bank is for voltages and temperatures only */
  997. static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
  998. u8 reg)
  999. {
  1000. int res;
  1001. mutex_lock(&(data->lock));
  1002. if (bank != NO_BANK)
  1003. outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
  1004. res = inb_p(data->address[ldi] + reg);
  1005. mutex_unlock(&(data->lock));
  1006. return res;
  1007. }
  1008. static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
  1009. u8 reg, u8 value)
  1010. {
  1011. mutex_lock(&(data->lock));
  1012. if (bank != NO_BANK)
  1013. outb_p(bank, data->address[ldi] + PC87365_REG_BANK);
  1014. outb_p(value, data->address[ldi] + reg);
  1015. mutex_unlock(&(data->lock));
  1016. }
  1017. static void pc87360_init_device(struct platform_device *pdev,
  1018. int use_thermistors)
  1019. {
  1020. struct pc87360_data *data = platform_get_drvdata(pdev);
  1021. int i, nr;
  1022. const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 };
  1023. const u8 init_temp[3] = { 2, 2, 1 };
  1024. u8 reg;
  1025. if (init >= 2 && data->innr) {
  1026. reg = pc87360_read_value(data, LD_IN, NO_BANK,
  1027. PC87365_REG_IN_CONVRATE);
  1028. dev_info(&pdev->dev, "VLM conversion set to "
  1029. "1s period, 160us delay\n");
  1030. pc87360_write_value(data, LD_IN, NO_BANK,
  1031. PC87365_REG_IN_CONVRATE,
  1032. (reg & 0xC0) | 0x11);
  1033. }
  1034. nr = data->innr < 11 ? data->innr : 11;
  1035. for (i = 0; i < nr; i++) {
  1036. if (init >= init_in[i]) {
  1037. /* Forcibly enable voltage channel */
  1038. reg = pc87360_read_value(data, LD_IN, i,
  1039. PC87365_REG_IN_STATUS);
  1040. if (!(reg & 0x01)) {
  1041. dev_dbg(&pdev->dev, "Forcibly "
  1042. "enabling in%d\n", i);
  1043. pc87360_write_value(data, LD_IN, i,
  1044. PC87365_REG_IN_STATUS,
  1045. (reg & 0x68) | 0x87);
  1046. }
  1047. }
  1048. }
  1049. /* We can't blindly trust the Super-I/O space configuration bit,
  1050. most BIOS won't set it properly */
  1051. for (i = 11; i < data->innr; i++) {
  1052. reg = pc87360_read_value(data, LD_IN, i,
  1053. PC87365_REG_TEMP_STATUS);
  1054. use_thermistors = use_thermistors || (reg & 0x01);
  1055. }
  1056. i = use_thermistors ? 2 : 0;
  1057. for (; i < data->tempnr; i++) {
  1058. if (init >= init_temp[i]) {
  1059. /* Forcibly enable temperature channel */
  1060. reg = pc87360_read_value(data, LD_TEMP, i,
  1061. PC87365_REG_TEMP_STATUS);
  1062. if (!(reg & 0x01)) {
  1063. dev_dbg(&pdev->dev, "Forcibly "
  1064. "enabling temp%d\n", i+1);
  1065. pc87360_write_value(data, LD_TEMP, i,
  1066. PC87365_REG_TEMP_STATUS,
  1067. 0xCF);
  1068. }
  1069. }
  1070. }
  1071. if (use_thermistors) {
  1072. for (i = 11; i < data->innr; i++) {
  1073. if (init >= init_in[i]) {
  1074. /* The pin may already be used by thermal
  1075. diodes */
  1076. reg = pc87360_read_value(data, LD_TEMP,
  1077. (i-11)/2, PC87365_REG_TEMP_STATUS);
  1078. if (reg & 0x01) {
  1079. dev_dbg(&pdev->dev, "Skipping "
  1080. "temp%d, pin already in use "
  1081. "by temp%d\n", i-7, (i-11)/2);
  1082. continue;
  1083. }
  1084. /* Forcibly enable thermistor channel */
  1085. reg = pc87360_read_value(data, LD_IN, i,
  1086. PC87365_REG_IN_STATUS);
  1087. if (!(reg & 0x01)) {
  1088. dev_dbg(&pdev->dev, "Forcibly "
  1089. "enabling temp%d\n", i-7);
  1090. pc87360_write_value(data, LD_IN, i,
  1091. PC87365_REG_TEMP_STATUS,
  1092. (reg & 0x60) | 0x8F);
  1093. }
  1094. }
  1095. }
  1096. }
  1097. if (data->innr) {
  1098. reg = pc87360_read_value(data, LD_IN, NO_BANK,
  1099. PC87365_REG_IN_CONFIG);
  1100. if (reg & 0x01) {
  1101. dev_dbg(&pdev->dev, "Forcibly "
  1102. "enabling monitoring (VLM)\n");
  1103. pc87360_write_value(data, LD_IN, NO_BANK,
  1104. PC87365_REG_IN_CONFIG,
  1105. reg & 0xFE);
  1106. }
  1107. }
  1108. if (data->tempnr) {
  1109. reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
  1110. PC87365_REG_TEMP_CONFIG);
  1111. if (reg & 0x01) {
  1112. dev_dbg(&pdev->dev, "Forcibly enabling "
  1113. "monitoring (TMS)\n");
  1114. pc87360_write_value(data, LD_TEMP, NO_BANK,
  1115. PC87365_REG_TEMP_CONFIG,
  1116. reg & 0xFE);
  1117. }
  1118. if (init >= 2) {
  1119. /* Chip config as documented by National Semi. */
  1120. pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08);
  1121. /* We voluntarily omit the bank here, in case the
  1122. sequence itself matters. It shouldn't be a problem,
  1123. since nobody else is supposed to access the
  1124. device at that point. */
  1125. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04);
  1126. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35);
  1127. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05);
  1128. pc87360_write_value(data, LD_TEMP, NO_BANK, 0xE, 0x05);
  1129. }
  1130. }
  1131. }
  1132. static void pc87360_autodiv(struct device *dev, int nr)
  1133. {
  1134. struct pc87360_data *data = dev_get_drvdata(dev);
  1135. u8 old_min = data->fan_min[nr];
  1136. /* Increase clock divider if needed and possible */
  1137. if ((data->fan_status[nr] & 0x04) /* overflow flag */
  1138. || (data->fan[nr] >= 224)) { /* next to overflow */
  1139. if ((data->fan_status[nr] & 0x60) != 0x60) {
  1140. data->fan_status[nr] += 0x20;
  1141. data->fan_min[nr] >>= 1;
  1142. data->fan[nr] >>= 1;
  1143. dev_dbg(dev, "Increasing "
  1144. "clock divider to %d for fan %d\n",
  1145. FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1);
  1146. }
  1147. } else {
  1148. /* Decrease clock divider if possible */
  1149. while (!(data->fan_min[nr] & 0x80) /* min "nails" divider */
  1150. && data->fan[nr] < 85 /* bad accuracy */
  1151. && (data->fan_status[nr] & 0x60) != 0x00) {
  1152. data->fan_status[nr] -= 0x20;
  1153. data->fan_min[nr] <<= 1;
  1154. data->fan[nr] <<= 1;
  1155. dev_dbg(dev, "Decreasing "
  1156. "clock divider to %d for fan %d\n",
  1157. FAN_DIV_FROM_REG(data->fan_status[nr]),
  1158. nr+1);
  1159. }
  1160. }
  1161. /* Write new fan min if it changed */
  1162. if (old_min != data->fan_min[nr]) {
  1163. pc87360_write_value(data, LD_FAN, NO_BANK,
  1164. PC87360_REG_FAN_MIN(nr),
  1165. data->fan_min[nr]);
  1166. }
  1167. }
  1168. static struct pc87360_data *pc87360_update_device(struct device *dev)
  1169. {
  1170. struct pc87360_data *data = dev_get_drvdata(dev);
  1171. u8 i;
  1172. mutex_lock(&data->update_lock);
  1173. if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
  1174. dev_dbg(dev, "Data update\n");
  1175. /* Fans */
  1176. for (i = 0; i < data->fannr; i++) {
  1177. if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
  1178. data->fan_status[i] =
  1179. pc87360_read_value(data, LD_FAN,
  1180. NO_BANK, PC87360_REG_FAN_STATUS(i));
  1181. data->fan[i] = pc87360_read_value(data, LD_FAN,
  1182. NO_BANK, PC87360_REG_FAN(i));
  1183. data->fan_min[i] = pc87360_read_value(data,
  1184. LD_FAN, NO_BANK,
  1185. PC87360_REG_FAN_MIN(i));
  1186. /* Change clock divider if needed */
  1187. pc87360_autodiv(dev, i);
  1188. /* Clear bits and write new divider */
  1189. pc87360_write_value(data, LD_FAN, NO_BANK,
  1190. PC87360_REG_FAN_STATUS(i),
  1191. data->fan_status[i]);
  1192. }
  1193. if (FAN_CONFIG_CONTROL(data->fan_conf, i))
  1194. data->pwm[i] = pc87360_read_value(data, LD_FAN,
  1195. NO_BANK, PC87360_REG_PWM(i));
  1196. }
  1197. /* Voltages */
  1198. for (i = 0; i < data->innr; i++) {
  1199. data->in_status[i] = pc87360_read_value(data, LD_IN, i,
  1200. PC87365_REG_IN_STATUS);
  1201. /* Clear bits */
  1202. pc87360_write_value(data, LD_IN, i,
  1203. PC87365_REG_IN_STATUS,
  1204. data->in_status[i]);
  1205. if ((data->in_status[i] & 0x81) == 0x81) {
  1206. data->in[i] = pc87360_read_value(data, LD_IN,
  1207. i, PC87365_REG_IN);
  1208. }
  1209. if (data->in_status[i] & 0x01) {
  1210. data->in_min[i] = pc87360_read_value(data,
  1211. LD_IN, i,
  1212. PC87365_REG_IN_MIN);
  1213. data->in_max[i] = pc87360_read_value(data,
  1214. LD_IN, i,
  1215. PC87365_REG_IN_MAX);
  1216. if (i >= 11)
  1217. data->in_crit[i-11] =
  1218. pc87360_read_value(data, LD_IN,
  1219. i, PC87365_REG_TEMP_CRIT);
  1220. }
  1221. }
  1222. if (data->innr) {
  1223. data->in_alarms = pc87360_read_value(data, LD_IN,
  1224. NO_BANK, PC87365_REG_IN_ALARMS1)
  1225. | ((pc87360_read_value(data, LD_IN,
  1226. NO_BANK, PC87365_REG_IN_ALARMS2)
  1227. & 0x07) << 8);
  1228. data->vid = (data->vid_conf & 0xE0) ?
  1229. pc87360_read_value(data, LD_IN,
  1230. NO_BANK, PC87365_REG_VID) : 0x1F;
  1231. }
  1232. /* Temperatures */
  1233. for (i = 0; i < data->tempnr; i++) {
  1234. data->temp_status[i] = pc87360_read_value(data,
  1235. LD_TEMP, i,
  1236. PC87365_REG_TEMP_STATUS);
  1237. /* Clear bits */
  1238. pc87360_write_value(data, LD_TEMP, i,
  1239. PC87365_REG_TEMP_STATUS,
  1240. data->temp_status[i]);
  1241. if ((data->temp_status[i] & 0x81) == 0x81) {
  1242. data->temp[i] = pc87360_read_value(data,
  1243. LD_TEMP, i,
  1244. PC87365_REG_TEMP);
  1245. }
  1246. if (data->temp_status[i] & 0x01) {
  1247. data->temp_min[i] = pc87360_read_value(data,
  1248. LD_TEMP, i,
  1249. PC87365_REG_TEMP_MIN);
  1250. data->temp_max[i] = pc87360_read_value(data,
  1251. LD_TEMP, i,
  1252. PC87365_REG_TEMP_MAX);
  1253. data->temp_crit[i] = pc87360_read_value(data,
  1254. LD_TEMP, i,
  1255. PC87365_REG_TEMP_CRIT);
  1256. }
  1257. }
  1258. if (data->tempnr) {
  1259. data->temp_alarms = pc87360_read_value(data, LD_TEMP,
  1260. NO_BANK, PC87365_REG_TEMP_ALARMS)
  1261. & 0x3F;
  1262. }
  1263. data->last_updated = jiffies;
  1264. data->valid = 1;
  1265. }
  1266. mutex_unlock(&data->update_lock);
  1267. return data;
  1268. }
  1269. static int __init pc87360_device_add(unsigned short address)
  1270. {
  1271. struct resource res = {
  1272. .name = "pc87360",
  1273. .flags = IORESOURCE_IO,
  1274. };
  1275. int err, i;
  1276. pdev = platform_device_alloc("pc87360", address);
  1277. if (!pdev) {
  1278. err = -ENOMEM;
  1279. printk(KERN_ERR "pc87360: Device allocation failed\n");
  1280. goto exit;
  1281. }
  1282. for (i = 0; i < 3; i++) {
  1283. if (!extra_isa[i])
  1284. continue;
  1285. res.start = extra_isa[i];
  1286. res.end = extra_isa[i] + PC87360_EXTENT - 1;
  1287. err = platform_device_add_resources(pdev, &res, 1);
  1288. if (err) {
  1289. printk(KERN_ERR "pc87360: Device resource[%d] "
  1290. "addition failed (%d)\n", i, err);
  1291. goto exit_device_put;
  1292. }
  1293. }
  1294. err = platform_device_add(pdev);
  1295. if (err) {
  1296. printk(KERN_ERR "pc87360: Device addition failed (%d)\n",
  1297. err);
  1298. goto exit_device_put;
  1299. }
  1300. return 0;
  1301. exit_device_put:
  1302. platform_device_put(pdev);
  1303. exit:
  1304. return err;
  1305. }
  1306. static int __init pc87360_init(void)
  1307. {
  1308. int err, i;
  1309. unsigned short address = 0;
  1310. if (pc87360_find(0x2e, &devid, extra_isa)
  1311. && pc87360_find(0x4e, &devid, extra_isa)) {
  1312. printk(KERN_WARNING "pc87360: PC8736x not detected, "
  1313. "module not inserted.\n");
  1314. return -ENODEV;
  1315. }
  1316. /* Arbitrarily pick one of the addresses */
  1317. for (i = 0; i < 3; i++) {
  1318. if (extra_isa[i] != 0x0000) {
  1319. address = extra_isa[i];
  1320. break;
  1321. }
  1322. }
  1323. if (address == 0x0000) {
  1324. printk(KERN_WARNING "pc87360: No active logical device, "
  1325. "module not inserted.\n");
  1326. return -ENODEV;
  1327. }
  1328. err = platform_driver_register(&pc87360_driver);
  1329. if (err)
  1330. goto exit;
  1331. /* Sets global pdev as a side effect */
  1332. err = pc87360_device_add(address);
  1333. if (err)
  1334. goto exit_driver;
  1335. return 0;
  1336. exit_driver:
  1337. platform_driver_unregister(&pc87360_driver);
  1338. exit:
  1339. return err;
  1340. }
  1341. static void __exit pc87360_exit(void)
  1342. {
  1343. platform_device_unregister(pdev);
  1344. platform_driver_unregister(&pc87360_driver);
  1345. }
  1346. MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
  1347. MODULE_DESCRIPTION("PC8736x hardware monitor");
  1348. MODULE_LICENSE("GPL");
  1349. module_init(pc87360_init);
  1350. module_exit(pc87360_exit);