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: [V3,5/6] usb: ehci: Add new EHCI driver for Broadcom STB SoC's From: Alan Cooper Message-Id: <1541453493-34981-6-git-send-email-alcooperx@gmail.com> Date: Mon, 5 Nov 2018 16:31:32 -0500 To: linux-kernel@vger.kernel.org Cc: Al Cooper , Alan Stern , Alban Bedel , Alex Elder , Andrew Morton , Arnd Bergmann , Avi Fishman , bcm-kernel-feedback-list@broadcom.com, Bjorn Andersson , Chunfeng Yun , "David S. Miller" , devicetree@vger.kernel.org, Dmitry Osipenko , Greg Kroah-Hartman , "Gustavo A. R. Silva" , Hans de Goede , James Hogan , Jianguo Sun , Johan Hovold , Kees Cook , linux-usb@vger.kernel.org, Lu Baolu , Mark Rutland , Martin Blumenstingl , Mathias Nyman , Mathias Nyman , Mauro Carvalho Chehab , Rishabh Bhatnagar , Rob Herring , Roger Quadros List-ID: QWRkIGEgbmV3IEVIQ0kgZHJpdmVyIGZvciBCcm9hZGNvbSBTVEIgU29DJ3MuIEEgbmV3IEVIQ0kg ZHJpdmVyCndhcyBjcmVhdGVkIGluc3RlYWQgb2YgYWRkaW5nIHN1cHBvcnQgdG8gdGhlIGV4aXN0 aW5nIGVoY2kgcGxhdGZvcm0KZHJpdmVyIGJlY2F1c2Ugb2YgdGhlIGNvZGUgcmVxdWlyZWQgdG8g d29ya2Fyb3VuZCBidWdzIGluIHRoZSBFSENJCmNvbnRyb2xsZXIuCgpTaWduZWQtb2ZmLWJ5OiBB bCBDb29wZXIgPGFsY29vcGVyeEBnbWFpbC5jb20+Ci0tLQogZHJpdmVycy91c2IvaG9zdC9laGNp LWJyY20uYyB8IDI4NyArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr CiAxIGZpbGUgY2hhbmdlZCwgMjg3IGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBk cml2ZXJzL3VzYi9ob3N0L2VoY2ktYnJjbS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvaG9z dC9laGNpLWJyY20uYyBiL2RyaXZlcnMvdXNiL2hvc3QvZWhjaS1icmNtLmMKbmV3IGZpbGUgbW9k ZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5mMzZjZTI0MDUzOGIKLS0tIC9kZXYvbnVsbAor KysgYi9kcml2ZXJzL3VzYi9ob3N0L2VoY2ktYnJjbS5jCkBAIC0wLDAgKzEsMjg3IEBACisvLyBT UERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAorLyogQ29weXJpZ2h0IChjKSAyMDE4LCBC cm9hZGNvbSAqLworCisjaW5jbHVkZSA8bGludXgvYWNwaS5oPgorI2luY2x1ZGUgPGxpbnV4L2Ns ay5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+CisjaW5jbHVkZSA8bGludXgvZXJy Lmg+CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaW8uaD4KKyNp bmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9vZi5oPgorI2luY2x1ZGUg PGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4L3VzYi5oPgorI2luY2x1 ZGUgPGxpbnV4L3VzYi9oY2QuaD4KKworI2luY2x1ZGUgImVoY2kuaCIKKworI2RlZmluZSBCUkNN X0RSSVZFUl9ERVNDICJFSENJIEJyb2FkY29tIFNUQiBkcml2ZXIiCisKKyNkZWZpbmUgaGNkX3Rv X2VoY2lfcHJpdihoKSAoKHN0cnVjdCBicmNtX3ByaXYgKiloY2RfdG9fZWhjaShoKS0+cHJpdikK Kworc3RydWN0IGJyY21fcHJpdiB7CisJc3RydWN0IGNsayAqY2xrOworfTsKKworc3RhdGljIGNv bnN0IGNoYXIgYnJjbV9oY2RfbmFtZVtdID0gImVoY2ktYnJjbSI7CisKK3N0YXRpYyBpbnQgKCpv cmdfaHViX2NvbnRyb2wpKHN0cnVjdCB1c2JfaGNkICpoY2QsCisJCQl1MTYgdHlwZVJlcSwgdTE2 IHdWYWx1ZSwgdTE2IHdJbmRleCwKKwkJCWNoYXIgKmJ1ZiwgdTE2IHdMZW5ndGgpOworCisvKiBl aGNpX2JyY21fd2FpdF9mb3Jfc29mCisgKiBXYWl0IGZvciBzdGFydCBvZiBuZXh0IG1pY3JvZnJh bWUsIHRoZW4gd2FpdCBleHRyYSBkZWxheSBtaWNyb3NlY29uZHMKKyAqLworc3RhdGljIGlubGlu ZSB2b2lkIGVoY2lfYnJjbV93YWl0X2Zvcl9zb2Yoc3RydWN0IGVoY2lfaGNkICplaGNpLCB1MzIg ZGVsYXkpCit7CisJaW50IGZyYW1lX2lkeCA9IGVoY2lfcmVhZGwoZWhjaSwgJmVoY2ktPnJlZ3Mt PmZyYW1lX2luZGV4KTsKKworCXdoaWxlIChmcmFtZV9pZHggPT0gZWhjaV9yZWFkbChlaGNpLCAm ZWhjaS0+cmVncy0+ZnJhbWVfaW5kZXgpKQorCQk7CisJdWRlbGF5KGRlbGF5KTsKK30KKworLyoK KyAqIGVoY2lfYnJjbV9odWJfY29udHJvbAorICogSW50ZXJjZXB0IGVjaGktaGNkIHJlcXVlc3Qg dG8gY29tcGxldGUgUkVTVU1FIGFuZCBhbGlnbiBpdCB0byB0aGUgc3RhcnQKKyAqIG9mIHRoZSBu ZXh0IG1pY3JvZnJhbWUuCisgKiBJZiBSRVNVTUUgaXMgY29tcGxldGUgdG9vIGxhdGUgaW4gdGhl IG1pY3JvZnJhbWUsIGhvc3QgY29udHJvbGxlcgorICogZGV0ZWN0cyBiYWJibGUgb24gc3VzcGVu ZGVkIHBvcnQgYW5kIHJlc2V0cyB0aGUgcG9ydCBhZnRlcndhcmRzLgorICogVGhpcyBzL3cgd29y a2Fyb3VuZCBhbGxvd3MgdG8gYXZvaWQgdGhpcyBwcm9ibGVtLgorICogU2VlIFNXTElOVVgtMTkw OSBmb3IgbW9yZSBkZXRhaWxzCisgKi8KK3N0YXRpYyBpbnQgZWhjaV9icmNtX2h1Yl9jb250cm9s KAorCXN0cnVjdCB1c2JfaGNkCSpoY2QsCisJdTE2CQl0eXBlUmVxLAorCXUxNgkJd1ZhbHVlLAor CXUxNgkJd0luZGV4LAorCWNoYXIJCSpidWYsCisJdTE2CQl3TGVuZ3RoKQoreworCXN0cnVjdCBl aGNpX2hjZAkqZWhjaSA9IGhjZF90b19laGNpKGhjZCk7CisJaW50CQlwb3J0cyA9IEhDU19OX1BP UlRTKGVoY2ktPmhjc19wYXJhbXMpOworCXUzMiBfX2lvbWVtCSpzdGF0dXNfcmVnID0gJmVoY2kt PnJlZ3MtPnBvcnRfc3RhdHVzWworCQkJCSh3SW5kZXggJiAweGZmKSAtIDFdOworCXVuc2lnbmVk IGxvbmcgZmxhZ3M7CisJaW50IHJldHZhbCwgaXJxX2Rpc2FibGVkID0gMDsKKworCS8qCisJICog UkVTVU1FIGlzIGNsZWFyZWQgd2hlbiBHZXRQb3J0U3RhdHVzKCkgaXMgY2FsbGVkIDIwbXMgYWZ0 ZXIgc3RhcnQKKwkgKiBvZiBSRVNVTUUKKwkgKi8KKwlpZiAoKHR5cGVSZXEgPT0gR2V0UG9ydFN0 YXR1cykgJiYKKwkgICAgKHdJbmRleCAmJiB3SW5kZXggPD0gcG9ydHMpICYmCisJICAgIGVoY2kt PnJlc2V0X2RvbmVbd0luZGV4LTFdICYmCisJICAgIHRpbWVfYWZ0ZXJfZXEoamlmZmllcywgZWhj aS0+cmVzZXRfZG9uZVt3SW5kZXgtMV0pICYmCisJICAgIChlaGNpX3JlYWRsKGVoY2ksIHN0YXR1 c19yZWcpICYgUE9SVF9SRVNVTUUpKSB7CisKKwkJLyoKKwkJICogdG8gbWFrZSBzdXJlIHdlIGFy ZSBub3QgaW50ZXJydXB0ZWQgdW50aWwgUkVTVU1FIGJpdAorCQkgKiBpcyBjbGVhcmVkLCBkaXNh YmxlIGludGVycnVwdHMgb24gY3VycmVudCBDUFUKKwkJICovCisJCWVoY2lfZGJnKGVoY2ksICJT T0YgYWxpZ25tZW50IHdvcmthcm91bmRcbiIpOworCQlpcnFfZGlzYWJsZWQgPSAxOworCQlsb2Nh bF9pcnFfc2F2ZShmbGFncyk7CisJCWVoY2lfYnJjbV93YWl0X2Zvcl9zb2YoZWhjaSwgNSk7CisJ fQorCXJldHZhbCA9ICgqb3JnX2h1Yl9jb250cm9sKShoY2QsIHR5cGVSZXEsIHdWYWx1ZSwgd0lu ZGV4LCBidWYsIHdMZW5ndGgpOworCWlmIChpcnFfZGlzYWJsZWQpCisJCWxvY2FsX2lycV9yZXN0 b3JlKGZsYWdzKTsKKwlyZXR1cm4gcmV0dmFsOworfQorCitzdGF0aWMgaW50IGVoY2lfYnJjbV9y ZXNldChzdHJ1Y3QgdXNiX2hjZCAqaGNkKQoreworCXN0cnVjdCBlaGNpX2hjZCAqZWhjaSA9IGhj ZF90b19laGNpKGhjZCk7CisKKwllaGNpLT5iaWdfZW5kaWFuX21taW8gPSAxOworCWhjZC0+c3Vz cGVuZF93aXRob3V0X3BoeV9leGl0ID0gMTsKKworCWVoY2ktPmNhcHMgPSAoc3RydWN0IGVoY2lf Y2FwcyAqKSBoY2QtPnJlZ3M7CisJZWhjaS0+cmVncyA9IChzdHJ1Y3QgZWhjaV9yZWdzICopICho Y2QtPnJlZ3MgKworCQlIQ19MRU5HVEgoZWhjaSwgZWhjaV9yZWFkbChlaGNpLCAmZWhjaS0+Y2Fw cy0+aGNfY2FwYmFzZSkpKTsKKworCS8qIFRoaXMgZml4ZXMgdGhlIGxvY2t1cCBkdXJpbmcgcmVi b290IGR1ZSB0byBwcmlvciBpbnRlcnJ1cHRzICovCisJZWhjaV93cml0ZWwoZWhjaSwgQ01EX1JF U0VULCAmZWhjaS0+cmVncy0+Y29tbWFuZCk7CisJbWRlbGF5KDEwKTsKKworCS8qCisJICogU1dM SU5VWC0xNzA1OiBBdm9pZCBPVVQgcGFja2V0IHVuZGVyZmxvd3MgZHVyaW5nIGhpZ2ggbWVtb3J5 CisJICogICBidXMgdXNhZ2UKKwkgKiBwb3J0X3N0YXR1c1sweDBmXSA9IEJyb2FkY29tLXByb3By aWV0YXJ5IFVTQl9FSENJX0lOU05SRUcwMCBAIDB4OTAKKwkgKi8KKwllaGNpX3dyaXRlbChlaGNp LCAweDAwODAwMDQwLCAmZWhjaS0+cmVncy0+cG9ydF9zdGF0dXNbMHgxMF0pOworCWVoY2lfd3Jp dGVsKGVoY2ksIDB4MDAwMDAwMDEsICZlaGNpLT5yZWdzLT5wb3J0X3N0YXR1c1sweDEyXSk7CisK KwlyZXR1cm4gZWhjaV9zZXR1cChoY2QpOworfQorCitzdGF0aWMgc3RydWN0IGhjX2RyaXZlciBf X3JlYWRfbW9zdGx5IGVoY2lfYnJjbV9oY19kcml2ZXI7CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg ZWhjaV9kcml2ZXJfb3ZlcnJpZGVzIGJyY21fb3ZlcnJpZGVzIF9faW5pdGNvbnN0ID0geworCisJ LnJlc2V0ID0JZWhjaV9icmNtX3Jlc2V0LAorCS5leHRyYV9wcml2X3NpemUgPSBzaXplb2Yoc3Ry dWN0IGJyY21fcHJpdiksCit9OworCitzdGF0aWMgaW50IGVoY2lfYnJjbV9wcm9iZShzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCB1c2JfaGNkICpoY2Q7CisJc3RydWN0 IHJlc291cmNlICpyZXNfbWVtOworCXN0cnVjdCBicmNtX3ByaXYgKnByaXY7CisJaW50IGlycTsK KwlpbnQgZXJyOworCisJaWYgKHVzYl9kaXNhYmxlZCgpKQorCQlyZXR1cm4gLUVOT0RFVjsKKwor CWVyciA9IGRtYV9zZXRfbWFza19hbmRfY29oZXJlbnQoJnBkZXYtPmRldiwgRE1BX0JJVF9NQVNL KDMyKSk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKworCWlycSA9IHBsYXRmb3JtX2dldF9p cnEocGRldiwgMCk7CisJaWYgKGlycSA8IDApIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAibm8g aXJxIHByb3ZpZGVkIik7CisJCXJldHVybiBpcnE7CisJfQorCisJLyogSG9vayB0aGUgaHViIGNv bnRyb2wgcm91dGluZSB0byB3b3JrIGFyb3VuZCBhIGJ1ZyAqLworCWlmIChvcmdfaHViX2NvbnRy b2wgPT0gTlVMTCkKKwkJb3JnX2h1Yl9jb250cm9sID0gZWhjaV9icmNtX2hjX2RyaXZlci5odWJf Y29udHJvbDsKKwllaGNpX2JyY21faGNfZHJpdmVyLmh1Yl9jb250cm9sID0gZWhjaV9icmNtX2h1 Yl9jb250cm9sOworCisJLyogaW5pdGlhbGl6ZSBoY2QgKi8KKwloY2QgPSB1c2JfY3JlYXRlX2hj ZCgmZWhjaV9icmNtX2hjX2RyaXZlciwKKwkJCSZwZGV2LT5kZXYsIGRldl9uYW1lKCZwZGV2LT5k ZXYpKTsKKwlpZiAoIWhjZCkKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlwbGF0Zm9ybV9zZXRfZHJ2 ZGF0YShwZGV2LCBoY2QpOworCXByaXYgPSBoY2RfdG9fZWhjaV9wcml2KGhjZCk7CisKKwlwcml2 LT5jbGsgPSBkZXZtX2Nsa19nZXQoJnBkZXYtPmRldiwgTlVMTCk7CisJaWYgKElTX0VSUihwcml2 LT5jbGspKSB7CisJCWRldl9lcnIoJnBkZXYtPmRldiwgIkNsb2NrIG5vdCBmb3VuZCBpbiBEZXZp Y2UgVHJlZVxuIik7CisJCXByaXYtPmNsayA9IE5VTEw7CisJfQorCWVyciA9IGNsa19wcmVwYXJl X2VuYWJsZShwcml2LT5jbGspOworCWlmIChlcnIpCisJCWdvdG8gZXJyX2hjZDsKKworCXJlc19t ZW0gPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOworCWhj ZC0+cmVncyA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgmcGRldi0+ZGV2LCByZXNfbWVtKTsKKwlp ZiAoSVNfRVJSKGhjZC0+cmVncykpIHsKKwkJZXJyID0gUFRSX0VSUihoY2QtPnJlZ3MpOworCQln b3RvIGVycl9jbGs7CisJfQorCWhjZC0+cnNyY19zdGFydCA9IHJlc19tZW0tPnN0YXJ0OworCWhj ZC0+cnNyY19sZW4gPSByZXNvdXJjZV9zaXplKHJlc19tZW0pOworCWVyciA9IHVzYl9hZGRfaGNk KGhjZCwgaXJxLCBJUlFGX1NIQVJFRCk7CisJaWYgKGVycikKKwkJZ290byBlcnJfY2xrOworCisJ ZGV2aWNlX3dha2V1cF9lbmFibGUoaGNkLT5zZWxmLmNvbnRyb2xsZXIpOworCWRldmljZV9lbmFi bGVfYXN5bmNfc3VzcGVuZChoY2QtPnNlbGYuY29udHJvbGxlcik7CisJcGxhdGZvcm1fc2V0X2Ry dmRhdGEocGRldiwgaGNkKTsKKworCXJldHVybiBlcnI7CisKK2Vycl9jbGs6CisJY2xrX2Rpc2Fi bGVfdW5wcmVwYXJlKHByaXYtPmNsayk7CitlcnJfaGNkOgorCXVzYl9wdXRfaGNkKGhjZCk7CisK KwlyZXR1cm4gZXJyOworfQorCitzdGF0aWMgaW50IGVoY2lfYnJjbV9yZW1vdmUoc3RydWN0IHBs YXRmb3JtX2RldmljZSAqZGV2KQoreworCXN0cnVjdCB1c2JfaGNkICpoY2QgPSBwbGF0Zm9ybV9n ZXRfZHJ2ZGF0YShkZXYpOworCXN0cnVjdCBicmNtX3ByaXYgKnByaXYgPSBoY2RfdG9fZWhjaV9w cml2KGhjZCk7CisKKwl1c2JfcmVtb3ZlX2hjZChoY2QpOworCWNsa19kaXNhYmxlX3VucHJlcGFy ZShwcml2LT5jbGspOworCXVzYl9wdXRfaGNkKGhjZCk7CisJcmV0dXJuIDA7Cit9CisKKyNpZmRl ZiBDT05GSUdfUE1fU0xFRVAKKworc3RhdGljIGludCBlaGNpX2JyY21fc3VzcGVuZChzdHJ1Y3Qg ZGV2aWNlICpkZXYpCit7CisJaW50IHJldDsKKwlzdHJ1Y3QgdXNiX2hjZCAqaGNkID0gZGV2X2dl dF9kcnZkYXRhKGRldik7CisJc3RydWN0IGJyY21fcHJpdiAqcHJpdiA9IGhjZF90b19laGNpX3By aXYoaGNkKTsKKwlib29sIGRvX3dha2V1cCA9IGRldmljZV9tYXlfd2FrZXVwKGRldik7CisKKwly ZXQgPSBlaGNpX3N1c3BlbmQoaGNkLCBkb193YWtldXApOworCWNsa19kaXNhYmxlX3VucHJlcGFy ZShwcml2LT5jbGspOworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgZWhjaV9icmNtX3Jl c3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJc3RydWN0IHVzYl9oY2QgKmhjZCA9IGRldl9n ZXRfZHJ2ZGF0YShkZXYpOworCXN0cnVjdCBlaGNpX2hjZCAqZWhjaSA9IGhjZF90b19laGNpKGhj ZCk7CisJc3RydWN0IGJyY21fcHJpdiAqcHJpdiA9IGhjZF90b19laGNpX3ByaXYoaGNkKTsKKwlp bnQgZXJyOworCisJZXJyID0gY2xrX3ByZXBhcmVfZW5hYmxlKHByaXYtPmNsayk7CisJaWYgKGVy cikKKwkJcmV0dXJuIGVycjsKKwkvKgorCSAqIFNXTElOVVgtMTcwNTogQXZvaWQgT1VUIHBhY2tl dCB1bmRlcmZsb3dzIGR1cmluZyBoaWdoIG1lbW9yeQorCSAqICAgYnVzIHVzYWdlCisJICogcG9y dF9zdGF0dXNbMHgwZl0gPSBCcm9hZGNvbS1wcm9wcmlldGFyeSBVU0JfRUhDSV9JTlNOUkVHMDAK KwkgKiBAIDB4OTAKKwkgKi8KKwllaGNpX3dyaXRlbChlaGNpLCAweDAwODAwMDQwLCAmZWhjaS0+ cmVncy0+cG9ydF9zdGF0dXNbMHgxMF0pOworCWVoY2lfd3JpdGVsKGVoY2ksIDB4MDAwMDAwMDEs ICZlaGNpLT5yZWdzLT5wb3J0X3N0YXR1c1sweDEyXSk7CisKKwllaGNpX3Jlc3VtZShoY2QsIGZh bHNlKTsKKwlyZXR1cm4gMDsKK30KKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KKworc3Rh dGljIFNJTVBMRV9ERVZfUE1fT1BTKGVoY2lfYnJjbV9wbV9vcHMsIGVoY2lfYnJjbV9zdXNwZW5k LAorCQllaGNpX2JyY21fcmVzdW1lKTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2Vf aWQgYnJjbV9laGNpX29mX21hdGNoW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJicmNtLGJjbTc0 NDUtZWhjaSIsIH0sCisJe30KK307CisKK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGVo Y2lfYnJjbV9kcml2ZXIgPSB7CisJLnByb2JlCQk9IGVoY2lfYnJjbV9wcm9iZSwKKwkucmVtb3Zl CQk9IGVoY2lfYnJjbV9yZW1vdmUsCisJLnNodXRkb3duCT0gdXNiX2hjZF9wbGF0Zm9ybV9zaHV0 ZG93biwKKwkuZHJpdmVyCQk9IHsKKwkJLm93bmVyCT0gVEhJU19NT0RVTEUsCisJCS5uYW1lCT0g ImVoY2ktYnJjbSIsCisJCS5wbQk9ICZlaGNpX2JyY21fcG1fb3BzLAorCQkub2ZfbWF0Y2hfdGFi bGUgPSBicmNtX2VoY2lfb2ZfbWF0Y2gsCisJfQorfTsKKworc3RhdGljIGludCBfX2luaXQgZWhj aV9icmNtX2luaXQodm9pZCkKK3sKKwlpZiAodXNiX2Rpc2FibGVkKCkpCisJCXJldHVybiAtRU5P REVWOworCisJcHJfaW5mbygiJXM6ICIgQlJDTV9EUklWRVJfREVTQyAiXG4iLCBicmNtX2hjZF9u YW1lKTsKKworCWVoY2lfaW5pdF9kcml2ZXIoJmVoY2lfYnJjbV9oY19kcml2ZXIsICZicmNtX292 ZXJyaWRlcyk7CisJcmV0dXJuIHBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmZWhjaV9icmNtX2Ry aXZlcik7Cit9Cittb2R1bGVfaW5pdChlaGNpX2JyY21faW5pdCk7CisKK3N0YXRpYyB2b2lkIF9f ZXhpdCBlaGNpX2JyY21fZXhpdCh2b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVy KCZlaGNpX2JyY21fZHJpdmVyKTsKK30KK21vZHVsZV9leGl0KGVoY2lfYnJjbV9leGl0KTsKKwor TU9EVUxFX0FMSUFTKCJwbGF0Zm9ybTplaGNpLWJyY20iKTsKK01PRFVMRV9ERVNDUklQVElPTihC UkNNX0RSSVZFUl9ERVNDKTsKK01PRFVMRV9BVVRIT1IoIkFsIENvb3BlciIpOworTU9EVUxFX0xJ Q0VOU0UoIkdQTCIpOwo= From mboxrd@z Thu Jan 1 00:00:00 1970 From: Al Cooper Subject: [PATCH V3 5/6] usb: ehci: Add new EHCI driver for Broadcom STB SoC's Date: Mon, 5 Nov 2018 16:31:32 -0500 Message-ID: <1541453493-34981-6-git-send-email-alcooperx@gmail.com> References: <1541453493-34981-1-git-send-email-alcooperx@gmail.com> Return-path: In-Reply-To: <1541453493-34981-1-git-send-email-alcooperx@gmail.com> Sender: linux-kernel-owner@vger.kernel.org To: linux-kernel@vger.kernel.org Cc: Al Cooper , Alan Stern , Alban Bedel , Alex Elder , Andrew Morton , Arnd Bergmann , Avi Fishman , bcm-kernel-feedback-list@broadcom.com, Bjorn Andersson , Chunfeng Yun , "David S. Miller" , devicetree@vger.kernel.org, Dmitry Osipenko , Greg Kroah-Hartman , "Gustavo A. R. Silva" , Hans de Goede , James Hogan , Jianguo Sun , Johan Hovold , Kees Cook , linux-usb@ List-Id: devicetree@vger.kernel.org Add a new EHCI driver for Broadcom STB SoC's. A new EHCI driver was created instead of adding support to the existing ehci platform driver because of the code required to workaround bugs in the EHCI controller. Signed-off-by: Al Cooper --- drivers/usb/host/ehci-brcm.c | 287 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 drivers/usb/host/ehci-brcm.c diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c new file mode 100644 index 000000000000..f36ce240538b --- /dev/null +++ b/drivers/usb/host/ehci-brcm.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018, Broadcom */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" + +#define BRCM_DRIVER_DESC "EHCI Broadcom STB driver" + +#define hcd_to_ehci_priv(h) ((struct brcm_priv *)hcd_to_ehci(h)->priv) + +struct brcm_priv { + struct clk *clk; +}; + +static const char brcm_hcd_name[] = "ehci-brcm"; + +static int (*org_hub_control)(struct usb_hcd *hcd, + u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength); + +/* ehci_brcm_wait_for_sof + * Wait for start of next microframe, then wait extra delay microseconds + */ +static inline void ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay) +{ + int frame_idx = ehci_readl(ehci, &ehci->regs->frame_index); + + while (frame_idx == ehci_readl(ehci, &ehci->regs->frame_index)) + ; + udelay(delay); +} + +/* + * ehci_brcm_hub_control + * Intercept echi-hcd request to complete RESUME and align it to the start + * of the next microframe. + * If RESUME is complete too late in the microframe, host controller + * detects babble on suspended port and resets the port afterwards. + * This s/w workaround allows to avoid this problem. + * See SWLINUX-1909 for more details + */ +static int ehci_brcm_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int ports = HCS_N_PORTS(ehci->hcs_params); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; + unsigned long flags; + int retval, irq_disabled = 0; + + /* + * RESUME is cleared when GetPortStatus() is called 20ms after start + * of RESUME + */ + if ((typeReq == GetPortStatus) && + (wIndex && wIndex <= ports) && + ehci->reset_done[wIndex-1] && + time_after_eq(jiffies, ehci->reset_done[wIndex-1]) && + (ehci_readl(ehci, status_reg) & PORT_RESUME)) { + + /* + * to make sure we are not interrupted until RESUME bit + * is cleared, disable interrupts on current CPU + */ + ehci_dbg(ehci, "SOF alignment workaround\n"); + irq_disabled = 1; + local_irq_save(flags); + ehci_brcm_wait_for_sof(ehci, 5); + } + retval = (*org_hub_control)(hcd, typeReq, wValue, wIndex, buf, wLength); + if (irq_disabled) + local_irq_restore(flags); + return retval; +} + +static int ehci_brcm_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + ehci->big_endian_mmio = 1; + hcd->suspend_without_phy_exit = 1; + + ehci->caps = (struct ehci_caps *) hcd->regs; + ehci->regs = (struct ehci_regs *) (hcd->regs + + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase))); + + /* This fixes the lockup during reboot due to prior interrupts */ + ehci_writel(ehci, CMD_RESET, &ehci->regs->command); + mdelay(10); + + /* + * SWLINUX-1705: Avoid OUT packet underflows during high memory + * bus usage + * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90 + */ + ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]); + ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]); + + return ehci_setup(hcd); +} + +static struct hc_driver __read_mostly ehci_brcm_hc_driver; + +static const struct ehci_driver_overrides brcm_overrides __initconst = { + + .reset = ehci_brcm_reset, + .extra_priv_size = sizeof(struct brcm_priv), +}; + +static int ehci_brcm_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct resource *res_mem; + struct brcm_priv *priv; + int irq; + int err; + + if (usb_disabled()) + return -ENODEV; + + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) + return err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq provided"); + return irq; + } + + /* Hook the hub control routine to work around a bug */ + if (org_hub_control == NULL) + org_hub_control = ehci_brcm_hc_driver.hub_control; + ehci_brcm_hc_driver.hub_control = ehci_brcm_hub_control; + + /* initialize hcd */ + hcd = usb_create_hcd(&ehci_brcm_hc_driver, + &pdev->dev, dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; + + platform_set_drvdata(pdev, hcd); + priv = hcd_to_ehci_priv(hcd); + + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "Clock not found in Device Tree\n"); + priv->clk = NULL; + } + err = clk_prepare_enable(priv->clk); + if (err) + goto err_hcd; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); + goto err_clk; + } + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) + goto err_clk; + + device_wakeup_enable(hcd->self.controller); + device_enable_async_suspend(hcd->self.controller); + platform_set_drvdata(pdev, hcd); + + return err; + +err_clk: + clk_disable_unprepare(priv->clk); +err_hcd: + usb_put_hcd(hcd); + + return err; +} + +static int ehci_brcm_remove(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + + usb_remove_hcd(hcd); + clk_disable_unprepare(priv->clk); + usb_put_hcd(hcd); + return 0; +} + +#ifdef CONFIG_PM_SLEEP + +static int ehci_brcm_suspend(struct device *dev) +{ + int ret; + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + bool do_wakeup = device_may_wakeup(dev); + + ret = ehci_suspend(hcd, do_wakeup); + clk_disable_unprepare(priv->clk); + return ret; +} + +static int ehci_brcm_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + int err; + + err = clk_prepare_enable(priv->clk); + if (err) + return err; + /* + * SWLINUX-1705: Avoid OUT packet underflows during high memory + * bus usage + * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 + * @ 0x90 + */ + ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]); + ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]); + + ehci_resume(hcd, false); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(ehci_brcm_pm_ops, ehci_brcm_suspend, + ehci_brcm_resume); + +static const struct of_device_id brcm_ehci_of_match[] = { + { .compatible = "brcm,bcm7445-ehci", }, + {} +}; + +static struct platform_driver ehci_brcm_driver = { + .probe = ehci_brcm_probe, + .remove = ehci_brcm_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = "ehci-brcm", + .pm = &ehci_brcm_pm_ops, + .of_match_table = brcm_ehci_of_match, + } +}; + +static int __init ehci_brcm_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " BRCM_DRIVER_DESC "\n", brcm_hcd_name); + + ehci_init_driver(&ehci_brcm_hc_driver, &brcm_overrides); + return platform_driver_register(&ehci_brcm_driver); +} +module_init(ehci_brcm_init); + +static void __exit ehci_brcm_exit(void) +{ + platform_driver_unregister(&ehci_brcm_driver); +} +module_exit(ehci_brcm_exit); + +MODULE_ALIAS("platform:ehci-brcm"); +MODULE_DESCRIPTION(BRCM_DRIVER_DESC); +MODULE_AUTHOR("Al Cooper"); +MODULE_LICENSE("GPL"); -- 1.9.0.138.g2de3478 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.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT 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 68B4CC0044C for ; Mon, 5 Nov 2018 21:33:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0F5352085A for ; Mon, 5 Nov 2018 21:33:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="U/150Byc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0F5352085A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.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 S2388160AbeKFGy4 (ORCPT ); Tue, 6 Nov 2018 01:54:56 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:46571 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388065AbeKFGyz (ORCPT ); Tue, 6 Nov 2018 01:54:55 -0500 Received: by mail-pf1-f194.google.com with SMTP id r64-v6so5032300pfb.13; Mon, 05 Nov 2018 13:33:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=74FmHITOWFSyLR/kjqZMnZTf7v6j4tt6nFEAL8fjtlM=; b=U/150Byct1h37TmZfjHyxzlAvSGHU2zJ+p2ixNPeaIrR34QdFP33AoXznVzuFjnvyK mwDpDpeHhWfKVvpT5cxRD9SlAuuWimmDxvrN4UZApFea8+t8xxx0h5TF6LyMS2oFY370 8UuYifefZks6sxkWdPm0weEKMP0adMGswWYzj9cbyxYYxUF13/zrx+vGQMurUN0lpij3 IYVt8s//ivbq0LYtGMvlkjPm7dTsP82glZiHhNs2Oo46sFgTUVrxojmGbMVXorg+ETQf uNanEa/+lvYSC3r5PGK8DUopdL2jxHLFMeTm5kbi2jW4Ar97ZczeWZStMbXPmIN619ot 3yvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=74FmHITOWFSyLR/kjqZMnZTf7v6j4tt6nFEAL8fjtlM=; b=NHYdnrZkDw3mAplB7QQsO0edDfAEDskGF4bkAFWAdge1FzchFxbLjrZoPwn+qGM9aN 2L5aRpF2ja+B4yY79+/8JSptwxKSyWLR/tykQ4qxHiWoTE5/IJjbQkyd0f+pchRCsLZ9 eu9k/DH0kyW2kr5WD0LxnFzaop25+lxLlcvuQ0kfb3NTeG08Ues05NglHPR4atA5FXJr Iy7I0m5FGrPh8L5+L+bog5SQAAQSODoI6JrBjhULo5k3O/JOZeoSrr0XNq5L+XeppotQ bHn88QzMMzGOYEXJBYS9fcCti5Q1sgglGauDbLfX0hiz25ZoEWSIbN7q2IjW+BZQkS3J KyUw== X-Gm-Message-State: AGRZ1gLnzpMIqr3640y4Uwx+z4bF+0mpqv8xHrfrhnD5kP5xO0T4i6J2 hpWCyIICCUmELFqrfZSix/6K/qNzSi8= X-Google-Smtp-Source: AJdET5flpVZMPyDJgdC0QDddCKcZgWKYKbQ1bgTw2QaT7omu3kCjRXcG+p75XFd78CX4Gp+Y7z96OA== X-Received: by 2002:a62:29c4:: with SMTP id p187-v6mr14030498pfp.62.1541453593666; Mon, 05 Nov 2018 13:33:13 -0800 (PST) Received: from stbsrv-and-3.and.broadcom.com ([192.19.231.250]) by smtp.gmail.com with ESMTPSA id m129-v6sm14328440pfm.78.2018.11.05.13.33.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 13:33:13 -0800 (PST) From: Al Cooper To: linux-kernel@vger.kernel.org Cc: Al Cooper , Alan Stern , Alban Bedel , Alex Elder , Andrew Morton , Arnd Bergmann , Avi Fishman , bcm-kernel-feedback-list@broadcom.com, Bjorn Andersson , Chunfeng Yun , "David S. Miller" , devicetree@vger.kernel.org, Dmitry Osipenko , Greg Kroah-Hartman , "Gustavo A. R. Silva" , Hans de Goede , James Hogan , Jianguo Sun , Johan Hovold , Kees Cook , linux-usb@vger.kernel.org, Lu Baolu , Mark Rutland , Martin Blumenstingl , Mathias Nyman , Mathias Nyman , Mauro Carvalho Chehab , Rishabh Bhatnagar , Rob Herring , Roger Quadros Subject: [PATCH V3 5/6] usb: ehci: Add new EHCI driver for Broadcom STB SoC's Date: Mon, 5 Nov 2018 16:31:32 -0500 Message-Id: <1541453493-34981-6-git-send-email-alcooperx@gmail.com> X-Mailer: git-send-email 1.9.0.138.g2de3478 In-Reply-To: <1541453493-34981-1-git-send-email-alcooperx@gmail.com> References: <1541453493-34981-1-git-send-email-alcooperx@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a new EHCI driver for Broadcom STB SoC's. A new EHCI driver was created instead of adding support to the existing ehci platform driver because of the code required to workaround bugs in the EHCI controller. Signed-off-by: Al Cooper --- drivers/usb/host/ehci-brcm.c | 287 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 drivers/usb/host/ehci-brcm.c diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c new file mode 100644 index 000000000000..f36ce240538b --- /dev/null +++ b/drivers/usb/host/ehci-brcm.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018, Broadcom */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" + +#define BRCM_DRIVER_DESC "EHCI Broadcom STB driver" + +#define hcd_to_ehci_priv(h) ((struct brcm_priv *)hcd_to_ehci(h)->priv) + +struct brcm_priv { + struct clk *clk; +}; + +static const char brcm_hcd_name[] = "ehci-brcm"; + +static int (*org_hub_control)(struct usb_hcd *hcd, + u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength); + +/* ehci_brcm_wait_for_sof + * Wait for start of next microframe, then wait extra delay microseconds + */ +static inline void ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay) +{ + int frame_idx = ehci_readl(ehci, &ehci->regs->frame_index); + + while (frame_idx == ehci_readl(ehci, &ehci->regs->frame_index)) + ; + udelay(delay); +} + +/* + * ehci_brcm_hub_control + * Intercept echi-hcd request to complete RESUME and align it to the start + * of the next microframe. + * If RESUME is complete too late in the microframe, host controller + * detects babble on suspended port and resets the port afterwards. + * This s/w workaround allows to avoid this problem. + * See SWLINUX-1909 for more details + */ +static int ehci_brcm_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int ports = HCS_N_PORTS(ehci->hcs_params); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; + unsigned long flags; + int retval, irq_disabled = 0; + + /* + * RESUME is cleared when GetPortStatus() is called 20ms after start + * of RESUME + */ + if ((typeReq == GetPortStatus) && + (wIndex && wIndex <= ports) && + ehci->reset_done[wIndex-1] && + time_after_eq(jiffies, ehci->reset_done[wIndex-1]) && + (ehci_readl(ehci, status_reg) & PORT_RESUME)) { + + /* + * to make sure we are not interrupted until RESUME bit + * is cleared, disable interrupts on current CPU + */ + ehci_dbg(ehci, "SOF alignment workaround\n"); + irq_disabled = 1; + local_irq_save(flags); + ehci_brcm_wait_for_sof(ehci, 5); + } + retval = (*org_hub_control)(hcd, typeReq, wValue, wIndex, buf, wLength); + if (irq_disabled) + local_irq_restore(flags); + return retval; +} + +static int ehci_brcm_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + ehci->big_endian_mmio = 1; + hcd->suspend_without_phy_exit = 1; + + ehci->caps = (struct ehci_caps *) hcd->regs; + ehci->regs = (struct ehci_regs *) (hcd->regs + + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase))); + + /* This fixes the lockup during reboot due to prior interrupts */ + ehci_writel(ehci, CMD_RESET, &ehci->regs->command); + mdelay(10); + + /* + * SWLINUX-1705: Avoid OUT packet underflows during high memory + * bus usage + * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90 + */ + ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]); + ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]); + + return ehci_setup(hcd); +} + +static struct hc_driver __read_mostly ehci_brcm_hc_driver; + +static const struct ehci_driver_overrides brcm_overrides __initconst = { + + .reset = ehci_brcm_reset, + .extra_priv_size = sizeof(struct brcm_priv), +}; + +static int ehci_brcm_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct resource *res_mem; + struct brcm_priv *priv; + int irq; + int err; + + if (usb_disabled()) + return -ENODEV; + + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) + return err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq provided"); + return irq; + } + + /* Hook the hub control routine to work around a bug */ + if (org_hub_control == NULL) + org_hub_control = ehci_brcm_hc_driver.hub_control; + ehci_brcm_hc_driver.hub_control = ehci_brcm_hub_control; + + /* initialize hcd */ + hcd = usb_create_hcd(&ehci_brcm_hc_driver, + &pdev->dev, dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; + + platform_set_drvdata(pdev, hcd); + priv = hcd_to_ehci_priv(hcd); + + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "Clock not found in Device Tree\n"); + priv->clk = NULL; + } + err = clk_prepare_enable(priv->clk); + if (err) + goto err_hcd; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); + goto err_clk; + } + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) + goto err_clk; + + device_wakeup_enable(hcd->self.controller); + device_enable_async_suspend(hcd->self.controller); + platform_set_drvdata(pdev, hcd); + + return err; + +err_clk: + clk_disable_unprepare(priv->clk); +err_hcd: + usb_put_hcd(hcd); + + return err; +} + +static int ehci_brcm_remove(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + + usb_remove_hcd(hcd); + clk_disable_unprepare(priv->clk); + usb_put_hcd(hcd); + return 0; +} + +#ifdef CONFIG_PM_SLEEP + +static int ehci_brcm_suspend(struct device *dev) +{ + int ret; + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + bool do_wakeup = device_may_wakeup(dev); + + ret = ehci_suspend(hcd, do_wakeup); + clk_disable_unprepare(priv->clk); + return ret; +} + +static int ehci_brcm_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct brcm_priv *priv = hcd_to_ehci_priv(hcd); + int err; + + err = clk_prepare_enable(priv->clk); + if (err) + return err; + /* + * SWLINUX-1705: Avoid OUT packet underflows during high memory + * bus usage + * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 + * @ 0x90 + */ + ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]); + ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]); + + ehci_resume(hcd, false); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(ehci_brcm_pm_ops, ehci_brcm_suspend, + ehci_brcm_resume); + +static const struct of_device_id brcm_ehci_of_match[] = { + { .compatible = "brcm,bcm7445-ehci", }, + {} +}; + +static struct platform_driver ehci_brcm_driver = { + .probe = ehci_brcm_probe, + .remove = ehci_brcm_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = "ehci-brcm", + .pm = &ehci_brcm_pm_ops, + .of_match_table = brcm_ehci_of_match, + } +}; + +static int __init ehci_brcm_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " BRCM_DRIVER_DESC "\n", brcm_hcd_name); + + ehci_init_driver(&ehci_brcm_hc_driver, &brcm_overrides); + return platform_driver_register(&ehci_brcm_driver); +} +module_init(ehci_brcm_init); + +static void __exit ehci_brcm_exit(void) +{ + platform_driver_unregister(&ehci_brcm_driver); +} +module_exit(ehci_brcm_exit); + +MODULE_ALIAS("platform:ehci-brcm"); +MODULE_DESCRIPTION(BRCM_DRIVER_DESC); +MODULE_AUTHOR("Al Cooper"); +MODULE_LICENSE("GPL"); -- 1.9.0.138.g2de3478