From mboxrd@z Thu Jan 1 00:00:00 1970 From: Neelesh Gupta Date: Tue, 08 Jul 2014 09:20:38 +0000 Subject: [lm-sensors] [PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature Message-Id: <20140708090315.3866.15604.stgit@localhost.localdomain> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org, lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org Cc: benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org, svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org, sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org, jdelvare-l3A5Bk7waGM@public.gmane.org, linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org VGhpcyBwYXRjaCBhZGRzIGJhc2ljIGtlcm5lbCBzdXBwb3J0IGZvciByZWFkaW5nIHBvd2VyIHZh bHVlcywgZmFuCnNwZWVkIHJwbSwgdm9sdGFnZSBhbmQgdGVtcGVyYXR1cmUgZGF0YSBvbiBwb3dl cm52IHBsYXRmb3JtcyB3aGljaAp3aWxsIGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3Vn aCBzeXNmcyBpbnRlcmZhY2UuCgpUZXN0IHJlc3VsdHM6Ci0tLS0tLS0tLS0tLS0KW3Jvb3RAdHVs MTYzcDEgfl0jIHNlbnNvcnMKaWJtcG93ZXJudi1pc2EtMDAwMApBZGFwdGVyOiBJU0EgYWRhcHRl cgpmYW4xOiAgICAgICAgNTQ2NSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuMjogICAgICAgIDUx NTIgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjM6ICAgICAgICA1NTIxIFJQTSAgKG1pbiA9ICAg IDAgUlBNKQpmYW40OiAgICAgICAgNDg5MSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuNTogICAg ICAgICAgIDAgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1p biA9ICAgIDAgUlBNKQpmYW43OiAgICAgICAgNzQ4MCBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFu ODogICAgICAgIDc5NDQgUlBNICAobWluID0gICAgMCBSUE0pCnRlbXAxOiAgICAgICAgKzM5LjDC sEMgIChoaWdoID0gICswLjDCsEMpCnBvd2VyMTogICAgICAxOTAuMDAgVyAgCgpbcm9vdEB0dWwx NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwphbGFybXRpbWVyICBpYm1wb3dlcm52 LjAgIHBvd2VyICBydGMtZ2VuZXJpYyAgc2VyaWFsODI1MCAgdWV2ZW50Cltyb290QHR1bDE2M3Ax IH5dIyBscyAvc3lzL2RldmljZXMvcGxhdGZvcm0vaWJtcG93ZXJudi4wL2h3bW9uL2h3bW9uMC8K ZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2Vy CmZhbjFfZmF1bHQgIGZhbjNfZmF1bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQg IHBvd2VyMV9pbnB1dApmYW4xX2lucHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5w dXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAg ZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZh bjZfZmF1bHQgIGZhbjhfZmF1bHQJaW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFu NF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2 M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KZGV2aWNlCSAgICBmYW4yX21pbglm YW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2VyCmZhbjFfZmF1bHQgIGZhbjNfZmF1 bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQgIHBvd2VyMV9pbnB1dApmYW4xX2lu cHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0 ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0 ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZhbjZfZmF1bHQgIGZhbjhfZmF1bHQJ aW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBm YW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2M3AxIH5dIwoKU2lnbmVkLW9mZi1i eTogTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPgpSZXZpZXdlZC1i eTogR3VlbnRlciBSb2VjayA8bGludXhAcm9lY2stdXMubmV0PgotLS0KCkNoYW5nZXMgaW4gdjUK PT09PT09PT09PT09PQotIEFkZHJlc3NlZCBjb3VwbGUgbWlub3IgY29tbWVudHMgaW4gdjQuCgpD aGFuZ2VzIGluIHY0Cj09PT09PT09PT09PT0KLSBSZXBsYWNlZCBwcl9lcnIoKSB3aXRoIGRldl9l cnIoKSBmb3IgbG9nZ2luZyBwcmludCBtZXNzYWdlcy4KLSBVc2luZyBrc3RydG91MzIoKSBmdW5j dGlvbiBmb3IgY29udmVydGluZyBzdHJpbmcgdG8gdTMyIGluc3RlYWQgb2Ygc3NjYW5mKCkuCgpD aGFuZ2VzIGluIHYzCj09PT09PT09PT09PT0KLSBGaXhlZCBhbiBlbmRpYW5uZXNzIGJ1ZyBsZWFk aW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCi0gRml4ZWQgYSBidWcgdGhhdCB3aGVuIG9u ZSBvZiB0aGUgJ2F0dHJpYnV0ZV9ncm91cCcgbm90IHBvcHVsYXRlZCwgZm9sbG93aW5nCiAgZ3Jv dXBzIGF0dHJpYnV0ZXMgd2VyZSBkcm9wcGVkLgotIFJld3JpdGUgdGhlIGdldF9zZW5zb3JfaW5k ZXhfYXR0cigpIGZ1bmN0aW9uIHRvIGhhbmRsZSBhbGwgdGhlIGVycm9yIHNjZW5hcmlvcwogIGxp a2UgJ3NzY2FuZicgZXRjLgotIEZpeGVkIGFsbCB0aGUgZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQg dG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCi0gQWRkZWQgJ0RvY3VtZW50YXRpb24nIGZpbGVz LgotIEFkZHJlc3NlZCByZW1haW5pbmcgcmV2aWV3IGNvbW1lbnRzIG9uIFYyLgoKQ2hhbmdlcyBp biB2Mgo9PT09PT09PT09PT09Ci0gR2VuZXJpYyB1c2Ugb2YgZGV2bV8qIGZ1bmN0aW9ucyBpbiBo d21vbiBsaWtlIHVzaW5nIGRldm1fa3phbGxvYygpIGZvciBkeW5hbWljCiAgbWVtb3J5IHJlcXVl c3QsIGF2b2lkaW5nIHRoZSBuZWVkIHRvIGV4cGxpY2l0IGZyZWUgb2YgbWVtb3J5LgogIEFkZGlu ZyAnc3RydWN0IGF0dHJpYnV0ZV9ncm91cCcgYXMgbWVtYmVyIG9mIHBsYXRmb3JtIGRhdGEgc3Ry dWN0dXJlIHRvIGJlCiAgcG9wdWxhdGVkIGFuZCB0aGVuIHBhc3NlZCB0byBkZXZtX2h3bW9uX2Rl dmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgoKICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2Yg cG9pbnRlcnMgb2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKICBjb3JyZXNwb25k cyB0byAnZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlk ZWFsIG9yCiAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1 dGVzIG9mIHNlbnNvciB0eXBlcz8KCi0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKICBmdW5jdGlvbiAo cHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCi0gRml4ZWQgaXNzdWVzIHJlbGF0ZWQgdG8g Y29kaW5nIHN0eWxlLgotIE90aGVyIGdlbmVyYWwgY29tbWVudHMgaW4gdjEuCgogLi4uL2Rldmlj ZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQgICAgICAgfCAgIDIzICsKIERvY3Vt ZW50YXRpb24vaHdtb24vaWJtcG93ZXJudiAgICAgICAgICAgICAgICAgICAgIHwgICA0MSArKwog ZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDEx ICsKIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg ICAgMSAKIGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jICAgICAgICAgICAgICAgICAgICAgICAg IHwgIDM2NCArKysrKysrKysrKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0 aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k aW5ncy9od21vbi9pYm1wb3dlcm52LnR4dAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp b24vaHdtb24vaWJtcG93ZXJudgogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJt cG93ZXJudi5jCgpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz L2h3bW9uL2libXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz L2h3bW9uL2libXBvd2VybnYudHh0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu LmY5MzI0MmIKLS0tIC9kZXYvbnVsbAorKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu ZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKQEAgLTAsMCArMSwyMyBAQAorSUJNIFBPV0VSTlYg cGxhdGZvcm0gc2Vuc29ycworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitSZXF1aXJl ZCBub2RlIHByb3BlcnRpZXM6CistIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCisJCSJpYm0s b3BhbC1zZW5zb3ItY29vbGluZy1mYW4iCisJCSJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiCisJ CSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5IgorCQkiaWJtLG9wYWwtc2Vuc29yLXBvd2Vy IgorLSBzZW5zb3ItaWQ6IGFuIG9wYXF1ZSBpZCBwcm92aWRlZCBieSB0aGUgZmlybXdhcmUgdG8g dGhlIGtlcm5lbCwgaWRlbnRpZmllcyBhCisJICAgICBnaXZlbiBzZW5zb3IgYW5kIGl0cyBhdHRy aWJ1dGUgZGF0YQorCitFeGFtcGxlIHNlbnNvcnMgbm9kZToKKworY29vbGluZy1mYW4jOC1kYXRh IHsKKwlzZW5zb3ItaWQgPSA8MHg3MDUyMTA3PjsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl bnNvci1jb29saW5nLWZhbiI7Cit9OworCithbWItdGVtcCMxLXRocnMgeworCXNlbnNvci1pZCA9 IDwweDUwOTYwMDA+OworCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1wIjsK K307CmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYgYi9Eb2N1bWVu dGF0aW9uL2h3bW9uL2libXBvd2VybnYKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw MC4uNjQ0MjQ1YQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93 ZXJudgpAQCAtMCwwICsxLDQxIEBACitLZXJuZWwgRHJpdmVyIElCTVBPV0VOVgorPT09PT09PT09 PT09PT09PT09PT09PT0KKworU3VwcG9ydGVkIHN5c3RlbXM6CisgICogQW55IHJlY2VudCBJQk0g UCBzZXJ2ZXJzIGJhc2VkIG9uIFBPV0VSTlYgcGxhdGZvcm0KKworQXV0aG9yOiBOZWVsZXNoIEd1 cHRhCisKK0Rlc2NyaXB0aW9uCistLS0tLS0tLS0tLQorCitUaGlzIGRyaXZlciBpbXBsZW1lbnRz IHJlYWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8K K3ZvbHRhZ2UvcG93ZXIgZm9yICdQT1dFUk5WJyBwbGF0Zm9ybS4KKworVGhlIGRyaXZlciB1c2Vz IHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2aWNl IHRyZWUKK2ZvciBzZW5zb3IgZGV2aWNlcyBkdXJpbmcgdGhlIF9faW5pdCBwaGFzZSBhbmQgcmVn aXN0ZXJzIHRoZW0gd2l0aCB0aGUgJ2h3bW9uJy4KKydod21vbicgcG9wdWxhdGVzIHRoZSAnc3lz ZnMnIHRyZWUgaGF2aW5nIGF0dHJpYnV0ZSBmaWxlcywgZWFjaCBmb3IgYSBnaXZlbgorc2Vuc29y IHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KKworQWxsIHRoZSBub2RlcyBpbiB0aGUgRFQg YXBwZWFyIHVuZGVyICIvaWJtLG9wYWwvc2Vuc29ycyIgYW5kIGVhY2ggdmFsaWQgbm9kZSBpbgor dGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2ZzJy4gVGhlIG5vZGUgZXhw b3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKK3doaWNoIHRoZSBkcml2ZXIgdXNlcyB0byBtYWtlIGFu IE9QQUwgY2FsbCB0byB0aGUgZmlybXdhcmUuCisKK1VzYWdlIG5vdGVzCistLS0tLS0tLS0tLQor VGhlIGRyaXZlciBpcyBidWlsdCBzdGF0aWNhbGx5IHdpdGggdGhlIGtlcm5lbCBieSBlbmFibGlu ZyB0aGUgY29uZmlnCitDT05GSUdfU0VOU09SU19JQk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBi dWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgorCitTeXNmcyBhdHRyaWJ1dGVzCistLS0tLS0t LS0tLS0tLS0tCisKK2ZhblhfaW5wdXQJCU1lYXN1cmVkIFJQTSB2YWx1ZS4KK2ZhblhfbWluCQlU aHJlc2hvbGQgUlBNIGZvciBhbGVydCBnZW5lcmF0aW9uLgorZmFuWF9mYXVsdAkJMDogTm8gZmFp bCBjb25kaXRpb24KKwkJCTE6IEZhaWxpbmcgZmFuCit0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1i aWVudCB0ZW1wZXJhdHVyZS4KK3RlbXBYX21heAkJVGhyZXNob2xkIGFtYmllbnQgdGVtcGVyYXR1 cmUgZm9yIGFsZXJ0IGdlbmVyYXRpb24uCitpblhfaW5wdXQJCU1lYXN1cmVkIHBvd2VyIHN1cHBs eSB2b2x0YWdlCitpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgorCQkJMTogRmFpbGlu ZyBwb3dlciBzdXBwbHkuCitwb3dlcjFfaW5wdXQJCVN5c3RlbSBwb3dlciBjb25zdW1wdGlvbiAo bWljcm9XYXR0KQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o d21vbi9LY29uZmlnCmluZGV4IDAyZDNkODUuLjI5YzNmY2IgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv aHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKQEAgLTU1NCw2ICs1NTQs MTcgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCiAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBi dWlsdCBhcyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCiAJICB3aWxsIGJlIGNhbGxlZCBp Ym1wZXguCiAKK2NvbmZpZyBTRU5TT1JTX0lCTVBPV0VSTlYKKwl0cmlzdGF0ZSAiSUJNIFBPV0VS TlYgcGxhdGZvcm0gc2Vuc29ycyIKKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCisJZGVmYXVsdCB5 CisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0 ZW1wZXJhdHVyZS9mYW4vcG93ZXIKKwkgIHNlbnNvcnMgb24geW91ciBQb3dlck5WIHBsYXRmb3Jt LgorCisJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s IHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVkIGlibXBvd2VybnYuCisKIGNvbmZpZyBTRU5T T1JTX0lJT19IV01PTgogCXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxz IHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCiAJZGVwZW5kcyBvbiBJSU8KZGlmZiAtLWdpdCBhL2Ry aXZlcnMvaHdtb24vTWFrZWZpbGUgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCmluZGV4IDNkYzBm MDIuLmZjNGVkMjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKKysrIGIvZHJp dmVycy9od21vbi9NYWtlZmlsZQpAQCAtNzEsNiArNzEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S U19VTFRSQTQ1KQkrPSB1bHRyYTQ1X2Vudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1C KQkrPSBpNWtfYW1iLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkJKz0gaWJtYWVtLm8K IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTVBFWCkJKz0gaWJtcGV4Lm8KK29iai0kKENPTkZJR19T RU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19J SU9fSFdNT04pICs9IGlpb19od21vbi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyMDkpCSs9 IGluYTIwOS5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgpCSs9IGluYTJ4eC5vCmRpZmYg LS1naXQgYS9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyBiL2RyaXZlcnMvaHdtb24vaWJtcG93 ZXJudi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmU2YjY1MmEKLS0tIC9k ZXYvbnVsbAorKysgYi9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwpAQCAtMCwwICsxLDM2NCBA QAorLyoKKyAqIElCTSBQb3dlck5WIHBsYXRmb3JtIHNlbnNvcnMgZm9yIHRlbXBlcmF0dXJlL2Zh bi92b2x0YWdlL3Bvd2VyCisgKiBDb3B5cmlnaHQgKEMpIDIwMTQgSUJNCisgKgorICogVGhpcyBw cm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBt b2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBl aXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBh bnkgbGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJS QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFC SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBH TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqIFlvdSBz aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl bnNlCisgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4KKyAqLworCisjZGVmaW5lIERSVk5BTUUJ CSJpYm1wb3dlcm52IgorI2RlZmluZSBwcl9mbXQoZm10KQlEUlZOQU1FICI6ICIgZm10CisKKyNp bmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxs aW51eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu dXgvc2xhYi5oPgorCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk ZSA8YXNtL29wYWwuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KKworI2RlZmluZSBNQVhfQVRU Ul9MRU4JMzIKKworLyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KKyNkZWZpbmUgRFRf RkFVTFRfQVRUUl9TVUZGSVgJCSJmYXVsdGVkIgorI2RlZmluZSBEVF9EQVRBX0FUVFJfU1VGRklY CQkiZGF0YSIKKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgorCisvKgor ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh dGZvcm0gYW5kIGRvZXMgaW5kZXgKKyAqIGludG8gJ3N0cnVjdCBzZW5zb3JfZ3JvdXAnCisgKi8K K2VudW0gc2Vuc29ycyB7CisJRkFOLAorCUFNQklFTlRfVEVNUCwKKwlQT1dFUl9TVVBQTFksCisJ UE9XRVJfSU5QVVQsCisJTUFYX1NFTlNPUl9UWVBFLAorfTsKKworc3RhdGljIHN0cnVjdCBzZW5z b3JfZ3JvdXAgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJY29uc3QgY2hhciAqY29tcGF0aWJsZTsK KwlzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGdyb3VwOworCXUzMiBhdHRyX2NvdW50OworfSBzZW5z b3JfZ3JvdXBzW10gPSB7CisJeyJmYW4iLCAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIn0s CisJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1hbWItdGVtcCJ9LAorCXsiaW4iLCAiaWJtLG9w YWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAorCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBv d2VyIn0KK307CisKK3N0cnVjdCBzZW5zb3JfZGF0YSB7CisJdTMyIGlkOyAvKiBBbiBvcGFxdWUg aWQgb2YgdGhlIGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLworCWVudW0gc2Vuc29ycyB0eXBl OworCWNoYXIgbmFtZVtNQVhfQVRUUl9MRU5dOworCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRl dl9hdHRyOworfTsKKworc3RydWN0IHBsYXRmb3JtX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhdHRy aWJ1dGVfZ3JvdXAgKmF0dHJfZ3JvdXBzW01BWF9TRU5TT1JfVFlQRSArIDFdOworCXUzMiBzZW5z b3JzX2NvdW50OyAvKiBUb3RhbCBjb3VudCBvZiBzZW5zb3JzIGZyb20gZWFjaCBncm91cCAqLwor fTsKKworLyogUGxhdGZvcm0gZGV2aWNlIHJlcHJlc2VudGluZyBhbGwgdGhlIGlibXBvd2VybnYg c2Vuc29ycyAqLworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXZpY2U7CisKK3N0 YXRpYyBzc2l6ZV90IHNob3dfc2Vuc29yKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmlj ZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkgICBjaGFyICpidWYpCit7CisJc3RydWN0IHNlbnNv cl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBzdHJ1Y3Qgc2Vuc29yX2RhdGEs CisJCQkJCQkgZGV2X2F0dHIpOworCXNzaXplX3QgcmV0OworCXUzMiB4OworCisJcmV0ID0gb3Bh bF9nZXRfc2Vuc29yX2RhdGEoc2RhdGEtPmlkLCAmeCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJl dDsKKworCS8qIENvbnZlcnQgdGVtcGVyYXR1cmUgdG8gbWlsbGktZGVncmVlcyAqLworCWlmIChz ZGF0YS0+dHlwZSA9PSBBTUJJRU5UX1RFTVApCisJCXggKj0gMTAwMDsKKwkvKiBDb252ZXJ0IHBv d2VyIHRvIG1pY3JvLXdhdHRzICovCisJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5Q VVQpCisJCXggKj0gMTAwMDAwMDsKKworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK K30KKworc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIg Km5hbWUsIHUzMiAqaW5kZXgsCisJCQkJCWNoYXIgKmF0dHIpCit7CisJY2hhciAqaGFzaF9wb3Mg PSBzdHJjaHIobmFtZSwgJyMnKTsKKwljaGFyIGJ1Zls4XSA9IHsgMCB9OworCWNoYXIgKmRhc2hf cG9zOworCXUzMiBjb3B5X2xlbjsKKwlpbnQgZXJyOworCisJaWYgKCFoYXNoX3BvcykKKwkJcmV0 dXJuIC1FSU5WQUw7CisKKwlkYXNoX3BvcyA9IHN0cmNocihoYXNoX3BvcywgJy0nKTsKKwlpZiAo IWRhc2hfcG9zKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNvcHlfbGVuID0gZGFzaF9wb3MgLSBo YXNoX3BvcyAtIDE7CisJaWYgKGNvcHlfbGVuID49IHNpemVvZihidWYpKQorCQlyZXR1cm4gLUVJ TlZBTDsKKworCXN0cm5jcHkoYnVmLCBoYXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKKworCWVyciA9 IGtzdHJ0b3UzMihidWYsIDEwLCBpbmRleCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKwor CXN0cm5jcHkoYXR0ciwgZGFzaF9wb3MgKyAxLCBNQVhfQVRUUl9MRU4pOworCisJcmV0dXJuIDA7 Cit9CisKKy8qCisgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMgdGhlIERUIG5vZGUgbmFtZSBp bnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgorICogSUJNUE9XRVJOViBkZXZpY2Ugbm9k ZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCisg KiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4yX2lucHV0LCB0ZW1wMV9tYXggcmVzcGVj dGl2ZWx5IGJlZm9yZQorICogcG9wdWxhdGluZyB0aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xh c3MuCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoc3RydWN0 IGRldmljZSAqZGV2LCBlbnVtIHNlbnNvcnMgdHlwZSwKKwkJCQkJIGNvbnN0IGNoYXIgKm5vZGVf bmFtZSwKKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKK3sKKwljaGFyIGF0dHJfc3VmZml4 W01BWF9BVFRSX0xFTl07CisJY2hhciAqYXR0cl9uYW1lOworCXUzMiBpbmRleDsKKwlpbnQgZXJy OworCisJZXJyID0gZ2V0X3NlbnNvcl9pbmRleF9hdHRyKG5vZGVfbmFtZSwgJmluZGV4LCBhdHRy X3N1ZmZpeCk7CisJaWYgKGVycikgeworCQlkZXZfZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9k ZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKKwkJCW5vZGVfbmFtZSk7CisJCXJldHVybiBlcnI7 CisJfQorCisJaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX0ZBVUxUX0FUVFJfU1VGRklYKSkg eworCQlhdHRyX25hbWUgPSAiZmF1bHQiOworCX0gZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp eCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpIHsKKwkJYXR0cl9uYW1lID0gImlucHV0IjsKKwl9IGVs c2UgaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsK KwkJaWYgKHR5cGUgPT0gQU1CSUVOVF9URU1QKQorCQkJYXR0cl9uYW1lID0gIm1heCI7CisJCWVs c2UgaWYgKHR5cGUgPT0gRkFOKQorCQkJYXR0cl9uYW1lID0gIm1pbiI7CisJCWVsc2UKKwkJCXJl dHVybiAtRU5PRU5UOworCX0gZWxzZSB7CisJCXJldHVybiAtRU5PRU5UOworCX0KKworCXNucHJp bnRmKGh3bW9uX2F0dHJfbmFtZSwgTUFYX0FUVFJfTEVOLCAiJXMlZF8lcyIsCisJCSBzZW5zb3Jf Z3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOworCXJldHVybiAwOworfQorCitz dGF0aWMgaW50IF9faW5pdCBwb3B1bGF0ZV9hdHRyX2dyb3VwcyhzdHJ1Y3QgcGxhdGZvcm1fZGV2 aWNlICpwZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dl dF9kcnZkYXRhKHBkZXYpOworCWNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKipwZ3JvdXBz ID0gcGRhdGEtPmF0dHJfZ3JvdXBzOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqb3BhbCwgKm5wOwor CWVudW0gc2Vuc29ycyB0eXBlOworCisJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJt LG9wYWwvc2Vuc29ycyIpOworCWlmICghb3BhbCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJP cGFsIG5vZGUgJ3NlbnNvcnMnIG5vdCBmb3VuZFxuIik7CisJCXJldHVybiAtRU5PREVWOworCX0K KworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKKwkJaWYgKG5wLT5uYW1lID09 IE5VTEwpCisJCQljb250aW51ZTsKKworCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNP Ul9UWVBFOyB0eXBlKyspCisJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCisJCQkJ CXNlbnNvcl9ncm91cHNbdHlwZV0uY29tcGF0aWJsZSkpIHsKKwkJCQlzZW5zb3JfZ3JvdXBzW3R5 cGVdLmF0dHJfY291bnQrKzsKKwkJCQlicmVhazsKKwkJCX0KKwl9CisKKwlvZl9ub2RlX3B1dChv cGFsKTsKKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHR5cGUrKykg eworCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzID0gZGV2bV9remFsbG9jKCZwZGV2 LT5kZXYsCisJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRlICopICoKKwkJCQkJKHNlbnNvcl9n cm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAorCQkJCQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFz ZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzKQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJ cGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOworCQlwZGF0YS0+c2Vu c29yc19jb3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7CisJCXNlbnNvcl9n cm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qCisg KiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5z b3JzJyBub2RlLCBjcmVhdGUKKyAqIGEgc3lzZnMgYXR0cmlidXRlIGZpbGUsIHRoZSBmaWxlIGlz IG5hbWVkIGJ5IHRyYW5zbGF0aW5nIHRoZSBEVCBub2RlIG5hbWUKKyAqIHRvIHRoZSBuYW1lIHJl cXVpcmVkIGJ5IHRoZSBoaWdoZXIgJ2h3bW9uJyBkcml2ZXIgbGlrZSBmYW4xX2lucHV0LCB0ZW1w MV9tYXgKKyAqIGV0Yy4uCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0 cnMoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcGxhdGZvcm1fZGF0 YSAqcGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKwljb25zdCBzdHJ1Y3QgYXR0 cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKKwlzdHJ1Y3QgZGV2 aWNlX25vZGUgKm9wYWwsICpucDsKKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOworCWNvbnN0 IF9fYmUzMiAqc2Vuc29yX2lkOworCWVudW0gc2Vuc29ycyB0eXBlOworCXUzMiBjb3VudCA9IDA7 CisJaW50IGVyciA9IDA7CisKKwlvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3Bh bC9zZW5zb3JzIik7CisJc2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgcGRhdGEtPnNl bnNvcnNfY291bnQgKiBzaXplb2YoKnNkYXRhKSwKKwkJCSAgICAgR0ZQX0tFUk5FTCk7CisJaWYg KCFzZGF0YSkgeworCQllcnIgPSAtRU5PTUVNOworCQlnb3RvIGV4aXRfcHV0X25vZGU7CisJfQor CisJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgeworCQlpZiAobnAtPm5hbWUgPT0g TlVMTCkKKwkJCWNvbnRpbnVlOworCisJCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09S X1RZUEU7IHR5cGUrKykKKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKKwkJCQkJ c2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKKwkJCQlicmVhazsKKworCQlpZiAodHlw ZSA9PSBNQVhfU0VOU09SX1RZUEUpCisJCQljb250aW51ZTsKKworCQlzZW5zb3JfaWQgPSBvZl9n ZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKKwkJaWYgKCFzZW5zb3JfaWQpIHsK KwkJCWRldl9pbmZvKCZwZGV2LT5kZXYsCisJCQkJICInc2Vuc29yLWlkJyBtaXNzaW5nIGluIHRo ZSBub2RlICclcydcbiIsCisJCQkJIG5wLT5uYW1lKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ c2RhdGFbY291bnRdLmlkID0gYmUzMl90b19jcHVwKHNlbnNvcl9pZCk7CisJCXNkYXRhW2NvdW50 XS50eXBlID0gdHlwZTsKKwkJZXJyID0gY3JlYXRlX2h3bW9uX2F0dHJfbmFtZSgmcGRldi0+ZGV2 LCB0eXBlLCBucC0+bmFtZSwKKwkJCQkJICAgICBzZGF0YVtjb3VudF0ubmFtZSk7CisJCWlmIChl cnIpCisJCQlnb3RvIGV4aXRfcHV0X25vZGU7CisKKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtj b3VudF0uZGV2X2F0dHIuYXR0cik7CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm5hbWUg PSBzZGF0YVtjb3VudF0ubmFtZTsKKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubW9kZSA9 IFNfSVJVR087CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7CisK KwkJcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50Kytd ID0KKwkJCQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKKwl9CisKK2V4aXRfcHV0X25v ZGU6CisJb2Zfbm9kZV9wdXQob3BhbCk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBf X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQorewor CXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7 CisJaW50IGVycjsKKworCXBkYXRhID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigq cGRhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKwor CXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKKwlwZGF0YS0+c2Vuc29yc19jb3Vu dCA9IDA7CisJZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7CisJaWYgKGVycikKKwkJ cmV0dXJuIGVycjsKKworCS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBz ZW5zb3IgZm91bmQgaW4gdGhlIERUICovCisJZXJyID0gY3JlYXRlX2RldmljZV9hdHRycyhwZGV2 KTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOworCisJLyogRmluYWxseSwgcmVnaXN0ZXIgd2l0 aCBod21vbiAqLworCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf Z3JvdXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCisJCQkJCQkJICAgcGRhdGEsCisJCQkJCQkJICAg cGRhdGEtPmF0dHJfZ3JvdXBzKTsKKworCXJldHVybiBQVFJfRVJSX09SX1pFUk8oaHdtb25fZGV2 KTsKK30KKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgaWJtcG93ZXJudl9kcml2ZXIg PSB7CisJLmRyaXZlciA9IHsKKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5uYW1lID0gRFJW TkFNRSwKKwl9LAorfTsKKworc3RhdGljIGludCBfX2luaXQgaWJtcG93ZXJudl9pbml0KHZvaWQp Cit7CisJaW50IGVycjsKKworCXBkZXZpY2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFN RSwgMCk7CisJaWYgKCFwZGV2aWNlKSB7CisJCXByX2VycigiRGV2aWNlIGFsbG9jYXRpb24gZmFp bGVkXG4iKTsKKwkJZXJyID0gLUVOT01FTTsKKwkJZ290byBleGl0OworCX0KKworCWVyciA9IHBs YXRmb3JtX2RldmljZV9hZGQocGRldmljZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIkRldmlj ZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJZ290byBleGl0X2RldmljZV9wdXQ7 CisJfQorCisJZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg aWJtcG93ZXJudl9wcm9iZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIlBsYXRmcm9tIGRyaXZl ciBwcm9iZSBmYWlsZWRcbiIpOworCQlnb3RvIGV4aXRfZGV2aWNlX2RlbDsKKwl9CisKKwlyZXR1 cm4gMDsKKworZXhpdF9kZXZpY2VfZGVsOgorCXBsYXRmb3JtX2RldmljZV9kZWwocGRldmljZSk7 CitleGl0X2RldmljZV9wdXQ6CisJcGxhdGZvcm1fZGV2aWNlX3B1dChwZGV2aWNlKTsKK2V4aXQ6 CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZvaWQgX19leGl0IGlibXBvd2VybnZfZXhpdCh2 b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dlcm52X2RyaXZlcik7 CisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIocGRldmljZSk7Cit9CisKK01PRFVMRV9BVVRI T1IoIk5lZWxlc2ggR3VwdGEgPG5lZWxlZ3VwQGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKK01PRFVM RV9ERVNDUklQVElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOworTU9EVUxFX0xJ Q0VOU0UoIkdQTCIpOworCittb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOworbW9kdWxlX2V4 aXQoaWJtcG93ZXJudl9leGl0KTsKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNv cnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNl bnNvcnM From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from e23smtp01.au.ibm.com (e23smtp01.au.ibm.com [202.81.31.143]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3EFE81A000B for ; Tue, 8 Jul 2014 19:09:15 +1000 (EST) Received: from /spool/local by e23smtp01.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 8 Jul 2014 19:09:13 +1000 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [9.190.235.21]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id 6F7B23578053 for ; Tue, 8 Jul 2014 19:09:09 +1000 (EST) Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s6898q1v9437664 for ; Tue, 8 Jul 2014 19:08:53 +1000 Received: from d23av03.au.ibm.com (localhost [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s689981L029669 for ; Tue, 8 Jul 2014 19:09:08 +1000 Subject: [PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature To: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, lm-sensors@lm-sensors.org From: Neelesh Gupta Date: Tue, 08 Jul 2014 14:38:38 +0530 Message-ID: <20140708090315.3866.15604.stgit@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Cc: sbhat@linux.vnet.ibm.com, linux@roeck-us.net, jdelvare@suse.de List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , This patch adds basic kernel support for reading power values, fan speed rpm, voltage and temperature data on powernv platforms which will be exported to user space through sysfs interface. Test results: ------------- [root@tul163p1 ~]# sensors ibmpowernv-isa-0000 Adapter: ISA adapter fan1: 5465 RPM (min = 0 RPM) fan2: 5152 RPM (min = 0 RPM) fan3: 5521 RPM (min = 0 RPM) fan4: 4891 RPM (min = 0 RPM) fan5: 0 RPM (min = 0 RPM) fan6: 0 RPM (min = 0 RPM) fan7: 7480 RPM (min = 0 RPM) fan8: 7944 RPM (min = 0 RPM) temp1: +39.0°C (high = +0.0°C) power1: 190.00 W [root@tul163p1 ~]# ls /sys/devices/platform/ alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/ device fan2_min fan4_min fan6_min fan8_min power fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input fan1_input fan3_input fan5_input fan7_input in2_fault subsystem fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max fan2_input fan4_input fan6_input fan8_input name uevent [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/ device fan2_min fan4_min fan6_min fan8_min power fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input fan1_input fan3_input fan5_input fan7_input in2_fault subsystem fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max fan2_input fan4_input fan6_input fan8_input name uevent [root@tul163p1 ~]# Signed-off-by: Neelesh Gupta Reviewed-by: Guenter Roeck --- Changes in v5 ============= - Addressed couple minor comments in v4. Changes in v4 ============= - Replaced pr_err() with dev_err() for logging print messages. - Using kstrtou32() function for converting string to u32 instead of sscanf(). Changes in v3 ============= - Fixed an endianness bug leading the driver to break on LE. - Fixed a bug that when one of the 'attribute_group' not populated, following groups attributes were dropped. - Rewrite the get_sensor_index_attr() function to handle all the error scenarios like 'sscanf' etc. - Fixed all the errors/warnings related to coding style/whitespace. - Added 'Documentation' files. - Addressed remaining review comments on V2. Changes in v2 ============= - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic memory request, avoiding the need to explicit free of memory. Adding 'struct attribute_group' as member of platform data structure to be populated and then passed to devm_hwmon_device_register_with_groups(). Note: Having an array of pointers of 'attribute_group' and each group corresponds to 'enum sensors' type. Not completely sure, if it's ideal or could have just one group populated with attributes of sensor types? - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' callback function (probe) as part of __init code. - Fixed issues related to coding style. - Other general comments in v1. .../devicetree/bindings/hwmon/ibmpowernv.txt | 23 + Documentation/hwmon/ibmpowernv | 41 ++ drivers/hwmon/Kconfig | 11 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpowernv.c | 364 ++++++++++++++++++++ 5 files changed, 440 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt create mode 100644 Documentation/hwmon/ibmpowernv create mode 100644 drivers/hwmon/ibmpowernv.c diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt new file mode 100644 index 0000000..f93242b --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt @@ -0,0 +1,23 @@ +IBM POWERNV platform sensors +---------------------------- + +Required node properties: +- compatible: must be one of + "ibm,opal-sensor-cooling-fan" + "ibm,opal-sensor-amb-temp" + "ibm,opal-sensor-power-supply" + "ibm,opal-sensor-power" +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a + given sensor and its attribute data + +Example sensors node: + +cooling-fan#8-data { + sensor-id = <0x7052107>; + compatible = "ibm,opal-sensor-cooling-fan"; +}; + +amb-temp#1-thrs { + sensor-id = <0x5096000>; + compatible = "ibm,opal-sensor-amb-temp"; +}; diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv new file mode 100644 index 0000000..644245a --- /dev/null +++ b/Documentation/hwmon/ibmpowernv @@ -0,0 +1,41 @@ +Kernel Driver IBMPOWENV +======================= + +Supported systems: + * Any recent IBM P servers based on POWERNV platform + +Author: Neelesh Gupta + +Description +----------- + +This driver implements reading the platform sensors data like temperature/fan/ +voltage/power for 'POWERNV' platform. + +The driver uses the platform device infrastructure. It probes the device tree +for sensor devices during the __init phase and registers them with the 'hwmon'. +'hwmon' populates the 'sysfs' tree having attribute files, each for a given +sensor type and its attribute data. + +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id' +which the driver uses to make an OPAL call to the firmware. + +Usage notes +----------- +The driver is built statically with the kernel by enabling the config +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'. + +Sysfs attributes +---------------- + +fanX_input Measured RPM value. +fanX_min Threshold RPM for alert generation. +fanX_fault 0: No fail condition + 1: Failing fan +tempX_input Measured ambient temperature. +tempX_max Threshold ambient temperature for alert generation. +inX_input Measured power supply voltage +inX_fault 0: No fail condition. + 1: Failing power supply. +power1_input System power consumption (microWatt) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 02d3d85..29c3fcb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -554,6 +554,17 @@ config SENSORS_IBMPEX This driver can also be built as a module. If so, the module will be called ibmpex. +config SENSORS_IBMPOWERNV + tristate "IBM POWERNV platform sensors" + depends on PPC_POWERNV + default y + help + If you say yes here you get support for the temperature/fan/power + sensors on your PowerNV platform. + + This driver can also be built as a module. If so, the module + will be called ibmpowernv. + config SENSORS_IIO_HWMON tristate "Hwmon driver that uses channels specified via iio maps" depends on IIO diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3dc0f02..fc4ed26 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o obj-$(CONFIG_SENSORS_INA209) += ina209.o obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c new file mode 100644 index 0000000..e6b652a --- /dev/null +++ b/drivers/hwmon/ibmpowernv.c @@ -0,0 +1,364 @@ +/* + * IBM PowerNV platform sensors for temperature/fan/voltage/power + * Copyright (C) 2014 IBM + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +#define DRVNAME "ibmpowernv" +#define pr_fmt(fmt) DRVNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_ATTR_LEN 32 + +/* Sensor suffix name from DT */ +#define DT_FAULT_ATTR_SUFFIX "faulted" +#define DT_DATA_ATTR_SUFFIX "data" +#define DT_THRESHOLD_ATTR_SUFFIX "thrs" + +/* + * Enumerates all the types of sensors in the POWERNV platform and does index + * into 'struct sensor_group' + */ +enum sensors { + FAN, + AMBIENT_TEMP, + POWER_SUPPLY, + POWER_INPUT, + MAX_SENSOR_TYPE, +}; + +static struct sensor_group { + const char *name; + const char *compatible; + struct attribute_group group; + u32 attr_count; +} sensor_groups[] = { + {"fan", "ibm,opal-sensor-cooling-fan"}, + {"temp", "ibm,opal-sensor-amb-temp"}, + {"in", "ibm,opal-sensor-power-supply"}, + {"power", "ibm,opal-sensor-power"} +}; + +struct sensor_data { + u32 id; /* An opaque id of the firmware for each sensor */ + enum sensors type; + char name[MAX_ATTR_LEN]; + struct device_attribute dev_attr; +}; + +struct platform_data { + const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1]; + u32 sensors_count; /* Total count of sensors from each group */ +}; + +/* Platform device representing all the ibmpowernv sensors */ +static struct platform_device *pdevice; + +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_data *sdata = container_of(devattr, struct sensor_data, + dev_attr); + ssize_t ret; + u32 x; + + ret = opal_get_sensor_data(sdata->id, &x); + if (ret) + return ret; + + /* Convert temperature to milli-degrees */ + if (sdata->type == AMBIENT_TEMP) + x *= 1000; + /* Convert power to micro-watts */ + else if (sdata->type == POWER_INPUT) + x *= 1000000; + + return sprintf(buf, "%u\n", x); +} + +static int __init get_sensor_index_attr(const char *name, u32 *index, + char *attr) +{ + char *hash_pos = strchr(name, '#'); + char buf[8] = { 0 }; + char *dash_pos; + u32 copy_len; + int err; + + if (!hash_pos) + return -EINVAL; + + dash_pos = strchr(hash_pos, '-'); + if (!dash_pos) + return -EINVAL; + + copy_len = dash_pos - hash_pos - 1; + if (copy_len >= sizeof(buf)) + return -EINVAL; + + strncpy(buf, hash_pos + 1, copy_len); + + err = kstrtou32(buf, 10, index); + if (err) + return err; + + strncpy(attr, dash_pos + 1, MAX_ATTR_LEN); + + return 0; +} + +/* + * This function translates the DT node name into the 'hwmon' attribute name. + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc. + * which need to be mapped as fan2_input, temp1_max respectively before + * populating them inside hwmon device class. + */ +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, + const char *node_name, + char *hwmon_attr_name) +{ + char attr_suffix[MAX_ATTR_LEN]; + char *attr_name; + u32 index; + int err; + + err = get_sensor_index_attr(node_name, &index, attr_suffix); + if (err) { + dev_err(dev, "Sensor device node name '%s' is invalid\n", + node_name); + return err; + } + + if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) { + attr_name = "fault"; + } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) { + attr_name = "input"; + } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) { + if (type == AMBIENT_TEMP) + attr_name = "max"; + else if (type == FAN) + attr_name = "min"; + else + return -ENOENT; + } else { + return -ENOENT; + } + + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", + sensor_groups[type].name, index, attr_name); + return 0; +} + +static int __init populate_attr_groups(struct platform_device *pdev) +{ + struct platform_data *pdata = platform_get_drvdata(pdev); + const struct attribute_group **pgroups = pdata->attr_groups; + struct device_node *opal, *np; + enum sensors type; + + opal = of_find_node_by_path("/ibm,opal/sensors"); + if (!opal) { + dev_err(&pdev->dev, "Opal node 'sensors' not found\n"); + return -ENODEV; + } + + for_each_child_of_node(opal, np) { + if (np->name == NULL) + continue; + + for (type = 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) { + sensor_groups[type].attr_count++; + break; + } + } + + of_node_put(opal); + + for (type = 0; type < MAX_SENSOR_TYPE; type++) { + sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev, + sizeof(struct attribute *) * + (sensor_groups[type].attr_count + 1), + GFP_KERNEL); + if (!sensor_groups[type].group.attrs) + return -ENOMEM; + + pgroups[type] = &sensor_groups[type].group; + pdata->sensors_count += sensor_groups[type].attr_count; + sensor_groups[type].attr_count = 0; + } + + return 0; +} + +/* + * Iterate through the device tree for each child of 'sensors' node, create + * a sysfs attribute file, the file is named by translating the DT node name + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max + * etc.. + */ +static int __init create_device_attrs(struct platform_device *pdev) +{ + struct platform_data *pdata = platform_get_drvdata(pdev); + const struct attribute_group **pgroups = pdata->attr_groups; + struct device_node *opal, *np; + struct sensor_data *sdata; + const __be32 *sensor_id; + enum sensors type; + u32 count = 0; + int err = 0; + + opal = of_find_node_by_path("/ibm,opal/sensors"); + sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata), + GFP_KERNEL); + if (!sdata) { + err = -ENOMEM; + goto exit_put_node; + } + + for_each_child_of_node(opal, np) { + if (np->name == NULL) + continue; + + for (type = 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) + break; + + if (type == MAX_SENSOR_TYPE) + continue; + + sensor_id = of_get_property(np, "sensor-id", NULL); + if (!sensor_id) { + dev_info(&pdev->dev, + "'sensor-id' missing in the node '%s'\n", + np->name); + continue; + } + + sdata[count].id = be32_to_cpup(sensor_id); + sdata[count].type = type; + err = create_hwmon_attr_name(&pdev->dev, type, np->name, + sdata[count].name); + if (err) + goto exit_put_node; + + sysfs_attr_init(&sdata[count].dev_attr.attr); + sdata[count].dev_attr.attr.name = sdata[count].name; + sdata[count].dev_attr.attr.mode = S_IRUGO; + sdata[count].dev_attr.show = show_sensor; + + pgroups[type]->attrs[sensor_groups[type].attr_count++] = + &sdata[count++].dev_attr.attr; + } + +exit_put_node: + of_node_put(opal); + return err; +} + +static int __init ibmpowernv_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct device *hwmon_dev; + int err; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + platform_set_drvdata(pdev, pdata); + pdata->sensors_count = 0; + err = populate_attr_groups(pdev); + if (err) + return err; + + /* Create sysfs attribute data for each sensor found in the DT */ + err = create_device_attrs(pdev); + if (err) + return err; + + /* Finally, register with hwmon */ + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME, + pdata, + pdata->attr_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct platform_driver ibmpowernv_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, +}; + +static int __init ibmpowernv_init(void) +{ + int err; + + pdevice = platform_device_alloc(DRVNAME, 0); + if (!pdevice) { + pr_err("Device allocation failed\n"); + err = -ENOMEM; + goto exit; + } + + err = platform_device_add(pdevice); + if (err) { + pr_err("Device addition failed (%d)\n", err); + goto exit_device_put; + } + + err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe); + if (err) { + pr_err("Platfrom driver probe failed\n"); + goto exit_device_del; + } + + return 0; + +exit_device_del: + platform_device_del(pdevice); +exit_device_put: + platform_device_put(pdevice); +exit: + return err; +} + +static void __exit ibmpowernv_exit(void) +{ + platform_driver_unregister(&ibmpowernv_driver); + platform_device_unregister(pdevice); +} + +MODULE_AUTHOR("Neelesh Gupta "); +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +MODULE_LICENSE("GPL"); + +module_init(ibmpowernv_init); +module_exit(ibmpowernv_exit); From mboxrd@z Thu Jan 1 00:00:00 1970 From: Neelesh Gupta Subject: [PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature Date: Tue, 08 Jul 2014 14:38:38 +0530 Message-ID: <20140708090315.3866.15604.stgit@localhost.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: Sender: devicetree-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org, lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org Cc: benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org, svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org, sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org, jdelvare-l3A5Bk7waGM@public.gmane.org, linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org List-Id: devicetree@vger.kernel.org This patch adds basic kernel support for reading power values, fan speed rpm, voltage and temperature data on powernv platforms which will be exported to user space through sysfs interface. Test results: ------------- [root@tul163p1 ~]# sensors ibmpowernv-isa-0000 Adapter: ISA adapter fan1: 5465 RPM (min =3D 0 RPM) fan2: 5152 RPM (min =3D 0 RPM) fan3: 5521 RPM (min =3D 0 RPM) fan4: 4891 RPM (min =3D 0 RPM) fan5: 0 RPM (min =3D 0 RPM) fan6: 0 RPM (min =3D 0 RPM) fan7: 7480 RPM (min =3D 0 RPM) fan8: 7944 RPM (min =3D 0 RPM) temp1: +39.0=C2=B0C (high =3D +0.0=C2=B0C) power1: 190.00 W =20 [root@tul163p1 ~]# ls /sys/devices/platform/ alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/ device fan2_min fan4_min fan6_min fan8_min power fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input fan1_input fan3_input fan5_input fan7_input in2_fault subsystem fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max fan2_input fan4_input fan6_input fan8_input name uevent [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/ device fan2_min fan4_min fan6_min fan8_min power fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input fan1_input fan3_input fan5_input fan7_input in2_fault subsystem fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max fan2_input fan4_input fan6_input fan8_input name uevent [root@tul163p1 ~]# Signed-off-by: Neelesh Gupta Reviewed-by: Guenter Roeck --- Changes in v5 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - Addressed couple minor comments in v4. Changes in v4 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - Replaced pr_err() with dev_err() for logging print messages. - Using kstrtou32() function for converting string to u32 instead of ss= canf(). Changes in v3 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - Fixed an endianness bug leading the driver to break on LE. - Fixed a bug that when one of the 'attribute_group' not populated, fol= lowing groups attributes were dropped. - Rewrite the get_sensor_index_attr() function to handle all the error = scenarios like 'sscanf' etc. - Fixed all the errors/warnings related to coding style/whitespace. - Added 'Documentation' files. - Addressed remaining review comments on V2. Changes in v2 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D - Generic use of devm_* functions in hwmon like using devm_kzalloc() fo= r dynamic memory request, avoiding the need to explicit free of memory. Adding 'struct attribute_group' as member of platform data structure = to be populated and then passed to devm_hwmon_device_register_with_groups()= =2E Note: Having an array of pointers of 'attribute_group' and each group corresponds to 'enum sensors' type. Not completely sure, if it's idea= l or could have just one group populated with attributes of sensor types? - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' = callback function (probe) as part of __init code. - Fixed issues related to coding style. - Other general comments in v1. .../devicetree/bindings/hwmon/ibmpowernv.txt | 23 + Documentation/hwmon/ibmpowernv | 41 ++ drivers/hwmon/Kconfig | 11 + drivers/hwmon/Makefile | 1=20 drivers/hwmon/ibmpowernv.c | 364 ++++++++++++= ++++++++ 5 files changed, 440 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.= txt create mode 100644 Documentation/hwmon/ibmpowernv create mode 100644 drivers/hwmon/ibmpowernv.c diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/D= ocumentation/devicetree/bindings/hwmon/ibmpowernv.txt new file mode 100644 index 0000000..f93242b --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt @@ -0,0 +1,23 @@ +IBM POWERNV platform sensors +---------------------------- + +Required node properties: +- compatible: must be one of + "ibm,opal-sensor-cooling-fan" + "ibm,opal-sensor-amb-temp" + "ibm,opal-sensor-power-supply" + "ibm,opal-sensor-power" +- sensor-id: an opaque id provided by the firmware to the kernel, iden= tifies a + given sensor and its attribute data + +Example sensors node: + +cooling-fan#8-data { + sensor-id =3D <0x7052107>; + compatible =3D "ibm,opal-sensor-cooling-fan"; +}; + +amb-temp#1-thrs { + sensor-id =3D <0x5096000>; + compatible =3D "ibm,opal-sensor-amb-temp"; +}; diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpo= wernv new file mode 100644 index 0000000..644245a --- /dev/null +++ b/Documentation/hwmon/ibmpowernv @@ -0,0 +1,41 @@ +Kernel Driver IBMPOWENV +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Supported systems: + * Any recent IBM P servers based on POWERNV platform + +Author: Neelesh Gupta + +Description +----------- + +This driver implements reading the platform sensors data like temperat= ure/fan/ +voltage/power for 'POWERNV' platform. + +The driver uses the platform device infrastructure. It probes the devi= ce tree +for sensor devices during the __init phase and registers them with the= 'hwmon'. +'hwmon' populates the 'sysfs' tree having attribute files, each for a = given +sensor type and its attribute data. + +All the nodes in the DT appear under "/ibm,opal/sensors" and each vali= d node in +the DT maps to an attribute file in 'sysfs'. The node exports unique '= sensor-id' +which the driver uses to make an OPAL call to the firmware. + +Usage notes +----------- +The driver is built statically with the kernel by enabling the config +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'= =2E + +Sysfs attributes +---------------- + +fanX_input Measured RPM value. +fanX_min Threshold RPM for alert generation. +fanX_fault 0: No fail condition + 1: Failing fan +tempX_input Measured ambient temperature. +tempX_max Threshold ambient temperature for alert generation. +inX_input Measured power supply voltage +inX_fault 0: No fail condition. + 1: Failing power supply. +power1_input System power consumption (microWatt) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 02d3d85..29c3fcb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -554,6 +554,17 @@ config SENSORS_IBMPEX This driver can also be built as a module. If so, the module will be called ibmpex. =20 +config SENSORS_IBMPOWERNV + tristate "IBM POWERNV platform sensors" + depends on PPC_POWERNV + default y + help + If you say yes here you get support for the temperature/fan/power + sensors on your PowerNV platform. + + This driver can also be built as a module. If so, the module + will be called ibmpowernv. + config SENSORS_IIO_HWMON tristate "Hwmon driver that uses channels specified via iio maps" depends on IIO diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3dc0f02..fc4ed26 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) +=3D ultra45_env.o obj-$(CONFIG_SENSORS_I5K_AMB) +=3D i5k_amb.o obj-$(CONFIG_SENSORS_IBMAEM) +=3D ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) +=3D ibmpex.o +obj-$(CONFIG_SENSORS_IBMPOWERNV)+=3D ibmpowernv.o obj-$(CONFIG_SENSORS_IIO_HWMON) +=3D iio_hwmon.o obj-$(CONFIG_SENSORS_INA209) +=3D ina209.o obj-$(CONFIG_SENSORS_INA2XX) +=3D ina2xx.o diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c new file mode 100644 index 0000000..e6b652a --- /dev/null +++ b/drivers/hwmon/ibmpowernv.c @@ -0,0 +1,364 @@ +/* + * IBM PowerNV platform sensors for temperature/fan/voltage/power + * Copyright (C) 2014 IBM + * + * This program is free software; you can redistribute it and/or modif= y + * it under the terms of the GNU General Public License as published b= y + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +#define DRVNAME "ibmpowernv" +#define pr_fmt(fmt) DRVNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_ATTR_LEN 32 + +/* Sensor suffix name from DT */ +#define DT_FAULT_ATTR_SUFFIX "faulted" +#define DT_DATA_ATTR_SUFFIX "data" +#define DT_THRESHOLD_ATTR_SUFFIX "thrs" + +/* + * Enumerates all the types of sensors in the POWERNV platform and doe= s index + * into 'struct sensor_group' + */ +enum sensors { + FAN, + AMBIENT_TEMP, + POWER_SUPPLY, + POWER_INPUT, + MAX_SENSOR_TYPE, +}; + +static struct sensor_group { + const char *name; + const char *compatible; + struct attribute_group group; + u32 attr_count; +} sensor_groups[] =3D { + {"fan", "ibm,opal-sensor-cooling-fan"}, + {"temp", "ibm,opal-sensor-amb-temp"}, + {"in", "ibm,opal-sensor-power-supply"}, + {"power", "ibm,opal-sensor-power"} +}; + +struct sensor_data { + u32 id; /* An opaque id of the firmware for each sensor */ + enum sensors type; + char name[MAX_ATTR_LEN]; + struct device_attribute dev_attr; +}; + +struct platform_data { + const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1]; + u32 sensors_count; /* Total count of sensors from each group */ +}; + +/* Platform device representing all the ibmpowernv sensors */ +static struct platform_device *pdevice; + +static ssize_t show_sensor(struct device *dev, struct device_attribute= *devattr, + char *buf) +{ + struct sensor_data *sdata =3D container_of(devattr, struct sensor_dat= a, + dev_attr); + ssize_t ret; + u32 x; + + ret =3D opal_get_sensor_data(sdata->id, &x); + if (ret) + return ret; + + /* Convert temperature to milli-degrees */ + if (sdata->type =3D=3D AMBIENT_TEMP) + x *=3D 1000; + /* Convert power to micro-watts */ + else if (sdata->type =3D=3D POWER_INPUT) + x *=3D 1000000; + + return sprintf(buf, "%u\n", x); +} + +static int __init get_sensor_index_attr(const char *name, u32 *index, + char *attr) +{ + char *hash_pos =3D strchr(name, '#'); + char buf[8] =3D { 0 }; + char *dash_pos; + u32 copy_len; + int err; + + if (!hash_pos) + return -EINVAL; + + dash_pos =3D strchr(hash_pos, '-'); + if (!dash_pos) + return -EINVAL; + + copy_len =3D dash_pos - hash_pos - 1; + if (copy_len >=3D sizeof(buf)) + return -EINVAL; + + strncpy(buf, hash_pos + 1, copy_len); + + err =3D kstrtou32(buf, 10, index); + if (err) + return err; + + strncpy(attr, dash_pos + 1, MAX_ATTR_LEN); + + return 0; +} + +/* + * This function translates the DT node name into the 'hwmon' attribut= e name. + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-t= hrs etc. + * which need to be mapped as fan2_input, temp1_max respectively befor= e + * populating them inside hwmon device class. + */ +static int __init create_hwmon_attr_name(struct device *dev, enum sens= ors type, + const char *node_name, + char *hwmon_attr_name) +{ + char attr_suffix[MAX_ATTR_LEN]; + char *attr_name; + u32 index; + int err; + + err =3D get_sensor_index_attr(node_name, &index, attr_suffix); + if (err) { + dev_err(dev, "Sensor device node name '%s' is invalid\n", + node_name); + return err; + } + + if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) { + attr_name =3D "fault"; + } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) { + attr_name =3D "input"; + } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) { + if (type =3D=3D AMBIENT_TEMP) + attr_name =3D "max"; + else if (type =3D=3D FAN) + attr_name =3D "min"; + else + return -ENOENT; + } else { + return -ENOENT; + } + + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", + sensor_groups[type].name, index, attr_name); + return 0; +} + +static int __init populate_attr_groups(struct platform_device *pdev) +{ + struct platform_data *pdata =3D platform_get_drvdata(pdev); + const struct attribute_group **pgroups =3D pdata->attr_groups; + struct device_node *opal, *np; + enum sensors type; + + opal =3D of_find_node_by_path("/ibm,opal/sensors"); + if (!opal) { + dev_err(&pdev->dev, "Opal node 'sensors' not found\n"); + return -ENODEV; + } + + for_each_child_of_node(opal, np) { + if (np->name =3D=3D NULL) + continue; + + for (type =3D 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) { + sensor_groups[type].attr_count++; + break; + } + } + + of_node_put(opal); + + for (type =3D 0; type < MAX_SENSOR_TYPE; type++) { + sensor_groups[type].group.attrs =3D devm_kzalloc(&pdev->dev, + sizeof(struct attribute *) * + (sensor_groups[type].attr_count + 1), + GFP_KERNEL); + if (!sensor_groups[type].group.attrs) + return -ENOMEM; + + pgroups[type] =3D &sensor_groups[type].group; + pdata->sensors_count +=3D sensor_groups[type].attr_count; + sensor_groups[type].attr_count =3D 0; + } + + return 0; +} + +/* + * Iterate through the device tree for each child of 'sensors' node, c= reate + * a sysfs attribute file, the file is named by translating the DT nod= e name + * to the name required by the higher 'hwmon' driver like fan1_input, = temp1_max + * etc.. + */ +static int __init create_device_attrs(struct platform_device *pdev) +{ + struct platform_data *pdata =3D platform_get_drvdata(pdev); + const struct attribute_group **pgroups =3D pdata->attr_groups; + struct device_node *opal, *np; + struct sensor_data *sdata; + const __be32 *sensor_id; + enum sensors type; + u32 count =3D 0; + int err =3D 0; + + opal =3D of_find_node_by_path("/ibm,opal/sensors"); + sdata =3D devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sda= ta), + GFP_KERNEL); + if (!sdata) { + err =3D -ENOMEM; + goto exit_put_node; + } + + for_each_child_of_node(opal, np) { + if (np->name =3D=3D NULL) + continue; + + for (type =3D 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) + break; + + if (type =3D=3D MAX_SENSOR_TYPE) + continue; + + sensor_id =3D of_get_property(np, "sensor-id", NULL); + if (!sensor_id) { + dev_info(&pdev->dev, + "'sensor-id' missing in the node '%s'\n", + np->name); + continue; + } + + sdata[count].id =3D be32_to_cpup(sensor_id); + sdata[count].type =3D type; + err =3D create_hwmon_attr_name(&pdev->dev, type, np->name, + sdata[count].name); + if (err) + goto exit_put_node; + + sysfs_attr_init(&sdata[count].dev_attr.attr); + sdata[count].dev_attr.attr.name =3D sdata[count].name; + sdata[count].dev_attr.attr.mode =3D S_IRUGO; + sdata[count].dev_attr.show =3D show_sensor; + + pgroups[type]->attrs[sensor_groups[type].attr_count++] =3D + &sdata[count++].dev_attr.attr; + } + +exit_put_node: + of_node_put(opal); + return err; +} + +static int __init ibmpowernv_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct device *hwmon_dev; + int err; + + pdata =3D devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + platform_set_drvdata(pdev, pdata); + pdata->sensors_count =3D 0; + err =3D populate_attr_groups(pdev); + if (err) + return err; + + /* Create sysfs attribute data for each sensor found in the DT */ + err =3D create_device_attrs(pdev); + if (err) + return err; + + /* Finally, register with hwmon */ + hwmon_dev =3D devm_hwmon_device_register_with_groups(&pdev->dev, DRVN= AME, + pdata, + pdata->attr_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct platform_driver ibmpowernv_driver =3D { + .driver =3D { + .owner =3D THIS_MODULE, + .name =3D DRVNAME, + }, +}; + +static int __init ibmpowernv_init(void) +{ + int err; + + pdevice =3D platform_device_alloc(DRVNAME, 0); + if (!pdevice) { + pr_err("Device allocation failed\n"); + err =3D -ENOMEM; + goto exit; + } + + err =3D platform_device_add(pdevice); + if (err) { + pr_err("Device addition failed (%d)\n", err); + goto exit_device_put; + } + + err =3D platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe); + if (err) { + pr_err("Platfrom driver probe failed\n"); + goto exit_device_del; + } + + return 0; + +exit_device_del: + platform_device_del(pdevice); +exit_device_put: + platform_device_put(pdevice); +exit: + return err; +} + +static void __exit ibmpowernv_exit(void) +{ + platform_driver_unregister(&ibmpowernv_driver); + platform_device_unregister(pdevice); +} + +MODULE_AUTHOR("Neelesh Gupta "); +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +MODULE_LICENSE("GPL"); + +module_init(ibmpowernv_init); +module_exit(ibmpowernv_exit); -- To unsubscribe from this list: send the line "unsubscribe devicetree" i= n the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html