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] USB: serial: cp210x: Implement GPIO support for CP2102N From: Johan Hovold Message-Id: <20180720105240.24680-1-johan@kernel.org> Date: Fri, 20 Jul 2018 12:52:40 +0200 To: Johan Hovold Cc: Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Karoly Pados , Martyn Welch List-ID: RnJvbTogS2Fyb2x5IFBhZG9zIDxwYWRvc0BwYWRvcy5odT4KClRoaXMgaXMgdjIgb2YgdGhlIHBh dGNoIGFuZCBhZGRyZXNzZXMgYWxsIGZlZWRiYWNrIHByZXZpb3VzbHkKcmVjZWl2ZWQgZnJvbSB0 aGUgbWFpbnRhaW5lci4gTmV3IGlucHV0L291dHB1dCBzdXBwb3J0IHN0YXllZAphcyBkaXNjdXNz ZWQgb24gdGhlIGUtbWFpbCBsaXN0cyBzZXBhcmF0ZWx5LiBDUDIxMDUgaXMgYWxzbwp1c2luZyB0 aGUgbmV3IGNvZGUgc3RydWN0dXJlLCBidXQgZHVlIHRvIG1pc3Npbmcgd2F5IHRvIGdldApkZWZh dWx0IHBpbiBzdGF0ZXMgYWZ0ZXIgcmVzZXQgZnJvbSB0aGUgZGV2aWNlLCBzdXBwb3J0CmZvciB0 aGlzIGRldmljZSBpcyBiYXNpY2FsbHkgc3RpbGwgb3V0cHV0LW9ubHkgYXMgYmVmb3JlLCBhdAps ZWFzdCBpbiBuYW1lLiBCdXQgQ1AyMTA1IGFuZCBDUDIxMDJOIHBhdGhzIGFyZSB1bmlmaWVkLgoK VGhpcyBwYXRjaCBpcyBiYXNlZCBvbiB0aGUgbGF0ZXN0IHBhdGNoIHNlcmllcyBieSBKb2hhbiBq dXN0CnN1Ym1pdHRlZCB0b2RheS4KClNpZ25lZC1vZmYtYnk6IEthcm9seSBQYWRvcyA8cGFkb3NA cGFkb3MuaHU+Clsgam9oYW46IGZpeCBzdHlsZSBpc3N1ZXMgYW5kIGEgY291cGxlIG9mIG1pbm9y IGJ1Z3MgXQpDYzogTWFydHluIFdlbGNoIDxtYXJ0eW4ud2VsY2hAY29sbGFib3JhLmNvLnVrPgpT aWduZWQtb2ZmLWJ5OiBKb2hhbiBIb3ZvbGQgPGpvaGFuQGtlcm5lbC5vcmc+Ci0tLQoKVGhpcyBp cyBLYXJvbHkncyB2MiBwYXRjaCB3aXRoIHNvbWUgc3R5bGUgaXNzdWVzIGFuZCBhIGNvdXBsZSBv ZiBtaW5vcgpidWdzIGZpeGVkLiBJJ2xsIHdhaXQgZm9yIGFuIHVwZGF0ZWQgY29tbWl0IG1lc3Nh Z2UgYmVmb3JlIGFwcGx5aW5nLgoKSm9oYW4KCgogZHJpdmVycy91c2Ivc2VyaWFsL2NwMjEweC5j IHwgMjQ1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tLS0tLQogMSBmaWxlIGNoYW5n ZWQsIDIwOSBpbnNlcnRpb25zKCspLCAzNiBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2 ZXJzL3VzYi9zZXJpYWwvY3AyMTB4LmMgYi9kcml2ZXJzL3VzYi9zZXJpYWwvY3AyMTB4LmMKaW5k ZXggNGExMThlYjEzNTkwLi5iOWJjODA3MDBiZTcgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvdXNiL3Nl cmlhbC9jcDIxMHguYworKysgYi9kcml2ZXJzL3VzYi9zZXJpYWwvY3AyMTB4LmMKQEAgLTIyNCw5 ICsyMjQsMTAgQEAgTU9EVUxFX0RFVklDRV9UQUJMRSh1c2IsIGlkX3RhYmxlKTsKIHN0cnVjdCBj cDIxMHhfc2VyaWFsX3ByaXZhdGUgewogI2lmZGVmIENPTkZJR19HUElPTElCCiAJc3RydWN0IGdw aW9fY2hpcAlnYzsKLQl1OAkJCWNvbmZpZzsKLQl1OAkJCWdwaW9fbW9kZTsKIAlib29sCQkJZ3Bp b19yZWdpc3RlcmVkOworCXU4CQkJZ3Bpb19wdXNocHVsbDsKKwl1OAkJCWdwaW9fYWx0ZnVuYzsK Kwl1OAkJCWdwaW9faW5wdXQ7CiAjZW5kaWYKIAl1OAkJCXBhcnRudW07CiAJc3BlZWRfdAkJCW1h eF9zcGVlZDsKQEAgLTM0Myw2ICszNDQsNyBAQCBzdGF0aWMgc3RydWN0IHVzYl9zZXJpYWxfZHJp dmVyICogY29uc3Qgc2VyaWFsX2RyaXZlcnNbXSA9IHsKICNkZWZpbmUgQ09OVFJPTF9XUklURV9S VFMJMHgwMjAwCiAKIC8qIENQMjEwWF9WRU5ET1JfU1BFQ0lGSUMgdmFsdWVzICovCisjZGVmaW5l IENQMjEwWF9SRUFEXzJOQ09ORklHCTB4MDAwRQogI2RlZmluZSBDUDIxMFhfUkVBRF9MQVRDSAkw eDAwQzIKICNkZWZpbmUgQ1AyMTBYX0dFVF9QQVJUTlVNCTB4MzcwQgogI2RlZmluZSBDUDIxMFhf R0VUX1BPUlRDT05GSUcJMHgzNzBDCkBAIC00NTIsNiArNDU0LDEyIEBAIHN0cnVjdCBjcDIxMHhf Y29uZmlnIHsKICNkZWZpbmUgQ1AyMTA1X0dQSU8xX1JYTEVEX01PREUJCUJJVCgxKQogI2RlZmlu ZSBDUDIxMDVfR1BJTzFfUlM0ODVfTU9ERQkJQklUKDIpCiAKKy8qIENQMjEwMk4gY29uZmlndXJh dGlvbiBhcnJheSBpbmRpY2VzICovCisjZGVmaW5lIENQMjEwWF8yTkNPTkZJR19DT05GSUdfVkVS U0lPTl9JRFgJMgorI2RlZmluZSBDUDIxMFhfMk5DT05GSUdfR1BJT19NT0RFX0lEWAkJNTgxCisj ZGVmaW5lIENQMjEwWF8yTkNPTkZJR19HUElPX1JTVExBVENIX0lEWAk1ODcKKyNkZWZpbmUgQ1Ay MTBYXzJOQ09ORklHX0dQSU9fQ09OVFJPTF9JRFgJNjAwCisKIC8qIENQMjEwWF9WRU5ET1JfU1BF Q0lGSUMsIENQMjEwWF9XUklURV9MQVRDSCBjYWxsIHdyaXRlcyB0aGVzZSAweDIgYnl0ZXMuICov CiBzdHJ1Y3QgY3AyMTB4X2dwaW9fd3JpdGUgewogCXU4CW1hc2s7CkBAIC0xMzEzLDE3ICsxMzIx LDggQEAgc3RhdGljIGludCBjcDIxMHhfZ3Bpb19yZXF1ZXN0KHN0cnVjdCBncGlvX2NoaXAgKmdj LCB1bnNpZ25lZCBpbnQgb2Zmc2V0KQogCXN0cnVjdCB1c2Jfc2VyaWFsICpzZXJpYWwgPSBncGlv Y2hpcF9nZXRfZGF0YShnYyk7CiAJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJpdiA9 IHVzYl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFsKTsKIAotCXN3aXRjaCAob2Zmc2V0KSB7Ci0JY2Fz ZSAwOgotCQlpZiAocHJpdi0+Y29uZmlnICYgQ1AyMTA1X0dQSU8wX1RYTEVEX01PREUpCi0JCQly ZXR1cm4gLUVOT0RFVjsKLQkJYnJlYWs7Ci0JY2FzZSAxOgotCQlpZiAocHJpdi0+Y29uZmlnICYg KENQMjEwNV9HUElPMV9SWExFRF9NT0RFIHwKLQkJCQkgICAgQ1AyMTA1X0dQSU8xX1JTNDg1X01P REUpKQotCQkJcmV0dXJuIC1FTk9ERVY7Ci0JCWJyZWFrOwotCX0KKwlpZiAocHJpdi0+Z3Bpb19h bHRmdW5jICYgQklUKG9mZnNldCkpCisJCXJldHVybiAtRU5PREVWOwogCiAJcmV0dXJuIDA7CiB9 CkBAIC0xMzMxLDEwICsxMzMwLDE1IEBAIHN0YXRpYyBpbnQgY3AyMTB4X2dwaW9fcmVxdWVzdChz dHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IG9mZnNldCkKIHN0YXRpYyBpbnQgY3Ay MTB4X2dwaW9fZ2V0KHN0cnVjdCBncGlvX2NoaXAgKmdjLCB1bnNpZ25lZCBpbnQgZ3BpbykKIHsK IAlzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsID0gZ3Bpb2NoaXBfZ2V0X2RhdGEoZ2MpOworCXN0 cnVjdCBjcDIxMHhfc2VyaWFsX3ByaXZhdGUgKnByaXYgPSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNl cmlhbCk7CisJdTggcmVxX3R5cGUgPSBSRVFUWVBFX0RFVklDRV9UT19IT1NUOwogCWludCByZXN1 bHQ7CiAJdTggYnVmOwogCi0JcmVzdWx0ID0gY3AyMTB4X3JlYWRfdmVuZG9yX2Jsb2NrKHNlcmlh bCwgUkVRVFlQRV9JTlRFUkZBQ0VfVE9fSE9TVCwKKwlpZiAocHJpdi0+cGFydG51bSA9PSBDUDIx MFhfUEFSVE5VTV9DUDIxMDUpCisJCXJlcV90eXBlID0gUkVRVFlQRV9JTlRFUkZBQ0VfVE9fSE9T VDsKKworCXJlc3VsdCA9IGNwMjEweF9yZWFkX3ZlbmRvcl9ibG9jayhzZXJpYWwsIHJlcV90eXBl LAogCQkJCQkgIENQMjEwWF9SRUFEX0xBVENILCAmYnVmLCBzaXplb2YoYnVmKSk7CiAJaWYgKHJl c3VsdCA8IDApCiAJCXJldHVybiByZXN1bHQ7CkBAIC0xMzQ1LDcgKzEzNDksOSBAQCBzdGF0aWMg aW50IGNwMjEweF9ncGlvX2dldChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IGdw aW8pCiBzdGF0aWMgdm9pZCBjcDIxMHhfZ3Bpb19zZXQoc3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVu c2lnbmVkIGludCBncGlvLCBpbnQgdmFsdWUpCiB7CiAJc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlh bCA9IGdwaW9jaGlwX2dldF9kYXRhKGdjKTsKKwlzdHJ1Y3QgY3AyMTB4X3NlcmlhbF9wcml2YXRl ICpwcml2ID0gdXNiX2dldF9zZXJpYWxfZGF0YShzZXJpYWwpOwogCXN0cnVjdCBjcDIxMHhfZ3Bp b193cml0ZSBidWY7CisJaW50IHJlc3VsdDsKIAogCWlmICh2YWx1ZSA9PSAxKQogCQlidWYuc3Rh dGUgPSBCSVQoZ3Bpbyk7CkBAIC0xMzU0LDI1ICsxMzYwLDY4IEBAIHN0YXRpYyB2b2lkIGNwMjEw eF9ncGlvX3NldChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IGdwaW8sIGludCB2 YWx1ZSkKIAogCWJ1Zi5tYXNrID0gQklUKGdwaW8pOwogCi0JY3AyMTB4X3dyaXRlX3ZlbmRvcl9i bG9jayhzZXJpYWwsIFJFUVRZUEVfSE9TVF9UT19JTlRFUkZBQ0UsCi0JCQkJICBDUDIxMFhfV1JJ VEVfTEFUQ0gsICZidWYsIHNpemVvZihidWYpKTsKKwlpZiAocHJpdi0+cGFydG51bSA9PSBDUDIx MFhfUEFSVE5VTV9DUDIxMDUpIHsKKwkJcmVzdWx0ID0gY3AyMTB4X3dyaXRlX3ZlbmRvcl9ibG9j ayhzZXJpYWwsCisJCQkJCQkgICBSRVFUWVBFX0hPU1RfVE9fSU5URVJGQUNFLAorCQkJCQkJICAg Q1AyMTBYX1dSSVRFX0xBVENILCAmYnVmLAorCQkJCQkJICAgc2l6ZW9mKGJ1ZikpOworCX0gZWxz ZSB7CisJCXUxNiB3SW5kZXggPSBidWYuc3RhdGUgPDwgOCB8IGJ1Zi5tYXNrOworCisJCXJlc3Vs dCA9IHVzYl9jb250cm9sX21zZyhzZXJpYWwtPmRldiwKKwkJCQkJIHVzYl9zbmRjdHJscGlwZShz ZXJpYWwtPmRldiwgMCksCisJCQkJCSBDUDIxMFhfVkVORE9SX1NQRUNJRklDLAorCQkJCQkgUkVR VFlQRV9IT1NUX1RPX0RFVklDRSwKKwkJCQkJIENQMjEwWF9XUklURV9MQVRDSCwKKwkJCQkJIHdJ bmRleCwKKwkJCQkJIE5VTEwsIDAsIFVTQl9DVFJMX1NFVF9USU1FT1VUKTsKKwl9CisKKwlpZiAo cmVzdWx0IDwgMCkgeworCQlkZXZfZXJyKCZzZXJpYWwtPmludGVyZmFjZS0+ZGV2LCAiZmFpbGVk IHRvIHNldCBHUElPIHZhbHVlOiAlZFxuIiwKKwkJCQlyZXN1bHQpOworCX0KIH0KIAogc3RhdGlj IGludCBjcDIxMHhfZ3Bpb19kaXJlY3Rpb25fZ2V0KHN0cnVjdCBncGlvX2NoaXAgKmdjLCB1bnNp Z25lZCBpbnQgZ3BpbykKIHsKLQkvKiBIYXJkd2FyZSBkb2VzIG5vdCBzdXBwb3J0IGFuIGlucHV0 IG1vZGUgKi8KLQlyZXR1cm4gMDsKKwlzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsID0gZ3Bpb2No aXBfZ2V0X2RhdGEoZ2MpOworCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3ByaXZhdGUgKnByaXYgPSB1 c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7CisKKwlyZXR1cm4gcHJpdi0+Z3Bpb19pbnB1dCAm IEJJVChncGlvKTsKIH0KIAogc3RhdGljIGludCBjcDIxMHhfZ3Bpb19kaXJlY3Rpb25faW5wdXQo c3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVuc2lnbmVkIGludCBncGlvKQogewotCS8qIEhhcmR3YXJl IGRvZXMgbm90IHN1cHBvcnQgYW4gaW5wdXQgbW9kZSAqLwotCXJldHVybiAtRU5PVFNVUFA7CisJ c3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCA9IGdwaW9jaGlwX2dldF9kYXRhKGdjKTsKKwlzdHJ1 Y3QgY3AyMTB4X3NlcmlhbF9wcml2YXRlICpwcml2ID0gdXNiX2dldF9zZXJpYWxfZGF0YShzZXJp YWwpOworCisJaWYgKHByaXYtPnBhcnRudW0gPT0gQ1AyMTBYX1BBUlROVU1fQ1AyMTA1KSB7CisJ CS8qIGhhcmR3YXJlIGRvZXMgbm90IHN1cHBvcnQgYW4gaW5wdXQgbW9kZSAqLworCQlyZXR1cm4g LUVOT1RTVVBQOworCX0KKworCS8qIHB1c2gtcHVsbCBwaW5zIGNhbm5vdCBiZSBjaGFuZ2VkIHRv IGJlIGlucHV0cyAqLworCWlmIChwcml2LT5ncGlvX3B1c2hwdWxsICYgQklUKGdwaW8pKQorCQly ZXR1cm4gLUVJTlZBTDsKKworCS8qIG1ha2Ugc3VyZSB0byByZWxlYXNlIHBpbiBpZiBpdCBpcyBi ZWluZyBkcml2ZW4gbG93ICovCisJY3AyMTB4X2dwaW9fc2V0KGdjLCBncGlvLCAxKTsKKworCXBy aXYtPmdwaW9faW5wdXQgfD0gQklUKGdwaW8pOworCisJcmV0dXJuIDA7CiB9CiAKIHN0YXRpYyBp bnQgY3AyMTB4X2dwaW9fZGlyZWN0aW9uX291dHB1dChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5z aWduZWQgaW50IGdwaW8sCiAJCQkJCWludCB2YWx1ZSkKIHsKKwlzdHJ1Y3QgdXNiX3NlcmlhbCAq c2VyaWFsID0gZ3Bpb2NoaXBfZ2V0X2RhdGEoZ2MpOworCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3By aXZhdGUgKnByaXYgPSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7CisKKwlwcml2LT5ncGlv X2lucHV0ICY9IH5CSVQoZ3Bpbyk7CisJY3AyMTB4X2dwaW9fc2V0KGdjLCBncGlvLCB2YWx1ZSk7 CisKIAlyZXR1cm4gMDsKIH0KIApAQCAtMTM4NSwxMSArMTQzNCwxMSBAQCBzdGF0aWMgaW50IGNw MjEweF9ncGlvX3NldF9jb25maWcoc3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVuc2lnbmVkIGludCBn cGlvLAogCiAJLyogU3VjY2VlZCBvbmx5IGlmIGluIGNvcnJlY3QgbW9kZSAodGhpcyBjYW4ndCBi ZSBzZXQgYXQgcnVudGltZSkgKi8KIAlpZiAoKHBhcmFtID09IFBJTl9DT05GSUdfRFJJVkVfUFVT SF9QVUxMKSAmJgotCSAgICAocHJpdi0+Z3Bpb19tb2RlICYgQklUKGdwaW8pKSkKKwkgICAgKHBy aXYtPmdwaW9fcHVzaHB1bGwgJiBCSVQoZ3BpbykpKQogCQlyZXR1cm4gMDsKIAogCWlmICgocGFy YW0gPT0gUElOX0NPTkZJR19EUklWRV9PUEVOX0RSQUlOKSAmJgotCSAgICAhKHByaXYtPmdwaW9f bW9kZSAmIEJJVChncGlvKSkpCisJICAgICEocHJpdi0+Z3Bpb19wdXNocHVsbCAmIEJJVChncGlv KSkpCiAJCXJldHVybiAwOwogCiAJcmV0dXJuIC1FTk9UU1VQUDsKQEAgLTE0MDIsMTIgKzE0NTEs MTMgQEAgc3RhdGljIGludCBjcDIxMHhfZ3Bpb19zZXRfY29uZmlnKHN0cnVjdCBncGlvX2NoaXAg KmdjLCB1bnNpZ25lZCBpbnQgZ3BpbywKICAqIHRoaXMgZHJpdmVyIHRoYXQgcHJvdmlkZSBHUElP IGRvIHNvIGluIGEgd2F5IHRoYXQgZG9lcyBub3QgaW1wYWN0IG90aGVyCiAgKiBzaWduYWxzIGFu ZCBhcmUgdGh1cyBleHBlY3RlZCB0byBoYXZlIHZlcnkgZGlmZmVyZW50IGluaXRpYWxpc2F0aW9u LgogICovCi1zdGF0aWMgaW50IGNwMjEwNV9zaGFyZWRfZ3Bpb19pbml0KHN0cnVjdCB1c2Jfc2Vy aWFsICpzZXJpYWwpCitzdGF0aWMgaW50IGNwMjEwNV9ncGlvY29uZl9pbml0KHN0cnVjdCB1c2Jf c2VyaWFsICpzZXJpYWwpCiB7CiAJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJpdiA9 IHVzYl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFsKTsKIAlzdHJ1Y3QgY3AyMTB4X3Bpbl9tb2RlIG1v ZGU7CiAJc3RydWN0IGNwMjEweF9jb25maWcgY29uZmlnOwogCXU4IGludGZfbnVtID0gY3AyMTB4 X2ludGVyZmFjZV9udW0oc2VyaWFsKTsKKwl1OCBpZmFjZV9jb25maWc7CiAJaW50IHJlc3VsdDsK IAogCXJlc3VsdCA9IGNwMjEweF9yZWFkX3ZlbmRvcl9ibG9jayhzZXJpYWwsIFJFUVRZUEVfREVW SUNFX1RPX0hPU1QsCkBAIC0xNDI0LDIwICsxNDc0LDI2IEBAIHN0YXRpYyBpbnQgY3AyMTA1X3No YXJlZF9ncGlvX2luaXQoc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCkKIAogCS8qICAyIGJhbmtz IG9mIEdQSU8gLSBPbmUgZm9yIHRoZSBwaW5zIHRha2VuIGZyb20gZWFjaCBzZXJpYWwgcG9ydCAq LwogCWlmIChpbnRmX251bSA9PSAwKSB7Ci0JCWlmIChtb2RlLmVjaSA9PSBDUDIxMFhfUElOX01P REVfTU9ERU0pCisJCWlmIChtb2RlLmVjaSA9PSBDUDIxMFhfUElOX01PREVfTU9ERU0pIHsKKwkJ CS8qIG1hcmsgYWxsIEdQSU9zIG9mIHRoaXMgaW50ZXJmYWNlIGFzIHJlc2VydmVkICovCisJCQlw cml2LT5ncGlvX2FsdGZ1bmMgPSAweGZmOwogCQkJcmV0dXJuIDA7CisJCX0KIAotCQlwcml2LT5j b25maWcgPSBjb25maWcuZWNpX2NmZzsKLQkJcHJpdi0+Z3Bpb19tb2RlID0gKHU4KSgobGUxNl90 b19jcHUoY29uZmlnLmdwaW9fbW9kZSkgJgorCQlpZmFjZV9jb25maWcgPSBjb25maWcuZWNpX2Nm ZzsKKwkJcHJpdi0+Z3Bpb19wdXNocHVsbCA9ICh1OCkoKGxlMTZfdG9fY3B1KGNvbmZpZy5ncGlv X21vZGUpICYKIAkJCQkJCUNQMjEwWF9FQ0lfR1BJT19NT0RFX01BU0spID4+CiAJCQkJCQlDUDIx MFhfRUNJX0dQSU9fTU9ERV9PRkZTRVQpOwogCQlwcml2LT5nYy5uZ3BpbyA9IDI7CiAJfSBlbHNl IGlmIChpbnRmX251bSA9PSAxKSB7Ci0JCWlmIChtb2RlLnNjaSA9PSBDUDIxMFhfUElOX01PREVf TU9ERU0pCisJCWlmIChtb2RlLnNjaSA9PSBDUDIxMFhfUElOX01PREVfTU9ERU0pIHsKKwkJCS8q IG1hcmsgYWxsIEdQSU9zIG9mIHRoaXMgaW50ZXJmYWNlIGFzIHJlc2VydmVkICovCisJCQlwcml2 LT5ncGlvX2FsdGZ1bmMgPSAweGZmOwogCQkJcmV0dXJuIDA7CisJCX0KIAotCQlwcml2LT5jb25m aWcgPSBjb25maWcuc2NpX2NmZzsKLQkJcHJpdi0+Z3Bpb19tb2RlID0gKHU4KSgobGUxNl90b19j cHUoY29uZmlnLmdwaW9fbW9kZSkgJgorCQlpZmFjZV9jb25maWcgPSBjb25maWcuc2NpX2NmZzsK KwkJcHJpdi0+Z3Bpb19wdXNocHVsbCA9ICh1OCkoKGxlMTZfdG9fY3B1KGNvbmZpZy5ncGlvX21v ZGUpICYKIAkJCQkJCUNQMjEwWF9TQ0lfR1BJT19NT0RFX01BU0spID4+CiAJCQkJCQlDUDIxMFhf U0NJX0dQSU9fTU9ERV9PRkZTRVQpOwogCQlwcml2LT5nYy5uZ3BpbyA9IDM7CkBAIC0xNDQ1LDYg KzE1MDEsMTI1IEBAIHN0YXRpYyBpbnQgY3AyMTA1X3NoYXJlZF9ncGlvX2luaXQoc3RydWN0IHVz Yl9zZXJpYWwgKnNlcmlhbCkKIAkJcmV0dXJuIC1FTk9ERVY7CiAJfQogCisJLyogbWFyayBhbGwg cGlucyB3aGljaCBhcmUgbm90IGluIEdQSU8gbW9kZSAqLworCWlmIChpZmFjZV9jb25maWcgJiBD UDIxMDVfR1BJTzBfVFhMRURfTU9ERSkJLyogR1BJTyAwICovCisJCXByaXYtPmdwaW9fYWx0ZnVu YyB8PSBCSVQoMCk7CisJaWYgKGlmYWNlX2NvbmZpZyAmIChDUDIxMDVfR1BJTzFfUlhMRURfTU9E RSB8CS8qIEdQSU8gMSAqLworCQkJQ1AyMTA1X0dQSU8xX1JTNDg1X01PREUpKQorCQlwcml2LT5n cGlvX2FsdGZ1bmMgfD0gQklUKDEpOworCisJLyogZHJpdmVyIGltcGxlbWVudGF0aW9uIGZvciBD UDIxMDUgb25seSBzdXBwb3J0cyBvdXRwdXRzICovCisJcHJpdi0+Z3Bpb19pbnB1dCA9IDA7CisK KwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjcDIxMDJuX2dwaW9jb25mX2luaXQoc3RydWN0 IHVzYl9zZXJpYWwgKnNlcmlhbCkKK3sKKwlzdHJ1Y3QgY3AyMTB4X3NlcmlhbF9wcml2YXRlICpw cml2ID0gdXNiX2dldF9zZXJpYWxfZGF0YShzZXJpYWwpOworCWNvbnN0IHUxNiBjb25maWdfc2l6 ZSA9IDB4MDJhNjsKKwl1OCBncGlvX3JzdF9sYXRjaDsKKwl1OCBjb25maWdfdmVyc2lvbjsKKwl1 OCBncGlvX3B1c2hwdWxsOworCXU4ICpjb25maWdfYnVmOworCXU4IGdwaW9fbGF0Y2g7CisJdTgg Z3Bpb19jdHJsOworCWludCByZXN1bHQ7CisJdTggaTsKKworCS8qCisJICogUmV0cmlldmUgZGV2 aWNlIGNvbmZpZ3VyYXRpb24gZnJvbSB0aGUgZGV2aWNlLgorCSAqIFRoZSBhcnJheSByZWNlaXZl ZCBjb250YWlucyBhbGwgY3VzdG9taXphdGlvbiBzZXR0aW5ncyBkb25lIGF0IHRoZQorCSAqIGZh Y3RvcnkvbWFudWZhY3R1cmVyLiBGb3JtYXQgb2YgdGhlIGFycmF5IGlzIGRvY3VtZW50ZWQgYXQg dGhlCisJICogdGltZSBvZiB3cml0aW5nIGF0OgorCSAqIGh0dHBzOi8vd3d3LnNpbGFicy5jb20v Y29tbXVuaXR5L2ludGVyZmFjZS9rbm93bGVkZ2UtYmFzZS5lbnRyeS5odG1sLzIwMTcvMDMvMzEv Y3AyMTAybl9zZXRjb25maWcteHNmYQorCSAqLworCWNvbmZpZ19idWYgPSBrbWFsbG9jKGNvbmZp Z19zaXplLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWNvbmZpZ19idWYpCisJCXJldHVybiAtRU5PTUVN OworCisJcmVzdWx0ID0gY3AyMTB4X3JlYWRfdmVuZG9yX2Jsb2NrKHNlcmlhbCwKKwkJCQkJICBS RVFUWVBFX0RFVklDRV9UT19IT1NULAorCQkJCQkgIENQMjEwWF9SRUFEXzJOQ09ORklHLAorCQkJ CQkgIGNvbmZpZ19idWYsCisJCQkJCSAgY29uZmlnX3NpemUpOworCWlmIChyZXN1bHQgPCAwKSB7 CisJCWtmcmVlKGNvbmZpZ19idWYpOworCQlyZXR1cm4gcmVzdWx0OworCX0KKworCWNvbmZpZ192 ZXJzaW9uID0gY29uZmlnX2J1ZltDUDIxMFhfMk5DT05GSUdfQ09ORklHX1ZFUlNJT05fSURYXTsK KwlncGlvX3B1c2hwdWxsID0gY29uZmlnX2J1ZltDUDIxMFhfMk5DT05GSUdfR1BJT19NT0RFX0lE WF07CisJZ3Bpb19jdHJsID0gY29uZmlnX2J1ZltDUDIxMFhfMk5DT05GSUdfR1BJT19DT05UUk9M X0lEWF07CisJZ3Bpb19yc3RfbGF0Y2ggPSBjb25maWdfYnVmW0NQMjEwWF8yTkNPTkZJR19HUElP X1JTVExBVENIX0lEWF07CisKKwlrZnJlZShjb25maWdfYnVmKTsKKworCS8qIE1ha2Ugc3VyZSB0 aGlzIGlzIGEgY29uZmlnIGZvcm1hdCB3ZSB1bmRlcnN0YW5kLiAqLworCWlmIChjb25maWdfdmVy c2lvbiAhPSAweDAxKQorCQlyZXR1cm4gLUVOT1RTVVBQOworCisJLyoKKwkgKiBXZSBvbmx5IHN1 cHBvcnQgNCBHUElPcyBldmVuIG9uIHRoZSBRRk4yOCBwYWNrYWdlLCBiZWNhdXNlCisJICogY29u ZmlnIGxvY2F0aW9ucyBvZiBHUElPcyA0LTYgZGV0ZXJtaW5lZCB1c2luZyByZXZlcnNlCisJICog ZW5naW5lZXJpbmcgcmV2ZWFsZWQgY29uZmxpY3Rpbmcgb2Zmc2V0cyB3aXRoIG90aGVyCisJICog ZG9jdW1lbnRlZCBmdW5jdGlvbnMuIFNvIHdlJ2xsIGp1c3QgcGxheSBpdCBzYWZlIGZvciBub3cu CisJICovCisJcHJpdi0+Z2MubmdwaW8gPSA0OworCisJLyoKKwkgKiBHZXQgZGVmYXVsdCBwaW4g c3RhdGVzIGFmdGVyIHJlc2V0LiBOZWVkZWQgc28gd2UgY2FuIGRldGVybWluZQorCSAqIHRoZSBk aXJlY3Rpb24gb2YgYW4gb3Blbi1kcmFpbiBwaW4uCisJICovCisJZ3Bpb19sYXRjaCA9IChncGlv X3JzdF9sYXRjaCA+PiAzKSAmIDB4MGY7CisKKwkvKiAwIGluZGljYXRlcyBvcGVuLWRyYWluIG1v ZGUsIDEgaXMgcHVzaC1wdWxsICovCisJcHJpdi0+Z3Bpb19wdXNocHVsbCA9IChncGlvX3B1c2hw dWxsID4+IDMpICYgMHgwZjsKKworCS8qIDAgaW5kaWNhdGVzIEdQSU8gbW9kZSwgMSBpcyBhbHRl cm5hdGUgZnVuY3Rpb24gKi8KKwlwcml2LT5ncGlvX2FsdGZ1bmMgPSAoZ3Bpb19jdHJsID4+IDIp ICYgMHgwZjsKKworCS8qCisJICogVGhlIENQMjEwMk4gZG9lcyBub3Qgc3RyaWN0bHkgaGFzIGlu cHV0IGFuZCBvdXRwdXQgcGluIG1vZGVzLAorCSAqIGl0IG9ubHkga25vd3Mgb3Blbi1kcmFpbiBh bmQgcHVzaC1wdWxsIG1vZGVzIHdoaWNoIGlzIHNldCBhdAorCSAqIGZhY3RvcnkuIEFuIG9wZW4t ZHJhaW4gcGluIGNhbiBmdW5jdGlvbiBib3RoIGFzIGFuCisJICogaW5wdXQgb3IgYW4gb3V0cHV0 LiBXZSBlbXVsYXRlIGlucHV0IG1vZGUgZm9yIG9wZW4tZHJhaW4gcGlucworCSAqIGJ5IG1ha2lu ZyBzdXJlIHRoZXkgYXJlIG5vdCBkcml2ZW4gbG93LCBhbmQgd2UgZG8gbm90IGFsbG93CisJICog cHVzaC1wdWxsIHBpbnMgdG8gYmUgc2V0IGFzIGFuIGlucHV0LgorCSAqLworCWZvciAoaSA9IDA7 IGkgPCBwcml2LT5nYy5uZ3BpbzsgKytpKSB7CisJCS8qCisJCSAqIFNldCBkaXJlY3Rpb24gdG8g ImlucHV0IiBpZmYgcGluIGlzIG9wZW4tZHJhaW4gYW5kIHJlc2V0CisJCSAqIHZhbHVlIGlzIDEu CisJCSAqLworCQlpZiAoIShwcml2LT5ncGlvX3B1c2hwdWxsICYgQklUKGkpKSAmJiAoZ3Bpb19s YXRjaCAmIEJJVChpKSkpCisJCQlwcml2LT5ncGlvX2lucHV0IHw9IEJJVChpKTsKKwl9CisKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIGludCBjcDIxMHhfZ3Bpb19pbml0KHN0cnVjdCB1c2Jfc2Vy aWFsICpzZXJpYWwpCit7CisJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJpdiA9IHVz Yl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFsKTsKKwlpbnQgcmVzdWx0OworCisJc3dpdGNoIChwcml2 LT5wYXJ0bnVtKSB7CisJY2FzZSBDUDIxMFhfUEFSVE5VTV9DUDIxMDU6CisJCXJlc3VsdCA9IGNw MjEwNV9ncGlvY29uZl9pbml0KHNlcmlhbCk7CisJCWJyZWFrOworCWNhc2UgQ1AyMTBYX1BBUlRO VU1fQ1AyMTAyTl9RRk4yODoKKwljYXNlIENQMjEwWF9QQVJUTlVNX0NQMjEwMk5fUUZOMjQ6CisJ Y2FzZSBDUDIxMFhfUEFSVE5VTV9DUDIxMDJOX1FGTjIwOgorCQlyZXN1bHQgPSBjcDIxMDJuX2dw aW9jb25mX2luaXQoc2VyaWFsKTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0dXJuIDA7CisJ fQorCisJaWYgKHJlc3VsdCA8IDApCisJCXJldHVybiByZXN1bHQ7CisKIAlwcml2LT5nYy5sYWJl bCA9ICJjcDIxMHgiOwogCXByaXYtPmdjLnJlcXVlc3QgPSBjcDIxMHhfZ3Bpb19yZXF1ZXN0Owog CXByaXYtPmdjLmdldF9kaXJlY3Rpb24gPSBjcDIxMHhfZ3Bpb19kaXJlY3Rpb25fZ2V0OwpAQCAt MTQ3Nyw3ICsxNjUyLDcgQEAgc3RhdGljIHZvaWQgY3AyMTB4X2dwaW9fcmVtb3ZlKHN0cnVjdCB1 c2Jfc2VyaWFsICpzZXJpYWwpCiAKICNlbHNlCiAKLXN0YXRpYyBpbnQgY3AyMTA1X3NoYXJlZF9n cGlvX2luaXQoc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCkKK3N0YXRpYyBpbnQgY3AyMTB4X2dw aW9faW5pdChzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsKQogewogCXJldHVybiAwOwogfQpAQCAt MTU4OCwxMiArMTc2MywxMCBAQCBzdGF0aWMgaW50IGNwMjEweF9hdHRhY2goc3RydWN0IHVzYl9z ZXJpYWwgKnNlcmlhbCkKIAogCWNwMjEweF9pbml0X21heF9zcGVlZChzZXJpYWwpOwogCi0JaWYg KHByaXYtPnBhcnRudW0gPT0gQ1AyMTBYX1BBUlROVU1fQ1AyMTA1KSB7Ci0JCXJlc3VsdCA9IGNw MjEwNV9zaGFyZWRfZ3Bpb19pbml0KHNlcmlhbCk7Ci0JCWlmIChyZXN1bHQgPCAwKSB7Ci0JCQlk ZXZfZXJyKCZzZXJpYWwtPmludGVyZmFjZS0+ZGV2LAotCQkJCSJHUElPIGluaXRpYWxpc2F0aW9u IGZhaWxlZCwgY29udGludWluZyB3aXRob3V0IEdQSU8gc3VwcG9ydFxuIik7Ci0JCX0KKwlyZXN1 bHQgPSBjcDIxMHhfZ3Bpb19pbml0KHNlcmlhbCk7CisJaWYgKHJlc3VsdCA8IDApIHsKKwkJZGV2 X2Vycigmc2VyaWFsLT5pbnRlcmZhY2UtPmRldiwgIkdQSU8gaW5pdGlhbGlzYXRpb24gZmFpbGVk OiAlZFxuIiwKKwkJCQlyZXN1bHQpOwogCX0KIAogCXJldHVybiAwOwo= 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=-2.9 required=3.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,SPF_PASS,T_DKIM_INVALID,URIBL_BLOCKED,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 C94B3ECDFBB for ; Fri, 20 Jul 2018 10:53:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F00820661 for ; Fri, 20 Jul 2018 10:53:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YaUxM8Ez" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F00820661 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728616AbeGTLlC (ORCPT ); Fri, 20 Jul 2018 07:41:02 -0400 Received: from mail-lf1-f65.google.com ([209.85.167.65]:32897 "EHLO mail-lf1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727408AbeGTLlC (ORCPT ); Fri, 20 Jul 2018 07:41:02 -0400 Received: by mail-lf1-f65.google.com with SMTP id u14-v6so1497423lfu.0; Fri, 20 Jul 2018 03:53:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=ZgOJx5nmfCxa2XCWtgxQW6K5OK0WOME5fy/V+GQGVKY=; b=YaUxM8EzsNdNQQ+lZEx/+W9vjqMra6FoZu1a5wNIOzyCdwVzUXcOeCAO56azWYUI+a grA3QZ9pKNcsCB3uQzl6+JawhPMxvboE2h7K6hK0WvS/y8M1/V6QIDvAFNOPs/GyqETo cLLFFNZvDwhNEx8KqPvjA+PsLQ2oYEeqBNLtsEhfwG+uuJsWXA7rkRG0xxulCklPtQH8 Vci0TIer8JFdJH5YvFLjB9tD4M/rLGLPnIXdMiuANtuj5DT+hVl7SdDoJqb5c9UtwHUc eT6CEoUauv2yXWSTFPGade6sKgmXYBR1jX6JnL5e9V2jF+ye42ACX9XCe9lbLqg8hgP4 2BIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=ZgOJx5nmfCxa2XCWtgxQW6K5OK0WOME5fy/V+GQGVKY=; b=kF5QE+NPLGgxMJhNjEIlrSrOZ33ODIacbBBE1DN13l1d1LiFxBzxr9mDDftz4NYdEP uGAe+XJfjUfv4XigndPybfVaDbCpxCvC4fRTIRF+lUqqU2kY6L7+MGsFcGHrHstMnk47 0PI9LjIWfy6/orN6cPELKaTrbfSZbqtyoq5P5gqxgIkGdrQa1yIrQ6NXLc/gM+7BBrAZ rjNykTv+8Q0aS8XGnYWV9FS/8fbrB9n0Titb3r6K77bPEPHXpKPaLZuUqFi36t+0V47/ QxGhRmRhCGnyOKKef8mNJ8lBxDQYqUvLRhk6erkA/htSKGx4sB1WDRmLsdZUMFfU49JM F3Cg== X-Gm-Message-State: AOUpUlE9PWbvMxhC2zRdolFonxO74dLhh2YrxhAgCydLI9sehULl3X5x Ith+fXBrYJH7FrVLMfJA6vY= X-Google-Smtp-Source: AAOMgpceINjSI9Q3/B5IKucLeXgmAr4gcZsZQo65s+ub0BXYwcAHxboH2PfQh15ZUpAK0t/GRQ+rUw== X-Received: by 2002:a19:8d07:: with SMTP id p7-v6mr1129956lfd.117.1532083998942; Fri, 20 Jul 2018 03:53:18 -0700 (PDT) Received: from xi.terra (c-8bb2e655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.178.139]) by smtp.gmail.com with ESMTPSA id y16-v6sm300865lje.30.2018.07.20.03.53.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Jul 2018 03:53:18 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1fgT20-0006Qw-6x; Fri, 20 Jul 2018 12:53:04 +0200 From: Johan Hovold To: Johan Hovold Cc: Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Karoly Pados , Martyn Welch Subject: [PATCH v3] USB: serial: cp210x: Implement GPIO support for CP2102N Date: Fri, 20 Jul 2018 12:52:40 +0200 Message-Id: <20180720105240.24680-1-johan@kernel.org> X-Mailer: git-send-email 2.18.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Karoly Pados This is v2 of the patch and addresses all feedback previously received from the maintainer. New input/output support stayed as discussed on the e-mail lists separately. CP2105 is also using the new code structure, but due to missing way to get default pin states after reset from the device, support for this device is basically still output-only as before, at least in name. But CP2105 and CP2102N paths are unified. This patch is based on the latest patch series by Johan just submitted today. Signed-off-by: Karoly Pados [ johan: fix style issues and a couple of minor bugs ] Cc: Martyn Welch Signed-off-by: Johan Hovold --- This is Karoly's v2 patch with some style issues and a couple of minor bugs fixed. I'll wait for an updated commit message before applying. Johan drivers/usb/serial/cp210x.c | 245 ++++++++++++++++++++++++++++++------ 1 file changed, 209 insertions(+), 36 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4a118eb13590..b9bc80700be7 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -224,9 +224,10 @@ MODULE_DEVICE_TABLE(usb, id_table); struct cp210x_serial_private { #ifdef CONFIG_GPIOLIB struct gpio_chip gc; - u8 config; - u8 gpio_mode; bool gpio_registered; + u8 gpio_pushpull; + u8 gpio_altfunc; + u8 gpio_input; #endif u8 partnum; speed_t max_speed; @@ -343,6 +344,7 @@ static struct usb_serial_driver * const serial_drivers[] = { #define CONTROL_WRITE_RTS 0x0200 /* CP210X_VENDOR_SPECIFIC values */ +#define CP210X_READ_2NCONFIG 0x000E #define CP210X_READ_LATCH 0x00C2 #define CP210X_GET_PARTNUM 0x370B #define CP210X_GET_PORTCONFIG 0x370C @@ -452,6 +454,12 @@ struct cp210x_config { #define CP2105_GPIO1_RXLED_MODE BIT(1) #define CP2105_GPIO1_RS485_MODE BIT(2) +/* CP2102N configuration array indices */ +#define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2 +#define CP210X_2NCONFIG_GPIO_MODE_IDX 581 +#define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587 +#define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600 + /* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */ struct cp210x_gpio_write { u8 mask; @@ -1313,17 +1321,8 @@ static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset) struct usb_serial *serial = gpiochip_get_data(gc); struct cp210x_serial_private *priv = usb_get_serial_data(serial); - switch (offset) { - case 0: - if (priv->config & CP2105_GPIO0_TXLED_MODE) - return -ENODEV; - break; - case 1: - if (priv->config & (CP2105_GPIO1_RXLED_MODE | - CP2105_GPIO1_RS485_MODE)) - return -ENODEV; - break; - } + if (priv->gpio_altfunc & BIT(offset)) + return -ENODEV; return 0; } @@ -1331,10 +1330,15 @@ static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset) static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + u8 req_type = REQTYPE_DEVICE_TO_HOST; int result; u8 buf; - result = cp210x_read_vendor_block(serial, REQTYPE_INTERFACE_TO_HOST, + if (priv->partnum == CP210X_PARTNUM_CP2105) + req_type = REQTYPE_INTERFACE_TO_HOST; + + result = cp210x_read_vendor_block(serial, req_type, CP210X_READ_LATCH, &buf, sizeof(buf)); if (result < 0) return result; @@ -1345,7 +1349,9 @@ static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) { struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); struct cp210x_gpio_write buf; + int result; if (value == 1) buf.state = BIT(gpio); @@ -1354,25 +1360,68 @@ static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) buf.mask = BIT(gpio); - cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE, - CP210X_WRITE_LATCH, &buf, sizeof(buf)); + if (priv->partnum == CP210X_PARTNUM_CP2105) { + result = cp210x_write_vendor_block(serial, + REQTYPE_HOST_TO_INTERFACE, + CP210X_WRITE_LATCH, &buf, + sizeof(buf)); + } else { + u16 wIndex = buf.state << 8 | buf.mask; + + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + CP210X_VENDOR_SPECIFIC, + REQTYPE_HOST_TO_DEVICE, + CP210X_WRITE_LATCH, + wIndex, + NULL, 0, USB_CTRL_SET_TIMEOUT); + } + + if (result < 0) { + dev_err(&serial->interface->dev, "failed to set GPIO value: %d\n", + result); + } } static int cp210x_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio) { - /* Hardware does not support an input mode */ - return 0; + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + return priv->gpio_input & BIT(gpio); } static int cp210x_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) { - /* Hardware does not support an input mode */ - return -ENOTSUPP; + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + if (priv->partnum == CP210X_PARTNUM_CP2105) { + /* hardware does not support an input mode */ + return -ENOTSUPP; + } + + /* push-pull pins cannot be changed to be inputs */ + if (priv->gpio_pushpull & BIT(gpio)) + return -EINVAL; + + /* make sure to release pin if it is being driven low */ + cp210x_gpio_set(gc, gpio, 1); + + priv->gpio_input |= BIT(gpio); + + return 0; } static int cp210x_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, int value) { + struct usb_serial *serial = gpiochip_get_data(gc); + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + + priv->gpio_input &= ~BIT(gpio); + cp210x_gpio_set(gc, gpio, value); + return 0; } @@ -1385,11 +1434,11 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio, /* Succeed only if in correct mode (this can't be set at runtime) */ if ((param == PIN_CONFIG_DRIVE_PUSH_PULL) && - (priv->gpio_mode & BIT(gpio))) + (priv->gpio_pushpull & BIT(gpio))) return 0; if ((param == PIN_CONFIG_DRIVE_OPEN_DRAIN) && - !(priv->gpio_mode & BIT(gpio))) + !(priv->gpio_pushpull & BIT(gpio))) return 0; return -ENOTSUPP; @@ -1402,12 +1451,13 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio, * this driver that provide GPIO do so in a way that does not impact other * signals and are thus expected to have very different initialisation. */ -static int cp2105_shared_gpio_init(struct usb_serial *serial) +static int cp2105_gpioconf_init(struct usb_serial *serial) { struct cp210x_serial_private *priv = usb_get_serial_data(serial); struct cp210x_pin_mode mode; struct cp210x_config config; u8 intf_num = cp210x_interface_num(serial); + u8 iface_config; int result; result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, @@ -1424,20 +1474,26 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial) /* 2 banks of GPIO - One for the pins taken from each serial port */ if (intf_num == 0) { - if (mode.eci == CP210X_PIN_MODE_MODEM) + if (mode.eci == CP210X_PIN_MODE_MODEM) { + /* mark all GPIOs of this interface as reserved */ + priv->gpio_altfunc = 0xff; return 0; + } - priv->config = config.eci_cfg; - priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & + iface_config = config.eci_cfg; + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & CP210X_ECI_GPIO_MODE_MASK) >> CP210X_ECI_GPIO_MODE_OFFSET); priv->gc.ngpio = 2; } else if (intf_num == 1) { - if (mode.sci == CP210X_PIN_MODE_MODEM) + if (mode.sci == CP210X_PIN_MODE_MODEM) { + /* mark all GPIOs of this interface as reserved */ + priv->gpio_altfunc = 0xff; return 0; + } - priv->config = config.sci_cfg; - priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & + iface_config = config.sci_cfg; + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & CP210X_SCI_GPIO_MODE_MASK) >> CP210X_SCI_GPIO_MODE_OFFSET); priv->gc.ngpio = 3; @@ -1445,6 +1501,125 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial) return -ENODEV; } + /* mark all pins which are not in GPIO mode */ + if (iface_config & CP2105_GPIO0_TXLED_MODE) /* GPIO 0 */ + priv->gpio_altfunc |= BIT(0); + if (iface_config & (CP2105_GPIO1_RXLED_MODE | /* GPIO 1 */ + CP2105_GPIO1_RS485_MODE)) + priv->gpio_altfunc |= BIT(1); + + /* driver implementation for CP2105 only supports outputs */ + priv->gpio_input = 0; + + return 0; +} + +static int cp2102n_gpioconf_init(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + const u16 config_size = 0x02a6; + u8 gpio_rst_latch; + u8 config_version; + u8 gpio_pushpull; + u8 *config_buf; + u8 gpio_latch; + u8 gpio_ctrl; + int result; + u8 i; + + /* + * Retrieve device configuration from the device. + * The array received contains all customization settings done at the + * factory/manufacturer. Format of the array is documented at the + * time of writing at: + * https://www.silabs.com/community/interface/knowledge-base.entry.html/2017/03/31/cp2102n_setconfig-xsfa + */ + config_buf = kmalloc(config_size, GFP_KERNEL); + if (!config_buf) + return -ENOMEM; + + result = cp210x_read_vendor_block(serial, + REQTYPE_DEVICE_TO_HOST, + CP210X_READ_2NCONFIG, + config_buf, + config_size); + if (result < 0) { + kfree(config_buf); + return result; + } + + config_version = config_buf[CP210X_2NCONFIG_CONFIG_VERSION_IDX]; + gpio_pushpull = config_buf[CP210X_2NCONFIG_GPIO_MODE_IDX]; + gpio_ctrl = config_buf[CP210X_2NCONFIG_GPIO_CONTROL_IDX]; + gpio_rst_latch = config_buf[CP210X_2NCONFIG_GPIO_RSTLATCH_IDX]; + + kfree(config_buf); + + /* Make sure this is a config format we understand. */ + if (config_version != 0x01) + return -ENOTSUPP; + + /* + * We only support 4 GPIOs even on the QFN28 package, because + * config locations of GPIOs 4-6 determined using reverse + * engineering revealed conflicting offsets with other + * documented functions. So we'll just play it safe for now. + */ + priv->gc.ngpio = 4; + + /* + * Get default pin states after reset. Needed so we can determine + * the direction of an open-drain pin. + */ + gpio_latch = (gpio_rst_latch >> 3) & 0x0f; + + /* 0 indicates open-drain mode, 1 is push-pull */ + priv->gpio_pushpull = (gpio_pushpull >> 3) & 0x0f; + + /* 0 indicates GPIO mode, 1 is alternate function */ + priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f; + + /* + * The CP2102N does not strictly has input and output pin modes, + * it only knows open-drain and push-pull modes which is set at + * factory. An open-drain pin can function both as an + * input or an output. We emulate input mode for open-drain pins + * by making sure they are not driven low, and we do not allow + * push-pull pins to be set as an input. + */ + for (i = 0; i < priv->gc.ngpio; ++i) { + /* + * Set direction to "input" iff pin is open-drain and reset + * value is 1. + */ + if (!(priv->gpio_pushpull & BIT(i)) && (gpio_latch & BIT(i))) + priv->gpio_input |= BIT(i); + } + + return 0; +} + +static int cp210x_gpio_init(struct usb_serial *serial) +{ + struct cp210x_serial_private *priv = usb_get_serial_data(serial); + int result; + + switch (priv->partnum) { + case CP210X_PARTNUM_CP2105: + result = cp2105_gpioconf_init(serial); + break; + case CP210X_PARTNUM_CP2102N_QFN28: + case CP210X_PARTNUM_CP2102N_QFN24: + case CP210X_PARTNUM_CP2102N_QFN20: + result = cp2102n_gpioconf_init(serial); + break; + default: + return 0; + } + + if (result < 0) + return result; + priv->gc.label = "cp210x"; priv->gc.request = cp210x_gpio_request; priv->gc.get_direction = cp210x_gpio_direction_get; @@ -1477,7 +1652,7 @@ static void cp210x_gpio_remove(struct usb_serial *serial) #else -static int cp2105_shared_gpio_init(struct usb_serial *serial) +static int cp210x_gpio_init(struct usb_serial *serial) { return 0; } @@ -1588,12 +1763,10 @@ static int cp210x_attach(struct usb_serial *serial) cp210x_init_max_speed(serial); - if (priv->partnum == CP210X_PARTNUM_CP2105) { - result = cp2105_shared_gpio_init(serial); - if (result < 0) { - dev_err(&serial->interface->dev, - "GPIO initialisation failed, continuing without GPIO support\n"); - } + result = cp210x_gpio_init(serial); + if (result < 0) { + dev_err(&serial->interface->dev, "GPIO initialisation failed: %d\n", + result); } return 0; -- 2.18.0