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: [v5,2/3] dmaengine: mediatek: Add MediaTek High-Speed DMA controller for MT7622 and MT7623 SoC From: Vinod Koul Message-Id: <20180301082329.GD15443@localhost> Date: Thu, 1 Mar 2018 13:53:29 +0530 To: sean.wang@mediatek.com Cc: dan.j.williams@intel.com, robh+dt@kernel.org, mark.rutland@arm.com, dmaengine@vger.kernel.org, devicetree@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Randy Dunlap , Fengguang Wu , Julia Lawall List-ID: T24gU3VuLCBGZWIgMTgsIDIwMTggYXQgMDM6MDg6MzBBTSArMDgwMCwgc2Vhbi53YW5nQG1lZGlh dGVrLmNvbSB3cm90ZToKCj4gQEAgLTAsMCArMSwxMDU0IEBACj4gKy8vIFNQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBHUEwtMi4wCi8vIENvcHlyaWdodCAuLi4KClRoZSBjb3B5cmlnaHQgbGluZSBu ZWVkcyB0byBmb2xsb3cgU1BEWCB0YWcgbGluZQoKPiArI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5o Pgo+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+ ICsjaW5jbHVkZSA8bGludXgvZG1hZW5naW5lLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFw cGluZy5oPgo+ICsjaW5jbHVkZSA8bGludXgvZXJyLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pbml0 Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pb3BvbGwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2ppZmZp ZXMuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2xpc3QuaD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZHVs ZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4KPiArI2luY2x1ZGUgPGxpbnV4L29mX2Rldmlj ZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvb2ZfZG1hLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wbGF0 Zm9ybV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BtX3J1bnRpbWUuaD4KPiArI2luY2x1 ZGUgPGxpbnV4L3JlZmNvdW50Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cgp0aGF0J3Mg YSBsb3Qgb2YgaGVhZGVycywgZG8gdSBuZWVkIGFsbCB0aG9zZT8KCj4gKwo+ICsjaW5jbHVkZSAi Li4vdmlydC1kbWEuaCIKPiArCj4gKyNkZWZpbmUgTVRLX0RNQV9ERVYgS0JVSUxEX01PRE5BTUUK CndoeSBkbyB5b3UgbmVlZCB0aGlzPwoKPiArCj4gKyNkZWZpbmUgTVRLX0hTRE1BX1VTRUNfUE9M TAkJMjAKPiArI2RlZmluZSBNVEtfSFNETUFfVElNRU9VVF9QT0xMCQkyMDAwMDAKPiArI2RlZmlu ZSBNVEtfSFNETUFfRE1BX0JVU1dJRFRIUwkJQklUKERNQV9TTEFWRV9CVVNXSURUSF9VTkRFRklO RUQpCgpVbmRlZmluZWQgYnVzd2lkdGg/PwoKPiArLyoqCj4gKyAqIHN0cnVjdCBtdGtfaHNkbWFf cGRlc2MgLSBUaGlzIGlzIHRoZSBzdHJ1Y3QgaG9sZGluZyBpbmZvIGRlc2NyaWJpbmcgcGh5c2lj YWwKPiArICoJCQkgICAgZGVzY3JpcHRvciAoUEQpIGFuZCBpdHMgcGxhY2VtZW50IG11c3QgYmUg a2VwdCBhdAo+ICsgKgkJCSAgICA0LWJ5dGVzIGFsaWdubWVudCBpbiBsaXR0bGUgZW5kaWFuIG9y ZGVyLgo+ICsgKiBAZGVzY1sxLTRdOgkJICAgIFRoZSBjb250cm9sIHBhZCB1c2VkIHRvIGluZGlj YXRlIGhhcmR3YXJlIGhvdyB0bwoKcGxzIGFsaWduIHRvIDgwY2hhciBvciBsZXNzZXIKCj4gKy8q Kgo+ICsgKiBzdHJ1Y3QgbXRrX2hzZG1hX3JpbmcgLSBUaGlzIHN0cnVjdCBob2xkcyBpbmZvIGRl c2NyaWJpbmcgdW5kZXJseWluZyByaW5nCj4gKyAqCQkJICAgc3BhY2UKPiArICogQHR4ZDoJCSAg IFRoZSBkZXNjcmlwdG9yIFRYIHJpbmcgd2hpY2ggZGVzY3JpYmVzIERNQSBzb3VyY2UKPiArICoJ CQkgICBpbmZvcm1hdGlvbgo+ICsgKiBAcnhkOgkJICAgVGhlIGRlc2NyaXB0b3IgUlggcmluZyB3 aGljaCBkZXNjcmliZXMgRE1BCj4gKyAqCQkJICAgZGVzdGluYXRpb24gaW5mb3JtYXRpb24KPiAr ICogQGNiOgkJCSAgIFRoZSBleHRyYSBpbmZvcm1hdGlvbiBwb2ludGVkIGF0IGJ5IFJYIHJpbmcK PiArICogQHRwaHlzOgkJICAgVGhlIHBoeXNpY2FsIGFkZHIgb2YgVFggcmluZwo+ICsgKiBAcnBo eXM6CQkgICBUaGUgcGh5c2ljYWwgYWRkciBvZiBSWCByaW5nCj4gKyAqIEBjdXJfdHB0cjoJCSAg IFBvaW50ZXIgdG8gdGhlIG5leHQgZnJlZSBkZXNjcmlwdG9yIHVzZWQgYnkgdGhlIGhvc3QKPiAr ICogQGN1cl9ycHRyOgkJICAgUG9pbnRlciB0byB0aGUgbGFzdCBkb25lIGRlc2NyaXB0b3IgYnkg dGhlIGRldmljZQoKaGVyZSBhbGlnbm1lbnQgYW5kIDgwIGNoYXIgd3JhcCB3aWxsIGhlbHAgdG9v IGFuZCBmZXcgb3RoZXIgcGxhY2VzLi4uCgoKPiArc3RydWN0IG10a19oc2RtYV92Y2hhbiB7Cj4g KwlzdHJ1Y3QgdmlydF9kbWFfY2hhbiB2YzsKPiArCXN0cnVjdCBjb21wbGV0aW9uIGlzc3VlX2Nv bXBsZXRpb247Cj4gKwlib29sIGlzc3VlX3N5bmNocm9uaXplOwo+ICsJLyogcHJvdGVjdGVkIGJ5 IHZjLmxvY2sgKi8KCnRoaXMgc2hvdWxkIGJlIGF0IGNvbW1lbnRzIGFib3ZlLi4uCgo+ICtzdGF0 aWMgc3RydWN0IG10a19oc2RtYV9kZXZpY2UgKnRvX2hzZG1hX2RldihzdHJ1Y3QgZG1hX2NoYW4g KmNoYW4pCj4gK3sKPiArCXJldHVybiBjb250YWluZXJfb2YoY2hhbi0+ZGV2aWNlLCBzdHJ1Y3Qg bXRrX2hzZG1hX2RldmljZSwKPiArCQkJICAgIGRkZXYpOwoKYW5kIHRoaXMgY2FuIGZpdCBpbiBh IGxpbmUKCj4gK3N0YXRpYyBpbnQgbXRrX2hzZG1hX2FsbG9jX3BjaGFuKHN0cnVjdCBtdGtfaHNk bWFfZGV2aWNlICpoc2RtYSwKPiArCQkJCSBzdHJ1Y3QgbXRrX2hzZG1hX3BjaGFuICpwYykKPiAr ewo+ICsJc3RydWN0IG10a19oc2RtYV9yaW5nICpyaW5nID0gJnBjLT5yaW5nOwo+ICsJaW50IGVy cjsKPiArCj4gKwltZW1zZXQocGMsIDAsIHNpemVvZigqcGMpKTsKPiArCj4gKwkvKgo+ICsJICog QWxsb2NhdGUgcmluZyBzcGFjZSB3aGVyZSBbMCAuLi4gTVRLX0RNQV9TSVpFIC0gMV0gaXMgZm9y IFRYIHJpbmcKPiArCSAqIGFuZCBbTVRLX0RNQV9TSVpFIC4uLiAyICogTVRLX0RNQV9TSVpFIC0g MV0gaXMgZm9yIFJYIHJpbmcuCj4gKwkgKi8KPiArCXBjLT5zel9yaW5nID0gMiAqIE1US19ETUFf U0laRSAqIHNpemVvZigqcmluZy0+dHhkKTsKPiArCXJpbmctPnR4ZCA9IGRtYV96YWxsb2NfY29o ZXJlbnQoaHNkbWEyZGV2KGhzZG1hKSwgcGMtPnN6X3JpbmcsCj4gKwkJCQkJJnJpbmctPnRwaHlz LCBHRlBfQVRPTUlDKTsKCkdGUF9OT1dBSVQgcGxlYXNlCgo+ICsJaWYgKCFyaW5nLT50eGQpCj4g KwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJcmluZy0+cnhkID0gJnJpbmctPnR4ZFtNVEtfRE1B X1NJWkVdOwo+ICsJcmluZy0+cnBoeXMgPSByaW5nLT50cGh5cyArIE1US19ETUFfU0laRSAqIHNp emVvZigqcmluZy0+dHhkKTsKPiArCXJpbmctPmN1cl90cHRyID0gMDsKPiArCXJpbmctPmN1cl9y cHRyID0gTVRLX0RNQV9TSVpFIC0gMTsKPiArCj4gKwlyaW5nLT5jYiA9IGtjYWxsb2MoTVRLX0RN QV9TSVpFLCBzaXplb2YoKnJpbmctPmNiKSwgR0ZQX0tFUk5FTCk7Cgp0aGlzIGlzIGluY29uc2lz dGVudCB3aXRoIHlvdXIgb3duIHBhdHRlcm4hIG1ha2UgaXQgR0ZQX05PV0FJVCBwbHMKCj4gK3N0 YXRpYyBpbnQgbXRrX2hzZG1hX2lzc3VlX3BlbmRpbmdfdmRlc2Moc3RydWN0IG10a19oc2RtYV9k ZXZpY2UgKmhzZG1hLAo+ICsJCQkJCSBzdHJ1Y3QgbXRrX2hzZG1hX3BjaGFuICpwYywKPiArCQkJ CQkgc3RydWN0IG10a19oc2RtYV92ZGVzYyAqaHZkKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRrX2hzZG1h X3JpbmcgKnJpbmcgPSAmcGMtPnJpbmc7Cj4gKwlzdHJ1Y3QgbXRrX2hzZG1hX3BkZXNjICp0eGQs ICpyeGQ7Cj4gKwl1MTYgcmVzZXJ2ZWQsIHByZXYsIHRsZW4sIG51bV9zZ3M7Cj4gKwl1bnNpZ25l ZCBsb25nIGZsYWdzOwo+ICsKPiArCS8qIFByb3RlY3QgYWdhaW5zdCBQQyBpcyBhY2Nlc3NlZCBi eSBtdWx0aXBsZSBWQ3Mgc2ltdWx0YW5lb3VzbHkgKi8KPiArCXNwaW5fbG9ja19pcnFzYXZlKCZo c2RtYS0+bG9jaywgZmxhZ3MpOwo+ICsKPiArCS8qCj4gKwkgKiBSZXNlcnZlIHJvb21zLCB3aGVy ZSBwYy0+bnJfZnJlZSBpcyB1c2VkIHRvIHRyYWNrIGhvdyBtYW55IGZyZWUKPiArCSAqIHJvb21z IGluIHRoZSByaW5nIGJlaW5nIHVwZGF0ZWQgaW4gdXNlciBhbmQgSVJRIGNvbnRleHQuCj4gKwkg Ki8KPiArCW51bV9zZ3MgPSBESVZfUk9VTkRfVVAoaHZkLT5sZW4sIE1US19IU0RNQV9NQVhfTEVO KTsKPiArCXJlc2VydmVkID0gbWluX3QodTE2LCBudW1fc2dzLCBhdG9taWNfcmVhZCgmcGMtPm5y X2ZyZWUpKTsKPiArCj4gKwlpZiAoIXJlc2VydmVkKSB7Cj4gKwkJc3Bpbl91bmxvY2tfaXJxcmVz dG9yZSgmaHNkbWEtPmxvY2ssIGZsYWdzKTsKPiArCQlyZXR1cm4gLUVOT1NQQzsKPiArCX0KPiAr Cj4gKwlhdG9taWNfc3ViKHJlc2VydmVkLCAmcGMtPm5yX2ZyZWUpOwo+ICsKPiArCXdoaWxlIChy ZXNlcnZlZC0tKSB7Cj4gKwkJLyogTGltaXQgc2l6ZSBieSBQRCBjYXBhYmlsaXR5IGZvciB2YWxp ZCBkYXRhIG1vdmluZyAqLwo+ICsJCXRsZW4gPSAoaHZkLT5sZW4gPiBNVEtfSFNETUFfTUFYX0xF TikgPwo+ICsJCSAgICAgICBNVEtfSFNETUFfTUFYX0xFTiA6IGh2ZC0+bGVuOwo+ICsKPiArCQkv Kgo+ICsJCSAqIFNldHVwIFBEcyB1c2luZyB0aGUgcmVtYWluaW5nIFZEIGluZm8gbWFwcGVkIG9u IHRob3NlCj4gKwkJICogcmVzZXJ2ZWQgcm9vbXMuIEFuZCBzaW5jZSBSWEQgaXMgc2hhcmVkIG1l bW9yeSBiZXR3ZWVuIHRoZQo+ICsJCSAqIGhvc3QgYW5kIHRoZSBkZXZpY2UgYWxsb2NhdGVkIGJ5 IGRtYV9hbGxvY19jb2hlcmVudCBjYWxsLAo+ICsJCSAqIHRoZSBoZWxwZXIgbWFjcm8gV1JJVEVf T05DRSBjYW4gZW5zdXJlIHRoZSBkYXRhIHdyaXR0ZW4gdG8KPiArCQkgKiBSQU0gd291bGQgcmVh bGx5IGhhcHBlbnMuCj4gKwkJICovCj4gKwkJdHhkID0gJnJpbmctPnR4ZFtyaW5nLT5jdXJfdHB0 cl07Cj4gKwkJV1JJVEVfT05DRSh0eGQtPmRlc2MxLCBodmQtPnNyYyk7Cj4gKwkJV1JJVEVfT05D RSh0eGQtPmRlc2MyLAo+ICsJCQkgICBoc2RtYS0+c29jLT5sczAgfCBNVEtfSFNETUFfREVTQ19Q TEVOKHRsZW4pKTsKPiArCj4gKwkJcnhkID0gJnJpbmctPnJ4ZFtyaW5nLT5jdXJfdHB0cl07Cj4g KwkJV1JJVEVfT05DRShyeGQtPmRlc2MxLCBodmQtPmRlc3QpOwo+ICsJCVdSSVRFX09OQ0Uocnhk LT5kZXNjMiwgTVRLX0hTRE1BX0RFU0NfUExFTih0bGVuKSk7Cj4gKwo+ICsJCS8qIEFzc29jaWF0 ZSBWRCwgdGhlIFBEIGJlbG9uZ2VkIHRvICovCj4gKwkJcmluZy0+Y2JbcmluZy0+Y3VyX3RwdHJd LnZkID0gJmh2ZC0+dmQ7Cj4gKwo+ICsJCS8qIE1vdmUgZm9yd2FyZCB0aGUgcG9pbnRlciBvZiBU WCByaW5nICovCj4gKwkJcmluZy0+Y3VyX3RwdHIgPSBNVEtfSFNETUFfTkVYVF9ERVNQX0lEWChy aW5nLT5jdXJfdHB0ciwKPiArCQkJCQkJCSBNVEtfRE1BX1NJWkUpOwo+ICsKPiArCQkvKiBVcGRh dGUgVkQgd2l0aCByZW1haW5pbmcgZGF0YSAqLwo+ICsJCWh2ZC0+c3JjICArPSB0bGVuOwo+ICsJ CWh2ZC0+ZGVzdCArPSB0bGVuOwo+ICsJCWh2ZC0+bGVuICAtPSB0bGVuOwo+ICsJfQo+ICsKPiAr CS8qCj4gKwkgKiBUYWdnaW5nIGZsYWcgZm9yIHRoZSBsYXN0IFBEIGZvciBWRCB3aWxsIGJlIHJl c3BvbnNpYmxlIGZvcgo+ICsJICogY29tcGxldGluZyBWRC4KPiArCSAqLwo+ICsJaWYgKCFodmQt Pmxlbikgewo+ICsJCXByZXYgPSBNVEtfSFNETUFfTEFTVF9ERVNQX0lEWChyaW5nLT5jdXJfdHB0 ciwgTVRLX0RNQV9TSVpFKTsKPiArCQlyaW5nLT5jYltwcmV2XS5mbGFnID0gTVRLX0hTRE1BX1ZE RVNDX0ZJTklTSEVEOwo+ICsJfQo+ICsKPiArCS8qIEVuc3VyZSBhbGwgY2hhbmdlcyBpbmRlZWQg ZG9uZSBiZWZvcmUgd2UncmUgZ29pbmcgb24gKi8KPiArCXdtYigpOwo+ICsKPiArCS8qCj4gKwkg KiBVcGRhdGluZyBpbnRvIGhhcmR3YXJlIHRoZSBwb2ludGVyIG9mIFRYIHJpbmcgbGV0cyBIU0RN QSB0byB0YWtlCj4gKwkgKiBhY3Rpb24gZm9yIHRob3NlIHBlbmRpbmcgUERzLgo+ICsJICovCj4g KwltdGtfZG1hX3dyaXRlKGhzZG1hLCBNVEtfSFNETUFfVFhfQ1BVLCByaW5nLT5jdXJfdHB0cik7 Cj4gKwo+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmaHNkbWEtPmxvY2ssIGZsYWdzKTsKPiAr Cj4gKwlyZXR1cm4gIWh2ZC0+bGVuID8gMCA6IC1FTk9TUEM7Cgp5b3UgYWxyZWFkeSB3cm90ZSBh bmQgc3RhcnRlZCB0eG4sIHNvIHdoeSB0aGlzPwoKPiArc3RhdGljIHZvaWQgbXRrX2hzZG1hX2Zy ZWVfcm9vbXNfaW5fcmluZyhzdHJ1Y3QgbXRrX2hzZG1hX2RldmljZSAqaHNkbWEpCj4gK3sKPiAr CXN0cnVjdCBtdGtfaHNkbWFfdmNoYW4gKmh2YzsKPiArCXN0cnVjdCBtdGtfaHNkbWFfcGRlc2Mg KnJ4ZDsKPiArCXN0cnVjdCBtdGtfaHNkbWFfdmRlc2MgKmh2ZDsKPiArCXN0cnVjdCBtdGtfaHNk bWFfcGNoYW4gKnBjOwo+ICsJc3RydWN0IG10a19oc2RtYV9jYiAqY2I7Cj4gKwlfX2xlMzIgZGVz YzI7Cj4gKwl1MzIgc3RhdHVzOwo+ICsJdTE2IG5leHQ7Cj4gKwlpbnQgaTsKPiArCj4gKwlwYyA9 IGhzZG1hLT5wYzsKPiArCj4gKwkvKiBSZWFkIElSUSBzdGF0dXMgKi8KPiArCXN0YXR1cyA9IG10 a19kbWFfcmVhZChoc2RtYSwgTVRLX0hTRE1BX0lOVF9TVEFUVVMpOwo+ICsKPiArCS8qCj4gKwkg KiBBY2sgdGhlIHBlbmRpbmcgSVJRIGFsbCB0byBsZXQgaGFyZHdhcmUga25vdyBzb2Z0d2FyZSBp cyBoYW5kbGluZwo+ICsJICogdGhvc2UgZmluaXNoZWQgcGh5c2ljYWwgZGVzY3JpcHRvcnMuIE90 aGVyd2lzZSwgdGhlIGhhcmR3YXJlIHdvdWxkCj4gKwkgKiBrZWVwIHRoZSB1c2VkIElSUSBsaW5l IGluIGNlcnRhaW4gdHJpZ2dlciBzdGF0ZS4KPiArCSAqLwo+ICsJbXRrX2RtYV93cml0ZShoc2Rt YSwgTVRLX0hTRE1BX0lOVF9TVEFUVVMsIHN0YXR1cyk7Cj4gKwo+ICsJd2hpbGUgKDEpIHsKPiAr CQluZXh0ID0gTVRLX0hTRE1BX05FWFRfREVTUF9JRFgocGMtPnJpbmcuY3VyX3JwdHIsCj4gKwkJ CQkJICAgICAgIE1US19ETUFfU0laRSk7CgpzaG91bGRuJ3Qgd2UgY2hlY2sgaWYgbmV4dCBpcyBp biByYW5nZSwgd2UgY2FuIGNyYXNoIGlmIHdlIGdldCBiYWQgdmFsdWUKZnJvbSBoYXJkd2FyZS4u Cgo+ICsJCXJ4ZCA9ICZwYy0+cmluZy5yeGRbbmV4dF07Cj4gKwo+ICsJCS8qCj4gKwkJICogSWYg TVRLX0hTRE1BX0RFU0NfRERPTkUgaXMgbm8gc3BlY2lmaWVkLCB0aGF0IG1lYW5zIGRhdGEKPiAr CQkgKiBtb3ZpbmcgZm9yIHRoZSBQRCBpcyBzdGlsbCB1bmRlciBnb2luZy4KPiArCQkgKi8KPiAr CQlkZXNjMiA9IFJFQURfT05DRShyeGQtPmRlc2MyKTsKPiArCQlpZiAoIShkZXNjMiAmIGhzZG1h LT5zb2MtPmRkb25lKSkKPiArCQkJYnJlYWs7Cgpva2F5IHRoaXMgaXMgb25lIGJyZWFrCgo+ICsK PiArCQljYiA9ICZwYy0+cmluZy5jYltuZXh0XTsKPiArCQlpZiAodW5saWtlbHkoIWNiLT52ZCkp IHsKPiArCQkJZGV2X2Vycihoc2RtYTJkZXYoaHNkbWEpLCAiY2ItPnZkIGNhbm5vdCBiZSBudWxs XG4iKTsKPiArCQkJYnJlYWs7CgphbmQgb3RoZXIgZm9yIG51bGwsIGkgZmVlbCB3ZSBuZWVkIHRv IGhhdmUgY2hlY2tzIGZvciB3aGlsZSgxKSB0byBicmVhaywKdGhpcyBjYW4gcnVuIGluZmluaXRl bHkgaWYgc29tZXRoaW5nIGJhZCBoYXBwZW5zLCBhIGZhaWwgc2FmZSB3b3VsZCBiZSBnb29kLAp0 aGF0IHRvbyB0aGlzIGJlaW5nIGludm9rZWQgZnJvbSBpc3IuCgo+ICtzdGF0aWMgZW51bSBkbWFf c3RhdHVzIG10a19oc2RtYV90eF9zdGF0dXMoc3RydWN0IGRtYV9jaGFuICpjLAo+ICsJCQkJCSAg IGRtYV9jb29raWVfdCBjb29raWUsCj4gKwkJCQkJICAgc3RydWN0IGRtYV90eF9zdGF0ZSAqdHhz dGF0ZSkKPiArewo+ICsJc3RydWN0IG10a19oc2RtYV92Y2hhbiAqaHZjID0gdG9faHNkbWFfdmNo YW4oYyk7Cj4gKwlzdHJ1Y3QgbXRrX2hzZG1hX3ZkZXNjICpodmQ7Cj4gKwlzdHJ1Y3QgdmlydF9k bWFfZGVzYyAqdmQ7Cj4gKwllbnVtIGRtYV9zdGF0dXMgcmV0Owo+ICsJdW5zaWduZWQgbG9uZyBm bGFnczsKPiArCXNpemVfdCBieXRlcyA9IDA7Cj4gKwo+ICsJcmV0ID0gZG1hX2Nvb2tpZV9zdGF0 dXMoYywgY29va2llLCB0eHN0YXRlKTsKPiArCWlmIChyZXQgPT0gRE1BX0NPTVBMRVRFIHx8ICF0 eHN0YXRlKQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmh2Yy0+ dmMubG9jaywgZmxhZ3MpOwo+ICsJdmQgPSBtdGtfaHNkbWFfZmluZF9hY3RpdmVfZGVzYyhjLCBj b29raWUpOwo+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmaHZjLT52Yy5sb2NrLCBmbGFncyk7 Cj4gKwo+ICsJaWYgKHZkKSB7Cj4gKwkJaHZkID0gdG9faHNkbWFfdmRlc2ModmQpOwo+ICsJCWJ5 dGVzID0gaHZkLT5yZXNpZHVlOwoKZm9yIGFjdGl2ZSBkZXNjcmlwdG9yLCBzaG91bGRuJ3QgeW91 IHJlYWQgY291bnRlcnMgZnJvbSBoYXJkd2FyZT8KCj4gK3N0YXRpYyBzdHJ1Y3QgZG1hX2FzeW5j X3R4X2Rlc2NyaXB0b3IgKgo+ICttdGtfaHNkbWFfcHJlcF9kbWFfbWVtY3B5KHN0cnVjdCBkbWFf Y2hhbiAqYywgZG1hX2FkZHJfdCBkZXN0LAo+ICsJCQkgIGRtYV9hZGRyX3Qgc3JjLCBzaXplX3Qg bGVuLCB1bnNpZ25lZCBsb25nIGZsYWdzKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRrX2hzZG1hX3ZkZXNj ICpodmQ7Cj4gKwo+ICsJaHZkID0ga3phbGxvYyhzaXplb2YoKmh2ZCksIEdGUF9OT1dBSVQpOwoK R0ZQX05PV0FJVCBoZXJlIHRvbwoKPiArc3RhdGljIGludCBtdGtfaHNkbWFfdGVybWluYXRlX2Fs bChzdHJ1Y3QgZG1hX2NoYW4gKmMpCj4gK3sKPiArCW10a19oc2RtYV9mcmVlX2luYWN0aXZlX2Rl c2MoYywgZmFsc2UpOwoKb25seSBpbmFjdGl2ZSwgYWN0aXZlIG9uZXMgbmVlZCB0byBiZSBmcmVl ZCBhbmQgY2hhbm5lbCBjbGVhbmVkCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vinod Koul Subject: Re: [PATCH v5 2/3] dmaengine: mediatek: Add MediaTek High-Speed DMA controller for MT7622 and MT7623 SoC Date: Thu, 1 Mar 2018 13:53:29 +0530 Message-ID: <20180301082329.GD15443@localhost> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Content-Disposition: inline In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org To: sean.wang@mediatek.com Cc: dan.j.williams@intel.com, robh+dt@kernel.org, mark.rutland@arm.com, dmaengine@vger.kernel.org, devicetree@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Randy Dunlap , Fengguang Wu , Julia Lawall List-Id: linux-mediatek@lists.infradead.org On Sun, Feb 18, 2018 at 03:08:30AM +0800, sean.wang@mediatek.com wrote: > @@ -0,0 +1,1054 @@ > +// SPDX-License-Identifier: GPL-2.0 // Copyright ... The copyright line needs to follow SPDX tag line > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include that's a lot of headers, do u need all those? > + > +#include "../virt-dma.h" > + > +#define MTK_DMA_DEV KBUILD_MODNAME why do you need this? > + > +#define MTK_HSDMA_USEC_POLL 20 > +#define MTK_HSDMA_TIMEOUT_POLL 200000 > +#define MTK_HSDMA_DMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) Undefined buswidth?? > +/** > + * struct mtk_hsdma_pdesc - This is the struct holding info describing physical > + * descriptor (PD) and its placement must be kept at > + * 4-bytes alignment in little endian order. > + * @desc[1-4]: The control pad used to indicate hardware how to pls align to 80char or lesser > +/** > + * struct mtk_hsdma_ring - This struct holds info describing underlying ring > + * space > + * @txd: The descriptor TX ring which describes DMA source > + * information > + * @rxd: The descriptor RX ring which describes DMA > + * destination information > + * @cb: The extra information pointed at by RX ring > + * @tphys: The physical addr of TX ring > + * @rphys: The physical addr of RX ring > + * @cur_tptr: Pointer to the next free descriptor used by the host > + * @cur_rptr: Pointer to the last done descriptor by the device here alignment and 80 char wrap will help too and few other places... > +struct mtk_hsdma_vchan { > + struct virt_dma_chan vc; > + struct completion issue_completion; > + bool issue_synchronize; > + /* protected by vc.lock */ this should be at comments above... > +static struct mtk_hsdma_device *to_hsdma_dev(struct dma_chan *chan) > +{ > + return container_of(chan->device, struct mtk_hsdma_device, > + ddev); and this can fit in a line > +static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma, > + struct mtk_hsdma_pchan *pc) > +{ > + struct mtk_hsdma_ring *ring = &pc->ring; > + int err; > + > + memset(pc, 0, sizeof(*pc)); > + > + /* > + * Allocate ring space where [0 ... MTK_DMA_SIZE - 1] is for TX ring > + * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring. > + */ > + pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd); > + ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring, > + &ring->tphys, GFP_ATOMIC); GFP_NOWAIT please > + if (!ring->txd) > + return -ENOMEM; > + > + ring->rxd = &ring->txd[MTK_DMA_SIZE]; > + ring->rphys = ring->tphys + MTK_DMA_SIZE * sizeof(*ring->txd); > + ring->cur_tptr = 0; > + ring->cur_rptr = MTK_DMA_SIZE - 1; > + > + ring->cb = kcalloc(MTK_DMA_SIZE, sizeof(*ring->cb), GFP_KERNEL); this is inconsistent with your own pattern! make it GFP_NOWAIT pls > +static int mtk_hsdma_issue_pending_vdesc(struct mtk_hsdma_device *hsdma, > + struct mtk_hsdma_pchan *pc, > + struct mtk_hsdma_vdesc *hvd) > +{ > + struct mtk_hsdma_ring *ring = &pc->ring; > + struct mtk_hsdma_pdesc *txd, *rxd; > + u16 reserved, prev, tlen, num_sgs; > + unsigned long flags; > + > + /* Protect against PC is accessed by multiple VCs simultaneously */ > + spin_lock_irqsave(&hsdma->lock, flags); > + > + /* > + * Reserve rooms, where pc->nr_free is used to track how many free > + * rooms in the ring being updated in user and IRQ context. > + */ > + num_sgs = DIV_ROUND_UP(hvd->len, MTK_HSDMA_MAX_LEN); > + reserved = min_t(u16, num_sgs, atomic_read(&pc->nr_free)); > + > + if (!reserved) { > + spin_unlock_irqrestore(&hsdma->lock, flags); > + return -ENOSPC; > + } > + > + atomic_sub(reserved, &pc->nr_free); > + > + while (reserved--) { > + /* Limit size by PD capability for valid data moving */ > + tlen = (hvd->len > MTK_HSDMA_MAX_LEN) ? > + MTK_HSDMA_MAX_LEN : hvd->len; > + > + /* > + * Setup PDs using the remaining VD info mapped on those > + * reserved rooms. And since RXD is shared memory between the > + * host and the device allocated by dma_alloc_coherent call, > + * the helper macro WRITE_ONCE can ensure the data written to > + * RAM would really happens. > + */ > + txd = &ring->txd[ring->cur_tptr]; > + WRITE_ONCE(txd->desc1, hvd->src); > + WRITE_ONCE(txd->desc2, > + hsdma->soc->ls0 | MTK_HSDMA_DESC_PLEN(tlen)); > + > + rxd = &ring->rxd[ring->cur_tptr]; > + WRITE_ONCE(rxd->desc1, hvd->dest); > + WRITE_ONCE(rxd->desc2, MTK_HSDMA_DESC_PLEN(tlen)); > + > + /* Associate VD, the PD belonged to */ > + ring->cb[ring->cur_tptr].vd = &hvd->vd; > + > + /* Move forward the pointer of TX ring */ > + ring->cur_tptr = MTK_HSDMA_NEXT_DESP_IDX(ring->cur_tptr, > + MTK_DMA_SIZE); > + > + /* Update VD with remaining data */ > + hvd->src += tlen; > + hvd->dest += tlen; > + hvd->len -= tlen; > + } > + > + /* > + * Tagging flag for the last PD for VD will be responsible for > + * completing VD. > + */ > + if (!hvd->len) { > + prev = MTK_HSDMA_LAST_DESP_IDX(ring->cur_tptr, MTK_DMA_SIZE); > + ring->cb[prev].flag = MTK_HSDMA_VDESC_FINISHED; > + } > + > + /* Ensure all changes indeed done before we're going on */ > + wmb(); > + > + /* > + * Updating into hardware the pointer of TX ring lets HSDMA to take > + * action for those pending PDs. > + */ > + mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr); > + > + spin_unlock_irqrestore(&hsdma->lock, flags); > + > + return !hvd->len ? 0 : -ENOSPC; you already wrote and started txn, so why this? > +static void mtk_hsdma_free_rooms_in_ring(struct mtk_hsdma_device *hsdma) > +{ > + struct mtk_hsdma_vchan *hvc; > + struct mtk_hsdma_pdesc *rxd; > + struct mtk_hsdma_vdesc *hvd; > + struct mtk_hsdma_pchan *pc; > + struct mtk_hsdma_cb *cb; > + __le32 desc2; > + u32 status; > + u16 next; > + int i; > + > + pc = hsdma->pc; > + > + /* Read IRQ status */ > + status = mtk_dma_read(hsdma, MTK_HSDMA_INT_STATUS); > + > + /* > + * Ack the pending IRQ all to let hardware know software is handling > + * those finished physical descriptors. Otherwise, the hardware would > + * keep the used IRQ line in certain trigger state. > + */ > + mtk_dma_write(hsdma, MTK_HSDMA_INT_STATUS, status); > + > + while (1) { > + next = MTK_HSDMA_NEXT_DESP_IDX(pc->ring.cur_rptr, > + MTK_DMA_SIZE); shouldn't we check if next is in range, we can crash if we get bad value from hardware.. > + rxd = &pc->ring.rxd[next]; > + > + /* > + * If MTK_HSDMA_DESC_DDONE is no specified, that means data > + * moving for the PD is still under going. > + */ > + desc2 = READ_ONCE(rxd->desc2); > + if (!(desc2 & hsdma->soc->ddone)) > + break; okay this is one break > + > + cb = &pc->ring.cb[next]; > + if (unlikely(!cb->vd)) { > + dev_err(hsdma2dev(hsdma), "cb->vd cannot be null\n"); > + break; and other for null, i feel we need to have checks for while(1) to break, this can run infinitely if something bad happens, a fail safe would be good, that too this being invoked from isr. > +static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, > + dma_cookie_t cookie, > + struct dma_tx_state *txstate) > +{ > + struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); > + struct mtk_hsdma_vdesc *hvd; > + struct virt_dma_desc *vd; > + enum dma_status ret; > + unsigned long flags; > + size_t bytes = 0; > + > + ret = dma_cookie_status(c, cookie, txstate); > + if (ret == DMA_COMPLETE || !txstate) > + return ret; > + > + spin_lock_irqsave(&hvc->vc.lock, flags); > + vd = mtk_hsdma_find_active_desc(c, cookie); > + spin_unlock_irqrestore(&hvc->vc.lock, flags); > + > + if (vd) { > + hvd = to_hsdma_vdesc(vd); > + bytes = hvd->residue; for active descriptor, shouldn't you read counters from hardware? > +static struct dma_async_tx_descriptor * > +mtk_hsdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, > + dma_addr_t src, size_t len, unsigned long flags) > +{ > + struct mtk_hsdma_vdesc *hvd; > + > + hvd = kzalloc(sizeof(*hvd), GFP_NOWAIT); GFP_NOWAIT here too > +static int mtk_hsdma_terminate_all(struct dma_chan *c) > +{ > + mtk_hsdma_free_inactive_desc(c, false); only inactive, active ones need to be freed and channel cleaned -- ~Vinod From mboxrd@z Thu Jan 1 00:00:00 1970 From: vinod.koul@intel.com (Vinod Koul) Date: Thu, 1 Mar 2018 13:53:29 +0530 Subject: [PATCH v5 2/3] dmaengine: mediatek: Add MediaTek High-Speed DMA controller for MT7622 and MT7623 SoC In-Reply-To: References: Message-ID: <20180301082329.GD15443@localhost> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On Sun, Feb 18, 2018 at 03:08:30AM +0800, sean.wang at mediatek.com wrote: > @@ -0,0 +1,1054 @@ > +// SPDX-License-Identifier: GPL-2.0 // Copyright ... The copyright line needs to follow SPDX tag line > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include that's a lot of headers, do u need all those? > + > +#include "../virt-dma.h" > + > +#define MTK_DMA_DEV KBUILD_MODNAME why do you need this? > + > +#define MTK_HSDMA_USEC_POLL 20 > +#define MTK_HSDMA_TIMEOUT_POLL 200000 > +#define MTK_HSDMA_DMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) Undefined buswidth?? > +/** > + * struct mtk_hsdma_pdesc - This is the struct holding info describing physical > + * descriptor (PD) and its placement must be kept at > + * 4-bytes alignment in little endian order. > + * @desc[1-4]: The control pad used to indicate hardware how to pls align to 80char or lesser > +/** > + * struct mtk_hsdma_ring - This struct holds info describing underlying ring > + * space > + * @txd: The descriptor TX ring which describes DMA source > + * information > + * @rxd: The descriptor RX ring which describes DMA > + * destination information > + * @cb: The extra information pointed at by RX ring > + * @tphys: The physical addr of TX ring > + * @rphys: The physical addr of RX ring > + * @cur_tptr: Pointer to the next free descriptor used by the host > + * @cur_rptr: Pointer to the last done descriptor by the device here alignment and 80 char wrap will help too and few other places... > +struct mtk_hsdma_vchan { > + struct virt_dma_chan vc; > + struct completion issue_completion; > + bool issue_synchronize; > + /* protected by vc.lock */ this should be at comments above... > +static struct mtk_hsdma_device *to_hsdma_dev(struct dma_chan *chan) > +{ > + return container_of(chan->device, struct mtk_hsdma_device, > + ddev); and this can fit in a line > +static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma, > + struct mtk_hsdma_pchan *pc) > +{ > + struct mtk_hsdma_ring *ring = &pc->ring; > + int err; > + > + memset(pc, 0, sizeof(*pc)); > + > + /* > + * Allocate ring space where [0 ... MTK_DMA_SIZE - 1] is for TX ring > + * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring. > + */ > + pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd); > + ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring, > + &ring->tphys, GFP_ATOMIC); GFP_NOWAIT please > + if (!ring->txd) > + return -ENOMEM; > + > + ring->rxd = &ring->txd[MTK_DMA_SIZE]; > + ring->rphys = ring->tphys + MTK_DMA_SIZE * sizeof(*ring->txd); > + ring->cur_tptr = 0; > + ring->cur_rptr = MTK_DMA_SIZE - 1; > + > + ring->cb = kcalloc(MTK_DMA_SIZE, sizeof(*ring->cb), GFP_KERNEL); this is inconsistent with your own pattern! make it GFP_NOWAIT pls > +static int mtk_hsdma_issue_pending_vdesc(struct mtk_hsdma_device *hsdma, > + struct mtk_hsdma_pchan *pc, > + struct mtk_hsdma_vdesc *hvd) > +{ > + struct mtk_hsdma_ring *ring = &pc->ring; > + struct mtk_hsdma_pdesc *txd, *rxd; > + u16 reserved, prev, tlen, num_sgs; > + unsigned long flags; > + > + /* Protect against PC is accessed by multiple VCs simultaneously */ > + spin_lock_irqsave(&hsdma->lock, flags); > + > + /* > + * Reserve rooms, where pc->nr_free is used to track how many free > + * rooms in the ring being updated in user and IRQ context. > + */ > + num_sgs = DIV_ROUND_UP(hvd->len, MTK_HSDMA_MAX_LEN); > + reserved = min_t(u16, num_sgs, atomic_read(&pc->nr_free)); > + > + if (!reserved) { > + spin_unlock_irqrestore(&hsdma->lock, flags); > + return -ENOSPC; > + } > + > + atomic_sub(reserved, &pc->nr_free); > + > + while (reserved--) { > + /* Limit size by PD capability for valid data moving */ > + tlen = (hvd->len > MTK_HSDMA_MAX_LEN) ? > + MTK_HSDMA_MAX_LEN : hvd->len; > + > + /* > + * Setup PDs using the remaining VD info mapped on those > + * reserved rooms. And since RXD is shared memory between the > + * host and the device allocated by dma_alloc_coherent call, > + * the helper macro WRITE_ONCE can ensure the data written to > + * RAM would really happens. > + */ > + txd = &ring->txd[ring->cur_tptr]; > + WRITE_ONCE(txd->desc1, hvd->src); > + WRITE_ONCE(txd->desc2, > + hsdma->soc->ls0 | MTK_HSDMA_DESC_PLEN(tlen)); > + > + rxd = &ring->rxd[ring->cur_tptr]; > + WRITE_ONCE(rxd->desc1, hvd->dest); > + WRITE_ONCE(rxd->desc2, MTK_HSDMA_DESC_PLEN(tlen)); > + > + /* Associate VD, the PD belonged to */ > + ring->cb[ring->cur_tptr].vd = &hvd->vd; > + > + /* Move forward the pointer of TX ring */ > + ring->cur_tptr = MTK_HSDMA_NEXT_DESP_IDX(ring->cur_tptr, > + MTK_DMA_SIZE); > + > + /* Update VD with remaining data */ > + hvd->src += tlen; > + hvd->dest += tlen; > + hvd->len -= tlen; > + } > + > + /* > + * Tagging flag for the last PD for VD will be responsible for > + * completing VD. > + */ > + if (!hvd->len) { > + prev = MTK_HSDMA_LAST_DESP_IDX(ring->cur_tptr, MTK_DMA_SIZE); > + ring->cb[prev].flag = MTK_HSDMA_VDESC_FINISHED; > + } > + > + /* Ensure all changes indeed done before we're going on */ > + wmb(); > + > + /* > + * Updating into hardware the pointer of TX ring lets HSDMA to take > + * action for those pending PDs. > + */ > + mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr); > + > + spin_unlock_irqrestore(&hsdma->lock, flags); > + > + return !hvd->len ? 0 : -ENOSPC; you already wrote and started txn, so why this? > +static void mtk_hsdma_free_rooms_in_ring(struct mtk_hsdma_device *hsdma) > +{ > + struct mtk_hsdma_vchan *hvc; > + struct mtk_hsdma_pdesc *rxd; > + struct mtk_hsdma_vdesc *hvd; > + struct mtk_hsdma_pchan *pc; > + struct mtk_hsdma_cb *cb; > + __le32 desc2; > + u32 status; > + u16 next; > + int i; > + > + pc = hsdma->pc; > + > + /* Read IRQ status */ > + status = mtk_dma_read(hsdma, MTK_HSDMA_INT_STATUS); > + > + /* > + * Ack the pending IRQ all to let hardware know software is handling > + * those finished physical descriptors. Otherwise, the hardware would > + * keep the used IRQ line in certain trigger state. > + */ > + mtk_dma_write(hsdma, MTK_HSDMA_INT_STATUS, status); > + > + while (1) { > + next = MTK_HSDMA_NEXT_DESP_IDX(pc->ring.cur_rptr, > + MTK_DMA_SIZE); shouldn't we check if next is in range, we can crash if we get bad value from hardware.. > + rxd = &pc->ring.rxd[next]; > + > + /* > + * If MTK_HSDMA_DESC_DDONE is no specified, that means data > + * moving for the PD is still under going. > + */ > + desc2 = READ_ONCE(rxd->desc2); > + if (!(desc2 & hsdma->soc->ddone)) > + break; okay this is one break > + > + cb = &pc->ring.cb[next]; > + if (unlikely(!cb->vd)) { > + dev_err(hsdma2dev(hsdma), "cb->vd cannot be null\n"); > + break; and other for null, i feel we need to have checks for while(1) to break, this can run infinitely if something bad happens, a fail safe would be good, that too this being invoked from isr. > +static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, > + dma_cookie_t cookie, > + struct dma_tx_state *txstate) > +{ > + struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); > + struct mtk_hsdma_vdesc *hvd; > + struct virt_dma_desc *vd; > + enum dma_status ret; > + unsigned long flags; > + size_t bytes = 0; > + > + ret = dma_cookie_status(c, cookie, txstate); > + if (ret == DMA_COMPLETE || !txstate) > + return ret; > + > + spin_lock_irqsave(&hvc->vc.lock, flags); > + vd = mtk_hsdma_find_active_desc(c, cookie); > + spin_unlock_irqrestore(&hvc->vc.lock, flags); > + > + if (vd) { > + hvd = to_hsdma_vdesc(vd); > + bytes = hvd->residue; for active descriptor, shouldn't you read counters from hardware? > +static struct dma_async_tx_descriptor * > +mtk_hsdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, > + dma_addr_t src, size_t len, unsigned long flags) > +{ > + struct mtk_hsdma_vdesc *hvd; > + > + hvd = kzalloc(sizeof(*hvd), GFP_NOWAIT); GFP_NOWAIT here too > +static int mtk_hsdma_terminate_all(struct dma_chan *c) > +{ > + mtk_hsdma_free_inactive_desc(c, false); only inactive, active ones need to be freed and channel cleaned -- ~Vinod