diff for duplicates of <5696500E.4090905@roeck-us.net> diff --git a/a/1.txt b/N1/1.txt index 8e7a044..65b7f97 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,190 +1,339 @@ -T24gMDEvMTMvMjAxNiAwMzowNSBBTSwgTWlrZSBMb29pam1hbnMgd3JvdGU6Cj4gVGhpcyBhZGRz -IHN1cHBvcnQgZm9yIHRoZSBMaW5lYXIgVGVjaG5vbG9neSBMVEMyOTkwICBJMkMgU3lzdGVtIE1v -bml0b3IuCj4gVGhlIExUQzI5OTAgc3VwcG9ydHMgYSBjb21iaW5hdGlvbiBvZiB2b2x0YWdlLCBj -dXJyZW50IGFuZCB0ZW1wZXJhdHVyZQo+IG1vbml0b3JpbmcuIFRoaXMgZHJpdmVyIGN1cnJlbnRs -eSBvbmx5IHN1cHBvcnRzIHJlYWRpbmcgdHdvIGN1cnJlbnRzCj4gYnkgbWVhc3VyaW5nIHR3byBk -aWZmZXJlbnRpYWwgdm9sdGFnZXMgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMsIGluCj4gYWRkaXRp -b24gdG8gdGhlIFZjYyBzdXBwbHkgdm9sdGFnZSBhbmQgaW50ZXJuYWwgdGVtcGVyYXR1cmUuCj4K -PiBUaGlzIGlzIHN1ZmZpY2llbnQgdG8gc3VwcG9ydCB0aGUgVG9waWMgTWlhbWkgU09NIHdoaWNo -IHVzZXMgdGhpcyBjaGlwCj4gdG8gbW9uaXRvciB0aGUgY3VycmVudHMgZmxvd2luZyBpbnRvIHRo -ZSBGUEdBIGFuZCB0aGUgQ1BVIHBhcnRzLgo+Cj4gU2lnbmVkLW9mZi1ieTogTWlrZSBMb29pam1h -bnMgPG1pa2UubG9vaWptYW5zQHRvcGljLm5sPgoKTWlrZSwKClRoYXQgbG9va3MgbXVjaCBiZXR0 -ZXIuIENhbiB5b3Ugc2VuZCBtZSB0aGUgb3V0cHV0IG9mIGkyY2R1bXAgZm9yIHRoZSBjaGlwID8K -VGhhdCB3b3VsZCBoZWxwIG1lIHdyaXRpbmcgbW9kdWxlIHRlc3QgY29kZSBmb3IgaXQuCgpUaGFu -a3MsCkd1ZW50ZXIKCj4gLS0tCj4gdjI6IFByb2Nlc3NlZCBhbGwgcmV2aWV3IGNvbW1lbnRzLgo+ -ICAgICAgUHV0IGNoaXAgaW50byBjb250aW51b3VzIG1lYXN1cmVtZW50IG1vZGUuCj4gICAgICBB -ZGRlZCBkdWN1bWVudGF0aW9uLgo+ICAgICAgVXNlIHN0YW5kYXJkIGh3bW9uIGludGVyZmFjZXMg -YW5kIG1hY3Jvcy4KPgo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9sdGMyOTkwIHwgIDQ0ICsrKysr -KysrKysrKwo+ICAgZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgIHwgIDE0ICsrKysKPiAgIGRy -aXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICB8ICAgMSArCj4gICBkcml2ZXJzL2h3bW9uL2x0YzI5 -OTAuYyAgICAgfCAxNjAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr -KysKPiAgIDQgZmlsZXMgY2hhbmdlZCwgMjE5IGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2Rl -IDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2x0YzI5OTAKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0 -NCBkcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24v -aHdtb24vbHRjMjk5MCBiL0RvY3VtZW50YXRpb24vaHdtb24vbHRjMjk5MAo+IG5ldyBmaWxlIG1v -ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uODM4Yjc0ZQo+IC0tLSAvZGV2L251bGwKPiArKysg -Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2x0YzI5OTAKPiBAQCAtMCwwICsxLDQ0IEBACj4gK0tlcm5l -bCBkcml2ZXIgbHRjMjk5MAo+ICs9PT09PT09PT09PT09PT09PT09PT0KPiArCj4gK1N1cHBvcnRl -ZCBjaGlwczoKPiArICAqIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAKPiArICAgIFByZWZpeDog -J2x0YzI5OTAnCj4gKyAgICBBZGRyZXNzZXMgc2Nhbm5lZDogLQo+ICsgICAgRGF0YXNoZWV0OiBo -dHRwOi8vd3d3LmxpbmVhci5jb20vcHJvZHVjdC9sdGMyOTkwCj4gKwo+ICtBdXRob3I6IE1pa2Ug -TG9vaWptYW5zIDxtaWtlLmxvb2lqbWFuc0B0b3BpYy5ubD4KPiArCj4gKwo+ICtEZXNjcmlwdGlv -bgo+ICstLS0tLS0tLS0tLQo+ICsKPiArTFRDMjk5MCBpcyBhIFF1YWQgSTJDIFZvbHRhZ2UsIEN1 -cnJlbnQgYW5kIFRlbXBlcmF0dXJlIE1vbml0b3IuCj4gK1RoZSBjaGlwJ3MgaW5wdXRzIGNhbiBt -ZWFzdXJlIDQgdm9sdGFnZXMsIG9yIHR3byBpbnB1dHMgdG9nZXRoZXIgKDErMiBhbmQgMys0KQo+ -ICtjYW4gYmUgY29tYmluZWQgdG8gbWVhc3VyZSBhIGRpZmZlcmVudGlhbCB2b2x0YWdlLCB3aGlj -aCBpcyB0eXBpY2FsbHkgdXNlZCB0bwo+ICttZWFzdXJlIGN1cnJlbnQgdGhyb3VnaCBhIHNlcmll -cyByZXNpc3Rvciwgb3IgYSB0ZW1wZXJhdHVyZS4KPiArCj4gK1RoaXMgZHJpdmVyIGN1cnJlbnRs -eSB1c2VzIHRoZSAyeCBkaWZmZXJlbnRpYWwgbW9kZSBvbmx5LiBJbiBvcmRlciB0byBzdXBwb3J0 -Cj4gK290aGVyIG1vZGVzLCB0aGUgZHJpdmVyIHdpbGwgbmVlZCB0byBiZSBleHBhbmRlZC4KPiAr -Cj4gKwo+ICtVc2FnZSBOb3Rlcwo+ICstLS0tLS0tLS0tLQo+ICsKPiArVGhpcyBkcml2ZXIgZG9l -cyBub3QgcHJvYmUgZm9yIFBNQnVzIGRldmljZXMuIFlvdSB3aWxsIGhhdmUgdG8gaW5zdGFudGlh -dGUKPiArZGV2aWNlcyBleHBsaWNpdGx5Lgo+ICsKPiArCj4gK1N5c2ZzIGF0dHJpYnV0ZXMKPiAr -LS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArVGhlICJjdXJyKl9pbnB1dCIgbWVhc3VyZW1lbnRzIGFj -dHVhbGx5IHJlcG9ydCB0aGUgdm9sdGFnZSBkcm9wIGFjcm9zcyB0aGUKPiAraW5wdXQgcGlucyBp -biBtaWNyb3ZvbHRzLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gdGhlIGN1cnJlbnQgdGhyb3VnaCBh -IDFtT2htCj4gK3NlbnNlIHJlc2lzdG9yLiBEaXZpZGUgdGhlIHJlcG9ydGVkIHZhbHVlIGJ5IHRo -ZSBhY3R1YWwgc2Vuc2UgcmVzaXN0b3IgdmFsdWUKPiAraW4gbU9obSB0byBnZXQgdGhlIGFjdHVh -bCB2YWx1ZS4KPiArCj4gK2luMF9pbnB1dCAgICAgVm9sdGFnZSBhdCBWY2MgcGluIGluIG1pbGxp -dm9sdCAocmFuZ2UgMi41ViB0byA1VikKPiArdGVtcDFfaW5wdXQgICBJbnRlcm5hbCBjaGlwIHRl -bXBlcmF0dXJlIGluIG1pbGxpZGVncmVlcyBDZWxjaXVzCj4gK2N1cnIxX2lucHV0ICAgQ3VycmVu -dCBpbiBtQSBhY3Jvc3MgdjEtdjIgYXNzdW1pbmcgYSAxbU9obSBzZW5zZSByZXNpc3Rvci4KPiAr -Y3VycjJfaW5wdXQgICBDdXJyZW50IGluIG1BIGFjcm9zcyB2My12NCBhc3N1bWluZyBhIDFtT2ht -IHNlbnNlIHJlc2lzdG9yLgo+ICsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmln -IGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4gaW5kZXggODBhNzNiZi4uOGEzMWQ2NCAxMDA2NDQK -PiAtLS0gYS9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25m -aWcKPiBAQCAtNjg1LDYgKzY4NSwyMCBAQCBjb25maWcgU0VOU09SU19MVEMyOTQ1Cj4gICAJICBU -aGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1 -bGUgd2lsbAo+ICAgCSAgYmUgY2FsbGVkIGx0YzI5NDUuCj4KPiArY29uZmlnIFNFTlNPUlNfTFRD -Mjk5MAo+ICsJdHJpc3RhdGUgIkxpbmVhciBUZWNobm9sb2d5IExUQzI5OTAgKGN1cnJlbnQgbW9u -aXRvcmluZyBtb2RlIG9ubHkpIgo+ICsJZGVwZW5kcyBvbiBJMkMKPiArCWhlbHAKPiArCSAgSWYg -eW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIExpbmVhciBUZWNobm9sb2d5IExU -QzI5OTAKPiArCSAgSTJDIFN5c3RlbSBNb25pdG9yLiBUaGUgTFRDMjk5MCBzdXBwb3J0cyBhIGNv -bWJpbmF0aW9uIG9mIHZvbHRhZ2UsCj4gKwkgIGN1cnJlbnQgYW5kIHRlbXBlcmF0dXJlIG1vbml0 -b3JpbmcsIGJ1dCBpbiBhZGRpdGlvbiB0byB0aGUgVmNjIHN1cHBseQo+ICsJICB2b2x0YWdlIGFu -ZCBjaGlwIHRlbXBlcmF0dXJlLCB0aGlzIGRyaXZlciBjdXJyZW50bHkgb25seSBzdXBwb3J0cwo+ -ICsJICByZWFkaW5nIHR3byBjdXJyZW50cyBieSBtZWFzdXJpbmcgdHdvIGRpZmZlcmVudGlhbCB2 -b2x0YWdlcyBhY3Jvc3MKPiArCSAgc2VyaWVzIHJlc2lzdG9ycy4KPiArCj4gKwkgIFRoaXMgZHJp -dmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZSB3aWxs -Cj4gKwkgIGJlIGNhbGxlZCBsdGMyOTkwLgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0xUQzQxNTEK -PiAgIAl0cmlzdGF0ZSAiTGluZWFyIFRlY2hub2xvZ3kgTFRDNDE1MSIKPiAgIAlkZXBlbmRzIG9u -IEkyQwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlIGIvZHJpdmVycy9od21v -bi9NYWtlZmlsZQo+IGluZGV4IDEyYTMyMzkuLmU0YmQxNWIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVy -cy9od21vbi9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBAQCAtMTAx -LDYgKzEwMSw3IEBAIG9iai0kKENPTkZJR19TRU5TT1JTX0xNOTUyMzQpCSs9IGxtOTUyMzQubwo+ -ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfTE05NTI0MSkJKz0gbG05NTI0MS5vCj4gICBvYmotJChD -T05GSUdfU0VOU09SU19MTTk1MjQ1KQkrPSBsbTk1MjQ1Lm8KPiAgIG9iai0kKENPTkZJR19TRU5T -T1JTX0xUQzI5NDUpCSs9IGx0YzI5NDUubwo+ICtvYmotJChDT05GSUdfU0VOU09SU19MVEMyOTkw -KQkrPSBsdGMyOTkwLm8KPiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQxNTEpCSs9IGx0YzQx -NTEubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfTFRDNDIxNSkJKz0gbHRjNDIxNS5vCj4gICBv -YmotJChDT05GSUdfU0VOU09SU19MVEM0MjIyKQkrPSBsdGM0MjIyLm8KPiBkaWZmIC0tZ2l0IGEv -ZHJpdmVycy9od21vbi9sdGMyOTkwLmMgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+IG5ldyBm -aWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uMzcyMGZmNwo+IC0tLSAvZGV2L251bGwK -PiArKysgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8q -Cj4gKyAqIERyaXZlciBmb3IgTGluZWFyIFRlY2hub2xvZ3kgTFRDMjk5MCBwb3dlciBtb25pdG9y -Cj4gKyAqCj4gKyAqIENvcHlyaWdodCAoQykgMjAxNCBUb3BpYyBFbWJlZGRlZCBQcm9kdWN0cwo+ -ICsgKiBBdXRob3I6IE1pa2UgTG9vaWptYW5zIDxtaWtlLmxvb2lqbWFuc0B0b3BpYy5ubD4KPiAr -ICoKPiArICogTGljZW5zZTogR1BMdjIKPiArICoKPiArICogVGhpcyBkcml2ZXIgYXNzdW1lcyB0 -aGUgY2hpcCBpcyB3aXJlZCBhcyBhIGR1YWwgY3VycmVudCBtb25pdG9yLCBhbmQKPiArICogcmVw -b3J0cyB0aGUgdm9sdGFnZSBkcm9wIGFjcm9zcyB0d28gc2VyaWVzIHJlc2lzdG9ycy4gSXQgYWxz -byByZXBvcnRzCj4gKyAqIHRoZSBjaGlwJ3MgaW50ZXJuYWwgdGVtcGVyYXR1cmUgYW5kIFZjYyBw -b3dlciBzdXBwbHkgdm9sdGFnZS4KPiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvZGVsYXku -aD4KPiArI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24uaD4K -PiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pMmMu -aD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxl -Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjZGVmaW5lIExUQzI5OTBfU1RB -VFVTCTB4MDAKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0wJMHgwMQo+ICsjZGVmaW5lIExUQzI5 -OTBfVFJJR0dFUgkweDAyCj4gKyNkZWZpbmUgTFRDMjk5MF9USU5UX01TQgkweDA0Cj4gKyNkZWZp -bmUgTFRDMjk5MF9USU5UX0xTQgkweDA1Cj4gKyNkZWZpbmUgTFRDMjk5MF9WMV9NU0IJMHgwNgo+ -ICsjZGVmaW5lIExUQzI5OTBfVjFfTFNCCTB4MDcKPiArI2RlZmluZSBMVEMyOTkwX1YyX01TQgkw -eDA4Cj4gKyNkZWZpbmUgTFRDMjk5MF9WMl9MU0IJMHgwOQo+ICsjZGVmaW5lIExUQzI5OTBfVjNf -TVNCCTB4MEEKPiArI2RlZmluZSBMVEMyOTkwX1YzX0xTQgkweDBCCj4gKyNkZWZpbmUgTFRDMjk5 -MF9WNF9NU0IJMHgwQwo+ICsjZGVmaW5lIExUQzI5OTBfVjRfTFNCCTB4MEQKPiArI2RlZmluZSBM -VEMyOTkwX1ZDQ19NU0IJMHgwRQo+ICsjZGVmaW5lIExUQzI5OTBfVkNDX0xTQgkweDBGCj4gKwoK -TFNCIG5vdCB1c2VkLgoKPiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19CVVNZCUJJVCgwKQo+ICsj -ZGVmaW5lIExUQzI5OTBfU1RBVFVTX1RJTlQJQklUKDEpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFU -VVNfVjEJQklUKDIpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVjIJQklUKDMpCj4gKyNkZWZp -bmUgTFRDMjk5MF9TVEFUVVNfVjMJQklUKDQpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVjQJ -QklUKDUpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVkNDCUJJVCg2KQo+ICsKTm8gbG9uZ2Vy -IHVzZWQgPwoKPiArLyogT25seSBkZWZpbmUgY29udHJvbCBzZXR0aW5ncyB3ZSBhY3R1YWxseSB1 -c2UgKi8KCkhtbW0gLi4uIGJ1dCBub3QgYWxsIGFyZSB1c2VkLgoKPiArI2RlZmluZSBMVEMyOTkw -X0NPTlRST0xfS0VMVklOCQlCSVQoNykKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0xfU0lOR0xF -CQlCSVQoNikKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0xfTUVBU1VSRV9BTEwJKDB4MyA8PCAz -KQo+ICsjZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9NT0RFX0NVUlJFTlQJMHgwNgo+ICsjZGVmaW5l -IExUQzI5OTBfQ09OVFJPTF9NT0RFX1ZPTFRBR0UJMHgwNwo+ICsKPiArLyogY29udmVydCByYXcg -cmVnaXN0ZXIgdmFsdWUgdG8gc2lnbi1leHRlbmRlZCBpbnRlZ2VyIGluIDE2LWJpdCByYW5nZSAq -Lwo+ICtzdGF0aWMgaW50IGx0YzI5OTBfdm9sdGFnZV90b19pbnQoaW50IHJhdykKPiArewo+ICsJ -aWYgKHJhdyAmIEJJVCgxNCkpIHsKPiArCQlyZXR1cm4gLSgweDQwMDAgLSAocmF3ICYgMHgzRkZG -KSkgPDwgMjsKPiArCX0gZWxzZSB7Cj4gKwkJcmV0dXJuIChyYXcgJiAweDNGRkYpIDw8IDI7Cj4g -Kwl9Cj4gK30KPiArCj4gKy8qIFJldHVybiB0aGUgY29udmVydGVkIHZhbHVlIGZyb20gdGhlIGdp -dmVuIHJlZ2lzdGVyIGluIHVWIG9yIG1DICovCj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9nZXRfdmFs -dWUoc3RydWN0IGkyY19jbGllbnQgKmkyYywgdTggaW5kZXgpCj4gK3sKPiArCWludCB2YWw7Cj4g -KwlpbnQgcmVzdWx0Owo+ICsKPiArCXZhbCA9IGkyY19zbWJ1c19yZWFkX3dvcmRfc3dhcHBlZChp -MmMsIChpbmRleCA8PCAxKSArIExUQzI5OTBfVElOVF9NU0IpOwo+ICsJaWYgKHVubGlrZWx5KHZh -bCA8IDApKQo+ICsJCXJldHVybiB2YWw7Cj4gKwo+ICsJaWYgKGluZGV4ID09IDApIHsgLyogaW50 -ZXJuYWwgdGVtcCwgMC4wNjI1IGRlZ3JlZXMvTFNCLCAxMy1iaXQgICovCj4gKwkJdmFsID0gKHZh -bCAmIDB4MUZGRikgPDwgMzsKPiArCQlyZXN1bHQgPSAodmFsICogMTAwMCkgPj4gNzsKPiArCX0g -ZWxzZSBpZiAoaW5kZXggPCA1KSB7IC8qIFZ4LVZ5LCAxOS40MnVWL0xTQiAqLwo+ICsJCXJlc3Vs -dCA9IGx0YzI5OTBfdm9sdGFnZV90b19pbnQodmFsKSAqIDE5NDIgLyAoNCAqIDEwMCk7Cj4gKwl9 -IGVsc2UgeyAvKiBWY2MsIDMwNS4xOM68Vi9MU0IsIDIuNVYgb2Zmc2V0ICovCj4gKwkJcmVzdWx0 -ID0gbHRjMjk5MF92b2x0YWdlX3RvX2ludCh2YWwpICogMzA1MTggLyAoNCAqIDEwMCAqIDEwMDAp -Owo+ICsJCXJlc3VsdCArPSAyNTAwOwo+ICsJfQo+ICsKV2l0aCB0aGUgcmVnaXN0ZXIgaW4gaW5k -ZXggKHNlZSBiZWxvdykgdGhpcyBjb3VsZCBiZQoKCXZhbCA9IGkyY19zbWJ1c19yZWFkX3dvcmRf -c3dhcHBlZChpMmMsIGluZGV4KTsKCglzd2l0Y2ggKGluZGV4KSB7CgljYXNlIExUQzI5OTBfVElO -VF9NU0I6CgkJdmFsID0gKHZhbCAmIDB4MUZGRikgPDwgMzsKCQlyZXN1bHQgPSAodmFsICogMTAw -MCkgPj4gNzsKCQlicmVhazsKCWNhc2UgTFRDMjk5MF9WMV9NU0I6CgljYXNlIExUQzI5OTBfVjJf -TVNCOgoJCS4uLgoJCXJlc3VsdCA9IGx0YzI5OTBfdm9sdGFnZV90b19pbnQodmFsKSAqIDE5NDIg -LyAoNCAqIDEwMCk7CgkJYnJlYWs7CgljYXNlIExUQzI5OTBfVkNDX01TQjoKCQlyZXN1bHQgPSBs -dGMyOTkwX3ZvbHRhZ2VfdG9faW50KHZhbCkgKiAzMDUxOCAvICg0ICogMTAwICogMTAwMCk7CgkJ -cmVzdWx0ICs9IDI1MDA7CgkJYnJlYWs7CglkZWZhdWx0OgoJCXJlc3VsdCA9IDA7CS8qIHdvbid0 -IGhhcHBlbiwgbWFrZXMgY29tcGlsZXIgaGFwcHkgKi8KCQlicmVhazsKCX0KCndoaWNoIEkgdGhp -bmsgd291bGQgYmUgZWFzaWVyIHRvIHVuZGVyc3RhbmQuCgkKPiArCXJldHVybiByZXN1bHQ7Cj4g -K30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGx0YzI5OTBfc2hvd192YWx1ZShzdHJ1Y3QgZGV2aWNl -ICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQo+ -ICt7Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3Jf -ZGV2X2F0dHIoZGEpOwo+ICsJaW50IHZhbHVlOwo+ICsKPiArCXZhbHVlID0gbHRjMjk5MF9nZXRf -dmFsdWUoZGV2X2dldF9kcnZkYXRhKGRldiksIGF0dHItPmluZGV4KTsKPiArCXJldHVybiBzbnBy -aW50ZihidWYsIFBBR0VfU0laRSwgIiVkXG4iLCB2YWx1ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBT -RU5TT1JfREVWSUNFX0FUVFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1 -ZSwgTlVMTCwgMCk7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoY3VycjFfaW5wdXQsIFNf -SVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwgTlVMTCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW -SUNFX0FUVFIoY3VycjJfaW5wdXQsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwgTlVMTCwg -Myk7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoaW4wX2lucHV0LCBTX0lSVUdPLCBsdGMy -OTkwX3Nob3dfdmFsdWUsIE5VTEwsIDUpOwoKQ29uc2lkZXIgcHJvdmlkaW5nIHRoZSByZWdpc3Rl -ciBNU0IgaW4gaW5kZXguCgpFeGFtcGxlOgoJc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1w -MV9pbnB1dCwgU19JUlVHTywgbHRjMjk5MF9zaG93X3ZhbHVlLCBOVUxMLCBMVEMyOTkwX1RJTlRf -TVNCKTsKCgoKCj4gKwo+ICtzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqbHRjMjk5MF9hdHRyc1td -ID0gewo+ICsJJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJ -JnNlbnNvcl9kZXZfYXR0cl9jdXJyMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k -ZXZfYXR0cl9jdXJyMl9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9kZXZfYXR0cl9p -bjBfaW5wdXQuZGV2X2F0dHIuYXR0ciwKPiArCU5VTEwsCj4gK307Cj4gK0FUVFJJQlVURV9HUk9V -UFMobHRjMjk5MCk7Cj4gKwo+ICtzdGF0aWMgaW50IGx0YzI5OTBfaTJjX3Byb2JlKHN0cnVjdCBp -MmNfY2xpZW50ICppMmMsCj4gKwljb25zdCBzdHJ1Y3QgaTJjX2RldmljZV9pZCAqaWQpCgpQbGVh -c2UgYWxpZ24gY29udGludWF0aW9uIGxpbmVzIHdpdGggJygnLgoKPiArewo+ICsJaW50IHJldDsK -PiArCXN0cnVjdCBkZXZpY2UgKmh3bW9uX2RldjsKPiArCj4gKwlpZiAoIWkyY19jaGVja19mdW5j -dGlvbmFsaXR5KGkyYy0+YWRhcHRlciwgSTJDX0ZVTkNfU01CVVNfQllURV9EQVRBKSkKCkFsc28g -bmVlZCBjYXBhYmlsaXR5IHRvIHJlYWQgd29yZHMuCgo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsK -PiArCS8qIFNldHVwIGNvbnRpbnVvdXMgbW9kZSwgY3VycmVudCBtb25pdG9yICovCj4gKwlyZXQg -PSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgTFRDMjk5MF9DT05UUk9MLAo+ICsJCUxU -QzI5OTBfQ09OVFJPTF9NRUFTVVJFX0FMTCB8IExUQzI5OTBfQ09OVFJPTF9NT0RFX0NVUlJFTlQp -Owo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKCZpMmMtPmRldiwgIkVycm9yOiBGYWls -ZWQgdG8gc2V0IGNvbnRyb2wgbW9kZS5cbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwkv -KiBUcmlnZ2VyIG9uY2UgdG8gc3RhcnQgY29udGludW91cyBjb252ZXJzaW9uICovCj4gKwlyZXQg -PSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgTFRDMjk5MF9UUklHR0VSLCAxKTsKPiAr -CWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2VycigmaTJjLT5kZXYsICJFcnJvcjogRmFpbGVkIHRv -IHN0YXJ0IGFxdWlzaXRpb24uXG4iKTsKCnMvYXF1aXNpdGlvbi9hY3F1aXNpdGlvbi8KCj4gKwkJ -cmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlod21vbl9kZXYgPSBkZXZtX2h3bW9uX2RldmljZV9y -ZWdpc3Rlcl93aXRoX2dyb3VwcygmaTJjLT5kZXYsCj4gKwkJCQkJCQkgICBpMmMtPm5hbWUsCj4g -KwkJCQkJCQkgICBpMmMsCj4gKwkJCQkJCQkgICBsdGMyOTkwX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0 -dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qg -c3RydWN0IGkyY19kZXZpY2VfaWQgbHRjMjk5MF9pMmNfaWRbXSA9IHsKPiArCXsgImx0YzI5OTAi -LCAwIH0sCj4gKwl7fQo+ICt9Owo+ICtNT0RVTEVfREVWSUNFX1RBQkxFKGkyYywgbHRjMjk5MF9p -MmNfaWQpOwo+ICsKPiArc3RhdGljIHN0cnVjdCBpMmNfZHJpdmVyIGx0YzI5OTBfaTJjX2RyaXZl -ciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm5hbWUgPSAibHRjMjk5MCIsCj4gKwl9LAo+ICsJ -LnByb2JlICAgID0gbHRjMjk5MF9pMmNfcHJvYmUsCj4gKwkuaWRfdGFibGUgPSBsdGMyOTkwX2ky -Y19pZCwKPiArfTsKPiArCj4gK21vZHVsZV9pMmNfZHJpdmVyKGx0YzI5OTBfaTJjX2RyaXZlcik7 -Cj4gKwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkxUQzI5OTAgU2Vuc29yIERyaXZlciIpOwo+ICtN -T0RVTEVfQVVUSE9SKCJUb3BpYyBFbWJlZGRlZCBQcm9kdWN0cyIpOwo+ICtNT0RVTEVfTElDRU5T -RSgiR1BMIHYyIik7Cj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f -X19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3Jn -Cmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM +On 01/13/2016 03:05 AM, Mike Looijmans wrote: +> This adds support for the Linear Technology LTC2990 I2C System Monitor. +> The LTC2990 supports a combination of voltage, current and temperature +> monitoring. This driver currently only supports reading two currents +> by measuring two differential voltages across series resistors, in +> addition to the Vcc supply voltage and internal temperature. +> +> This is sufficient to support the Topic Miami SOM which uses this chip +> to monitor the currents flowing into the FPGA and the CPU parts. +> +> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl> + +Mike, + +That looks much better. Can you send me the output of i2cdump for the chip ? +That would help me writing module test code for it. + +Thanks, +Guenter + +> --- +> v2: Processed all review comments. +> Put chip into continuous measurement mode. +> Added ducumentation. +> Use standard hwmon interfaces and macros. +> +> Documentation/hwmon/ltc2990 | 44 ++++++++++++ +> drivers/hwmon/Kconfig | 14 ++++ +> drivers/hwmon/Makefile | 1 + +> drivers/hwmon/ltc2990.c | 160 ++++++++++++++++++++++++++++++++++++++++++++ +> 4 files changed, 219 insertions(+) +> create mode 100644 Documentation/hwmon/ltc2990 +> create mode 100644 drivers/hwmon/ltc2990.c +> +> diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990 +> new file mode 100644 +> index 0000000..838b74e +> --- /dev/null +> +++ b/Documentation/hwmon/ltc2990 +> @@ -0,0 +1,44 @@ +> +Kernel driver ltc2990 +> +===================== +> + +> +Supported chips: +> + * Linear Technology LTC2990 +> + Prefix: 'ltc2990' +> + Addresses scanned: - +> + Datasheet: http://www.linear.com/product/ltc2990 +> + +> +Author: Mike Looijmans <mike.looijmans@topic.nl> +> + +> + +> +Description +> +----------- +> + +> +LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor. +> +The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4) +> +can be combined to measure a differential voltage, which is typically used to +> +measure current through a series resistor, or a temperature. +> + +> +This driver currently uses the 2x differential mode only. In order to support +> +other modes, the driver will need to be expanded. +> + +> + +> +Usage Notes +> +----------- +> + +> +This driver does not probe for PMBus devices. You will have to instantiate +> +devices explicitly. +> + +> + +> +Sysfs attributes +> +---------------- +> + +> +The "curr*_input" measurements actually report the voltage drop across the +> +input pins in microvolts. This is equivalent to the current through a 1mOhm +> +sense resistor. Divide the reported value by the actual sense resistor value +> +in mOhm to get the actual value. +> + +> +in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V) +> +temp1_input Internal chip temperature in millidegrees Celcius +> +curr1_input Current in mA across v1-v2 assuming a 1mOhm sense resistor. +> +curr2_input Current in mA across v3-v4 assuming a 1mOhm sense resistor. +> + +> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +> index 80a73bf..8a31d64 100644 +> --- a/drivers/hwmon/Kconfig +> +++ b/drivers/hwmon/Kconfig +> @@ -685,6 +685,20 @@ config SENSORS_LTC2945 +> This driver can also be built as a module. If so, the module will +> be called ltc2945. +> +> +config SENSORS_LTC2990 +> + tristate "Linear Technology LTC2990 (current monitoring mode only)" +> + depends on I2C +> + help +> + If you say yes here you get support for Linear Technology LTC2990 +> + I2C System Monitor. The LTC2990 supports a combination of voltage, +> + current and temperature monitoring, but in addition to the Vcc supply +> + voltage and chip temperature, this driver currently only supports +> + reading two currents by measuring two differential voltages across +> + series resistors. +> + +> + This driver can also be built as a module. If so, the module will +> + be called ltc2990. +> + +> config SENSORS_LTC4151 +> tristate "Linear Technology LTC4151" +> depends on I2C +> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +> index 12a3239..e4bd15b 100644 +> --- a/drivers/hwmon/Makefile +> +++ b/drivers/hwmon/Makefile +> @@ -101,6 +101,7 @@ obj-$(CONFIG_SENSORS_LM95234) += lm95234.o +> obj-$(CONFIG_SENSORS_LM95241) += lm95241.o +> obj-$(CONFIG_SENSORS_LM95245) += lm95245.o +> obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o +> +obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o +> obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o +> obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o +> obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o +> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c +> new file mode 100644 +> index 0000000..3720ff7 +> --- /dev/null +> +++ b/drivers/hwmon/ltc2990.c +> @@ -0,0 +1,160 @@ +> +/* +> + * Driver for Linear Technology LTC2990 power monitor +> + * +> + * Copyright (C) 2014 Topic Embedded Products +> + * Author: Mike Looijmans <mike.looijmans@topic.nl> +> + * +> + * License: GPLv2 +> + * +> + * This driver assumes the chip is wired as a dual current monitor, and +> + * reports the voltage drop across two series resistors. It also reports +> + * the chip's internal temperature and Vcc power supply voltage. +> + */ +> + +> +#include <linux/delay.h> +> +#include <linux/err.h> +> +#include <linux/hwmon.h> +> +#include <linux/hwmon-sysfs.h> +> +#include <linux/i2c.h> +> +#include <linux/kernel.h> +> +#include <linux/module.h> +> +#include <linux/slab.h> +> + +> +#define LTC2990_STATUS 0x00 +> +#define LTC2990_CONTROL 0x01 +> +#define LTC2990_TRIGGER 0x02 +> +#define LTC2990_TINT_MSB 0x04 +> +#define LTC2990_TINT_LSB 0x05 +> +#define LTC2990_V1_MSB 0x06 +> +#define LTC2990_V1_LSB 0x07 +> +#define LTC2990_V2_MSB 0x08 +> +#define LTC2990_V2_LSB 0x09 +> +#define LTC2990_V3_MSB 0x0A +> +#define LTC2990_V3_LSB 0x0B +> +#define LTC2990_V4_MSB 0x0C +> +#define LTC2990_V4_LSB 0x0D +> +#define LTC2990_VCC_MSB 0x0E +> +#define LTC2990_VCC_LSB 0x0F +> + + +LSB not used. + +> +#define LTC2990_STATUS_BUSY BIT(0) +> +#define LTC2990_STATUS_TINT BIT(1) +> +#define LTC2990_STATUS_V1 BIT(2) +> +#define LTC2990_STATUS_V2 BIT(3) +> +#define LTC2990_STATUS_V3 BIT(4) +> +#define LTC2990_STATUS_V4 BIT(5) +> +#define LTC2990_STATUS_VCC BIT(6) +> + +No longer used ? + +> +/* Only define control settings we actually use */ + +Hmmm ... but not all are used. + +> +#define LTC2990_CONTROL_KELVIN BIT(7) +> +#define LTC2990_CONTROL_SINGLE BIT(6) +> +#define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3) +> +#define LTC2990_CONTROL_MODE_CURRENT 0x06 +> +#define LTC2990_CONTROL_MODE_VOLTAGE 0x07 +> + +> +/* convert raw register value to sign-extended integer in 16-bit range */ +> +static int ltc2990_voltage_to_int(int raw) +> +{ +> + if (raw & BIT(14)) { +> + return -(0x4000 - (raw & 0x3FFF)) << 2; +> + } else { +> + return (raw & 0x3FFF) << 2; +> + } +> +} +> + +> +/* Return the converted value from the given register in uV or mC */ +> +static int ltc2990_get_value(struct i2c_client *i2c, u8 index) +> +{ +> + int val; +> + int result; +> + +> + val = i2c_smbus_read_word_swapped(i2c, (index << 1) + LTC2990_TINT_MSB); +> + if (unlikely(val < 0)) +> + return val; +> + +> + if (index == 0) { /* internal temp, 0.0625 degrees/LSB, 13-bit */ +> + val = (val & 0x1FFF) << 3; +> + result = (val * 1000) >> 7; +> + } else if (index < 5) { /* Vx-Vy, 19.42uV/LSB */ +> + result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100); +> + } else { /* Vcc, 305.18μV/LSB, 2.5V offset */ +> + result = ltc2990_voltage_to_int(val) * 30518 / (4 * 100 * 1000); +> + result += 2500; +> + } +> + +With the register in index (see below) this could be + + val = i2c_smbus_read_word_swapped(i2c, index); + + switch (index) { + case LTC2990_TINT_MSB: + val = (val & 0x1FFF) << 3; + result = (val * 1000) >> 7; + break; + case LTC2990_V1_MSB: + case LTC2990_V2_MSB: + ... + result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100); + break; + case LTC2990_VCC_MSB: + result = ltc2990_voltage_to_int(val) * 30518 / (4 * 100 * 1000); + result += 2500; + break; + default: + result = 0; /* won't happen, makes compiler happy */ + break; + } + +which I think would be easier to understand. + +> + return result; +> +} +> + +> +static ssize_t ltc2990_show_value(struct device *dev, +> + struct device_attribute *da, char *buf) +> +{ +> + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); +> + int value; +> + +> + value = ltc2990_get_value(dev_get_drvdata(dev), attr->index); +> + return snprintf(buf, PAGE_SIZE, "%d\n", value); +> +} +> + +> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, 0); +> +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL, 1); +> +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL, 3); +> +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL, 5); + +Consider providing the register MSB in index. + +Example: + static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, LTC2990_TINT_MSB); + + + + +> + +> +static struct attribute *ltc2990_attrs[] = { +> + &sensor_dev_attr_temp1_input.dev_attr.attr, +> + &sensor_dev_attr_curr1_input.dev_attr.attr, +> + &sensor_dev_attr_curr2_input.dev_attr.attr, +> + &sensor_dev_attr_in0_input.dev_attr.attr, +> + NULL, +> +}; +> +ATTRIBUTE_GROUPS(ltc2990); +> + +> +static int ltc2990_i2c_probe(struct i2c_client *i2c, +> + const struct i2c_device_id *id) + +Please align continuation lines with '('. + +> +{ +> + int ret; +> + struct device *hwmon_dev; +> + +> + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + +Also need capability to read words. + +> + return -ENODEV; +> + +> + /* Setup continuous mode, current monitor */ +> + ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL, +> + LTC2990_CONTROL_MEASURE_ALL | LTC2990_CONTROL_MODE_CURRENT); +> + if (ret < 0) { +> + dev_err(&i2c->dev, "Error: Failed to set control mode.\n"); +> + return ret; +> + } +> + /* Trigger once to start continuous conversion */ +> + ret = i2c_smbus_write_byte_data(i2c, LTC2990_TRIGGER, 1); +> + if (ret < 0) { +> + dev_err(&i2c->dev, "Error: Failed to start aquisition.\n"); + +s/aquisition/acquisition/ + +> + return ret; +> + } +> + +> + hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev, +> + i2c->name, +> + i2c, +> + ltc2990_groups); +> + +> + return PTR_ERR_OR_ZERO(hwmon_dev); +> +} +> + +> +static const struct i2c_device_id ltc2990_i2c_id[] = { +> + { "ltc2990", 0 }, +> + {} +> +}; +> +MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id); +> + +> +static struct i2c_driver ltc2990_i2c_driver = { +> + .driver = { +> + .name = "ltc2990", +> + }, +> + .probe = ltc2990_i2c_probe, +> + .id_table = ltc2990_i2c_id, +> +}; +> + +> +module_i2c_driver(ltc2990_i2c_driver); +> + +> +MODULE_DESCRIPTION("LTC2990 Sensor Driver"); +> +MODULE_AUTHOR("Topic Embedded Products"); +> +MODULE_LICENSE("GPL v2"); +> diff --git a/a/content_digest b/N1/content_digest index a68d81d..9df1938 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -2,203 +2,352 @@ "ref\01452067627-24939-1-git-send-email-mike.looijmans@topic.nl\0" "ref\01452683150-27747-1-git-send-email-mike.looijmans@topic.nl\0" "From\0Guenter Roeck <linux@roeck-us.net>\0" - "Subject\0Re: [lm-sensors] [PATCH v2] hwmon: Add LTC2990 sensor driver\0" - "Date\0Wed, 13 Jan 2016 13:24:30 +0000\0" + "Subject\0Re: [PATCH v2] hwmon: Add LTC2990 sensor driver\0" + "Date\0Wed, 13 Jan 2016 05:24:30 -0800\0" "To\0Mike Looijmans <mike.looijmans@topic.nl>" " lm-sensors@lm-sensors.org\0" "Cc\0jdelvare@suse.com" " linux-kernel@vger.kernel.org\0" "\00:1\0" "b\0" - "T24gMDEvMTMvMjAxNiAwMzowNSBBTSwgTWlrZSBMb29pam1hbnMgd3JvdGU6Cj4gVGhpcyBhZGRz\n" - "IHN1cHBvcnQgZm9yIHRoZSBMaW5lYXIgVGVjaG5vbG9neSBMVEMyOTkwICBJMkMgU3lzdGVtIE1v\n" - "bml0b3IuCj4gVGhlIExUQzI5OTAgc3VwcG9ydHMgYSBjb21iaW5hdGlvbiBvZiB2b2x0YWdlLCBj\n" - "dXJyZW50IGFuZCB0ZW1wZXJhdHVyZQo+IG1vbml0b3JpbmcuIFRoaXMgZHJpdmVyIGN1cnJlbnRs\n" - "eSBvbmx5IHN1cHBvcnRzIHJlYWRpbmcgdHdvIGN1cnJlbnRzCj4gYnkgbWVhc3VyaW5nIHR3byBk\n" - "aWZmZXJlbnRpYWwgdm9sdGFnZXMgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMsIGluCj4gYWRkaXRp\n" - "b24gdG8gdGhlIFZjYyBzdXBwbHkgdm9sdGFnZSBhbmQgaW50ZXJuYWwgdGVtcGVyYXR1cmUuCj4K\n" - "PiBUaGlzIGlzIHN1ZmZpY2llbnQgdG8gc3VwcG9ydCB0aGUgVG9waWMgTWlhbWkgU09NIHdoaWNo\n" - "IHVzZXMgdGhpcyBjaGlwCj4gdG8gbW9uaXRvciB0aGUgY3VycmVudHMgZmxvd2luZyBpbnRvIHRo\n" - "ZSBGUEdBIGFuZCB0aGUgQ1BVIHBhcnRzLgo+Cj4gU2lnbmVkLW9mZi1ieTogTWlrZSBMb29pam1h\n" - "bnMgPG1pa2UubG9vaWptYW5zQHRvcGljLm5sPgoKTWlrZSwKClRoYXQgbG9va3MgbXVjaCBiZXR0\n" - "ZXIuIENhbiB5b3Ugc2VuZCBtZSB0aGUgb3V0cHV0IG9mIGkyY2R1bXAgZm9yIHRoZSBjaGlwID8K\n" - "VGhhdCB3b3VsZCBoZWxwIG1lIHdyaXRpbmcgbW9kdWxlIHRlc3QgY29kZSBmb3IgaXQuCgpUaGFu\n" - "a3MsCkd1ZW50ZXIKCj4gLS0tCj4gdjI6IFByb2Nlc3NlZCBhbGwgcmV2aWV3IGNvbW1lbnRzLgo+\n" - "ICAgICAgUHV0IGNoaXAgaW50byBjb250aW51b3VzIG1lYXN1cmVtZW50IG1vZGUuCj4gICAgICBB\n" - "ZGRlZCBkdWN1bWVudGF0aW9uLgo+ICAgICAgVXNlIHN0YW5kYXJkIGh3bW9uIGludGVyZmFjZXMg\n" - "YW5kIG1hY3Jvcy4KPgo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9sdGMyOTkwIHwgIDQ0ICsrKysr\n" - "KysrKysrKwo+ICAgZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgIHwgIDE0ICsrKysKPiAgIGRy\n" - "aXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICB8ICAgMSArCj4gICBkcml2ZXJzL2h3bW9uL2x0YzI5\n" - "OTAuYyAgICAgfCAxNjAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr\n" - "KysKPiAgIDQgZmlsZXMgY2hhbmdlZCwgMjE5IGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2Rl\n" - "IDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2x0YzI5OTAKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0\n" - "NCBkcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24v\n" - "aHdtb24vbHRjMjk5MCBiL0RvY3VtZW50YXRpb24vaHdtb24vbHRjMjk5MAo+IG5ldyBmaWxlIG1v\n" - "ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uODM4Yjc0ZQo+IC0tLSAvZGV2L251bGwKPiArKysg\n" - "Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2x0YzI5OTAKPiBAQCAtMCwwICsxLDQ0IEBACj4gK0tlcm5l\n" - "bCBkcml2ZXIgbHRjMjk5MAo+ICs9PT09PT09PT09PT09PT09PT09PT0KPiArCj4gK1N1cHBvcnRl\n" - "ZCBjaGlwczoKPiArICAqIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAKPiArICAgIFByZWZpeDog\n" - "J2x0YzI5OTAnCj4gKyAgICBBZGRyZXNzZXMgc2Nhbm5lZDogLQo+ICsgICAgRGF0YXNoZWV0OiBo\n" - "dHRwOi8vd3d3LmxpbmVhci5jb20vcHJvZHVjdC9sdGMyOTkwCj4gKwo+ICtBdXRob3I6IE1pa2Ug\n" - "TG9vaWptYW5zIDxtaWtlLmxvb2lqbWFuc0B0b3BpYy5ubD4KPiArCj4gKwo+ICtEZXNjcmlwdGlv\n" - "bgo+ICstLS0tLS0tLS0tLQo+ICsKPiArTFRDMjk5MCBpcyBhIFF1YWQgSTJDIFZvbHRhZ2UsIEN1\n" - "cnJlbnQgYW5kIFRlbXBlcmF0dXJlIE1vbml0b3IuCj4gK1RoZSBjaGlwJ3MgaW5wdXRzIGNhbiBt\n" - "ZWFzdXJlIDQgdm9sdGFnZXMsIG9yIHR3byBpbnB1dHMgdG9nZXRoZXIgKDErMiBhbmQgMys0KQo+\n" - "ICtjYW4gYmUgY29tYmluZWQgdG8gbWVhc3VyZSBhIGRpZmZlcmVudGlhbCB2b2x0YWdlLCB3aGlj\n" - "aCBpcyB0eXBpY2FsbHkgdXNlZCB0bwo+ICttZWFzdXJlIGN1cnJlbnQgdGhyb3VnaCBhIHNlcmll\n" - "cyByZXNpc3Rvciwgb3IgYSB0ZW1wZXJhdHVyZS4KPiArCj4gK1RoaXMgZHJpdmVyIGN1cnJlbnRs\n" - "eSB1c2VzIHRoZSAyeCBkaWZmZXJlbnRpYWwgbW9kZSBvbmx5LiBJbiBvcmRlciB0byBzdXBwb3J0\n" - "Cj4gK290aGVyIG1vZGVzLCB0aGUgZHJpdmVyIHdpbGwgbmVlZCB0byBiZSBleHBhbmRlZC4KPiAr\n" - "Cj4gKwo+ICtVc2FnZSBOb3Rlcwo+ICstLS0tLS0tLS0tLQo+ICsKPiArVGhpcyBkcml2ZXIgZG9l\n" - "cyBub3QgcHJvYmUgZm9yIFBNQnVzIGRldmljZXMuIFlvdSB3aWxsIGhhdmUgdG8gaW5zdGFudGlh\n" - "dGUKPiArZGV2aWNlcyBleHBsaWNpdGx5Lgo+ICsKPiArCj4gK1N5c2ZzIGF0dHJpYnV0ZXMKPiAr\n" - "LS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArVGhlICJjdXJyKl9pbnB1dCIgbWVhc3VyZW1lbnRzIGFj\n" - "dHVhbGx5IHJlcG9ydCB0aGUgdm9sdGFnZSBkcm9wIGFjcm9zcyB0aGUKPiAraW5wdXQgcGlucyBp\n" - "biBtaWNyb3ZvbHRzLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gdGhlIGN1cnJlbnQgdGhyb3VnaCBh\n" - "IDFtT2htCj4gK3NlbnNlIHJlc2lzdG9yLiBEaXZpZGUgdGhlIHJlcG9ydGVkIHZhbHVlIGJ5IHRo\n" - "ZSBhY3R1YWwgc2Vuc2UgcmVzaXN0b3IgdmFsdWUKPiAraW4gbU9obSB0byBnZXQgdGhlIGFjdHVh\n" - "bCB2YWx1ZS4KPiArCj4gK2luMF9pbnB1dCAgICAgVm9sdGFnZSBhdCBWY2MgcGluIGluIG1pbGxp\n" - "dm9sdCAocmFuZ2UgMi41ViB0byA1VikKPiArdGVtcDFfaW5wdXQgICBJbnRlcm5hbCBjaGlwIHRl\n" - "bXBlcmF0dXJlIGluIG1pbGxpZGVncmVlcyBDZWxjaXVzCj4gK2N1cnIxX2lucHV0ICAgQ3VycmVu\n" - "dCBpbiBtQSBhY3Jvc3MgdjEtdjIgYXNzdW1pbmcgYSAxbU9obSBzZW5zZSByZXNpc3Rvci4KPiAr\n" - "Y3VycjJfaW5wdXQgICBDdXJyZW50IGluIG1BIGFjcm9zcyB2My12NCBhc3N1bWluZyBhIDFtT2ht\n" - "IHNlbnNlIHJlc2lzdG9yLgo+ICsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmln\n" - "IGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4gaW5kZXggODBhNzNiZi4uOGEzMWQ2NCAxMDA2NDQK\n" - "PiAtLS0gYS9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25m\n" - "aWcKPiBAQCAtNjg1LDYgKzY4NSwyMCBAQCBjb25maWcgU0VOU09SU19MVEMyOTQ1Cj4gICAJICBU\n" - "aGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1\n" - "bGUgd2lsbAo+ICAgCSAgYmUgY2FsbGVkIGx0YzI5NDUuCj4KPiArY29uZmlnIFNFTlNPUlNfTFRD\n" - "Mjk5MAo+ICsJdHJpc3RhdGUgIkxpbmVhciBUZWNobm9sb2d5IExUQzI5OTAgKGN1cnJlbnQgbW9u\n" - "aXRvcmluZyBtb2RlIG9ubHkpIgo+ICsJZGVwZW5kcyBvbiBJMkMKPiArCWhlbHAKPiArCSAgSWYg\n" - "eW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIExpbmVhciBUZWNobm9sb2d5IExU\n" - "QzI5OTAKPiArCSAgSTJDIFN5c3RlbSBNb25pdG9yLiBUaGUgTFRDMjk5MCBzdXBwb3J0cyBhIGNv\n" - "bWJpbmF0aW9uIG9mIHZvbHRhZ2UsCj4gKwkgIGN1cnJlbnQgYW5kIHRlbXBlcmF0dXJlIG1vbml0\n" - "b3JpbmcsIGJ1dCBpbiBhZGRpdGlvbiB0byB0aGUgVmNjIHN1cHBseQo+ICsJICB2b2x0YWdlIGFu\n" - "ZCBjaGlwIHRlbXBlcmF0dXJlLCB0aGlzIGRyaXZlciBjdXJyZW50bHkgb25seSBzdXBwb3J0cwo+\n" - "ICsJICByZWFkaW5nIHR3byBjdXJyZW50cyBieSBtZWFzdXJpbmcgdHdvIGRpZmZlcmVudGlhbCB2\n" - "b2x0YWdlcyBhY3Jvc3MKPiArCSAgc2VyaWVzIHJlc2lzdG9ycy4KPiArCj4gKwkgIFRoaXMgZHJp\n" - "dmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZSB3aWxs\n" - "Cj4gKwkgIGJlIGNhbGxlZCBsdGMyOTkwLgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0xUQzQxNTEK\n" - "PiAgIAl0cmlzdGF0ZSAiTGluZWFyIFRlY2hub2xvZ3kgTFRDNDE1MSIKPiAgIAlkZXBlbmRzIG9u\n" - "IEkyQwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlIGIvZHJpdmVycy9od21v\n" - "bi9NYWtlZmlsZQo+IGluZGV4IDEyYTMyMzkuLmU0YmQxNWIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVy\n" - "cy9od21vbi9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBAQCAtMTAx\n" - "LDYgKzEwMSw3IEBAIG9iai0kKENPTkZJR19TRU5TT1JTX0xNOTUyMzQpCSs9IGxtOTUyMzQubwo+\n" - "ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfTE05NTI0MSkJKz0gbG05NTI0MS5vCj4gICBvYmotJChD\n" - "T05GSUdfU0VOU09SU19MTTk1MjQ1KQkrPSBsbTk1MjQ1Lm8KPiAgIG9iai0kKENPTkZJR19TRU5T\n" - "T1JTX0xUQzI5NDUpCSs9IGx0YzI5NDUubwo+ICtvYmotJChDT05GSUdfU0VOU09SU19MVEMyOTkw\n" - "KQkrPSBsdGMyOTkwLm8KPiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQxNTEpCSs9IGx0YzQx\n" - "NTEubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfTFRDNDIxNSkJKz0gbHRjNDIxNS5vCj4gICBv\n" - "YmotJChDT05GSUdfU0VOU09SU19MVEM0MjIyKQkrPSBsdGM0MjIyLm8KPiBkaWZmIC0tZ2l0IGEv\n" - "ZHJpdmVycy9od21vbi9sdGMyOTkwLmMgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+IG5ldyBm\n" - "aWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uMzcyMGZmNwo+IC0tLSAvZGV2L251bGwK\n" - "PiArKysgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8q\n" - "Cj4gKyAqIERyaXZlciBmb3IgTGluZWFyIFRlY2hub2xvZ3kgTFRDMjk5MCBwb3dlciBtb25pdG9y\n" - "Cj4gKyAqCj4gKyAqIENvcHlyaWdodCAoQykgMjAxNCBUb3BpYyBFbWJlZGRlZCBQcm9kdWN0cwo+\n" - "ICsgKiBBdXRob3I6IE1pa2UgTG9vaWptYW5zIDxtaWtlLmxvb2lqbWFuc0B0b3BpYy5ubD4KPiAr\n" - "ICoKPiArICogTGljZW5zZTogR1BMdjIKPiArICoKPiArICogVGhpcyBkcml2ZXIgYXNzdW1lcyB0\n" - "aGUgY2hpcCBpcyB3aXJlZCBhcyBhIGR1YWwgY3VycmVudCBtb25pdG9yLCBhbmQKPiArICogcmVw\n" - "b3J0cyB0aGUgdm9sdGFnZSBkcm9wIGFjcm9zcyB0d28gc2VyaWVzIHJlc2lzdG9ycy4gSXQgYWxz\n" - "byByZXBvcnRzCj4gKyAqIHRoZSBjaGlwJ3MgaW50ZXJuYWwgdGVtcGVyYXR1cmUgYW5kIFZjYyBw\n" - "b3dlciBzdXBwbHkgdm9sdGFnZS4KPiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvZGVsYXku\n" - "aD4KPiArI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24uaD4K\n" - "PiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pMmMu\n" - "aD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxl\n" - "Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjZGVmaW5lIExUQzI5OTBfU1RB\n" - "VFVTCTB4MDAKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0wJMHgwMQo+ICsjZGVmaW5lIExUQzI5\n" - "OTBfVFJJR0dFUgkweDAyCj4gKyNkZWZpbmUgTFRDMjk5MF9USU5UX01TQgkweDA0Cj4gKyNkZWZp\n" - "bmUgTFRDMjk5MF9USU5UX0xTQgkweDA1Cj4gKyNkZWZpbmUgTFRDMjk5MF9WMV9NU0IJMHgwNgo+\n" - "ICsjZGVmaW5lIExUQzI5OTBfVjFfTFNCCTB4MDcKPiArI2RlZmluZSBMVEMyOTkwX1YyX01TQgkw\n" - "eDA4Cj4gKyNkZWZpbmUgTFRDMjk5MF9WMl9MU0IJMHgwOQo+ICsjZGVmaW5lIExUQzI5OTBfVjNf\n" - "TVNCCTB4MEEKPiArI2RlZmluZSBMVEMyOTkwX1YzX0xTQgkweDBCCj4gKyNkZWZpbmUgTFRDMjk5\n" - "MF9WNF9NU0IJMHgwQwo+ICsjZGVmaW5lIExUQzI5OTBfVjRfTFNCCTB4MEQKPiArI2RlZmluZSBM\n" - "VEMyOTkwX1ZDQ19NU0IJMHgwRQo+ICsjZGVmaW5lIExUQzI5OTBfVkNDX0xTQgkweDBGCj4gKwoK\n" - "TFNCIG5vdCB1c2VkLgoKPiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19CVVNZCUJJVCgwKQo+ICsj\n" - "ZGVmaW5lIExUQzI5OTBfU1RBVFVTX1RJTlQJQklUKDEpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFU\n" - "VVNfVjEJQklUKDIpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVjIJQklUKDMpCj4gKyNkZWZp\n" - "bmUgTFRDMjk5MF9TVEFUVVNfVjMJQklUKDQpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVjQJ\n" - "QklUKDUpCj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVNfVkNDCUJJVCg2KQo+ICsKTm8gbG9uZ2Vy\n" - "IHVzZWQgPwoKPiArLyogT25seSBkZWZpbmUgY29udHJvbCBzZXR0aW5ncyB3ZSBhY3R1YWxseSB1\n" - "c2UgKi8KCkhtbW0gLi4uIGJ1dCBub3QgYWxsIGFyZSB1c2VkLgoKPiArI2RlZmluZSBMVEMyOTkw\n" - "X0NPTlRST0xfS0VMVklOCQlCSVQoNykKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0xfU0lOR0xF\n" - "CQlCSVQoNikKPiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0xfTUVBU1VSRV9BTEwJKDB4MyA8PCAz\n" - "KQo+ICsjZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9NT0RFX0NVUlJFTlQJMHgwNgo+ICsjZGVmaW5l\n" - "IExUQzI5OTBfQ09OVFJPTF9NT0RFX1ZPTFRBR0UJMHgwNwo+ICsKPiArLyogY29udmVydCByYXcg\n" - "cmVnaXN0ZXIgdmFsdWUgdG8gc2lnbi1leHRlbmRlZCBpbnRlZ2VyIGluIDE2LWJpdCByYW5nZSAq\n" - "Lwo+ICtzdGF0aWMgaW50IGx0YzI5OTBfdm9sdGFnZV90b19pbnQoaW50IHJhdykKPiArewo+ICsJ\n" - "aWYgKHJhdyAmIEJJVCgxNCkpIHsKPiArCQlyZXR1cm4gLSgweDQwMDAgLSAocmF3ICYgMHgzRkZG\n" - "KSkgPDwgMjsKPiArCX0gZWxzZSB7Cj4gKwkJcmV0dXJuIChyYXcgJiAweDNGRkYpIDw8IDI7Cj4g\n" - "Kwl9Cj4gK30KPiArCj4gKy8qIFJldHVybiB0aGUgY29udmVydGVkIHZhbHVlIGZyb20gdGhlIGdp\n" - "dmVuIHJlZ2lzdGVyIGluIHVWIG9yIG1DICovCj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9nZXRfdmFs\n" - "dWUoc3RydWN0IGkyY19jbGllbnQgKmkyYywgdTggaW5kZXgpCj4gK3sKPiArCWludCB2YWw7Cj4g\n" - "KwlpbnQgcmVzdWx0Owo+ICsKPiArCXZhbCA9IGkyY19zbWJ1c19yZWFkX3dvcmRfc3dhcHBlZChp\n" - "MmMsIChpbmRleCA8PCAxKSArIExUQzI5OTBfVElOVF9NU0IpOwo+ICsJaWYgKHVubGlrZWx5KHZh\n" - "bCA8IDApKQo+ICsJCXJldHVybiB2YWw7Cj4gKwo+ICsJaWYgKGluZGV4ID09IDApIHsgLyogaW50\n" - "ZXJuYWwgdGVtcCwgMC4wNjI1IGRlZ3JlZXMvTFNCLCAxMy1iaXQgICovCj4gKwkJdmFsID0gKHZh\n" - "bCAmIDB4MUZGRikgPDwgMzsKPiArCQlyZXN1bHQgPSAodmFsICogMTAwMCkgPj4gNzsKPiArCX0g\n" - "ZWxzZSBpZiAoaW5kZXggPCA1KSB7IC8qIFZ4LVZ5LCAxOS40MnVWL0xTQiAqLwo+ICsJCXJlc3Vs\n" - "dCA9IGx0YzI5OTBfdm9sdGFnZV90b19pbnQodmFsKSAqIDE5NDIgLyAoNCAqIDEwMCk7Cj4gKwl9\n" - "IGVsc2UgeyAvKiBWY2MsIDMwNS4xOM68Vi9MU0IsIDIuNVYgb2Zmc2V0ICovCj4gKwkJcmVzdWx0\n" - "ID0gbHRjMjk5MF92b2x0YWdlX3RvX2ludCh2YWwpICogMzA1MTggLyAoNCAqIDEwMCAqIDEwMDAp\n" - "Owo+ICsJCXJlc3VsdCArPSAyNTAwOwo+ICsJfQo+ICsKV2l0aCB0aGUgcmVnaXN0ZXIgaW4gaW5k\n" - "ZXggKHNlZSBiZWxvdykgdGhpcyBjb3VsZCBiZQoKCXZhbCA9IGkyY19zbWJ1c19yZWFkX3dvcmRf\n" - "c3dhcHBlZChpMmMsIGluZGV4KTsKCglzd2l0Y2ggKGluZGV4KSB7CgljYXNlIExUQzI5OTBfVElO\n" - "VF9NU0I6CgkJdmFsID0gKHZhbCAmIDB4MUZGRikgPDwgMzsKCQlyZXN1bHQgPSAodmFsICogMTAw\n" - "MCkgPj4gNzsKCQlicmVhazsKCWNhc2UgTFRDMjk5MF9WMV9NU0I6CgljYXNlIExUQzI5OTBfVjJf\n" - "TVNCOgoJCS4uLgoJCXJlc3VsdCA9IGx0YzI5OTBfdm9sdGFnZV90b19pbnQodmFsKSAqIDE5NDIg\n" - "LyAoNCAqIDEwMCk7CgkJYnJlYWs7CgljYXNlIExUQzI5OTBfVkNDX01TQjoKCQlyZXN1bHQgPSBs\n" - "dGMyOTkwX3ZvbHRhZ2VfdG9faW50KHZhbCkgKiAzMDUxOCAvICg0ICogMTAwICogMTAwMCk7CgkJ\n" - "cmVzdWx0ICs9IDI1MDA7CgkJYnJlYWs7CglkZWZhdWx0OgoJCXJlc3VsdCA9IDA7CS8qIHdvbid0\n" - "IGhhcHBlbiwgbWFrZXMgY29tcGlsZXIgaGFwcHkgKi8KCQlicmVhazsKCX0KCndoaWNoIEkgdGhp\n" - "bmsgd291bGQgYmUgZWFzaWVyIHRvIHVuZGVyc3RhbmQuCgkKPiArCXJldHVybiByZXN1bHQ7Cj4g\n" - "K30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGx0YzI5OTBfc2hvd192YWx1ZShzdHJ1Y3QgZGV2aWNl\n" - "ICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQo+\n" - "ICt7Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3Jf\n" - "ZGV2X2F0dHIoZGEpOwo+ICsJaW50IHZhbHVlOwo+ICsKPiArCXZhbHVlID0gbHRjMjk5MF9nZXRf\n" - "dmFsdWUoZGV2X2dldF9kcnZkYXRhKGRldiksIGF0dHItPmluZGV4KTsKPiArCXJldHVybiBzbnBy\n" - "aW50ZihidWYsIFBBR0VfU0laRSwgIiVkXG4iLCB2YWx1ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBT\n" - "RU5TT1JfREVWSUNFX0FUVFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1\n" - "ZSwgTlVMTCwgMCk7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoY3VycjFfaW5wdXQsIFNf\n" - "SVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwgTlVMTCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW\n" - "SUNFX0FUVFIoY3VycjJfaW5wdXQsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwgTlVMTCwg\n" - "Myk7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoaW4wX2lucHV0LCBTX0lSVUdPLCBsdGMy\n" - "OTkwX3Nob3dfdmFsdWUsIE5VTEwsIDUpOwoKQ29uc2lkZXIgcHJvdmlkaW5nIHRoZSByZWdpc3Rl\n" - "ciBNU0IgaW4gaW5kZXguCgpFeGFtcGxlOgoJc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1w\n" - "MV9pbnB1dCwgU19JUlVHTywgbHRjMjk5MF9zaG93X3ZhbHVlLCBOVUxMLCBMVEMyOTkwX1RJTlRf\n" - "TVNCKTsKCgoKCj4gKwo+ICtzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqbHRjMjk5MF9hdHRyc1td\n" - "ID0gewo+ICsJJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJ\n" - "JnNlbnNvcl9kZXZfYXR0cl9jdXJyMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k\n" - "ZXZfYXR0cl9jdXJyMl9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9kZXZfYXR0cl9p\n" - "bjBfaW5wdXQuZGV2X2F0dHIuYXR0ciwKPiArCU5VTEwsCj4gK307Cj4gK0FUVFJJQlVURV9HUk9V\n" - "UFMobHRjMjk5MCk7Cj4gKwo+ICtzdGF0aWMgaW50IGx0YzI5OTBfaTJjX3Byb2JlKHN0cnVjdCBp\n" - "MmNfY2xpZW50ICppMmMsCj4gKwljb25zdCBzdHJ1Y3QgaTJjX2RldmljZV9pZCAqaWQpCgpQbGVh\n" - "c2UgYWxpZ24gY29udGludWF0aW9uIGxpbmVzIHdpdGggJygnLgoKPiArewo+ICsJaW50IHJldDsK\n" - "PiArCXN0cnVjdCBkZXZpY2UgKmh3bW9uX2RldjsKPiArCj4gKwlpZiAoIWkyY19jaGVja19mdW5j\n" - "dGlvbmFsaXR5KGkyYy0+YWRhcHRlciwgSTJDX0ZVTkNfU01CVVNfQllURV9EQVRBKSkKCkFsc28g\n" - "bmVlZCBjYXBhYmlsaXR5IHRvIHJlYWQgd29yZHMuCgo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsK\n" - "PiArCS8qIFNldHVwIGNvbnRpbnVvdXMgbW9kZSwgY3VycmVudCBtb25pdG9yICovCj4gKwlyZXQg\n" - "PSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgTFRDMjk5MF9DT05UUk9MLAo+ICsJCUxU\n" - "QzI5OTBfQ09OVFJPTF9NRUFTVVJFX0FMTCB8IExUQzI5OTBfQ09OVFJPTF9NT0RFX0NVUlJFTlQp\n" - "Owo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKCZpMmMtPmRldiwgIkVycm9yOiBGYWls\n" - "ZWQgdG8gc2V0IGNvbnRyb2wgbW9kZS5cbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwkv\n" - "KiBUcmlnZ2VyIG9uY2UgdG8gc3RhcnQgY29udGludW91cyBjb252ZXJzaW9uICovCj4gKwlyZXQg\n" - "PSBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgTFRDMjk5MF9UUklHR0VSLCAxKTsKPiAr\n" - "CWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2VycigmaTJjLT5kZXYsICJFcnJvcjogRmFpbGVkIHRv\n" - "IHN0YXJ0IGFxdWlzaXRpb24uXG4iKTsKCnMvYXF1aXNpdGlvbi9hY3F1aXNpdGlvbi8KCj4gKwkJ\n" - "cmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlod21vbl9kZXYgPSBkZXZtX2h3bW9uX2RldmljZV9y\n" - "ZWdpc3Rlcl93aXRoX2dyb3VwcygmaTJjLT5kZXYsCj4gKwkJCQkJCQkgICBpMmMtPm5hbWUsCj4g\n" - "KwkJCQkJCQkgICBpMmMsCj4gKwkJCQkJCQkgICBsdGMyOTkwX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0\n" - "dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qg\n" - "c3RydWN0IGkyY19kZXZpY2VfaWQgbHRjMjk5MF9pMmNfaWRbXSA9IHsKPiArCXsgImx0YzI5OTAi\n" - "LCAwIH0sCj4gKwl7fQo+ICt9Owo+ICtNT0RVTEVfREVWSUNFX1RBQkxFKGkyYywgbHRjMjk5MF9p\n" - "MmNfaWQpOwo+ICsKPiArc3RhdGljIHN0cnVjdCBpMmNfZHJpdmVyIGx0YzI5OTBfaTJjX2RyaXZl\n" - "ciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm5hbWUgPSAibHRjMjk5MCIsCj4gKwl9LAo+ICsJ\n" - "LnByb2JlICAgID0gbHRjMjk5MF9pMmNfcHJvYmUsCj4gKwkuaWRfdGFibGUgPSBsdGMyOTkwX2ky\n" - "Y19pZCwKPiArfTsKPiArCj4gK21vZHVsZV9pMmNfZHJpdmVyKGx0YzI5OTBfaTJjX2RyaXZlcik7\n" - "Cj4gKwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkxUQzI5OTAgU2Vuc29yIERyaXZlciIpOwo+ICtN\n" - "T0RVTEVfQVVUSE9SKCJUb3BpYyBFbWJlZGRlZCBQcm9kdWN0cyIpOwo+ICtNT0RVTEVfTElDRU5T\n" - "RSgiR1BMIHYyIik7Cj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n" - "X19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3Jn\n" - Cmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM + "On 01/13/2016 03:05 AM, Mike Looijmans wrote:\n" + "> This adds support for the Linear Technology LTC2990 I2C System Monitor.\n" + "> The LTC2990 supports a combination of voltage, current and temperature\n" + "> monitoring. This driver currently only supports reading two currents\n" + "> by measuring two differential voltages across series resistors, in\n" + "> addition to the Vcc supply voltage and internal temperature.\n" + ">\n" + "> This is sufficient to support the Topic Miami SOM which uses this chip\n" + "> to monitor the currents flowing into the FPGA and the CPU parts.\n" + ">\n" + "> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>\n" + "\n" + "Mike,\n" + "\n" + "That looks much better. Can you send me the output of i2cdump for the chip ?\n" + "That would help me writing module test code for it.\n" + "\n" + "Thanks,\n" + "Guenter\n" + "\n" + "> ---\n" + "> v2: Processed all review comments.\n" + "> Put chip into continuous measurement mode.\n" + "> Added ducumentation.\n" + "> Use standard hwmon interfaces and macros.\n" + ">\n" + "> Documentation/hwmon/ltc2990 | 44 ++++++++++++\n" + "> drivers/hwmon/Kconfig | 14 ++++\n" + "> drivers/hwmon/Makefile | 1 +\n" + "> drivers/hwmon/ltc2990.c | 160 ++++++++++++++++++++++++++++++++++++++++++++\n" + "> 4 files changed, 219 insertions(+)\n" + "> create mode 100644 Documentation/hwmon/ltc2990\n" + "> create mode 100644 drivers/hwmon/ltc2990.c\n" + ">\n" + "> diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990\n" + "> new file mode 100644\n" + "> index 0000000..838b74e\n" + "> --- /dev/null\n" + "> +++ b/Documentation/hwmon/ltc2990\n" + "> @@ -0,0 +1,44 @@\n" + "> +Kernel driver ltc2990\n" + "> +=====================\n" + "> +\n" + "> +Supported chips:\n" + "> + * Linear Technology LTC2990\n" + "> + Prefix: 'ltc2990'\n" + "> + Addresses scanned: -\n" + "> + Datasheet: http://www.linear.com/product/ltc2990\n" + "> +\n" + "> +Author: Mike Looijmans <mike.looijmans@topic.nl>\n" + "> +\n" + "> +\n" + "> +Description\n" + "> +-----------\n" + "> +\n" + "> +LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor.\n" + "> +The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4)\n" + "> +can be combined to measure a differential voltage, which is typically used to\n" + "> +measure current through a series resistor, or a temperature.\n" + "> +\n" + "> +This driver currently uses the 2x differential mode only. In order to support\n" + "> +other modes, the driver will need to be expanded.\n" + "> +\n" + "> +\n" + "> +Usage Notes\n" + "> +-----------\n" + "> +\n" + "> +This driver does not probe for PMBus devices. You will have to instantiate\n" + "> +devices explicitly.\n" + "> +\n" + "> +\n" + "> +Sysfs attributes\n" + "> +----------------\n" + "> +\n" + "> +The \"curr*_input\" measurements actually report the voltage drop across the\n" + "> +input pins in microvolts. This is equivalent to the current through a 1mOhm\n" + "> +sense resistor. Divide the reported value by the actual sense resistor value\n" + "> +in mOhm to get the actual value.\n" + "> +\n" + "> +in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V)\n" + "> +temp1_input Internal chip temperature in millidegrees Celcius\n" + "> +curr1_input Current in mA across v1-v2 assuming a 1mOhm sense resistor.\n" + "> +curr2_input Current in mA across v3-v4 assuming a 1mOhm sense resistor.\n" + "> +\n" + "> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig\n" + "> index 80a73bf..8a31d64 100644\n" + "> --- a/drivers/hwmon/Kconfig\n" + "> +++ b/drivers/hwmon/Kconfig\n" + "> @@ -685,6 +685,20 @@ config SENSORS_LTC2945\n" + "> \t This driver can also be built as a module. If so, the module will\n" + "> \t be called ltc2945.\n" + ">\n" + "> +config SENSORS_LTC2990\n" + "> +\ttristate \"Linear Technology LTC2990 (current monitoring mode only)\"\n" + "> +\tdepends on I2C\n" + "> +\thelp\n" + "> +\t If you say yes here you get support for Linear Technology LTC2990\n" + "> +\t I2C System Monitor. The LTC2990 supports a combination of voltage,\n" + "> +\t current and temperature monitoring, but in addition to the Vcc supply\n" + "> +\t voltage and chip temperature, this driver currently only supports\n" + "> +\t reading two currents by measuring two differential voltages across\n" + "> +\t series resistors.\n" + "> +\n" + "> +\t This driver can also be built as a module. If so, the module will\n" + "> +\t be called ltc2990.\n" + "> +\n" + "> config SENSORS_LTC4151\n" + "> \ttristate \"Linear Technology LTC4151\"\n" + "> \tdepends on I2C\n" + "> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile\n" + "> index 12a3239..e4bd15b 100644\n" + "> --- a/drivers/hwmon/Makefile\n" + "> +++ b/drivers/hwmon/Makefile\n" + "> @@ -101,6 +101,7 @@ obj-$(CONFIG_SENSORS_LM95234)\t+= lm95234.o\n" + "> obj-$(CONFIG_SENSORS_LM95241)\t+= lm95241.o\n" + "> obj-$(CONFIG_SENSORS_LM95245)\t+= lm95245.o\n" + "> obj-$(CONFIG_SENSORS_LTC2945)\t+= ltc2945.o\n" + "> +obj-$(CONFIG_SENSORS_LTC2990)\t+= ltc2990.o\n" + "> obj-$(CONFIG_SENSORS_LTC4151)\t+= ltc4151.o\n" + "> obj-$(CONFIG_SENSORS_LTC4215)\t+= ltc4215.o\n" + "> obj-$(CONFIG_SENSORS_LTC4222)\t+= ltc4222.o\n" + "> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c\n" + "> new file mode 100644\n" + "> index 0000000..3720ff7\n" + "> --- /dev/null\n" + "> +++ b/drivers/hwmon/ltc2990.c\n" + "> @@ -0,0 +1,160 @@\n" + "> +/*\n" + "> + * Driver for Linear Technology LTC2990 power monitor\n" + "> + *\n" + "> + * Copyright (C) 2014 Topic Embedded Products\n" + "> + * Author: Mike Looijmans <mike.looijmans@topic.nl>\n" + "> + *\n" + "> + * License: GPLv2\n" + "> + *\n" + "> + * This driver assumes the chip is wired as a dual current monitor, and\n" + "> + * reports the voltage drop across two series resistors. It also reports\n" + "> + * the chip's internal temperature and Vcc power supply voltage.\n" + "> + */\n" + "> +\n" + "> +#include <linux/delay.h>\n" + "> +#include <linux/err.h>\n" + "> +#include <linux/hwmon.h>\n" + "> +#include <linux/hwmon-sysfs.h>\n" + "> +#include <linux/i2c.h>\n" + "> +#include <linux/kernel.h>\n" + "> +#include <linux/module.h>\n" + "> +#include <linux/slab.h>\n" + "> +\n" + "> +#define LTC2990_STATUS\t0x00\n" + "> +#define LTC2990_CONTROL\t0x01\n" + "> +#define LTC2990_TRIGGER\t0x02\n" + "> +#define LTC2990_TINT_MSB\t0x04\n" + "> +#define LTC2990_TINT_LSB\t0x05\n" + "> +#define LTC2990_V1_MSB\t0x06\n" + "> +#define LTC2990_V1_LSB\t0x07\n" + "> +#define LTC2990_V2_MSB\t0x08\n" + "> +#define LTC2990_V2_LSB\t0x09\n" + "> +#define LTC2990_V3_MSB\t0x0A\n" + "> +#define LTC2990_V3_LSB\t0x0B\n" + "> +#define LTC2990_V4_MSB\t0x0C\n" + "> +#define LTC2990_V4_LSB\t0x0D\n" + "> +#define LTC2990_VCC_MSB\t0x0E\n" + "> +#define LTC2990_VCC_LSB\t0x0F\n" + "> +\n" + "\n" + "LSB not used.\n" + "\n" + "> +#define LTC2990_STATUS_BUSY\tBIT(0)\n" + "> +#define LTC2990_STATUS_TINT\tBIT(1)\n" + "> +#define LTC2990_STATUS_V1\tBIT(2)\n" + "> +#define LTC2990_STATUS_V2\tBIT(3)\n" + "> +#define LTC2990_STATUS_V3\tBIT(4)\n" + "> +#define LTC2990_STATUS_V4\tBIT(5)\n" + "> +#define LTC2990_STATUS_VCC\tBIT(6)\n" + "> +\n" + "No longer used ?\n" + "\n" + "> +/* Only define control settings we actually use */\n" + "\n" + "Hmmm ... but not all are used.\n" + "\n" + "> +#define LTC2990_CONTROL_KELVIN\t\tBIT(7)\n" + "> +#define LTC2990_CONTROL_SINGLE\t\tBIT(6)\n" + "> +#define LTC2990_CONTROL_MEASURE_ALL\t(0x3 << 3)\n" + "> +#define LTC2990_CONTROL_MODE_CURRENT\t0x06\n" + "> +#define LTC2990_CONTROL_MODE_VOLTAGE\t0x07\n" + "> +\n" + "> +/* convert raw register value to sign-extended integer in 16-bit range */\n" + "> +static int ltc2990_voltage_to_int(int raw)\n" + "> +{\n" + "> +\tif (raw & BIT(14)) {\n" + "> +\t\treturn -(0x4000 - (raw & 0x3FFF)) << 2;\n" + "> +\t} else {\n" + "> +\t\treturn (raw & 0x3FFF) << 2;\n" + "> +\t}\n" + "> +}\n" + "> +\n" + "> +/* Return the converted value from the given register in uV or mC */\n" + "> +static int ltc2990_get_value(struct i2c_client *i2c, u8 index)\n" + "> +{\n" + "> +\tint val;\n" + "> +\tint result;\n" + "> +\n" + "> +\tval = i2c_smbus_read_word_swapped(i2c, (index << 1) + LTC2990_TINT_MSB);\n" + "> +\tif (unlikely(val < 0))\n" + "> +\t\treturn val;\n" + "> +\n" + "> +\tif (index == 0) { /* internal temp, 0.0625 degrees/LSB, 13-bit */\n" + "> +\t\tval = (val & 0x1FFF) << 3;\n" + "> +\t\tresult = (val * 1000) >> 7;\n" + "> +\t} else if (index < 5) { /* Vx-Vy, 19.42uV/LSB */\n" + "> +\t\tresult = ltc2990_voltage_to_int(val) * 1942 / (4 * 100);\n" + "> +\t} else { /* Vcc, 305.18\316\274V/LSB, 2.5V offset */\n" + "> +\t\tresult = ltc2990_voltage_to_int(val) * 30518 / (4 * 100 * 1000);\n" + "> +\t\tresult += 2500;\n" + "> +\t}\n" + "> +\n" + "With the register in index (see below) this could be\n" + "\n" + "\tval = i2c_smbus_read_word_swapped(i2c, index);\n" + "\n" + "\tswitch (index) {\n" + "\tcase LTC2990_TINT_MSB:\n" + "\t\tval = (val & 0x1FFF) << 3;\n" + "\t\tresult = (val * 1000) >> 7;\n" + "\t\tbreak;\n" + "\tcase LTC2990_V1_MSB:\n" + "\tcase LTC2990_V2_MSB:\n" + "\t\t...\n" + "\t\tresult = ltc2990_voltage_to_int(val) * 1942 / (4 * 100);\n" + "\t\tbreak;\n" + "\tcase LTC2990_VCC_MSB:\n" + "\t\tresult = ltc2990_voltage_to_int(val) * 30518 / (4 * 100 * 1000);\n" + "\t\tresult += 2500;\n" + "\t\tbreak;\n" + "\tdefault:\n" + "\t\tresult = 0;\t/* won't happen, makes compiler happy */\n" + "\t\tbreak;\n" + "\t}\n" + "\n" + "which I think would be easier to understand.\n" + "\t\n" + "> +\treturn result;\n" + "> +}\n" + "> +\n" + "> +static ssize_t ltc2990_show_value(struct device *dev,\n" + "> +\t\t\t\t struct device_attribute *da, char *buf)\n" + "> +{\n" + "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" + "> +\tint value;\n" + "> +\n" + "> +\tvalue = ltc2990_get_value(dev_get_drvdata(dev), attr->index);\n" + "> +\treturn snprintf(buf, PAGE_SIZE, \"%d\\n\", value);\n" + "> +}\n" + "> +\n" + "> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, 0);\n" + "> +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL, 1);\n" + "> +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL, 3);\n" + "> +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL, 5);\n" + "\n" + "Consider providing the register MSB in index.\n" + "\n" + "Example:\n" + "\tstatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, LTC2990_TINT_MSB);\n" + "\n" + "\n" + "\n" + "\n" + "> +\n" + "> +static struct attribute *ltc2990_attrs[] = {\n" + "> +\t&sensor_dev_attr_temp1_input.dev_attr.attr,\n" + "> +\t&sensor_dev_attr_curr1_input.dev_attr.attr,\n" + "> +\t&sensor_dev_attr_curr2_input.dev_attr.attr,\n" + "> +\t&sensor_dev_attr_in0_input.dev_attr.attr,\n" + "> +\tNULL,\n" + "> +};\n" + "> +ATTRIBUTE_GROUPS(ltc2990);\n" + "> +\n" + "> +static int ltc2990_i2c_probe(struct i2c_client *i2c,\n" + "> +\tconst struct i2c_device_id *id)\n" + "\n" + "Please align continuation lines with '('.\n" + "\n" + "> +{\n" + "> +\tint ret;\n" + "> +\tstruct device *hwmon_dev;\n" + "> +\n" + "> +\tif (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))\n" + "\n" + "Also need capability to read words.\n" + "\n" + "> +\t\treturn -ENODEV;\n" + "> +\n" + "> +\t/* Setup continuous mode, current monitor */\n" + "> +\tret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL,\n" + "> +\t\tLTC2990_CONTROL_MEASURE_ALL | LTC2990_CONTROL_MODE_CURRENT);\n" + "> +\tif (ret < 0) {\n" + "> +\t\tdev_err(&i2c->dev, \"Error: Failed to set control mode.\\n\");\n" + "> +\t\treturn ret;\n" + "> +\t}\n" + "> +\t/* Trigger once to start continuous conversion */\n" + "> +\tret = i2c_smbus_write_byte_data(i2c, LTC2990_TRIGGER, 1);\n" + "> +\tif (ret < 0) {\n" + "> +\t\tdev_err(&i2c->dev, \"Error: Failed to start aquisition.\\n\");\n" + "\n" + "s/aquisition/acquisition/\n" + "\n" + "> +\t\treturn ret;\n" + "> +\t}\n" + "> +\n" + "> +\thwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev,\n" + "> +\t\t\t\t\t\t\t i2c->name,\n" + "> +\t\t\t\t\t\t\t i2c,\n" + "> +\t\t\t\t\t\t\t ltc2990_groups);\n" + "> +\n" + "> +\treturn PTR_ERR_OR_ZERO(hwmon_dev);\n" + "> +}\n" + "> +\n" + "> +static const struct i2c_device_id ltc2990_i2c_id[] = {\n" + "> +\t{ \"ltc2990\", 0 },\n" + "> +\t{}\n" + "> +};\n" + "> +MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id);\n" + "> +\n" + "> +static struct i2c_driver ltc2990_i2c_driver = {\n" + "> +\t.driver = {\n" + "> +\t\t.name = \"ltc2990\",\n" + "> +\t},\n" + "> +\t.probe = ltc2990_i2c_probe,\n" + "> +\t.id_table = ltc2990_i2c_id,\n" + "> +};\n" + "> +\n" + "> +module_i2c_driver(ltc2990_i2c_driver);\n" + "> +\n" + "> +MODULE_DESCRIPTION(\"LTC2990 Sensor Driver\");\n" + "> +MODULE_AUTHOR(\"Topic Embedded Products\");\n" + "> +MODULE_LICENSE(\"GPL v2\");\n" + > -80ee6a65fc161eb4a443d59d7889e65d8b6b394852e768415b418f0e466d497e +bc0d65a51f69800bcef6977a751bcb51583f16a8139f25688b574fbf110b5d91
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.