From mboxrd@z Thu Jan 1 00:00:00 1970 From: Philippe Schenker Subject: [PATCH v2 2/4] iio: adc: add STMPE ADC driver using IIO framework Date: Mon, 19 Nov 2018 11:25:26 +0100 Message-ID: <20181119102528.2830-2-dev@pschenker.ch> References: <20181119102528.2830-1-dev@pschenker.ch> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20181119102528.2830-1-dev@pschenker.ch> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: jic23@kernel.org, marcel.ziswiler@toradex.com, stefan@agner.ch Cc: Dmitry Torokhov , Max Krummenacher , linux-iio@vger.kernel.org, Peter Meerwald-Stadler , Lee Jones , linux-stm32@st-md-mailman.stormreply.com, Marcus Folkesson , Lars-Peter Clausen , Freeman Liu , Geert Uytterhoeven , linux-input@vger.kernel.org, Alexandre Torgue , Siddartha Mohanadoss , William Breathitt Gray , Philippe Schenker , Mark Brown , linux-arm-kernel@lists.infradead.org, Randy Dunlap , Arnaud Pouliquen , linux-kernel@vger.kernel.org, Maxime Coquelin , Hartmut Knaack List-Id: linux-input@vger.kernel.org RnJvbTogU3RlZmFuIEFnbmVyIDxzdGVmYW5AYWduZXIuY2g+CgpUaGlzIGFkZHMgYW4gQURDIGRy aXZlciBmb3IgdGhlIFNUTVBFIGRldmljZSB1c2luZyB0aGUgaW5kdXN0cmlhbAppbnB1dC9vdXRw dXQgaW50ZXJmYWNlLiBUaGUgZHJpdmVyIHN1cHBvcnRzIHJhdyByZWFkaW5nIG9mIHZhbHVlcy4K VGhlIGRyaXZlciBkZXBlbmRzIG9uIHRoZSBNRkQgU1RNUEUgZHJpdmVyLiBJZiB0aGUgdG91Y2hz Y3JlZW4KYmxvY2sgaXMgZW5hYmxlZCB0b28sIG9ubHkgZm91ciBvZiB0aGUgOCBBREMgY2hhbm5l bHMgYXJlIGF2YWlsYWJsZS4KClNpZ25lZC1vZmYtYnk6IFN0ZWZhbiBBZ25lciA8c3RlZmFuQGFn bmVyLmNoPgpTaWduZWQtb2ZmLWJ5OiBNYXggS3J1bW1lbmFjaGVyIDxtYXgua3J1bW1lbmFjaGVy QHRvcmFkZXguY29tPgpTaWduZWQtb2ZmLWJ5OiBQaGlsaXBwZSBTY2hlbmtlciA8cGhpbGlwcGUu c2NoZW5rZXJAdG9yYWRleC5jb20+Ci0tLQoKQ2hhbmdlcyBpbiB2MjoKIC0gQ29kZSBmb3JtYXR0 aW5nCiAtIE1vdmUgY29kZSB0byBzZXR1cCBBREMgdG8gTUZEIGRldmljZSwgYXMgaXQgaXMgdXNl ZCBieSBib3RoIGRyaXZlcnMKICAgYWRjIGFuZCB0b3VjaHNjcmVlbgogLSBSZW1vdmVkIHVudXNl ZCBpbmNsdWRlcwogLSBEZWZpbmVkIHRoZSBtYWNybyBTVE1QRV9TVEFSVF9PTkVfVEVNUF9DT05W IHdpdGggb3RoZXIgbWFjcm9zLgogLSBBZGRlZCBuZXcgbWFjcm8gdGhhdCBkZWZpbmVzIHRoZSBj aGFubmVsIG9mIHRoZSB0ZW1wZXJhdHVyZSBzZW5zb3IuCiAgIFRvb2sgbmV3IG5hbWUgZm9yIFNU TVBFX01BWF9BREMtPlNUTVBFX0FEQ19MQVNUX05SIGFuZCB1c2VkIGl0IHRocm91Z2hvdXQKICAg dGhlIGNvZGUgZm9yIGJldHRlciByZWFkYWJpbGl0eS4KIC0gQWRkZWQgbXV0ZXhfdW5sb2NrIHdo ZXJlIG1pc3NpbmcuCgogZHJpdmVycy9paW8vYWRjL0tjb25maWcgICAgICAgICAgICAgIHwgICA3 ICsKIGRyaXZlcnMvaWlvL2FkYy9NYWtlZmlsZSAgICAgICAgICAgICB8ICAgMSArCiBkcml2ZXJz L2lpby9hZGMvc3RtcGUtYWRjLmMgICAgICAgICAgfCAzNDAgKysrKysrKysrKysrKysrKysrKysr KysrKysrCiBkcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL3N0bXBlLXRzLmMgfCAgNDMgKy0tLQog ZHJpdmVycy9tZmQvS2NvbmZpZyAgICAgICAgICAgICAgICAgIHwgICAzICstCiBkcml2ZXJzL21m ZC9zdG1wZS5jICAgICAgICAgICAgICAgICAgfCAgODQgKysrKysrKwogaW5jbHVkZS9saW51eC9t ZmQvc3RtcGUuaCAgICAgICAgICAgIHwgICA2ICsKIDcgZmlsZXMgY2hhbmdlZCwgNDQ1IGluc2Vy dGlvbnMoKyksIDM5IGRlbGV0aW9ucygtKQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaWlv L2FkYy9zdG1wZS1hZGMuYwoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvaWlvL2FkYy9LY29uZmlnIGIv ZHJpdmVycy9paW8vYWRjL0tjb25maWcKaW5kZXggYTUyZmVhODc0OWE5Li41ZDRjMDYxZDgyOTYg MTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaWlvL2FkYy9LY29uZmlnCisrKyBiL2RyaXZlcnMvaWlvL2Fk Yy9LY29uZmlnCkBAIC03MzQsNiArNzM0LDEzIEBAIGNvbmZpZyBTVE0zMl9ERlNETV9BREMKIAkg IFRoaXMgZHJpdmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBt b2R1bGUKIAkgIHdpbGwgYmUgY2FsbGVkIHN0bTMyLWRmc2RtLWFkYy4KIAorY29uZmlnIFNUTVBF X0FEQworCXRyaXN0YXRlICJTVE1pY3JvZWxlY3Ryb25pY3MgU1RNUEUgQURDIGRyaXZlciIKKwlk ZXBlbmRzIG9uIChPRiB8fCBDT01QSUxFX1RFU1QgfHwgTUZEX1NUTVBFKQorCWhlbHAKKwkgIFNh eSB5ZXMgaGVyZSB0byBidWlsZCBzdXBwb3J0IGZvciBTVCBNaWNyb2VsZWN0cm9uaWNzIFNUTVBF CisJICBidWlsdC1pbiBBREMgYmxvY2sgKHN0bXBlODExKS4KKwogY29uZmlnIFNUWDEwNAogCXRy aXN0YXRlICJBcGV4IEVtYmVkZGVkIFN5c3RlbXMgU1RYMTA0IGRyaXZlciIKIAlkZXBlbmRzIG9u IFBDMTA0ICYmIFg4NgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIGIvZHJp dmVycy9paW8vYWRjL01ha2VmaWxlCmluZGV4IGE2ZTZhMGI2NTllMi4uY2JhODg5YzMwYmY5IDEw MDY0NAotLS0gYS9kcml2ZXJzL2lpby9hZGMvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9paW8vYWRj L01ha2VmaWxlCkBAIC02OSw2ICs2OSw3IEBAIG9iai0kKENPTkZJR19TVE0zMl9BRENfQ09SRSkg Kz0gc3RtMzItYWRjLWNvcmUubwogb2JqLSQoQ09ORklHX1NUTTMyX0FEQykgKz0gc3RtMzItYWRj Lm8KIG9iai0kKENPTkZJR19TVE0zMl9ERlNETV9DT1JFKSArPSBzdG0zMi1kZnNkbS1jb3JlLm8K IG9iai0kKENPTkZJR19TVE0zMl9ERlNETV9BREMpICs9IHN0bTMyLWRmc2RtLWFkYy5vCitvYmot JChDT05GSUdfU1RNUEVfQURDKSArPSBzdG1wZS1hZGMubwogb2JqLSQoQ09ORklHX1RJX0FEQzA4 MUMpICs9IHRpLWFkYzA4MWMubwogb2JqLSQoQ09ORklHX1RJX0FEQzA4MzIpICs9IHRpLWFkYzA4 MzIubwogb2JqLSQoQ09ORklHX1RJX0FEQzA4NFMwMjEpICs9IHRpLWFkYzA4NHMwMjEubwpkaWZm IC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL3N0bXBlLWFkYy5jIGIvZHJpdmVycy9paW8vYWRjL3N0 bXBlLWFkYy5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uMTUxZjFj OGY4MjdlCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9paW8vYWRjL3N0bXBlLWFkYy5jCkBA IC0wLDAgKzEsMzQwIEBACisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAorLyoK KyAqICBTVE1pY3JvZWxlY3Ryb25pY3MgU1RNUEU4MTEgSUlPIEFEQyBEcml2ZXIKKyAqCisgKiAg NCBjaGFubmVsLCAxMC8xMi1iaXQgQURDCisgKgorICogIENvcHlyaWdodCAoQykgMjAxMy0yMDE4 IFRvcmFkZXggQUcgPHN0ZWZhbi5hZ25lckB0b3JhZGV4LmNvbT4KKyAqLworCisjaW5jbHVkZSA8 bGludXgvY29tcGxldGlvbi5oPgorI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgorI2luY2x1ZGUgPGxp bnV4L2lpby9paW8uaD4KKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KKyNpbmNsdWRlIDxs aW51eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9tZmQvc3RtcGUuaD4KKyNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9wbGF0Zm9ybS5oPgorI2luY2x1ZGUg PGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgorCisjZGVmaW5lIFNUTVBFX1JFR19JTlRfU1RBCQkw eDBCCisjZGVmaW5lIFNUTVBFX1JFR19BRENfSU5UX0VOCQkweDBFCisjZGVmaW5lIFNUTVBFX1JF R19BRENfSU5UX1NUQQkJMHgwRgorCisjZGVmaW5lIFNUTVBFX1JFR19BRENfQ1RSTDEJCTB4MjAK KyNkZWZpbmUgU1RNUEVfUkVHX0FEQ19DVFJMMgkJMHgyMQorI2RlZmluZSBTVE1QRV9SRUdfQURD X0NBUFQJCTB4MjIKKyNkZWZpbmUgU1RNUEVfUkVHX0FEQ19EQVRBX0NIKGNoYW5uZWwpCSgweDMw ICsgMiAqIChjaGFubmVsKSkKKworI2RlZmluZSBTVE1QRV9SRUdfVEVNUF9DVFJMCQkweDYwCisj ZGVmaW5lIFNUTVBFX1RFTVBfQ1RSTF9FTkFCTEUJCUJJVCgwKQorI2RlZmluZSBTVE1QRV9URU1Q X0NUUkxfQUNRCQlCSVQoMSkKKyNkZWZpbmUgU1RNUEVfVEVNUF9DVFJMX1RIUkVTX0VOCUJJVCgz KQorI2RlZmluZSBTVE1QRV9TVEFSVF9PTkVfVEVNUF9DT05WCShTVE1QRV9URU1QX0NUUkxfRU5B QkxFIHwgXAorCQkJCQlTVE1QRV9URU1QX0NUUkxfQUNRIHwgXAorCQkJCQlTVE1QRV9URU1QX0NU UkxfVEhSRVNfRU4pCisjZGVmaW5lIFNUTVBFX1JFR19URU1QX0RBVEEJCTB4NjEKKyNkZWZpbmUg U1RNUEVfUkVHX1RFTVBfVEgJCTB4NjMKKyNkZWZpbmUgU1RNUEVfQURDX0xBU1RfTlIJCTcKKyNk ZWZpbmUgU1RNUEVfVEVNUF9DSEFOTkVMCQkoU1RNUEVfQURDX0xBU1RfTlIgKyAxKQorCisjZGVm aW5lIFNUTVBFX0FEQ19DSChjaGFubmVsKQkJKCgxIDw8IChjaGFubmVsKSkgJiAweGZmKQorCisj ZGVmaW5lIFNUTVBFX0FEQ19USU1FT1VUCQltc2Vjc190b19qaWZmaWVzKDEwMDApCisKK3N0cnVj dCBzdG1wZV9hZGMgeworCXN0cnVjdCBzdG1wZSAqc3RtcGU7CisJc3RydWN0IGNsayAqY2xrOwor CXN0cnVjdCBkZXZpY2UgKmRldjsKKworCS8qIFdlIGFyZSBhbGxvY2F0aW5nIHBsdXMgb25lIGZv ciB0aGUgdGVtcGVyYXR1cmUgY2hhbm5lbCAqLworCXN0cnVjdCBpaW9fY2hhbl9zcGVjIHN0bXBl X2FkY19paW9fY2hhbm5lbHNbU1RNUEVfQURDX0xBU1RfTlIgKyAyXTsKKworCXN0cnVjdCBjb21w bGV0aW9uIGNvbXBsZXRpb247CisKKwl1OCBjaGFubmVsOworCXUzMiB2YWx1ZTsKKwl1MzIgbm9y ZXF1ZXN0X21hc2s7Cit9OworCitzdGF0aWMgaW50IHN0bXBlX3JlYWRfcmF3KHN0cnVjdCBpaW9f ZGV2ICppbmRpb19kZXYsCisJCQkgIHN0cnVjdCBpaW9fY2hhbl9zcGVjIGNvbnN0ICpjaGFuLAor CQkJICBpbnQgKnZhbCwKKwkJCSAgaW50ICp2YWwyLAorCQkJICBsb25nIG1hc2spCit7CisJc3Ry dWN0IHN0bXBlX2FkYyAqaW5mbyA9IGlpb19wcml2KGluZGlvX2Rldik7CisJbG9uZyByZXQ7CisK Kwlzd2l0Y2ggKG1hc2spIHsKKwljYXNlIElJT19DSEFOX0lORk9fUkFXOgorCWNhc2UgSUlPX0NI QU5fSU5GT19QUk9DRVNTRUQ6CisKKwkJbXV0ZXhfbG9jaygmaW5kaW9fZGV2LT5tbG9jayk7CisK KwkJaW5mby0+Y2hhbm5lbCA9ICh1OCljaGFuLT5jaGFubmVsOworCisJCXN3aXRjaCAoY2hhbi0+ dHlwZSkgeworCQljYXNlIElJT19WT0xUQUdFOgorCQkJaWYgKGluZm8tPmNoYW5uZWwgPiBTVE1Q RV9BRENfTEFTVF9OUikgeworCQkJCW11dGV4X3VubG9jaygmaW5kaW9fZGV2LT5tbG9jayk7CisJ CQkJcmV0dXJuIC1FSU5WQUw7CisJCQl9CisKKwkJCXN0bXBlX3JlZ193cml0ZShpbmZvLT5zdG1w ZSwgU1RNUEVfUkVHX0FEQ19JTlRfRU4sCisJCQkJCVNUTVBFX0FEQ19DSChpbmZvLT5jaGFubmVs KSk7CisKKwkJCXN0bXBlX3JlZ193cml0ZShpbmZvLT5zdG1wZSwgU1RNUEVfUkVHX0FEQ19DQVBU LAorCQkJCQlTVE1QRV9BRENfQ0goaW5mby0+Y2hhbm5lbCkpOworCisJCQkqdmFsID0gaW5mby0+ dmFsdWU7CisJCQlicmVhazsKKworCQljYXNlIElJT19URU1QOgorCQkJaWYgKGluZm8tPmNoYW5u ZWwgIT0gU1RNUEVfVEVNUF9DSEFOTkVMKSB7CisJCQkJbXV0ZXhfdW5sb2NrKCZpbmRpb19kZXYt Pm1sb2NrKTsKKwkJCQlyZXR1cm4gLUVJTlZBTDsKKwkJCX0KKworCQkJc3RtcGVfcmVnX3dyaXRl KGluZm8tPnN0bXBlLCBTVE1QRV9SRUdfVEVNUF9DVFJMLAorCQkJCQlTVE1QRV9TVEFSVF9PTkVf VEVNUF9DT05WKTsKKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJbXV0ZXhfdW5sb2NrKCZpbmRp b19kZXYtPm1sb2NrKTsKKwkJCXJldHVybiAtRUlOVkFMOworCQl9CisKKwkJcmV0ID0gd2FpdF9m b3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlX3RpbWVvdXQKKwkJCSgmaW5mby0+Y29tcGxldGlv biwgU1RNUEVfQURDX1RJTUVPVVQpOworCisJCWlmIChyZXQgPD0gMCkgeworCQkJbXV0ZXhfdW5s b2NrKCZpbmRpb19kZXYtPm1sb2NrKTsKKwkJCWlmIChyZXQgPT0gMCkKKwkJCQlyZXR1cm4gLUVU SU1FRE9VVDsKKwkJCWVsc2UKKwkJCQlyZXR1cm4gcmV0OworCQl9CisKKwkJc3dpdGNoIChjaGFu LT50eXBlKSB7CisJCWNhc2UgSUlPX1ZPTFRBR0U6CisJCQkqdmFsID0gaW5mby0+dmFsdWU7CisJ CQlicmVhazsKKworCQljYXNlIElJT19URU1QOgorCQkJLyoKKwkJCSAqIGFic29sdXRlIHRlbXAg PSArVjMuMyAqIHZhbHVlIC83LjUxIFtLXQorCQkJICogc2NhbGUgdG8gW21pbGxpIMKwQ10KKwkJ CSAqLworCQkJKnZhbCA9ICgoNDQ5OTYwbCAqIGluZm8tPnZhbHVlKSAvIDEwMjRsKSAtIDI3MzE1 MDsKKwkJCWJyZWFrOworCQlkZWZhdWx0OgorCQkJYnJlYWs7CisJCX0KKworCQltdXRleF91bmxv Y2soJmluZGlvX2Rldi0+bWxvY2spOworCQlyZXR1cm4gSUlPX1ZBTF9JTlQ7CisKKwljYXNlIElJ T19DSEFOX0lORk9fU0NBTEU6CisJCSp2YWwgPSAzMzAwOworCQkqdmFsMiA9IGluZm8tPnN0bXBl LT5tb2RfMTJiID8gMTIgOiAxMDsKKwkJcmV0dXJuIElJT19WQUxfRlJBQ1RJT05BTF9MT0cyOwor CisJZGVmYXVsdDoKKwkJYnJlYWs7CisJfQorCisJcmV0dXJuIC1FSU5WQUw7Cit9CisKK3N0YXRp YyBpcnFyZXR1cm5fdCBzdG1wZV9hZGNfaXNyKGludCBpcnEsIHZvaWQgKmRldl9pZCkKK3sKKwlz dHJ1Y3Qgc3RtcGVfYWRjICppbmZvID0gKHN0cnVjdCBzdG1wZV9hZGMgKilkZXZfaWQ7CisJdTgg ZGF0YVsyXTsKKworCWlmIChpbmZvLT5jaGFubmVsID4gU1RNUEVfVEVNUF9DSEFOTkVMKQorCQly ZXR1cm4gSVJRX05PTkU7CisKKwlpZiAoaW5mby0+Y2hhbm5lbCA8PSBTVE1QRV9BRENfTEFTVF9O UikgeworCQlpbnQgaW50X3N0YTsKKworCQlpbnRfc3RhID0gc3RtcGVfcmVnX3JlYWQoaW5mby0+ c3RtcGUsIFNUTVBFX1JFR19BRENfSU5UX1NUQSk7CisKKwkJLyogSXMgdGhlIGludGVycnVwdCBy ZWxldmFudCAqLworCQlpZiAoIShpbnRfc3RhICYgU1RNUEVfQURDX0NIKGluZm8tPmNoYW5uZWwp KSkKKwkJCXJldHVybiBJUlFfTk9ORTsKKworCQkvKiBSZWFkIHZhbHVlICovCisJCXN0bXBlX2Js b2NrX3JlYWQoaW5mby0+c3RtcGUsCisJCQlTVE1QRV9SRUdfQURDX0RBVEFfQ0goaW5mby0+Y2hh bm5lbCksIDIsIGRhdGEpOworCisJCXN0bXBlX3JlZ193cml0ZShpbmZvLT5zdG1wZSwgU1RNUEVf UkVHX0FEQ19JTlRfU1RBLCBpbnRfc3RhKTsKKwl9IGVsc2UgaWYgKGluZm8tPmNoYW5uZWwgPT0g U1RNUEVfVEVNUF9DSEFOTkVMKSB7CisJCS8qIFJlYWQgdmFsdWUgKi8KKwkJc3RtcGVfYmxvY2tf cmVhZChpbmZvLT5zdG1wZSwgU1RNUEVfUkVHX1RFTVBfREFUQSwgMiwgZGF0YSk7CisJfQorCisJ aW5mby0+dmFsdWUgPSAoKHUzMilkYXRhWzBdIDw8IDgpICsgZGF0YVsxXTsKKwljb21wbGV0ZSgm aW5mby0+Y29tcGxldGlvbik7CisKKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cit9CisKK3N0YXRpYyBj b25zdCBzdHJ1Y3QgaWlvX2luZm8gc3RtcGVfYWRjX2lpb19pbmZvID0geworCS5yZWFkX3JhdyA9 ICZzdG1wZV9yZWFkX3JhdywKK307CisKK3N0YXRpYyB2b2lkIHN0bXBlX2FkY192b2x0YWdlX2No YW4oc3RydWN0IGlpb19jaGFuX3NwZWMgKmljcywgaW50IGNoYW4pCit7CisJaWNzLT50eXBlID0g SUlPX1ZPTFRBR0U7CisJaWNzLT5pbmZvX21hc2tfc2VwYXJhdGUgPSBCSVQoSUlPX0NIQU5fSU5G T19SQVcpOworCWljcy0+aW5mb19tYXNrX3NoYXJlZF9ieV90eXBlID0gQklUKElJT19DSEFOX0lO Rk9fU0NBTEUpOworCWljcy0+aW5kZXhlZCA9IDE7CisJaWNzLT5jaGFubmVsID0gY2hhbjsKK30K Kworc3RhdGljIHZvaWQgc3RtcGVfYWRjX3RlbXBfY2hhbihzdHJ1Y3QgaWlvX2NoYW5fc3BlYyAq aWNzLCBpbnQgY2hhbikKK3sKKwlpY3MtPnR5cGUgPSBJSU9fVEVNUDsKKwlpY3MtPmluZm9fbWFz a19zZXBhcmF0ZSA9IEJJVChJSU9fQ0hBTl9JTkZPX1BST0NFU1NFRCk7CisJaWNzLT5pbmRleGVk ID0gMTsKKwlpY3MtPmNoYW5uZWwgPSBjaGFuOworfQorCitzdGF0aWMgaW50IHN0bXBlX2FkY19p bml0X2h3KHN0cnVjdCBzdG1wZV9hZGMgKmFkYykKK3sKKwlzdHJ1Y3Qgc3RtcGUgKnN0bXBlID0g YWRjLT5zdG1wZTsKKworCS8qIHVzZSB0ZW1wIGlycSBmb3IgZWFjaCBjb252ZXJzaW9uIGNvbXBs ZXRpb24gKi8KKwlzdG1wZV9yZWdfd3JpdGUoc3RtcGUsIFNUTVBFX1JFR19URU1QX1RILCAwKTsK KwlzdG1wZV9yZWdfd3JpdGUoc3RtcGUsIFNUTVBFX1JFR19URU1QX1RIICsgMSwgMCk7CisKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgc3RtcGVfYWRjX2dldF9wbGF0Zm9ybV9pbmZvKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsCisJCQkJCXN0cnVjdCBzdG1wZV9hZGMgKmFkYykK K3sKKwlzdHJ1Y3Qgc3RtcGUgKnN0bXBlID0gZGV2X2dldF9kcnZkYXRhKHBkZXYtPmRldi5wYXJl bnQpOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBwZGV2LT5kZXYub2Zfbm9kZTsKKwl1MzIg dmFsOworCisJYWRjLT5zdG1wZSA9IHN0bXBlOworCisJaWYgKCFucCkgeworCQlkZXZfZXJyKCZw ZGV2LT5kZXYsICJubyBkZXZpY2UgdHJlZSBub2RlIGZvdW5kXG4iKTsKKwkJcmV0dXJuOworCX0K KworCWlmICghb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJzdCxub3JlcXVlc3QtbWFzayIsICZ2 YWwpKQorCQlhZGMtPm5vcmVxdWVzdF9tYXNrID0gdmFsOworfQorCitzdGF0aWMgaW50IHN0bXBl X2FkY19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCBpaW9f ZGV2ICppbmRpb19kZXYgPSBOVUxMOworCXN0cnVjdCBzdG1wZV9hZGMgKmluZm8gPSBOVUxMOwor CWludCBpcnFfdGVtcCwgaXJxX2FkYzsKKwlpbnQgbnVtX2NoYW4gPSAwOworCWludCBpID0gMDsK KwlpbnQgcmV0OworCisJaXJxX2FkYyA9IHBsYXRmb3JtX2dldF9pcnFfYnluYW1lKHBkZXYsICJT VE1QRV9BREMiKTsKKwlpZiAoaXJxX2FkYyA8IDApCisJCXJldHVybiBpcnFfYWRjOworCisJaW5k aW9fZGV2ID0gZGV2bV9paW9fZGV2aWNlX2FsbG9jKCZwZGV2LT5kZXYsIHNpemVvZihzdHJ1Y3Qg c3RtcGVfYWRjKSk7CisJaWYgKCFpbmRpb19kZXYpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAi ZmFpbGVkIGFsbG9jYXRpbmcgaWlvIGRldmljZVxuIik7CisJCXJldHVybiAtRU5PTUVNOworCX0K KworCWluZm8gPSBpaW9fcHJpdihpbmRpb19kZXYpOworCisJaW5pdF9jb21wbGV0aW9uKCZpbmZv LT5jb21wbGV0aW9uKTsKKwlyZXQgPSBkZXZtX3JlcXVlc3RfdGhyZWFkZWRfaXJxKCZwZGV2LT5k ZXYsIGlycV9hZGMsIE5VTEwsCisJCQkJCXN0bXBlX2FkY19pc3IsIElSUUZfT05FU0hPVCwKKwkJ CQkJInN0bXBlLWFkYyIsIGluZm8pOworCWlmIChyZXQgPCAwKSB7CisJCWRldl9lcnIoJnBkZXYt PmRldiwgImZhaWxlZCByZXF1ZXN0aW5nIGlycSwgaXJxID0gJWRcbiIsCisJCQkJaXJxX2FkYyk7 CisJCXJldHVybiByZXQ7CisJfQorCisJaXJxX3RlbXAgPSBwbGF0Zm9ybV9nZXRfaXJxX2J5bmFt ZShwZGV2LCAiU1RNUEVfVEVNUF9TRU5TIik7CisJaWYgKGlycV90ZW1wID49IDApIHsKKwkJcmV0 ID0gZGV2bV9yZXF1ZXN0X3RocmVhZGVkX2lycSgmcGRldi0+ZGV2LCBpcnFfdGVtcCwgTlVMTCwK KwkJCQkJCXN0bXBlX2FkY19pc3IsIElSUUZfT05FU0hPVCwKKwkJCQkJCSJzdG1wZS1hZGMiLCBp bmZvKTsKKwkJaWYgKHJldCA8IDApCisJCQlkZXZfd2FybigmcGRldi0+ZGV2LCAiZmFpbGVkIHJl cXVlc3RpbmcgaXJxIGZvciIKKwkJCQkgIiB0ZW1wIHNlbnNvciwgaXJxID0gJWRcbiIsIGlycV90 ZW1wKTsKKwl9CisKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBpbmRpb19kZXYpOworCisJ aW5kaW9fZGV2LT5uYW1lCQk9IGRldl9uYW1lKCZwZGV2LT5kZXYpOworCWluZGlvX2Rldi0+ZGV2 LnBhcmVudAk9ICZwZGV2LT5kZXY7CisJaW5kaW9fZGV2LT5pbmZvCQk9ICZzdG1wZV9hZGNfaWlv X2luZm87CisJaW5kaW9fZGV2LT5tb2Rlcwk9IElORElPX0RJUkVDVF9NT0RFOworCisJc3RtcGVf YWRjX2dldF9wbGF0Zm9ybV9pbmZvKHBkZXYsIGluZm8pOworCisJZm9yX2VhY2hfY2xlYXJfYml0 KGksICh1bnNpZ25lZCBsb25nICopICZpbmZvLT5ub3JlcXVlc3RfbWFzaywKKwkJCSAgIChTVE1Q RV9BRENfTEFTVF9OUiArIDEpKSB7CisJCXN0bXBlX2FkY192b2x0YWdlX2NoYW4oJmluZm8tPnN0 bXBlX2FkY19paW9fY2hhbm5lbHNbbnVtX2NoYW5dLCBpKTsKKwkJbnVtX2NoYW4rKzsKKwl9CisJ c3RtcGVfYWRjX3RlbXBfY2hhbigmaW5mby0+c3RtcGVfYWRjX2lpb19jaGFubmVsc1tudW1fY2hh bl0sIGkpOworCW51bV9jaGFuKys7CisJaW5kaW9fZGV2LT5jaGFubmVscyA9IGluZm8tPnN0bXBl X2FkY19paW9fY2hhbm5lbHM7CisJaW5kaW9fZGV2LT5udW1fY2hhbm5lbHMgPSBudW1fY2hhbjsK KworCXJldCA9IHN0bXBlX2FkY19pbml0X2h3KGluZm8pOworCWlmIChyZXQpCisJCXJldHVybiBy ZXQ7CisKKwlyZXQgPSBpaW9fZGV2aWNlX3JlZ2lzdGVyKGluZGlvX2Rldik7CisJaWYgKHJldCkK KwkJcmV0dXJuIHJldDsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IHN0bXBlX2FkY19y ZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgaWlvX2RldiAq aW5kaW9fZGV2ID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7CisJc3RydWN0IHN0bXBlX2Fk YyAqaW5mbyA9IGlpb19wcml2KGluZGlvX2Rldik7CisKKwlpaW9fZGV2aWNlX3VucmVnaXN0ZXIo aW5kaW9fZGV2KTsKKwlzdG1wZV9kaXNhYmxlKGluZm8tPnN0bXBlLCBTVE1QRV9CTE9DS19BREMp OworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19tYXliZV91bnVzZWQgc3RtcGVfYWRj X3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCit7CisJc3RydWN0IGlpb19kZXYgKmluZGlvX2Rl diA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOworCXN0cnVjdCBzdG1wZV9hZGMgKmluZm8gPSBpaW9f cHJpdihpbmRpb19kZXYpOworCisJc3RtcGVfYWRjX2luaXRfaHcoaW5mbyk7CisKKwlyZXR1cm4g MDsKK30KKworc3RhdGljIFNJTVBMRV9ERVZfUE1fT1BTKHN0bXBlX2FkY19wbV9vcHMsIE5VTEws IHN0bXBlX2FkY19yZXN1bWUpOworCitzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBzdG1w ZV9hZGNfZHJpdmVyID0geworCS5wcm9iZQkJPSBzdG1wZV9hZGNfcHJvYmUsCisJLnJlbW92ZQkJ PSBzdG1wZV9hZGNfcmVtb3ZlLAorCS5kcml2ZXIJCT0geworCQkubmFtZQk9ICJzdG1wZS1hZGMi LAorCQkucG0JPSAmc3RtcGVfYWRjX3BtX29wcywKKwl9LAorfTsKKworbW9kdWxlX3BsYXRmb3Jt X2RyaXZlcihzdG1wZV9hZGNfZHJpdmVyKTsKKworTU9EVUxFX0FVVEhPUigiU3RlZmFuIEFnbmVy IDxzdGVmYW4uYWduZXJAdG9yYWRleC5jb20+Iik7CitNT0RVTEVfREVTQ1JJUFRJT04oIlNUTVBF WFhYIEFEQyBkcml2ZXIiKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKK01PRFVMRV9BTElB UygicGxhdGZvcm06c3RtcGUtYWRjIik7CmRpZmYgLS1naXQgYS9kcml2ZXJzL2lucHV0L3RvdWNo c2NyZWVuL3N0bXBlLXRzLmMgYi9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVuL3N0bXBlLXRzLmMK aW5kZXggYzVkOTAwNjU4OGEyLi4zMWQxNTcwMzJmNGEgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaW5w dXQvdG91Y2hzY3JlZW4vc3RtcGUtdHMuYworKysgYi9kcml2ZXJzL2lucHV0L3RvdWNoc2NyZWVu L3N0bXBlLXRzLmMKQEAgLTMwLDggKzMwLDYgQEAKICAqIHdpdGggdG91Y2hzY3JlZW4gY29udHJv bGxlcgogICovCiAjZGVmaW5lIFNUTVBFX1JFR19JTlRfU1RBCQkweDBCCi0jZGVmaW5lIFNUTVBF X1JFR19BRENfQ1RSTDEJCTB4MjAKLSNkZWZpbmUgU1RNUEVfUkVHX0FEQ19DVFJMMgkJMHgyMQog I2RlZmluZSBTVE1QRV9SRUdfVFNDX0NUUkwJCTB4NDAKICNkZWZpbmUgU1RNUEVfUkVHX1RTQ19D RkcJCTB4NDEKICNkZWZpbmUgU1RNUEVfUkVHX0ZJRk9fVEgJCTB4NEEKQEAgLTg4LDEwICs4Niw2 IEBAIHN0cnVjdCBzdG1wZV90b3VjaCB7CiAJc3RydWN0IGlucHV0X2RldiAqaWRldjsKIAlzdHJ1 Y3QgZGVsYXllZF93b3JrIHdvcms7CiAJc3RydWN0IGRldmljZSAqZGV2OwotCXU4IHNhbXBsZV90 aW1lOwotCXU4IG1vZF8xMmI7Ci0JdTggcmVmX3NlbDsKLQl1OCBhZGNfZnJlcTsKIAl1OCBhdmVf Y3RybDsKIAl1OCB0b3VjaF9kZXRfZGVsYXk7CiAJdTggc2V0dGxpbmc7CkBAIC0xNzYsNyArMTcw LDcgQEAgc3RhdGljIGlycXJldHVybl90IHN0bXBlX3RzX2hhbmRsZXIoaW50IGlycSwgdm9pZCAq ZGF0YSkKIAlpbnB1dF9yZXBvcnRfa2V5KHRzLT5pZGV2LCBCVE5fVE9VQ0gsIDEpOwogCWlucHV0 X3N5bmModHMtPmlkZXYpOwogCi0gICAgICAgLyogZmx1c2ggdGhlIEZJRk8gYWZ0ZXIgd2UgaGF2 ZSByZWFkIG91dCBvdXIgdmFsdWVzLiAqLworCS8qIGZsdXNoIHRoZSBGSUZPIGFmdGVyIHdlIGhh dmUgcmVhZCBvdXQgb3VyIHZhbHVlcy4gKi8KIAlfX3N0bXBlX3Jlc2V0X2ZpZm8odHMtPnN0bXBl KTsKIAogCS8qIHJlZW5hYmxlIHRoZSB0c2MgKi8KQEAgLTE5Miw3ICsxODYsNyBAQCBzdGF0aWMg aXJxcmV0dXJuX3Qgc3RtcGVfdHNfaGFuZGxlcihpbnQgaXJxLCB2b2lkICpkYXRhKQogc3RhdGlj IGludCBzdG1wZV9pbml0X2h3KHN0cnVjdCBzdG1wZV90b3VjaCAqdHMpCiB7CiAJaW50IHJldDsK LQl1OCBhZGNfY3RybDEsIGFkY19jdHJsMV9tYXNrLCB0c2NfY2ZnLCB0c2NfY2ZnX21hc2s7CisJ dTggdHNjX2NmZywgdHNjX2NmZ19tYXNrOwogCXN0cnVjdCBzdG1wZSAqc3RtcGUgPSB0cy0+c3Rt cGU7CiAJc3RydWN0IGRldmljZSAqZGV2ID0gdHMtPmRldjsKIApAQCAtMjAyLDI1ICsxOTYsNiBA QCBzdGF0aWMgaW50IHN0bXBlX2luaXRfaHcoc3RydWN0IHN0bXBlX3RvdWNoICp0cykKIAkJcmV0 dXJuIHJldDsKIAl9CiAKLQlhZGNfY3RybDEgPSBTVE1QRV9TQU1QTEVfVElNRSh0cy0+c2FtcGxl X3RpbWUpIHwKLQkJICAgIFNUTVBFX01PRF8xMkIodHMtPm1vZF8xMmIpIHwgU1RNUEVfUkVGX1NF TCh0cy0+cmVmX3NlbCk7Ci0JYWRjX2N0cmwxX21hc2sgPSBTVE1QRV9TQU1QTEVfVElNRSgweGZm KSB8IFNUTVBFX01PRF8xMkIoMHhmZikgfAotCQkJIFNUTVBFX1JFRl9TRUwoMHhmZik7Ci0KLQly ZXQgPSBzdG1wZV9zZXRfYml0cyhzdG1wZSwgU1RNUEVfUkVHX0FEQ19DVFJMMSwKLQkJCWFkY19j dHJsMV9tYXNrLCBhZGNfY3RybDEpOwotCWlmIChyZXQpIHsKLQkJZGV2X2VycihkZXYsICJDb3Vs ZCBub3Qgc2V0dXAgQURDXG4iKTsKLQkJcmV0dXJuIHJldDsKLQl9Ci0KLQlyZXQgPSBzdG1wZV9z ZXRfYml0cyhzdG1wZSwgU1RNUEVfUkVHX0FEQ19DVFJMMiwKLQkJCVNUTVBFX0FEQ19GUkVRKDB4 ZmYpLCBTVE1QRV9BRENfRlJFUSh0cy0+YWRjX2ZyZXEpKTsKLQlpZiAocmV0KSB7Ci0JCWRldl9l cnIoZGV2LCAiQ291bGQgbm90IHNldHVwIEFEQ1xuIik7Ci0JCXJldHVybiByZXQ7Ci0JfQotCiAJ dHNjX2NmZyA9IFNUTVBFX0FWRV9DVFJMKHRzLT5hdmVfY3RybCkgfAogCQkgIFNUTVBFX0RFVF9E RUxBWSh0cy0+dG91Y2hfZGV0X2RlbGF5KSB8CiAJCSAgU1RNUEVfU0VUVExJTkcodHMtPnNldHRs aW5nKTsKQEAgLTIzNCwxNCArMjA5LDE0IEBAIHN0YXRpYyBpbnQgc3RtcGVfaW5pdF9odyhzdHJ1 Y3Qgc3RtcGVfdG91Y2ggKnRzKQogCX0KIAogCXJldCA9IHN0bXBlX3NldF9iaXRzKHN0bXBlLCBT VE1QRV9SRUdfVFNDX0ZSQUNUSU9OX1osCi0JCQlTVE1QRV9GUkFDVElPTl9aKDB4ZmYpLCBTVE1Q RV9GUkFDVElPTl9aKHRzLT5mcmFjdGlvbl96KSk7CisJCVNUTVBFX0ZSQUNUSU9OX1ooMHhmZiks IFNUTVBFX0ZSQUNUSU9OX1oodHMtPmZyYWN0aW9uX3opKTsKIAlpZiAocmV0KSB7CiAJCWRldl9l cnIoZGV2LCAiQ291bGQgbm90IGNvbmZpZyB0b3VjaFxuIik7CiAJCXJldHVybiByZXQ7CiAJfQog CiAJcmV0ID0gc3RtcGVfc2V0X2JpdHMoc3RtcGUsIFNUTVBFX1JFR19UU0NfSV9EUklWRSwKLQkJ CVNUTVBFX0lfRFJJVkUoMHhmZiksIFNUTVBFX0lfRFJJVkUodHMtPmlfZHJpdmUpKTsKKwkJU1RN UEVfSV9EUklWRSgweGZmKSwgU1RNUEVfSV9EUklWRSh0cy0+aV9kcml2ZSkpOwogCWlmIChyZXQp IHsKIAkJZGV2X2VycihkZXYsICJDb3VsZCBub3QgY29uZmlnIHRvdWNoXG4iKTsKIAkJcmV0dXJu IHJldDsKQEAgLTI1NSw3ICsyMzAsNyBAQCBzdGF0aWMgaW50IHN0bXBlX2luaXRfaHcoc3RydWN0 IHN0bXBlX3RvdWNoICp0cykKIAl9CiAKIAlyZXQgPSBzdG1wZV9zZXRfYml0cyhzdG1wZSwgU1RN UEVfUkVHX1RTQ19DVFJMLAotCQkJU1RNUEVfT1BfTU9ERSgweGZmKSwgU1RNUEVfT1BfTU9ERShP UF9NT0RfWFlaKSk7CisJCVNUTVBFX09QX01PREUoMHhmZiksIFNUTVBFX09QX01PREUoT1BfTU9E X1hZWikpOwogCWlmIChyZXQpIHsKIAkJZGV2X2VycihkZXYsICJDb3VsZCBub3Qgc2V0IG1vZGVc biIpOwogCQlyZXR1cm4gcmV0OwpAQCAtMjk0LDE0ICsyNjksNiBAQCBzdGF0aWMgdm9pZCBzdG1w ZV90c19nZXRfcGxhdGZvcm1faW5mbyhzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2LAogCXUz MiB2YWw7CiAKIAlpZiAobnApIHsKLQkJaWYgKCFvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInN0 LHNhbXBsZS10aW1lIiwgJnZhbCkpCi0JCQl0cy0+c2FtcGxlX3RpbWUgPSB2YWw7Ci0JCWlmICgh b2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJzdCxtb2QtMTJiIiwgJnZhbCkpCi0JCQl0cy0+bW9k XzEyYiA9IHZhbDsKLQkJaWYgKCFvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInN0LHJlZi1zZWwi LCAmdmFsKSkKLQkJCXRzLT5yZWZfc2VsID0gdmFsOwotCQlpZiAoIW9mX3Byb3BlcnR5X3JlYWRf dTMyKG5wLCAic3QsYWRjLWZyZXEiLCAmdmFsKSkKLQkJCXRzLT5hZGNfZnJlcSA9IHZhbDsKIAkJ aWYgKCFvZl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInN0LGF2ZS1jdHJsIiwgJnZhbCkpCiAJCQl0 cy0+YXZlX2N0cmwgPSB2YWw7CiAJCWlmICghb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJzdCx0 b3VjaC1kZXQtZGVsYXkiLCAmdmFsKSkKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWZkL0tjb25maWcg Yi9kcml2ZXJzL21mZC9LY29uZmlnCmluZGV4IDhjNWRmZGNlNDMyNi4uYmJhMTU5ZThlYWE0IDEw MDY0NAotLS0gYS9kcml2ZXJzL21mZC9LY29uZmlnCisrKyBiL2RyaXZlcnMvbWZkL0tjb25maWcK QEAgLTEyMDQsNyArMTIwNCw3IEBAIGNvbmZpZyBNRkRfU1RNUEUKIAogCSAgQ3VycmVudGx5IHN1 cHBvcnRlZCBkZXZpY2VzIGFyZToKIAotCQlTVE1QRTgxMTogR1BJTywgVG91Y2hzY3JlZW4KKwkJ U1RNUEU4MTE6IEdQSU8sIFRvdWNoc2NyZWVuLCBBREMKIAkJU1RNUEUxNjAxOiBHUElPLCBLZXlw YWQKIAkJU1RNUEUxODAxOiBHUElPLCBLZXlwYWQKIAkJU1RNUEUyNDAxOiBHUElPLCBLZXlwYWQK QEAgLTEyMTcsNiArMTIxNyw3IEBAIGNvbmZpZyBNRkRfU1RNUEUKIAkJR1BJTzogc3RtcGUtZ3Bp bwogCQlLZXlwYWQ6IHN0bXBlLWtleXBhZAogCQlUb3VjaHNjcmVlbjogc3RtcGUtdHMKKwkJQURD OiBzdG1wZS1hZGMKIAogbWVudSAiU1RNaWNyb2VsZWN0cm9uaWNzIFNUTVBFIEludGVyZmFjZSBE cml2ZXJzIgogZGVwZW5kcyBvbiBNRkRfU1RNUEUKZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWZkL3N0 bXBlLmMgYi9kcml2ZXJzL21mZC9zdG1wZS5jCmluZGV4IDU2NmNhY2E0ZWZkOC4uZWFiM2QzM2U0 MDkzIDEwMDY0NAotLS0gYS9kcml2ZXJzL21mZC9zdG1wZS5jCisrKyBiL2RyaXZlcnMvbWZkL3N0 bXBlLmMKQEAgLTIzLDYgKzIzLDkgQEAKICNpbmNsdWRlIDxsaW51eC9yZWd1bGF0b3IvY29uc3Vt ZXIuaD4KICNpbmNsdWRlICJzdG1wZS5oIgogCisjZGVmaW5lIFNUTVBFX1JFR19BRENfQ1RSTDEJ MHgyMAorI2RlZmluZSBTVE1QRV9SRUdfQURDX0NUUkwyCTB4MjEKKwogLyoqCiAgKiBzdHJ1Y3Qg c3RtcGVfcGxhdGZvcm1fZGF0YSAtIFNUTVBFIHBsYXRmb3JtIGRhdGEKICAqIEBpZDogZGV2aWNl IGlkIHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gbXVsdGlwbGUgU1RNUEVzIG9uIHRoZSBzYW1lIGJv YXJkCkBAIC00NjMsNiArNDY2LDI4IEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3QgbWZkX2NlbGwgc3Rt cGVfdHNfY2VsbCA9IHsKIAkubnVtX3Jlc291cmNlcwk9IEFSUkFZX1NJWkUoc3RtcGVfdHNfcmVz b3VyY2VzKSwKIH07CiAKKy8qCisgKiBBREMgKFNUTVBFODExKQorICovCisKK3N0YXRpYyBzdHJ1 Y3QgcmVzb3VyY2Ugc3RtcGVfYWRjX3Jlc291cmNlc1tdID0geworCXsKKwkJLm5hbWUJPSAiU1RN UEVfVEVNUF9TRU5TIiwKKwkJLmZsYWdzCT0gSU9SRVNPVVJDRV9JUlEsCisJfSwKKwl7CisJCS5u YW1lCT0gIlNUTVBFX0FEQyIsCisJCS5mbGFncwk9IElPUkVTT1VSQ0VfSVJRLAorCX0sCit9Owor CitzdGF0aWMgY29uc3Qgc3RydWN0IG1mZF9jZWxsIHN0bXBlX2FkY19jZWxsID0geworCS5uYW1l CQk9ICJzdG1wZS1hZGMiLAorCS5vZl9jb21wYXRpYmxlCT0gInN0LHN0bXBlLWFkYyIsCisJLnJl c291cmNlcwk9IHN0bXBlX2FkY19yZXNvdXJjZXMsCisJLm51bV9yZXNvdXJjZXMJPSBBUlJBWV9T SVpFKHN0bXBlX2FkY19yZXNvdXJjZXMpLAorfTsKKwogLyoKICAqIFNUTVBFODExIG9yIFNUTVBF NjEwCiAgKi8KQEAgLTQ5Nyw2ICs1MjIsMTEgQEAgc3RhdGljIHN0cnVjdCBzdG1wZV92YXJpYW50 X2Jsb2NrIHN0bXBlODExX2Jsb2Nrc1tdID0gewogCQkuaXJxCT0gU1RNUEU4MTFfSVJRX1RPVUNI X0RFVCwKIAkJLmJsb2NrCT0gU1RNUEVfQkxPQ0tfVE9VQ0hTQ1JFRU4sCiAJfSwKKwl7CisJCS5j ZWxsCT0gJnN0bXBlX2FkY19jZWxsLAorCQkuaXJxCT0gU1RNUEU4MTFfSVJRX1RFTVBfU0VOUywK KwkJLmJsb2NrCT0gU1RNUEVfQkxPQ0tfQURDLAorCX0sCiB9OwogCiBzdGF0aWMgaW50IHN0bXBl ODExX2VuYWJsZShzdHJ1Y3Qgc3RtcGUgKnN0bXBlLCB1bnNpZ25lZCBpbnQgYmxvY2tzLApAQCAt NTE3LDYgKzU0Nyw0NCBAQCBzdGF0aWMgaW50IHN0bXBlODExX2VuYWJsZShzdHJ1Y3Qgc3RtcGUg KnN0bXBlLCB1bnNpZ25lZCBpbnQgYmxvY2tzLAogCQkJCWVuYWJsZSA/IDAgOiBtYXNrKTsKIH0K IAorc3RhdGljIGludCBzdG1wZTgxMV9pbml0X2FkYyhzdHJ1Y3Qgc3RtcGUgKnN0bXBlKQorewor CWludCByZXQ7CisJdTggYWRjX2N0cmwxLCBhZGNfY3RybDFfbWFzazsKKworCXJldCA9IHN0bXBl X2VuYWJsZShzdG1wZSwgU1RNUEVfQkxPQ0tfQURDKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIo c3RtcGUtPmRldiwgIkNvdWxkIG5vdCBlbmFibGUgY2xvY2sgZm9yIEFEQ1xuIik7CisJCWdvdG8g ZXJyX2FkYzsKKwl9CisKKwlhZGNfY3RybDEgPSBTVE1QRV9TQU1QTEVfVElNRShzdG1wZS0+c2Ft cGxlX3RpbWUpIHwKKwkJICAgIFNUTVBFX01PRF8xMkIoc3RtcGUtPm1vZF8xMmIpIHwKKwkJICAg IFNUTVBFX1JFRl9TRUwoc3RtcGUtPnJlZl9zZWwpOworCWFkY19jdHJsMV9tYXNrID0gU1RNUEVf U0FNUExFX1RJTUUoMHhmZikgfCBTVE1QRV9NT0RfMTJCKDB4ZmYpIHwKKwkJCSBTVE1QRV9SRUZf U0VMKDB4ZmYpOworCisJcmV0ID0gc3RtcGVfc2V0X2JpdHMoc3RtcGUsIFNUTVBFX1JFR19BRENf Q1RSTDEsCisJCQlhZGNfY3RybDFfbWFzaywgYWRjX2N0cmwxKTsKKwlpZiAocmV0KSB7CisJCWRl dl9lcnIoc3RtcGUtPmRldiwgIkNvdWxkIG5vdCBzZXR1cCBBRENcbiIpOworCQlnb3RvIGVycl9h ZGM7CisJfQorCisJcmV0ID0gc3RtcGVfc2V0X2JpdHMoc3RtcGUsIFNUTVBFX1JFR19BRENfQ1RS TDIsCisJCQlTVE1QRV9BRENfRlJFUSgweGZmKSwgU1RNUEVfQURDX0ZSRVEoc3RtcGUtPmFkY19m cmVxKSk7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKHN0bXBlLT5kZXYsICJDb3VsZCBub3Qgc2V0 dXAgQURDXG4iKTsKKwkJZ290byBlcnJfYWRjOworCX0KKworCXJldHVybiAwOworZXJyX2FkYzoK KwlzdG1wZV9kaXNhYmxlKHN0bXBlLCBTVE1QRV9CTE9DS19BREMpOworCisJcmV0dXJuIHJldDsK K30KKwogc3RhdGljIGludCBzdG1wZTgxMV9nZXRfYWx0ZnVuYyhzdHJ1Y3Qgc3RtcGUgKnN0bXBl LCBlbnVtIHN0bXBlX2Jsb2NrIGJsb2NrKQogewogCS8qIDAgZm9yIHRvdWNoc2NyZWVuLCAxIGZv ciBHUElPICovCkBAIC0xMjM1LDYgKzEzMDMsMTIgQEAgc3RhdGljIGludCBzdG1wZV9jaGlwX2lu aXQoc3RydWN0IHN0bXBlICpzdG1wZSkKIAkJCXJldHVybiByZXQ7CiAJfQogCisJaWYgKGlkID09 IFNUTVBFNjEwIHx8IGlkID09IFNUTVBFODExKSB7CisJCXJldCA9IHN0bXBlODExX2luaXRfYWRj KHN0bXBlKTsKKwkJaWYgKHJldCkKKwkJCXJldHVybiByZXQ7CisJfQorCiAJcmV0dXJuIHN0bXBl X3JlZ193cml0ZShzdG1wZSwgc3RtcGUtPnJlZ3NbU1RNUEVfSURYX0lDUl9MU0JdLCBpY3IpOwog fQogCkBAIC0xMzI1LDYgKzEzOTksNyBAQCBpbnQgc3RtcGVfcHJvYmUoc3RydWN0IHN0bXBlX2Ns aWVudF9pbmZvICpjaSwgZW51bSBzdG1wZV9wYXJ0bnVtIHBhcnRudW0pCiAJc3RydWN0IGRldmlj ZV9ub2RlICpucCA9IGNpLT5kZXYtPm9mX25vZGU7CiAJc3RydWN0IHN0bXBlICpzdG1wZTsKIAlp bnQgcmV0OworCXUzMiB2YWw7CiAKIAlwZGF0YSA9IGRldm1fa3phbGxvYyhjaS0+ZGV2LCBzaXpl b2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7CiAJaWYgKCFwZGF0YSkKQEAgLTEzNDIsNiArMTQxNywx NSBAQCBpbnQgc3RtcGVfcHJvYmUoc3RydWN0IHN0bXBlX2NsaWVudF9pbmZvICpjaSwgZW51bSBz dG1wZV9wYXJ0bnVtIHBhcnRudW0pCiAJbXV0ZXhfaW5pdCgmc3RtcGUtPmlycV9sb2NrKTsKIAlt dXRleF9pbml0KCZzdG1wZS0+bG9jayk7CiAKKwlpZiAoIW9mX3Byb3BlcnR5X3JlYWRfdTMyKG5w LCAic3Qsc2FtcGxlLXRpbWUiLCAmdmFsKSkKKwkJc3RtcGUtPnNhbXBsZV90aW1lID0gdmFsOwor CWlmICghb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJzdCxtb2QtMTJiIiwgJnZhbCkpCisJCXN0 bXBlLT5tb2RfMTJiID0gdmFsOworCWlmICghb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJzdCxy ZWYtc2VsIiwgJnZhbCkpCisJCXN0bXBlLT5yZWZfc2VsID0gdmFsOworCWlmICghb2ZfcHJvcGVy dHlfcmVhZF91MzIobnAsICJzdCxhZGMtZnJlcSIsICZ2YWwpKQorCQlzdG1wZS0+YWRjX2ZyZXEg PSB2YWw7CisKIAlzdG1wZS0+ZGV2ID0gY2ktPmRldjsKIAlzdG1wZS0+Y2xpZW50ID0gY2ktPmNs aWVudDsKIAlzdG1wZS0+cGRhdGEgPSBwZGF0YTsKZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgv bWZkL3N0bXBlLmggYi9pbmNsdWRlL2xpbnV4L21mZC9zdG1wZS5oCmluZGV4IGMwMzUzZjY0MzFm OS4uNGUzZjZmZjYwNDA4IDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L21mZC9zdG1wZS5oCisr KyBiL2luY2x1ZGUvbGludXgvbWZkL3N0bXBlLmgKQEAgLTEzNCw2ICsxMzQsMTIgQEAgc3RydWN0 IHN0bXBlIHsKIAl1OCBpZXJbMl07CiAJdTggb2xkaWVyWzJdOwogCXN0cnVjdCBzdG1wZV9wbGF0 Zm9ybV9kYXRhICpwZGF0YTsKKworCS8qIEZvciBkZXZpY2VzIHRoYXQgdXNlIGFuIEFEQyAqLwor CXU4IHNhbXBsZV90aW1lOworCXU4IG1vZF8xMmI7CisJdTggcmVmX3NlbDsKKwl1OCBhZGNfZnJl cTsKIH07CiAKIGV4dGVybiBpbnQgc3RtcGVfcmVnX3dyaXRlKHN0cnVjdCBzdG1wZSAqc3RtcGUs IHU4IHJlZywgdTggZGF0YSk7Ci0tIAoyLjE5LjEKCgpfX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51 eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5v cmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Philippe Schenker To: jic23@kernel.org, marcel.ziswiler@toradex.com, stefan@agner.ch Cc: Max Krummenacher , Philippe Schenker , Siddartha Mohanadoss , Arnaud Pouliquen , linux-iio@vger.kernel.org, Geert Uytterhoeven , William Breathitt Gray , linux-stm32@st-md-mailman.stormreply.com, Randy Dunlap , Marcus Folkesson , Freeman Liu , linux-input@vger.kernel.org, Eugen Hristev , Maxime Coquelin , Peter Meerwald-Stadler , Lee Jones , Lars-Peter Clausen , Hartmut Knaack , linux-arm-kernel@lists.infradead.org, Alexandre Torgue , Mark Brown , linux-kernel@vger.kernel.org, Dmitry Torokhov Subject: [PATCH v2 2/4] iio: adc: add STMPE ADC driver using IIO framework Date: Mon, 19 Nov 2018 11:25:26 +0100 Message-Id: <20181119102528.2830-2-dev@pschenker.ch> In-Reply-To: <20181119102528.2830-1-dev@pschenker.ch> References: <20181119102528.2830-1-dev@pschenker.ch> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 List-ID: From: Stefan Agner This adds an ADC driver for the STMPE device using the industrial input/output interface. The driver supports raw reading of values. The driver depends on the MFD STMPE driver. If the touchscreen block is enabled too, only four of the 8 ADC channels are available. Signed-off-by: Stefan Agner Signed-off-by: Max Krummenacher Signed-off-by: Philippe Schenker --- Changes in v2: - Code formatting - Move code to setup ADC to MFD device, as it is used by both drivers adc and touchscreen - Removed unused includes - Defined the macro STMPE_START_ONE_TEMP_CONV with other macros. - Added new macro that defines the channel of the temperature sensor. Took new name for STMPE_MAX_ADC->STMPE_ADC_LAST_NR and used it throughout the code for better readability. - Added mutex_unlock where missing. drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/stmpe-adc.c | 340 +++++++++++++++++++++++++++ drivers/input/touchscreen/stmpe-ts.c | 43 +--- drivers/mfd/Kconfig | 3 +- drivers/mfd/stmpe.c | 84 +++++++ include/linux/mfd/stmpe.h | 6 + 7 files changed, 445 insertions(+), 39 deletions(-) create mode 100644 drivers/iio/adc/stmpe-adc.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a52fea8749a9..5d4c061d8296 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -734,6 +734,13 @@ config STM32_DFSDM_ADC This driver can also be built as a module. If so, the module will be called stm32-dfsdm-adc. +config STMPE_ADC + tristate "STMicroelectronics STMPE ADC driver" + depends on (OF || COMPILE_TEST || MFD_STMPE) + help + Say yes here to build support for ST Microelectronics STMPE + built-in ADC block (stmpe811). + config STX104 tristate "Apex Embedded Systems STX104 driver" depends on PC104 && X86 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a6e6a0b659e2..cba889c30bf9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o +obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c new file mode 100644 index 000000000000..151f1c8f827e --- /dev/null +++ b/drivers/iio/adc/stmpe-adc.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * STMicroelectronics STMPE811 IIO ADC Driver + * + * 4 channel, 10/12-bit ADC + * + * Copyright (C) 2013-2018 Toradex AG + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STMPE_REG_INT_STA 0x0B +#define STMPE_REG_ADC_INT_EN 0x0E +#define STMPE_REG_ADC_INT_STA 0x0F + +#define STMPE_REG_ADC_CTRL1 0x20 +#define STMPE_REG_ADC_CTRL2 0x21 +#define STMPE_REG_ADC_CAPT 0x22 +#define STMPE_REG_ADC_DATA_CH(channel) (0x30 + 2 * (channel)) + +#define STMPE_REG_TEMP_CTRL 0x60 +#define STMPE_TEMP_CTRL_ENABLE BIT(0) +#define STMPE_TEMP_CTRL_ACQ BIT(1) +#define STMPE_TEMP_CTRL_THRES_EN BIT(3) +#define STMPE_START_ONE_TEMP_CONV (STMPE_TEMP_CTRL_ENABLE | \ + STMPE_TEMP_CTRL_ACQ | \ + STMPE_TEMP_CTRL_THRES_EN) +#define STMPE_REG_TEMP_DATA 0x61 +#define STMPE_REG_TEMP_TH 0x63 +#define STMPE_ADC_LAST_NR 7 +#define STMPE_TEMP_CHANNEL (STMPE_ADC_LAST_NR + 1) + +#define STMPE_ADC_CH(channel) ((1 << (channel)) & 0xff) + +#define STMPE_ADC_TIMEOUT msecs_to_jiffies(1000) + +struct stmpe_adc { + struct stmpe *stmpe; + struct clk *clk; + struct device *dev; + + /* We are allocating plus one for the temperature channel */ + struct iio_chan_spec stmpe_adc_iio_channels[STMPE_ADC_LAST_NR + 2]; + + struct completion completion; + + u8 channel; + u32 value; + u32 norequest_mask; +}; + +static int stmpe_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct stmpe_adc *info = iio_priv(indio_dev); + long ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + + mutex_lock(&indio_dev->mlock); + + info->channel = (u8)chan->channel; + + switch (chan->type) { + case IIO_VOLTAGE: + if (info->channel > STMPE_ADC_LAST_NR) { + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN, + STMPE_ADC_CH(info->channel)); + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT, + STMPE_ADC_CH(info->channel)); + + *val = info->value; + break; + + case IIO_TEMP: + if (info->channel != STMPE_TEMP_CHANNEL) { + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL, + STMPE_START_ONE_TEMP_CONV); + break; + default: + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + ret = wait_for_completion_interruptible_timeout + (&info->completion, STMPE_ADC_TIMEOUT); + + if (ret <= 0) { + mutex_unlock(&indio_dev->mlock); + if (ret == 0) + return -ETIMEDOUT; + else + return ret; + } + + switch (chan->type) { + case IIO_VOLTAGE: + *val = info->value; + break; + + case IIO_TEMP: + /* + * absolute temp = +V3.3 * value /7.51 [K] + * scale to [milli °C] + */ + *val = ((449960l * info->value) / 1024l) - 273150; + break; + default: + break; + } + + mutex_unlock(&indio_dev->mlock); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 3300; + *val2 = info->stmpe->mod_12b ? 12 : 10; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + break; + } + + return -EINVAL; +} + +static irqreturn_t stmpe_adc_isr(int irq, void *dev_id) +{ + struct stmpe_adc *info = (struct stmpe_adc *)dev_id; + u8 data[2]; + + if (info->channel > STMPE_TEMP_CHANNEL) + return IRQ_NONE; + + if (info->channel <= STMPE_ADC_LAST_NR) { + int int_sta; + + int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA); + + /* Is the interrupt relevant */ + if (!(int_sta & STMPE_ADC_CH(info->channel))) + return IRQ_NONE; + + /* Read value */ + stmpe_block_read(info->stmpe, + STMPE_REG_ADC_DATA_CH(info->channel), 2, data); + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta); + } else if (info->channel == STMPE_TEMP_CHANNEL) { + /* Read value */ + stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2, data); + } + + info->value = ((u32)data[0] << 8) + data[1]; + complete(&info->completion); + + return IRQ_HANDLED; +} + +static const struct iio_info stmpe_adc_iio_info = { + .read_raw = &stmpe_read_raw, +}; + +static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan) +{ + ics->type = IIO_VOLTAGE; + ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + ics->indexed = 1; + ics->channel = chan; +} + +static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan) +{ + ics->type = IIO_TEMP; + ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED); + ics->indexed = 1; + ics->channel = chan; +} + +static int stmpe_adc_init_hw(struct stmpe_adc *adc) +{ + struct stmpe *stmpe = adc->stmpe; + + /* use temp irq for each conversion completion */ + stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0); + stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0); + + return 0; +} + +static void stmpe_adc_get_platform_info(struct platform_device *pdev, + struct stmpe_adc *adc) +{ + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); + struct device_node *np = pdev->dev.of_node; + u32 val; + + adc->stmpe = stmpe; + + if (!np) { + dev_err(&pdev->dev, "no device tree node found\n"); + return; + } + + if (!of_property_read_u32(np, "st,norequest-mask", &val)) + adc->norequest_mask = val; +} + +static int stmpe_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = NULL; + struct stmpe_adc *info = NULL; + int irq_temp, irq_adc; + int num_chan = 0; + int i = 0; + int ret; + + irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC"); + if (irq_adc < 0) + return irq_adc; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc)); + if (!indio_dev) { + dev_err(&pdev->dev, "failed allocating iio device\n"); + return -ENOMEM; + } + + info = iio_priv(indio_dev); + + init_completion(&info->completion); + ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL, + stmpe_adc_isr, IRQF_ONESHOT, + "stmpe-adc", info); + if (ret < 0) { + dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", + irq_adc); + return ret; + } + + irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS"); + if (irq_temp >= 0) { + ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL, + stmpe_adc_isr, IRQF_ONESHOT, + "stmpe-adc", info); + if (ret < 0) + dev_warn(&pdev->dev, "failed requesting irq for" + " temp sensor, irq = %d\n", irq_temp); + } + + platform_set_drvdata(pdev, indio_dev); + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &stmpe_adc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + stmpe_adc_get_platform_info(pdev, info); + + for_each_clear_bit(i, (unsigned long *) &info->norequest_mask, + (STMPE_ADC_LAST_NR + 1)) { + stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i); + num_chan++; + } + stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i); + num_chan++; + indio_dev->channels = info->stmpe_adc_iio_channels; + indio_dev->num_channels = num_chan; + + ret = stmpe_adc_init_hw(info); + if (ret) + return ret; + + ret = iio_device_register(indio_dev); + if (ret) + return ret; + + return 0; +} + +static int stmpe_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct stmpe_adc *info = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + stmpe_disable(info->stmpe, STMPE_BLOCK_ADC); + + return 0; +} + +static int __maybe_unused stmpe_adc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct stmpe_adc *info = iio_priv(indio_dev); + + stmpe_adc_init_hw(info); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume); + +static struct platform_driver stmpe_adc_driver = { + .probe = stmpe_adc_probe, + .remove = stmpe_adc_remove, + .driver = { + .name = "stmpe-adc", + .pm = &stmpe_adc_pm_ops, + }, +}; + +module_platform_driver(stmpe_adc_driver); + +MODULE_AUTHOR("Stefan Agner "); +MODULE_DESCRIPTION("STMPEXXX ADC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:stmpe-adc"); diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index c5d9006588a2..31d157032f4a 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -30,8 +30,6 @@ * with touchscreen controller */ #define STMPE_REG_INT_STA 0x0B -#define STMPE_REG_ADC_CTRL1 0x20 -#define STMPE_REG_ADC_CTRL2 0x21 #define STMPE_REG_TSC_CTRL 0x40 #define STMPE_REG_TSC_CFG 0x41 #define STMPE_REG_FIFO_TH 0x4A @@ -88,10 +86,6 @@ struct stmpe_touch { struct input_dev *idev; struct delayed_work work; struct device *dev; - u8 sample_time; - u8 mod_12b; - u8 ref_sel; - u8 adc_freq; u8 ave_ctrl; u8 touch_det_delay; u8 settling; @@ -176,7 +170,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) input_report_key(ts->idev, BTN_TOUCH, 1); input_sync(ts->idev); - /* flush the FIFO after we have read out our values. */ + /* flush the FIFO after we have read out our values. */ __stmpe_reset_fifo(ts->stmpe); /* reenable the tsc */ @@ -192,7 +186,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) static int stmpe_init_hw(struct stmpe_touch *ts) { int ret; - u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; + u8 tsc_cfg, tsc_cfg_mask; struct stmpe *stmpe = ts->stmpe; struct device *dev = ts->dev; @@ -202,25 +196,6 @@ static int stmpe_init_hw(struct stmpe_touch *ts) return ret; } - adc_ctrl1 = STMPE_SAMPLE_TIME(ts->sample_time) | - STMPE_MOD_12B(ts->mod_12b) | STMPE_REF_SEL(ts->ref_sel); - adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | - STMPE_REF_SEL(0xff); - - ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, - adc_ctrl1_mask, adc_ctrl1); - if (ret) { - dev_err(dev, "Could not setup ADC\n"); - return ret; - } - - ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, - STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(ts->adc_freq)); - if (ret) { - dev_err(dev, "Could not setup ADC\n"); - return ret; - } - tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) | STMPE_DET_DELAY(ts->touch_det_delay) | STMPE_SETTLING(ts->settling); @@ -234,14 +209,14 @@ static int stmpe_init_hw(struct stmpe_touch *ts) } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, - STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z)); + STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z)); if (ret) { dev_err(dev, "Could not config touch\n"); return ret; } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, - STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive)); + STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive)); if (ret) { dev_err(dev, "Could not config touch\n"); return ret; @@ -255,7 +230,7 @@ static int stmpe_init_hw(struct stmpe_touch *ts) } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, - STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ)); + STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ)); if (ret) { dev_err(dev, "Could not set mode\n"); return ret; @@ -294,14 +269,6 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev, u32 val; if (np) { - if (!of_property_read_u32(np, "st,sample-time", &val)) - ts->sample_time = val; - if (!of_property_read_u32(np, "st,mod-12b", &val)) - ts->mod_12b = val; - if (!of_property_read_u32(np, "st,ref-sel", &val)) - ts->ref_sel = val; - if (!of_property_read_u32(np, "st,adc-freq", &val)) - ts->adc_freq = val; if (!of_property_read_u32(np, "st,ave-ctrl", &val)) ts->ave_ctrl = val; if (!of_property_read_u32(np, "st,touch-det-delay", &val)) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8c5dfdce4326..bba159e8eaa4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1204,7 +1204,7 @@ config MFD_STMPE Currently supported devices are: - STMPE811: GPIO, Touchscreen + STMPE811: GPIO, Touchscreen, ADC STMPE1601: GPIO, Keypad STMPE1801: GPIO, Keypad STMPE2401: GPIO, Keypad @@ -1217,6 +1217,7 @@ config MFD_STMPE GPIO: stmpe-gpio Keypad: stmpe-keypad Touchscreen: stmpe-ts + ADC: stmpe-adc menu "STMicroelectronics STMPE Interface Drivers" depends on MFD_STMPE diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 566caca4efd8..eab3d33e4093 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -23,6 +23,9 @@ #include #include "stmpe.h" +#define STMPE_REG_ADC_CTRL1 0x20 +#define STMPE_REG_ADC_CTRL2 0x21 + /** * struct stmpe_platform_data - STMPE platform data * @id: device id to distinguish between multiple STMPEs on the same board @@ -463,6 +466,28 @@ static const struct mfd_cell stmpe_ts_cell = { .num_resources = ARRAY_SIZE(stmpe_ts_resources), }; +/* + * ADC (STMPE811) + */ + +static struct resource stmpe_adc_resources[] = { + { + .name = "STMPE_TEMP_SENS", + .flags = IORESOURCE_IRQ, + }, + { + .name = "STMPE_ADC", + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct mfd_cell stmpe_adc_cell = { + .name = "stmpe-adc", + .of_compatible = "st,stmpe-adc", + .resources = stmpe_adc_resources, + .num_resources = ARRAY_SIZE(stmpe_adc_resources), +}; + /* * STMPE811 or STMPE610 */ @@ -497,6 +522,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = { .irq = STMPE811_IRQ_TOUCH_DET, .block = STMPE_BLOCK_TOUCHSCREEN, }, + { + .cell = &stmpe_adc_cell, + .irq = STMPE811_IRQ_TEMP_SENS, + .block = STMPE_BLOCK_ADC, + }, }; static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, @@ -517,6 +547,44 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, enable ? 0 : mask); } +static int stmpe811_init_adc(struct stmpe *stmpe) +{ + int ret; + u8 adc_ctrl1, adc_ctrl1_mask; + + ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC); + if (ret) { + dev_err(stmpe->dev, "Could not enable clock for ADC\n"); + goto err_adc; + } + + adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) | + STMPE_MOD_12B(stmpe->mod_12b) | + STMPE_REF_SEL(stmpe->ref_sel); + adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | + STMPE_REF_SEL(0xff); + + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, + adc_ctrl1_mask, adc_ctrl1); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + goto err_adc; + } + + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, + STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq)); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + goto err_adc; + } + + return 0; +err_adc: + stmpe_disable(stmpe, STMPE_BLOCK_ADC); + + return ret; +} + static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) { /* 0 for touchscreen, 1 for GPIO */ @@ -1235,6 +1303,12 @@ static int stmpe_chip_init(struct stmpe *stmpe) return ret; } + if (id == STMPE610 || id == STMPE811) { + ret = stmpe811_init_adc(stmpe); + if (ret) + return ret; + } + return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); } @@ -1325,6 +1399,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; + u32 val; pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1342,6 +1417,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) mutex_init(&stmpe->irq_lock); mutex_init(&stmpe->lock); + if (!of_property_read_u32(np, "st,sample-time", &val)) + stmpe->sample_time = val; + if (!of_property_read_u32(np, "st,mod-12b", &val)) + stmpe->mod_12b = val; + if (!of_property_read_u32(np, "st,ref-sel", &val)) + stmpe->ref_sel = val; + if (!of_property_read_u32(np, "st,adc-freq", &val)) + stmpe->adc_freq = val; + stmpe->dev = ci->dev; stmpe->client = ci->client; stmpe->pdata = pdata; diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index c0353f6431f9..4e3f6ff60408 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -134,6 +134,12 @@ struct stmpe { u8 ier[2]; u8 oldier[2]; struct stmpe_platform_data *pdata; + + /* For devices that use an ADC */ + u8 sample_time; + u8 mod_12b; + u8 ref_sel; + u8 adc_freq; }; extern int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 data); -- 2.19.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: dev@pschenker.ch (Philippe Schenker) Date: Mon, 19 Nov 2018 11:25:26 +0100 Subject: [PATCH v2 2/4] iio: adc: add STMPE ADC driver using IIO framework In-Reply-To: <20181119102528.2830-1-dev@pschenker.ch> References: <20181119102528.2830-1-dev@pschenker.ch> Message-ID: <20181119102528.2830-2-dev@pschenker.ch> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: Stefan Agner This adds an ADC driver for the STMPE device using the industrial input/output interface. The driver supports raw reading of values. The driver depends on the MFD STMPE driver. If the touchscreen block is enabled too, only four of the 8 ADC channels are available. Signed-off-by: Stefan Agner Signed-off-by: Max Krummenacher Signed-off-by: Philippe Schenker --- Changes in v2: - Code formatting - Move code to setup ADC to MFD device, as it is used by both drivers adc and touchscreen - Removed unused includes - Defined the macro STMPE_START_ONE_TEMP_CONV with other macros. - Added new macro that defines the channel of the temperature sensor. Took new name for STMPE_MAX_ADC->STMPE_ADC_LAST_NR and used it throughout the code for better readability. - Added mutex_unlock where missing. drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/stmpe-adc.c | 340 +++++++++++++++++++++++++++ drivers/input/touchscreen/stmpe-ts.c | 43 +--- drivers/mfd/Kconfig | 3 +- drivers/mfd/stmpe.c | 84 +++++++ include/linux/mfd/stmpe.h | 6 + 7 files changed, 445 insertions(+), 39 deletions(-) create mode 100644 drivers/iio/adc/stmpe-adc.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a52fea8749a9..5d4c061d8296 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -734,6 +734,13 @@ config STM32_DFSDM_ADC This driver can also be built as a module. If so, the module will be called stm32-dfsdm-adc. +config STMPE_ADC + tristate "STMicroelectronics STMPE ADC driver" + depends on (OF || COMPILE_TEST || MFD_STMPE) + help + Say yes here to build support for ST Microelectronics STMPE + built-in ADC block (stmpe811). + config STX104 tristate "Apex Embedded Systems STX104 driver" depends on PC104 && X86 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a6e6a0b659e2..cba889c30bf9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o +obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c new file mode 100644 index 000000000000..151f1c8f827e --- /dev/null +++ b/drivers/iio/adc/stmpe-adc.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * STMicroelectronics STMPE811 IIO ADC Driver + * + * 4 channel, 10/12-bit ADC + * + * Copyright (C) 2013-2018 Toradex AG + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STMPE_REG_INT_STA 0x0B +#define STMPE_REG_ADC_INT_EN 0x0E +#define STMPE_REG_ADC_INT_STA 0x0F + +#define STMPE_REG_ADC_CTRL1 0x20 +#define STMPE_REG_ADC_CTRL2 0x21 +#define STMPE_REG_ADC_CAPT 0x22 +#define STMPE_REG_ADC_DATA_CH(channel) (0x30 + 2 * (channel)) + +#define STMPE_REG_TEMP_CTRL 0x60 +#define STMPE_TEMP_CTRL_ENABLE BIT(0) +#define STMPE_TEMP_CTRL_ACQ BIT(1) +#define STMPE_TEMP_CTRL_THRES_EN BIT(3) +#define STMPE_START_ONE_TEMP_CONV (STMPE_TEMP_CTRL_ENABLE | \ + STMPE_TEMP_CTRL_ACQ | \ + STMPE_TEMP_CTRL_THRES_EN) +#define STMPE_REG_TEMP_DATA 0x61 +#define STMPE_REG_TEMP_TH 0x63 +#define STMPE_ADC_LAST_NR 7 +#define STMPE_TEMP_CHANNEL (STMPE_ADC_LAST_NR + 1) + +#define STMPE_ADC_CH(channel) ((1 << (channel)) & 0xff) + +#define STMPE_ADC_TIMEOUT msecs_to_jiffies(1000) + +struct stmpe_adc { + struct stmpe *stmpe; + struct clk *clk; + struct device *dev; + + /* We are allocating plus one for the temperature channel */ + struct iio_chan_spec stmpe_adc_iio_channels[STMPE_ADC_LAST_NR + 2]; + + struct completion completion; + + u8 channel; + u32 value; + u32 norequest_mask; +}; + +static int stmpe_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct stmpe_adc *info = iio_priv(indio_dev); + long ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + + mutex_lock(&indio_dev->mlock); + + info->channel = (u8)chan->channel; + + switch (chan->type) { + case IIO_VOLTAGE: + if (info->channel > STMPE_ADC_LAST_NR) { + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN, + STMPE_ADC_CH(info->channel)); + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT, + STMPE_ADC_CH(info->channel)); + + *val = info->value; + break; + + case IIO_TEMP: + if (info->channel != STMPE_TEMP_CHANNEL) { + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL, + STMPE_START_ONE_TEMP_CONV); + break; + default: + mutex_unlock(&indio_dev->mlock); + return -EINVAL; + } + + ret = wait_for_completion_interruptible_timeout + (&info->completion, STMPE_ADC_TIMEOUT); + + if (ret <= 0) { + mutex_unlock(&indio_dev->mlock); + if (ret == 0) + return -ETIMEDOUT; + else + return ret; + } + + switch (chan->type) { + case IIO_VOLTAGE: + *val = info->value; + break; + + case IIO_TEMP: + /* + * absolute temp = +V3.3 * value /7.51 [K] + * scale to [milli ?C] + */ + *val = ((449960l * info->value) / 1024l) - 273150; + break; + default: + break; + } + + mutex_unlock(&indio_dev->mlock); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 3300; + *val2 = info->stmpe->mod_12b ? 12 : 10; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + break; + } + + return -EINVAL; +} + +static irqreturn_t stmpe_adc_isr(int irq, void *dev_id) +{ + struct stmpe_adc *info = (struct stmpe_adc *)dev_id; + u8 data[2]; + + if (info->channel > STMPE_TEMP_CHANNEL) + return IRQ_NONE; + + if (info->channel <= STMPE_ADC_LAST_NR) { + int int_sta; + + int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA); + + /* Is the interrupt relevant */ + if (!(int_sta & STMPE_ADC_CH(info->channel))) + return IRQ_NONE; + + /* Read value */ + stmpe_block_read(info->stmpe, + STMPE_REG_ADC_DATA_CH(info->channel), 2, data); + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta); + } else if (info->channel == STMPE_TEMP_CHANNEL) { + /* Read value */ + stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2, data); + } + + info->value = ((u32)data[0] << 8) + data[1]; + complete(&info->completion); + + return IRQ_HANDLED; +} + +static const struct iio_info stmpe_adc_iio_info = { + .read_raw = &stmpe_read_raw, +}; + +static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan) +{ + ics->type = IIO_VOLTAGE; + ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + ics->indexed = 1; + ics->channel = chan; +} + +static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan) +{ + ics->type = IIO_TEMP; + ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED); + ics->indexed = 1; + ics->channel = chan; +} + +static int stmpe_adc_init_hw(struct stmpe_adc *adc) +{ + struct stmpe *stmpe = adc->stmpe; + + /* use temp irq for each conversion completion */ + stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0); + stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0); + + return 0; +} + +static void stmpe_adc_get_platform_info(struct platform_device *pdev, + struct stmpe_adc *adc) +{ + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); + struct device_node *np = pdev->dev.of_node; + u32 val; + + adc->stmpe = stmpe; + + if (!np) { + dev_err(&pdev->dev, "no device tree node found\n"); + return; + } + + if (!of_property_read_u32(np, "st,norequest-mask", &val)) + adc->norequest_mask = val; +} + +static int stmpe_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = NULL; + struct stmpe_adc *info = NULL; + int irq_temp, irq_adc; + int num_chan = 0; + int i = 0; + int ret; + + irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC"); + if (irq_adc < 0) + return irq_adc; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc)); + if (!indio_dev) { + dev_err(&pdev->dev, "failed allocating iio device\n"); + return -ENOMEM; + } + + info = iio_priv(indio_dev); + + init_completion(&info->completion); + ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL, + stmpe_adc_isr, IRQF_ONESHOT, + "stmpe-adc", info); + if (ret < 0) { + dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", + irq_adc); + return ret; + } + + irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS"); + if (irq_temp >= 0) { + ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL, + stmpe_adc_isr, IRQF_ONESHOT, + "stmpe-adc", info); + if (ret < 0) + dev_warn(&pdev->dev, "failed requesting irq for" + " temp sensor, irq = %d\n", irq_temp); + } + + platform_set_drvdata(pdev, indio_dev); + + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &stmpe_adc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + stmpe_adc_get_platform_info(pdev, info); + + for_each_clear_bit(i, (unsigned long *) &info->norequest_mask, + (STMPE_ADC_LAST_NR + 1)) { + stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i); + num_chan++; + } + stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i); + num_chan++; + indio_dev->channels = info->stmpe_adc_iio_channels; + indio_dev->num_channels = num_chan; + + ret = stmpe_adc_init_hw(info); + if (ret) + return ret; + + ret = iio_device_register(indio_dev); + if (ret) + return ret; + + return 0; +} + +static int stmpe_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct stmpe_adc *info = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + stmpe_disable(info->stmpe, STMPE_BLOCK_ADC); + + return 0; +} + +static int __maybe_unused stmpe_adc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct stmpe_adc *info = iio_priv(indio_dev); + + stmpe_adc_init_hw(info); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume); + +static struct platform_driver stmpe_adc_driver = { + .probe = stmpe_adc_probe, + .remove = stmpe_adc_remove, + .driver = { + .name = "stmpe-adc", + .pm = &stmpe_adc_pm_ops, + }, +}; + +module_platform_driver(stmpe_adc_driver); + +MODULE_AUTHOR("Stefan Agner "); +MODULE_DESCRIPTION("STMPEXXX ADC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:stmpe-adc"); diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index c5d9006588a2..31d157032f4a 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -30,8 +30,6 @@ * with touchscreen controller */ #define STMPE_REG_INT_STA 0x0B -#define STMPE_REG_ADC_CTRL1 0x20 -#define STMPE_REG_ADC_CTRL2 0x21 #define STMPE_REG_TSC_CTRL 0x40 #define STMPE_REG_TSC_CFG 0x41 #define STMPE_REG_FIFO_TH 0x4A @@ -88,10 +86,6 @@ struct stmpe_touch { struct input_dev *idev; struct delayed_work work; struct device *dev; - u8 sample_time; - u8 mod_12b; - u8 ref_sel; - u8 adc_freq; u8 ave_ctrl; u8 touch_det_delay; u8 settling; @@ -176,7 +170,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) input_report_key(ts->idev, BTN_TOUCH, 1); input_sync(ts->idev); - /* flush the FIFO after we have read out our values. */ + /* flush the FIFO after we have read out our values. */ __stmpe_reset_fifo(ts->stmpe); /* reenable the tsc */ @@ -192,7 +186,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) static int stmpe_init_hw(struct stmpe_touch *ts) { int ret; - u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; + u8 tsc_cfg, tsc_cfg_mask; struct stmpe *stmpe = ts->stmpe; struct device *dev = ts->dev; @@ -202,25 +196,6 @@ static int stmpe_init_hw(struct stmpe_touch *ts) return ret; } - adc_ctrl1 = STMPE_SAMPLE_TIME(ts->sample_time) | - STMPE_MOD_12B(ts->mod_12b) | STMPE_REF_SEL(ts->ref_sel); - adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | - STMPE_REF_SEL(0xff); - - ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, - adc_ctrl1_mask, adc_ctrl1); - if (ret) { - dev_err(dev, "Could not setup ADC\n"); - return ret; - } - - ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, - STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(ts->adc_freq)); - if (ret) { - dev_err(dev, "Could not setup ADC\n"); - return ret; - } - tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) | STMPE_DET_DELAY(ts->touch_det_delay) | STMPE_SETTLING(ts->settling); @@ -234,14 +209,14 @@ static int stmpe_init_hw(struct stmpe_touch *ts) } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, - STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z)); + STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z)); if (ret) { dev_err(dev, "Could not config touch\n"); return ret; } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, - STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive)); + STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive)); if (ret) { dev_err(dev, "Could not config touch\n"); return ret; @@ -255,7 +230,7 @@ static int stmpe_init_hw(struct stmpe_touch *ts) } ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, - STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ)); + STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ)); if (ret) { dev_err(dev, "Could not set mode\n"); return ret; @@ -294,14 +269,6 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev, u32 val; if (np) { - if (!of_property_read_u32(np, "st,sample-time", &val)) - ts->sample_time = val; - if (!of_property_read_u32(np, "st,mod-12b", &val)) - ts->mod_12b = val; - if (!of_property_read_u32(np, "st,ref-sel", &val)) - ts->ref_sel = val; - if (!of_property_read_u32(np, "st,adc-freq", &val)) - ts->adc_freq = val; if (!of_property_read_u32(np, "st,ave-ctrl", &val)) ts->ave_ctrl = val; if (!of_property_read_u32(np, "st,touch-det-delay", &val)) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 8c5dfdce4326..bba159e8eaa4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1204,7 +1204,7 @@ config MFD_STMPE Currently supported devices are: - STMPE811: GPIO, Touchscreen + STMPE811: GPIO, Touchscreen, ADC STMPE1601: GPIO, Keypad STMPE1801: GPIO, Keypad STMPE2401: GPIO, Keypad @@ -1217,6 +1217,7 @@ config MFD_STMPE GPIO: stmpe-gpio Keypad: stmpe-keypad Touchscreen: stmpe-ts + ADC: stmpe-adc menu "STMicroelectronics STMPE Interface Drivers" depends on MFD_STMPE diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 566caca4efd8..eab3d33e4093 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -23,6 +23,9 @@ #include #include "stmpe.h" +#define STMPE_REG_ADC_CTRL1 0x20 +#define STMPE_REG_ADC_CTRL2 0x21 + /** * struct stmpe_platform_data - STMPE platform data * @id: device id to distinguish between multiple STMPEs on the same board @@ -463,6 +466,28 @@ static const struct mfd_cell stmpe_ts_cell = { .num_resources = ARRAY_SIZE(stmpe_ts_resources), }; +/* + * ADC (STMPE811) + */ + +static struct resource stmpe_adc_resources[] = { + { + .name = "STMPE_TEMP_SENS", + .flags = IORESOURCE_IRQ, + }, + { + .name = "STMPE_ADC", + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct mfd_cell stmpe_adc_cell = { + .name = "stmpe-adc", + .of_compatible = "st,stmpe-adc", + .resources = stmpe_adc_resources, + .num_resources = ARRAY_SIZE(stmpe_adc_resources), +}; + /* * STMPE811 or STMPE610 */ @@ -497,6 +522,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = { .irq = STMPE811_IRQ_TOUCH_DET, .block = STMPE_BLOCK_TOUCHSCREEN, }, + { + .cell = &stmpe_adc_cell, + .irq = STMPE811_IRQ_TEMP_SENS, + .block = STMPE_BLOCK_ADC, + }, }; static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, @@ -517,6 +547,44 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, enable ? 0 : mask); } +static int stmpe811_init_adc(struct stmpe *stmpe) +{ + int ret; + u8 adc_ctrl1, adc_ctrl1_mask; + + ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC); + if (ret) { + dev_err(stmpe->dev, "Could not enable clock for ADC\n"); + goto err_adc; + } + + adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) | + STMPE_MOD_12B(stmpe->mod_12b) | + STMPE_REF_SEL(stmpe->ref_sel); + adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | + STMPE_REF_SEL(0xff); + + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1, + adc_ctrl1_mask, adc_ctrl1); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + goto err_adc; + } + + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2, + STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq)); + if (ret) { + dev_err(stmpe->dev, "Could not setup ADC\n"); + goto err_adc; + } + + return 0; +err_adc: + stmpe_disable(stmpe, STMPE_BLOCK_ADC); + + return ret; +} + static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) { /* 0 for touchscreen, 1 for GPIO */ @@ -1235,6 +1303,12 @@ static int stmpe_chip_init(struct stmpe *stmpe) return ret; } + if (id == STMPE610 || id == STMPE811) { + ret = stmpe811_init_adc(stmpe); + if (ret) + return ret; + } + return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); } @@ -1325,6 +1399,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) struct device_node *np = ci->dev->of_node; struct stmpe *stmpe; int ret; + u32 val; pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1342,6 +1417,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) mutex_init(&stmpe->irq_lock); mutex_init(&stmpe->lock); + if (!of_property_read_u32(np, "st,sample-time", &val)) + stmpe->sample_time = val; + if (!of_property_read_u32(np, "st,mod-12b", &val)) + stmpe->mod_12b = val; + if (!of_property_read_u32(np, "st,ref-sel", &val)) + stmpe->ref_sel = val; + if (!of_property_read_u32(np, "st,adc-freq", &val)) + stmpe->adc_freq = val; + stmpe->dev = ci->dev; stmpe->client = ci->client; stmpe->pdata = pdata; diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index c0353f6431f9..4e3f6ff60408 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -134,6 +134,12 @@ struct stmpe { u8 ier[2]; u8 oldier[2]; struct stmpe_platform_data *pdata; + + /* For devices that use an ADC */ + u8 sample_time; + u8 mod_12b; + u8 ref_sel; + u8 adc_freq; }; extern int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 data); -- 2.19.1