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: [1/4] dmaengine: mediatek: Add MediaTek UART APDMA support From: Long Cheng Message-Id: <1556336193-15198-2-git-send-email-long.cheng@mediatek.com> Date: Sat, 27 Apr 2019 11:36:30 +0800 To: Vinod Koul , Randy Dunlap , Rob Herring , Mark Rutland , Ryder Lee , Sean Wang , Nicolas Boichat , Matthias Brugger Cc: Dan Williams , Greg Kroah-Hartman , Jiri Slaby , Sean Wang , dmaengine@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, srv_heupstream@mediatek.com, Yingjoe Chen , YT Shen , Zhenbao Liu , Long Cheng List-ID: QWRkIDgyNTAgVUFSVCBBUERNQSB0byBzdXBwb3J0IE1lZGlhVGVrIFVBUlQuIElmIE1lZGlhVGVr IFVBUlQgaXMKZW5hYmxlZCBieSBTRVJJQUxfODI1MF9NVDY1NzcsIGFuZCB3ZSBjYW4gZW5hYmxl IHRoaXMgZHJpdmVyIHRvIG9mZmxvYWQKdGhlIFVBUlQgZGV2aWNlIG1vdmluZyBieXRlcy4KClNp Z25lZC1vZmYtYnk6IExvbmcgQ2hlbmcgPGxvbmcuY2hlbmdAbWVkaWF0ZWsuY29tPgpTaWduZWQt b2ZmLWJ5OiBTZWFuIFdhbmcgPHNlYW4ud2FuZ0BtZWRpYXRlay5jb20+Ci0tLQogZHJpdmVycy9k bWEvbWVkaWF0ZWsvS2NvbmZpZyAgICAgICAgICB8ICAgMTEgKwogZHJpdmVycy9kbWEvbWVkaWF0 ZWsvTWFrZWZpbGUgICAgICAgICB8ICAgIDEgKwogZHJpdmVycy9kbWEvbWVkaWF0ZWsvbXRrLXVh cnQtYXBkbWEuYyB8ICA2NjYgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiAzIGZp bGVzIGNoYW5nZWQsIDY3OCBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVy cy9kbWEvbWVkaWF0ZWsvbXRrLXVhcnQtYXBkbWEuYwoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1h L21lZGlhdGVrL0tjb25maWcgYi9kcml2ZXJzL2RtYS9tZWRpYXRlay9LY29uZmlnCmluZGV4IDY4 MGZjMDUuLmFjNDllYjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZG1hL21lZGlhdGVrL0tjb25maWcK KysrIGIvZHJpdmVycy9kbWEvbWVkaWF0ZWsvS2NvbmZpZwpAQCAtMjQsMyArMjQsMTQgQEAgY29u ZmlnIE1US19DUURNQQogCiAJICBUaGlzIGNvbnRyb2xsZXIgcHJvdmlkZXMgdGhlIGNoYW5uZWxz IHdoaWNoIGlzIGRlZGljYXRlZCB0bwogCSAgbWVtb3J5LXRvLW1lbW9yeSB0cmFuc2ZlciB0byBv ZmZsb2FkIGZyb20gQ1BVLgorCitjb25maWcgTVRLX1VBUlRfQVBETUEKKwl0cmlzdGF0ZSAiTWVk aWFUZWsgU29DcyBBUERNQSBzdXBwb3J0IGZvciBVQVJUIgorCWRlcGVuZHMgb24gT0YgJiYgU0VS SUFMXzgyNTBfTVQ2NTc3CisJc2VsZWN0IERNQV9FTkdJTkUKKwlzZWxlY3QgRE1BX1ZJUlRVQUxf Q0hBTk5FTFMKKwloZWxwCisJICBTdXBwb3J0IGZvciB0aGUgVUFSVCBETUEgZW5naW5lIGZvdW5k IG9uIE1lZGlhVGVrIE1USyBTb0NzLgorCSAgV2hlbiBTRVJJQUxfODI1MF9NVDY1NzcgaXMgZW5h YmxlZCwgYW5kIGlmIHlvdSB3YW50IHRvIHVzZSBETUEsCisJICB5b3UgY2FuIGVuYWJsZSB0aGUg Y29uZmlnLiBUaGUgRE1BIGVuZ2luZSBjYW4gb25seSBiZSB1c2VkCisJICB3aXRoIE1lZGlhVGVr IFNvQ3MuCmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9tZWRpYXRlay9NYWtlZmlsZSBiL2RyaXZl cnMvZG1hL21lZGlhdGVrL01ha2VmaWxlCmluZGV4IDQxYmIzODEuLjYxYTZkMjkgMTAwNjQ0Ci0t LSBhL2RyaXZlcnMvZG1hL21lZGlhdGVrL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvZG1hL21lZGlh dGVrL01ha2VmaWxlCkBAIC0xLDIgKzEsMyBAQAorb2JqLSQoQ09ORklHX01US19VQVJUX0FQRE1B KSArPSBtdGstdWFydC1hcGRtYS5vCiBvYmotJChDT05GSUdfTVRLX0hTRE1BKSArPSBtdGstaHNk bWEubwogb2JqLSQoQ09ORklHX01US19DUURNQSkgKz0gbXRrLWNxZG1hLm8KZGlmZiAtLWdpdCBh L2RyaXZlcnMvZG1hL21lZGlhdGVrL210ay11YXJ0LWFwZG1hLmMgYi9kcml2ZXJzL2RtYS9tZWRp YXRlay9tdGstdWFydC1hcGRtYS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu LjU0Njk5NWMKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2RtYS9tZWRpYXRlay9tdGstdWFy dC1hcGRtYS5jCkBAIC0wLDAgKzEsNjY2IEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjog R1BMLTIuMAorLyoKKyAqIE1lZGlhVGVrIFVBUlQgQVBETUEgZHJpdmVyLgorICoKKyAqIENvcHly aWdodCAoYykgMjAxOSBNZWRpYVRlayBJbmMuCisgKiBBdXRob3I6IExvbmcgQ2hlbmcgPGxvbmcu Y2hlbmdAbWVkaWF0ZWsuY29tPgorICovCisKKyNpbmNsdWRlIDxsaW51eC9jbGsuaD4KKyNpbmNs dWRlIDxsaW51eC9kbWFlbmdpbmUuaD4KKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPgor I2luY2x1ZGUgPGxpbnV4L2Vyci5oPgorI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KKyNpbmNsdWRl IDxsaW51eC9pbnRlcnJ1cHQuaD4KKyNpbmNsdWRlIDxsaW51eC9pb3BvbGwuaD4KKyNpbmNsdWRl IDxsaW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+CisjaW5jbHVkZSA8bGlu dXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgvb2ZfZGV2aWNlLmg+CisjaW5jbHVkZSA8bGlu dXgvb2ZfZG1hLmg+CisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk ZSA8bGludXgvcG1fcnVudGltZS5oPgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKyNpbmNsdWRl IDxsaW51eC9zcGlubG9jay5oPgorCisjaW5jbHVkZSAiLi4vdmlydC1kbWEuaCIKKworLyogVGhl IGRlZmF1bHQgbnVtYmVyIG9mIHZpcnR1YWwgY2hhbm5lbCAqLworI2RlZmluZSBNVEtfVUFSVF9B UERNQV9OUl9WQ0hBTlMJOAorCisjZGVmaW5lIFZGRl9FTl9CCQlCSVQoMCkKKyNkZWZpbmUgVkZG X1NUT1BfQgkJQklUKDApCisjZGVmaW5lIFZGRl9GTFVTSF9CCQlCSVQoMCkKKyNkZWZpbmUgVkZG XzRHX0VOX0IJCUJJVCgwKQorLyogcnggdmFsaWQgc2l6ZSA+PSAgdmZmIHRocmUgKi8KKyNkZWZp bmUgVkZGX1JYX0lOVF9FTl9CCQkoQklUKDApIHwgQklUKDEpKQorLyogdHggbGVmdCBzaXplID49 IHZmZiB0aHJlICovCisjZGVmaW5lIFZGRl9UWF9JTlRfRU5fQgkJQklUKDApCisjZGVmaW5lIFZG Rl9XQVJNX1JTVF9CCQlCSVQoMCkKKyNkZWZpbmUgVkZGX1JYX0lOVF9DTFJfQgkoQklUKDApIHwg QklUKDEpKQorI2RlZmluZSBWRkZfVFhfSU5UX0NMUl9CCTAKKyNkZWZpbmUgVkZGX1NUT1BfQ0xS X0IJCTAKKyNkZWZpbmUgVkZGX0VOX0NMUl9CCQkwCisjZGVmaW5lIFZGRl9JTlRfRU5fQ0xSX0IJ MAorI2RlZmluZSBWRkZfNEdfU1VQUE9SVF9DTFJfQgkwCisKKy8qCisgKiBpbnRlcnJ1cHQgdHJp Z2dlciBsZXZlbCBmb3IgdHgKKyAqIGlmIHRocmVzaG9sZCBpcyBuLCBubyBwb2xsaW5nIGlzIHJl cXVpcmVkIHRvIHN0YXJ0IHR4LgorICogb3RoZXJ3aXNlIG5lZWQgcG9sbGluZyBWRkZfRkxVU0gu CisgKi8KKyNkZWZpbmUgVkZGX1RYX1RIUkUobikJCShuKQorLyogaW50ZXJydXB0IHRyaWdnZXIg bGV2ZWwgZm9yIHJ4ICovCisjZGVmaW5lIFZGRl9SWF9USFJFKG4pCQkoKG4pICogMyAvIDQpCisK KyNkZWZpbmUgVkZGX1JJTkdfU0laRQkweGZmZmYKKy8qIGludmVydCB0aGlzIGJpdCB3aGVuIHdy YXAgcmluZyBoZWFkIGFnYWluICovCisjZGVmaW5lIFZGRl9SSU5HX1dSQVAJMHgxMDAwMAorCisj ZGVmaW5lIFZGRl9JTlRfRkxBRwkJMHgwMAorI2RlZmluZSBWRkZfSU5UX0VOCQkweDA0CisjZGVm aW5lIFZGRl9FTgkJCTB4MDgKKyNkZWZpbmUgVkZGX1JTVAkJCTB4MGMKKyNkZWZpbmUgVkZGX1NU T1AJCTB4MTAKKyNkZWZpbmUgVkZGX0ZMVVNICQkweDE0CisjZGVmaW5lIFZGRl9BRERSCQkweDFj CisjZGVmaW5lIFZGRl9MRU4JCQkweDI0CisjZGVmaW5lIFZGRl9USFJFCQkweDI4CisjZGVmaW5l IFZGRl9XUFQJCQkweDJjCisjZGVmaW5lIFZGRl9SUFQJCQkweDMwCisvKiBUWDogdGhlIGJ1ZmZl ciBzaXplIEhXIGNhbiByZWFkLiBSWDogdGhlIGJ1ZmZlciBzaXplIFNXIGNhbiByZWFkLiAqLwor I2RlZmluZSBWRkZfVkFMSURfU0laRQkJMHgzYworLyogVFg6IHRoZSBidWZmZXIgc2l6ZSBTVyBj YW4gd3JpdGUuIFJYOiB0aGUgYnVmZmVyIHNpemUgSFcgY2FuIHdyaXRlLiAqLworI2RlZmluZSBW RkZfTEVGVF9TSVpFCQkweDQwCisjZGVmaW5lIFZGRl9ERUJVR19TVEFUVVMJMHg1MAorI2RlZmlu ZSBWRkZfNEdfU1VQUE9SVAkJMHg1NAorCitzdHJ1Y3QgbXRrX3VhcnRfYXBkbWFkZXYgeworCXN0 cnVjdCBkbWFfZGV2aWNlIGRkZXY7CisJc3RydWN0IGNsayAqY2xrOworCWJvb2wgc3VwcG9ydF8z M2JpdHM7CisJdW5zaWduZWQgaW50IGRtYV9yZXF1ZXN0czsKK307CisKK3N0cnVjdCBtdGtfdWFy dF9hcGRtYV9kZXNjIHsKKwlzdHJ1Y3QgdmlydF9kbWFfZGVzYyB2ZDsKKworCWRtYV9hZGRyX3Qg YWRkcjsKKwl1bnNpZ25lZCBpbnQgYXZhaWxfbGVuOworfTsKKworc3RydWN0IG10a19jaGFuIHsK KwlzdHJ1Y3QgdmlydF9kbWFfY2hhbiB2YzsKKwlzdHJ1Y3QgZG1hX3NsYXZlX2NvbmZpZwljZmc7 CisJc3RydWN0IG10a191YXJ0X2FwZG1hX2Rlc2MgKmRlc2M7CisJZW51bSBkbWFfdHJhbnNmZXJf ZGlyZWN0aW9uIGRpcjsKKworCXZvaWQgX19pb21lbSAqYmFzZTsKKwl1bnNpZ25lZCBpbnQgaXJx OworCisJdW5zaWduZWQgaW50IHJ4X3N0YXR1czsKK307CisKK3N0YXRpYyBpbmxpbmUgc3RydWN0 IG10a191YXJ0X2FwZG1hZGV2ICoKK3RvX210a191YXJ0X2FwZG1hX2RldihzdHJ1Y3QgZG1hX2Rl dmljZSAqZCkKK3sKKwlyZXR1cm4gY29udGFpbmVyX29mKGQsIHN0cnVjdCBtdGtfdWFydF9hcGRt YWRldiwgZGRldik7Cit9CisKK3N0YXRpYyBpbmxpbmUgc3RydWN0IG10a19jaGFuICp0b19tdGtf dWFydF9hcGRtYV9jaGFuKHN0cnVjdCBkbWFfY2hhbiAqYykKK3sKKwlyZXR1cm4gY29udGFpbmVy X29mKGMsIHN0cnVjdCBtdGtfY2hhbiwgdmMuY2hhbik7Cit9CisKK3N0YXRpYyBpbmxpbmUgc3Ry dWN0IG10a191YXJ0X2FwZG1hX2Rlc2MgKnRvX210a191YXJ0X2FwZG1hX2Rlc2MKKwkoc3RydWN0 IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICp0KQoreworCXJldHVybiBjb250YWluZXJfb2YodCwg c3RydWN0IG10a191YXJ0X2FwZG1hX2Rlc2MsIHZkLnR4KTsKK30KKworc3RhdGljIHZvaWQgbXRr X3VhcnRfYXBkbWFfd3JpdGUoc3RydWN0IG10a19jaGFuICpjLAorCQkJICAgICAgIHVuc2lnbmVk IGludCByZWcsIHVuc2lnbmVkIGludCB2YWwpCit7CisJd3JpdGVsKHZhbCwgYy0+YmFzZSArIHJl Zyk7Cit9CisKK3N0YXRpYyB1bnNpZ25lZCBpbnQgbXRrX3VhcnRfYXBkbWFfcmVhZChzdHJ1Y3Qg bXRrX2NoYW4gKmMsIHVuc2lnbmVkIGludCByZWcpCit7CisJcmV0dXJuIHJlYWRsKGMtPmJhc2Ug KyByZWcpOworfQorCitzdGF0aWMgdm9pZCBtdGtfdWFydF9hcGRtYV9kZXNjX2ZyZWUoc3RydWN0 IHZpcnRfZG1hX2Rlc2MgKnZkKQoreworCXN0cnVjdCBkbWFfY2hhbiAqY2hhbiA9IHZkLT50eC5j aGFuOworCXN0cnVjdCBtdGtfY2hhbiAqYyA9IHRvX210a191YXJ0X2FwZG1hX2NoYW4oY2hhbik7 CisKKwlrZnJlZShjLT5kZXNjKTsKK30KKworc3RhdGljIHZvaWQgbXRrX3VhcnRfYXBkbWFfc3Rh cnRfdHgoc3RydWN0IG10a19jaGFuICpjKQoreworCXN0cnVjdCBtdGtfdWFydF9hcGRtYWRldiAq bXRrZCA9CisJCQkJdG9fbXRrX3VhcnRfYXBkbWFfZGV2KGMtPnZjLmNoYW4uZGV2aWNlKTsKKwlz dHJ1Y3QgbXRrX3VhcnRfYXBkbWFfZGVzYyAqZCA9IGMtPmRlc2M7CisJdW5zaWduZWQgaW50IHdw dCwgdmZmX3N6OworCisJdmZmX3N6ID0gYy0+Y2ZnLmRzdF9wb3J0X3dpbmRvd19zaXplOworCWlm ICghbXRrX3VhcnRfYXBkbWFfcmVhZChjLCBWRkZfTEVOKSkgeworCQltdGtfdWFydF9hcGRtYV93 cml0ZShjLCBWRkZfQUREUiwgZC0+YWRkcik7CisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZG Rl9MRU4sIHZmZl9zeik7CisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9USFJFLCBWRkZf VFhfVEhSRSh2ZmZfc3opKTsKKwkJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX1dQVCwgMCk7 CisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1RYX0lOVF9DTFJf Qik7CisKKwkJaWYgKG10a2QtPnN1cHBvcnRfMzNiaXRzKQorCQkJbXRrX3VhcnRfYXBkbWFfd3Jp dGUoYywgVkZGXzRHX1NVUFBPUlQsIFZGRl80R19FTl9CKTsKKwl9CisKKwltdGtfdWFydF9hcGRt YV93cml0ZShjLCBWRkZfRU4sIFZGRl9FTl9CKTsKKwlpZiAobXRrX3VhcnRfYXBkbWFfcmVhZChj LCBWRkZfRU4pICE9IFZGRl9FTl9CKQorCQlkZXZfZXJyKGMtPnZjLmNoYW4uZGV2aWNlLT5kZXYs ICJFbmFibGUgVFggZmFpbFxuIik7CisKKwlpZiAoIW10a191YXJ0X2FwZG1hX3JlYWQoYywgVkZG X0xFRlRfU0laRSkpIHsKKwkJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX0lOVF9FTiwgVkZG X1RYX0lOVF9FTl9CKTsKKwkJcmV0dXJuOworCX0KKworCXdwdCA9IG10a191YXJ0X2FwZG1hX3Jl YWQoYywgVkZGX1dQVCk7CisKKwl3cHQgKz0gYy0+ZGVzYy0+YXZhaWxfbGVuOworCWlmICgod3B0 ICYgVkZGX1JJTkdfU0laRSkgPT0gdmZmX3N6KQorCQl3cHQgPSAod3B0ICYgVkZGX1JJTkdfV1JB UCkgXiBWRkZfUklOR19XUkFQOworCisJLyogTGV0IERNQSBzdGFydCBtb3ZpbmcgZGF0YSAqLwor CW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9XUFQsIHdwdCk7CisKKwkvKiBIVyBhdXRvIHNl dCB0byAwIHdoZW4gbGVmdCBzaXplID49IHRocmVzaG9sZCAqLworCW10a191YXJ0X2FwZG1hX3dy aXRlKGMsIFZGRl9JTlRfRU4sIFZGRl9UWF9JTlRfRU5fQik7CisJaWYgKCFtdGtfdWFydF9hcGRt YV9yZWFkKGMsIFZGRl9GTFVTSCkpCisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9GTFVT SCwgVkZGX0ZMVVNIX0IpOworfQorCitzdGF0aWMgdm9pZCBtdGtfdWFydF9hcGRtYV9zdGFydF9y eChzdHJ1Y3QgbXRrX2NoYW4gKmMpCit7CisJc3RydWN0IG10a191YXJ0X2FwZG1hZGV2ICptdGtk ID0KKwkJCQl0b19tdGtfdWFydF9hcGRtYV9kZXYoYy0+dmMuY2hhbi5kZXZpY2UpOworCXN0cnVj dCBtdGtfdWFydF9hcGRtYV9kZXNjICpkID0gYy0+ZGVzYzsKKwl1bnNpZ25lZCBpbnQgdmZmX3N6 OworCisJdmZmX3N6ID0gYy0+Y2ZnLnNyY19wb3J0X3dpbmRvd19zaXplOworCWlmICghbXRrX3Vh cnRfYXBkbWFfcmVhZChjLCBWRkZfTEVOKSkgeworCQltdGtfdWFydF9hcGRtYV93cml0ZShjLCBW RkZfQUREUiwgZC0+YWRkcik7CisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9MRU4sIHZm Zl9zeik7CisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9USFJFLCBWRkZfUlhfVEhSRSh2 ZmZfc3opKTsKKwkJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX1JQVCwgMCk7CisJCW10a191 YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1JYX0lOVF9DTFJfQik7CisKKwkJ aWYgKG10a2QtPnN1cHBvcnRfMzNiaXRzKQorCQkJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZG XzRHX1NVUFBPUlQsIFZGRl80R19FTl9CKTsKKwl9CisKKwltdGtfdWFydF9hcGRtYV93cml0ZShj LCBWRkZfSU5UX0VOLCBWRkZfUlhfSU5UX0VOX0IpOworCW10a191YXJ0X2FwZG1hX3dyaXRlKGMs IFZGRl9FTiwgVkZGX0VOX0IpOworCWlmIChtdGtfdWFydF9hcGRtYV9yZWFkKGMsIFZGRl9FTikg IT0gVkZGX0VOX0IpCisJCWRldl9lcnIoYy0+dmMuY2hhbi5kZXZpY2UtPmRldiwgIkVuYWJsZSBS WCBmYWlsXG4iKTsKK30KKworc3RhdGljIHZvaWQgbXRrX3VhcnRfYXBkbWFfdHhfaGFuZGxlcihz dHJ1Y3QgbXRrX2NoYW4gKmMpCit7CisJc3RydWN0IG10a191YXJ0X2FwZG1hX2Rlc2MgKmQgPSBj LT5kZXNjOworCisJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX0lOVF9GTEFHLCBWRkZfVFhf SU5UX0NMUl9CKTsKKwltdGtfdWFydF9hcGRtYV93cml0ZShjLCBWRkZfSU5UX0VOLCBWRkZfSU5U X0VOX0NMUl9CKTsKKwltdGtfdWFydF9hcGRtYV93cml0ZShjLCBWRkZfRU4sIFZGRl9FTl9DTFJf Qik7CisKKwlsaXN0X2RlbCgmZC0+dmQubm9kZSk7CisJdmNoYW5fY29va2llX2NvbXBsZXRlKCZk LT52ZCk7Cit9CisKK3N0YXRpYyB2b2lkIG10a191YXJ0X2FwZG1hX3J4X2hhbmRsZXIoc3RydWN0 IG10a19jaGFuICpjKQoreworCXN0cnVjdCBtdGtfdWFydF9hcGRtYV9kZXNjICpkID0gYy0+ZGVz YzsKKwl1bnNpZ25lZCBpbnQgbGVuLCB3Zywgcmc7CisJaW50IGNudDsKKworCW10a191YXJ0X2Fw ZG1hX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1JYX0lOVF9DTFJfQik7CisKKwlpZiAoIW10 a191YXJ0X2FwZG1hX3JlYWQoYywgVkZGX1ZBTElEX1NJWkUpKQorCQlyZXR1cm47CisKKwltdGtf dWFydF9hcGRtYV93cml0ZShjLCBWRkZfRU4sIFZGRl9FTl9DTFJfQik7CisJbXRrX3VhcnRfYXBk bWFfd3JpdGUoYywgVkZGX0lOVF9FTiwgVkZGX0lOVF9FTl9DTFJfQik7CisKKwlsZW4gPSBjLT5j Zmcuc3JjX3BvcnRfd2luZG93X3NpemU7CisJcmcgPSBtdGtfdWFydF9hcGRtYV9yZWFkKGMsIFZG Rl9SUFQpOworCXdnID0gbXRrX3VhcnRfYXBkbWFfcmVhZChjLCBWRkZfV1BUKTsKKwljbnQgPSAo d2cgJiBWRkZfUklOR19TSVpFKSAtIChyZyAmIFZGRl9SSU5HX1NJWkUpOworCisJLyoKKwkgKiBU aGUgYnVmZmVyIGlzIHJpbmcgYnVmZmVyLiBJZiB3cmFwIGJpdCBkaWZmZXJlbnQsCisJICogcmVw cmVzZW50cyB0aGUgc3RhcnQgb2YgdGhlIG5leHQgY3ljbGUgZm9yIFdQVAorCSAqLworCWlmICgo cmcgXiB3ZykgJiBWRkZfUklOR19XUkFQKQorCQljbnQgKz0gbGVuOworCisJYy0+cnhfc3RhdHVz ID0gZC0+YXZhaWxfbGVuIC0gY250OworCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9SUFQs IHdnKTsKKworCWxpc3RfZGVsKCZkLT52ZC5ub2RlKTsKKwl2Y2hhbl9jb29raWVfY29tcGxldGUo JmQtPnZkKTsKK30KKworc3RhdGljIGlycXJldHVybl90IG10a191YXJ0X2FwZG1hX2lycV9oYW5k bGVyKGludCBpcnEsIHZvaWQgKmRldl9pZCkKK3sKKwlzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4gPSAo c3RydWN0IGRtYV9jaGFuICopZGV2X2lkOworCXN0cnVjdCBtdGtfY2hhbiAqYyA9IHRvX210a191 YXJ0X2FwZG1hX2NoYW4oY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCXNwaW5fbG9j a19pcnFzYXZlKCZjLT52Yy5sb2NrLCBmbGFncyk7CisJaWYgKGMtPmRpciA9PSBETUFfREVWX1RP X01FTSkKKwkJbXRrX3VhcnRfYXBkbWFfcnhfaGFuZGxlcihjKTsKKwllbHNlIGlmIChjLT5kaXIg PT0gRE1BX01FTV9UT19ERVYpCisJCW10a191YXJ0X2FwZG1hX3R4X2hhbmRsZXIoYyk7CisJc3Bp bl91bmxvY2tfaXJxcmVzdG9yZSgmYy0+dmMubG9jaywgZmxhZ3MpOworCisJcmV0dXJuIElSUV9I QU5ETEVEOworfQorCitzdGF0aWMgaW50IG10a191YXJ0X2FwZG1hX2FsbG9jX2NoYW5fcmVzb3Vy Y2VzKHN0cnVjdCBkbWFfY2hhbiAqY2hhbikKK3sKKwlzdHJ1Y3QgbXRrX3VhcnRfYXBkbWFkZXYg Km10a2QgPSB0b19tdGtfdWFydF9hcGRtYV9kZXYoY2hhbi0+ZGV2aWNlKTsKKwlzdHJ1Y3QgbXRr X2NoYW4gKmMgPSB0b19tdGtfdWFydF9hcGRtYV9jaGFuKGNoYW4pOworCXVuc2lnbmVkIGludCBz dGF0dXM7CisJaW50IHJldDsKKworCXJldCA9IHBtX3J1bnRpbWVfZ2V0X3N5bmMobXRrZC0+ZGRl di5kZXYpOworCWlmIChyZXQgPCAwKSB7CisJCXBtX3J1bnRpbWVfcHV0X25vaWRsZShjaGFuLT5k ZXZpY2UtPmRldik7CisJCXJldHVybiByZXQ7CisJfQorCisJbXRrX3VhcnRfYXBkbWFfd3JpdGUo YywgVkZGX0FERFIsIDApOworCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9USFJFLCAwKTsK KwltdGtfdWFydF9hcGRtYV93cml0ZShjLCBWRkZfTEVOLCAwKTsKKwltdGtfdWFydF9hcGRtYV93 cml0ZShjLCBWRkZfUlNULCBWRkZfV0FSTV9SU1RfQik7CisKKwlyZXQgPSByZWFkeF9wb2xsX3Rp bWVvdXQocmVhZGwsIGMtPmJhc2UgKyBWRkZfRU4sCisJCQkgIHN0YXR1cywgIXN0YXR1cywgMTAs IDEwMCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJldCA9IHJlcXVlc3RfaXJxKGMt PmlycSwgbXRrX3VhcnRfYXBkbWFfaXJxX2hhbmRsZXIsCisJCQkgIElSUUZfVFJJR0dFUl9OT05F LCBLQlVJTERfTU9ETkFNRSwgY2hhbik7CisJaWYgKHJldCA8IDApIHsKKwkJZGV2X2VycihjaGFu LT5kZXZpY2UtPmRldiwgIkNhbid0IHJlcXVlc3QgZG1hIElSUVxuIik7CisJCXJldHVybiAtRUlO VkFMOworCX0KKworCWlmIChtdGtkLT5zdXBwb3J0XzMzYml0cykKKwkJbXRrX3VhcnRfYXBkbWFf d3JpdGUoYywgVkZGXzRHX1NVUFBPUlQsIFZGRl80R19TVVBQT1JUX0NMUl9CKTsKKworCXJldHVy biByZXQ7Cit9CisKK3N0YXRpYyB2b2lkIG10a191YXJ0X2FwZG1hX2ZyZWVfY2hhbl9yZXNvdXJj ZXMoc3RydWN0IGRtYV9jaGFuICpjaGFuKQoreworCXN0cnVjdCBtdGtfdWFydF9hcGRtYWRldiAq bXRrZCA9IHRvX210a191YXJ0X2FwZG1hX2RldihjaGFuLT5kZXZpY2UpOworCXN0cnVjdCBtdGtf Y2hhbiAqYyA9IHRvX210a191YXJ0X2FwZG1hX2NoYW4oY2hhbik7CisKKwlmcmVlX2lycShjLT5p cnEsIGNoYW4pOworCisJdGFza2xldF9raWxsKCZjLT52Yy50YXNrKTsKKworCXZjaGFuX2ZyZWVf Y2hhbl9yZXNvdXJjZXMoJmMtPnZjKTsKKworCXBtX3J1bnRpbWVfcHV0X3N5bmMobXRrZC0+ZGRl di5kZXYpOworfQorCitzdGF0aWMgZW51bSBkbWFfc3RhdHVzIG10a191YXJ0X2FwZG1hX3R4X3N0 YXR1cyhzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4sCisJCQkJCSBkbWFfY29va2llX3QgY29va2llLAor CQkJCQkgc3RydWN0IGRtYV90eF9zdGF0ZSAqdHhzdGF0ZSkKK3sKKwlzdHJ1Y3QgbXRrX2NoYW4g KmMgPSB0b19tdGtfdWFydF9hcGRtYV9jaGFuKGNoYW4pOworCWVudW0gZG1hX3N0YXR1cyByZXQ7 CisKKwlyZXQgPSBkbWFfY29va2llX3N0YXR1cyhjaGFuLCBjb29raWUsIHR4c3RhdGUpOworCWlm ICghdHhzdGF0ZSkKKwkJcmV0dXJuIHJldDsKKworCWRtYV9zZXRfcmVzaWR1ZSh0eHN0YXRlLCBj LT5yeF9zdGF0dXMpOworCisJcmV0dXJuIHJldDsKK30KKworLyoKKyAqIGRtYWVuZ2luZV9wcmVw X3NsYXZlX3NpbmdsZSB3aWxsIGNhbGwgdGhlIGZ1bmN0aW9uLiBhbmQgc2dsZW4gaXMgMS4KKyAq IDgyNTAgdWFydCB1c2luZyBvbmUgcmluZyBidWZmZXIsIGFuZCBkZWFsIHdpdGggb25lIHNnLgor ICovCitzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICptdGtfdWFydF9hcGRt YV9wcmVwX3NsYXZlX3NnCisJKHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwgc3RydWN0IHNjYXR0ZXJs aXN0ICpzZ2wsCisJdW5zaWduZWQgaW50IHNnbGVuLCBlbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rp b24gZGlyLAorCXVuc2lnbmVkIGxvbmcgdHhfZmxhZ3MsIHZvaWQgKmNvbnRleHQpCit7CisJc3Ry dWN0IG10a19jaGFuICpjID0gdG9fbXRrX3VhcnRfYXBkbWFfY2hhbihjaGFuKTsKKwlzdHJ1Y3Qg bXRrX3VhcnRfYXBkbWFfZGVzYyAqZDsKKworCWlmICghaXNfc2xhdmVfZGlyZWN0aW9uKGRpcikg fHwgc2dsZW4gIT0gMSkKKwkJcmV0dXJuIE5VTEw7CisKKwkvKiBOb3cgYWxsb2NhdGUgYW5kIHNl dHVwIHRoZSBkZXNjcmlwdG9yICovCisJZCA9IGt6YWxsb2Moc2l6ZW9mKCpkKSwgR0ZQX0FUT01J Qyk7CisJaWYgKCFkKQorCQlyZXR1cm4gTlVMTDsKKworCWQtPmF2YWlsX2xlbiA9IHNnX2RtYV9s ZW4oc2dsKTsKKwlkLT5hZGRyID0gc2dfZG1hX2FkZHJlc3Moc2dsKTsKKwljLT5kaXIgPSBkaXI7 CisKKwlyZXR1cm4gdmNoYW5fdHhfcHJlcCgmYy0+dmMsICZkLT52ZCwgdHhfZmxhZ3MpOworfQor CitzdGF0aWMgdm9pZCBtdGtfdWFydF9hcGRtYV9pc3N1ZV9wZW5kaW5nKHN0cnVjdCBkbWFfY2hh biAqY2hhbikKK3sKKwlzdHJ1Y3QgbXRrX2NoYW4gKmMgPSB0b19tdGtfdWFydF9hcGRtYV9jaGFu KGNoYW4pOworCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKKwl1bnNpZ25lZCBsb25nIGZsYWdz OworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmMtPnZjLmxvY2ssIGZsYWdzKTsKKwlpZiAodmNoYW5f aXNzdWVfcGVuZGluZygmYy0+dmMpKSB7CisJCXZkID0gdmNoYW5fbmV4dF9kZXNjKCZjLT52Yyk7 CisJCWMtPmRlc2MgPSB0b19tdGtfdWFydF9hcGRtYV9kZXNjKCZ2ZC0+dHgpOworCisJCWlmIChj LT5kaXIgPT0gRE1BX0RFVl9UT19NRU0pCisJCQltdGtfdWFydF9hcGRtYV9zdGFydF9yeChjKTsK KwkJZWxzZSBpZiAoYy0+ZGlyID09IERNQV9NRU1fVE9fREVWKQorCQkJbXRrX3VhcnRfYXBkbWFf c3RhcnRfdHgoYyk7CisJfQorCisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmYy0+dmMubG9jaywg ZmxhZ3MpOworfQorCitzdGF0aWMgaW50IG10a191YXJ0X2FwZG1hX3NsYXZlX2NvbmZpZyhzdHJ1 Y3QgZG1hX2NoYW4gKmNoYW4sCisJCQkJICAgc3RydWN0IGRtYV9zbGF2ZV9jb25maWcgKmNvbmZp ZykKK3sKKwlzdHJ1Y3QgbXRrX2NoYW4gKmMgPSB0b19tdGtfdWFydF9hcGRtYV9jaGFuKGNoYW4p OworCisJbWVtY3B5KCZjLT5jZmcsIGNvbmZpZywgc2l6ZW9mKCpjb25maWcpKTsKKworCXJldHVy biAwOworfQorCitzdGF0aWMgaW50IG10a191YXJ0X2FwZG1hX3Rlcm1pbmF0ZV9hbGwoc3RydWN0 IGRtYV9jaGFuICpjaGFuKQoreworCXN0cnVjdCBtdGtfY2hhbiAqYyA9IHRvX210a191YXJ0X2Fw ZG1hX2NoYW4oY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwl1bnNpZ25lZCBpbnQgc3Rh dHVzOworCUxJU1RfSEVBRChoZWFkKTsKKwlpbnQgcmV0OworCisJbXRrX3VhcnRfYXBkbWFfd3Jp dGUoYywgVkZGX0ZMVVNILCBWRkZfRkxVU0hfQik7CisKKwlyZXQgPSByZWFkeF9wb2xsX3RpbWVv dXQocmVhZGwsIGMtPmJhc2UgKyBWRkZfRkxVU0gsCisJCQkgIHN0YXR1cywgc3RhdHVzICE9IFZG Rl9GTFVTSF9CLCAxMCwgMTAwKTsKKwlpZiAocmV0KQorCQlkZXZfZXJyKGMtPnZjLmNoYW4uZGV2 aWNlLT5kZXYsICJmbHVzaDogZmFpbCwgc3RhdHVzPTB4JXhcbiIsCisJCQltdGtfdWFydF9hcGRt YV9yZWFkKGMsIFZGRl9ERUJVR19TVEFUVVMpKTsKKworCS8qCisJICogU3RvcCBuZWVkIDMgc3Rl cHMuCisJICogMS4gc2V0IHN0b3AgdG8gMQorCSAqIDIuIHdhaXQgZW4gdG8gMAorCSAqIDMuIHNl dCBzdG9wIGFzIDAKKwkgKi8KKwltdGtfdWFydF9hcGRtYV93cml0ZShjLCBWRkZfU1RPUCwgVkZG X1NUT1BfQik7CisJcmV0ID0gcmVhZHhfcG9sbF90aW1lb3V0KHJlYWRsLCBjLT5iYXNlICsgVkZG X0VOLAorCQkJICBzdGF0dXMsICFzdGF0dXMsIDEwLCAxMDApOworCWlmIChyZXQpCisJCWRldl9l cnIoYy0+dmMuY2hhbi5kZXZpY2UtPmRldiwgInN0b3A6IGZhaWwsIHN0YXR1cz0weCV4XG4iLAor CQkJbXRrX3VhcnRfYXBkbWFfcmVhZChjLCBWRkZfREVCVUdfU1RBVFVTKSk7CisKKwltdGtfdWFy dF9hcGRtYV93cml0ZShjLCBWRkZfU1RPUCwgVkZGX1NUT1BfQ0xSX0IpOworCW10a191YXJ0X2Fw ZG1hX3dyaXRlKGMsIFZGRl9JTlRfRU4sIFZGRl9JTlRfRU5fQ0xSX0IpOworCisJaWYgKGMtPmRp ciA9PSBETUFfREVWX1RPX01FTSkKKwkJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX0lOVF9G TEFHLCBWRkZfUlhfSU5UX0NMUl9CKTsKKwllbHNlIGlmIChjLT5kaXIgPT0gRE1BX01FTV9UT19E RVYpCisJCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1RYX0lOVF9D TFJfQik7CisKKwlzeW5jaHJvbml6ZV9pcnEoYy0+aXJxKTsKKworCXNwaW5fbG9ja19pcnFzYXZl KCZjLT52Yy5sb2NrLCBmbGFncyk7CisJdmNoYW5fZ2V0X2FsbF9kZXNjcmlwdG9ycygmYy0+dmMs ICZoZWFkKTsKKwl2Y2hhbl9kbWFfZGVzY19mcmVlX2xpc3QoJmMtPnZjLCAmaGVhZCk7CisJc3Bp bl91bmxvY2tfaXJxcmVzdG9yZSgmYy0+dmMubG9jaywgZmxhZ3MpOworCisJcmV0dXJuIDA7Cit9 CisKK3N0YXRpYyBpbnQgbXRrX3VhcnRfYXBkbWFfZGV2aWNlX3BhdXNlKHN0cnVjdCBkbWFfY2hh biAqY2hhbikKK3sKKwlzdHJ1Y3QgbXRrX2NoYW4gKmMgPSB0b19tdGtfdWFydF9hcGRtYV9jaGFu KGNoYW4pOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmYy0+ dmMubG9jaywgZmxhZ3MpOworCisJbXRrX3VhcnRfYXBkbWFfd3JpdGUoYywgVkZGX0VOLCBWRkZf RU5fQ0xSX0IpOworCW10a191YXJ0X2FwZG1hX3dyaXRlKGMsIFZGRl9JTlRfRU4sIFZGRl9JTlRf RU5fQ0xSX0IpOworCisJc3luY2hyb25pemVfaXJxKGMtPmlycSk7CisKKwlzcGluX3VubG9ja19p cnFyZXN0b3JlKCZjLT52Yy5sb2NrLCBmbGFncyk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGlj IHZvaWQgbXRrX3VhcnRfYXBkbWFfZnJlZShzdHJ1Y3QgbXRrX3VhcnRfYXBkbWFkZXYgKm10a2Qp Cit7CisJd2hpbGUgKCFsaXN0X2VtcHR5KCZtdGtkLT5kZGV2LmNoYW5uZWxzKSkgeworCQlzdHJ1 Y3QgbXRrX2NoYW4gKmMgPSBsaXN0X2ZpcnN0X2VudHJ5KCZtdGtkLT5kZGV2LmNoYW5uZWxzLAor CQkJc3RydWN0IG10a19jaGFuLCB2Yy5jaGFuLmRldmljZV9ub2RlKTsKKworCQlsaXN0X2RlbCgm Yy0+dmMuY2hhbi5kZXZpY2Vfbm9kZSk7CisJCXRhc2tsZXRfa2lsbCgmYy0+dmMudGFzayk7CisJ fQorfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBtdGtfdWFydF9hcGRtYV9t YXRjaFtdID0geworCXsgLmNvbXBhdGlibGUgPSAibWVkaWF0ZWssbXQ2NTc3LXVhcnQtZG1hIiwg fSwKKwl7IC8qIHNlbnRpbmVsICovIH0sCit9OworTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgbXRr X3VhcnRfYXBkbWFfbWF0Y2gpOworCitzdGF0aWMgaW50IG10a191YXJ0X2FwZG1hX3Byb2JlKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IGRldmljZV9ub2RlICpucCA9 IHBkZXYtPmRldi5vZl9ub2RlOworCXN0cnVjdCBtdGtfdWFydF9hcGRtYWRldiAqbXRrZDsKKwlp bnQgYml0X21hc2sgPSAzMiwgcmM7CisJc3RydWN0IHJlc291cmNlICpyZXM7CisJc3RydWN0IG10 a19jaGFuICpjOworCXVuc2lnbmVkIGludCBpOworCisJbXRrZCA9IGRldm1fa3phbGxvYygmcGRl di0+ZGV2LCBzaXplb2YoKm10a2QpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIW10a2QpCisJCXJldHVy biAtRU5PTUVNOworCisJbXRrZC0+Y2xrID0gZGV2bV9jbGtfZ2V0KCZwZGV2LT5kZXYsIE5VTEwp OworCWlmIChJU19FUlIobXRrZC0+Y2xrKSkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJObyBj bG9jayBzcGVjaWZpZWRcbiIpOworCQlyYyA9IFBUUl9FUlIobXRrZC0+Y2xrKTsKKwkJcmV0dXJu IHJjOworCX0KKworCWlmIChvZl9wcm9wZXJ0eV9yZWFkX2Jvb2wobnAsICJtZWRpYXRlayxkbWEt MzNiaXRzIikpCisJCW10a2QtPnN1cHBvcnRfMzNiaXRzID0gdHJ1ZTsKKworCWlmIChtdGtkLT5z dXBwb3J0XzMzYml0cykKKwkJYml0X21hc2sgPSAzMzsKKworCXJjID0gZG1hX3NldF9tYXNrX2Fu ZF9jb2hlcmVudCgmcGRldi0+ZGV2LCBETUFfQklUX01BU0soYml0X21hc2spKTsKKwlpZiAocmMp CisJCXJldHVybiByYzsKKworCWRtYV9jYXBfc2V0KERNQV9TTEFWRSwgbXRrZC0+ZGRldi5jYXBf bWFzayk7CisJbXRrZC0+ZGRldi5kZXZpY2VfYWxsb2NfY2hhbl9yZXNvdXJjZXMgPQorCQkJCW10 a191YXJ0X2FwZG1hX2FsbG9jX2NoYW5fcmVzb3VyY2VzOworCW10a2QtPmRkZXYuZGV2aWNlX2Zy ZWVfY2hhbl9yZXNvdXJjZXMgPQorCQkJCW10a191YXJ0X2FwZG1hX2ZyZWVfY2hhbl9yZXNvdXJj ZXM7CisJbXRrZC0+ZGRldi5kZXZpY2VfdHhfc3RhdHVzID0gbXRrX3VhcnRfYXBkbWFfdHhfc3Rh dHVzOworCW10a2QtPmRkZXYuZGV2aWNlX2lzc3VlX3BlbmRpbmcgPSBtdGtfdWFydF9hcGRtYV9p c3N1ZV9wZW5kaW5nOworCW10a2QtPmRkZXYuZGV2aWNlX3ByZXBfc2xhdmVfc2cgPSBtdGtfdWFy dF9hcGRtYV9wcmVwX3NsYXZlX3NnOworCW10a2QtPmRkZXYuZGV2aWNlX2NvbmZpZyA9IG10a191 YXJ0X2FwZG1hX3NsYXZlX2NvbmZpZzsKKwltdGtkLT5kZGV2LmRldmljZV9wYXVzZSA9IG10a191 YXJ0X2FwZG1hX2RldmljZV9wYXVzZTsKKwltdGtkLT5kZGV2LmRldmljZV90ZXJtaW5hdGVfYWxs ID0gbXRrX3VhcnRfYXBkbWFfdGVybWluYXRlX2FsbDsKKwltdGtkLT5kZGV2LnNyY19hZGRyX3dp ZHRocyA9IEJJVChETUFfU0xBVkVfQlVTV0lEVEhfMV9CWVRFKTsKKwltdGtkLT5kZGV2LmRzdF9h ZGRyX3dpZHRocyA9IEJJVChETUFfU0xBVkVfQlVTV0lEVEhfMV9CWVRFKTsKKwltdGtkLT5kZGV2 LmRpcmVjdGlvbnMgPSBCSVQoRE1BX0RFVl9UT19NRU0pIHwgQklUKERNQV9NRU1fVE9fREVWKTsK KwltdGtkLT5kZGV2LnJlc2lkdWVfZ3JhbnVsYXJpdHkgPSBETUFfUkVTSURVRV9HUkFOVUxBUklU WV9TRUdNRU5UOworCW10a2QtPmRkZXYuZGV2ID0gJnBkZXYtPmRldjsKKwlJTklUX0xJU1RfSEVB RCgmbXRrZC0+ZGRldi5jaGFubmVscyk7CisKKwltdGtkLT5kbWFfcmVxdWVzdHMgPSBNVEtfVUFS VF9BUERNQV9OUl9WQ0hBTlM7CisJaWYgKG9mX3Byb3BlcnR5X3JlYWRfdTMyKG5wLCAiZG1hLXJl cXVlc3RzIiwgJm10a2QtPmRtYV9yZXF1ZXN0cykpIHsKKwkJZGV2X2luZm8oJnBkZXYtPmRldiwK KwkJCSAiVXNpbmcgJXUgYXMgbWlzc2luZyBkbWEtcmVxdWVzdHMgcHJvcGVydHlcbiIsCisJCQkg TVRLX1VBUlRfQVBETUFfTlJfVkNIQU5TKTsKKwl9CisKKwlmb3IgKGkgPSAwOyBpIDwgbXRrZC0+ ZG1hX3JlcXVlc3RzOyBpKyspIHsKKwkJYyA9IGRldm1fa3phbGxvYyhtdGtkLT5kZGV2LmRldiwg c2l6ZW9mKCpjKSwgR0ZQX0tFUk5FTCk7CisJCWlmICghYykgeworCQkJcmMgPSAtRU5PREVWOwor CQkJZ290byBlcnJfbm9fZG1hOworCQl9CisKKwkJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNl KHBkZXYsIElPUkVTT1VSQ0VfTUVNLCBpKTsKKwkJaWYgKCFyZXMpIHsKKwkJCXJjID0gLUVOT0RF VjsKKwkJCWdvdG8gZXJyX25vX2RtYTsKKwkJfQorCisJCWMtPmJhc2UgPSBkZXZtX2lvcmVtYXBf cmVzb3VyY2UoJnBkZXYtPmRldiwgcmVzKTsKKwkJaWYgKElTX0VSUihjLT5iYXNlKSkgeworCQkJ cmMgPSBQVFJfRVJSKGMtPmJhc2UpOworCQkJZ290byBlcnJfbm9fZG1hOworCQl9CisJCWMtPnZj LmRlc2NfZnJlZSA9IG10a191YXJ0X2FwZG1hX2Rlc2NfZnJlZTsKKwkJdmNoYW5faW5pdCgmYy0+ dmMsICZtdGtkLT5kZGV2KTsKKworCQlyYyA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwgaSk7CisJ CWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIoJnBkZXYtPmRldiwgImZhaWxlZCB0byBnZXQgSVJR WyVkXVxuIiwgaSk7CisJCQlnb3RvIGVycl9ub19kbWE7CisJCX0KKwkJYy0+aXJxID0gcmM7CisJ fQorCisJcG1fcnVudGltZV9lbmFibGUoJnBkZXYtPmRldik7CisJcG1fcnVudGltZV9zZXRfYWN0 aXZlKCZwZGV2LT5kZXYpOworCisJcmMgPSBkbWFfYXN5bmNfZGV2aWNlX3JlZ2lzdGVyKCZtdGtk LT5kZGV2KTsKKwlpZiAocmMpCisJCWdvdG8gcnBtX2Rpc2FibGU7CisKKwlwbGF0Zm9ybV9zZXRf ZHJ2ZGF0YShwZGV2LCBtdGtkKTsKKworCS8qIERldmljZS10cmVlIERNQSBjb250cm9sbGVyIHJl Z2lzdHJhdGlvbiAqLworCXJjID0gb2ZfZG1hX2NvbnRyb2xsZXJfcmVnaXN0ZXIobnAsIG9mX2Rt YV94bGF0ZV9ieV9jaGFuX2lkLCBtdGtkKTsKKwlpZiAocmMpCisJCWdvdG8gZG1hX3JlbW92ZTsK KworCXJldHVybiByYzsKKworZG1hX3JlbW92ZToKKwlkbWFfYXN5bmNfZGV2aWNlX3VucmVnaXN0 ZXIoJm10a2QtPmRkZXYpOworcnBtX2Rpc2FibGU6CisJcG1fcnVudGltZV9kaXNhYmxlKCZwZGV2 LT5kZXYpOworZXJyX25vX2RtYToKKwltdGtfdWFydF9hcGRtYV9mcmVlKG10a2QpOworCXJldHVy biByYzsKK30KKworc3RhdGljIGludCBtdGtfdWFydF9hcGRtYV9yZW1vdmUoc3RydWN0IHBsYXRm b3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgbXRrX3VhcnRfYXBkbWFkZXYgKm10a2QgPSBw bGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKworCW9mX2RtYV9jb250cm9sbGVyX2ZyZWUocGRl di0+ZGV2Lm9mX25vZGUpOworCisJbXRrX3VhcnRfYXBkbWFfZnJlZShtdGtkKTsKKworCWRtYV9h c3luY19kZXZpY2VfdW5yZWdpc3RlcigmbXRrZC0+ZGRldik7CisKKwlwbV9ydW50aW1lX2Rpc2Fi bGUoJnBkZXYtPmRldik7CisKKwlyZXR1cm4gMDsKK30KKworI2lmZGVmIENPTkZJR19QTV9TTEVF UAorc3RhdGljIGludCBtdGtfdWFydF9hcGRtYV9zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikK K3sKKwlzdHJ1Y3QgbXRrX3VhcnRfYXBkbWFkZXYgKm10a2QgPSBkZXZfZ2V0X2RydmRhdGEoZGV2 KTsKKworCWlmICghcG1fcnVudGltZV9zdXNwZW5kZWQoZGV2KSkKKwkJY2xrX2Rpc2FibGVfdW5w cmVwYXJlKG10a2QtPmNsayk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBtdGtfdWFy dF9hcGRtYV9yZXN1bWUoc3RydWN0IGRldmljZSAqZGV2KQoreworCWludCByZXQ7CisJc3RydWN0 IG10a191YXJ0X2FwZG1hZGV2ICptdGtkID0gZGV2X2dldF9kcnZkYXRhKGRldik7CisKKwlpZiAo IXBtX3J1bnRpbWVfc3VzcGVuZGVkKGRldikpIHsKKwkJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxl KG10a2QtPmNsayk7CisJCWlmIChyZXQpCisJCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiAw OworfQorI2VuZGlmIC8qIENPTkZJR19QTV9TTEVFUCAqLworCisjaWZkZWYgQ09ORklHX1BNCitz dGF0aWMgaW50IG10a191YXJ0X2FwZG1hX3J1bnRpbWVfc3VzcGVuZChzdHJ1Y3QgZGV2aWNlICpk ZXYpCit7CisJc3RydWN0IG10a191YXJ0X2FwZG1hZGV2ICptdGtkID0gZGV2X2dldF9kcnZkYXRh KGRldik7CisKKwljbGtfZGlzYWJsZV91bnByZXBhcmUobXRrZC0+Y2xrKTsKKworCXJldHVybiAw OworfQorCitzdGF0aWMgaW50IG10a191YXJ0X2FwZG1hX3J1bnRpbWVfcmVzdW1lKHN0cnVjdCBk ZXZpY2UgKmRldikKK3sKKwlpbnQgcmV0OworCXN0cnVjdCBtdGtfdWFydF9hcGRtYWRldiAqbXRr ZCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCisJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKG10 a2QtPmNsayk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJldDsKKworCXJldHVybiAwOworfQorI2Vu ZGlmIC8qIENPTkZJR19QTSAqLworCitzdGF0aWMgY29uc3Qgc3RydWN0IGRldl9wbV9vcHMgbXRr X3VhcnRfYXBkbWFfcG1fb3BzID0geworCVNFVF9TWVNURU1fU0xFRVBfUE1fT1BTKG10a191YXJ0 X2FwZG1hX3N1c3BlbmQsIG10a191YXJ0X2FwZG1hX3Jlc3VtZSkKKwlTRVRfUlVOVElNRV9QTV9P UFMobXRrX3VhcnRfYXBkbWFfcnVudGltZV9zdXNwZW5kLAorCQkJICAgbXRrX3VhcnRfYXBkbWFf cnVudGltZV9yZXN1bWUsIE5VTEwpCit9OworCitzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZl ciBtdGtfdWFydF9hcGRtYV9kcml2ZXIgPSB7CisJLnByb2JlCT0gbXRrX3VhcnRfYXBkbWFfcHJv YmUsCisJLnJlbW92ZQk9IG10a191YXJ0X2FwZG1hX3JlbW92ZSwKKwkuZHJpdmVyID0geworCQku bmFtZQkJPSBLQlVJTERfTU9ETkFNRSwKKwkJLnBtCQk9ICZtdGtfdWFydF9hcGRtYV9wbV9vcHMs CisJCS5vZl9tYXRjaF90YWJsZSA9IG9mX21hdGNoX3B0cihtdGtfdWFydF9hcGRtYV9tYXRjaCks CisJfSwKK307CisKK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIobXRrX3VhcnRfYXBkbWFfZHJpdmVy KTsKKworTU9EVUxFX0RFU0NSSVBUSU9OKCJNZWRpYVRlayBVQVJUIEFQRE1BIENvbnRyb2xsZXIg RHJpdmVyIik7CitNT0RVTEVfQVVUSE9SKCJMb25nIENoZW5nIDxsb25nLmNoZW5nQG1lZGlhdGVr LmNvbT4iKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsK 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=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,UNPARSEABLE_RELAY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable 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 D4620C43219 for ; Sat, 27 Apr 2019 03:37:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8DD63206C1 for ; Sat, 27 Apr 2019 03:37:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726861AbfD0Dg4 (ORCPT ); Fri, 26 Apr 2019 23:36:56 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:27878 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725933AbfD0Dgz (ORCPT ); Fri, 26 Apr 2019 23:36:55 -0400 X-UUID: d2d1505ba0f34e09a8fe5e80b7d4ef9d-20190427 X-UUID: d2d1505ba0f34e09a8fe5e80b7d4ef9d-20190427 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 1073761034; Sat, 27 Apr 2019 11:36:50 +0800 Received: from mtkcas07.mediatek.inc (172.21.101.84) by mtkmbs03n2.mediatek.inc (172.21.101.182) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Sat, 27 Apr 2019 11:36:42 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Sat, 27 Apr 2019 11:36:41 +0800 From: Long Cheng To: Vinod Koul , Randy Dunlap , "Rob Herring" , Mark Rutland , Ryder Lee , Sean Wang , Nicolas Boichat , Matthias Brugger CC: Dan Williams , Greg Kroah-Hartman , Jiri Slaby , Sean Wang , , , , , , , , Yingjoe Chen , YT Shen , Zhenbao Liu , Long Cheng Subject: [PATCH 1/4] dmaengine: mediatek: Add MediaTek UART APDMA support Date: Sat, 27 Apr 2019 11:36:30 +0800 Message-ID: <1556336193-15198-2-git-send-email-long.cheng@mediatek.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1556336193-15198-1-git-send-email-long.cheng@mediatek.com> References: <1556336193-15198-1-git-send-email-long.cheng@mediatek.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" X-TM-SNTS-SMTP: 7F8DA4DC7EDB503104174522F7C93896631D3AA5BC1BA5A4BF2169237ECCA62E2000:8 X-MTK: N Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org Message-ID: <20190427033630.Ap_7FRLfI662v5-QQH6rcpw1Qzp3wyy9RSs5ED8AQfA@z> Add 8250 UART APDMA to support MediaTek UART. If MediaTek UART is enabled by SERIAL_8250_MT6577, and we can enable this driver to offload the UART device moving bytes. Signed-off-by: Long Cheng Signed-off-by: Sean Wang --- drivers/dma/mediatek/Kconfig | 11 + drivers/dma/mediatek/Makefile | 1 + drivers/dma/mediatek/mtk-uart-apdma.c | 666 +++++++++++++++++++++++++++++++++ 3 files changed, 678 insertions(+) create mode 100644 drivers/dma/mediatek/mtk-uart-apdma.c diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig index 680fc05..ac49eb6 100644 --- a/drivers/dma/mediatek/Kconfig +++ b/drivers/dma/mediatek/Kconfig @@ -24,3 +24,14 @@ config MTK_CQDMA This controller provides the channels which is dedicated to memory-to-memory transfer to offload from CPU. + +config MTK_UART_APDMA + tristate "MediaTek SoCs APDMA support for UART" + depends on OF && SERIAL_8250_MT6577 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Support for the UART DMA engine found on MediaTek MTK SoCs. + When SERIAL_8250_MT6577 is enabled, and if you want to use DMA, + you can enable the config. The DMA engine can only be used + with MediaTek SoCs. diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile index 41bb381..61a6d29 100644 --- a/drivers/dma/mediatek/Makefile +++ b/drivers/dma/mediatek/Makefile @@ -1,2 +1,3 @@ +obj-$(CONFIG_MTK_UART_APDMA) += mtk-uart-apdma.o obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o obj-$(CONFIG_MTK_CQDMA) += mtk-cqdma.o diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c new file mode 100644 index 0000000..546995c --- /dev/null +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -0,0 +1,666 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek UART APDMA driver. + * + * Copyright (c) 2019 MediaTek Inc. + * Author: Long Cheng + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../virt-dma.h" + +/* The default number of virtual channel */ +#define MTK_UART_APDMA_NR_VCHANS 8 + +#define VFF_EN_B BIT(0) +#define VFF_STOP_B BIT(0) +#define VFF_FLUSH_B BIT(0) +#define VFF_4G_EN_B BIT(0) +/* rx valid size >= vff thre */ +#define VFF_RX_INT_EN_B (BIT(0) | BIT(1)) +/* tx left size >= vff thre */ +#define VFF_TX_INT_EN_B BIT(0) +#define VFF_WARM_RST_B BIT(0) +#define VFF_RX_INT_CLR_B (BIT(0) | BIT(1)) +#define VFF_TX_INT_CLR_B 0 +#define VFF_STOP_CLR_B 0 +#define VFF_EN_CLR_B 0 +#define VFF_INT_EN_CLR_B 0 +#define VFF_4G_SUPPORT_CLR_B 0 + +/* + * interrupt trigger level for tx + * if threshold is n, no polling is required to start tx. + * otherwise need polling VFF_FLUSH. + */ +#define VFF_TX_THRE(n) (n) +/* interrupt trigger level for rx */ +#define VFF_RX_THRE(n) ((n) * 3 / 4) + +#define VFF_RING_SIZE 0xffff +/* invert this bit when wrap ring head again */ +#define VFF_RING_WRAP 0x10000 + +#define VFF_INT_FLAG 0x00 +#define VFF_INT_EN 0x04 +#define VFF_EN 0x08 +#define VFF_RST 0x0c +#define VFF_STOP 0x10 +#define VFF_FLUSH 0x14 +#define VFF_ADDR 0x1c +#define VFF_LEN 0x24 +#define VFF_THRE 0x28 +#define VFF_WPT 0x2c +#define VFF_RPT 0x30 +/* TX: the buffer size HW can read. RX: the buffer size SW can read. */ +#define VFF_VALID_SIZE 0x3c +/* TX: the buffer size SW can write. RX: the buffer size HW can write. */ +#define VFF_LEFT_SIZE 0x40 +#define VFF_DEBUG_STATUS 0x50 +#define VFF_4G_SUPPORT 0x54 + +struct mtk_uart_apdmadev { + struct dma_device ddev; + struct clk *clk; + bool support_33bits; + unsigned int dma_requests; +}; + +struct mtk_uart_apdma_desc { + struct virt_dma_desc vd; + + dma_addr_t addr; + unsigned int avail_len; +}; + +struct mtk_chan { + struct virt_dma_chan vc; + struct dma_slave_config cfg; + struct mtk_uart_apdma_desc *desc; + enum dma_transfer_direction dir; + + void __iomem *base; + unsigned int irq; + + unsigned int rx_status; +}; + +static inline struct mtk_uart_apdmadev * +to_mtk_uart_apdma_dev(struct dma_device *d) +{ + return container_of(d, struct mtk_uart_apdmadev, ddev); +} + +static inline struct mtk_chan *to_mtk_uart_apdma_chan(struct dma_chan *c) +{ + return container_of(c, struct mtk_chan, vc.chan); +} + +static inline struct mtk_uart_apdma_desc *to_mtk_uart_apdma_desc + (struct dma_async_tx_descriptor *t) +{ + return container_of(t, struct mtk_uart_apdma_desc, vd.tx); +} + +static void mtk_uart_apdma_write(struct mtk_chan *c, + unsigned int reg, unsigned int val) +{ + writel(val, c->base + reg); +} + +static unsigned int mtk_uart_apdma_read(struct mtk_chan *c, unsigned int reg) +{ + return readl(c->base + reg); +} + +static void mtk_uart_apdma_desc_free(struct virt_dma_desc *vd) +{ + struct dma_chan *chan = vd->tx.chan; + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + + kfree(c->desc); +} + +static void mtk_uart_apdma_start_tx(struct mtk_chan *c) +{ + struct mtk_uart_apdmadev *mtkd = + to_mtk_uart_apdma_dev(c->vc.chan.device); + struct mtk_uart_apdma_desc *d = c->desc; + unsigned int wpt, vff_sz; + + vff_sz = c->cfg.dst_port_window_size; + if (!mtk_uart_apdma_read(c, VFF_LEN)) { + mtk_uart_apdma_write(c, VFF_ADDR, d->addr); + mtk_uart_apdma_write(c, VFF_LEN, vff_sz); + mtk_uart_apdma_write(c, VFF_THRE, VFF_TX_THRE(vff_sz)); + mtk_uart_apdma_write(c, VFF_WPT, 0); + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); + + if (mtkd->support_33bits) + mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); + } + + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_B); + if (mtk_uart_apdma_read(c, VFF_EN) != VFF_EN_B) + dev_err(c->vc.chan.device->dev, "Enable TX fail\n"); + + if (!mtk_uart_apdma_read(c, VFF_LEFT_SIZE)) { + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); + return; + } + + wpt = mtk_uart_apdma_read(c, VFF_WPT); + + wpt += c->desc->avail_len; + if ((wpt & VFF_RING_SIZE) == vff_sz) + wpt = (wpt & VFF_RING_WRAP) ^ VFF_RING_WRAP; + + /* Let DMA start moving data */ + mtk_uart_apdma_write(c, VFF_WPT, wpt); + + /* HW auto set to 0 when left size >= threshold */ + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); + if (!mtk_uart_apdma_read(c, VFF_FLUSH)) + mtk_uart_apdma_write(c, VFF_FLUSH, VFF_FLUSH_B); +} + +static void mtk_uart_apdma_start_rx(struct mtk_chan *c) +{ + struct mtk_uart_apdmadev *mtkd = + to_mtk_uart_apdma_dev(c->vc.chan.device); + struct mtk_uart_apdma_desc *d = c->desc; + unsigned int vff_sz; + + vff_sz = c->cfg.src_port_window_size; + if (!mtk_uart_apdma_read(c, VFF_LEN)) { + mtk_uart_apdma_write(c, VFF_ADDR, d->addr); + mtk_uart_apdma_write(c, VFF_LEN, vff_sz); + mtk_uart_apdma_write(c, VFF_THRE, VFF_RX_THRE(vff_sz)); + mtk_uart_apdma_write(c, VFF_RPT, 0); + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B); + + if (mtkd->support_33bits) + mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_EN_B); + } + + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_RX_INT_EN_B); + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_B); + if (mtk_uart_apdma_read(c, VFF_EN) != VFF_EN_B) + dev_err(c->vc.chan.device->dev, "Enable RX fail\n"); +} + +static void mtk_uart_apdma_tx_handler(struct mtk_chan *c) +{ + struct mtk_uart_apdma_desc *d = c->desc; + + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); + + list_del(&d->vd.node); + vchan_cookie_complete(&d->vd); +} + +static void mtk_uart_apdma_rx_handler(struct mtk_chan *c) +{ + struct mtk_uart_apdma_desc *d = c->desc; + unsigned int len, wg, rg; + int cnt; + + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B); + + if (!mtk_uart_apdma_read(c, VFF_VALID_SIZE)) + return; + + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); + + len = c->cfg.src_port_window_size; + rg = mtk_uart_apdma_read(c, VFF_RPT); + wg = mtk_uart_apdma_read(c, VFF_WPT); + cnt = (wg & VFF_RING_SIZE) - (rg & VFF_RING_SIZE); + + /* + * The buffer is ring buffer. If wrap bit different, + * represents the start of the next cycle for WPT + */ + if ((rg ^ wg) & VFF_RING_WRAP) + cnt += len; + + c->rx_status = d->avail_len - cnt; + mtk_uart_apdma_write(c, VFF_RPT, wg); + + list_del(&d->vd.node); + vchan_cookie_complete(&d->vd); +} + +static irqreturn_t mtk_uart_apdma_irq_handler(int irq, void *dev_id) +{ + struct dma_chan *chan = (struct dma_chan *)dev_id; + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + if (c->dir == DMA_DEV_TO_MEM) + mtk_uart_apdma_rx_handler(c); + else if (c->dir == DMA_MEM_TO_DEV) + mtk_uart_apdma_tx_handler(c); + spin_unlock_irqrestore(&c->vc.lock, flags); + + return IRQ_HANDLED; +} + +static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan) +{ + struct mtk_uart_apdmadev *mtkd = to_mtk_uart_apdma_dev(chan->device); + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + unsigned int status; + int ret; + + ret = pm_runtime_get_sync(mtkd->ddev.dev); + if (ret < 0) { + pm_runtime_put_noidle(chan->device->dev); + return ret; + } + + mtk_uart_apdma_write(c, VFF_ADDR, 0); + mtk_uart_apdma_write(c, VFF_THRE, 0); + mtk_uart_apdma_write(c, VFF_LEN, 0); + mtk_uart_apdma_write(c, VFF_RST, VFF_WARM_RST_B); + + ret = readx_poll_timeout(readl, c->base + VFF_EN, + status, !status, 10, 100); + if (ret) + return ret; + + ret = request_irq(c->irq, mtk_uart_apdma_irq_handler, + IRQF_TRIGGER_NONE, KBUILD_MODNAME, chan); + if (ret < 0) { + dev_err(chan->device->dev, "Can't request dma IRQ\n"); + return -EINVAL; + } + + if (mtkd->support_33bits) + mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); + + return ret; +} + +static void mtk_uart_apdma_free_chan_resources(struct dma_chan *chan) +{ + struct mtk_uart_apdmadev *mtkd = to_mtk_uart_apdma_dev(chan->device); + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + + free_irq(c->irq, chan); + + tasklet_kill(&c->vc.task); + + vchan_free_chan_resources(&c->vc); + + pm_runtime_put_sync(mtkd->ddev.dev); +} + +static enum dma_status mtk_uart_apdma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + enum dma_status ret; + + ret = dma_cookie_status(chan, cookie, txstate); + if (!txstate) + return ret; + + dma_set_residue(txstate, c->rx_status); + + return ret; +} + +/* + * dmaengine_prep_slave_single will call the function. and sglen is 1. + * 8250 uart using one ring buffer, and deal with one sg. + */ +static struct dma_async_tx_descriptor *mtk_uart_apdma_prep_slave_sg + (struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sglen, enum dma_transfer_direction dir, + unsigned long tx_flags, void *context) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + struct mtk_uart_apdma_desc *d; + + if (!is_slave_direction(dir) || sglen != 1) + return NULL; + + /* Now allocate and setup the descriptor */ + d = kzalloc(sizeof(*d), GFP_ATOMIC); + if (!d) + return NULL; + + d->avail_len = sg_dma_len(sgl); + d->addr = sg_dma_address(sgl); + c->dir = dir; + + return vchan_tx_prep(&c->vc, &d->vd, tx_flags); +} + +static void mtk_uart_apdma_issue_pending(struct dma_chan *chan) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + struct virt_dma_desc *vd; + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + if (vchan_issue_pending(&c->vc)) { + vd = vchan_next_desc(&c->vc); + c->desc = to_mtk_uart_apdma_desc(&vd->tx); + + if (c->dir == DMA_DEV_TO_MEM) + mtk_uart_apdma_start_rx(c); + else if (c->dir == DMA_MEM_TO_DEV) + mtk_uart_apdma_start_tx(c); + } + + spin_unlock_irqrestore(&c->vc.lock, flags); +} + +static int mtk_uart_apdma_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + + memcpy(&c->cfg, config, sizeof(*config)); + + return 0; +} + +static int mtk_uart_apdma_terminate_all(struct dma_chan *chan) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + unsigned long flags; + unsigned int status; + LIST_HEAD(head); + int ret; + + mtk_uart_apdma_write(c, VFF_FLUSH, VFF_FLUSH_B); + + ret = readx_poll_timeout(readl, c->base + VFF_FLUSH, + status, status != VFF_FLUSH_B, 10, 100); + if (ret) + dev_err(c->vc.chan.device->dev, "flush: fail, status=0x%x\n", + mtk_uart_apdma_read(c, VFF_DEBUG_STATUS)); + + /* + * Stop need 3 steps. + * 1. set stop to 1 + * 2. wait en to 0 + * 3. set stop as 0 + */ + mtk_uart_apdma_write(c, VFF_STOP, VFF_STOP_B); + ret = readx_poll_timeout(readl, c->base + VFF_EN, + status, !status, 10, 100); + if (ret) + dev_err(c->vc.chan.device->dev, "stop: fail, status=0x%x\n", + mtk_uart_apdma_read(c, VFF_DEBUG_STATUS)); + + mtk_uart_apdma_write(c, VFF_STOP, VFF_STOP_CLR_B); + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); + + if (c->dir == DMA_DEV_TO_MEM) + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B); + else if (c->dir == DMA_MEM_TO_DEV) + mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); + + synchronize_irq(c->irq); + + spin_lock_irqsave(&c->vc.lock, flags); + vchan_get_all_descriptors(&c->vc, &head); + vchan_dma_desc_free_list(&c->vc, &head); + spin_unlock_irqrestore(&c->vc.lock, flags); + + return 0; +} + +static int mtk_uart_apdma_device_pause(struct dma_chan *chan) +{ + struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&c->vc.lock, flags); + + mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); + mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); + + synchronize_irq(c->irq); + + spin_unlock_irqrestore(&c->vc.lock, flags); + + return 0; +} + +static void mtk_uart_apdma_free(struct mtk_uart_apdmadev *mtkd) +{ + while (!list_empty(&mtkd->ddev.channels)) { + struct mtk_chan *c = list_first_entry(&mtkd->ddev.channels, + struct mtk_chan, vc.chan.device_node); + + list_del(&c->vc.chan.device_node); + tasklet_kill(&c->vc.task); + } +} + +static const struct of_device_id mtk_uart_apdma_match[] = { + { .compatible = "mediatek,mt6577-uart-dma", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mtk_uart_apdma_match); + +static int mtk_uart_apdma_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct mtk_uart_apdmadev *mtkd; + int bit_mask = 32, rc; + struct resource *res; + struct mtk_chan *c; + unsigned int i; + + mtkd = devm_kzalloc(&pdev->dev, sizeof(*mtkd), GFP_KERNEL); + if (!mtkd) + return -ENOMEM; + + mtkd->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mtkd->clk)) { + dev_err(&pdev->dev, "No clock specified\n"); + rc = PTR_ERR(mtkd->clk); + return rc; + } + + if (of_property_read_bool(np, "mediatek,dma-33bits")) + mtkd->support_33bits = true; + + if (mtkd->support_33bits) + bit_mask = 33; + + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(bit_mask)); + if (rc) + return rc; + + dma_cap_set(DMA_SLAVE, mtkd->ddev.cap_mask); + mtkd->ddev.device_alloc_chan_resources = + mtk_uart_apdma_alloc_chan_resources; + mtkd->ddev.device_free_chan_resources = + mtk_uart_apdma_free_chan_resources; + mtkd->ddev.device_tx_status = mtk_uart_apdma_tx_status; + mtkd->ddev.device_issue_pending = mtk_uart_apdma_issue_pending; + mtkd->ddev.device_prep_slave_sg = mtk_uart_apdma_prep_slave_sg; + mtkd->ddev.device_config = mtk_uart_apdma_slave_config; + mtkd->ddev.device_pause = mtk_uart_apdma_device_pause; + mtkd->ddev.device_terminate_all = mtk_uart_apdma_terminate_all; + mtkd->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); + mtkd->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); + mtkd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + mtkd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + mtkd->ddev.dev = &pdev->dev; + INIT_LIST_HEAD(&mtkd->ddev.channels); + + mtkd->dma_requests = MTK_UART_APDMA_NR_VCHANS; + if (of_property_read_u32(np, "dma-requests", &mtkd->dma_requests)) { + dev_info(&pdev->dev, + "Using %u as missing dma-requests property\n", + MTK_UART_APDMA_NR_VCHANS); + } + + for (i = 0; i < mtkd->dma_requests; i++) { + c = devm_kzalloc(mtkd->ddev.dev, sizeof(*c), GFP_KERNEL); + if (!c) { + rc = -ENODEV; + goto err_no_dma; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) { + rc = -ENODEV; + goto err_no_dma; + } + + c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(c->base)) { + rc = PTR_ERR(c->base); + goto err_no_dma; + } + c->vc.desc_free = mtk_uart_apdma_desc_free; + vchan_init(&c->vc, &mtkd->ddev); + + rc = platform_get_irq(pdev, i); + if (rc < 0) { + dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i); + goto err_no_dma; + } + c->irq = rc; + } + + pm_runtime_enable(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + + rc = dma_async_device_register(&mtkd->ddev); + if (rc) + goto rpm_disable; + + platform_set_drvdata(pdev, mtkd); + + /* Device-tree DMA controller registration */ + rc = of_dma_controller_register(np, of_dma_xlate_by_chan_id, mtkd); + if (rc) + goto dma_remove; + + return rc; + +dma_remove: + dma_async_device_unregister(&mtkd->ddev); +rpm_disable: + pm_runtime_disable(&pdev->dev); +err_no_dma: + mtk_uart_apdma_free(mtkd); + return rc; +} + +static int mtk_uart_apdma_remove(struct platform_device *pdev) +{ + struct mtk_uart_apdmadev *mtkd = platform_get_drvdata(pdev); + + of_dma_controller_free(pdev->dev.of_node); + + mtk_uart_apdma_free(mtkd); + + dma_async_device_unregister(&mtkd->ddev); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mtk_uart_apdma_suspend(struct device *dev) +{ + struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev); + + if (!pm_runtime_suspended(dev)) + clk_disable_unprepare(mtkd->clk); + + return 0; +} + +static int mtk_uart_apdma_resume(struct device *dev) +{ + int ret; + struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev); + + if (!pm_runtime_suspended(dev)) { + ret = clk_prepare_enable(mtkd->clk); + if (ret) + return ret; + } + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM +static int mtk_uart_apdma_runtime_suspend(struct device *dev) +{ + struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev); + + clk_disable_unprepare(mtkd->clk); + + return 0; +} + +static int mtk_uart_apdma_runtime_resume(struct device *dev) +{ + int ret; + struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev); + + ret = clk_prepare_enable(mtkd->clk); + if (ret) + return ret; + + return 0; +} +#endif /* CONFIG_PM */ + +static const struct dev_pm_ops mtk_uart_apdma_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mtk_uart_apdma_suspend, mtk_uart_apdma_resume) + SET_RUNTIME_PM_OPS(mtk_uart_apdma_runtime_suspend, + mtk_uart_apdma_runtime_resume, NULL) +}; + +static struct platform_driver mtk_uart_apdma_driver = { + .probe = mtk_uart_apdma_probe, + .remove = mtk_uart_apdma_remove, + .driver = { + .name = KBUILD_MODNAME, + .pm = &mtk_uart_apdma_pm_ops, + .of_match_table = of_match_ptr(mtk_uart_apdma_match), + }, +}; + +module_platform_driver(mtk_uart_apdma_driver); + +MODULE_DESCRIPTION("MediaTek UART APDMA Controller Driver"); +MODULE_AUTHOR("Long Cheng "); +MODULE_LICENSE("GPL v2"); -- 1.7.9.5