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: [v1,2/2] usb:cdns3 Add Cadence USB3 DRD Driver From: Felipe Balbi Message-Id: <87h8fkmfar.fsf@linux.intel.com> Date: Tue, 11 Dec 2018 14:14:04 +0200 To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, rogerq@ti.com, 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: SGksCgpQYXdlbCBMYXN6Y3phayA8cGF3ZWxsQGNhZGVuY2UuY29tPiB3cml0ZXM6Cj4gK3N0YXRp YyBpbnQgY2RuczNfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJ c3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPiArCXN0cnVjdCByZXNvdXJjZQkqcmVz Owo+ICsJc3RydWN0IGNkbnMzICpjZG5zOwo+ICsJdm9pZCBfX2lvbWVtICpyZWdzOwo+ICsJaW50 IHJldDsKPiArCj4gKwljZG5zID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCpjZG5zKSwgR0ZQ X0tFUk5FTCk7Cj4gKwlpZiAoIWNkbnMpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJY2Ru cy0+ZGV2ID0gZGV2Owo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIGNkbnMpOwo+ ICsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShwZGV2LCBJT1JFU09VUkNFX0lSUSwg MCk7Cj4gKwlpZiAoIXJlcykgewo+ICsJCWRldl9lcnIoZGV2LCAibWlzc2luZyBJUlFcbiIpOwo+ ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsJY2Rucy0+aXJxID0gcmVzLT5zdGFydDsKPiAr Cj4gKwljZG5zLT54aGNpX3Jlc1swXSA9ICpyZXM7Cj4gKwo+ICsJLyoKPiArCSAqIFJlcXVlc3Qg bWVtb3J5IHJlZ2lvbgo+ICsJICogcmVnaW9uLTA6IHhIQ0kKPiArCSAqIHJlZ2lvbi0xOiBQZXJp cGhlcmFsCj4gKwkgKiByZWdpb24tMjogT1RHIHJlZ2lzdGVycwo+ICsJICovCj4gKwlyZXMgPSBw bGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOwo+ICsJY2Rucy0+ eGhjaV9yZXNbMV0gPSAqcmVzOwo+ICsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShw ZGV2LCBJT1JFU09VUkNFX01FTSwgMSk7Cj4gKwlyZWdzID0gZGV2bV9pb3JlbWFwX3Jlc291cmNl KGRldiwgcmVzKTsKPiArCWlmIChJU19FUlIocmVncykpCj4gKwkJcmV0dXJuIFBUUl9FUlIocmVn cyk7Cj4gKwljZG5zLT5kZXZfcmVncwk9IHJlZ3M7Cj4gKwo+ICsJcmVzID0gcGxhdGZvcm1fZ2V0 X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCAyKTsKPiArCXJlZ3MgPSBkZXZtX2lvcmVt YXBfcmVzb3VyY2UoZGV2LCByZXMpOwo+ICsJaWYgKElTX0VSUihyZWdzKSkKPiArCQlyZXR1cm4g UFRSX0VSUihyZWdzKTsKPiArCWNkbnMtPm90Z19yZWdzID0gcmVnczsKPiArCj4gKwltdXRleF9p bml0KCZjZG5zLT5tdXRleCk7Cj4gKwo+ICsJY2Rucy0+cGh5ID0gZGV2bV9waHlfZ2V0KGRldiwg ImNkbnMzLHVzYnBoeSIpOwo+ICsJaWYgKElTX0VSUihjZG5zLT5waHkpKSB7Cj4gKwkJcmV0ID0g UFRSX0VSUihjZG5zLT5waHkpOwo+ICsJCWlmIChyZXQgPT0gLUVOT1NZUyB8fCByZXQgPT0gLUVO T0RFVikgewoKQXJlIHlvdSBzdXJlIHlvdSBjYW4gZ2V0IEVOT1NZUyBoZXJlPyBIYXZlIHlvdSBj aGVja2VkIG91dHB1dCBvZgpjaGVja3BhdGNoIC0tc3RyaWN0PwoKLTo4NTI6IFdBUk5JTkc6IEVO T1NZUyBtZWFucyAnaW52YWxpZCBzeXNjYWxsIG5yJyBhbmQgbm90aGluZyBlbHNlCgo+ICsjaWZk ZWYgQ09ORklHX1BNX1NMRUVQCj4gK3N0YXRpYyBpbnQgY2RuczNfc3VzcGVuZChzdHJ1Y3QgZGV2 aWNlICpkZXYpCj4gK3sKPiArCS8qIFRPRE86IEltcGxlbWVudHMgdGhpcyBmdW5jdGlvbi4gKi8K PiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNkbnMzX3Jlc3VtZShzdHJ1Y3Qg ZGV2aWNlICpkZXYpCj4gK3sKPiArCS8qIFRPRE86IEltcGxlbWVudHMgdGhpcyBmdW5jdGlvbi4g Ki8KPiArCXJldHVybiAwOwo+ICt9Cj4gKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KPiAr c3RhdGljIGludCBjZG5zM19ydW50aW1lX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7 CS8qIFRPRE86IEltcGxlbWVudHMgdGhpcyBmdW5jdGlvbi4gKi8KPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IGNkbnMzX3J1bnRpbWVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRl dikKPiArewo+ICsJLyogVE9ETzogSW1wbGVtZW50cyB0aGlzIGZ1bmN0aW9uLiAqLwo+ICsJcmV0 dXJuIDA7Cj4gK30KPiArI2VuZGlmIC8qIENPTkZJR19QTSAqLwoKcGxlYXNlIG5vIFRPRE8gc3R1 YnMuIEp1c3QgZ2V0IHJpZCBvZiB5b3VyIGRldl9wbV9vcHMgaWYgeW91IGRvbid0CmltcGxlbWVu dCB0aGVtLiBDb21lIHVwIHdpdGggYSBsYXRlciBwYXRjaCBhZGRpbmcgYSBwcm9wZXIKaW1wbGVt ZW50YXRpb24gZm9yIFBNLgoKPiArc3RhdGljIGludCBfX2luaXQgY2RuczNfZHJpdmVyX3BsYXRm b3JtX3JlZ2lzdGVyKHZvaWQpCj4gK3sKPiArCXJldHVybiBwbGF0Zm9ybV9kcml2ZXJfcmVnaXN0 ZXIoJmNkbnMzX2RyaXZlcik7Cj4gK30KPiArbW9kdWxlX2luaXQoY2RuczNfZHJpdmVyX3BsYXRm b3JtX3JlZ2lzdGVyKTsKPiArCj4gK3N0YXRpYyB2b2lkIF9fZXhpdCBjZG5zM19kcml2ZXJfcGxh dGZvcm1fdW5yZWdpc3Rlcih2b2lkKQo+ICt7Cj4gKwlwbGF0Zm9ybV9kcml2ZXJfdW5yZWdpc3Rl cigmY2RuczNfZHJpdmVyKTsKPiArfQo+ICttb2R1bGVfZXhpdChjZG5zM19kcml2ZXJfcGxhdGZv cm1fdW5yZWdpc3Rlcik7Cgptb2R1bGVfcGxhdGZvcm1fZHJpdmVyKCkKCj4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvdXNiL2NkbnMzL2RlYnVnLmggYi9kcml2ZXJzL3VzYi9jZG5zMy9kZWJ1Zy5oCj4g bmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLmFmYjgxZDIyNDcxOAo+ IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3VzYi9jZG5zMy9kZWJ1Zy5oCj4gQEAgLTAs MCArMSwzNDYgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8KPiAr LyoKPiArICogQ2FkZW5jZSBVU0JTUyBEUkQgRHJpdmVyLgo+ICsgKiBEZWJ1ZyBoZWFkZXIgZmls ZS4KPiArICoKPiArICogQ29weXJpZ2h0IChDKSAyMDE4IENhZGVuY2UuCj4gKyAqCj4gKyAqIEF1 dGhvcjogUGF3ZWwgTGFzemN6YWsgPHBhd2VsbEBjYWRlbmNlLmNvbT4KPiArICovCj4gKyNpZm5k ZWYgX19MSU5VWF9DRE5TM19ERUJVRwo+ICsjZGVmaW5lIF9fTElOVVhfQ0ROUzNfREVCVUcKPiAr I2luY2x1ZGUgImdhZGdldC5oIgo+ICsKPiArc3RhdGljIGlubGluZSB2b2lkIGNkbnMzX2RlY29k ZV9nZXRfc3RhdHVzKHU4IGJSZXF1ZXN0VHlwZSwgdTE2IHdJbmRleCwKPiArCQkJCQkgICB1MTYg d0xlbmd0aCwgY2hhciAqc3RyKQo+ICt7Cj4gKwlzd2l0Y2ggKGJSZXF1ZXN0VHlwZSAmIFVTQl9S RUNJUF9NQVNLKSB7Cj4gKwljYXNlIFVTQl9SRUNJUF9JTlRFUkZBQ0U6Cj4gKwkJc3ByaW50Zihz dHIsICJHZXQgSW50ZXJmYWNlIFN0YXR1cyBJbnRmID0gJWQsIEw6ID0gJWQiLAo+ICsJCQl3SW5k ZXgsIHdMZW5ndGgpOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfUkVDSVBfRU5EUE9JTlQ6Cj4g KwkJc3ByaW50ZihzdHIsICJHZXQgRW5kcG9pbnQgU3RhdHVzIGVwJWQlcyIsCj4gKwkJCXdJbmRl eCAmIH5VU0JfRElSX0lOLAo+ICsJCQl3SW5kZXggJiBVU0JfRElSX0lOID8gImluIiA6ICJvdXQi KTsKPiArCQlicmVhazsKPiArCX0KPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBjb25zdCBjaGFy ICpjZG5zM19kZWNvZGVfZGV2aWNlX2ZlYXR1cmUodTE2IHdWYWx1ZSkKPiArewo+ICsJc3dpdGNo ICh3VmFsdWUpIHsKPiArCWNhc2UgVVNCX0RFVklDRV9TRUxGX1BPV0VSRUQ6Cj4gKwkJcmV0dXJu ICJTZWxmIFBvd2VyZWQiOwo+ICsJY2FzZSBVU0JfREVWSUNFX1JFTU9URV9XQUtFVVA6Cj4gKwkJ cmV0dXJuICJSZW1vdGUgV2FrZXVwIjsKPiArCWNhc2UgVVNCX0RFVklDRV9URVNUX01PREU6Cj4g KwkJcmV0dXJuICJUZXN0IE1vZGUiOwo+ICsJY2FzZSBVU0JfREVWSUNFX1UxX0VOQUJMRToKPiAr CQlyZXR1cm4gIlUxIEVuYWJsZSI7Cj4gKwljYXNlIFVTQl9ERVZJQ0VfVTJfRU5BQkxFOgo+ICsJ CXJldHVybiAiVTIgRW5hYmxlIjsKPiArCWNhc2UgVVNCX0RFVklDRV9MVE1fRU5BQkxFOgo+ICsJ CXJldHVybiAiTFRNIEVuYWJsZSI7Cj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiAiVU5LTk9XTiI7 Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgY29uc3QgY2hhciAqY2RuczNfZGVjb2Rl X3Rlc3RfbW9kZSh1MTYgd0luZGV4KQo+ICt7Cj4gKwlzd2l0Y2ggKHdJbmRleCkgewo+ICsJY2Fz ZSBURVNUX0o6Cj4gKwkJcmV0dXJuICI6IFRFU1RfSiI7Cj4gKwljYXNlIFRFU1RfSzoKPiArCQly ZXR1cm4gIjogVEVTVF9LIjsKPiArCWNhc2UgVEVTVF9TRTBfTkFLOgo+ICsJCXJldHVybiAiOiBU RVNUX1NFMF9OQUsiOwo+ICsJY2FzZSBURVNUX1BBQ0tFVDoKPiArCQlyZXR1cm4gIjogVEVTVF9Q QUNLRVQiOwo+ICsJY2FzZSBURVNUX0ZPUkNFX0VOOgo+ICsJCXJldHVybiAiOiBURVNUX0ZPUkNF X0VOIjsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuICI6IFVOS05PV04iOwo+ICsJfQo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW5saW5lIHZvaWQgY2RuczNfZGVjb2RlX3NldF9jbGVhcl9mZWF0dXJlKHU4 IGJSZXF1ZXN0VHlwZSwgdTggYlJlcXVlc3QsCj4gKwkJCQkJCSAgdTE2IHdWYWx1ZSwgdTE2IHdJ bmRleCwKPiArCQkJCQkJICBjaGFyICpzdHIpCj4gK3sKPiArCXN3aXRjaCAoYlJlcXVlc3RUeXBl ICYgVVNCX1JFQ0lQX01BU0spIHsKPiArCWNhc2UgVVNCX1JFQ0lQX0RFVklDRToKPiArCQlzcHJp bnRmKHN0ciwgIiVzIERldmljZSBGZWF0dXJlKCVzJXMpIiwKPiArCQkJYlJlcXVlc3QgPT0gVVNC X1JFUV9DTEVBUl9GRUFUVVJFID8gIkNsZWFyIiA6ICJTZXQiLAo+ICsJCQljZG5zM19kZWNvZGVf ZGV2aWNlX2ZlYXR1cmUod1ZhbHVlKSwKPiArCQkJd1ZhbHVlID09IFVTQl9ERVZJQ0VfVEVTVF9N T0RFID8KPiArCQkJY2RuczNfZGVjb2RlX3Rlc3RfbW9kZSh3SW5kZXgpIDogIiIpOwo+ICsJCWJy ZWFrOwo+ICsJY2FzZSBVU0JfUkVDSVBfSU5URVJGQUNFOgo+ICsJCXNwcmludGYoc3RyLCAiJXMg SW50ZXJmYWNlIEZlYXR1cmUoJXMpIiwKPiArCQkJYlJlcXVlc3QgPT0gVVNCX1JFUV9DTEVBUl9G RUFUVVJFID8gIkNsZWFyIiA6ICJTZXQiLAo+ICsJCQl3SW5kZXggPT0gVVNCX0lOVFJGX0ZVTkNf U1VTUEVORCA/Cj4gKwkJCSJGdW5jdGlvbiBTdXNwZW5kIiA6ICJVTktOT1dOIik7Cj4gKwkJYnJl YWs7Cj4gKwljYXNlIFVTQl9SRUNJUF9FTkRQT0lOVDoKPiArCQlzcHJpbnRmKHN0ciwgIiVzIEVu ZHBvaW50IEZlYXR1cmUoJXMgZXAlZCVzKSIsCj4gKwkJCWJSZXF1ZXN0ID09IFVTQl9SRVFfQ0xF QVJfRkVBVFVSRSA/ICJDbGVhciIgOiAiU2V0IiwKPiArCQkJICAgIHdJbmRleCA9PSBVU0JfRU5E UE9JTlRfSEFMVCA/ICJIYWx0IiA6ICJVTktOT1dOIiwKPiArCQkJd0luZGV4ICYgflVTQl9ESVJf SU4sCj4gKwkJCXdJbmRleCAmIFVTQl9ESVJfSU4gPyAiaW4iIDogIm91dCIpOwo+ICsJCWJyZWFr Owo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGNvbnN0IGNoYXIgKmNkbnMzX2RlY29k ZV9kZXNjcmlwdG9yKHUxNiB3VmFsdWUpCj4gK3sKPiArCXN3aXRjaCAod1ZhbHVlID4+IDgpIHsK PiArCWNhc2UgVVNCX0RUX0RFVklDRToKPiArCQlyZXR1cm4gIkRldmljZSI7Cj4gKwljYXNlIFVT Ql9EVF9DT05GSUc6Cj4gKwkJcmV0dXJuICJDb25maWd1cmF0aW9uIjsKPiArCWNhc2UgVVNCX0RU X1NUUklORzoKPiArCQlyZXR1cm4gIlN0cmluZyI7Cj4gKwljYXNlIFVTQl9EVF9JTlRFUkZBQ0U6 Cj4gKwkJcmV0dXJuICJJbnRlcmZhY2UiOwo+ICsJY2FzZSBVU0JfRFRfRU5EUE9JTlQ6Cj4gKwkJ cmV0dXJuICJFbmRwb2ludCI7Cj4gKwljYXNlIFVTQl9EVF9ERVZJQ0VfUVVBTElGSUVSOgo+ICsJ CXJldHVybiAiRGV2aWNlIFF1YWxpZmllciI7Cj4gKwljYXNlIFVTQl9EVF9PVEhFUl9TUEVFRF9D T05GSUc6Cj4gKwkJcmV0dXJuICJPdGhlciBTcGVlZCBDb25maWciOwo+ICsJY2FzZSBVU0JfRFRf SU5URVJGQUNFX1BPV0VSOgo+ICsJCXJldHVybiAiSW50ZXJmYWNlIFBvd2VyIjsKPiArCWNhc2Ug VVNCX0RUX09URzoKPiArCQlyZXR1cm4gIk9URyI7Cj4gKwljYXNlIFVTQl9EVF9ERUJVRzoKPiAr CQlyZXR1cm4gIkRlYnVnIjsKPiArCWNhc2UgVVNCX0RUX0lOVEVSRkFDRV9BU1NPQ0lBVElPTjoK PiArCQlyZXR1cm4gIkludGVyZmFjZSBBc3NvY2lhdGlvbiI7Cj4gKwljYXNlIFVTQl9EVF9CT1M6 Cj4gKwkJcmV0dXJuICJCT1MiOwo+ICsJY2FzZSBVU0JfRFRfREVWSUNFX0NBUEFCSUxJVFk6Cj4g KwkJcmV0dXJuICJEZXZpY2UgQ2FwYWJpbGl0eSI7Cj4gKwljYXNlIFVTQl9EVF9TU19FTkRQT0lO VF9DT01QOgo+ICsJCXJldHVybiAiU1MgRW5kcG9pbnQgQ29tcGFuaW9uIjsKPiArCWNhc2UgVVNC X0RUX1NTUF9JU09DX0VORFBPSU5UX0NPTVA6Cj4gKwkJcmV0dXJuICJTU1AgSXNvY2hyb25vdXMg RW5kcG9pbnQgQ29tcGFuaW9uIjsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuICJVTktOT1dOIjsK PiArCX0KPiArfQo+ICsKPiArLyoqCj4gKyAqIGNkbnMzX2RlY29kZV9jdHJsIC0gcmV0dXJucyBh IHN0cmluZyByZXByZXNldGlvbiBvZiBjdHJsIHJlcXVlc3QKPiArICovCj4gK3N0YXRpYyBpbmxp bmUgY29uc3QgY2hhciAqY2RuczNfZGVjb2RlX2N0cmwoY2hhciAqc3RyLCB1OCBiUmVxdWVzdFR5 cGUsCj4gKwkJCQkJICAgIHU4IGJSZXF1ZXN0LCB1MTYgd1ZhbHVlLAo+ICsJCQkJCSAgICB1MTYg d0luZGV4LCB1MTYgd0xlbmd0aCkKPiArewo+ICsJc3dpdGNoIChiUmVxdWVzdCkgewo+ICsJY2Fz ZSBVU0JfUkVRX0dFVF9TVEFUVVM6Cj4gKwkJY2RuczNfZGVjb2RlX2dldF9zdGF0dXMoYlJlcXVl c3RUeXBlLCB3SW5kZXgsCj4gKwkJCQkJd0xlbmd0aCwgc3RyKTsKPiArCQlicmVhazsKPiArCWNh c2UgVVNCX1JFUV9DTEVBUl9GRUFUVVJFOgo+ICsJY2FzZSBVU0JfUkVRX1NFVF9GRUFUVVJFOgo+ ICsJCWNkbnMzX2RlY29kZV9zZXRfY2xlYXJfZmVhdHVyZShiUmVxdWVzdFR5cGUsIGJSZXF1ZXN0 LAo+ICsJCQkJCSAgICAgICB3VmFsdWUsIHdJbmRleCwgc3RyKTsKPiArCQlicmVhazsKPiArCWNh c2UgVVNCX1JFUV9TRVRfQUREUkVTUzoKPiArCQlzcHJpbnRmKHN0ciwgIlNldCBBZGRyZXNzIEFk ZHI6ICUwMngiLCB3VmFsdWUpOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfUkVRX0dFVF9ERVND UklQVE9SOgo+ICsJCXNwcmludGYoc3RyLCAiR0VUICVzIERlc2NyaXB0b3IgSTogJWQsIEw6ICVk IiwKPiArCQkJY2RuczNfZGVjb2RlX2Rlc2NyaXB0b3Iod1ZhbHVlKSwKPiArCQkJd1ZhbHVlICYg MHhmZiwgd0xlbmd0aCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9SRVFfU0VUX0RFU0NSSVBU T1I6Cj4gKwkJc3ByaW50ZihzdHIsICJTRVQgJXMgRGVzY3JpcHRvciBJOiAlZCwgTDogJWQiLAo+ ICsJCQljZG5zM19kZWNvZGVfZGVzY3JpcHRvcih3VmFsdWUpLAo+ICsJCQl3VmFsdWUgJiAweGZm LCB3TGVuZ3RoKTsKPiArCQlicmVhazsKPiArCWNhc2UgVVNCX1JFUV9HRVRfQ09ORklHVVJBVElP TjoKPiArCQlzcHJpbnRmKHN0ciwgIkdldCBDb25maWd1cmF0aW9uIEw6ICVkIiwgd0xlbmd0aCk7 Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9SRVFfU0VUX0NPTkZJR1VSQVRJT046Cj4gKwkJc3By aW50ZihzdHIsICJTZXQgQ29uZmlndXJhdGlvbiBDb25maWc6ICVkICIsIHdWYWx1ZSk7Cj4gKwkJ YnJlYWs7Cj4gKwljYXNlIFVTQl9SRVFfR0VUX0lOVEVSRkFDRToKPiArCQlzcHJpbnRmKHN0ciwg IkdldCBJbnRlcmZhY2UgSW50ZjogJWQsIEw6ICVkIiwgd0luZGV4LCB3TGVuZ3RoKTsKPiArCQli cmVhazsKPiArCWNhc2UgVVNCX1JFUV9TRVRfSU5URVJGQUNFOgo+ICsJCXNwcmludGYoc3RyLCAi U2V0IEludGVyZmFjZSBJbnRmOiAlZCwgQWx0OiAlZCIsIHdJbmRleCwgd1ZhbHVlKTsKPiArCQli cmVhazsKPiArCWNhc2UgVVNCX1JFUV9TWU5DSF9GUkFNRToKPiArCQlzcHJpbnRmKHN0ciwgIlN5 bmNoIEZyYW1lIEVwOiAlZCwgTDogJWQiLCB3SW5kZXgsIHdMZW5ndGgpOwo+ICsJCWJyZWFrOwo+ ICsJY2FzZSBVU0JfUkVRX1NFVF9TRUw6Cj4gKwkJc3ByaW50ZihzdHIsICJTZXQgU0VMIEw6ICVk Iiwgd0xlbmd0aCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9SRVFfU0VUX0lTT0NIX0RFTEFZ Ogo+ICsJCXNwcmludGYoc3RyLCAiU2V0IElzb2Nocm9ub3VzIERlbGF5IERlbGF5OiAlZCBucyIs IHdWYWx1ZSk7Cj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCXNwcmludGYoc3RyLAo+ICsJ CQkiU0VUVVAgQlJUOiAlMDJ4IEJSOiAlMDJ4IFY6ICUwNHggSTogJTA0eCBMOiAlMDR4XG4iLAo+ ICsJCQliUmVxdWVzdFR5cGUsIGJSZXF1ZXN0LAo+ICsJCQl3VmFsdWUsIHdJbmRleCwgd0xlbmd0 aCk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHN0cjsKPiArfQoKQWxsIG9mIHRoZXNlIGFyZSBhIGZs YXQgb3V0IGNvcHkgb2YgZHdjMydzIGltcGxlbWVudGF0aW9uLiBJdCdzIG11Y2gsCm11Y2ggYmV0 dGVyIHRvIHR1cm4gZHdjMydzIGltcGxlbWVudGF0aW9uIGludG8gYSBnZW5lcmljLCByZXVzYWJs ZQpsaWJyYXJ5IGZ1bmN0aW9uIHRoZW4gc3Bpbm5pbmcgeW91ciBvd24gYXMgYSBkdXBsaWNhdGVk IGVmZm9ydC4KCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL2NkbnMzL2VwMC5jIGIvZHJpdmVy cy91c2IvY2RuczMvZXAwLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAw MDAwMC4uMWVmMGU5ZjczZTNlCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvdXNiL2Nk bnMzL2VwMC5jCj4gQEAgLTAsMCArMSw4NjQgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IEdQTC0yLjAKPiArLyoKPiArICogQ2FkZW5jZSBVU0JTUyBEUkQgRHJpdmVyIC0gZ2FkZ2V0 IHNpZGUuCj4gKyAqCj4gKyAqIENvcHlyaWdodCAoQykgMjAxOCBDYWRlbmNlIERlc2lnbiBTeXN0 ZW1zLgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTctMjAxOCBOWFAKPiArICoKPiArICogQXV0aG9y czogUGF3ZWwgSmV6IDxwamV6QGNhZGVuY2UuY29tPiwKPiArICogICAgICAgICAgUGF3ZWwgTGFz emN6YWsgPHBhd2VsbEBjYWRlbmNlLmNvbT4KPiArICoJICAgIFBldGVyIENoZW4gPHBldGVyLmNo ZW5AbnhwLmNvbT4KPiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvdXNiL2NvbXBvc2l0ZS5o Pgo+ICsKPiArI2luY2x1ZGUgImdhZGdldC5oIgo+ICsjaW5jbHVkZSAidHJhY2UuaCIKPiArCj4g K3N0YXRpYyBzdHJ1Y3QgdXNiX2VuZHBvaW50X2Rlc2NyaXB0b3IgY2RuczNfZ2FkZ2V0X2VwMF9k ZXNjID0gewo+ICsJLmJMZW5ndGggPSBVU0JfRFRfRU5EUE9JTlRfU0laRSwKPiArCS5iRGVzY3Jp cHRvclR5cGUgPSBVU0JfRFRfRU5EUE9JTlQsCj4gKwkuYm1BdHRyaWJ1dGVzID0JVVNCX0VORFBP SU5UX1hGRVJfQ09OVFJPTCwKPiArfTsKPiArCj4gKy8qKgo+ICsgKiBjZG5zM19lcDBfcnVuX3Ry YW5zZmVyIC0gRG8gdHJhbnNmZXIgb24gZGVmYXVsdCBlbmRwb2ludCBoYXJkd2FyZQo+ICsgKiBA cHJpdl9kZXY6IGV4dGVuZGVkIGdhZGdldCBvYmplY3QKPiArICogQGRtYV9hZGRyOiBwaHlzaWNh bCBhZGRyZXNzIHdoZXJlIGRhdGEgaXMvd2lsbCBiZSBzdG9yZWQKPiArICogQGxlbmd0aDogZGF0 YSBsZW5ndGgKPiArICogQGVyZHk6IHNldCBpdCB0byAxIHdoZW4gRVJEWSBwYWNrZXQgc2hvdWxk IGJlIHNlbnQgLQo+ICsgKiAgICAgICAgZXhpdCBmcm9tIGZsb3cgY29udHJvbCBzdGF0ZQo+ICsg Ki8KPiArc3RhdGljIHZvaWQgY2RuczNfZXAwX3J1bl90cmFuc2ZlcihzdHJ1Y3QgY2RuczNfZGV2 aWNlICpwcml2X2RldiwKPiArCQkJCSAgIGRtYV9hZGRyX3QgZG1hX2FkZHIsCj4gKwkJCQkgICB1 bnNpZ25lZCBpbnQgbGVuZ3RoLCBpbnQgZXJkeSkKPiArewo+ICsJc3RydWN0IGNkbnMzX3VzYl9y ZWdzIF9faW9tZW0gKnJlZ3MgPSBwcml2X2Rldi0+cmVnczsKPiArCXN0cnVjdCBjZG5zM19lbmRw b2ludCAqcHJpdl9lcCA9IGVwX3RvX2NkbnMzX2VwKHByaXZfZGV2LT5nYWRnZXQuZXAwKTsKPiAr Cj4gKwlwcml2X2Rldi0+ZXAwX3RyYi0+YnVmZmVyID0gVFJCX0JVRkZFUihkbWFfYWRkcik7Cj4g Kwlwcml2X2Rldi0+ZXAwX3RyYi0+bGVuZ3RoID0gVFJCX0xFTihsZW5ndGgpOwo+ICsJcHJpdl9k ZXYtPmVwMF90cmItPmNvbnRyb2wgPSBUUkJfQ1lDTEUgfCBUUkJfSU9DIHwgVFJCX1RZUEUoVFJC X05PUk1BTCk7Cj4gKwo+ICsJdHJhY2VfY2RuczNfcHJlcGFyZV90cmIocHJpdl9lcCwgcHJpdl9k ZXYtPmVwMF90cmIpOwo+ICsKPiArCWNkbnMzX3NlbGVjdF9lcChwcml2X2RldiwgcHJpdl9kZXYt PmVwMF9kYXRhX2Rpcik7Cj4gKwo+ICsJd3JpdGVsKEVQX1NUU19UUkJFUlIsICZyZWdzLT5lcF9z dHMpOwo+ICsJd3JpdGVsKEVQX1RSQUREUl9UUkFERFIocHJpdl9kZXYtPmVwMF90cmJfZG1hKSwg JnJlZ3MtPmVwX3RyYWRkcik7Cj4gKwl0cmFjZV9jZG5zM19kb29yYmVsbF9lcDAocHJpdl9kZXYt PmVwMF9kYXRhX2RpciA/ICJlcDBpbiIgOiAiZXAwb3V0Iik7Cj4gKwo+ICsJLyogVFJCIHNob3Vs ZCBiZSBwcmVwYXJlZCBiZWZvcmUgc3RhcnRpbmcgdHJhbnNmZXIgKi8KPiArCXdyaXRlbChFUF9D TURfRFJEWSwgJnJlZ3MtPmVwX2NtZCk7Cj4gKwo+ICsJaWYgKGVyZHkpCj4gKwkJd3JpdGVsKEVQ X0NNRF9FUkRZLCAmcHJpdl9kZXYtPnJlZ3MtPmVwX2NtZCk7Cj4gK30KPiArCj4gKy8qKgo+ICsg KiBjZG5zM19lcDBfZGVsZWdhdGVfcmVxIC0gUmV0dXJucyBzdGF0dXMgb2YgaGFuZGxpbmcgc2V0 dXAgcGFja2V0Cj4gKyAqIFNldHVwIGlzIGhhbmRsZWQgYnkgZ2FkZ2V0IGRyaXZlcgo+ICsgKiBA cHJpdl9kZXY6IGV4dGVuZGVkIGdhZGdldCBvYmplY3QKPiArICogQGN0cmxfcmVxOiBwb2ludGVy IHRvIHJlY2VpdmVkIHNldHVwIHBhY2tldAo+ICsgKgo+ICsgKiBSZXR1cm5zIHplcm8gb24gc3Vj Y2VzcyBvciBuZWdhdGl2ZSB2YWx1ZSBvbiBmYWlsdXJlCj4gKyAqLwo+ICtzdGF0aWMgaW50IGNk bnMzX2VwMF9kZWxlZ2F0ZV9yZXEoc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYsCj4gKwkJ CQkgIHN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmxfcmVxKQo+ICt7Cj4gKwlpbnQgcmV0Owo+ ICsKPiArCXNwaW5fdW5sb2NrKCZwcml2X2Rldi0+bG9jayk7Cj4gKwlwcml2X2Rldi0+c2V0dXBf cGVuZGluZyA9IDE7Cj4gKwlyZXQgPSBwcml2X2Rldi0+Z2FkZ2V0X2RyaXZlci0+c2V0dXAoJnBy aXZfZGV2LT5nYWRnZXQsIGN0cmxfcmVxKTsKPiArCXByaXZfZGV2LT5zZXR1cF9wZW5kaW5nID0g MDsKPiArCXNwaW5fbG9jaygmcHJpdl9kZXYtPmxvY2spOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgY2RuczNfcHJlcGFyZV9zZXR1cF9wYWNrZXQoc3RydWN0IGNkbnMz X2RldmljZSAqcHJpdl9kZXYpCj4gK3sKPiArCXByaXZfZGV2LT5lcDBfZGF0YV9kaXIgPSAwOwo+ ICsJY2RuczNfZXAwX3J1bl90cmFuc2Zlcihwcml2X2RldiwgcHJpdl9kZXYtPnNldHVwX2RtYSwK PiArCQkJICAgICAgIHNpemVvZihzdHJ1Y3QgdXNiX2N0cmxyZXF1ZXN0KSwgMCk7Cj4gK30KPiAr Cj4gKy8qKgo+ICsgKiBjZG5zM19yZXFfZXAwX3NldF9jb25maWd1cmF0aW9uIC0gSGFuZGxpbmcg b2YgU0VUX0NPTkZJRyBzdGFuZGFyZCBVU0IgcmVxdWVzdAo+ICsgKiBAcHJpdl9kZXY6IGV4dGVu ZGVkIGdhZGdldCBvYmplY3QKPiArICogQGN0cmxfcmVxOiBwb2ludGVyIHRvIHJlY2VpdmVkIHNl dHVwIHBhY2tldAo+ICsgKgo+ICsgKiBSZXR1cm5zIDAgaWYgc3VjY2VzcywgVVNCX0dBREdFVF9E RUxBWUVEX1NUQVRVUyBvbiBkZWZlcnJlZCBzdGF0dXMgc3RhZ2UsCj4gKyAqIGVycm9yIGNvZGUg b24gZXJyb3IKPiArICovCj4gK3N0YXRpYyBpbnQgY2RuczNfcmVxX2VwMF9zZXRfY29uZmlndXJh dGlvbihzdHJ1Y3QgY2RuczNfZGV2aWNlICpwcml2X2RldiwKPiArCQkJCQkgICBzdHJ1Y3QgdXNi X2N0cmxyZXF1ZXN0ICpjdHJsX3JlcSkKPiArewo+ICsJZW51bSB1c2JfZGV2aWNlX3N0YXRlIGRl dmljZV9zdGF0ZSA9IHByaXZfZGV2LT5nYWRnZXQuc3RhdGU7Cj4gKwlzdHJ1Y3QgY2RuczNfZW5k cG9pbnQgKnByaXZfZXA7Cj4gKwl1MzIgY29uZmlnID0gbGUxNl90b19jcHUoY3RybF9yZXEtPndW YWx1ZSk7Cj4gKwlpbnQgcmVzdWx0ID0gMDsKPiArCWludCBpOwo+ICsKPiArCXN3aXRjaCAoZGV2 aWNlX3N0YXRlKSB7Cj4gKwljYXNlIFVTQl9TVEFURV9BRERSRVNTOgo+ICsJCS8qIENvbmZpZ3Vy ZSBub24tY29udHJvbCBFUHMgKi8KPiArCQlmb3IgKGkgPSAwOyBpIDwgQ0ROUzNfRU5EUE9JTlRT X01BWF9DT1VOVDsgaSsrKSB7Cj4gKwkJCXByaXZfZXAgPSBwcml2X2Rldi0+ZXBzW2ldOwo+ICsJ CQlpZiAoIXByaXZfZXApCj4gKwkJCQljb250aW51ZTsKPiArCj4gKwkJCWlmIChwcml2X2VwLT5m bGFncyAmIEVQX0NMQUlNRUQpCj4gKwkJCQljZG5zM19lcF9jb25maWcocHJpdl9lcCk7Cj4gKwkJ fQo+ICsKPiArCQlyZXN1bHQgPSBjZG5zM19lcDBfZGVsZWdhdGVfcmVxKHByaXZfZGV2LCBjdHJs X3JlcSk7Cj4gKwo+ICsJCWlmIChyZXN1bHQpCj4gKwkJCXJldHVybiByZXN1bHQ7Cj4gKwo+ICsJ CWlmIChjb25maWcpIHsKPiArCQkJY2RuczNfc2V0X2h3X2NvbmZpZ3VyYXRpb24ocHJpdl9kZXYp Owo+ICsJCX0gZWxzZSB7Cj4gKwkJCWNkbnMzX2dhZGdldF91bmNvbmZpZyhwcml2X2Rldik7Cj4g KwkJCXVzYl9nYWRnZXRfc2V0X3N0YXRlKCZwcml2X2Rldi0+Z2FkZ2V0LAo+ICsJCQkJCSAgICAg VVNCX1NUQVRFX0FERFJFU1MpOwoKdGhpcyBpcyB3cm9uZy4gSWYgYWRkcmVzcyBpcyB6ZXJvLCBz dGF0ZSBzaG91bGQgYmUgZGVmYXVsdCwgbm90CmFkZHJlc3NlZC4gQWRkcmVzc2VkIHdvdWxkIGJl IHVzZWQgb24gdGhlIG90aGVyIGJyYW5jaCBoZXJlLCB3aGVuIHlvdQpoYXZlIGEgbm9uLXplcm8g YWRkcmVzcwoKPiArCQl9Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9TVEFURV9DT05GSUdVUkVE OgoKd2hlcmUgZG8geW91IHNldCB0aGlzIHN0YXRlPwoKPiArc3RhdGljIGludCBjZG5zM19lcDBf ZmVhdHVyZV9oYW5kbGVfZGV2aWNlKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICsJ CQkJCSAgIHN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmwsCj4gKwkJCQkJICAgaW50IHNldCkK PiArewo+ICsJZW51bSB1c2JfZGV2aWNlX3N0YXRlIHN0YXRlOwo+ICsJZW51bSB1c2JfZGV2aWNl X3NwZWVkIHNwZWVkOwo+ICsJaW50IHJldCA9IDA7Cj4gKwl1MzIgd1ZhbHVlOwo+ICsJdTMyIHdJ bmRleDsKPiArCXUxNiB0bW9kZTsKPiArCj4gKwl3VmFsdWUgPSBsZTE2X3RvX2NwdShjdHJsLT53 VmFsdWUpOwo+ICsJd0luZGV4ID0gbGUxNl90b19jcHUoY3RybC0+d0luZGV4KTsKPiArCXN0YXRl ID0gcHJpdl9kZXYtPmdhZGdldC5zdGF0ZTsKPiArCXNwZWVkID0gcHJpdl9kZXYtPmdhZGdldC5z cGVlZDsKPiArCj4gKwlzd2l0Y2ggKGN0cmwtPndWYWx1ZSkgewo+ICsJY2FzZSBVU0JfREVWSUNF X1JFTU9URV9XQUtFVVA6Cj4gKwkJcHJpdl9kZXYtPndha2VfdXBfZmxhZyA9ICEhc2V0Owo+ICsJ CWJyZWFrOwo+ICsJY2FzZSBVU0JfREVWSUNFX1UxX0VOQUJMRToKPiArCQlpZiAoc3RhdGUgIT0g VVNCX1NUQVRFX0NPTkZJR1VSRUQgfHwgc3BlZWQgIT0gVVNCX1NQRUVEX1NVUEVSKQo+ICsJCQly ZXR1cm4gLUVJTlZBTDsKPiArCj4gKwkJcHJpdl9kZXYtPnUxX2FsbG93ZWQgPSAhIXNldDsKPiAr CQlicmVhazsKPiArCWNhc2UgVVNCX0RFVklDRV9VMl9FTkFCTEU6Cj4gKwkJaWYgKHN0YXRlICE9 IFVTQl9TVEFURV9DT05GSUdVUkVEIHx8IHNwZWVkICE9IFVTQl9TUEVFRF9TVVBFUikKPiArCQkJ cmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXByaXZfZGV2LT51Ml9hbGxvd2VkID0gISFzZXQ7Cj4g KwkJYnJlYWs7Cj4gKwljYXNlIFVTQl9ERVZJQ0VfTFRNX0VOQUJMRToKPiArCQlyZXQgPSAtRUlO VkFMOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfREVWSUNFX1RFU1RfTU9ERToKPiArCQlpZiAo c3RhdGUgIT0gVVNCX1NUQVRFX0NPTkZJR1VSRUQgfHwgc3BlZWQgPiBVU0JfU1BFRURfSElHSCkK PiArCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXRtb2RlID0gbGUxNl90b19jcHUoY3RybC0+ d0luZGV4KTsKPiArCj4gKwkJaWYgKCFzZXQgfHwgKHRtb2RlICYgMHhmZikgIT0gMCkKPiArCQkJ cmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXN3aXRjaCAodG1vZGUgPj4gOCkgewo+ICsJCWNhc2Ug VEVTVF9KOgo+ICsJCWNhc2UgVEVTVF9LOgo+ICsJCWNhc2UgVEVTVF9TRTBfTkFLOgo+ICsJCWNh c2UgVEVTVF9QQUNLRVQ6Cj4gKwkJCWNkbnMzX3NldF9yZWdpc3Rlcl9iaXQoJnByaXZfZGV2LT5y ZWdzLT51c2JfY21kLAo+ICsJCQkJCSAgICAgICBVU0JfQ01EX1NUTU9ERSB8Cj4gKwkJCQkJICAg ICAgIFVTQl9TVFNfVE1PREVfU0VMKHRtb2RlIC0gMSkpOwoKSSdtIDkwJSBzdXJlIHRoaXMgd29u J3Qgd29yay4gVGhlcmUncyBhIHJlYXNvbiB3aHkgd2Ugb25seSBlbnRlciB0aGUKcmVxdWVzdGVk IHRlc3QgbW9kZSBmcm9tIHN0YXR1cyBzdGFnZS4gSG93IGhhdmUgeW91IHRlc3RlZCB0aGlzPwoK PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMgYi9kcml2ZXJzL3VzYi9j ZG5zMy9nYWRnZXQuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAw Li5hMDIxZWFmMDdhZWUKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy91c2IvY2RuczMv Z2FkZ2V0LmMKCjxzbmlwPgoKPiArc3RydWN0IHVzYl9yZXF1ZXN0ICpjZG5zM19uZXh0X3JlcXVl c3Qoc3RydWN0IGxpc3RfaGVhZCAqbGlzdCkKPiArewo+ICsJaWYgKGxpc3RfZW1wdHkobGlzdCkp Cj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwlyZXR1cm4gbGlzdF9maXJzdF9lbnRyeShsaXN0LCBzdHJ1 Y3QgdXNiX3JlcXVlc3QsIGxpc3QpOwoKbGlzdF9maXJzdF9lbnRyeV9vcl9udWxsKCkKCj4gK3Zv aWQgY2RuczNfZ2FkZ2V0X3VuY29uZmlnKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2KQo+ ICt7Cj4gKwkvKiBSRVNFVCBDT05GSUdVUkFUSU9OICovCj4gKwl3cml0ZWwoVVNCX0NPTkZfQ0ZH UlNULCAmcHJpdl9kZXYtPnJlZ3MtPnVzYl9jb25mKTsKPiArCj4gKwljZG5zM19hbGxvd19lbmFi bGVfbDEocHJpdl9kZXYsIDApOwo+ICsJcHJpdl9kZXYtPmh3X2NvbmZpZ3VyZWRfZmxhZyA9IDA7 Cj4gKwlwcml2X2Rldi0+b25jaGlwX21lbV9hbGxvY2F0ZWRfc2l6ZSA9IDA7CgpjbGVhciBhbGwg dGVzdCBtb2Rlcz8gUmVzZXQgZXAwIG1heF9wYWNrZXRfc2l6ZSB0byA1MTI/Cgo+ICtzdGF0aWMg aXJxcmV0dXJuX3QgY2RuczNfZGV2aWNlX2lycV9oYW5kbGVyKGludCBpcnEsIHZvaWQgKmRhdGEp Cj4gK3sKPiArCXN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2Owo+ICsJc3RydWN0IGNkbnMz ICpjZG5zID0gZGF0YTsKPiArCWlycXJldHVybl90IHJldCA9IElSUV9OT05FOwo+ICsJdW5zaWdu ZWQgbG9uZyBmbGFnczsKPiArCXUzMiByZWc7Cj4gKwo+ICsJcHJpdl9kZXYgPSBjZG5zLT5nYWRn ZXRfZGV2Owo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJnByaXZfZGV2LT5sb2NrLCBmbGFncyk7Cgp5 b3UncmUgYWxyZWFkeSBydW5uaW5nIGluIGhhcmRpcnEgY29udGV4dC4gV2h5IGRvIHlvdSBuZWVk IHRoaXMgbG9jayBhdAphbGw/IEkgd291bGQgYmUgYmV0dGVyIHRvIHVzZSB0aGUgaGFyZGlycSBo YW5kbGVyIHRvIG1hc2sgeW91cgppbnRlcnJ1cHRzLCBzbyB0aGV5IGRvbid0IGZpcmUgYWdhaW4s IHRoZW4gdXNlZCB0aGUgdG9wLWhhbGYgKHNvZnRpcnEpCmhhbmRsZXIgdG8gYWN0dWFsbHkgaGFu ZGxlIHRoZSBpbnRlcnJ1cHRzLgoKPiArCS8qIGNoZWNrIFVTQiBkZXZpY2UgaW50ZXJydXB0ICov Cj4gKwlyZWcgPSByZWFkbCgmcHJpdl9kZXYtPnJlZ3MtPnVzYl9pc3RzKTsKPiArCXdyaXRlbChy ZWcsICZwcml2X2Rldi0+cmVncy0+dXNiX2lzdHMpOwo+ICsKPiArCWlmIChyZWcpIHsKPiArCQlk ZXZfZGJnKHByaXZfZGV2LT5kZXYsICJJUlE6IHVzYl9pc3RzOiAlMDhYXG4iLCByZWcpOwoKSSBz dHJvbmdseSBhZHZpc2UgYWdhaW5zdCB1c2luZyBkZXZfZGJnKCkgZm9yIGRlYnVnZ2luZy4gRXZl biBtb3JlIHNvCmluc2lkZSB5b3VyIElSUSBoYW5kbGVyLgoKPiArCQljZG5zM19jaGVja191c2Jf aW50ZXJydXB0X3Byb2NlZWQocHJpdl9kZXYsIHJlZyk7Cj4gKwkJcmV0ID0gSVJRX0hBTkRMRUQ7 Cj4gKwl9Cj4gKwo+ICsJLyogY2hlY2sgZW5kcG9pbnQgaW50ZXJydXB0ICovCj4gKwlyZWcgPSBy ZWFkbCgmcHJpdl9kZXYtPnJlZ3MtPmVwX2lzdHMpOwo+ICsKPiArCS8qIGhhbmRsZSBkZWZhdWx0 IGVuZHBvaW50IE9VVCAqLwo+ICsJaWYgKHJlZyAmIEVQX0lTVFNfRVBfT1VUMCkgewo+ICsJCWNk bnMzX2NoZWNrX2VwMF9pbnRlcnJ1cHRfcHJvY2VlZChwcml2X2RldiwgVVNCX0RJUl9PVVQpOwo+ ICsJCXJldCA9IElSUV9IQU5ETEVEOwo+ICsJfQo+ICsKPiArCS8qIGhhbmRsZSBkZWZhdWx0IGVu ZHBvaW50IElOICovCj4gKwlpZiAocmVnICYgRVBfSVNUU19FUF9JTjApIHsKPiArCQljZG5zM19j aGVja19lcDBfaW50ZXJydXB0X3Byb2NlZWQocHJpdl9kZXYsIFVTQl9ESVJfSU4pOwo+ICsJCXJl dCA9IElSUV9IQU5ETEVEOwo+ICsJfQo+ICsKPiArCS8qIGNoZWNrIGlmIGludGVycnVwdCBmcm9t IG5vbiBkZWZhdWx0IGVuZHBvaW50LCBpZiBubyBleGl0ICovCj4gKwlyZWcgJj0gfihFUF9JU1RT X0VQX09VVDAgfCBFUF9JU1RTX0VQX0lOMCk7Cj4gKwlpZiAoIXJlZykKPiArCQlnb3RvIGlycWVu ZDsKPiArCj4gKwlkbyB7Cj4gKwkJdW5zaWduZWQgaW50IGJpdF9wb3MgPSBmZnMocmVnKTsKPiAr CQl1MzIgYml0X21hc2sgPSAxIDw8IChiaXRfcG9zIC0gMSk7Cj4gKwkJaW50IGluZGV4Owo+ICsK PiArCQlpbmRleCA9IGNkbnMzX2VwX3JlZ19wb3NfdG9faW5kZXgoYml0X3Bvcyk7Cj4gKwkJY2Ru czNfY2hlY2tfZXBfaW50ZXJydXB0X3Byb2NlZWQocHJpdl9kZXYtPmVwc1tpbmRleF0pOwo+ICsJ CXJlZyAmPSB+Yml0X21hc2s7Cj4gKwkJcmV0ID0gSVJRX0hBTkRMRUQ7Cj4gKwl9IHdoaWxlIChy ZWcpOwoKdXNlIGZvcl9lYWNoX3NldF9iaXQoKSBoZXJlLgoKPiArdm9pZCBjZG5zM19lcF9jb25m aWcoc3RydWN0IGNkbnMzX2VuZHBvaW50ICpwcml2X2VwKQo+ICt7Cj4gKwlib29sIGlzX2lzb19l cCA9IChwcml2X2VwLT50eXBlID09IFVTQl9FTkRQT0lOVF9YRkVSX0lTT0MpOwo+ICsJc3RydWN0 IGNkbnMzX2RldmljZSAqcHJpdl9kZXYgPSBwcml2X2VwLT5jZG5zM19kZXY7Cj4gKwl1MzIgYkVu ZHBvaW50QWRkcmVzcyA9IHByaXZfZXAtPm51bSB8IHByaXZfZXAtPmRpcjsKPiArCXUzMiBpbnRl cnJ1cHRfbWFzayA9IEVQX1NUU19FTl9UUkJFUlJFTjsKPiArCXUzMiBtYXhfcGFja2V0X3NpemUg PSAwOwo+ICsJdTMyIGVwX2NmZyA9IDA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmICghcHJpdl9l cC0+ZGlyKQo+ICsJCWludGVycnVwdF9tYXNrIHw9IEVQX1NUU19FTl9ERVNDTUlTRU47Cj4gKwo+ ICsJaWYgKHByaXZfZXAtPnR5cGUgPT0gVVNCX0VORFBPSU5UX1hGRVJfSU5UKSB7Cgp5b3UgY2Fu IHR1cm4gdGlzIGludG8gYSBzd2l0Y2ggc3RhdGVtZW50LiBJdCdsbCBsb29rIG5pY2VyCgo+ICsJ CWVwX2NmZyA9IEVQX0NGR19FUFRZUEUoVVNCX0VORFBPSU5UX1hGRVJfSU5UKTsKPiArCX0gZWxz ZSBpZiAocHJpdl9lcC0+dHlwZSA9PSBVU0JfRU5EUE9JTlRfWEZFUl9CVUxLKSB7Cj4gKwkJZXBf Y2ZnID0gRVBfQ0ZHX0VQVFlQRShVU0JfRU5EUE9JTlRfWEZFUl9CVUxLKTsKPiArCX0gZWxzZSB7 Cj4gKwkJZXBfY2ZnID0gRVBfQ0ZHX0VQVFlQRShVU0JfRU5EUE9JTlRfWEZFUl9JU09DKTsKPiAr CQlpbnRlcnJ1cHRfbWFzayA9IDB4RkZGRkZGRkY7Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChwcml2 X2Rldi0+Z2FkZ2V0LnNwZWVkKSB7Cj4gKwljYXNlIFVTQl9TUEVFRF9GVUxMOgo+ICsJCW1heF9w YWNrZXRfc2l6ZSA9IGlzX2lzb19lcCA/IDEwMjMgOiA2NDsKPiArCQlicmVhazsKPiArCWNhc2Ug VVNCX1NQRUVEX0hJR0g6Cj4gKwkJbWF4X3BhY2tldF9zaXplID0gaXNfaXNvX2VwID8gMTAyNCA6 IDUxMjsKPiArCQlicmVhazsKPiArCWNhc2UgVVNCX1NQRUVEX1NVUEVSOgo+ICsJCW1heF9wYWNr ZXRfc2l6ZSA9IDEwMjQ7Cj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCS8qIGFsbCBvdGhl ciBzcGVlZCBhcmUgbm90IHN1cHBvcnRlZCAqLwo+ICsJCXJldHVybjsKPiArCX0KPiArCj4gKwly ZXQgPSBjZG5zM19lcF9vbmNoaXBfYnVmZmVyX3Jlc2VydmUocHJpdl9kZXYsIENETlMzX0VQX0JV Rl9TSVpFKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKHByaXZfZGV2LT5kZXYsICJvbmNo aXAgbWVtIGlzIGZ1bGwsIGVwIGlzIGludmFsaWRcbiIpOwo+ICsJCXJldHVybjsKPiArCX0KPiAr Cj4gKwllcF9jZmcgfD0gRVBfQ0ZHX01BWFBLVFNJWkUobWF4X3BhY2tldF9zaXplKSB8Cj4gKwkJ ICBFUF9DRkdfQlVGRkVSSU5HKENETlMzX0VQX0JVRl9TSVpFIC0gMSkgfAo+ICsJCSAgRVBfQ0ZH X01BWEJVUlNUKHByaXZfZXAtPmVuZHBvaW50Lm1heGJ1cnN0KTsKPiArCj4gKwljZG5zM19zZWxl Y3RfZXAocHJpdl9kZXYsIGJFbmRwb2ludEFkZHJlc3MpOwo+ICsKPiArCXdyaXRlbChlcF9jZmcs ICZwcml2X2Rldi0+cmVncy0+ZXBfY2ZnKTsKPiArCXdyaXRlbChpbnRlcnJ1cHRfbWFzaywgJnBy aXZfZGV2LT5yZWdzLT5lcF9zdHNfZW4pOwo+ICsKPiArCWRldl9kYmcocHJpdl9kZXYtPmRldiwg IkNvbmZpZ3VyZSAlczogd2l0aCB2YWwgJTA4eFxuIiwKPiArCQlwcml2X2VwLT5uYW1lLCBlcF9j ZmcpOwo+ICsKPiArCS8qIGVuYWJsZSBpbnRlcnJ1cHQgZm9yIHNlbGVjdGVkIGVuZHBvaW50ICov Cj4gKwljZG5zM19zZXRfcmVnaXN0ZXJfYml0KCZwcml2X2Rldi0+cmVncy0+ZXBfaWVuLAo+ICsJ CQkgICAgICAgY2RuczNfZXBfYWRkcl90b19iaXRfcG9zKGJFbmRwb2ludEFkZHJlc3MpKTsKPiAr fQo= From mboxrd@z Thu Jan 1 00:00:00 1970 From: Felipe Balbi Subject: Re: [PATCH v1 2/2] usb:cdns3 Add Cadence USB3 DRD Driver Date: Tue, 11 Dec 2018 14:14:04 +0200 Message-ID: <87h8fkmfar.fsf@linux.intel.com> References: <1544445555-17325-1-git-send-email-pawell@cadence.com> <1544445555-17325-3-git-send-email-pawell@cadence.com> Mime-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" Return-path: In-Reply-To: <1544445555-17325-3-git-send-email-pawell@cadence.com> Sender: linux-kernel-owner@vger.kernel.org To: devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, rogerq@ti.com, 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, Pawel Laszczak List-Id: devicetree@vger.kernel.org --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Hi, Pawel Laszczak writes: > +static int cdns3_probe(struct platform_device *pdev) > +{ > + struct device *dev =3D &pdev->dev; > + struct resource *res; > + struct cdns3 *cdns; > + void __iomem *regs; > + int ret; > + > + cdns =3D devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); > + if (!cdns) > + return -ENOMEM; > + > + cdns->dev =3D dev; > + > + platform_set_drvdata(pdev, cdns); > + > + res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0); > + if (!res) { > + dev_err(dev, "missing IRQ\n"); > + return -ENODEV; > + } > + cdns->irq =3D res->start; > + > + cdns->xhci_res[0] =3D *res; > + > + /* > + * Request memory region > + * region-0: xHCI > + * region-1: Peripheral > + * region-2: OTG registers > + */ > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); > + cdns->xhci_res[1] =3D *res; > + > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 1); > + regs =3D devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->dev_regs =3D regs; > + > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 2); > + regs =3D devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->otg_regs =3D regs; > + > + mutex_init(&cdns->mutex); > + > + cdns->phy =3D devm_phy_get(dev, "cdns3,usbphy"); > + if (IS_ERR(cdns->phy)) { > + ret =3D PTR_ERR(cdns->phy); > + if (ret =3D=3D -ENOSYS || ret =3D=3D -ENODEV) { Are you sure you can get ENOSYS here? Have you checked output of checkpatch --strict? =2D:852: WARNING: ENOSYS means 'invalid syscall nr' and nothing else > +#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 */ please no TODO stubs. Just get rid of your dev_pm_ops if you don't implement them. Come up with a later patch adding a proper implementation for PM. > +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_platform_driver() > diff --git a/drivers/usb/cdns3/debug.h b/drivers/usb/cdns3/debug.h > new file mode 100644 > index 000000000000..afb81d224718 > --- /dev/null > +++ b/drivers/usb/cdns3/debug.h > @@ -0,0 +1,346 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Cadence USBSS DRD Driver. > + * Debug header file. > + * > + * Copyright (C) 2018 Cadence. > + * > + * Author: Pawel Laszczak > + */ > +#ifndef __LINUX_CDNS3_DEBUG > +#define __LINUX_CDNS3_DEBUG > +#include "gadget.h" > + > +static inline void cdns3_decode_get_status(u8 bRequestType, u16 wIndex, > + u16 wLength, char *str) > +{ > + switch (bRequestType & USB_RECIP_MASK) { > + case USB_RECIP_INTERFACE: > + sprintf(str, "Get Interface Status Intf =3D %d, L: =3D %d", > + wIndex, wLength); > + break; > + case USB_RECIP_ENDPOINT: > + sprintf(str, "Get Endpoint Status ep%d%s", > + wIndex & ~USB_DIR_IN, > + wIndex & USB_DIR_IN ? "in" : "out"); > + break; > + } > +} > + > +static inline const char *cdns3_decode_device_feature(u16 wValue) > +{ > + switch (wValue) { > + case USB_DEVICE_SELF_POWERED: > + return "Self Powered"; > + case USB_DEVICE_REMOTE_WAKEUP: > + return "Remote Wakeup"; > + case USB_DEVICE_TEST_MODE: > + return "Test Mode"; > + case USB_DEVICE_U1_ENABLE: > + return "U1 Enable"; > + case USB_DEVICE_U2_ENABLE: > + return "U2 Enable"; > + case USB_DEVICE_LTM_ENABLE: > + return "LTM Enable"; > + default: > + return "UNKNOWN"; > + } > +} > + > +static inline const char *cdns3_decode_test_mode(u16 wIndex) > +{ > + switch (wIndex) { > + case TEST_J: > + return ": TEST_J"; > + case TEST_K: > + return ": TEST_K"; > + case TEST_SE0_NAK: > + return ": TEST_SE0_NAK"; > + case TEST_PACKET: > + return ": TEST_PACKET"; > + case TEST_FORCE_EN: > + return ": TEST_FORCE_EN"; > + default: > + return ": UNKNOWN"; > + } > +} > + > +static inline void cdns3_decode_set_clear_feature(u8 bRequestType, u8 bR= equest, > + u16 wValue, u16 wIndex, > + char *str) > +{ > + switch (bRequestType & USB_RECIP_MASK) { > + case USB_RECIP_DEVICE: > + sprintf(str, "%s Device Feature(%s%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + cdns3_decode_device_feature(wValue), > + wValue =3D=3D USB_DEVICE_TEST_MODE ? > + cdns3_decode_test_mode(wIndex) : ""); > + break; > + case USB_RECIP_INTERFACE: > + sprintf(str, "%s Interface Feature(%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + wIndex =3D=3D USB_INTRF_FUNC_SUSPEND ? > + "Function Suspend" : "UNKNOWN"); > + break; > + case USB_RECIP_ENDPOINT: > + sprintf(str, "%s Endpoint Feature(%s ep%d%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + wIndex =3D=3D USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", > + wIndex & ~USB_DIR_IN, > + wIndex & USB_DIR_IN ? "in" : "out"); > + break; > + } > +} > + > +static inline const char *cdns3_decode_descriptor(u16 wValue) > +{ > + switch (wValue >> 8) { > + case USB_DT_DEVICE: > + return "Device"; > + case USB_DT_CONFIG: > + return "Configuration"; > + case USB_DT_STRING: > + return "String"; > + case USB_DT_INTERFACE: > + return "Interface"; > + case USB_DT_ENDPOINT: > + return "Endpoint"; > + case USB_DT_DEVICE_QUALIFIER: > + return "Device Qualifier"; > + case USB_DT_OTHER_SPEED_CONFIG: > + return "Other Speed Config"; > + case USB_DT_INTERFACE_POWER: > + return "Interface Power"; > + case USB_DT_OTG: > + return "OTG"; > + case USB_DT_DEBUG: > + return "Debug"; > + case USB_DT_INTERFACE_ASSOCIATION: > + return "Interface Association"; > + case USB_DT_BOS: > + return "BOS"; > + case USB_DT_DEVICE_CAPABILITY: > + return "Device Capability"; > + case USB_DT_SS_ENDPOINT_COMP: > + return "SS Endpoint Companion"; > + case USB_DT_SSP_ISOC_ENDPOINT_COMP: > + return "SSP Isochronous Endpoint Companion"; > + default: > + return "UNKNOWN"; > + } > +} > + > +/** > + * cdns3_decode_ctrl - returns a string represetion of ctrl request > + */ > +static inline const char *cdns3_decode_ctrl(char *str, u8 bRequestType, > + u8 bRequest, u16 wValue, > + u16 wIndex, u16 wLength) > +{ > + switch (bRequest) { > + case USB_REQ_GET_STATUS: > + cdns3_decode_get_status(bRequestType, wIndex, > + wLength, str); > + break; > + case USB_REQ_CLEAR_FEATURE: > + case USB_REQ_SET_FEATURE: > + cdns3_decode_set_clear_feature(bRequestType, bRequest, > + wValue, wIndex, str); > + break; > + case USB_REQ_SET_ADDRESS: > + sprintf(str, "Set Address Addr: %02x", wValue); > + break; > + case USB_REQ_GET_DESCRIPTOR: > + sprintf(str, "GET %s Descriptor I: %d, L: %d", > + cdns3_decode_descriptor(wValue), > + wValue & 0xff, wLength); > + break; > + case USB_REQ_SET_DESCRIPTOR: > + sprintf(str, "SET %s Descriptor I: %d, L: %d", > + cdns3_decode_descriptor(wValue), > + wValue & 0xff, wLength); > + break; > + case USB_REQ_GET_CONFIGURATION: > + sprintf(str, "Get Configuration L: %d", wLength); > + break; > + case USB_REQ_SET_CONFIGURATION: > + sprintf(str, "Set Configuration Config: %d ", wValue); > + break; > + case USB_REQ_GET_INTERFACE: > + sprintf(str, "Get Interface Intf: %d, L: %d", wIndex, wLength); > + break; > + case USB_REQ_SET_INTERFACE: > + sprintf(str, "Set Interface Intf: %d, Alt: %d", wIndex, wValue); > + break; > + case USB_REQ_SYNCH_FRAME: > + sprintf(str, "Synch Frame Ep: %d, L: %d", wIndex, wLength); > + break; > + case USB_REQ_SET_SEL: > + sprintf(str, "Set SEL L: %d", wLength); > + break; > + case USB_REQ_SET_ISOCH_DELAY: > + sprintf(str, "Set Isochronous Delay Delay: %d ns", wValue); > + break; > + default: > + sprintf(str, > + "SETUP BRT: %02x BR: %02x V: %04x I: %04x L: %04x\n", > + bRequestType, bRequest, > + wValue, wIndex, wLength); > + } > + > + return str; > +} All of these are a flat out copy of dwc3's implementation. It's much, much better to turn dwc3's implementation into a generic, reusable library function then spinning your own as a duplicated effort. > diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c > new file mode 100644 > index 000000000000..1ef0e9f73e3e > --- /dev/null > +++ b/drivers/usb/cdns3/ep0.c > @@ -0,0 +1,864 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Cadence USBSS DRD Driver - gadget side. > + * > + * Copyright (C) 2018 Cadence Design Systems. > + * Copyright (C) 2017-2018 NXP > + * > + * Authors: Pawel Jez , > + * Pawel Laszczak > + * Peter Chen > + */ > + > +#include > + > +#include "gadget.h" > +#include "trace.h" > + > +static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc =3D { > + .bLength =3D USB_DT_ENDPOINT_SIZE, > + .bDescriptorType =3D USB_DT_ENDPOINT, > + .bmAttributes =3D USB_ENDPOINT_XFER_CONTROL, > +}; > + > +/** > + * cdns3_ep0_run_transfer - Do transfer on default endpoint hardware > + * @priv_dev: extended gadget object > + * @dma_addr: physical address where data is/will be stored > + * @length: data length > + * @erdy: set it to 1 when ERDY packet should be sent - > + * exit from flow control state > + */ > +static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, > + dma_addr_t dma_addr, > + unsigned int length, int erdy) > +{ > + struct cdns3_usb_regs __iomem *regs =3D priv_dev->regs; > + struct cdns3_endpoint *priv_ep =3D ep_to_cdns3_ep(priv_dev->gadget.ep0); > + > + priv_dev->ep0_trb->buffer =3D TRB_BUFFER(dma_addr); > + priv_dev->ep0_trb->length =3D TRB_LEN(length); > + priv_dev->ep0_trb->control =3D TRB_CYCLE | TRB_IOC | TRB_TYPE(TRB_NORMA= L); > + > + trace_cdns3_prepare_trb(priv_ep, priv_dev->ep0_trb); > + > + cdns3_select_ep(priv_dev, priv_dev->ep0_data_dir); > + > + writel(EP_STS_TRBERR, ®s->ep_sts); > + writel(EP_TRADDR_TRADDR(priv_dev->ep0_trb_dma), ®s->ep_traddr); > + trace_cdns3_doorbell_ep0(priv_dev->ep0_data_dir ? "ep0in" : "ep0out"); > + > + /* TRB should be prepared before starting transfer */ > + writel(EP_CMD_DRDY, ®s->ep_cmd); > + > + if (erdy) > + writel(EP_CMD_ERDY, &priv_dev->regs->ep_cmd); > +} > + > +/** > + * cdns3_ep0_delegate_req - Returns status of handling setup packet > + * Setup is handled by gadget driver > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns zero on success or negative value on failure > + */ > +static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + spin_unlock(&priv_dev->lock); > + priv_dev->setup_pending =3D 1; > + ret =3D priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); > + priv_dev->setup_pending =3D 0; > + spin_lock(&priv_dev->lock); > + return ret; > +} > + > +static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) > +{ > + priv_dev->ep0_data_dir =3D 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, > + sizeof(struct usb_ctrlrequest), 0); > +} > + > +/** > + * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB= request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, USB_GADGET_DELAYED_STATUS on deferred status st= age, > + * error code on error > + */ > +static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state =3D priv_dev->gadget.state; > + struct cdns3_endpoint *priv_ep; > + u32 config =3D le16_to_cpu(ctrl_req->wValue); > + int result =3D 0; > + int i; > + > + switch (device_state) { > + case USB_STATE_ADDRESS: > + /* Configure non-control EPs */ > + for (i =3D 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) { > + priv_ep =3D priv_dev->eps[i]; > + if (!priv_ep) > + continue; > + > + if (priv_ep->flags & EP_CLAIMED) > + cdns3_ep_config(priv_ep); > + } > + > + result =3D cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (result) > + return result; > + > + if (config) { > + cdns3_set_hw_configuration(priv_dev); > + } else { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); this is wrong. If address is zero, state should be default, not addressed. Addressed would be used on the other branch here, when you have a non-zero address > + } > + break; > + case USB_STATE_CONFIGURED: where do you set this state? > +static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + enum usb_device_state state; > + enum usb_device_speed speed; > + int ret =3D 0; > + u32 wValue; > + u32 wIndex; > + u16 tmode; > + > + wValue =3D le16_to_cpu(ctrl->wValue); > + wIndex =3D le16_to_cpu(ctrl->wIndex); > + state =3D priv_dev->gadget.state; > + speed =3D priv_dev->gadget.speed; > + > + switch (ctrl->wValue) { > + case USB_DEVICE_REMOTE_WAKEUP: > + priv_dev->wake_up_flag =3D !!set; > + break; > + case USB_DEVICE_U1_ENABLE: > + if (state !=3D USB_STATE_CONFIGURED || speed !=3D USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u1_allowed =3D !!set; > + break; > + case USB_DEVICE_U2_ENABLE: > + if (state !=3D USB_STATE_CONFIGURED || speed !=3D USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u2_allowed =3D !!set; > + break; > + case USB_DEVICE_LTM_ENABLE: > + ret =3D -EINVAL; > + break; > + case USB_DEVICE_TEST_MODE: > + if (state !=3D USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) > + return -EINVAL; > + > + tmode =3D le16_to_cpu(ctrl->wIndex); > + > + if (!set || (tmode & 0xff) !=3D 0) > + return -EINVAL; > + > + switch (tmode >> 8) { > + case TEST_J: > + case TEST_K: > + case TEST_SE0_NAK: > + case TEST_PACKET: > + cdns3_set_register_bit(&priv_dev->regs->usb_cmd, > + USB_CMD_STMODE | > + USB_STS_TMODE_SEL(tmode - 1)); I'm 90% sure this won't work. There's a reason why we only enter the requested test mode from status stage. How have you tested this? > diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c > new file mode 100644 > index 000000000000..a021eaf07aee > --- /dev/null > +++ b/drivers/usb/cdns3/gadget.c > +struct usb_request *cdns3_next_request(struct list_head *list) > +{ > + if (list_empty(list)) > + return NULL; > + return list_first_entry(list, struct usb_request, list); list_first_entry_or_null() > +void cdns3_gadget_unconfig(struct cdns3_device *priv_dev) > +{ > + /* RESET CONFIGURATION */ > + writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf); > + > + cdns3_allow_enable_l1(priv_dev, 0); > + priv_dev->hw_configured_flag =3D 0; > + priv_dev->onchip_mem_allocated_size =3D 0; clear all test modes? Reset ep0 max_packet_size to 512? > +static irqreturn_t cdns3_device_irq_handler(int irq, void *data) > +{ > + struct cdns3_device *priv_dev; > + struct cdns3 *cdns =3D data; > + irqreturn_t ret =3D IRQ_NONE; > + unsigned long flags; > + u32 reg; > + > + priv_dev =3D cdns->gadget_dev; > + spin_lock_irqsave(&priv_dev->lock, flags); you're already running in hardirq context. Why do you need this lock at all? I would be better to use the hardirq handler to mask your interrupts, so they don't fire again, then used the top-half (softirq) handler to actually handle the interrupts. > + /* check USB device interrupt */ > + reg =3D readl(&priv_dev->regs->usb_ists); > + writel(reg, &priv_dev->regs->usb_ists); > + > + if (reg) { > + dev_dbg(priv_dev->dev, "IRQ: usb_ists: %08X\n", reg); I strongly advise against using dev_dbg() for debugging. Even more so inside your IRQ handler. > + cdns3_check_usb_interrupt_proceed(priv_dev, reg); > + ret =3D IRQ_HANDLED; > + } > + > + /* check endpoint interrupt */ > + reg =3D readl(&priv_dev->regs->ep_ists); > + > + /* handle default endpoint OUT */ > + if (reg & EP_ISTS_EP_OUT0) { > + cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_OUT); > + ret =3D IRQ_HANDLED; > + } > + > + /* handle default endpoint IN */ > + if (reg & EP_ISTS_EP_IN0) { > + cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_IN); > + ret =3D IRQ_HANDLED; > + } > + > + /* check if interrupt from non default endpoint, if no exit */ > + reg &=3D ~(EP_ISTS_EP_OUT0 | EP_ISTS_EP_IN0); > + if (!reg) > + goto irqend; > + > + do { > + unsigned int bit_pos =3D ffs(reg); > + u32 bit_mask =3D 1 << (bit_pos - 1); > + int index; > + > + index =3D cdns3_ep_reg_pos_to_index(bit_pos); > + cdns3_check_ep_interrupt_proceed(priv_dev->eps[index]); > + reg &=3D ~bit_mask; > + ret =3D IRQ_HANDLED; > + } while (reg); use for_each_set_bit() here. > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep) > +{ > + bool is_iso_ep =3D (priv_ep->type =3D=3D USB_ENDPOINT_XFER_ISOC); > + struct cdns3_device *priv_dev =3D priv_ep->cdns3_dev; > + u32 bEndpointAddress =3D priv_ep->num | priv_ep->dir; > + u32 interrupt_mask =3D EP_STS_EN_TRBERREN; > + u32 max_packet_size =3D 0; > + u32 ep_cfg =3D 0; > + int ret; > + > + if (!priv_ep->dir) > + interrupt_mask |=3D EP_STS_EN_DESCMISEN; > + > + if (priv_ep->type =3D=3D USB_ENDPOINT_XFER_INT) { you can turn tis into a switch statement. It'll look nicer > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT); > + } else if (priv_ep->type =3D=3D USB_ENDPOINT_XFER_BULK) { > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK); > + } else { > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); > + interrupt_mask =3D 0xFFFFFFFF; > + } > + > + switch (priv_dev->gadget.speed) { > + case USB_SPEED_FULL: > + max_packet_size =3D is_iso_ep ? 1023 : 64; > + break; > + case USB_SPEED_HIGH: > + max_packet_size =3D is_iso_ep ? 1024 : 512; > + break; > + case USB_SPEED_SUPER: > + max_packet_size =3D 1024; > + break; > + default: > + /* all other speed are not supported */ > + return; > + } > + > + ret =3D cdns3_ep_onchip_buffer_reserve(priv_dev, CDNS3_EP_BUF_SIZE); > + if (ret) { > + dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n"); > + return; > + } > + > + ep_cfg |=3D EP_CFG_MAXPKTSIZE(max_packet_size) | > + EP_CFG_BUFFERING(CDNS3_EP_BUF_SIZE - 1) | > + EP_CFG_MAXBURST(priv_ep->endpoint.maxburst); > + > + cdns3_select_ep(priv_dev, bEndpointAddress); > + > + writel(ep_cfg, &priv_dev->regs->ep_cfg); > + writel(interrupt_mask, &priv_dev->regs->ep_sts_en); > + > + dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n", > + priv_ep->name, ep_cfg); > + > + /* enable interrupt for selected endpoint */ > + cdns3_set_register_bit(&priv_dev->regs->ep_ien, > + cdns3_ep_addr_to_bit_pos(bEndpointAddress)); > +} =2D-=20 balbi --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEElLzh7wn96CXwjh2IzL64meEamQYFAlwPqgwACgkQzL64meEa mQauLQ/+OSVX4rrN+PWm0vc2XDCEpbkmJ2wy7rDD8PbDBPQWYYjRoW0wNPl8DKTQ lTxsUYPyPQ/OtxJWqQ9a/d6DDDCTx1i3NJb6zYvxYc4Ihf45yRdIabnkTtEJzTWW Lt7DO0WKPi+kKWS3UupZ9IGKLVHFFMSnjIolCdXpc1fARdFhlvR0VmTK2A/kc61k /IT0txaa7wDOiSevDPKenbgDIQ7an8oQwqD6Ll997ZJTj3CjRWh11a3OPQgLm4XY ftwlYVhAm3rznNIHTJqmV+jW9YJMw+0EQWuCpqVLBEtcflm8ZHsi5AY1/bYXVGIh zvExG7mS03TIY2x0kmLCuT/nKADEtqB3Jwaq2Pc8a3ncdK0su5PEJ8GDDa36owdz DHHHMvMJMr7fxMe1mNUb1glcScWgG4YWVgC6udv2ZbbCAh+LG7F2yWVyUeUeHR3C p09aVHVnGgBL+1E+FvxrOUo8l46C45JT73Yv78resl6yZoT7Vav+xbNOxbPLLVUi EYHB8zTzj1G3zYGe15lOiRkSshq6v8kyKDfmetVSFSNb/57U1umhVyW9WE1IaQEI RWg/E7X2ahaCIxPdaRVuyEQ5SEi3U0yv10dVadxT4w3gV3LwAkquQGhqi8w3A8wT fzL54aBC6kZppf08TXQgcNnJS8kYPbf4HKu1QL3Tabkpon4iK34= =F3Gz -----END PGP SIGNATURE----- --=-=-=-- 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=-4.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,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 AC2FBC07E85 for ; Tue, 11 Dec 2018 12:14:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3323120811 for ; Tue, 11 Dec 2018 12:14:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1544530459; bh=gK2AzgYpqK3zcvA/bnshyuoPJeSxGwCBj82/yP1gGW4=; h=From:To:Cc:Subject:In-Reply-To:References:Date:List-ID:From; b=ouJ/gsgBoKsPIWqrF43g68z5TfKu8U1CUCz5HgxQnydeDadKmfkmVXcya8a8oasvK rBmBMwKAY9/7i1oGdHDXg8ES1gwhdZGSudbNPl+shb2MLBUjMTurrp8+m5L53rtLu4 f0IKgDyl1HGewnxdoQlIxOLrj7K4bsBsU48T13Ts= DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3323120811 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org 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 S1726311AbeLKMOR (ORCPT ); Tue, 11 Dec 2018 07:14:17 -0500 Received: from mga12.intel.com ([192.55.52.136]:36956 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726135AbeLKMOQ (ORCPT ); Tue, 11 Dec 2018 07:14:16 -0500 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Dec 2018 04:14:12 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,342,1539673200"; d="asc'?scan'208";a="117844849" Received: from pipin.fi.intel.com (HELO localhost) ([10.237.72.175]) by orsmga001.jf.intel.com with ESMTP; 11 Dec 2018 04:14:08 -0800 From: Felipe Balbi To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, rogerq@ti.com, 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, Pawel Laszczak Subject: Re: [PATCH v1 2/2] usb:cdns3 Add Cadence USB3 DRD Driver In-Reply-To: <1544445555-17325-3-git-send-email-pawell@cadence.com> References: <1544445555-17325-1-git-send-email-pawell@cadence.com> <1544445555-17325-3-git-send-email-pawell@cadence.com> Date: Tue, 11 Dec 2018 14:14:04 +0200 Message-ID: <87h8fkmfar.fsf@linux.intel.com> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Hi, Pawel Laszczak writes: > +static int cdns3_probe(struct platform_device *pdev) > +{ > + struct device *dev =3D &pdev->dev; > + struct resource *res; > + struct cdns3 *cdns; > + void __iomem *regs; > + int ret; > + > + cdns =3D devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL); > + if (!cdns) > + return -ENOMEM; > + > + cdns->dev =3D dev; > + > + platform_set_drvdata(pdev, cdns); > + > + res =3D platform_get_resource(pdev, IORESOURCE_IRQ, 0); > + if (!res) { > + dev_err(dev, "missing IRQ\n"); > + return -ENODEV; > + } > + cdns->irq =3D res->start; > + > + cdns->xhci_res[0] =3D *res; > + > + /* > + * Request memory region > + * region-0: xHCI > + * region-1: Peripheral > + * region-2: OTG registers > + */ > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); > + cdns->xhci_res[1] =3D *res; > + > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 1); > + regs =3D devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->dev_regs =3D regs; > + > + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 2); > + regs =3D devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + cdns->otg_regs =3D regs; > + > + mutex_init(&cdns->mutex); > + > + cdns->phy =3D devm_phy_get(dev, "cdns3,usbphy"); > + if (IS_ERR(cdns->phy)) { > + ret =3D PTR_ERR(cdns->phy); > + if (ret =3D=3D -ENOSYS || ret =3D=3D -ENODEV) { Are you sure you can get ENOSYS here? Have you checked output of checkpatch --strict? =2D:852: WARNING: ENOSYS means 'invalid syscall nr' and nothing else > +#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 */ please no TODO stubs. Just get rid of your dev_pm_ops if you don't implement them. Come up with a later patch adding a proper implementation for PM. > +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_platform_driver() > diff --git a/drivers/usb/cdns3/debug.h b/drivers/usb/cdns3/debug.h > new file mode 100644 > index 000000000000..afb81d224718 > --- /dev/null > +++ b/drivers/usb/cdns3/debug.h > @@ -0,0 +1,346 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Cadence USBSS DRD Driver. > + * Debug header file. > + * > + * Copyright (C) 2018 Cadence. > + * > + * Author: Pawel Laszczak > + */ > +#ifndef __LINUX_CDNS3_DEBUG > +#define __LINUX_CDNS3_DEBUG > +#include "gadget.h" > + > +static inline void cdns3_decode_get_status(u8 bRequestType, u16 wIndex, > + u16 wLength, char *str) > +{ > + switch (bRequestType & USB_RECIP_MASK) { > + case USB_RECIP_INTERFACE: > + sprintf(str, "Get Interface Status Intf =3D %d, L: =3D %d", > + wIndex, wLength); > + break; > + case USB_RECIP_ENDPOINT: > + sprintf(str, "Get Endpoint Status ep%d%s", > + wIndex & ~USB_DIR_IN, > + wIndex & USB_DIR_IN ? "in" : "out"); > + break; > + } > +} > + > +static inline const char *cdns3_decode_device_feature(u16 wValue) > +{ > + switch (wValue) { > + case USB_DEVICE_SELF_POWERED: > + return "Self Powered"; > + case USB_DEVICE_REMOTE_WAKEUP: > + return "Remote Wakeup"; > + case USB_DEVICE_TEST_MODE: > + return "Test Mode"; > + case USB_DEVICE_U1_ENABLE: > + return "U1 Enable"; > + case USB_DEVICE_U2_ENABLE: > + return "U2 Enable"; > + case USB_DEVICE_LTM_ENABLE: > + return "LTM Enable"; > + default: > + return "UNKNOWN"; > + } > +} > + > +static inline const char *cdns3_decode_test_mode(u16 wIndex) > +{ > + switch (wIndex) { > + case TEST_J: > + return ": TEST_J"; > + case TEST_K: > + return ": TEST_K"; > + case TEST_SE0_NAK: > + return ": TEST_SE0_NAK"; > + case TEST_PACKET: > + return ": TEST_PACKET"; > + case TEST_FORCE_EN: > + return ": TEST_FORCE_EN"; > + default: > + return ": UNKNOWN"; > + } > +} > + > +static inline void cdns3_decode_set_clear_feature(u8 bRequestType, u8 bR= equest, > + u16 wValue, u16 wIndex, > + char *str) > +{ > + switch (bRequestType & USB_RECIP_MASK) { > + case USB_RECIP_DEVICE: > + sprintf(str, "%s Device Feature(%s%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + cdns3_decode_device_feature(wValue), > + wValue =3D=3D USB_DEVICE_TEST_MODE ? > + cdns3_decode_test_mode(wIndex) : ""); > + break; > + case USB_RECIP_INTERFACE: > + sprintf(str, "%s Interface Feature(%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + wIndex =3D=3D USB_INTRF_FUNC_SUSPEND ? > + "Function Suspend" : "UNKNOWN"); > + break; > + case USB_RECIP_ENDPOINT: > + sprintf(str, "%s Endpoint Feature(%s ep%d%s)", > + bRequest =3D=3D USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", > + wIndex =3D=3D USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", > + wIndex & ~USB_DIR_IN, > + wIndex & USB_DIR_IN ? "in" : "out"); > + break; > + } > +} > + > +static inline const char *cdns3_decode_descriptor(u16 wValue) > +{ > + switch (wValue >> 8) { > + case USB_DT_DEVICE: > + return "Device"; > + case USB_DT_CONFIG: > + return "Configuration"; > + case USB_DT_STRING: > + return "String"; > + case USB_DT_INTERFACE: > + return "Interface"; > + case USB_DT_ENDPOINT: > + return "Endpoint"; > + case USB_DT_DEVICE_QUALIFIER: > + return "Device Qualifier"; > + case USB_DT_OTHER_SPEED_CONFIG: > + return "Other Speed Config"; > + case USB_DT_INTERFACE_POWER: > + return "Interface Power"; > + case USB_DT_OTG: > + return "OTG"; > + case USB_DT_DEBUG: > + return "Debug"; > + case USB_DT_INTERFACE_ASSOCIATION: > + return "Interface Association"; > + case USB_DT_BOS: > + return "BOS"; > + case USB_DT_DEVICE_CAPABILITY: > + return "Device Capability"; > + case USB_DT_SS_ENDPOINT_COMP: > + return "SS Endpoint Companion"; > + case USB_DT_SSP_ISOC_ENDPOINT_COMP: > + return "SSP Isochronous Endpoint Companion"; > + default: > + return "UNKNOWN"; > + } > +} > + > +/** > + * cdns3_decode_ctrl - returns a string represetion of ctrl request > + */ > +static inline const char *cdns3_decode_ctrl(char *str, u8 bRequestType, > + u8 bRequest, u16 wValue, > + u16 wIndex, u16 wLength) > +{ > + switch (bRequest) { > + case USB_REQ_GET_STATUS: > + cdns3_decode_get_status(bRequestType, wIndex, > + wLength, str); > + break; > + case USB_REQ_CLEAR_FEATURE: > + case USB_REQ_SET_FEATURE: > + cdns3_decode_set_clear_feature(bRequestType, bRequest, > + wValue, wIndex, str); > + break; > + case USB_REQ_SET_ADDRESS: > + sprintf(str, "Set Address Addr: %02x", wValue); > + break; > + case USB_REQ_GET_DESCRIPTOR: > + sprintf(str, "GET %s Descriptor I: %d, L: %d", > + cdns3_decode_descriptor(wValue), > + wValue & 0xff, wLength); > + break; > + case USB_REQ_SET_DESCRIPTOR: > + sprintf(str, "SET %s Descriptor I: %d, L: %d", > + cdns3_decode_descriptor(wValue), > + wValue & 0xff, wLength); > + break; > + case USB_REQ_GET_CONFIGURATION: > + sprintf(str, "Get Configuration L: %d", wLength); > + break; > + case USB_REQ_SET_CONFIGURATION: > + sprintf(str, "Set Configuration Config: %d ", wValue); > + break; > + case USB_REQ_GET_INTERFACE: > + sprintf(str, "Get Interface Intf: %d, L: %d", wIndex, wLength); > + break; > + case USB_REQ_SET_INTERFACE: > + sprintf(str, "Set Interface Intf: %d, Alt: %d", wIndex, wValue); > + break; > + case USB_REQ_SYNCH_FRAME: > + sprintf(str, "Synch Frame Ep: %d, L: %d", wIndex, wLength); > + break; > + case USB_REQ_SET_SEL: > + sprintf(str, "Set SEL L: %d", wLength); > + break; > + case USB_REQ_SET_ISOCH_DELAY: > + sprintf(str, "Set Isochronous Delay Delay: %d ns", wValue); > + break; > + default: > + sprintf(str, > + "SETUP BRT: %02x BR: %02x V: %04x I: %04x L: %04x\n", > + bRequestType, bRequest, > + wValue, wIndex, wLength); > + } > + > + return str; > +} All of these are a flat out copy of dwc3's implementation. It's much, much better to turn dwc3's implementation into a generic, reusable library function then spinning your own as a duplicated effort. > diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c > new file mode 100644 > index 000000000000..1ef0e9f73e3e > --- /dev/null > +++ b/drivers/usb/cdns3/ep0.c > @@ -0,0 +1,864 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Cadence USBSS DRD Driver - gadget side. > + * > + * Copyright (C) 2018 Cadence Design Systems. > + * Copyright (C) 2017-2018 NXP > + * > + * Authors: Pawel Jez , > + * Pawel Laszczak > + * Peter Chen > + */ > + > +#include > + > +#include "gadget.h" > +#include "trace.h" > + > +static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc =3D { > + .bLength =3D USB_DT_ENDPOINT_SIZE, > + .bDescriptorType =3D USB_DT_ENDPOINT, > + .bmAttributes =3D USB_ENDPOINT_XFER_CONTROL, > +}; > + > +/** > + * cdns3_ep0_run_transfer - Do transfer on default endpoint hardware > + * @priv_dev: extended gadget object > + * @dma_addr: physical address where data is/will be stored > + * @length: data length > + * @erdy: set it to 1 when ERDY packet should be sent - > + * exit from flow control state > + */ > +static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, > + dma_addr_t dma_addr, > + unsigned int length, int erdy) > +{ > + struct cdns3_usb_regs __iomem *regs =3D priv_dev->regs; > + struct cdns3_endpoint *priv_ep =3D ep_to_cdns3_ep(priv_dev->gadget.ep0); > + > + priv_dev->ep0_trb->buffer =3D TRB_BUFFER(dma_addr); > + priv_dev->ep0_trb->length =3D TRB_LEN(length); > + priv_dev->ep0_trb->control =3D TRB_CYCLE | TRB_IOC | TRB_TYPE(TRB_NORMA= L); > + > + trace_cdns3_prepare_trb(priv_ep, priv_dev->ep0_trb); > + > + cdns3_select_ep(priv_dev, priv_dev->ep0_data_dir); > + > + writel(EP_STS_TRBERR, ®s->ep_sts); > + writel(EP_TRADDR_TRADDR(priv_dev->ep0_trb_dma), ®s->ep_traddr); > + trace_cdns3_doorbell_ep0(priv_dev->ep0_data_dir ? "ep0in" : "ep0out"); > + > + /* TRB should be prepared before starting transfer */ > + writel(EP_CMD_DRDY, ®s->ep_cmd); > + > + if (erdy) > + writel(EP_CMD_ERDY, &priv_dev->regs->ep_cmd); > +} > + > +/** > + * cdns3_ep0_delegate_req - Returns status of handling setup packet > + * Setup is handled by gadget driver > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns zero on success or negative value on failure > + */ > +static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + spin_unlock(&priv_dev->lock); > + priv_dev->setup_pending =3D 1; > + ret =3D priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); > + priv_dev->setup_pending =3D 0; > + spin_lock(&priv_dev->lock); > + return ret; > +} > + > +static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) > +{ > + priv_dev->ep0_data_dir =3D 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, > + sizeof(struct usb_ctrlrequest), 0); > +} > + > +/** > + * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB= request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, USB_GADGET_DELAYED_STATUS on deferred status st= age, > + * error code on error > + */ > +static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state =3D priv_dev->gadget.state; > + struct cdns3_endpoint *priv_ep; > + u32 config =3D le16_to_cpu(ctrl_req->wValue); > + int result =3D 0; > + int i; > + > + switch (device_state) { > + case USB_STATE_ADDRESS: > + /* Configure non-control EPs */ > + for (i =3D 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) { > + priv_ep =3D priv_dev->eps[i]; > + if (!priv_ep) > + continue; > + > + if (priv_ep->flags & EP_CLAIMED) > + cdns3_ep_config(priv_ep); > + } > + > + result =3D cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (result) > + return result; > + > + if (config) { > + cdns3_set_hw_configuration(priv_dev); > + } else { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); this is wrong. If address is zero, state should be default, not addressed. Addressed would be used on the other branch here, when you have a non-zero address > + } > + break; > + case USB_STATE_CONFIGURED: where do you set this state? > +static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + enum usb_device_state state; > + enum usb_device_speed speed; > + int ret =3D 0; > + u32 wValue; > + u32 wIndex; > + u16 tmode; > + > + wValue =3D le16_to_cpu(ctrl->wValue); > + wIndex =3D le16_to_cpu(ctrl->wIndex); > + state =3D priv_dev->gadget.state; > + speed =3D priv_dev->gadget.speed; > + > + switch (ctrl->wValue) { > + case USB_DEVICE_REMOTE_WAKEUP: > + priv_dev->wake_up_flag =3D !!set; > + break; > + case USB_DEVICE_U1_ENABLE: > + if (state !=3D USB_STATE_CONFIGURED || speed !=3D USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u1_allowed =3D !!set; > + break; > + case USB_DEVICE_U2_ENABLE: > + if (state !=3D USB_STATE_CONFIGURED || speed !=3D USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u2_allowed =3D !!set; > + break; > + case USB_DEVICE_LTM_ENABLE: > + ret =3D -EINVAL; > + break; > + case USB_DEVICE_TEST_MODE: > + if (state !=3D USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) > + return -EINVAL; > + > + tmode =3D le16_to_cpu(ctrl->wIndex); > + > + if (!set || (tmode & 0xff) !=3D 0) > + return -EINVAL; > + > + switch (tmode >> 8) { > + case TEST_J: > + case TEST_K: > + case TEST_SE0_NAK: > + case TEST_PACKET: > + cdns3_set_register_bit(&priv_dev->regs->usb_cmd, > + USB_CMD_STMODE | > + USB_STS_TMODE_SEL(tmode - 1)); I'm 90% sure this won't work. There's a reason why we only enter the requested test mode from status stage. How have you tested this? > diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c > new file mode 100644 > index 000000000000..a021eaf07aee > --- /dev/null > +++ b/drivers/usb/cdns3/gadget.c > +struct usb_request *cdns3_next_request(struct list_head *list) > +{ > + if (list_empty(list)) > + return NULL; > + return list_first_entry(list, struct usb_request, list); list_first_entry_or_null() > +void cdns3_gadget_unconfig(struct cdns3_device *priv_dev) > +{ > + /* RESET CONFIGURATION */ > + writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf); > + > + cdns3_allow_enable_l1(priv_dev, 0); > + priv_dev->hw_configured_flag =3D 0; > + priv_dev->onchip_mem_allocated_size =3D 0; clear all test modes? Reset ep0 max_packet_size to 512? > +static irqreturn_t cdns3_device_irq_handler(int irq, void *data) > +{ > + struct cdns3_device *priv_dev; > + struct cdns3 *cdns =3D data; > + irqreturn_t ret =3D IRQ_NONE; > + unsigned long flags; > + u32 reg; > + > + priv_dev =3D cdns->gadget_dev; > + spin_lock_irqsave(&priv_dev->lock, flags); you're already running in hardirq context. Why do you need this lock at all? I would be better to use the hardirq handler to mask your interrupts, so they don't fire again, then used the top-half (softirq) handler to actually handle the interrupts. > + /* check USB device interrupt */ > + reg =3D readl(&priv_dev->regs->usb_ists); > + writel(reg, &priv_dev->regs->usb_ists); > + > + if (reg) { > + dev_dbg(priv_dev->dev, "IRQ: usb_ists: %08X\n", reg); I strongly advise against using dev_dbg() for debugging. Even more so inside your IRQ handler. > + cdns3_check_usb_interrupt_proceed(priv_dev, reg); > + ret =3D IRQ_HANDLED; > + } > + > + /* check endpoint interrupt */ > + reg =3D readl(&priv_dev->regs->ep_ists); > + > + /* handle default endpoint OUT */ > + if (reg & EP_ISTS_EP_OUT0) { > + cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_OUT); > + ret =3D IRQ_HANDLED; > + } > + > + /* handle default endpoint IN */ > + if (reg & EP_ISTS_EP_IN0) { > + cdns3_check_ep0_interrupt_proceed(priv_dev, USB_DIR_IN); > + ret =3D IRQ_HANDLED; > + } > + > + /* check if interrupt from non default endpoint, if no exit */ > + reg &=3D ~(EP_ISTS_EP_OUT0 | EP_ISTS_EP_IN0); > + if (!reg) > + goto irqend; > + > + do { > + unsigned int bit_pos =3D ffs(reg); > + u32 bit_mask =3D 1 << (bit_pos - 1); > + int index; > + > + index =3D cdns3_ep_reg_pos_to_index(bit_pos); > + cdns3_check_ep_interrupt_proceed(priv_dev->eps[index]); > + reg &=3D ~bit_mask; > + ret =3D IRQ_HANDLED; > + } while (reg); use for_each_set_bit() here. > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep) > +{ > + bool is_iso_ep =3D (priv_ep->type =3D=3D USB_ENDPOINT_XFER_ISOC); > + struct cdns3_device *priv_dev =3D priv_ep->cdns3_dev; > + u32 bEndpointAddress =3D priv_ep->num | priv_ep->dir; > + u32 interrupt_mask =3D EP_STS_EN_TRBERREN; > + u32 max_packet_size =3D 0; > + u32 ep_cfg =3D 0; > + int ret; > + > + if (!priv_ep->dir) > + interrupt_mask |=3D EP_STS_EN_DESCMISEN; > + > + if (priv_ep->type =3D=3D USB_ENDPOINT_XFER_INT) { you can turn tis into a switch statement. It'll look nicer > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT); > + } else if (priv_ep->type =3D=3D USB_ENDPOINT_XFER_BULK) { > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK); > + } else { > + ep_cfg =3D EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); > + interrupt_mask =3D 0xFFFFFFFF; > + } > + > + switch (priv_dev->gadget.speed) { > + case USB_SPEED_FULL: > + max_packet_size =3D is_iso_ep ? 1023 : 64; > + break; > + case USB_SPEED_HIGH: > + max_packet_size =3D is_iso_ep ? 1024 : 512; > + break; > + case USB_SPEED_SUPER: > + max_packet_size =3D 1024; > + break; > + default: > + /* all other speed are not supported */ > + return; > + } > + > + ret =3D cdns3_ep_onchip_buffer_reserve(priv_dev, CDNS3_EP_BUF_SIZE); > + if (ret) { > + dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n"); > + return; > + } > + > + ep_cfg |=3D EP_CFG_MAXPKTSIZE(max_packet_size) | > + EP_CFG_BUFFERING(CDNS3_EP_BUF_SIZE - 1) | > + EP_CFG_MAXBURST(priv_ep->endpoint.maxburst); > + > + cdns3_select_ep(priv_dev, bEndpointAddress); > + > + writel(ep_cfg, &priv_dev->regs->ep_cfg); > + writel(interrupt_mask, &priv_dev->regs->ep_sts_en); > + > + dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n", > + priv_ep->name, ep_cfg); > + > + /* enable interrupt for selected endpoint */ > + cdns3_set_register_bit(&priv_dev->regs->ep_ien, > + cdns3_ep_addr_to_bit_pos(bEndpointAddress)); > +} =2D-=20 balbi --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEElLzh7wn96CXwjh2IzL64meEamQYFAlwPqgwACgkQzL64meEa mQauLQ/+OSVX4rrN+PWm0vc2XDCEpbkmJ2wy7rDD8PbDBPQWYYjRoW0wNPl8DKTQ lTxsUYPyPQ/OtxJWqQ9a/d6DDDCTx1i3NJb6zYvxYc4Ihf45yRdIabnkTtEJzTWW Lt7DO0WKPi+kKWS3UupZ9IGKLVHFFMSnjIolCdXpc1fARdFhlvR0VmTK2A/kc61k /IT0txaa7wDOiSevDPKenbgDIQ7an8oQwqD6Ll997ZJTj3CjRWh11a3OPQgLm4XY ftwlYVhAm3rznNIHTJqmV+jW9YJMw+0EQWuCpqVLBEtcflm8ZHsi5AY1/bYXVGIh zvExG7mS03TIY2x0kmLCuT/nKADEtqB3Jwaq2Pc8a3ncdK0su5PEJ8GDDa36owdz DHHHMvMJMr7fxMe1mNUb1glcScWgG4YWVgC6udv2ZbbCAh+LG7F2yWVyUeUeHR3C p09aVHVnGgBL+1E+FvxrOUo8l46C45JT73Yv78resl6yZoT7Vav+xbNOxbPLLVUi EYHB8zTzj1G3zYGe15lOiRkSshq6v8kyKDfmetVSFSNb/57U1umhVyW9WE1IaQEI RWg/E7X2ahaCIxPdaRVuyEQ5SEi3U0yv10dVadxT4w3gV3LwAkquQGhqi8w3A8wT fzL54aBC6kZppf08TXQgcNnJS8kYPbf4HKu1QL3Tabkpon4iK34= =F3Gz -----END PGP SIGNATURE----- --=-=-=--