From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [RFC,v2,04/15] usb:cdns3: Driver initialization code. From: Roger Quadros Message-Id: <5BF7E5E8.3090406@ti.com> Date: Fri, 23 Nov 2018 13:35:04 +0200 To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, adouglas@cadence.com, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, pjez@cadence.com, kurahul@cadence.com List-ID: T24gMTgvMTEvMTggMTI6MDksIFBhd2VsIExhc3pjemFrIHdyb3RlOgo+IFBhdGNoIGFkZHMgY29y ZS5jIGFuZCBjb3JlLmggZmlsZSB0aGF0IGltcGxlbWVudHMgaW5pdGlhbGl6YXRpb24KPiBvZiBw bGF0Zm9ybSBkcml2ZXIgYW5kIGFkZHMgZnVuY3Rpb24gcmVzcG9uc2libGUgZm9yIHNlbGVjdGlu ZywKPiBzd2l0Y2hpbmcgYW5kIHJ1bm5pbmcgYXBwcm9wcmlhdGUgRGV2aWNlL0hvc3QgbW9kZS4K PiAKPiBTaWduZWQtb2ZmLWJ5OiBQYXdlbCBMYXN6Y3phayA8cGF3ZWxsQGNhZGVuY2UuY29tPgo+ IC0tLQo+ICBkcml2ZXJzL3VzYi9jZG5zMy9NYWtlZmlsZSB8ICAgMiArCj4gIGRyaXZlcnMvdXNi L2NkbnMzL2NvcmUuYyAgIHwgNDEzICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysKPiAgZHJpdmVycy91c2IvY2RuczMvY29yZS5oICAgfCAxMDAgKysrKysrKysrCj4gIDMgZmls ZXMgY2hhbmdlZCwgNTE1IGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl cnMvdXNiL2NkbnMzL2NvcmUuYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvY2Ru czMvY29yZS5oCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL2NkbnMzL01ha2VmaWxlIGIv ZHJpdmVycy91c2IvY2RuczMvTWFrZWZpbGUKPiBpbmRleCBkY2RkNjIwMDNjNmEuLjAyZDI1YjIz YzVkMyAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9jZG5zMy9NYWtlZmlsZQo+ICsrKyBiL2Ry aXZlcnMvdXNiL2NkbnMzL01ha2VmaWxlCj4gQEAgLTEsMyArMSw1IEBACj4gK29iai0kKENPTkZJ R19VU0JfQ0ROUzMpCQkJKz0gY2RuczMubwo+ICBvYmotJChDT05GSUdfVVNCX0NETlMzX1BDSV9X UkFQKQkrPSBjZG5zMy1wY2kubwo+ICAKPiArY2RuczMteQkJCQkJOj0gY29yZS5vCj4gIGNkbnMz LXBjaS15CQkgCQk6PSBjZG5zMy1wY2ktd3JhcC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNi L2NkbnMzL2NvcmUuYyBiL2RyaXZlcnMvdXNiL2NkbnMzL2NvcmUuYwo+IG5ldyBmaWxlIG1vZGUg MTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi5mOTA1NWQ0ZGE2N2YKPiAtLS0gL2Rldi9udWxs Cj4gKysrIGIvZHJpdmVycy91c2IvY2RuczMvY29yZS5jCj4gQEAgLTAsMCArMSw0MTMgQEAKPiAr Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKPiArLyoKPiArICogQ2FkZW5jZSBV U0JTUyBEUkQgRHJpdmVyLgo+ICsgKgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTggQ2FkZW5jZS4K PiArICoKPiArICogQXV0aG9yOiBQZXRlciBDaGVuIDxwZXRlci5jaGVuQG54cC5jb20+Cj4gKyAq ICAgICAgICAgUGF3ZWwgTGFzemN6YWsgPHBhd2VsbEBjYWRlbmNlLmNvbT4KPiArICovCj4gKwo+ ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4K PiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv aW50ZXJydXB0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+ICsjaW5jbHVkZSA8bGludXgv cG1fcnVudGltZS5oPgo+ICsKPiArI2luY2x1ZGUgImdhZGdldC5oIgo+ICsjaW5jbHVkZSAiY29y ZS5oIgo+ICsKPiArc3RhdGljIGlubGluZSBzdHJ1Y3QgY2RuczNfcm9sZV9kcml2ZXIgKmNkbnMz X2dldF9jdXJyZW50X3JvbGVfZHJpdmVyKHN0cnVjdCBjZG5zMyAqY2RucykKPiArewo+ICsJV0FS Tl9PTihjZG5zLT5yb2xlID49IENETlMzX1JPTEVfRU5EIHx8ICFjZG5zLT5yb2xlc1tjZG5zLT5y b2xlXSk7Cj4gKwlyZXR1cm4gY2Rucy0+cm9sZXNbY2Rucy0+cm9sZV07Cj4gK30KPiArCj4gK3N0 YXRpYyBpbmxpbmUgaW50IGNkbnMzX3JvbGVfc3RhcnQoc3RydWN0IGNkbnMzICpjZG5zLCBlbnVt IGNkbnMzX3JvbGVzIHJvbGUpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKHJvbGUgPj0g Q0ROUzNfUk9MRV9FTkQpCgpXQVJOX09OKCk/Cgo+ICsJCXJldHVybiAwOwo+ICsKPiArCWlmICgh Y2Rucy0+cm9sZXNbcm9sZV0pCj4gKwkJcmV0dXJuIC1FTlhJTzsKPiArCj4gKwltdXRleF9sb2Nr KCZjZG5zLT5tdXRleCk7Cj4gKwljZG5zLT5yb2xlID0gcm9sZTsKPiArCXJldCA9IGNkbnMtPnJv bGVzW3JvbGVdLT5zdGFydChjZG5zKTsKPiArCW11dGV4X3VubG9jaygmY2Rucy0+bXV0ZXgpOwo+ ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSB2b2lkIGNkbnMzX3JvbGVf c3RvcChzdHJ1Y3QgY2RuczMgKmNkbnMpCj4gK3sKPiArCWVudW0gY2RuczNfcm9sZXMgcm9sZSA9 IGNkbnMtPnJvbGU7Cj4gKwo+ICsJaWYgKHJvbGUgPT0gQ0ROUzNfUk9MRV9FTkQpCgpXQVJOX09O KHJvbGUgPj0gQ05EUzNfUk9MRV9FTkQpID8KCj4gKwkJcmV0dXJuOwo+ICsKPiArCW11dGV4X2xv Y2soJmNkbnMtPm11dGV4KTsKPiArCWNkbnMtPnJvbGVzW3JvbGVdLT5zdG9wKGNkbnMpOwo+ICsJ Y2Rucy0+cm9sZSA9IENETlMzX1JPTEVfRU5EOwoKV2h5IGNoYW5nZSB0aGUgcm9sZSBoZXJlPyBZ b3UgYXJlIGp1c3Qgc3RvcHBpbmcgdGhlIHJvbGUgbm90IGNoYW5naW5nIGl0LgpJIHRoaW5rIGNk bnMtPnJvbGUgc2hvdWxkIHJlbWFpbiB1bmNoYW5nZWQsIHNvIHdlIGNhbiBjYWxsIGNkbnMzX3Jv bGVfc3RhcnQoKQppZiByZXF1aXJlZCB3aXRob3V0IGVycm9yLgoKPiArCW11dGV4X3VubG9jaygm Y2Rucy0+bXV0ZXgpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgZW51bSBjZG5zM19yb2xlcyBjZG5zM19n ZXRfcm9sZShzdHJ1Y3QgY2RuczMgKmNkbnMpCj4gK3sKPiArCWlmIChjZG5zLT5yb2xlc1tDRE5T M19ST0xFX0hPU1RdICYmIGNkbnMtPnJvbGVzW0NETlMzX1JPTEVfR0FER0VUXSkgewo+ICsJCS8v VE9ETzogaW1wbGVtZW50cyBzZWxlY3RpbmcgZGV2aWNlL2hvc3QgbW9kZQo+ICsJCXJldHVybiBD RE5TM19ST0xFX0hPU1Q7Cj4gKwl9Cj4gKwlyZXR1cm4gY2Rucy0+cm9sZXNbQ0ROUzNfUk9MRV9I T1NUXQo+ICsJCT8gQ0ROUzNfUk9MRV9IT1NUCj4gKwkJOiBDRE5TM19ST0xFX0dBREdFVDsKCldo eSBub3QganVzdAoJcmV0dXJuIGNkbnMtPnJvbGU7CgpJJ20gd29uZGVyaW5nIGlmIHdlIHJlYWxs eSBuZWVkIHRoaXMgZnVuY3Rpb24uCj4gK30KCj4gKwo+ICsvKioKPiArICogY2RuczNfY29yZV9p bml0X3JvbGUgLSBpbml0aWFsaXplIHJvbGUgb2Ygb3BlcmF0aW9uCj4gKyAqIEBjZG5zOiBQb2lu dGVyIHRvIGNkbnMzIHN0cnVjdHVyZQo+ICsgKgo+ICsgKiBSZXR1cm5zIDAgb24gc3VjY2VzcyBv dGhlcndpc2UgbmVnYXRpdmUgZXJybm8KPiArICovCj4gK3N0YXRpYyBpbnQgY2RuczNfY29yZV9p bml0X3JvbGUoc3RydWN0IGNkbnMzICpjZG5zKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYg PSBjZG5zLT5kZXY7Cj4gKwllbnVtIHVzYl9kcl9tb2RlIGRyX21vZGU7Cj4gKwo+ICsJZHJfbW9k ZSA9IHVzYl9nZXRfZHJfbW9kZShkZXYpOwo+ICsJY2Rucy0+cm9sZSA9IENETlMzX1JPTEVfRU5E Owo+ICsKPiArCS8qCj4gKwkgKiBJZiBkcml2ZXIgY2FuJ3QgcmVhZCBtb2RlIGJ5IG1lYW5zIG9m IHVzYl9nZXRfZHJfbWRvZSBmdW5jdGlvbiB0aGVuCj4gKwkgKiBjaG9vc2VzIG1vZGUgYWNjb3Jk aW5nIHdpdGggS2VybmVsIGNvbmZpZ3VyYXRpb24uIFRoaXMgc2V0dGluZwo+ICsJICogY2FuIGJl IHJlc3RyaWN0ZWQgbGF0ZXIgZGVwZW5kaW5nIG9uIHN0cmFwIHBpbiBjb25maWd1cmF0aW9uLgo+ ICsJICovCj4gKwlpZiAoZHJfbW9kZSA9PSBVU0JfRFJfTU9ERV9VTktOT1dOKSB7Cj4gKwkJaWYg KElTX0VOQUJMRUQoQ09ORklHX1VTQl9DRE5TM19IT1NUKSAmJgo+ICsJCSAgICBJU19FTkFCTEVE KENPTkZJR19VU0JfQ0ROUzNfR0FER0VUKSkKPiArCQkJZHJfbW9kZSA9IFVTQl9EUl9NT0RFX09U RzsKPiArCQllbHNlIGlmIChJU19FTkFCTEVEKENPTkZJR19VU0JfQ0ROUzNfSE9TVCkpCj4gKwkJ CWRyX21vZGUgPSBVU0JfRFJfTU9ERV9IT1NUOwo+ICsJCWVsc2UgaWYgKElTX0VOQUJMRUQoQ09O RklHX1VTQl9DRE5TM19HQURHRVQpKQo+ICsJCQlkcl9tb2RlID0gVVNCX0RSX01PREVfUEVSSVBI RVJBTDsKPiArCX0KPiArCj4gKwlpZiAoZHJfbW9kZSA9PSBVU0JfRFJfTU9ERV9PVEcgfHwgZHJf bW9kZSA9PSBVU0JfRFJfTU9ERV9IT1NUKSB7Cj4gKwkJLy9UT0RPOiBpbXBsZW1lbnRzIGhvc3Qg aW5pdGlhbGl6YXRpb24KCgkJLyogVE9ETzogQWRkIGhvc3Qgcm9sZSAqLyA/Cgo+ICsJfQo+ICsK PiArCWlmIChkcl9tb2RlID09IFVTQl9EUl9NT0RFX09URyB8fCBkcl9tb2RlID09IFVTQl9EUl9N T0RFX1BFUklQSEVSQUwpIHsKPiArCQkvL1RPRE86IGltcGxlbWVudHMgZGV2aWNlIGluaXRpYWxp emF0aW9uCgoJCS8qIFRPRE86IEFkZCBkZXZpY2Ugcm9sZSAqLyA/Cgo+ICsJfQo+ICsKPiArCWlm ICghY2Rucy0+cm9sZXNbQ0ROUzNfUk9MRV9IT1NUXSAmJiAhY2Rucy0+cm9sZXNbQ0ROUzNfUk9M RV9HQURHRVRdKSB7Cj4gKwkJZGV2X2VycihkZXYsICJubyBzdXBwb3J0ZWQgcm9sZXNcbiIpOwo+ ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsKPiArCWNkbnMtPmRyX21vZGUgPSBkcl9tb2Rl Owo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gKy8qKgo+ICsgKiBjZG5zM19pcnEgLSBpbnRlcnJ1 cHQgaGFuZGxlciBmb3IgY2RuczMgY29yZSBkZXZpY2UKPiArICoKPiArICogQGlycTogaXJxIG51 bWJlciBmb3IgY2RuczMgY29yZSBkZXZpY2UKPiArICogQGRhdGE6IHN0cnVjdHVyZSBvZiBjZG5z Mwo+ICsgKgo+ICsgKiBSZXR1cm5zIElSUV9IQU5ETEVEIG9yIElSUV9OT05FCj4gKyAqLwo+ICtz dGF0aWMgaXJxcmV0dXJuX3QgY2RuczNfaXJxKGludCBpcnEsIHZvaWQgKmRhdGEpCj4gK3sKPiAr CXN0cnVjdCBjZG5zMyAqY2RucyA9IGRhdGE7Cj4gKwlpcnFyZXR1cm5fdCByZXQgPSBJUlFfTk9O RTsKPiArCj4gKwkvKiBIYW5kbGUgZGV2aWNlL2hvc3QgaW50ZXJydXB0ICovCj4gKwlpZiAoY2Ru cy0+cm9sZSAhPSBDRE5TM19ST0xFX0VORCkKCklzIGl0IGJlY2F1c2Ugb2YgdGhpcyB0aGF0IHlv dSBuZWVkIHRvIHNldCByb2xlIHRvIEVORCBhdCByb2xlX3N0b3A/CkkgdGhpbmsgaXQgaXMgYmV0 dGVyIHRvIGFkZCBhIHN0YXRlIHZhcmlhYmxlIHRvIHN0cnVjdCBjZG5zM19yb2xlX2RyaXZlciwg c28gd2UgY2FuCmNoZWNrIGlmIGl0IGlzIGFjdGl2ZSBvciBzdG9wcGVkLgoKZS5nLgoJaWYgKGNk bnMzX2dldF9jdXJyZW50X3JvbGVfZHJpdmVyKGNkbnMpLT5zdGF0ZSA9PSBDRE5TM19ST0xFX1NU QVRFX0FDVElWRSkKCj4gKwkJcmV0ID0gY2RuczNfZ2V0X2N1cnJlbnRfcm9sZV9kcml2ZXIoY2Ru cyktPmlycShjZG5zKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCBjZG5zM19yZW1vdmVfcm9sZXMoc3RydWN0IGNkbnMzICpjZG5zKQoKU2hvdWxkIHRoaXMgYmUg Y2FsbGVkIGNkbnMzX2V4aXRfcm9sZXMoKSB0byBiZSBvcHBvc2l0ZSBvZiBjZG5zM19pbml0X3Jv bGVzKCk/Cgo+ICt7Cj4gKwkvL1RPRE86IGltcGxlbWVudHMgdGhpcyBmdW5jdGlvbgo+ICt9Cgo+ ICsKPiArc3RhdGljIGludCBjZG5zM19kb19yb2xlX3N3aXRjaChzdHJ1Y3QgY2RuczMgKmNkbnMs IGVudW0gY2RuczNfcm9sZXMgcm9sZSkKPiArewo+ICsJZW51bSBjZG5zM19yb2xlcyBjdXJyZW50 X3JvbGU7Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwljdXJyZW50X3JvbGUgPSBjZG5zLT5yb2xl Owo+ICsKPiArCWlmIChyb2xlID09IENETlMzX1JPTEVfRU5EKQo+ICsJCXJldHVybiAwOwoKcm9s ZSA9PSBFTkQgbG9va3MgbGlrZSBlcnJvciBzdGF0ZS4gYW5kIGl0IHNob3VsZCBuZXZlciBoYXBw ZW4uCldBUk4gaGVyZT8KCj4gKwo+ICsJZGV2X2RiZyhjZG5zLT5kZXYsICJTd2l0Y2hpbmcgcm9s ZSIpOwo+ICsKCkRvbid0IHlvdSBoYXZlIHRvIHN0b3AgdGhlIHByZXZpb3VzIHJvbGUgYmVmb3Jl IHN0YXJ0aW5nIHRoZSBuZXcgcm9sZT8KCj4gKwlyZXQgPSBjZG5zM19yb2xlX3N0YXJ0KGNkbnMs IHJvbGUpOwo+ICsJaWYgKHJldCkgewo+ICsJCS8qIEJhY2sgdG8gY3VycmVudCByb2xlICovCj4g KwkJZGV2X2VycihjZG5zLT5kZXYsICJzZXQgJWQgaGFzIGZhaWxlZCwgYmFjayB0byAlZFxuIiwK PiArCQkJcm9sZSwgY3VycmVudF9yb2xlKTsKPiArCQlyZXQgPSBjZG5zM19yb2xlX3N0YXJ0KGNk bnMsIGN1cnJlbnRfcm9sZSk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAr LyoqCj4gKyAqIGNkbnMzX3JvbGVfc3dpdGNoIC0gd29yayBxdWV1ZSBoYW5kbGVyIGZvciByb2xl IHN3aXRjaAo+ICsgKgo+ICsgKiBAd29yazogd29yayBxdWV1ZSBpdGVtIHN0cnVjdHVyZQo+ICsg Kgo+ICsgKiBIYW5kbGVzIGJlbG93IGV2ZW50czoKPiArICogLSBSb2xlIHN3aXRjaCBmb3IgZHVh bC1yb2xlIGRldmljZXMKPiArICogLSBDRE5TM19ST0xFX0dBREdFVCA8LS0+IENETlMzX1JPTEVf RU5EIGZvciBwZXJpcGhlcmFsLW9ubHkgZGV2aWNlcwo+ICsgKi8KPiArc3RhdGljIHZvaWQgY2Ru czNfcm9sZV9zd2l0Y2goc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQo+ICt7Cj4gKwllbnVtIGNk bnMzX3JvbGVzIHJvbGUgPSBDRE5TM19ST0xFX0VORDsKPiArCXN0cnVjdCBjZG5zMyAqY2RuczsK PiArCWJvb2wgZGV2aWNlLCBob3N0Owo+ICsKPiArCWNkbnMgPSBjb250YWluZXJfb2Yod29yaywg c3RydWN0IGNkbnMzLCByb2xlX3N3aXRjaF93cSk7Cj4gKwo+ICsJLy9UT0RPOiBpbXBsZW1lbnRz IHRoaXMgZnVuY3Rpb25zLgo+ICsJLy9ob3N0ID0gY2RuczNfaXNfaG9zdChjZG5zKTsKPiArCS8v ZGV2aWNlID0gY2RuczNfaXNfZGV2aWNlKGNkbnMpOwo+ICsJaG9zdCA9IDE7Cj4gKwlkZXZpY2Ug PSAwOwo+ICsKPiArCWlmIChob3N0KQo+ICsJCXJvbGUgPSBDRE5TM19ST0xFX0hPU1Q7Cj4gKwll bHNlIGlmIChkZXZpY2UpCj4gKwkJcm9sZSA9IENETlMzX1JPTEVfR0FER0VUOwo+ICsKPiArCWlm IChjZG5zLT5kZXNpcmVkX2RyX21vZGUgPT0gY2Rucy0+Y3VycmVudF9kcl9tb2RlICYmCj4gKwkg ICAgY2Rucy0+cm9sZSA9PSByb2xlKQo+ICsJCXJldHVybjsKPiArCgpJIHRoaW5rIGFsbCB0aGUg YmVsb3cgY29kZSBjYW4gYmUgbW92ZWQgdG8gY2RuczNfZG9fcm9sZV9zd2l0Y2goKS4KCj4gKwlw bV9ydW50aW1lX2dldF9zeW5jKGNkbnMtPmRldik7Cj4gKwljZG5zM19yb2xlX3N0b3AoY2Rucyk7 Cj4gKwo+ICsJaWYgKGhvc3QpIHsKPiArCQlpZiAoY2Rucy0+cm9sZXNbQ0ROUzNfUk9MRV9IT1NU XSkKPiArCQkJY2RuczNfZG9fcm9sZV9zd2l0Y2goY2RucywgQ0ROUzNfUk9MRV9IT1NUKTsKPiAr CQlwbV9ydW50aW1lX3B1dF9zeW5jKGNkbnMtPmRldik7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsK PiArCWlmIChkZXZpY2UpCj4gKwkJY2RuczNfZG9fcm9sZV9zd2l0Y2goY2RucywgQ0ROUzNfUk9M RV9HQURHRVQpOwo+ICsJZWxzZQo+ICsJCWNkbnMzX2RvX3JvbGVfc3dpdGNoKGNkbnMsIENETlMz X1JPTEVfRU5EKTsKPiArCj4gKwlwbV9ydW50aW1lX3B1dF9zeW5jKGNkbnMtPmRldik7Cj4gK30K PiArCj4gKy8qKgo+ICsgKiBjZG5zM19wcm9iZSAtIHByb2JlIGZvciBjZG5zMyBjb3JlIGRldmlj ZQo+ICsgKiBAcGRldjogUG9pbnRlciB0byBjZG5zMyBjb3JlIHBsYXRmb3JtIGRldmljZQo+ICsg Kgo+ICsgKiBSZXR1cm5zIDAgb24gc3VjY2VzcyBvdGhlcndpc2UgbmVnYXRpdmUgZXJybm8KPiAr ICovCj4gK3N0YXRpYyBpbnQgY2RuczNfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRl dikKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPiArCXN0cnVjdCBy ZXNvdXJjZQkqcmVzOwo+ICsJc3RydWN0IGNkbnMzICpjZG5zOwo+ICsJdm9pZCBfX2lvbWVtICpy ZWdzOwo+ICsJaW50IHJldDsKPiArCj4gKwljZG5zID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9m KCpjZG5zKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWNkbnMpCj4gKwkJcmV0dXJuIC1FTk9NRU07 Cj4gKwo+ICsJY2Rucy0+ZGV2ID0gZGV2Owo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBk ZXYsIGNkbnMpOwo+ICsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShwZGV2LCBJT1JF U09VUkNFX0lSUSwgMCk7Cj4gKwlpZiAoIXJlcykgewo+ICsJCWRldl9lcnIoZGV2LCAibWlzc2lu ZyBJUlFcbiIpOwo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsJY2Rucy0+aXJxID0gcmVz LT5zdGFydDsKPiArCj4gKwkvKgo+ICsJICogUmVxdWVzdCBtZW1vcnkgcmVnaW9uCj4gKwkgKiBy ZWdpb24tMDogeEhDSQo+ICsJICogcmVnaW9uLTE6IFBlcmlwaGVyYWwKPiArCSAqIHJlZ2lvbi0y OiBPVEcgcmVnaXN0ZXJzCj4gKwkgKi8KClRoZSBtZW1vcnkgcmVnaW9uIG9yZGVyIGlzIGRpZmZl cmVudCBmcm9tIHRoZSBkdC1iaW5kaW5nLgpUaGVyZSBpdCBpcyBPVEcsIGhvc3QoeGhjaSksIGRl dmljZSAocGVyaXBoZXJhbCkuCgo+ICsJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYs IElPUkVTT1VSQ0VfTUVNLCAwKTsKPiArCXJlZ3MgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoZGV2 LCByZXMpOwo+ICsKPiArCWlmIChJU19FUlIocmVncykpCj4gKwkJcmV0dXJuIFBUUl9FUlIocmVn cyk7Cj4gKwljZG5zLT54aGNpX3JlZ3MgPSByZWdzOwo+ICsJY2Rucy0+eGhjaV9yZXMgPSByZXM7 Cj4gKwo+ICsJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVN LCAxKTsKPiArCXJlZ3MgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoZGV2LCByZXMpOwo+ICsJaWYg KElTX0VSUihyZWdzKSkKPiArCQlyZXR1cm4gUFRSX0VSUihyZWdzKTsKPiArCWNkbnMtPmRldl9y ZWdzCT0gcmVnczsKPiArCj4gKwlyZXMgPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9S RVNPVVJDRV9NRU0sIDIpOwo+ICsJcmVncyA9IGRldm1faW9yZW1hcF9yZXNvdXJjZShkZXYsIHJl cyk7Cj4gKwlpZiAoSVNfRVJSKHJlZ3MpKQo+ICsJCXJldHVybiBQVFJfRVJSKHJlZ3MpOwo+ICsJ Y2Rucy0+b3RnX3JlZ3MgPSByZWdzOwo+ICsKPiArCW11dGV4X2luaXQoJmNkbnMtPm11dGV4KTsK PiArCj4gKwljZG5zLT5waHkgPSBkZXZtX3BoeV9nZXQoZGV2LCAiY2RuczMsdXNicGh5Iik7Cgoi Y2RuczMsdXNicGh5IiBpcyBub3QgZG9jdW1lbnRlZCBpbiBkdC1iaW5kaW5nLgoKPiArCWlmIChJ U19FUlIoY2Rucy0+cGh5KSkgewo+ICsJCWRldl9pbmZvKGRldiwgIm5vIGdlbmVyaWMgcGh5IGZv dW5kXG4iKTsKPiArCQljZG5zLT5waHkgPSBOVUxMOwo+ICsJCS8qCj4gKwkJICogZmFsbCB0aHJv dWdoIGhlcmUhCj4gKwkJICogaWYgbm8gZ2VuZXJpYyBwaHkgZm91bmQsIHBoeSBpbml0Cj4gKwkJ ICogc2hvdWxkIGJlIGRvbmUgdW5kZXIgYm9vdCEKPiArCQkgKi8KCk5vIHlvdSBzaG91bGRuJ3Qg ZmFsbCB0aHJvdWdoIGFsd2F5cyBpZiBpdCBpcyBhbiBlcnJvciBjb25kaXRpb24uClNvbWV0aGlu ZyBsaWtlIHRoaXMgc2hvdWxkIHdvcmsgYmV0dGVyLgoKICAgICAgICBpZiAoSVNfRVJSKGNuZHMt PnBoeSkpIHsKICAgICAgICAgICAgICAgIHJldCA9IFBUUl9FUlIoY2Rucy0+cGh5KTsKICAgICAg ICAgICAgICAgIGlmIChyZXQgPT0gLUVOT1NZUyB8fCByZXQgPT0gLUVOT0RFVikgewogICAgICAg ICAgICAgICAgICAgICAgICBjZG5zLT5waHkgPSBOVUxMOwogICAgICAgICAgICAgICAgfSBlbHNl IGlmIChyZXQgPT0gLUVQUk9CRV9ERUZFUikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1 cm4gcmV0OwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAg ZGV2X2VycihkZXYsICJubyBwaHkgZm91bmRcbiIpOwogICAgICAgICAgICAgICAgICAgICAgICBn b3RvIGVycjA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgfQoKU28gaWYgUEhZIHdhcyBwcm92 aWRlZCBpbiBEVCwgYW5kIFBIWSBzdXBwb3J0L2RyaXZlcnMgaXMgcHJlc2VudAphbmQgZXJyb3Ig Y29uZGl0aW9uIG1lYW5zIHNvbWV0aGluZyBpcyB3cm9uZyBhbmQgd2UgaGF2ZSB0byBlcnJvciBv dXQuCgo+ICsJfSBlbHNlIHsKPiArCQlwaHlfaW5pdChjZG5zLT5waHkpOwo+ICsJfQoKWW91IGNh biBkbyBwaHlfaW5pdCgpIG91dHNpZGUgdGhlIGVsc2UuCgo+ICsKPiArCXJldCA9IGNkbnMzX2Nv cmVfaW5pdF9yb2xlKGNkbnMpOwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIGVycjE7Cj4gKwo+ICsJ SU5JVF9XT1JLKCZjZG5zLT5yb2xlX3N3aXRjaF93cSwgY2RuczNfcm9sZV9zd2l0Y2gpOwo+ICsJ aWYgKHJldCkKPiArCQlnb3RvIGVycjI7Cj4gKwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIGVycjI7 Cj4gKwo+ICsJY2Rucy0+cm9sZSA9IGNkbnMzX2dldF9yb2xlKGNkbnMpOwoKSSB0aGluayB0aGlz IHNob3VsZCBtb3ZlIHRvIGNkbnMzX2NvcmVfaW5pdF9yb2xlKCkuCgo+ICsKPiArCXJldCA9IGRl dm1fcmVxdWVzdF9pcnEoZGV2LCBjZG5zLT5pcnEsIGNkbnMzX2lycSwgSVJRRl9TSEFSRUQsCj4g KwkJCSAgICAgICBkZXZfbmFtZShkZXYpLCBjZG5zKTsKPiArCj4gKwlpZiAocmV0KQo+ICsJCWdv dG8gZXJyMjsKCkhvdyBhYm91dCBtb3ZpbmcgcmVxdWVzdF9pcnEgdG8gYmVmb3JlIGNkc24zX2Nv cmVfaW5pdF9yb2xlKCk/CgpUaGVuIHlvdSBjYW4gbW92ZSBjZG5zM19yb2xlX3N0YXJ0KCkgYXMg d2VsbCB0byBjb3JlX2luaXRfcm9sZSgpLgoKPiArCj4gKwlyZXQgPSBjZG5zM19yb2xlX3N0YXJ0 KGNkbnMsIGNkbnMtPnJvbGUpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoZGV2LCAiY2Fu J3Qgc3RhcnQgJXMgcm9sZVxuIiwKPiArCQkJY2RuczNfZ2V0X2N1cnJlbnRfcm9sZV9kcml2ZXIo Y2RucyktPm5hbWUpOwo+ICsJCWdvdG8gZXJyMjsKPiArCX0KPiArCj4gKwlkZXZpY2Vfc2V0X3dh a2V1cF9jYXBhYmxlKGRldiwgdHJ1ZSk7Cj4gKwlwbV9ydW50aW1lX3NldF9hY3RpdmUoZGV2KTsK PiArCXBtX3J1bnRpbWVfZW5hYmxlKGRldik7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZSBjb250cm9s bGVyIG5lZWRzIGxlc3MgdGltZSBiZXR3ZWVuIGJ1cyBhbmQgY29udHJvbGxlciBzdXNwZW5kLAo+ ICsJICogYW5kIHdlIGFsc28gbmVlZHMgYSBzbWFsbCBkZWxheSB0byBhdm9pZCBmcmVxdWVudGx5 IGVudGVyaW5nIGxvdwo+ICsJICogcG93ZXIgbW9kZS4KPiArCSAqLwo+ICsJcG1fcnVudGltZV9z ZXRfYXV0b3N1c3BlbmRfZGVsYXkoZGV2LCAyMCk7Cj4gKwlwbV9ydW50aW1lX21hcmtfbGFzdF9i dXN5KGRldik7Cj4gKwlwbV9ydW50aW1lX3VzZV9hdXRvc3VzcGVuZChkZXYpOwo+ICsJZGV2X2Ri ZyhkZXYsICJDYWRlbmNlIFVTQjMgY29yZTogcHJvYmUgc3VjY2VlZFxuIik7Cj4gKwo+ICsJcmV0 dXJuIDA7Cj4gKwo+ICtlcnIyOgo+ICsJY2RuczNfcmVtb3ZlX3JvbGVzKGNkbnMpOwo+ICtlcnIx OgoKcGh5X2V4aXQoKSA/Cgo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyoqCj4gKyAqIGNk bnMzX3JlbW92ZSAtIHVuYmluZCBkcmQgZHJpdmVyIGFuZCBjbGVhbiB1cAo+ICsgKiBAcGRldjog UG9pbnRlciB0byBMaW51eCBwbGF0Zm9ybSBkZXZpY2UKPiArICoKPiArICogUmV0dXJucyAwIG9u IHN1Y2Nlc3Mgb3RoZXJ3aXNlIG5lZ2F0aXZlIGVycm5vCj4gKyAqLwo+ICtzdGF0aWMgaW50IGNk bnMzX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3Qg Y2RuczMgKmNkbnMgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPiArCj4gKwlwbV9ydW50 aW1lX2dldF9zeW5jKCZwZGV2LT5kZXYpOwo+ICsJcG1fcnVudGltZV9kaXNhYmxlKCZwZGV2LT5k ZXYpOwo+ICsJcG1fcnVudGltZV9wdXRfbm9pZGxlKCZwZGV2LT5kZXYpOwo+ICsJY2RuczNfcmVt b3ZlX3JvbGVzKGNkbnMpOwoKcGh5X2V4aXQoKSA/Cgo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4g Kwo+ICsjaWZkZWYgQ09ORklHX09GCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lk IG9mX2NkbnMzX21hdGNoW10gPSB7Cj4gKwl7IC5jb21wYXRpYmxlID0gImNkbnMsdXNiMyIgfSwK PiArCXsgfSwKPiArfTsKPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgb2ZfY2RuczNfbWF0Y2gp Owo+ICsjZW5kaWYKPiArCj4gKyNpZmRlZiBDT05GSUdfUE0KPiArCj4gKyNpZmRlZiBDT05GSUdf UE1fU0xFRVAKPiArc3RhdGljIGludCBjZG5zM19zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikK PiArewo+ICsJLy9UT0RPOiBpbXBsZW1lbnRzIHRoaXMgZnVuY3Rpb24KPiArCXJldHVybiAwOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNkbnMzX3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCj4g K3sKPiArCS8vVE9ETzogaW1wbGVtZW50cyB0aGlzIGZ1bmN0aW9uCj4gKwlyZXR1cm4gMDsKPiAr fQo+ICsjZW5kaWYgLyogQ09ORklHX1BNX1NMRUVQICovCj4gK3N0YXRpYyBpbnQgY2RuczNfcnVu dGltZV9zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewkvL1RPRE86IGltcGxlbWVudHMg dGhpcyBmdW5jdGlvbgo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2RuczNf cnVudGltZV9yZXN1bWUoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gKwkvL1RPRE86IGltcGxl bWVudHMgdGhpcyBmdW5jdGlvbgo+ICsJcmV0dXJuIDA7Cj4gK30KPiArI2VuZGlmIC8qIENPTkZJ R19QTSAqLwo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBkZXZfcG1fb3BzIGNkbnMzX3BtX29w cyA9IHsKPiArCVNFVF9TWVNURU1fU0xFRVBfUE1fT1BTKGNkbnMzX3N1c3BlbmQsIGNkbnMzX3Jl c3VtZSkKPiArCVNFVF9SVU5USU1FX1BNX09QUyhjZG5zM19ydW50aW1lX3N1c3BlbmQsIGNkbnMz X3J1bnRpbWVfcmVzdW1lLCBOVUxMKQo+ICt9Owo+ICsKPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9y bV9kcml2ZXIgY2RuczNfZHJpdmVyID0gewo+ICsJLnByb2JlCQk9IGNkbnMzX3Byb2JlLAo+ICsJ LnJlbW92ZQkJPSBjZG5zM19yZW1vdmUsCj4gKwkuZHJpdmVyCQk9IHsKPiArCQkubmFtZQk9ICJj ZG5zLXVzYjMiLAo+ICsJCS5vZl9tYXRjaF90YWJsZQk9IG9mX21hdGNoX3B0cihvZl9jZG5zM19t YXRjaCksCj4gKwkJLnBtCT0gJmNkbnMzX3BtX29wcywKPiArCX0sCj4gK307Cj4gKwo+ICtzdGF0 aWMgaW50IF9faW5pdCBjZG5zM19kcml2ZXJfcGxhdGZvcm1fcmVnaXN0ZXIodm9pZCkKPiArewo+ ICsJcmV0dXJuIHBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmY2RuczNfZHJpdmVyKTsKPiArfQo+ ICttb2R1bGVfaW5pdChjZG5zM19kcml2ZXJfcGxhdGZvcm1fcmVnaXN0ZXIpOwo+ICsKPiArc3Rh dGljIHZvaWQgX19leGl0IGNkbnMzX2RyaXZlcl9wbGF0Zm9ybV91bnJlZ2lzdGVyKHZvaWQpCj4g K3sKPiArCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZjZG5zM19kcml2ZXIpOwo+ICt9Cj4g K21vZHVsZV9leGl0KGNkbnMzX2RyaXZlcl9wbGF0Zm9ybV91bnJlZ2lzdGVyKTsKPiArCj4gK01P RFVMRV9BTElBUygicGxhdGZvcm06Y2RuczMiKTsKPiArTU9EVUxFX0FVVEhPUigiUGF3ZWwgTGFz emN6YWsgPHBhd2VsbEBjYWRlbmNlLmNvbT4iKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIp Owo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkNhZGVuY2UgVVNCMyBEUkQgQ29udHJvbGxlciBEcml2 ZXIiKTsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvY2RuczMvY29yZS5oIGIvZHJpdmVycy91 c2IvY2RuczMvY29yZS5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAw MDAuLjdjODIwNGZlNGQzZAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3VzYi9jZG5z My9jb3JlLmgKPiBAQCAtMCwwICsxLDEwMCBAQAo+ICsvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmll cjogR1BMLTIuMCAqLwo+ICsvKgo+ICsgKiBDYWRlbmNlIFVTQlNTIERSRCBEcml2ZXIuCj4gKyAq Cj4gKyAqIENvcHlyaWdodCAoQykgMjAxNyBOWFAKPiArICogQ29weXJpZ2h0IChDKSAyMDE4IENh ZGVuY2UuCj4gKyAqCj4gKyAqIEF1dGhvcnM6IFBldGVyIENoZW4gPHBldGVyLmNoZW5AbnhwLmNv bT4KPiArICogICAgICAgICAgUGF3ZWwgTGFzemN6YWsgPHBhd2VsbEBjYWRlbmNlLmNvbT4KPiAr ICovCj4gKyNpbmNsdWRlIDxsaW51eC91c2Ivb3RnLmg+Cj4gKwo+ICsjaWZuZGVmIF9fTElOVVhf Q0ROUzNfQ09SRV9ICj4gKyNkZWZpbmUgX19MSU5VWF9DRE5TM19DT1JFX0gKPiArCj4gK3N0cnVj dCBjZG5zMzsKPiArZW51bSBjZG5zM19yb2xlcyB7Cj4gKwlDRE5TM19ST0xFX0hPU1QgPSAwLAo+ ICsJQ0ROUzNfUk9MRV9HQURHRVQsCj4gKwlDRE5TM19ST0xFX0VORCwKPiArfTsKPiArCj4gKy8q Kgo+ICsgKiBzdHJ1Y3QgY2RuczNfcm9sZV9kcml2ZXIgLSBob3N0L2dhZGdldCByb2xlIGRyaXZl cgo+ICsgKiBAc3RhcnQ6IHN0YXJ0IHRoaXMgcm9sZQo+ICsgKiBAc3RvcDogc3RvcCB0aGlzIHJv bGUKPiArICogQHN1c3BlbmQ6IHN1c3BlbmQgY2FsbGJhY2sgZm9yIHRoaXMgcm9sZQo+ICsgKiBA cmVzdW1lOiByZXN1bWUgY2FsbGJhY2sgZm9yIHRoaXMgcm9sZQo+ICsgKiBAaXJxOiBpcnEgaGFu ZGxlciBmb3IgdGhpcyByb2xlCj4gKyAqIEBuYW1lOiByb2xlIG5hbWUgc3RyaW5nIChob3N0L2dh ZGdldCkKPiArICovCj4gK3N0cnVjdCBjZG5zM19yb2xlX2RyaXZlciB7Cj4gKwlpbnQgKCpzdGFy dCkoc3RydWN0IGNkbnMzICpjZG5zKTsKPiArCXZvaWQgKCpzdG9wKShzdHJ1Y3QgY2RuczMgKmNk bnMpOwo+ICsJaW50ICgqc3VzcGVuZCkoc3RydWN0IGNkbnMzICpjZG5zLCBib29sIGRvX3dha2V1 cCk7Cj4gKwlpbnQgKCpyZXN1bWUpKHN0cnVjdCBjZG5zMyAqY2RucywgYm9vbCBoaWJlcm5hdGVk KTsKPiArCWlycXJldHVybl90ICgqaXJxKShzdHJ1Y3QgY2RuczMgKmNkbnMpOwo+ICsJY29uc3Qg Y2hhciAqbmFtZTsKPiArfTsKPiArCj4gKyNkZWZpbmUgQ0ROUzNfTlVNX09GX0NMS1MJNQo+ICsv KioKPiArICogc3RydWN0IGNkbnMzIC0gUmVwcmVzZW50YXRpb24gb2YgQ2FkZW5jZSBVU0IzIERS RCBjb250cm9sbGVyLgo+ICsgKiBAZGV2OiBwb2ludGVyIHRvIENhZGVuY2UgZGV2aWNlIHN0cnVj dAo+ICsgKiBAeGhjaV9yZWdzOiBwb2ludGVyIHRvIGJhc2Ugb2YgeGhjaSByZWdpc3RlcnMKPiAr ICogQHhoY2lfcmVzOiB0aGUgcmVzb3VyY2UgZm9yIHhoY2kKPiArICogQGRldl9yZWdzOiBwb2lu dGVyIHRvIGJhc2Ugb2YgZGV2IHJlZ2lzdGVycwo+ICsgKiBAb3RnX3JlZ3M6IHBvaW50ZXIgdG8g YmFzZSBvZiBvdGcgcmVnaXN0ZXJzCj4gKyAqIEBpcnE6IGlycSBudW1iZXIgZm9yIGNvbnRyb2xs ZXIKPiArICogQHJvbGVzOiBhcnJheSBvZiBzdXBwb3J0ZWQgcm9sZXMgZm9yIHRoaXMgY29udHJv bGxlcgo+ICsgKiBAcm9sZTogY3VycmVudCByb2xlCj4gKyAqIEBob3N0X2RldjogdGhlIGNoaWxk IGhvc3QgZGV2aWNlIHBvaW50ZXIgZm9yIGNkbnMzIGNvcmUKPiArICogQGdhZGdldF9kZXY6IHRo ZSBjaGlsZCBnYWRnZXQgZGV2aWNlIHBvaW50ZXIgZm9yIGNkbnMzIGNvcmUKPiArICogQHVzYjog cGh5IGZvciB0aGlzIGNvbnRyb2xsZXIKPiArICogQHJvbGVfc3dpdGNoX3dxOiB3b3JrIHF1ZXVl IGl0ZW0gZm9yIHJvbGUgc3dpdGNoCj4gKyAqIEBpbl9scG06IHRoZSBjb250cm9sbGVyIGluIGxv dyBwb3dlciBtb2RlCj4gKyAqIEB3YWtldXBfaW50OiB0aGUgd2FrZXVwIGludGVycnVwdAo+ICsg KiBAbXV0ZXg6IHRoZSBtdXRleCBmb3IgY29uY3VycmVudCBjb2RlIGF0IGRyaXZlcgo+ICsgKiBA ZHJfbW9kZTogc3VwcG9ydGVkIG1vZGUgb2Ygb3BlcmF0aW9uIGl0IGNhbiBiZSBvbmx5IEhvc3Qs IG9ubHkgRGV2aWNlCj4gKyAqICAgICAgICAgICBvciBPVEcgbW9kZSB0aGF0IGFsbG93IHRvIHN3 aXRjaCBiZXR3ZWVuIERldmljZSBhbmQgSG9zdCBtb2RlLgo+ICsgKiAgICAgICAgICAgVGhpcyBm aWVsZCBiYXNlZCBvbiBoYXJkd2FyZSBjb25maWd1cmF0aW9uIGFuZCBjYW50J3QgYmUgY2hhbmdl ZC4KCkJ1dCBkcl9tb2RlIGNhbiBiZSBmb3JjZWQgaW4gZGV2aWNlLXRyZWUuIFNvIGl0IGlzbid0 IHJlYWxseSBvbmx5IGhhcmR3YXJlIGNvbmZpZ3VyYXRpb24uCgo+ICsgKiBAY3VycmVudF9kcl9y b2xlOiBjdXJyZW50IG1vZGUgb2Ygb3BlcmF0aW9uIHdoZW4gaW4gZHVhbC1yb2xlIG1vZGUKPiAr ICogQGRlc2lyZWRfZHJfcm9sZTogZGVzaXJlZCBtb2RlIG9mIG9wZXJhdGlvbiB3aGVuIGluIGR1 YWwtcm9sZSBtb2RlLgo+ICsgKiAgICAgICAgICAgVGhpcyB2YWx1ZSBjYW4gYmUgY2hhbmdlZCBk dXJpbmcgcnVudGltZS4KPiArICogICAgICAgICAgIEF2YWlsYWJsZSBvcHRpb25zIGRlcGVuZHMg b24gIGRyX21vZGU6Cj4gKyAqICAgICAgICAgICBkcl9tb2RlICAgICAgICAgICAgICAgICB8ICBk ZXNpcmVkX2RyX3JvbGUgYW5kIGN1cnJlbnRfZHJfcm9sZQo+ICsgKiAgICAgICAgICAgLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LQo+ICsgKiAgICAgICAgICAgVVNCX0RSX01PREVfSE9TVCAgICAgICAgfCBvbmx5IFVTQl9EUl9N T0RFX0hPU1QKPiArICogICAgICAgICAgIFVTQl9EUl9NT0RFX1BFUklQSEVSQUwgIHwgb25seSBV U0JfRFJfTU9ERV9QRVJJUEhFUkFMCj4gKyAqICAgICAgICAgICBVU0JfRFJfTU9ERV9PVEcgICAg ICAgICB8IG9ubHkgVVNCX0RSX01PREVfSE9TVAo+ICsgKiAgICAgICAgICAgVVNCX0RSX01PREVf T1RHICAgICAgICAgfCBvbmx5IFVTQl9EUl9NT0RFX1BFUklQSEVSQUwKPiArICogICAgICAgICAg IFVTQl9EUl9NT0RFX09URyAgICAgICAgIHwgVVNCX0RSX01PREVfT1RHCgpEbyB5b3UgbmVlZCB0 byB1cGRhdGUgdGhlIHJpZ2h0IGhhbmQgc2lkZSB0byByZWZsZWN0IFJPTEVzIGluc3RlYWQgb2Yg TU9ERT8KCj4gKyAqCj4gKyAqICAgICAgICAgICBEZXNpcmVkX2RyX3JvbGUgY2FuIGJlIGNoYW5n ZWQgYnkgbWVhbnMgb2YgZGVidWdmcy4KPiArICogQHJvb3Q6IGRlYnVnZnMgcm9vdCBmb2xkZXIg cG9pbnRlcgo+ICsgKi8KPiArc3RydWN0IGNkbnMzIHsKPiArCXN0cnVjdCBkZXZpY2UJCQkqZGV2 Owo+ICsJdm9pZCBfX2lvbWVtCQkJKnhoY2lfcmVnczsKPiArCXN0cnVjdCByZXNvdXJjZQkJCSp4 aGNpX3JlczsKPiArCXN0cnVjdCBjZG5zM191c2JfcmVncyBfX2lvbWVtCSpkZXZfcmVnczsKPiAr CXN0cnVjdCBjZG5zM19vdGdfcmVncwkJKm90Z19yZWdzOwo+ICsJaW50IGlycTsKPiArCXN0cnVj dCBjZG5zM19yb2xlX2RyaXZlcgkqcm9sZXNbQ0ROUzNfUk9MRV9FTkRdOwo+ICsJZW51bSBjZG5z M19yb2xlcwkJcm9sZTsKPiArCXN0cnVjdCBkZXZpY2UJCQkqaG9zdF9kZXY7Cj4gKwlzdHJ1Y3Qg ZGV2aWNlCQkJKmdhZGdldF9kZXY7Cj4gKwlzdHJ1Y3QgcGh5CQkJKnBoeTsKPiArCXN0cnVjdCB3 b3JrX3N0cnVjdAkJcm9sZV9zd2l0Y2hfd3E7Cj4gKwlpbnQJCQkJaW5fbHBtOjE7Cj4gKwlpbnQJ CQkJd2FrZXVwX2ludDoxOwo+ICsJLyogbXV0ZXh0IHVzZWQgaW4gd29ya3F1ZXVlKi8KPiArCXN0 cnVjdCBtdXRleAkJCW11dGV4Owo+ICsJZW51bSB1c2JfZHJfbW9kZQkJZHJfbW9kZTsKPiArCWVu dW0gdXNiX2RyX21vZGUJCWN1cnJlbnRfZHJfbW9kZTsKPiArCWVudW0gdXNiX2RyX21vZGUJCWRl c2lyZWRfZHJfbW9kZTsKPiArCXN0cnVjdCBkZW50cnkJCQkqcm9vdDsKPiArfTsKPiArCj4gKyNl bmRpZiAvKiBfX0xJTlVYX0NETlMzX0NPUkVfSCAqLwo+IAoKY2hlZXJzLAotcm9nZXIK From mboxrd@z Thu Jan 1 00:00:00 1970 From: Roger Quadros Subject: Re: [RFC PATCH v2 04/15] usb:cdns3: Driver initialization code. Date: Fri, 23 Nov 2018 13:35:04 +0200 Message-ID: <5BF7E5E8.3090406@ti.com> References: <1542535751-16079-1-git-send-email-pawell@cadence.com> <1542535751-16079-5-git-send-email-pawell@cadence.com> Mime-Version: 1.0 Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1542535751-16079-5-git-send-email-pawell@cadence.com> Sender: linux-kernel-owner@vger.kernel.org To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, adouglas@cadence.com, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, pjez@cadence.com, kurahul@cadence.com List-Id: devicetree@vger.kernel.org On 18/11/18 12:09, Pawel Laszczak wrote: > Patch adds core.c and core.h file that implements initialization > of platform driver and adds function responsible for selecting, > switching and running appropriate Device/Host mode. > > Signed-off-by: Pawel Laszczak > --- > drivers/usb/cdns3/Makefile | 2 + > drivers/usb/cdns3/core.c | 413 +++++++++++++++++++++++++++++++++++++ > drivers/usb/cdns3/core.h | 100 +++++++++ > 3 files changed, 515 insertions(+) > create mode 100644 drivers/usb/cdns3/core.c > create mode 100644 drivers/usb/cdns3/core.h > > diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile > index dcdd62003c6a..02d25b23c5d3 100644 > --- a/drivers/usb/cdns3/Makefile > +++ b/drivers/usb/cdns3/Makefile > @@ -1,3 +1,5 @@ > +obj-$(CONFIG_USB_CDNS3) += cdns3.o > obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci.o > > +cdns3-y := core.o > cdns3-pci-y := cdns3-pci-wrap.o > diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c > new file mode 100644 > index 000000000000..f9055d4da67f > --- /dev/null > +++ b/drivers/usb/cdns3/core.c > @@ -0,0 +1,413 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Cadence USBSS DRD Driver. > + * > + * Copyright (C) 2018 Cadence. > + * > + * Author: Peter Chen > + * Pawel Laszczak > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "gadget.h" > +#include "core.h" > + > +static inline struct cdns3_role_driver *cdns3_get_current_role_driver(struct cdns3 *cdns) > +{ > + WARN_ON(cdns->role >= CDNS3_ROLE_END || !cdns->roles[cdns->role]); > + return cdns->roles[cdns->role]; > +} > + > +static inline int cdns3_role_start(struct cdns3 *cdns, enum cdns3_roles role) > +{ > + int ret; > + > + if (role >= CDNS3_ROLE_END) WARN_ON()? > + return 0; > + > + if (!cdns->roles[role]) > + return -ENXIO; > + > + mutex_lock(&cdns->mutex); > + cdns->role = role; > + ret = cdns->roles[role]->start(cdns); > + mutex_unlock(&cdns->mutex); > + return ret; > +} > + > +static inline void cdns3_role_stop(struct cdns3 *cdns) > +{ > + enum cdns3_roles role = cdns->role; > + > + if (role == CDNS3_ROLE_END) WARN_ON(role >= CNDS3_ROLE_END) ? > + return; > + > + mutex_lock(&cdns->mutex); > + cdns->roles[role]->stop(cdns); > + cdns->role = CDNS3_ROLE_END; Why change the role here? You are just stopping the role not changing it. I think cdns->role should remain unchanged, so we can call cdns3_role_start() if required without error. > + mutex_unlock(&cdns->mutex); > +} > + > +static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns) > +{ > + if (cdns->roles[CDNS3_ROLE_HOST] && cdns->roles[CDNS3_ROLE_GADGET]) { > + //TODO: implements selecting device/host mode > + return CDNS3_ROLE_HOST; > + } > + return cdns->roles[CDNS3_ROLE_HOST] > + ? CDNS3_ROLE_HOST > + : CDNS3_ROLE_GADGET; Why not just return cdns->role; I'm wondering if we really need this function. > +} > + > +/** > + * cdns3_core_init_role - initialize role of operation > + * @cdns: Pointer to cdns3 structure > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_core_init_role(struct cdns3 *cdns) > +{ > + struct device *dev = cdns->dev; > + enum usb_dr_mode dr_mode; > + > + dr_mode = usb_get_dr_mode(dev); > + cdns->role = CDNS3_ROLE_END; > + > + /* > + * If driver can't read mode by means of usb_get_dr_mdoe function then > + * chooses mode according with Kernel configuration. This setting > + * can be restricted later depending on strap pin configuration. > + */ > + if (dr_mode == USB_DR_MODE_UNKNOWN) { > + if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) && > + IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) > + dr_mode = USB_DR_MODE_OTG; > + else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST)) > + dr_mode = USB_DR_MODE_HOST; > + else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) > + dr_mode = USB_DR_MODE_PERIPHERAL; > + } > + > + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { > + //TODO: implements host initialization /* TODO: Add host role */ ? > + } > + > + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { > + //TODO: implements device initialization /* TODO: Add device role */ ? > + } > + > + if (!cdns->roles[CDNS3_ROLE_HOST] && !cdns->roles[CDNS3_ROLE_GADGET]) { > + dev_err(dev, "no supported roles\n"); > + return -ENODEV; > + } > + > + cdns->dr_mode = dr_mode; > + return 0; > +} > + > +/** > + * cdns3_irq - interrupt handler for cdns3 core device > + * > + * @irq: irq number for cdns3 core device > + * @data: structure of cdns3 > + * > + * Returns IRQ_HANDLED or IRQ_NONE > + */ > +static irqreturn_t cdns3_irq(int irq, void *data) > +{ > + struct cdns3 *cdns = data; > + irqreturn_t ret = IRQ_NONE; > + > + /* Handle device/host interrupt */ > + if (cdns->role != CDNS3_ROLE_END) Is it because of this that you need to set role to END at role_stop? I think it is better to add a state variable to struct cdns3_role_driver, so we can check if it is active or stopped. e.g. if (cdns3_get_current_role_driver(cdns)->state == CDNS3_ROLE_STATE_ACTIVE) > + ret = cdns3_get_current_role_driver(cdns)->irq(cdns); > + > + return ret; > +} > + > +static void cdns3_remove_roles(struct cdns3 *cdns) Should this be called cdns3_exit_roles() to be opposite of cdns3_init_roles()? > +{ > + //TODO: implements this function > +} > + > +static int cdns3_do_role_switch(struct cdns3 *cdns, enum cdns3_roles role) > +{ > + enum cdns3_roles current_role; > + int ret = 0; > + > + current_role = cdns->role; > + > + if (role == CDNS3_ROLE_END) > + return 0; role == END looks like error state. and it should never happen. WARN here? > + > + dev_dbg(cdns->dev, "Switching role"); > + Don't you have to stop the previous role before starting the new role? > + ret = cdns3_role_start(cdns, role); > + if (ret) { > + /* Back to current role */ > + dev_err(cdns->dev, "set %d has failed, back to %d\n", > + role, current_role); > + ret = cdns3_role_start(cdns, current_role); > + } > + > + return ret; > +} > + > +/** > + * cdns3_role_switch - work queue handler for role switch > + * > + * @work: work queue item structure > + * > + * Handles below events: > + * - Role switch for dual-role devices > + * - CDNS3_ROLE_GADGET <--> CDNS3_ROLE_END for peripheral-only devices > + */ > +static void cdns3_role_switch(struct work_struct *work) > +{ > + enum cdns3_roles role = CDNS3_ROLE_END; > + struct cdns3 *cdns; > + bool device, host; > + > + cdns = container_of(work, struct cdns3, role_switch_wq); > + > + //TODO: implements this functions. > + //host = cdns3_is_host(cdns); > + //device = cdns3_is_device(cdns); > + host = 1; > + device = 0; > + > + if (host) > + role = CDNS3_ROLE_HOST; > + else if (device) > + role = CDNS3_ROLE_GADGET; > + > + if (cdns->desired_dr_mode == cdns->current_dr_mode && > + cdns->role == role) > + return; > + I think all the below code can be moved to cdns3_do_role_switch(). > + pm_runtime_get_sync(cdns->dev); > + cdns3_role_stop(cdns); > + > + if (host) { > + if (cdns->roles[CDNS3_ROLE_HOST]) > + cdns3_do_role_switch(cdns, CDNS3_ROLE_HOST); > + pm_runtime_put_sync(cdns->dev); > + return; > + } > + > + if (device) > + cdns3_do_role_switch(cdns, CDNS3_ROLE_GADGET); > + else > + cdns3_do_role_switch(cdns, CDNS3_ROLE_END); > + > + pm_runtime_put_sync(cdns->dev); > +} > + > +/** > + * cdns3_probe - probe for cdns3 core device > + * @pdev: Pointer to cdns3 core platform device > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct resource *res; > + struct cdns3 *cdns; > + void __iomem *regs; > + int ret; > + > + cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); > + if (!cdns) > + return -ENOMEM; > + > + cdns->dev = dev; > + > + platform_set_drvdata(pdev, cdns); > + > + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); > + if (!res) { > + dev_err(dev, "missing IRQ\n"); > + return -ENODEV; > + } > + cdns->irq = res->start; > + > + /* > + * Request memory region > + * region-0: xHCI > + * region-1: Peripheral > + * region-2: OTG registers > + */ The memory region order is different from the dt-binding. There it is OTG, host(xhci), device (peripheral). > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + regs = devm_ioremap_resource(dev, res); > + > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->xhci_regs = regs; > + cdns->xhci_res = res; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->dev_regs = regs; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); > + regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->otg_regs = regs; > + > + mutex_init(&cdns->mutex); > + > + cdns->phy = devm_phy_get(dev, "cdns3,usbphy"); "cdns3,usbphy" is not documented in dt-binding. > + if (IS_ERR(cdns->phy)) { > + dev_info(dev, "no generic phy found\n"); > + cdns->phy = NULL; > + /* > + * fall through here! > + * if no generic phy found, phy init > + * should be done under boot! > + */ No you shouldn't fall through always if it is an error condition. Something like this should work better. if (IS_ERR(cnds->phy)) { ret = PTR_ERR(cdns->phy); if (ret == -ENOSYS || ret == -ENODEV) { cdns->phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no phy found\n"); goto err0; } } So if PHY was provided in DT, and PHY support/drivers is present and error condition means something is wrong and we have to error out. > + } else { > + phy_init(cdns->phy); > + } You can do phy_init() outside the else. > + > + ret = cdns3_core_init_role(cdns); > + if (ret) > + goto err1; > + > + INIT_WORK(&cdns->role_switch_wq, cdns3_role_switch); > + if (ret) > + goto err2; > + > + if (ret) > + goto err2; > + > + cdns->role = cdns3_get_role(cdns); I think this should move to cdns3_core_init_role(). > + > + ret = devm_request_irq(dev, cdns->irq, cdns3_irq, IRQF_SHARED, > + dev_name(dev), cdns); > + > + if (ret) > + goto err2; How about moving request_irq to before cdsn3_core_init_role()? Then you can move cdns3_role_start() as well to core_init_role(). > + > + ret = cdns3_role_start(cdns, cdns->role); > + if (ret) { > + dev_err(dev, "can't start %s role\n", > + cdns3_get_current_role_driver(cdns)->name); > + goto err2; > + } > + > + device_set_wakeup_capable(dev, true); > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > + > + /* > + * The controller needs less time between bus and controller suspend, > + * and we also needs a small delay to avoid frequently entering low > + * power mode. > + */ > + pm_runtime_set_autosuspend_delay(dev, 20); > + pm_runtime_mark_last_busy(dev); > + pm_runtime_use_autosuspend(dev); > + dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); > + > + return 0; > + > +err2: > + cdns3_remove_roles(cdns); > +err1: phy_exit() ? > + return ret; > +} > + > +/** > + * cdns3_remove - unbind drd driver and clean up > + * @pdev: Pointer to Linux platform device > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_remove(struct platform_device *pdev) > +{ > + struct cdns3 *cdns = platform_get_drvdata(pdev); > + > + pm_runtime_get_sync(&pdev->dev); > + pm_runtime_disable(&pdev->dev); > + pm_runtime_put_noidle(&pdev->dev); > + cdns3_remove_roles(cdns); phy_exit() ? > + > + return 0; > +} > + > +#ifdef CONFIG_OF > +static const struct of_device_id of_cdns3_match[] = { > + { .compatible = "cdns,usb3" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, of_cdns3_match); > +#endif > + > +#ifdef CONFIG_PM > + > +#ifdef CONFIG_PM_SLEEP > +static int cdns3_suspend(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > + > +static int cdns3_resume(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > +#endif /* CONFIG_PM_SLEEP */ > +static int cdns3_runtime_suspend(struct device *dev) > +{ //TODO: implements this function > + return 0; > +} > + > +static int cdns3_runtime_resume(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > +#endif /* CONFIG_PM */ > + > +static const struct dev_pm_ops cdns3_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume) > + SET_RUNTIME_PM_OPS(cdns3_runtime_suspend, cdns3_runtime_resume, NULL) > +}; > + > +static struct platform_driver cdns3_driver = { > + .probe = cdns3_probe, > + .remove = cdns3_remove, > + .driver = { > + .name = "cdns-usb3", > + .of_match_table = of_match_ptr(of_cdns3_match), > + .pm = &cdns3_pm_ops, > + }, > +}; > + > +static int __init cdns3_driver_platform_register(void) > +{ > + return platform_driver_register(&cdns3_driver); > +} > +module_init(cdns3_driver_platform_register); > + > +static void __exit cdns3_driver_platform_unregister(void) > +{ > + platform_driver_unregister(&cdns3_driver); > +} > +module_exit(cdns3_driver_platform_unregister); > + > +MODULE_ALIAS("platform:cdns3"); > +MODULE_AUTHOR("Pawel Laszczak "); > +MODULE_LICENSE("GPL v2"); > +MODULE_DESCRIPTION("Cadence USB3 DRD Controller Driver"); > diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h > new file mode 100644 > index 000000000000..7c8204fe4d3d > --- /dev/null > +++ b/drivers/usb/cdns3/core.h > @@ -0,0 +1,100 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Cadence USBSS DRD Driver. > + * > + * Copyright (C) 2017 NXP > + * Copyright (C) 2018 Cadence. > + * > + * Authors: Peter Chen > + * Pawel Laszczak > + */ > +#include > + > +#ifndef __LINUX_CDNS3_CORE_H > +#define __LINUX_CDNS3_CORE_H > + > +struct cdns3; > +enum cdns3_roles { > + CDNS3_ROLE_HOST = 0, > + CDNS3_ROLE_GADGET, > + CDNS3_ROLE_END, > +}; > + > +/** > + * struct cdns3_role_driver - host/gadget role driver > + * @start: start this role > + * @stop: stop this role > + * @suspend: suspend callback for this role > + * @resume: resume callback for this role > + * @irq: irq handler for this role > + * @name: role name string (host/gadget) > + */ > +struct cdns3_role_driver { > + int (*start)(struct cdns3 *cdns); > + void (*stop)(struct cdns3 *cdns); > + int (*suspend)(struct cdns3 *cdns, bool do_wakeup); > + int (*resume)(struct cdns3 *cdns, bool hibernated); > + irqreturn_t (*irq)(struct cdns3 *cdns); > + const char *name; > +}; > + > +#define CDNS3_NUM_OF_CLKS 5 > +/** > + * struct cdns3 - Representation of Cadence USB3 DRD controller. > + * @dev: pointer to Cadence device struct > + * @xhci_regs: pointer to base of xhci registers > + * @xhci_res: the resource for xhci > + * @dev_regs: pointer to base of dev registers > + * @otg_regs: pointer to base of otg registers > + * @irq: irq number for controller > + * @roles: array of supported roles for this controller > + * @role: current role > + * @host_dev: the child host device pointer for cdns3 core > + * @gadget_dev: the child gadget device pointer for cdns3 core > + * @usb: phy for this controller > + * @role_switch_wq: work queue item for role switch > + * @in_lpm: the controller in low power mode > + * @wakeup_int: the wakeup interrupt > + * @mutex: the mutex for concurrent code at driver > + * @dr_mode: supported mode of operation it can be only Host, only Device > + * or OTG mode that allow to switch between Device and Host mode. > + * This field based on hardware configuration and cant't be changed. But dr_mode can be forced in device-tree. So it isn't really only hardware configuration. > + * @current_dr_role: current mode of operation when in dual-role mode > + * @desired_dr_role: desired mode of operation when in dual-role mode. > + * This value can be changed during runtime. > + * Available options depends on dr_mode: > + * dr_mode | desired_dr_role and current_dr_role > + * ---------------------------------------------------------------- > + * USB_DR_MODE_HOST | only USB_DR_MODE_HOST > + * USB_DR_MODE_PERIPHERAL | only USB_DR_MODE_PERIPHERAL > + * USB_DR_MODE_OTG | only USB_DR_MODE_HOST > + * USB_DR_MODE_OTG | only USB_DR_MODE_PERIPHERAL > + * USB_DR_MODE_OTG | USB_DR_MODE_OTG Do you need to update the right hand side to reflect ROLEs instead of MODE? > + * > + * Desired_dr_role can be changed by means of debugfs. > + * @root: debugfs root folder pointer > + */ > +struct cdns3 { > + struct device *dev; > + void __iomem *xhci_regs; > + struct resource *xhci_res; > + struct cdns3_usb_regs __iomem *dev_regs; > + struct cdns3_otg_regs *otg_regs; > + int irq; > + struct cdns3_role_driver *roles[CDNS3_ROLE_END]; > + enum cdns3_roles role; > + struct device *host_dev; > + struct device *gadget_dev; > + struct phy *phy; > + struct work_struct role_switch_wq; > + int in_lpm:1; > + int wakeup_int:1; > + /* mutext used in workqueue*/ > + struct mutex mutex; > + enum usb_dr_mode dr_mode; > + enum usb_dr_mode current_dr_mode; > + enum usb_dr_mode desired_dr_mode; > + struct dentry *root; > +}; > + > +#endif /* __LINUX_CDNS3_CORE_H */ > cheers, -roger -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.6 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10FBBC43441 for ; Fri, 23 Nov 2018 11:35:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A0E6F20864 for ; Fri, 23 Nov 2018 11:35:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="SeMvF44U" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A0E6F20864 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=ti.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2503828AbeKWWTK (ORCPT ); Fri, 23 Nov 2018 17:19:10 -0500 Received: from fllv0015.ext.ti.com ([198.47.19.141]:45794 "EHLO fllv0015.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729929AbeKWWTK (ORCPT ); Fri, 23 Nov 2018 17:19:10 -0500 Received: from lelv0266.itg.ti.com ([10.180.67.225]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id wANBZ97L005046; Fri, 23 Nov 2018 05:35:09 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1542972909; bh=Mxfgl5vFtDetWATJkozv6ygXJFBzsLX6OpXiKiIXRqo=; h=Subject:To:References:CC:From:Date:In-Reply-To; b=SeMvF44Uha//JzG5uR42RlvQQw+YG7ct+l+7XCt1l7pyvzVHuO8fuOFO1cKJKixLM 3SI6G4GJwEHyBFHfxYAbzzDNoXNWMrTwfRtKaeJaQQPpuoFeJj9UtGxR7cXvG3RU8Y zAVTEFTDmc8Hrk40qgB+iudySa0MlaX4CMLZX9uM= Received: from DLEE100.ent.ti.com (dlee100.ent.ti.com [157.170.170.30]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id wANBZ9NT118504 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 23 Nov 2018 05:35:09 -0600 Received: from DLEE106.ent.ti.com (157.170.170.36) by DLEE100.ent.ti.com (157.170.170.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Fri, 23 Nov 2018 05:35:07 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE106.ent.ti.com (157.170.170.36) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Fri, 23 Nov 2018 05:35:07 -0600 Received: from [192.168.2.6] (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id wANBZ4TR019775; Fri, 23 Nov 2018 05:35:05 -0600 Subject: Re: [RFC PATCH v2 04/15] usb:cdns3: Driver initialization code. To: Pawel Laszczak , References: <1542535751-16079-1-git-send-email-pawell@cadence.com> <1542535751-16079-5-git-send-email-pawell@cadence.com> CC: , , , , , , , , , , From: Roger Quadros Message-ID: <5BF7E5E8.3090406@ti.com> Date: Fri, 23 Nov 2018 13:35:04 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <1542535751-16079-5-git-send-email-pawell@cadence.com> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 18/11/18 12:09, Pawel Laszczak wrote: > Patch adds core.c and core.h file that implements initialization > of platform driver and adds function responsible for selecting, > switching and running appropriate Device/Host mode. > > Signed-off-by: Pawel Laszczak > --- > drivers/usb/cdns3/Makefile | 2 + > drivers/usb/cdns3/core.c | 413 +++++++++++++++++++++++++++++++++++++ > drivers/usb/cdns3/core.h | 100 +++++++++ > 3 files changed, 515 insertions(+) > create mode 100644 drivers/usb/cdns3/core.c > create mode 100644 drivers/usb/cdns3/core.h > > diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile > index dcdd62003c6a..02d25b23c5d3 100644 > --- a/drivers/usb/cdns3/Makefile > +++ b/drivers/usb/cdns3/Makefile > @@ -1,3 +1,5 @@ > +obj-$(CONFIG_USB_CDNS3) += cdns3.o > obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci.o > > +cdns3-y := core.o > cdns3-pci-y := cdns3-pci-wrap.o > diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c > new file mode 100644 > index 000000000000..f9055d4da67f > --- /dev/null > +++ b/drivers/usb/cdns3/core.c > @@ -0,0 +1,413 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Cadence USBSS DRD Driver. > + * > + * Copyright (C) 2018 Cadence. > + * > + * Author: Peter Chen > + * Pawel Laszczak > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "gadget.h" > +#include "core.h" > + > +static inline struct cdns3_role_driver *cdns3_get_current_role_driver(struct cdns3 *cdns) > +{ > + WARN_ON(cdns->role >= CDNS3_ROLE_END || !cdns->roles[cdns->role]); > + return cdns->roles[cdns->role]; > +} > + > +static inline int cdns3_role_start(struct cdns3 *cdns, enum cdns3_roles role) > +{ > + int ret; > + > + if (role >= CDNS3_ROLE_END) WARN_ON()? > + return 0; > + > + if (!cdns->roles[role]) > + return -ENXIO; > + > + mutex_lock(&cdns->mutex); > + cdns->role = role; > + ret = cdns->roles[role]->start(cdns); > + mutex_unlock(&cdns->mutex); > + return ret; > +} > + > +static inline void cdns3_role_stop(struct cdns3 *cdns) > +{ > + enum cdns3_roles role = cdns->role; > + > + if (role == CDNS3_ROLE_END) WARN_ON(role >= CNDS3_ROLE_END) ? > + return; > + > + mutex_lock(&cdns->mutex); > + cdns->roles[role]->stop(cdns); > + cdns->role = CDNS3_ROLE_END; Why change the role here? You are just stopping the role not changing it. I think cdns->role should remain unchanged, so we can call cdns3_role_start() if required without error. > + mutex_unlock(&cdns->mutex); > +} > + > +static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns) > +{ > + if (cdns->roles[CDNS3_ROLE_HOST] && cdns->roles[CDNS3_ROLE_GADGET]) { > + //TODO: implements selecting device/host mode > + return CDNS3_ROLE_HOST; > + } > + return cdns->roles[CDNS3_ROLE_HOST] > + ? CDNS3_ROLE_HOST > + : CDNS3_ROLE_GADGET; Why not just return cdns->role; I'm wondering if we really need this function. > +} > + > +/** > + * cdns3_core_init_role - initialize role of operation > + * @cdns: Pointer to cdns3 structure > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_core_init_role(struct cdns3 *cdns) > +{ > + struct device *dev = cdns->dev; > + enum usb_dr_mode dr_mode; > + > + dr_mode = usb_get_dr_mode(dev); > + cdns->role = CDNS3_ROLE_END; > + > + /* > + * If driver can't read mode by means of usb_get_dr_mdoe function then > + * chooses mode according with Kernel configuration. This setting > + * can be restricted later depending on strap pin configuration. > + */ > + if (dr_mode == USB_DR_MODE_UNKNOWN) { > + if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) && > + IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) > + dr_mode = USB_DR_MODE_OTG; > + else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST)) > + dr_mode = USB_DR_MODE_HOST; > + else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET)) > + dr_mode = USB_DR_MODE_PERIPHERAL; > + } > + > + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { > + //TODO: implements host initialization /* TODO: Add host role */ ? > + } > + > + if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { > + //TODO: implements device initialization /* TODO: Add device role */ ? > + } > + > + if (!cdns->roles[CDNS3_ROLE_HOST] && !cdns->roles[CDNS3_ROLE_GADGET]) { > + dev_err(dev, "no supported roles\n"); > + return -ENODEV; > + } > + > + cdns->dr_mode = dr_mode; > + return 0; > +} > + > +/** > + * cdns3_irq - interrupt handler for cdns3 core device > + * > + * @irq: irq number for cdns3 core device > + * @data: structure of cdns3 > + * > + * Returns IRQ_HANDLED or IRQ_NONE > + */ > +static irqreturn_t cdns3_irq(int irq, void *data) > +{ > + struct cdns3 *cdns = data; > + irqreturn_t ret = IRQ_NONE; > + > + /* Handle device/host interrupt */ > + if (cdns->role != CDNS3_ROLE_END) Is it because of this that you need to set role to END at role_stop? I think it is better to add a state variable to struct cdns3_role_driver, so we can check if it is active or stopped. e.g. if (cdns3_get_current_role_driver(cdns)->state == CDNS3_ROLE_STATE_ACTIVE) > + ret = cdns3_get_current_role_driver(cdns)->irq(cdns); > + > + return ret; > +} > + > +static void cdns3_remove_roles(struct cdns3 *cdns) Should this be called cdns3_exit_roles() to be opposite of cdns3_init_roles()? > +{ > + //TODO: implements this function > +} > + > +static int cdns3_do_role_switch(struct cdns3 *cdns, enum cdns3_roles role) > +{ > + enum cdns3_roles current_role; > + int ret = 0; > + > + current_role = cdns->role; > + > + if (role == CDNS3_ROLE_END) > + return 0; role == END looks like error state. and it should never happen. WARN here? > + > + dev_dbg(cdns->dev, "Switching role"); > + Don't you have to stop the previous role before starting the new role? > + ret = cdns3_role_start(cdns, role); > + if (ret) { > + /* Back to current role */ > + dev_err(cdns->dev, "set %d has failed, back to %d\n", > + role, current_role); > + ret = cdns3_role_start(cdns, current_role); > + } > + > + return ret; > +} > + > +/** > + * cdns3_role_switch - work queue handler for role switch > + * > + * @work: work queue item structure > + * > + * Handles below events: > + * - Role switch for dual-role devices > + * - CDNS3_ROLE_GADGET <--> CDNS3_ROLE_END for peripheral-only devices > + */ > +static void cdns3_role_switch(struct work_struct *work) > +{ > + enum cdns3_roles role = CDNS3_ROLE_END; > + struct cdns3 *cdns; > + bool device, host; > + > + cdns = container_of(work, struct cdns3, role_switch_wq); > + > + //TODO: implements this functions. > + //host = cdns3_is_host(cdns); > + //device = cdns3_is_device(cdns); > + host = 1; > + device = 0; > + > + if (host) > + role = CDNS3_ROLE_HOST; > + else if (device) > + role = CDNS3_ROLE_GADGET; > + > + if (cdns->desired_dr_mode == cdns->current_dr_mode && > + cdns->role == role) > + return; > + I think all the below code can be moved to cdns3_do_role_switch(). > + pm_runtime_get_sync(cdns->dev); > + cdns3_role_stop(cdns); > + > + if (host) { > + if (cdns->roles[CDNS3_ROLE_HOST]) > + cdns3_do_role_switch(cdns, CDNS3_ROLE_HOST); > + pm_runtime_put_sync(cdns->dev); > + return; > + } > + > + if (device) > + cdns3_do_role_switch(cdns, CDNS3_ROLE_GADGET); > + else > + cdns3_do_role_switch(cdns, CDNS3_ROLE_END); > + > + pm_runtime_put_sync(cdns->dev); > +} > + > +/** > + * cdns3_probe - probe for cdns3 core device > + * @pdev: Pointer to cdns3 core platform device > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct resource *res; > + struct cdns3 *cdns; > + void __iomem *regs; > + int ret; > + > + cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); > + if (!cdns) > + return -ENOMEM; > + > + cdns->dev = dev; > + > + platform_set_drvdata(pdev, cdns); > + > + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); > + if (!res) { > + dev_err(dev, "missing IRQ\n"); > + return -ENODEV; > + } > + cdns->irq = res->start; > + > + /* > + * Request memory region > + * region-0: xHCI > + * region-1: Peripheral > + * region-2: OTG registers > + */ The memory region order is different from the dt-binding. There it is OTG, host(xhci), device (peripheral). > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + regs = devm_ioremap_resource(dev, res); > + > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->xhci_regs = regs; > + cdns->xhci_res = res; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > + regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->dev_regs = regs; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); > + regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->otg_regs = regs; > + > + mutex_init(&cdns->mutex); > + > + cdns->phy = devm_phy_get(dev, "cdns3,usbphy"); "cdns3,usbphy" is not documented in dt-binding. > + if (IS_ERR(cdns->phy)) { > + dev_info(dev, "no generic phy found\n"); > + cdns->phy = NULL; > + /* > + * fall through here! > + * if no generic phy found, phy init > + * should be done under boot! > + */ No you shouldn't fall through always if it is an error condition. Something like this should work better. if (IS_ERR(cnds->phy)) { ret = PTR_ERR(cdns->phy); if (ret == -ENOSYS || ret == -ENODEV) { cdns->phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no phy found\n"); goto err0; } } So if PHY was provided in DT, and PHY support/drivers is present and error condition means something is wrong and we have to error out. > + } else { > + phy_init(cdns->phy); > + } You can do phy_init() outside the else. > + > + ret = cdns3_core_init_role(cdns); > + if (ret) > + goto err1; > + > + INIT_WORK(&cdns->role_switch_wq, cdns3_role_switch); > + if (ret) > + goto err2; > + > + if (ret) > + goto err2; > + > + cdns->role = cdns3_get_role(cdns); I think this should move to cdns3_core_init_role(). > + > + ret = devm_request_irq(dev, cdns->irq, cdns3_irq, IRQF_SHARED, > + dev_name(dev), cdns); > + > + if (ret) > + goto err2; How about moving request_irq to before cdsn3_core_init_role()? Then you can move cdns3_role_start() as well to core_init_role(). > + > + ret = cdns3_role_start(cdns, cdns->role); > + if (ret) { > + dev_err(dev, "can't start %s role\n", > + cdns3_get_current_role_driver(cdns)->name); > + goto err2; > + } > + > + device_set_wakeup_capable(dev, true); > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > + > + /* > + * The controller needs less time between bus and controller suspend, > + * and we also needs a small delay to avoid frequently entering low > + * power mode. > + */ > + pm_runtime_set_autosuspend_delay(dev, 20); > + pm_runtime_mark_last_busy(dev); > + pm_runtime_use_autosuspend(dev); > + dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); > + > + return 0; > + > +err2: > + cdns3_remove_roles(cdns); > +err1: phy_exit() ? > + return ret; > +} > + > +/** > + * cdns3_remove - unbind drd driver and clean up > + * @pdev: Pointer to Linux platform device > + * > + * Returns 0 on success otherwise negative errno > + */ > +static int cdns3_remove(struct platform_device *pdev) > +{ > + struct cdns3 *cdns = platform_get_drvdata(pdev); > + > + pm_runtime_get_sync(&pdev->dev); > + pm_runtime_disable(&pdev->dev); > + pm_runtime_put_noidle(&pdev->dev); > + cdns3_remove_roles(cdns); phy_exit() ? > + > + return 0; > +} > + > +#ifdef CONFIG_OF > +static const struct of_device_id of_cdns3_match[] = { > + { .compatible = "cdns,usb3" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, of_cdns3_match); > +#endif > + > +#ifdef CONFIG_PM > + > +#ifdef CONFIG_PM_SLEEP > +static int cdns3_suspend(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > + > +static int cdns3_resume(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > +#endif /* CONFIG_PM_SLEEP */ > +static int cdns3_runtime_suspend(struct device *dev) > +{ //TODO: implements this function > + return 0; > +} > + > +static int cdns3_runtime_resume(struct device *dev) > +{ > + //TODO: implements this function > + return 0; > +} > +#endif /* CONFIG_PM */ > + > +static const struct dev_pm_ops cdns3_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume) > + SET_RUNTIME_PM_OPS(cdns3_runtime_suspend, cdns3_runtime_resume, NULL) > +}; > + > +static struct platform_driver cdns3_driver = { > + .probe = cdns3_probe, > + .remove = cdns3_remove, > + .driver = { > + .name = "cdns-usb3", > + .of_match_table = of_match_ptr(of_cdns3_match), > + .pm = &cdns3_pm_ops, > + }, > +}; > + > +static int __init cdns3_driver_platform_register(void) > +{ > + return platform_driver_register(&cdns3_driver); > +} > +module_init(cdns3_driver_platform_register); > + > +static void __exit cdns3_driver_platform_unregister(void) > +{ > + platform_driver_unregister(&cdns3_driver); > +} > +module_exit(cdns3_driver_platform_unregister); > + > +MODULE_ALIAS("platform:cdns3"); > +MODULE_AUTHOR("Pawel Laszczak "); > +MODULE_LICENSE("GPL v2"); > +MODULE_DESCRIPTION("Cadence USB3 DRD Controller Driver"); > diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h > new file mode 100644 > index 000000000000..7c8204fe4d3d > --- /dev/null > +++ b/drivers/usb/cdns3/core.h > @@ -0,0 +1,100 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Cadence USBSS DRD Driver. > + * > + * Copyright (C) 2017 NXP > + * Copyright (C) 2018 Cadence. > + * > + * Authors: Peter Chen > + * Pawel Laszczak > + */ > +#include > + > +#ifndef __LINUX_CDNS3_CORE_H > +#define __LINUX_CDNS3_CORE_H > + > +struct cdns3; > +enum cdns3_roles { > + CDNS3_ROLE_HOST = 0, > + CDNS3_ROLE_GADGET, > + CDNS3_ROLE_END, > +}; > + > +/** > + * struct cdns3_role_driver - host/gadget role driver > + * @start: start this role > + * @stop: stop this role > + * @suspend: suspend callback for this role > + * @resume: resume callback for this role > + * @irq: irq handler for this role > + * @name: role name string (host/gadget) > + */ > +struct cdns3_role_driver { > + int (*start)(struct cdns3 *cdns); > + void (*stop)(struct cdns3 *cdns); > + int (*suspend)(struct cdns3 *cdns, bool do_wakeup); > + int (*resume)(struct cdns3 *cdns, bool hibernated); > + irqreturn_t (*irq)(struct cdns3 *cdns); > + const char *name; > +}; > + > +#define CDNS3_NUM_OF_CLKS 5 > +/** > + * struct cdns3 - Representation of Cadence USB3 DRD controller. > + * @dev: pointer to Cadence device struct > + * @xhci_regs: pointer to base of xhci registers > + * @xhci_res: the resource for xhci > + * @dev_regs: pointer to base of dev registers > + * @otg_regs: pointer to base of otg registers > + * @irq: irq number for controller > + * @roles: array of supported roles for this controller > + * @role: current role > + * @host_dev: the child host device pointer for cdns3 core > + * @gadget_dev: the child gadget device pointer for cdns3 core > + * @usb: phy for this controller > + * @role_switch_wq: work queue item for role switch > + * @in_lpm: the controller in low power mode > + * @wakeup_int: the wakeup interrupt > + * @mutex: the mutex for concurrent code at driver > + * @dr_mode: supported mode of operation it can be only Host, only Device > + * or OTG mode that allow to switch between Device and Host mode. > + * This field based on hardware configuration and cant't be changed. But dr_mode can be forced in device-tree. So it isn't really only hardware configuration. > + * @current_dr_role: current mode of operation when in dual-role mode > + * @desired_dr_role: desired mode of operation when in dual-role mode. > + * This value can be changed during runtime. > + * Available options depends on dr_mode: > + * dr_mode | desired_dr_role and current_dr_role > + * ---------------------------------------------------------------- > + * USB_DR_MODE_HOST | only USB_DR_MODE_HOST > + * USB_DR_MODE_PERIPHERAL | only USB_DR_MODE_PERIPHERAL > + * USB_DR_MODE_OTG | only USB_DR_MODE_HOST > + * USB_DR_MODE_OTG | only USB_DR_MODE_PERIPHERAL > + * USB_DR_MODE_OTG | USB_DR_MODE_OTG Do you need to update the right hand side to reflect ROLEs instead of MODE? > + * > + * Desired_dr_role can be changed by means of debugfs. > + * @root: debugfs root folder pointer > + */ > +struct cdns3 { > + struct device *dev; > + void __iomem *xhci_regs; > + struct resource *xhci_res; > + struct cdns3_usb_regs __iomem *dev_regs; > + struct cdns3_otg_regs *otg_regs; > + int irq; > + struct cdns3_role_driver *roles[CDNS3_ROLE_END]; > + enum cdns3_roles role; > + struct device *host_dev; > + struct device *gadget_dev; > + struct phy *phy; > + struct work_struct role_switch_wq; > + int in_lpm:1; > + int wakeup_int:1; > + /* mutext used in workqueue*/ > + struct mutex mutex; > + enum usb_dr_mode dr_mode; > + enum usb_dr_mode current_dr_mode; > + enum usb_dr_mode desired_dr_mode; > + struct dentry *root; > +}; > + > +#endif /* __LINUX_CDNS3_CORE_H */ > cheers, -roger -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki