From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vasant Hegde Subject: [PATCH v3 3/3] leds/powernv: Add driver for PowerNV platform Date: Mon, 20 Apr 2015 13:31:45 +0530 Message-ID: <20150420080124.12371.41528.stgit@localhost.localdomain> References: <20150420075558.12371.6697.stgit@localhost.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20150420075558.12371.6697.stgit@localhost.localdomain> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+glppe-linuxppc-embedded-2=m.gmane.org@lists.ozlabs.org Sender: "Linuxppc-dev" To: linuxppc-dev@lists.ozlabs.org, linux-leds@vger.kernel.org Cc: stewart@linux.vnet.ibm.com, cooloney@gmail.com, rpurdie@rpsys.net, j.anaszewski@samsung.com, khandual@linux.vnet.ibm.com List-Id: linux-leds@vger.kernel.org VGhpcyBwYXRjaCBpbXBsZW1lbnRzIExFRCBkcml2ZXIgZm9yIFBvd2VyTlYgcGxhdGZvcm0gdXNp bmcgdGhlIGV4aXN0aW5nCmdlbmVyaWMgTEVEIGNsYXNzIGZyYW1ld29yay4KClBvd2VyTlYgcGxh dGZvcm0gaGFzIGJlbG93IHR5cGUgb2YgTEVEczoKICAtIFN5c3RlbSBhdHRlbnRpb24KICAgICAg SW5kaWNhdGVzIHRoZXJlIGlzIGEgcHJvYmxlbSB3aXRoIHRoZSBzeXN0ZW0gdGhhdCBuZWVkcyBh dHRlbnRpb24uCiAgLSBJZGVudGlmeQogICAgICBIZWxwcyB0aGUgdXNlciBsb2NhdGUvaWRlbnRp ZnkgYSBwYXJ0aWN1bGFyIEZSVSBvciByZXNvdXJjZSBpbiB0aGUKICAgICAgc3lzdGVtLgogIC0g RmF1bHQKICAgICAgSW5kaWNhdGVzIHRoZXJlIGlzIGEgcHJvYmxlbSB3aXRoIHRoZSBGUlUgb3Ig cmVzb3VyY2UgYXQgdGhlCiAgICAgIGxvY2F0aW9uIHdpdGggd2hpY2ggdGhlIGluZGljYXRvciBp cyBhc3NvY2lhdGVkLgoKV2UgcmVnaXN0ZXJzIGNsYXNzZGV2IHN0cnVjdHVyZXMgZm9yIGFsbCBp bmRpdmlkdWFsIExFRHMgZGV0ZWN0ZWQgb24gdGhlCnN5c3RlbSB0aHJvdWdoIExFRCBzcGVjaWZp YyBkZXZpY2UgdHJlZSBub2Rlcy4gRGV2aWNlIHRyZWUgbm9kZXMgc3BlY2lmeQp3aGF0ICBhbGwg a2luZCBvZiBMRURzIHByZXNlbnQgb24gdGhlIHNhbWUgbG9jYXRpb24gY29kZS4gSXQgcmVnaXN0 ZXJzCkxFRCBjbGFzc2RldiBzdHJ1Y3R1cmUgZm9yIGVhY2ggb2YgdGhlbS4KCkFsbCB0aGUgc3lz dGVtIExFRHMgY2FuIGJlIGZvdW5kIGluIHRoZSBzYW1lIHJlZ3VsYXIgcGF0aCAvc3lzL2NsYXNz L2xlZHMvLgpXZSBkb24ndCB1c2UgTEVEIGNvbG9ycy4gSGVuY2Ugb3VyIExFRHMgaGF2ZSBuYW1l cyBpbiB0aGlzIGZvcm1hdC4KCiAgICAgICAgPGxvY2F0aW9uX2NvZGU+OjxBVFRFTlRJT058SURF TlR8RkFVTFQ+CgpBbnkgcG9zaXRpdmUgYnJpZ2h0bmVzcyB2YWx1ZSB3b3VsZCB0dXJuIG9uIHRo ZSBMRUQgYW5kIGEgemVybyB2YWx1ZSB3b3VsZAp0dXJuIG9mZiB0aGUgTEVELiBUaGUgZHJpdmVy IHdpbGwgcmV0dXJuIExFRF9GVUxMICgyNTUpIGZvciBhbnkgdHVybmVkIG9uCkxFRCBhbmQgTEVE X09GRiAoMCkgZm9yIGFueSB0dXJuZWQgb2ZmIExFRC4KCkFzIHBlciB0aGUgTEVEIGNsYXNzIGZy YW1ld29yaywgdGhlICdicmlnaHRuZXNzX3NldCcgZnVuY3Rpb24gc2hvdWxkIG5vdApzbGVlcC4g SGVuY2UgdGhlc2UgZnVuY3Rpb25zIGhhdmUgYmVlbiBpbXBsZW1lbnRlZCB0aHJvdWdoIGdsb2Jh bCB3b3JrCnF1ZXVlIHRhc2tzIHdoaWNoIG1pZ2h0IHNsZWVwIG9uIE9QQUwgYXN5bmMgY2FsbCBj b21wbGV0aW9uLgoKVGhlIHBsYXRmb3JtIGxldmVsIGltcGxlbWVudGF0aW9uIG9mIExFRCBnZXQg YW5kIHNldCBzdGF0ZSBoYXMgYmVlbiBhY2hpZXZlZAp0aHJvdWdoIE9QQUwgY2FsbHMuIFRoZXNl IGNhbGxzIGFyZSBtYWRlIGF2YWlsYWJsZSBmb3IgdGhlIGRyaXZlciBieQpleHBvcnRpbmcgZnJv bSBhcmNoaXRlY3R1cmUgc3BlY2lmaWMgY29kZXMuCgpTaWduZWQtb2ZmLWJ5OiBWYXNhbnQgSGVn ZGUgPGhlZ2RldmFzYW50QGxpbnV4LnZuZXQuaWJtLmNvbT4KU2lnbmVkLW9mZi1ieTogQW5zaHVt YW4gS2hhbmR1YWwgPGtoYW5kdWFsQGxpbnV4LnZuZXQuaWJtLmNvbT4KQWNrZWQtYnk6IFN0ZXdh cnQgU21pdGggPHN0ZXdhcnRAbGludXgudm5ldC5pYm0uY29tPgpUZXN0ZWQtYnk6IFN0ZXdhcnQg U21pdGggPHN0ZXdhcnRAbGludXgudm5ldC5pYm0uY29tPgoKLS0tCkNoYW5nZXMgaW4gdjM6CiAg LSBBZGRyZXNzZWQgcmV2aWV3IGNvbW1lbnRzIGZyb20gSmFjZWsuIE1ham9yIG9uY2UgYXJlOgog ICAgUmVwbGFjZWQgc3BpbiBsb2NrIGFuZCBtdXRleCBhbmQgcmVtb3ZlZCByZWR1bmRhbnQgc3Ry dWN0dXJlcwogICAgUmVwbGFjZWQgcHJfKiB3aXRoIGRldl8qCiAgICBNb3ZlZCBPUEFMIHBsYXRm b3JtIHNlcGNpZmljIHBhcnQgdG8gc2VwYXJhdGUgcGF0Y2gKICAgIE1vdmVkIHJlcHRlYXRlZCBj b2RlIHRvIGNvbW1vbiBmdW5jdGlvbgogICAgQWRkZWQgZGV2aWNlIHRyZWUgZG9jdW1lbnRhdGlv biBmb3IgTEVEcwoKQ2hhbmdlcyBpbiB2MjoKICAtIEFkZGVkIFN5c3RlbSBBdHRlbnRpb24gaW5k aWNhdG9yIHN1cHBvcnQKICAtIE1vdmVkIGNvbW1vbiBjb2RlIHRvIHBvd2VybnZfbGVkX3NldF9x dWV1ZSgpCgogLi4uL2RldmljZXRyZWUvYmluZGluZ3MvbGVkcy9sZWRzLXBvd2VybnYudHh0ICAg ICAgfCAgIDM0ICsKIGRyaXZlcnMvbGVkcy9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHwgICAxMSAKIGRyaXZlcnMvbGVkcy9NYWtlZmlsZSAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIHwgICAgMSAKIGRyaXZlcnMvbGVkcy9sZWRzLXBvd2VybnYuYyAgICAgICAgICAg ICAgICAgICAgICAgIHwgIDQ1NSArKysrKysrKysrKysrKysrKysrKwogNCBmaWxlcyBjaGFuZ2Vk LCA1MDEgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2 aWNldHJlZS9iaW5kaW5ncy9sZWRzL2xlZHMtcG93ZXJudi50eHQKIGNyZWF0ZSBtb2RlIDEwMDY0 NCBkcml2ZXJzL2xlZHMvbGVkcy1wb3dlcm52LmMKCmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9u L2RldmljZXRyZWUvYmluZGluZ3MvbGVkcy9sZWRzLXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlv bi9kZXZpY2V0cmVlL2JpbmRpbmdzL2xlZHMvbGVkcy1wb3dlcm52LnR4dApuZXcgZmlsZSBtb2Rl IDEwMDY0NAppbmRleCAwMDAwMDAwLi40OTUzZmRmCi0tLSAvZGV2L251bGwKKysrIGIvRG9jdW1l bnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2xlZHMvbGVkcy1wb3dlcm52LnR4dApAQCAtMCww ICsxLDM0IEBACitEZXZpY2UgVHJlZSBiaW5kaW5nIGZvciBMRURzIG9uIElCTSBQb3dlciBTeXN0 ZW1zCistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisK K1RoZSAnbGVkJyBub2RlIHVuZGVyICcvaWJtLG9wYWwnIGxpc3RzIHNlcnZpY2UgaW5kaWNhdG9y cyBhdmFpbGFibGUgaW4gdGhlCitzeXN0ZW0gYW5kIHRoZWlyIGNhcGFiaWxpdGllcy4KKworbGVk IHsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXYzLWxlZCI7CisJcGhhbmRsZSA9IDwweDEwMDAw MDZiPjsKKwlsaW51eCxwaGFuZGxlID0gPDB4MTAwMDAwNmI+OworCWxlZC1tb2RlID0gImxpZ2h0 cGF0aCI7CisKKwlVNzhDOS4wMDEuUlNUMDAyNy1QMS1DMSB7CisJCWxlZC10eXBlcyA9ICJpZGVu dGlmeSIsICJmYXVsdCI7CisJCWxlZC1sb2MgPSAiZGVzY2VuZGVudCI7CisJCXBoYW5kbGUgPSA8 MHgxMDAwMDA2Zj47CisJCWxpbnV4LHBoYW5kbGUgPSA8MHgxMDAwMDA2Zj47CisJfTsKKwkuLi4K KwkuLi4KK307CisKKworJ2NvbXBhdGlibGUnIHByb3BlcnR5IGRlc2NyaWJlcyBMRURzIGNvbXBh dGliaWxpdHkuCisKKydsZWQtbW9kZScgcHJvcGVydHkgZGVzY3JpYmVzIHNlcnZpY2UgaW5kaWNh dG9yIG1vZGUgKGxpZ2h0cGF0aC9ndWlkaW5nbGlnaHQpLgorCitFYWNoIG5vZGUgdW5kZXIgJ2xl ZCcgbm9kZSBkZXNjcmliZXMgbG9jYXRpb24gY29kZSBvZiBGUlUvRW5jbG9zdXJlLgorCitUaGUg cHJvcGVydGllcyB1bmRlciBlYWNoIG5vZGU6CisKKyAgbGVkLXR5cGVzIDogU3VwcG9ydGVkIGlu ZGljYXRvcnMgKGF0dGVudGlvbi9pZGVudGlmeS9mYXVsdCkuCisKKyAgbGVkLWxvYyAgIDogZW5j bG9zdXJlL2Rlc2NlbmRlbnQoRlJVKSBsb2NhdGlvbiBjb2RlLgpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9sZWRzL0tjb25maWcgYi9kcml2ZXJzL2xlZHMvS2NvbmZpZwppbmRleCAyNWIzMjBkLi4yZWEw ODQ5IDEwMDY0NAotLS0gYS9kcml2ZXJzL2xlZHMvS2NvbmZpZworKysgYi9kcml2ZXJzL2xlZHMv S2NvbmZpZwpAQCAtNTA4LDYgKzUwOCwxNyBAQCBjb25maWcgTEVEU19CTElOS00KIAkgIFRoaXMg b3B0aW9uIGVuYWJsZXMgc3VwcG9ydCBmb3IgdGhlIEJsaW5rTSBSR0IgTEVEIGNvbm5lY3RlZAog CSAgdGhyb3VnaCBJMkMuIFNheSBZIHRvIGVuYWJsZSBzdXBwb3J0IGZvciB0aGUgQmxpbmtNIExF RC4KIAorY29uZmlnIExFRFNfUE9XRVJOVgorCXRyaXN0YXRlICJMRUQgc3VwcG9ydCBmb3IgUG93 ZXJOViBQbGF0Zm9ybSIKKwlkZXBlbmRzIG9uIExFRFNfQ0xBU1MKKwlkZXBlbmRzIG9uIFBQQ19Q T1dFUk5WCisJZGVwZW5kcyBvbiBPRgorCWhlbHAKKwkgIFRoaXMgb3B0aW9uIGVuYWJsZXMgc3Vw cG9ydCBmb3IgdGhlIHN5c3RlbSBMRURzIHByZXNlbnQgb24KKwkgIFBvd2VyTlYgcGxhdGZvcm1z LiBTYXkgJ3knIHRvIGVuYWJsZSB0aGlzIHN1cHBvcnQgaW4ga2VybmVsLgorCSAgVG8gY29tcGls ZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlICdtJyBoZXJlOiB0aGUgbW9kdWxlCisJ ICB3aWxsIGJlIGNhbGxlZCBsZWRzLXBvd2VybnYuCisKIGNvbmZpZyBMRURTX1NZU0NPTgogCWJv b2wgIkxFRCBzdXBwb3J0IGZvciBMRURzIG9uIHN5c3RlbSBjb250cm9sbGVycyIKIAlkZXBlbmRz IG9uIExFRFNfQ0xBU1M9eQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL01ha2VmaWxlIGIvZHJp dmVycy9sZWRzL01ha2VmaWxlCmluZGV4IGNiYmE5MjEuLjYwNGZmYzkgMTAwNjQ0Ci0tLSBhL2Ry aXZlcnMvbGVkcy9NYWtlZmlsZQorKysgYi9kcml2ZXJzL2xlZHMvTWFrZWZpbGUKQEAgLTU4LDYg KzU4LDcgQEAgb2JqLSQoQ09ORklHX0xFRFNfQkxJTktNKQkJKz0gbGVkcy1ibGlua20ubwogb2Jq LSQoQ09ORklHX0xFRFNfU1lTQ09OKQkJKz0gbGVkcy1zeXNjb24ubwogb2JqLSQoQ09ORklHX0xF RFNfVkVSU0FUSUxFKQkJKz0gbGVkcy12ZXJzYXRpbGUubwogb2JqLSQoQ09ORklHX0xFRFNfTUVO RjIxQk1DKQkJKz0gbGVkcy1tZW5mMjFibWMubworb2JqLSQoQ09ORklHX0xFRFNfUE9XRVJOVikJ CSs9IGxlZHMtcG93ZXJudi5vCiAKICMgTEVEIFNQSSBEcml2ZXJzCiBvYmotJChDT05GSUdfTEVE U19EQUMxMjRTMDg1KQkJKz0gbGVkcy1kYWMxMjRzMDg1Lm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMv bGVkcy9sZWRzLXBvd2VybnYuYyBiL2RyaXZlcnMvbGVkcy9sZWRzLXBvd2VybnYuYwpuZXcgZmls ZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5lM2MwMzNkCi0tLSAvZGV2L251bGwKKysrIGIv ZHJpdmVycy9sZWRzL2xlZHMtcG93ZXJudi5jCkBAIC0wLDAgKzEsNDU1IEBACisvKgorICogUG93 ZXJOViBMRUQgRHJpdmVyCisgKgorICogQ29weXJpZ2h0IElCTSBDb3JwLiAyMDE1CisgKgorICog QXV0aG9yOiBWYXNhbnQgSGVnZGUgPGhlZ2RldmFzYW50QGxpbnV4LnZuZXQuaWJtLmNvbT4KKyAq IEF1dGhvcjogQW5zaHVtYW4gS2hhbmR1YWwgPGtoYW5kdWFsQGxpbnV4LnZuZXQuaWJtLmNvbT4K KyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1 dGUgaXQgYW5kL29yCisgKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2Vu ZXJhbCBQdWJsaWMgTGljZW5zZQorICogYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJl IEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uCisgKiAyIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQg eW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgorICovCisKKyNkZWZpbmUgUFJFRklYCQki UE9XRVJOVl9MRUQiCisKKyNpbmNsdWRlIDxsaW51eC9sZWRzLmg+CisjaW5jbHVkZSA8bGludXgv bGlzdC5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+ CisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvc2xh Yi5oPgorCisjaW5jbHVkZSA8YXNtL29wYWwuaD4KKworI2RlZmluZSBQT1dFUk5WX0xFRF9BVFRO CSI6QVRURU5USU9OIgorI2RlZmluZSBQT1dFUk5WX0xFRF9JREVOVAkiOklERU5UIgorI2RlZmlu ZSBQT1dFUk5WX0xFRF9GQVVMVAkiOkZBVUxUIgorCisvKgorICogQnkgZGVmYXVsdCB1bmxvYWQg cGF0aCByZXNldHMgYWxsIHRoZSBMRURzLiBCdXQgb24gUG93ZXJOViBwbGF0Zm9ybQorICogd2Ug d2FudCB0byByZXRhaW4gTEVEIHN0YXRlIGFjcm9zcyByZWJvb3QgYXMgdGhlc2UgYXJlIGNvbnRy b2xsZWQgYnkKKyAqIGZpcm13YXJlLiBBbHNvIHNlcnZpY2UgcHJvY2Vzc29yIGNhbiBtb2RpZnkg dGhlIExFRHMgaW5kZXBlbmRlbnQgb2YKKyAqIE9TLiBIZW5jZSBhdm9pZCByZXNldHRpbmcgTEVE cyBpbiB1bmxvYWQgcGF0aC4KKyAqLworc3RhdGljIGJvb2wgbGVkX2Rpc2FibGVkOworCisvKiBD b252ZXJ0cyBMRUQgZXZlbnQgdHlwZSBpbnRvIGl0J3MgZGVzY3JpcHRpb24uICovCitzdGF0aWMg Y29uc3QgY2hhciAqbGVkX3R5cGVfbWFwW09QQUxfU0xPVF9MRURfVFlQRV9NQVhdID0geworCSJB dHRlbnRpb24iLCAiSWRlbnQiLCAiRmF1bHQiCit9OworCisvKgorICogTEVEIHNldCByb3V0aW5l cyBoYXZlIGJlZW4gaW1wbGVtZW50ZWQgYXMgd29yayBxdWV1ZSB0YXNrcyBzY2hlZHVsZWQKKyAq IG9uIHRoZSBnbG9iYWwgd29yayBxdWV1ZS4gSW5kaXZpZHVhbCB0YXNrIGNhbGxzIE9QQUwgaW50 ZXJmYWNlIHRvIHNldAorICogdGhlIExFRCBzdGF0ZSB3aGljaCBtaWdodCBzbGVlcCBmb3Igc29t ZSB0aW1lLgorICovCitzdHJ1Y3QgcG93ZXJudl9sZWRfZGF0YSB7CisJc3RydWN0IGxlZF9jbGFz c2RldgljZGV2OworCisJdTY0CQkJbGVkX3R5cGU7ICAvKiBBdHRlbnRpb24gb3IgSWRlbnQgb3Ig RmF1bHQgKi8KKwllbnVtIGxlZF9icmlnaHRuZXNzCXZhbHVlOyAgICAgLyogQnJpZ2h0bmVzcyB2 YWx1ZSAqLworCisJc3RydWN0IG11dGV4CQlsb2NrOworCXN0cnVjdCB3b3JrX3N0cnVjdAl3b3Jr X2xlZDsgLyogTEVEIHVwZGF0ZSB3b3JrcXVldWUgKi8KKworCXN0cnVjdCBsaXN0X2hlYWQJbGlu azsKK307CitzdGF0aWMgTElTVF9IRUFEKHBvd2VybnZfbGVkX2xpc3QpOworCisKKy8qIEdldCBM RUQgbG9jYXRpb24gY29kZSBiYXNlZCBvbiBMRUQgbmFtZSAqLworc3RhdGljIGludCBwb3dlcm52 X2dldF9sb2NfY29kZSh1NjQgbGVkX3R5cGUsIGNoYXIgKmxvY19jb2RlKQoreworCXN3aXRjaCAo bGVkX3R5cGUpIHsKKwljYXNlIE9QQUxfU0xPVF9MRURfVFlQRV9BVFROOgorCQlsb2NfY29kZVtz dHJsZW4obG9jX2NvZGUpIC0gc3RybGVuKFBPV0VSTlZfTEVEX0FUVE4pXSA9ICdcMCc7CisJCWJy ZWFrOworCWNhc2UgT1BBTF9TTE9UX0xFRF9UWVBFX0lEOgorCQlsb2NfY29kZVtzdHJsZW4obG9j X2NvZGUpIC0gc3RybGVuKFBPV0VSTlZfTEVEX0lERU5UKV0gPSAnXDAnOworCQlicmVhazsKKwlj YXNlIE9QQUxfU0xPVF9MRURfVFlQRV9GQVVMVDoKKwkJbG9jX2NvZGVbc3RybGVuKGxvY19jb2Rl KSAtIHN0cmxlbihQT1dFUk5WX0xFRF9GQVVMVCldID0gJ1wwJzsKKwkJYnJlYWs7CisJZGVmYXVs dDoJLyogVW5zdXBwb3J0ZWQgTEVEIHR5cGUgKi8KKwkJcmV0dXJuIC0xOworCX0KKwlyZXR1cm4g MDsKK30KKworLyoKKyAqIFRoaXMgY29tbWl0cyB0aGUgc3RhdGUgY2hhbmdlIG9mIHRoZSByZXF1 ZXN0ZWQgTEVEIHRocm91Z2ggYW4gT1BBTCBjYWxsLgorICogVGhpcyBmdW5jdGlvbiBpcyBjYWxs ZWQgZnJvbSB3b3JrIHF1ZXVlIHRhc2sgY29udGV4dCB3aGVuIGV2ZXIgaXQgZ2V0cworICogc2No ZWR1bGVkLiBUaGlzIGZ1bmN0aW9uIGNhbiBzbGVlcCBhdCBvcGFsX2FzeW5jX3dhaXRfcmVzcG9u c2UgY2FsbC4KKyAqLworc3RhdGljIHZvaWQgcG93ZXJudl9sZWRfc2V0KHN0cnVjdCBsZWRfY2xh c3NkZXYgKmxlZF9jZGV2LAorCQkJICAgIGVudW0gbGVkX2JyaWdodG5lc3MgdmFsdWUsIHU2NCBs ZWRfdHlwZSkKK3sKKwljaGFyICpsb2NfY29kZTsKKwlpbnQgcmMsIHRva2VuOworCXU2NCBsZWRf bWFzaywgbWF4X2xlZF90eXBlLCBsZWRfdmFsdWUgPSAwOworCXN0cnVjdCBvcGFsX21zZyBtc2c7 CisKKwkvKiBMb2NhdGlvbiBjb2RlIG9mIHRoZSBMRUQgKi8KKwlsb2NfY29kZSA9IGthc3ByaW50 ZihHRlBfS0VSTkVMLCAiJXMiLCBsZWRfY2Rldi0+bmFtZSk7CisJaWYgKCFsb2NfY29kZSkgewor CQlkZXZfZXJyKGxlZF9jZGV2LT5kZXYsCisJCQkiJXM6IE1lbW9yeSBhbGxvY2F0aW9uIGZhaWxl ZFxuIiwgX19mdW5jX18pOworCQlyZXR1cm47CisJfQorCisJaWYgKHBvd2VybnZfZ2V0X2xvY19j b2RlKGxlZF90eXBlLCBsb2NfY29kZSkgIT0gMCkKKwkJZ290byBvdXRfbG9jOworCisJLyogUHJl cGFyZSBmb3IgdGhlIE9QQUwgY2FsbCAqLworCW1heF9sZWRfdHlwZSA9IGNwdV90b19iZTY0KE9Q QUxfU0xPVF9MRURfVFlQRV9NQVgpOworCWxlZF9tYXNrID0gT1BBTF9TTE9UX0xFRF9TVEFURV9P TiA8PCBsZWRfdHlwZTsKKwlpZiAodmFsdWUpCisJCWxlZF92YWx1ZSA9IE9QQUxfU0xPVF9MRURf U1RBVEVfT04gPDwgbGVkX3R5cGU7CisKKwkvKiBPUEFMIGFzeW5jIGNhbGwgKi8KKwl0b2tlbiA9 IG9wYWxfYXN5bmNfZ2V0X3Rva2VuX2ludGVycnVwdGlibGUoKTsKKwlpZiAodG9rZW4gPCAwKSB7 CisJCWlmICh0b2tlbiAhPSAtRVJFU1RBUlRTWVMpCisJCQlkZXZfZXJyKGxlZF9jZGV2LT5kZXYs CisJCQkJIiVzOiBDb3VsZG4ndCBnZXQgT1BBTCBhc3luYyB0b2tlblxuIiwKKwkJCQlfX2Z1bmNf Xyk7CisJCWdvdG8gb3V0X2xvYzsKKwl9CisKKwlyYyA9IG9wYWxfbGVkc19zZXRfaW5kKHRva2Vu LCBsb2NfY29kZSwKKwkJCSAgICAgICBsZWRfbWFzaywgbGVkX3ZhbHVlLCAmbWF4X2xlZF90eXBl KTsKKwlpZiAocmMgIT0gT1BBTF9BU1lOQ19DT01QTEVUSU9OKSB7CisJCWRldl9lcnIobGVkX2Nk ZXYtPmRldiwKKwkJCSIlczogT1BBTCBzZXQgTEVEIGNhbGwgZmFpbGVkIGZvciAlcyBbcmM9JWRd XG4iLAorCQkJX19mdW5jX18sIGxvY19jb2RlLCByYyk7CisJCWdvdG8gb3V0X3Rva2VuOworCX0K KworCXJjID0gb3BhbF9hc3luY193YWl0X3Jlc3BvbnNlKHRva2VuLCAmbXNnKTsKKwlpZiAocmMp IHsKKwkJZGV2X2VycihsZWRfY2Rldi0+ZGV2LAorCQkJIiVzOiBGYWlsZWQgdG8gd2FpdCBmb3Ig dGhlIGFzeW5jIHJlc3BvbnNlIFtyYz0lZF1cbiIsCisJCQlfX2Z1bmNfXywgcmMpOworCQlnb3Rv IG91dF90b2tlbjsKKwl9CisKKwlyYyA9IGJlNjRfdG9fY3B1KG1zZy5wYXJhbXNbMV0pOworCWlm IChyYyAhPSBPUEFMX1NVQ0NFU1MpCisJCWRldl9lcnIobGVkX2NkZXYtPmRldiwKKwkJCSIlcyA6 IE9BUEwgYXN5bmMgY2FsbCByZXR1cm5lZCBmYWlsZWQgW3JjPSVkXVxuIiwKKwkJCV9fZnVuY19f LCByYyk7CisKK291dF90b2tlbjoKKwlvcGFsX2FzeW5jX3JlbGVhc2VfdG9rZW4odG9rZW4pOwor CitvdXRfbG9jOgorCWtmcmVlKGxvY19jb2RlKTsKK30KKworLyoKKyAqIFRoaXMgZnVuY3Rpb24g ZmV0Y2hlcyB0aGUgTEVEIHN0YXRlIGZvciBhIGdpdmVuIExFRCB0eXBlIGZvcgorICogbWVudGlv bmVkIExFRCBjbGFzc2RldiBzdHJ1Y3R1cmUuCisgKi8KK3N0YXRpYyBlbnVtIGxlZF9icmlnaHRu ZXNzIHBvd2VybnZfbGVkX2dldChzdHJ1Y3QgbGVkX2NsYXNzZGV2ICpsZWRfY2RldiwKKwkJCQkJ ICAgdTY0IGxlZF90eXBlKQoreworCWNoYXIgKmxvY19jb2RlOworCWludCByYzsKKwl1NjQgbGVk X21hc2ssIGxlZF92YWx1ZSwgbWF4X2xlZF90eXBlOworCisJLyogTEVEIGxvY2F0aW9uIGNvZGUg Ki8KKwlsb2NfY29kZSA9IGthc3ByaW50ZihHRlBfS0VSTkVMLCAiJXMiLCBsZWRfY2Rldi0+bmFt ZSk7CisJaWYgKCFsb2NfY29kZSkgeworCQlkZXZfZXJyKGxlZF9jZGV2LT5kZXYsCisJCQkiJXM6 IE1lbW9yeSBhbGxvY2F0aW9uIGZhaWxlZFxuIiwgX19mdW5jX18pOworCQlyZXR1cm4gLUVOT01F TTsKKwl9CisKKwlpZiAocG93ZXJudl9nZXRfbG9jX2NvZGUobGVkX3R5cGUsIGxvY19jb2RlKSAh PSAwKQorCQlnb3RvIGxlZF9mYWlsOworCisJLyogRmV0Y2ggYWxsIExFRCBzdGF0dXMgKi8KKwls ZWRfbWFzayA9IGNwdV90b19iZTY0KDApOworCWxlZF92YWx1ZSA9IGNwdV90b19iZTY0KDApOwor CW1heF9sZWRfdHlwZSA9IGNwdV90b19iZTY0KE9QQUxfU0xPVF9MRURfVFlQRV9NQVgpOworCisJ cmMgPSBvcGFsX2xlZHNfZ2V0X2luZChsb2NfY29kZSwgJmxlZF9tYXNrLCAmbGVkX3ZhbHVlLCAm bWF4X2xlZF90eXBlKTsKKwlpZiAocmMgIT0gT1BBTF9TVUNDRVNTICYmIHJjICE9IE9QQUxfUEFS VElBTCkgeworCQlkZXZfZXJyKGxlZF9jZGV2LT5kZXYsCisJCQkiJXM6IE9QQUwgZ2V0IGxlZCBj YWxsIGZhaWxlZCBbcmM9JWRdXG4iLAorCQkJX19mdW5jX18sIHJjKTsKKwkJZ290byBsZWRfZmFp bDsKKwl9CisKKwlsZWRfbWFzayA9IGJlNjRfdG9fY3B1KGxlZF9tYXNrKTsKKwlsZWRfdmFsdWUg PSBiZTY0X3RvX2NwdShsZWRfdmFsdWUpOworCisJLyogTEVEIHN0YXR1cyBhdmFpbGFibGUgKi8K KwlpZiAoISgobGVkX21hc2sgPj4gbGVkX3R5cGUpICYgT1BBTF9TTE9UX0xFRF9TVEFURV9PTikp IHsKKwkJZGV2X2VycihsZWRfY2Rldi0+ZGV2LAorCQkJIiVzOiAlcyBMRUQgc3RhdHVzIG5vdCBh dmFpbGFibGUgZm9yICVzXG4iLAorCQkJX19mdW5jX18sIGxlZF90eXBlX21hcFtsZWRfdHlwZV0s IGxvY19jb2RlKTsKKwkJZ290byBsZWRfZmFpbDsKKwl9CisKKwkvKiBMRUQgc3RhdHVzIHZhbHVl ICovCisJaWYgKChsZWRfdmFsdWUgPj4gbGVkX3R5cGUpICYgT1BBTF9TTE9UX0xFRF9TVEFURV9P TikgeworCQlrZnJlZShsb2NfY29kZSk7CisJCXJldHVybiBMRURfRlVMTDsKKwl9CisKK2xlZF9m YWlsOgorCWtmcmVlKGxvY19jb2RlKTsKKwlyZXR1cm4gTEVEX09GRjsKK30KKworLyoKKyAqIFRo aXMgdGhlIGZ1bmN0aW9uIHdoaWNoIHdpbGwgYmUgZXhlY3V0ZWQgYnkgYW55IExFRCB3b3JrIHRh c2sgb24gdGhlCisgKiBnbG9iYWwgd29yayBxdWV1ZS4KKyAqLworc3RhdGljIHZvaWQgcG93ZXJu dl9kZWZlcnJlZF9sZWRfc2V0KHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKK3sKKwlzdHJ1Y3Qg cG93ZXJudl9sZWRfZGF0YSAqcG93ZXJudl9sZWQgPQorCQljb250YWluZXJfb2Yod29yaywgc3Ry dWN0IHBvd2VybnZfbGVkX2RhdGEsIHdvcmtfbGVkKTsKKworCW11dGV4X2xvY2soJnBvd2VybnZf bGVkLT5sb2NrKTsKKwlwb3dlcm52X2xlZF9zZXQoJnBvd2VybnZfbGVkLT5jZGV2LAorCQkJcG93 ZXJudl9sZWQtPnZhbHVlLCBwb3dlcm52X2xlZC0+bGVkX3R5cGUpOworCW11dGV4X3VubG9jaygm cG93ZXJudl9sZWQtPmxvY2spOworfQorCisvKiBTY2hlZHVsZSB3b3JrIHRvIHVwZGF0ZSBMRUQg c3RhdGUgKi8KK3N0YXRpYyB2b2lkIHBvd2VybnZfbGVkX3NldF9xdWV1ZShzdHJ1Y3QgbGVkX2Ns YXNzZGV2ICpsZWRfY2RldiwKKwkJCQkgIGVudW0gbGVkX2JyaWdodG5lc3MgdmFsdWUsIHU2NCBs ZWRfdHlwZSkKK3sKKwlzdHJ1Y3QgcG93ZXJudl9sZWRfZGF0YSAqcG93ZXJudl9sZWQgPQorCQlj b250YWluZXJfb2YobGVkX2NkZXYsIHN0cnVjdCBwb3dlcm52X2xlZF9kYXRhLCBjZGV2KTsKKwor CS8qIERvIG5vdCBtb2RpZnkgTEVEIGluIHVubG9hZCBwYXRoICovCisJaWYgKGxlZF9kaXNhYmxl ZCkKKwkJcmV0dXJuOworCisJLyogUHJlcGFyZSB0aGUgcmVxdWVzdCAqLworCXBvd2VybnZfbGVk LT52YWx1ZSA9IHZhbHVlOworCXBvd2VybnZfbGVkLT5sZWRfdHlwZSA9IGxlZF90eXBlOworCisJ LyogU2NoZWR1bGUgdGhlIG5ldyB0YXNrICovCisJc2NoZWR1bGVfd29yaygmcG93ZXJudl9sZWQt PndvcmtfbGVkKTsKK30KKworCisvKiBMRUQgY2xhc3NkZXYgJ2JyaWdodG5lc3Nfc2V0JyBmdW5j dGlvbiBmb3IgYXR0ZW50aW9uIExFRC4gKi8KK3N0YXRpYyB2b2lkIHBvd2VybnZfbGVkX3NldF9h dHRuKHN0cnVjdCBsZWRfY2xhc3NkZXYgKmxlZF9jZGV2LAorCQkJCSAgZW51bSBsZWRfYnJpZ2h0 bmVzcyB2YWx1ZSkKK3sKKwlyZXR1cm4gcG93ZXJudl9sZWRfc2V0X3F1ZXVlKGxlZF9jZGV2LCB2 YWx1ZSwgT1BBTF9TTE9UX0xFRF9UWVBFX0FUVE4pOworfQorCisvKiBMRUQgY2xhc3NkZXYgJ2Jy aWdodG5lc3NfZ2V0JyBmdW5jdGlvbiBmb3IgYXR0ZW50aW9uIExFRC4gICovCitzdGF0aWMgZW51 bSBsZWRfYnJpZ2h0bmVzcyBwb3dlcm52X2xlZF9nZXRfYXR0bihzdHJ1Y3QgbGVkX2NsYXNzZGV2 ICpsZWRfY2RldikKK3sKKwlyZXR1cm4gcG93ZXJudl9sZWRfZ2V0KGxlZF9jZGV2LCBPUEFMX1NM T1RfTEVEX1RZUEVfQVRUTik7Cit9CisKKy8qIExFRCBjbGFzc2RldiAnYnJpZ2h0bmVzc19zZXQn IGZ1bmN0aW9uIGZvciBpZGVudCBMRUQgdHlwZXMuICovCitzdGF0aWMgdm9pZCBwb3dlcm52X2xl ZF9zZXRfaWRlbnQoc3RydWN0IGxlZF9jbGFzc2RldiAqbGVkX2NkZXYsCisJCQkJICBlbnVtIGxl ZF9icmlnaHRuZXNzIHZhbHVlKQoreworCXJldHVybiBwb3dlcm52X2xlZF9zZXRfcXVldWUobGVk X2NkZXYsIHZhbHVlLCBPUEFMX1NMT1RfTEVEX1RZUEVfSUQpOworfQorCisvKiBMRUQgY2xhc3Nk ZXYgJ2JyaWdodG5lc3NfZ2V0JyBmdW5jdGlvbiBmb3IgaWRlbnQgTEVEIHR5cGVzLiAqLworc3Rh dGljIGVudW0gbGVkX2JyaWdodG5lc3MgcG93ZXJudl9sZWRfZ2V0X2lkZW50KHN0cnVjdCBsZWRf Y2xhc3NkZXYgKmxlZF9jZGV2KQoreworCXJldHVybiBwb3dlcm52X2xlZF9nZXQobGVkX2NkZXYs IE9QQUxfU0xPVF9MRURfVFlQRV9JRCk7Cit9CisKKy8qIExFRCBjbGFzc2RldiAnYnJpZ2h0bmVz c19zZXQnIGZ1bmN0aW9uIGZvciBmYXVsdCBMRUQgdHlwZXMuICovCitzdGF0aWMgdm9pZCBwb3dl cm52X2xlZF9zZXRfZmF1bHQoc3RydWN0IGxlZF9jbGFzc2RldiAqbGVkX2NkZXYsCisJCQkJICBl bnVtIGxlZF9icmlnaHRuZXNzIHZhbHVlKQoreworCXJldHVybiBwb3dlcm52X2xlZF9zZXRfcXVl dWUobGVkX2NkZXYsIHZhbHVlLCBPUEFMX1NMT1RfTEVEX1RZUEVfRkFVTFQpOworfQorCisvKiBM RUQgY2xhc3NkZXYgJ2JyaWdodG5lc3NfZ2V0JyBmdW5jdGlvbiBmb3IgZmF1bHQgTEVEIHR5cGVz LiAqLworc3RhdGljIGVudW0gbGVkX2JyaWdodG5lc3MgcG93ZXJudl9sZWRfZ2V0X2ZhdWx0KHN0 cnVjdCBsZWRfY2xhc3NkZXYgKmxlZF9jZGV2KQoreworCXJldHVybiBwb3dlcm52X2xlZF9nZXQo bGVkX2NkZXYsIE9QQUxfU0xPVF9MRURfVFlQRV9GQVVMVCk7Cit9CisKKworLyoKKyAqIFRoaXMg ZnVuY3Rpb24gdmVyaWZpZXMgd2hldGhlciB0aGUgY2hpbGQgTEVEIGRldmljZSBub2RlIHN1cHBv cnRzIGNlcnRhaW4KKyAqIHR5cGUgb2YgTEVEIG9yIG5vdC4gVGhpcyB3aWxsIGJlIHVzZWQgdG8g cmVnaXN0ZXIgTEVEIGNsYXNzZGV2IHN0cnVjdHVyZXMKKyAqIGZvciB0aGF0IHBhcnRpY3VhbCB0 eXBlIG9mIExFRCBmb3IgYSBnaXZlbiBkZXZpY2UgdHJlZSBub2RlLgorICovCitzdGF0aWMgYm9v bCBoYXNfbGVkX3R5cGUoc3RydWN0IGRldmljZV9ub2RlICpub2RlLCBjb25zdCBjaGFyICpsZWRf dHlwZSkKK3sKKwlib29sIHJlc3VsdCA9IGZhbHNlOworCisJaWYgKG9mX3Byb3BlcnR5X21hdGNo X3N0cmluZyhub2RlLCAibGVkLXR5cGVzIiwgbGVkX3R5cGUpID49IDApCisJCXJlc3VsdCA9IHRy dWU7CisKKwlyZXR1cm4gcmVzdWx0OworfQorCisvKgorICogVGhpcyBmdW5jdGlvbiByZWdpc3Rl cnMgY2xhc3NkZXYgc3RydWN0dXJlIGZvciBhbnkgZ2l2ZW4gdHlwZSBvZiBMRUQgb24KKyAqIGEg Z2l2ZW4gY2hpbGQgTEVEIGRldmljZSBub2RlLgorICovCitzdGF0aWMgaW50IHBvd2VyX2xlZF9j bGFzc2RldihzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2LAorCQkJICAgICAgc3RydWN0IGRl dmljZV9ub2RlICpub2RlLCB1NjQgbGVkX3R5cGUpCit7CisJaW50IHJjOworCXN0cnVjdCBwb3dl cm52X2xlZF9kYXRhICpwb3dlcm52X2xlZDsKKworCXBvd2VybnZfbGVkID0ga3phbGxvYyhzaXpl b2Yoc3RydWN0IHBvd2VybnZfbGVkX2RhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBvd2VybnZf bGVkKSB7CisJCWRldl9lcnIoJnBkZXYtPmRldiwKKwkJCSIlczogTWVtb3J5IGFsbG9jYXRpb24g ZmFpbGVkXG4iLCBfX2Z1bmNfXyk7CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCS8qIENyZWF0 ZSB0aGUgbmFtZSBmb3IgY2xhc3NkZXYgKi8KKwlzd2l0Y2ggKGxlZF90eXBlKSB7CisJY2FzZSBP UEFMX1NMT1RfTEVEX1RZUEVfQVRUTjoKKwkJcG93ZXJudl9sZWQtPmNkZXYubmFtZSA9IGthc3By aW50ZihHRlBfS0VSTkVMLAorCQkJCQkJICAgIiVzJXMiLCBub2RlLT5uYW1lLAorCQkJCQkJICAg UE9XRVJOVl9MRURfQVRUTik7CisJCXBvd2VybnZfbGVkLT5jZGV2LmJyaWdodG5lc3Nfc2V0ID0g cG93ZXJudl9sZWRfc2V0X2F0dG47CisJCXBvd2VybnZfbGVkLT5jZGV2LmJyaWdodG5lc3NfZ2V0 ID0gcG93ZXJudl9sZWRfZ2V0X2F0dG47CisJCWJyZWFrOworCWNhc2UgT1BBTF9TTE9UX0xFRF9U WVBFX0lEOgorCQlwb3dlcm52X2xlZC0+Y2Rldi5uYW1lID0ga2FzcHJpbnRmKEdGUF9LRVJORUws CisJCQkJCQkgICAiJXMlcyIsIG5vZGUtPm5hbWUsCisJCQkJCQkgICBQT1dFUk5WX0xFRF9JREVO VCk7CisJCXBvd2VybnZfbGVkLT5jZGV2LmJyaWdodG5lc3Nfc2V0ID0gcG93ZXJudl9sZWRfc2V0 X2lkZW50OworCQlwb3dlcm52X2xlZC0+Y2Rldi5icmlnaHRuZXNzX2dldCA9IHBvd2VybnZfbGVk X2dldF9pZGVudDsKKwkJYnJlYWs7CisJY2FzZSBPUEFMX1NMT1RfTEVEX1RZUEVfRkFVTFQ6CisJ CXBvd2VybnZfbGVkLT5jZGV2Lm5hbWUgPSBrYXNwcmludGYoR0ZQX0tFUk5FTCwKKwkJCQkJCSAg ICIlcyVzIiwgbm9kZS0+bmFtZSwKKwkJCQkJCSAgIFBPV0VSTlZfTEVEX0ZBVUxUKTsKKwkJcG93 ZXJudl9sZWQtPmNkZXYuYnJpZ2h0bmVzc19zZXQgPSBwb3dlcm52X2xlZF9zZXRfZmF1bHQ7CisJ CXBvd2VybnZfbGVkLT5jZGV2LmJyaWdodG5lc3NfZ2V0ID0gcG93ZXJudl9sZWRfZ2V0X2ZhdWx0 OworCQlicmVhazsKKwlkZWZhdWx0OiAvKiBVbnN1cHBvcnRlZCBMRUQgdHlwZSAqLworCQlrZnJl ZShwb3dlcm52X2xlZCk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmICghcG93ZXJudl9s ZWQtPmNkZXYubmFtZSkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsCisJCQkiJXM6IE1lbW9yeSBh bGxvY2F0aW9uIGZhaWxlZCBmb3IgY2xhc3NkZXYgbmFtZVxuIiwKKwkJCV9fZnVuY19fKTsKKwkJ a2ZyZWUocG93ZXJudl9sZWQpOworCQlyZXR1cm4gLUVOT01FTTsKKwl9CisKKwlwb3dlcm52X2xl ZC0+Y2Rldi5icmlnaHRuZXNzID0gTEVEX09GRjsKKwlwb3dlcm52X2xlZC0+Y2Rldi5tYXhfYnJp Z2h0bmVzcyA9IExFRF9GVUxMOworCXBvd2VybnZfbGVkLT5jZGV2LmZsYWdzID0gTEVEX0NPUkVf U1VTUEVORFJFU1VNRTsKKworCW11dGV4X2luaXQoJnBvd2VybnZfbGVkLT5sb2NrKTsKKwlJTklU X1dPUksoJnBvd2VybnZfbGVkLT53b3JrX2xlZCwgcG93ZXJudl9kZWZlcnJlZF9sZWRfc2V0KTsK KworCS8qIFJlZ2lzdGVyIHRoZSBjbGFzc2RldiAqLworCXJjID0gbGVkX2NsYXNzZGV2X3JlZ2lz dGVyKCZwZGV2LT5kZXYsICZwb3dlcm52X2xlZC0+Y2Rldik7CisJaWYgKHJjKSB7CisJCWRldl9l cnIoJnBkZXYtPmRldiwgIiVzOiBDbGFzc2RldiByZWdpc3RyYXRpb24gZmFpbGVkIGZvciAlc1xu IiwKKwkJCV9fZnVuY19fLCBwb3dlcm52X2xlZC0+Y2Rldi5uYW1lKTsKKwkJa2ZyZWUocG93ZXJu dl9sZWQtPmNkZXYubmFtZSk7CisJCWtmcmVlKHBvd2VybnZfbGVkKTsKKwl9IGVsc2UgeworCQls aXN0X2FkZF90YWlsKCZwb3dlcm52X2xlZC0+bGluaywgJnBvd2VybnZfbGVkX2xpc3QpOworCQlk ZXZfZGJnKCZwZGV2LT5kZXYsCisJCQkiQ2xhc3NkZXYgcmVnaXN0cmF0aW9uIHN1Y2Nlc3NmdWwg Zm9yICVzXG4iLAorCQkJcG93ZXJudl9sZWQtPmNkZXYubmFtZSk7CisJfQorCXJldHVybiByYzsK K30KKworLyogUGxhdGZvcm0gZHJpdmVyIHByb2JlICovCitzdGF0aWMgaW50IHBvd2VybnZfbGVk X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJaW50IHJjID0gMDsKKwlz dHJ1Y3QgZGV2aWNlX25vZGUgKmxlZF9ub2RlLCAqbnA7CisKKwlsZWRfbm9kZSA9IG9mX2ZpbmRf bm9kZV9ieV9wYXRoKCIvaWJtLG9wYWwvbGVkIik7CisJaWYgKCFsZWRfbm9kZSkgeworCQlkZXZf ZXJyKCZwZGV2LT5kZXYsCisJCQkiJXM6IExFRCBwYXJlbnQgZGV2aWNlIG5vZGUgbm90IGZvdW5k XG4iLCBfX2Z1bmNfXyk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWZvcl9lYWNoX2NoaWxk X29mX25vZGUobGVkX25vZGUsIG5wKSB7CisJCWlmIChoYXNfbGVkX3R5cGUobnAsIExFRF9UWVBF X0FUVEVOVElPTikpCisJCQlyYyA9IHBvd2VyX2xlZF9jbGFzc2RldihwZGV2LCBucCwKKwkJCQkJ CU9QQUxfU0xPVF9MRURfVFlQRV9BVFROKTsKKworCQlpZiAoaGFzX2xlZF90eXBlKG5wLCBMRURf VFlQRV9JREVOVElGWSkpCisJCQlyYyA9IHBvd2VyX2xlZF9jbGFzc2RldihwZGV2LCBucCwKKwkJ CQkJCU9QQUxfU0xPVF9MRURfVFlQRV9JRCk7CisKKwkJaWYgKGhhc19sZWRfdHlwZShucCwgTEVE X1RZUEVfRkFVTFQpKQorCQkJcmMgPSBwb3dlcl9sZWRfY2xhc3NkZXYocGRldiwgbnAsCisJCQkJ CQlPUEFMX1NMT1RfTEVEX1RZUEVfRkFVTFQpOworCX0KKwlyZXR1cm4gcmM7Cit9CisKKy8qIFBs YXRmb3JtIGRyaXZlciByZW1vdmUgKi8KK3N0YXRpYyBpbnQgcG93ZXJudl9sZWRfcmVtb3ZlKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IHBvd2VybnZfbGVkX2RhdGEg KnBvd2VybnZfbGVkOworCisJLyogRGlzYWJsZSBMRUQgb3BlcmF0aW9uICovCisJbGVkX2Rpc2Fi bGVkID0gdHJ1ZTsKKworCWRldl9kYmcoJnBkZXYtPmRldiwKKwkJIiVzOiBVbnJlZ2lzdGVyIGFs bCBjbGFzc2RldiBzdHJ1Y3R1cmVzXG4iLCBfX2Z1bmNfXyk7CisJbGlzdF9mb3JfZWFjaF9lbnRy eShwb3dlcm52X2xlZCwgJnBvd2VybnZfbGVkX2xpc3QsIGxpbmspCisJCWxlZF9jbGFzc2Rldl91 bnJlZ2lzdGVyKCZwb3dlcm52X2xlZC0+Y2Rldik7CisKKwlkZXZfZGJnKCZwZGV2LT5kZXYsCisJ CSIlczogV2FpdCBmb3IgYWxsIHdvcmsgdGFza3MgdG8gZmluaXNoXG4iLCBfX2Z1bmNfXyk7CisJ bGlzdF9mb3JfZWFjaF9lbnRyeShwb3dlcm52X2xlZCwgJnBvd2VybnZfbGVkX2xpc3QsIGxpbmsp CisJCWZsdXNoX3dvcmsoJnBvd2VybnZfbGVkLT53b3JrX2xlZCk7CisKKwl3aGlsZSAoIWxpc3Rf ZW1wdHkoJnBvd2VybnZfbGVkX2xpc3QpKSB7CisJCXBvd2VybnZfbGVkID0gbGlzdF9maXJzdF9l bnRyeSgmcG93ZXJudl9sZWRfbGlzdCwKKwkJCQkJICAgICAgIHN0cnVjdCBwb3dlcm52X2xlZF9k YXRhLCBsaW5rKTsKKwkJbGlzdF9kZWwoJnBvd2VybnZfbGVkLT5saW5rKTsKKwkJa2ZyZWUocG93 ZXJudl9sZWQpOworCX0KKworCWRldl9pbmZvKCZwZGV2LT5kZXYsICJQb3dlck5WIGxlZCBtb2R1 bGUgdW5yZWdpc3RlcmVkXG4iKTsKKwlyZXR1cm4gMDsKK30KKworLyogUGxhdGZvcm0gZHJpdmVy IHByb3BlcnR5IG1hdGNoICovCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBwb3dl cm52X2xlZF9tYXRjaFtdID0geworCXsKKwkJLmNvbXBhdGlibGUJPSAiaWJtLG9wYWwtdjMtbGVk IiwKKwl9LAorCXt9LAorfTsKK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIHBvd2VybnZfbGVkX21h dGNoKTsKKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgcG93ZXJudl9sZWRfZHJpdmVy ID0geworCS5wcm9iZQk9IHBvd2VybnZfbGVkX3Byb2JlLAorCS5yZW1vdmUgPSBwb3dlcm52X2xl ZF9yZW1vdmUsCisJLmRyaXZlciA9IHsKKwkJLm5hbWUgPSAicG93ZXJudi1sZWQtZHJpdmVyIiwK KwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5vZl9tYXRjaF90YWJsZSA9IHBvd2VybnZfbGVk X21hdGNoLAorCX0sCit9OworCittb2R1bGVfcGxhdGZvcm1fZHJpdmVyKHBvd2VybnZfbGVkX2Ry aXZlcik7CisKK01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKK01PRFVMRV9ERVNDUklQVElPTigiUG93 ZXJOViBMRUQgZHJpdmVyIik7CitNT0RVTEVfQVVUSE9SKCJWYXNhbnQgSGVnZGUgPGhlZ2RldmFz YW50QGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fCkxpbnV4cHBjLWRldiBtYWlsaW5nIGxpc3QKTGludXhwcGMtZGV2 QGxpc3RzLm96bGFicy5vcmcKaHR0cHM6Ly9saXN0cy5vemxhYnMub3JnL2xpc3RpbmZvL2xpbnV4 cHBjLWRldg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from e28smtp04.in.ibm.com (e28smtp04.in.ibm.com [122.248.162.4]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id BE9671A2B7E for ; Mon, 20 Apr 2015 18:01:55 +1000 (AEST) Received: from /spool/local by e28smtp04.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 20 Apr 2015 13:31:53 +0530 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 09A54125805A for ; Mon, 20 Apr 2015 13:33:46 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t3K81nuC1769866 for ; Mon, 20 Apr 2015 13:31:49 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t3K7cn9B009360 for ; Mon, 20 Apr 2015 13:08:51 +0530 Subject: [PATCH v3 3/3] leds/powernv: Add driver for PowerNV platform From: Vasant Hegde To: linuxppc-dev@lists.ozlabs.org, linux-leds@vger.kernel.org Date: Mon, 20 Apr 2015 13:31:45 +0530 Message-ID: <20150420080124.12371.41528.stgit@localhost.localdomain> In-Reply-To: <20150420075558.12371.6697.stgit@localhost.localdomain> References: <20150420075558.12371.6697.stgit@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Cc: stewart@linux.vnet.ibm.com, cooloney@gmail.com, rpurdie@rpsys.net, j.anaszewski@samsung.com, khandual@linux.vnet.ibm.com List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , This patch implements LED driver for PowerNV platform using the existing generic LED class framework. PowerNV platform has below type of LEDs: - System attention Indicates there is a problem with the system that needs attention. - Identify Helps the user locate/identify a particular FRU or resource in the system. - Fault Indicates there is a problem with the FRU or resource at the location with which the indicator is associated. We registers classdev structures for all individual LEDs detected on the system through LED specific device tree nodes. Device tree nodes specify what all kind of LEDs present on the same location code. It registers LED classdev structure for each of them. All the system LEDs can be found in the same regular path /sys/class/leds/. We don't use LED colors. Hence our LEDs have names in this format. : Any positive brightness value would turn on the LED and a zero value would turn off the LED. The driver will return LED_FULL (255) for any turned on LED and LED_OFF (0) for any turned off LED. As per the LED class framework, the 'brightness_set' function should not sleep. Hence these functions have been implemented through global work queue tasks which might sleep on OPAL async call completion. The platform level implementation of LED get and set state has been achieved through OPAL calls. These calls are made available for the driver by exporting from architecture specific codes. Signed-off-by: Vasant Hegde Signed-off-by: Anshuman Khandual Acked-by: Stewart Smith Tested-by: Stewart Smith --- Changes in v3: - Addressed review comments from Jacek. Major once are: Replaced spin lock and mutex and removed redundant structures Replaced pr_* with dev_* Moved OPAL platform sepcific part to separate patch Moved repteated code to common function Added device tree documentation for LEDs Changes in v2: - Added System Attention indicator support - Moved common code to powernv_led_set_queue() .../devicetree/bindings/leds/leds-powernv.txt | 34 + drivers/leds/Kconfig | 11 drivers/leds/Makefile | 1 drivers/leds/leds-powernv.c | 455 ++++++++++++++++++++ 4 files changed, 501 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-powernv.txt create mode 100644 drivers/leds/leds-powernv.c diff --git a/Documentation/devicetree/bindings/leds/leds-powernv.txt b/Documentation/devicetree/bindings/leds/leds-powernv.txt new file mode 100644 index 0000000..4953fdf --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-powernv.txt @@ -0,0 +1,34 @@ +Device Tree binding for LEDs on IBM Power Systems +------------------------------------------------- + +The 'led' node under '/ibm,opal' lists service indicators available in the +system and their capabilities. + +led { + compatible = "ibm,opal-v3-led"; + phandle = <0x1000006b>; + linux,phandle = <0x1000006b>; + led-mode = "lightpath"; + + U78C9.001.RST0027-P1-C1 { + led-types = "identify", "fault"; + led-loc = "descendent"; + phandle = <0x1000006f>; + linux,phandle = <0x1000006f>; + }; + ... + ... +}; + + +'compatible' property describes LEDs compatibility. + +'led-mode' property describes service indicator mode (lightpath/guidinglight). + +Each node under 'led' node describes location code of FRU/Enclosure. + +The properties under each node: + + led-types : Supported indicators (attention/identify/fault). + + led-loc : enclosure/descendent(FRU) location code. diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 25b320d..2ea0849 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -508,6 +508,17 @@ config LEDS_BLINKM This option enables support for the BlinkM RGB LED connected through I2C. Say Y to enable support for the BlinkM LED. +config LEDS_POWERNV + tristate "LED support for PowerNV Platform" + depends on LEDS_CLASS + depends on PPC_POWERNV + depends on OF + help + This option enables support for the system LEDs present on + PowerNV platforms. Say 'y' to enable this support in kernel. + To compile this driver as a module, choose 'm' here: the module + will be called leds-powernv. + config LEDS_SYSCON bool "LED support for LEDs on system controllers" depends on LEDS_CLASS=y diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index cbba921..604ffc9 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o +obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c new file mode 100644 index 0000000..e3c033d --- /dev/null +++ b/drivers/leds/leds-powernv.c @@ -0,0 +1,455 @@ +/* + * PowerNV LED Driver + * + * Copyright IBM Corp. 2015 + * + * Author: Vasant Hegde + * Author: Anshuman Khandual + * + * 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. + */ + +#define PREFIX "POWERNV_LED" + +#include +#include +#include +#include +#include +#include + +#include + +#define POWERNV_LED_ATTN ":ATTENTION" +#define POWERNV_LED_IDENT ":IDENT" +#define POWERNV_LED_FAULT ":FAULT" + +/* + * By default unload path resets all the LEDs. But on PowerNV platform + * we want to retain LED state across reboot as these are controlled by + * firmware. Also service processor can modify the LEDs independent of + * OS. Hence avoid resetting LEDs in unload path. + */ +static bool led_disabled; + +/* Converts LED event type into it's description. */ +static const char *led_type_map[OPAL_SLOT_LED_TYPE_MAX] = { + "Attention", "Ident", "Fault" +}; + +/* + * LED set routines have been implemented as work queue tasks scheduled + * on the global work queue. Individual task calls OPAL interface to set + * the LED state which might sleep for some time. + */ +struct powernv_led_data { + struct led_classdev cdev; + + u64 led_type; /* Attention or Ident or Fault */ + enum led_brightness value; /* Brightness value */ + + struct mutex lock; + struct work_struct work_led; /* LED update workqueue */ + + struct list_head link; +}; +static LIST_HEAD(powernv_led_list); + + +/* Get LED location code based on LED name */ +static int powernv_get_loc_code(u64 led_type, char *loc_code) +{ + switch (led_type) { + case OPAL_SLOT_LED_TYPE_ATTN: + loc_code[strlen(loc_code) - strlen(POWERNV_LED_ATTN)] = '\0'; + break; + case OPAL_SLOT_LED_TYPE_ID: + loc_code[strlen(loc_code) - strlen(POWERNV_LED_IDENT)] = '\0'; + break; + case OPAL_SLOT_LED_TYPE_FAULT: + loc_code[strlen(loc_code) - strlen(POWERNV_LED_FAULT)] = '\0'; + break; + default: /* Unsupported LED type */ + return -1; + } + return 0; +} + +/* + * This commits the state change of the requested LED through an OPAL call. + * This function is called from work queue task context when ever it gets + * scheduled. This function can sleep at opal_async_wait_response call. + */ +static void powernv_led_set(struct led_classdev *led_cdev, + enum led_brightness value, u64 led_type) +{ + char *loc_code; + int rc, token; + u64 led_mask, max_led_type, led_value = 0; + struct opal_msg msg; + + /* Location code of the LED */ + loc_code = kasprintf(GFP_KERNEL, "%s", led_cdev->name); + if (!loc_code) { + dev_err(led_cdev->dev, + "%s: Memory allocation failed\n", __func__); + return; + } + + if (powernv_get_loc_code(led_type, loc_code) != 0) + goto out_loc; + + /* Prepare for the OPAL call */ + max_led_type = cpu_to_be64(OPAL_SLOT_LED_TYPE_MAX); + led_mask = OPAL_SLOT_LED_STATE_ON << led_type; + if (value) + led_value = OPAL_SLOT_LED_STATE_ON << led_type; + + /* OPAL async call */ + token = opal_async_get_token_interruptible(); + if (token < 0) { + if (token != -ERESTARTSYS) + dev_err(led_cdev->dev, + "%s: Couldn't get OPAL async token\n", + __func__); + goto out_loc; + } + + rc = opal_leds_set_ind(token, loc_code, + led_mask, led_value, &max_led_type); + if (rc != OPAL_ASYNC_COMPLETION) { + dev_err(led_cdev->dev, + "%s: OPAL set LED call failed for %s [rc=%d]\n", + __func__, loc_code, rc); + goto out_token; + } + + rc = opal_async_wait_response(token, &msg); + if (rc) { + dev_err(led_cdev->dev, + "%s: Failed to wait for the async response [rc=%d]\n", + __func__, rc); + goto out_token; + } + + rc = be64_to_cpu(msg.params[1]); + if (rc != OPAL_SUCCESS) + dev_err(led_cdev->dev, + "%s : OAPL async call returned failed [rc=%d]\n", + __func__, rc); + +out_token: + opal_async_release_token(token); + +out_loc: + kfree(loc_code); +} + +/* + * This function fetches the LED state for a given LED type for + * mentioned LED classdev structure. + */ +static enum led_brightness powernv_led_get(struct led_classdev *led_cdev, + u64 led_type) +{ + char *loc_code; + int rc; + u64 led_mask, led_value, max_led_type; + + /* LED location code */ + loc_code = kasprintf(GFP_KERNEL, "%s", led_cdev->name); + if (!loc_code) { + dev_err(led_cdev->dev, + "%s: Memory allocation failed\n", __func__); + return -ENOMEM; + } + + if (powernv_get_loc_code(led_type, loc_code) != 0) + goto led_fail; + + /* Fetch all LED status */ + led_mask = cpu_to_be64(0); + led_value = cpu_to_be64(0); + max_led_type = cpu_to_be64(OPAL_SLOT_LED_TYPE_MAX); + + rc = opal_leds_get_ind(loc_code, &led_mask, &led_value, &max_led_type); + if (rc != OPAL_SUCCESS && rc != OPAL_PARTIAL) { + dev_err(led_cdev->dev, + "%s: OPAL get led call failed [rc=%d]\n", + __func__, rc); + goto led_fail; + } + + led_mask = be64_to_cpu(led_mask); + led_value = be64_to_cpu(led_value); + + /* LED status available */ + if (!((led_mask >> led_type) & OPAL_SLOT_LED_STATE_ON)) { + dev_err(led_cdev->dev, + "%s: %s LED status not available for %s\n", + __func__, led_type_map[led_type], loc_code); + goto led_fail; + } + + /* LED status value */ + if ((led_value >> led_type) & OPAL_SLOT_LED_STATE_ON) { + kfree(loc_code); + return LED_FULL; + } + +led_fail: + kfree(loc_code); + return LED_OFF; +} + +/* + * This the function which will be executed by any LED work task on the + * global work queue. + */ +static void powernv_deferred_led_set(struct work_struct *work) +{ + struct powernv_led_data *powernv_led = + container_of(work, struct powernv_led_data, work_led); + + mutex_lock(&powernv_led->lock); + powernv_led_set(&powernv_led->cdev, + powernv_led->value, powernv_led->led_type); + mutex_unlock(&powernv_led->lock); +} + +/* Schedule work to update LED state */ +static void powernv_led_set_queue(struct led_classdev *led_cdev, + enum led_brightness value, u64 led_type) +{ + struct powernv_led_data *powernv_led = + container_of(led_cdev, struct powernv_led_data, cdev); + + /* Do not modify LED in unload path */ + if (led_disabled) + return; + + /* Prepare the request */ + powernv_led->value = value; + powernv_led->led_type = led_type; + + /* Schedule the new task */ + schedule_work(&powernv_led->work_led); +} + + +/* LED classdev 'brightness_set' function for attention LED. */ +static void powernv_led_set_attn(struct led_classdev *led_cdev, + enum led_brightness value) +{ + return powernv_led_set_queue(led_cdev, value, OPAL_SLOT_LED_TYPE_ATTN); +} + +/* LED classdev 'brightness_get' function for attention LED. */ +static enum led_brightness powernv_led_get_attn(struct led_classdev *led_cdev) +{ + return powernv_led_get(led_cdev, OPAL_SLOT_LED_TYPE_ATTN); +} + +/* LED classdev 'brightness_set' function for ident LED types. */ +static void powernv_led_set_ident(struct led_classdev *led_cdev, + enum led_brightness value) +{ + return powernv_led_set_queue(led_cdev, value, OPAL_SLOT_LED_TYPE_ID); +} + +/* LED classdev 'brightness_get' function for ident LED types. */ +static enum led_brightness powernv_led_get_ident(struct led_classdev *led_cdev) +{ + return powernv_led_get(led_cdev, OPAL_SLOT_LED_TYPE_ID); +} + +/* LED classdev 'brightness_set' function for fault LED types. */ +static void powernv_led_set_fault(struct led_classdev *led_cdev, + enum led_brightness value) +{ + return powernv_led_set_queue(led_cdev, value, OPAL_SLOT_LED_TYPE_FAULT); +} + +/* LED classdev 'brightness_get' function for fault LED types. */ +static enum led_brightness powernv_led_get_fault(struct led_classdev *led_cdev) +{ + return powernv_led_get(led_cdev, OPAL_SLOT_LED_TYPE_FAULT); +} + + +/* + * This function verifies whether the child LED device node supports certain + * type of LED or not. This will be used to register LED classdev structures + * for that particual type of LED for a given device tree node. + */ +static bool has_led_type(struct device_node *node, const char *led_type) +{ + bool result = false; + + if (of_property_match_string(node, "led-types", led_type) >= 0) + result = true; + + return result; +} + +/* + * This function registers classdev structure for any given type of LED on + * a given child LED device node. + */ +static int power_led_classdev(struct platform_device *pdev, + struct device_node *node, u64 led_type) +{ + int rc; + struct powernv_led_data *powernv_led; + + powernv_led = kzalloc(sizeof(struct powernv_led_data), GFP_KERNEL); + if (!powernv_led) { + dev_err(&pdev->dev, + "%s: Memory allocation failed\n", __func__); + return -ENOMEM; + } + + /* Create the name for classdev */ + switch (led_type) { + case OPAL_SLOT_LED_TYPE_ATTN: + powernv_led->cdev.name = kasprintf(GFP_KERNEL, + "%s%s", node->name, + POWERNV_LED_ATTN); + powernv_led->cdev.brightness_set = powernv_led_set_attn; + powernv_led->cdev.brightness_get = powernv_led_get_attn; + break; + case OPAL_SLOT_LED_TYPE_ID: + powernv_led->cdev.name = kasprintf(GFP_KERNEL, + "%s%s", node->name, + POWERNV_LED_IDENT); + powernv_led->cdev.brightness_set = powernv_led_set_ident; + powernv_led->cdev.brightness_get = powernv_led_get_ident; + break; + case OPAL_SLOT_LED_TYPE_FAULT: + powernv_led->cdev.name = kasprintf(GFP_KERNEL, + "%s%s", node->name, + POWERNV_LED_FAULT); + powernv_led->cdev.brightness_set = powernv_led_set_fault; + powernv_led->cdev.brightness_get = powernv_led_get_fault; + break; + default: /* Unsupported LED type */ + kfree(powernv_led); + return -EINVAL; + } + + if (!powernv_led->cdev.name) { + dev_err(&pdev->dev, + "%s: Memory allocation failed for classdev name\n", + __func__); + kfree(powernv_led); + return -ENOMEM; + } + + powernv_led->cdev.brightness = LED_OFF; + powernv_led->cdev.max_brightness = LED_FULL; + powernv_led->cdev.flags = LED_CORE_SUSPENDRESUME; + + mutex_init(&powernv_led->lock); + INIT_WORK(&powernv_led->work_led, powernv_deferred_led_set); + + /* Register the classdev */ + rc = led_classdev_register(&pdev->dev, &powernv_led->cdev); + if (rc) { + dev_err(&pdev->dev, "%s: Classdev registration failed for %s\n", + __func__, powernv_led->cdev.name); + kfree(powernv_led->cdev.name); + kfree(powernv_led); + } else { + list_add_tail(&powernv_led->link, &powernv_led_list); + dev_dbg(&pdev->dev, + "Classdev registration successful for %s\n", + powernv_led->cdev.name); + } + return rc; +} + +/* Platform driver probe */ +static int powernv_led_probe(struct platform_device *pdev) +{ + int rc = 0; + struct device_node *led_node, *np; + + led_node = of_find_node_by_path("/ibm,opal/led"); + if (!led_node) { + dev_err(&pdev->dev, + "%s: LED parent device node not found\n", __func__); + return -EINVAL; + } + + for_each_child_of_node(led_node, np) { + if (has_led_type(np, LED_TYPE_ATTENTION)) + rc = power_led_classdev(pdev, np, + OPAL_SLOT_LED_TYPE_ATTN); + + if (has_led_type(np, LED_TYPE_IDENTIFY)) + rc = power_led_classdev(pdev, np, + OPAL_SLOT_LED_TYPE_ID); + + if (has_led_type(np, LED_TYPE_FAULT)) + rc = power_led_classdev(pdev, np, + OPAL_SLOT_LED_TYPE_FAULT); + } + return rc; +} + +/* Platform driver remove */ +static int powernv_led_remove(struct platform_device *pdev) +{ + struct powernv_led_data *powernv_led; + + /* Disable LED operation */ + led_disabled = true; + + dev_dbg(&pdev->dev, + "%s: Unregister all classdev structures\n", __func__); + list_for_each_entry(powernv_led, &powernv_led_list, link) + led_classdev_unregister(&powernv_led->cdev); + + dev_dbg(&pdev->dev, + "%s: Wait for all work tasks to finish\n", __func__); + list_for_each_entry(powernv_led, &powernv_led_list, link) + flush_work(&powernv_led->work_led); + + while (!list_empty(&powernv_led_list)) { + powernv_led = list_first_entry(&powernv_led_list, + struct powernv_led_data, link); + list_del(&powernv_led->link); + kfree(powernv_led); + } + + dev_info(&pdev->dev, "PowerNV led module unregistered\n"); + return 0; +} + +/* Platform driver property match */ +static const struct of_device_id powernv_led_match[] = { + { + .compatible = "ibm,opal-v3-led", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, powernv_led_match); + +static struct platform_driver powernv_led_driver = { + .probe = powernv_led_probe, + .remove = powernv_led_remove, + .driver = { + .name = "powernv-led-driver", + .owner = THIS_MODULE, + .of_match_table = powernv_led_match, + }, +}; + +module_platform_driver(powernv_led_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PowerNV LED driver"); +MODULE_AUTHOR("Vasant Hegde ");