From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MIME_BASE64_TEXT,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY, 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 D50ADC43603 for ; Wed, 11 Dec 2019 01:55:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8CF772073B for ; Wed, 11 Dec 2019 01:55:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="FVja0oTD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727619AbfLKBzU (ORCPT ); Tue, 10 Dec 2019 20:55:20 -0500 Received: from Mailgw01.mediatek.com ([1.203.163.78]:41400 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727420AbfLKBzS (ORCPT ); Tue, 10 Dec 2019 20:55:18 -0500 X-UUID: 5a8aad32c92f460690120230902284f1-20191211 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=tlAzxBX9ycjTVdOifSbzxIms9Y9rG2W7CX+ujLd3EZ0=; b=FVja0oTDok/fyCj9ngjsRMaXFTvkiLbGhbG5Jh3oq9dcNld1sp367U66ZzvhBa2gAXSNbuEbuej6svFD4gjA7F/Ef21IJY5noCVkF4k+XMg4DnydQY0hIPjuPonbMgROqOKpcxGgb8N2F2aMCPnu7YXedJmF1VyVNEj5YnU5h4U=; X-UUID: 5a8aad32c92f460690120230902284f1-20191211 Received: from mtkcas34.mediatek.inc [(172.27.4.253)] by mailgw01.mediatek.com (envelope-from ) (mailgw01.mediatek.com ESMTP with TLS) with ESMTP id 728132360; Wed, 11 Dec 2019 09:55:02 +0800 Received: from mtkcas09.mediatek.inc (172.21.101.178) by MTKMBS31N2.mediatek.inc (172.27.4.87) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Wed, 11 Dec 2019 09:54:04 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkcas09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Wed, 11 Dec 2019 09:54:55 +0800 From: To: Bin Liu , Rob Herring CC: Greg Kroah-Hartman , Mark Rutland , Matthias Brugger , Alan Stern , , , , , , , , , Min Guo , Yonglong Wu Subject: [PATCH v9 6/6] usb: musb: Add support for MediaTek musb controller Date: Wed, 11 Dec 2019 09:54:46 +0800 Message-ID: <20191211015446.11477-7-min.guo@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20191211015446.11477-1-min.guo@mediatek.com> References: <20191211015446.11477-1-min.guo@mediatek.com> MIME-Version: 1.0 Content-Type: text/plain X-TM-SNTS-SMTP: 0E7D616F6EE3390380FA359D3DFADACE75E7945CE4BA4AF9E345364A01F2D4402000:8 X-MTK: N Content-Transfer-Encoding: base64 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org RnJvbTogTWluIEd1byA8bWluLmd1b0BtZWRpYXRlay5jb20+DQoNClRoaXMgYWRkcyBzdXBwb3J0 IGZvciBNZWRpYVRlayBtdXNiIGNvbnRyb2xsZXIgaW4NCmhvc3QsIHBlcmlwaGVyYWwgYW5kIG90 ZyBtb2RlLg0KVGhlcmUgYXJlIHNvbWUgcXVpcmsgb2YgTWVkaWFUZWsgbXVzYiBjb250cm9sbGVy LCBzdWNoIGFzOg0KIC1XMUMgaW50ZXJydXB0IHN0YXR1cyByZWdpc3RlcnMNCiAtUHJpdmF0ZSBk YXRhIHRvZ2dsZSByZWdpc3RlcnMNCiAtTm8gZGVkaWNhdGVkIERNQSBpbnRlcnJ1cHQgbGluZQ0K DQpTaWduZWQtb2ZmLWJ5OiBNaW4gR3VvIDxtaW4uZ3VvQG1lZGlhdGVrLmNvbT4NClNpZ25lZC1v ZmYtYnk6IFlvbmdsb25nIFd1IDx5b25nbG9uZy53dUBtZWRpYXRlay5jb20+DQotLS0NCmNoYW5n ZXMgaW4gdjk6DQoxLiBubyBjaGFuZ2VzDQoNCmNoYW5nZXMgaW4gdjg6DQoxLiBubyBjaGFuZ2Vz DQoNCmNoYW5nZXMgaW4gdjc6DQoxLiBubyBjaGFuZ2VzDQoNCmNoYW5nZXMgaW4gdjY6DQoxLiBB ZGQgb2ZfcGxhdGZvcm1fcG9wdWxhdGUgaW4gcHJvYmUgdG8gcG9wdWxhdGUgY29ubmVjdG9yIHBs YXRmb3JtX2RldmljZXMNCiAgIGZyb20gZGV2aWNlIHRyZWUgZGF0YQ0KMi4gUmVwbGFjZSBleHRj b24gd2l0aCB1c2Igcm9sZSBzd2l0Y2ggbWVjaGFuaXNtIHRvIHN1cHBvcnQgZHVhbC1yb2xlIG1v ZGUNCjMuIFJlbW92ZSBzZXQgdmJ1cyBmdW5jdGlvbg0KDQpjaGFuZ2VzIGluIHY1Og0KMS4gUmVw bGFjZSBtdXNiX3JlYWRiKCkgd2l0aCBtdXNiX2NsZWFyYigpIHRvIGNsZWFyIGNvbW1vbi90eC9y eCBwZW5kaW5nIGludGVycnVwdHMNCjIuIE1ha2UgbXVzYl9jbGVhcmIvdygpIHJldHVybiB0aGUg dmFsdWUgb2YgbXVzYl9yZWFkYi93KCkNCjMuIEFkZCBkcml2ZXIgdG8gZ2V0IGNoaWxkIG5vZGVz IG9mIHVzYiBjb25uZWN0b3IgYW5kIGV4dGNvbiBkZXZpY2UNCg0KY2hhbmdlcyBpbiB2NDoNCjEu IG5vIGNoYW5nZXMNCg0KY2hhbmdlcyBpbiB2MzoNCnN1Z2dlc3RlZCBieSBCaW46DQoxLiBSZW1v dmUgJ3U4L3UxNiBkYXRhJyBwYXJhbWV0ZXIgaW4gY2xlYXJiL3coKSBob29rcw0KMi4gUmVwbGFj ZSBtdXNiX3JlYWRiL3coKSB3aXRoIG11c2JfY2xlYXJiL3coKSB0byBjbGVhciBpbnRlcnJ1cHRz IHN0YXR1cw0KDQpjaGFuZ2VzIGluIHYyOg0Kc3VnZ2VzdGVkIGJ5IEJpbjoNCjEuIEFkZCBzdW1t YXJpemUgb2YgTWVkaWFUZWsgbXVzYiBjb250cm9sbGVyIGRpZmZlcmVuY2VzIGluIHRoZSBjb21t aXQgbG9nDQoyLiBBZGQgInx8IENPTVBJTEVfVEVTVCIgaW4gS2NvbmZpZw0KMy4gTW92ZSBNZWRp YVRlaydzIHByaXZhdGUgdG9nZ2xlIHJlZ2lzdGVycyBmcm9tIG11c2JfcmVncy5oIHRvIG1lZGlh dGVrLmMNCjQuIFJlcGxhY2UgbXVzYl9yZWFkbCgpIHdpdGggbXVzYl9yZWFkdygpIHRvIHJlYWQg MTZiaXQgdG9nZ2xlIHJlZ2lzdGVyDQotLS0NCiBkcml2ZXJzL3VzYi9tdXNiL0tjb25maWcgICAg fCAgIDkgKy0NCiBkcml2ZXJzL3VzYi9tdXNiL01ha2VmaWxlICAgfCAgIDEgKw0KIGRyaXZlcnMv dXNiL211c2IvbWVkaWF0ZWsuYyB8IDU4MiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysNCiAzIGZpbGVzIGNoYW5nZWQsIDU5MSBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0p DQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdXNiL211c2IvbWVkaWF0ZWsuYw0KDQpkaWZm IC0tZ2l0IGEvZHJpdmVycy91c2IvbXVzYi9LY29uZmlnIGIvZHJpdmVycy91c2IvbXVzYi9LY29u ZmlnDQppbmRleCA1MmY4ZTJiNTdhZDUuLjc2N2M1ZGE5MDkxMiAxMDA2NDQNCi0tLSBhL2RyaXZl cnMvdXNiL211c2IvS2NvbmZpZw0KKysrIGIvZHJpdmVycy91c2IvbXVzYi9LY29uZmlnDQpAQCAt MTE2LDYgKzExNiwxMyBAQCBjb25maWcgVVNCX01VU0JfSlo0NzQwDQogCWRlcGVuZHMgb24gVVNC X01VU0JfR0FER0VUDQogCWRlcGVuZHMgb24gVVNCPW4gfHwgVVNCX09UR19CTEFDS0xJU1RfSFVC DQogDQorY29uZmlnIFVTQl9NVVNCX01FRElBVEVLDQorCXRyaXN0YXRlICJNZWRpYVRlayBwbGF0 Zm9ybXMiDQorCWRlcGVuZHMgb24gQVJDSF9NRURJQVRFSyB8fCBDT01QSUxFX1RFU1QNCisJZGVw ZW5kcyBvbiBOT1BfVVNCX1hDRUlWDQorCWRlcGVuZHMgb24gR0VORVJJQ19QSFkNCisJc2VsZWN0 IFVTQl9ST0xFX1NXSVRDSA0KKw0KIGNvbmZpZyBVU0JfTVVTQl9BTTMzNVhfQ0hJTEQNCiAJdHJp c3RhdGUNCiANCkBAIC0xNDIsNyArMTQ5LDcgQEAgY29uZmlnIFVTQl9VWDUwMF9ETUENCiANCiBj b25maWcgVVNCX0lOVkVOVFJBX0RNQQ0KIAlib29sICdJbnZlbnRyYScNCi0JZGVwZW5kcyBvbiBV U0JfTVVTQl9PTUFQMlBMVVMNCisJZGVwZW5kcyBvbiBVU0JfTVVTQl9PTUFQMlBMVVMgfHwgVVNC X01VU0JfTUVESUFURUsNCiAJaGVscA0KIAkgIEVuYWJsZSBETUEgdHJhbnNmZXJzIHVzaW5nIE1l bnRvcidzIGVuZ2luZS4NCiANCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9tdXNiL01ha2VmaWxl IGIvZHJpdmVycy91c2IvbXVzYi9NYWtlZmlsZQ0KaW5kZXggM2E4OGM3OWU2NTBjLi42M2Q4MmQw ZmFiNjcgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL3VzYi9tdXNiL01ha2VmaWxlDQorKysgYi9kcml2 ZXJzL3VzYi9tdXNiL01ha2VmaWxlDQpAQCAtMjQsNiArMjQsNyBAQCBvYmotJChDT05GSUdfVVNC X01VU0JfREE4WFgpCQkJKz0gZGE4eHgubw0KIG9iai0kKENPTkZJR19VU0JfTVVTQl9VWDUwMCkJ CQkrPSB1eDUwMC5vDQogb2JqLSQoQ09ORklHX1VTQl9NVVNCX0paNDc0MCkJCQkrPSBqejQ3NDAu bw0KIG9iai0kKENPTkZJR19VU0JfTVVTQl9TVU5YSSkJCQkrPSBzdW54aS5vDQorb2JqLSQoQ09O RklHX1VTQl9NVVNCX01FRElBVEVLKSAgICAgIAkJKz0gbWVkaWF0ZWsubw0KIA0KIA0KIG9iai0k KENPTkZJR19VU0JfTVVTQl9BTTMzNVhfQ0hJTEQpCQkrPSBtdXNiX2FtMzM1eC5vDQpkaWZmIC0t Z2l0IGEvZHJpdmVycy91c2IvbXVzYi9tZWRpYXRlay5jIGIvZHJpdmVycy91c2IvbXVzYi9tZWRp YXRlay5jDQpuZXcgZmlsZSBtb2RlIDEwMDY0NA0KaW5kZXggMDAwMDAwMDAwMDAwLi4zZGY4ZDdl ZjA4NDcNCi0tLSAvZGV2L251bGwNCisrKyBiL2RyaXZlcnMvdXNiL211c2IvbWVkaWF0ZWsuYw0K QEAgLTAsMCArMSw1ODIgQEANCisvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMA0K Ky8qDQorICogQ29weXJpZ2h0IChDKSAyMDE5IE1lZGlhVGVrIEluYy4NCisgKg0KKyAqIEF1dGhv cjoNCisgKiAgTWluIEd1byA8bWluLmd1b0BtZWRpYXRlay5jb20+DQorICogIFlvbmdsb25nIFd1 IDx5b25nbG9uZy53dUBtZWRpYXRlay5jb20+DQorICovDQorDQorI2luY2x1ZGUgPGxpbnV4L2Ns ay5oPg0KKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPg0KKyNpbmNsdWRlIDxsaW51eC9t b2R1bGUuaD4NCisjaW5jbHVkZSA8bGludXgvb2ZfcGxhdGZvcm0uaD4NCisjaW5jbHVkZSA8bGlu dXgvcGxhdGZvcm1fZGV2aWNlLmg+DQorI2luY2x1ZGUgPGxpbnV4L3VzYi9yb2xlLmg+DQorI2lu Y2x1ZGUgPGxpbnV4L3VzYi91c2JfcGh5X2dlbmVyaWMuaD4NCisjaW5jbHVkZSAibXVzYl9jb3Jl LmgiDQorI2luY2x1ZGUgIm11c2JfZG1hLmgiDQorDQorI2RlZmluZSBVU0JfTDFJTlRTCTB4MDBh MA0KKyNkZWZpbmUgVVNCX0wxSU5UTQkweDAwYTQNCisjZGVmaW5lIE1US19NVVNCX1RYRlVOQ0FE RFIJMHgwNDgwDQorDQorLyogTWVkaWFUZWsgY29udHJvbGxlciB0b2dnbGUgZW5hYmxlIGFuZCBz dGF0dXMgcmVnICovDQorI2RlZmluZSBNVVNCX1JYVE9HCQkweDgwDQorI2RlZmluZSBNVVNCX1JY VE9HRU4JCTB4ODINCisjZGVmaW5lIE1VU0JfVFhUT0cJCTB4ODQNCisjZGVmaW5lIE1VU0JfVFhU T0dFTgkJMHg4Ng0KKyNkZWZpbmUgTVRLX1RPR0dMRV9FTgkJR0VOTUFTSygxNSwgMCkNCisNCisj ZGVmaW5lIFRYX0lOVF9TVEFUVVMJCUJJVCgwKQ0KKyNkZWZpbmUgUlhfSU5UX1NUQVRVUwkJQklU KDEpDQorI2RlZmluZSBVU0JDT01fSU5UX1NUQVRVUwkJQklUKDIpDQorI2RlZmluZSBETUFfSU5U X1NUQVRVUwkJQklUKDMpDQorDQorI2RlZmluZSBETUFfSU5UUl9TVEFUVVNfTVNLCQlHRU5NQVNL KDcsIDApDQorI2RlZmluZSBETUFfSU5UUl9VTk1BU0tfU0VUX01TSwlHRU5NQVNLKDMxLCAyNCkN CisNCitzdHJ1Y3QgbXRrX2dsdWUgew0KKwlzdHJ1Y3QgZGV2aWNlICpkZXY7DQorCXN0cnVjdCBt dXNiICptdXNiOw0KKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICptdXNiX3BkZXY7DQorCXN0cnVj dCBwbGF0Zm9ybV9kZXZpY2UgKnVzYl9waHk7DQorCXN0cnVjdCBwaHkgKnBoeTsNCisJc3RydWN0 IHVzYl9waHkgKnhjZWl2Ow0KKwllbnVtIHBoeV9tb2RlIHBoeV9tb2RlOw0KKwlzdHJ1Y3QgY2xr ICptYWluOw0KKwlzdHJ1Y3QgY2xrICptY3U7DQorCXN0cnVjdCBjbGsgKnVuaXZwbGw7DQorCWVu dW0gdXNiX3JvbGUgcm9sZTsNCisJc3RydWN0IHVzYl9yb2xlX3N3aXRjaCAqcm9sZV9zdzsNCit9 Ow0KKw0KK3N0YXRpYyBpbnQgbXRrX211c2JfY2xrc19nZXQoc3RydWN0IG10a19nbHVlICpnbHVl KQ0KK3sNCisJc3RydWN0IGRldmljZSAqZGV2ID0gZ2x1ZS0+ZGV2Ow0KKw0KKwlnbHVlLT5tYWlu ID0gZGV2bV9jbGtfZ2V0KGRldiwgIm1haW4iKTsNCisJaWYgKElTX0VSUihnbHVlLT5tYWluKSkg ew0KKwkJZGV2X2VycihkZXYsICJmYWlsIHRvIGdldCBtYWluIGNsb2NrXG4iKTsNCisJCXJldHVy biBQVFJfRVJSKGdsdWUtPm1haW4pOw0KKwl9DQorDQorCWdsdWUtPm1jdSA9IGRldm1fY2xrX2dl dChkZXYsICJtY3UiKTsNCisJaWYgKElTX0VSUihnbHVlLT5tY3UpKSB7DQorCQlkZXZfZXJyKGRl diwgImZhaWwgdG8gZ2V0IG1jdSBjbG9ja1xuIik7DQorCQlyZXR1cm4gUFRSX0VSUihnbHVlLT5t Y3UpOw0KKwl9DQorDQorCWdsdWUtPnVuaXZwbGwgPSBkZXZtX2Nsa19nZXQoZGV2LCAidW5pdnBs bCIpOw0KKwlpZiAoSVNfRVJSKGdsdWUtPnVuaXZwbGwpKSB7DQorCQlkZXZfZXJyKGRldiwgImZh aWwgdG8gZ2V0IHVuaXZwbGwgY2xvY2tcbiIpOw0KKwkJcmV0dXJuIFBUUl9FUlIoZ2x1ZS0+dW5p dnBsbCk7DQorCX0NCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRpYyBpbnQgbXRrX211c2Jf Y2xrc19lbmFibGUoc3RydWN0IG10a19nbHVlICpnbHVlKQ0KK3sNCisJaW50IHJldDsNCisNCisJ cmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGdsdWUtPm1haW4pOw0KKwlpZiAocmV0KSB7DQorCQlk ZXZfZXJyKGdsdWUtPmRldiwgImZhaWxlZCB0byBlbmFibGUgbWFpbiBjbG9ja1xuIik7DQorCQln b3RvIGVycl9tYWluX2NsazsNCisJfQ0KKw0KKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoZ2x1 ZS0+bWN1KTsNCisJaWYgKHJldCkgew0KKwkJZGV2X2VycihnbHVlLT5kZXYsICJmYWlsZWQgdG8g ZW5hYmxlIG1jdSBjbG9ja1xuIik7DQorCQlnb3RvIGVycl9tY3VfY2xrOw0KKwl9DQorDQorCXJl dCA9IGNsa19wcmVwYXJlX2VuYWJsZShnbHVlLT51bml2cGxsKTsNCisJaWYgKHJldCkgew0KKwkJ ZGV2X2VycihnbHVlLT5kZXYsICJmYWlsZWQgdG8gZW5hYmxlIHVuaXZwbGwgY2xvY2tcbiIpOw0K KwkJZ290byBlcnJfdW5pdnBsbF9jbGs7DQorCX0NCisNCisJcmV0dXJuIDA7DQorDQorZXJyX3Vu aXZwbGxfY2xrOg0KKwljbGtfZGlzYWJsZV91bnByZXBhcmUoZ2x1ZS0+bWN1KTsNCitlcnJfbWN1 X2NsazoNCisJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGdsdWUtPm1haW4pOw0KK2Vycl9tYWluX2Ns azoNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIHZvaWQgbXRrX211c2JfY2xrc19kaXNh YmxlKHN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSkNCit7DQorCWNsa19kaXNhYmxlX3VucHJlcGFyZShn bHVlLT51bml2cGxsKTsNCisJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGdsdWUtPm1jdSk7DQorCWNs a19kaXNhYmxlX3VucHJlcGFyZShnbHVlLT5tYWluKTsNCit9DQorDQorc3RhdGljIGludCBtdXNi X3VzYl9yb2xlX3N4X3NldChzdHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gdXNiX3JvbGUgcm9sZSkN Cit7DQorCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOw0KKwlz dHJ1Y3QgbXVzYiAqbXVzYiA9IGdsdWUtPm11c2I7DQorCXU4IGRldmN0bCA9IHJlYWRiKG11c2It Pm1yZWdzICsgTVVTQl9ERVZDVEwpOw0KKwllbnVtIHVzYl9yb2xlIG5ld19yb2xlOw0KKw0KKwlp ZiAocm9sZSA9PSBnbHVlLT5yb2xlKQ0KKwkJcmV0dXJuIDA7DQorDQorCXN3aXRjaCAocm9sZSkg ew0KKwljYXNlIFVTQl9ST0xFX0hPU1Q6DQorCQltdXNiLT54Y2Vpdi0+b3RnLT5zdGF0ZSA9IE9U R19TVEFURV9BX1dBSVRfVlJJU0U7DQorCQlnbHVlLT5waHlfbW9kZSA9IFBIWV9NT0RFX1VTQl9I T1NUOw0KKwkJbmV3X3JvbGUgPSBVU0JfUk9MRV9IT1NUOw0KKwkJaWYgKGdsdWUtPnJvbGUgPT0g VVNCX1JPTEVfTk9ORSkNCisJCQlwaHlfcG93ZXJfb24oZ2x1ZS0+cGh5KTsNCisNCisJCWRldmN0 bCB8PSBNVVNCX0RFVkNUTF9TRVNTSU9OOw0KKwkJbXVzYl93cml0ZWIobXVzYi0+bXJlZ3MsIE1V U0JfREVWQ1RMLCBkZXZjdGwpOw0KKwkJTVVTQl9IU1RfTU9ERShtdXNiKTsNCisJCWJyZWFrOw0K KwljYXNlIFVTQl9ST0xFX0RFVklDRToNCisJCW11c2ItPnhjZWl2LT5vdGctPnN0YXRlID0gT1RH X1NUQVRFX0JfSURMRTsNCisJCWdsdWUtPnBoeV9tb2RlID0gUEhZX01PREVfVVNCX0RFVklDRTsN CisJCW5ld19yb2xlID0gVVNCX1JPTEVfREVWSUNFOw0KKwkJZGV2Y3RsICY9IH5NVVNCX0RFVkNU TF9TRVNTSU9OOw0KKwkJbXVzYl93cml0ZWIobXVzYi0+bXJlZ3MsIE1VU0JfREVWQ1RMLCBkZXZj dGwpOw0KKwkJaWYgKGdsdWUtPnJvbGUgPT0gVVNCX1JPTEVfTk9ORSkNCisJCQlwaHlfcG93ZXJf b24oZ2x1ZS0+cGh5KTsNCisNCisJCU1VU0JfREVWX01PREUobXVzYik7DQorCQlicmVhazsNCisJ Y2FzZSBVU0JfUk9MRV9OT05FOg0KKwkJZ2x1ZS0+cGh5X21vZGUgPSBQSFlfTU9ERV9VU0JfT1RH Ow0KKwkJbmV3X3JvbGUgPSBVU0JfUk9MRV9OT05FOw0KKwkJZGV2Y3RsICY9IH5NVVNCX0RFVkNU TF9TRVNTSU9OOw0KKwkJbXVzYl93cml0ZWIobXVzYi0+bXJlZ3MsIE1VU0JfREVWQ1RMLCBkZXZj dGwpOw0KKwkJaWYgKGdsdWUtPnJvbGUgIT0gVVNCX1JPTEVfTk9ORSkNCisJCQlwaHlfcG93ZXJf b2ZmKGdsdWUtPnBoeSk7DQorDQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJCWRldl9lcnIoZ2x1 ZS0+ZGV2LCAiSW52YWxpZCBTdGF0ZVxuIik7DQorCQlyZXR1cm4gLUVJTlZBTDsNCisJfQ0KKw0K KwlnbHVlLT5yb2xlID0gbmV3X3JvbGU7DQorCXBoeV9zZXRfbW9kZShnbHVlLT5waHksIGdsdWUt PnBoeV9tb2RlKTsNCisNCisJcmV0dXJuIDA7DQorfQ0KKw0KK3N0YXRpYyBlbnVtIHVzYl9yb2xl IG11c2JfdXNiX3JvbGVfc3hfZ2V0KHN0cnVjdCBkZXZpY2UgKmRldikNCit7DQorCXN0cnVjdCBt dGtfZ2x1ZSAqZ2x1ZSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOw0KKw0KKwlyZXR1cm4gZ2x1ZS0+ cm9sZTsNCit9DQorDQorc3RhdGljIGludCBtdGtfb3RnX3N3aXRjaF9pbml0KHN0cnVjdCBtdGtf Z2x1ZSAqZ2x1ZSkNCit7DQorCXN0cnVjdCB1c2Jfcm9sZV9zd2l0Y2hfZGVzYyByb2xlX3N4X2Rl c2MgPSB7IDAgfTsNCisNCisJcm9sZV9zeF9kZXNjLnNldCA9IG11c2JfdXNiX3JvbGVfc3hfc2V0 Ow0KKwlyb2xlX3N4X2Rlc2MuZ2V0ID0gbXVzYl91c2Jfcm9sZV9zeF9nZXQ7DQorCXJvbGVfc3hf ZGVzYy5md25vZGUgPSBkZXZfZndub2RlKGdsdWUtPmRldik7DQorCWdsdWUtPnJvbGVfc3cgPSB1 c2Jfcm9sZV9zd2l0Y2hfcmVnaXN0ZXIoZ2x1ZS0+ZGV2LCAmcm9sZV9zeF9kZXNjKTsNCisNCisJ cmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhnbHVlLT5yb2xlX3N3KTsNCit9DQorDQorc3RhdGljIHZv aWQgbXRrX290Z19zd2l0Y2hfZXhpdChzdHJ1Y3QgbXRrX2dsdWUgKmdsdWUpDQorew0KKwlyZXR1 cm4gdXNiX3JvbGVfc3dpdGNoX3VucmVnaXN0ZXIoZ2x1ZS0+cm9sZV9zdyk7DQorfQ0KKw0KK3N0 YXRpYyBpcnFyZXR1cm5fdCBnZW5lcmljX2ludGVycnVwdChpbnQgaXJxLCB2b2lkICpfX2hjaSkN Cit7DQorCXVuc2lnbmVkIGxvbmcgZmxhZ3M7DQorCWlycXJldHVybl90IHJldHZhbCA9IElSUV9O T05FOw0KKwlzdHJ1Y3QgbXVzYiAqbXVzYiA9IF9faGNpOw0KKw0KKwlzcGluX2xvY2tfaXJxc2F2 ZSgmbXVzYi0+bG9jaywgZmxhZ3MpOw0KKwltdXNiLT5pbnRfdXNiID0gbXVzYl9jbGVhcmIobXVz Yi0+bXJlZ3MsIE1VU0JfSU5UUlVTQik7DQorCW11c2ItPmludF9yeCA9IG11c2JfY2xlYXJ3KG11 c2ItPm1yZWdzLCBNVVNCX0lOVFJSWCk7DQorCW11c2ItPmludF90eCA9IG11c2JfY2xlYXJ3KG11 c2ItPm1yZWdzLCBNVVNCX0lOVFJUWCk7DQorDQorCWlmIChtdXNiLT5pbnRfdXNiIHx8IG11c2It PmludF90eCB8fCBtdXNiLT5pbnRfcngpDQorCQlyZXR2YWwgPSBtdXNiX2ludGVycnVwdChtdXNi KTsNCisNCisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmbXVzYi0+bG9jaywgZmxhZ3MpOw0KKw0K KwlyZXR1cm4gcmV0dmFsOw0KK30NCisNCitzdGF0aWMgaXJxcmV0dXJuX3QgbXRrX211c2JfaW50 ZXJydXB0KGludCBpcnEsIHZvaWQgKmRldl9pZCkNCit7DQorCWlycXJldHVybl90IHJldHZhbCA9 IElSUV9OT05FOw0KKwlzdHJ1Y3QgbXVzYiAqbXVzYiA9IChzdHJ1Y3QgbXVzYiAqKWRldl9pZDsN CisJdTMyIGwxX2ludHM7DQorDQorCWwxX2ludHMgPSBtdXNiX3JlYWRsKG11c2ItPm1yZWdzLCBV U0JfTDFJTlRTKSAmDQorCQkJbXVzYl9yZWFkbChtdXNiLT5tcmVncywgVVNCX0wxSU5UTSk7DQor DQorCWlmIChsMV9pbnRzICYgKFRYX0lOVF9TVEFUVVMgfCBSWF9JTlRfU1RBVFVTIHwgVVNCQ09N X0lOVF9TVEFUVVMpKQ0KKwkJcmV0dmFsID0gZ2VuZXJpY19pbnRlcnJ1cHQoaXJxLCBtdXNiKTsN CisNCisjaWYgZGVmaW5lZChDT05GSUdfVVNCX0lOVkVOVFJBX0RNQSkNCisJaWYgKGwxX2ludHMg JiBETUFfSU5UX1NUQVRVUykNCisJCXJldHZhbCA9IGRtYV9jb250cm9sbGVyX2lycShpcnEsIG11 c2ItPmRtYV9jb250cm9sbGVyKTsNCisjZW5kaWYNCisJcmV0dXJuIHJldHZhbDsNCit9DQorDQor c3RhdGljIHUzMiBtdGtfbXVzYl9idXNjdGxfb2Zmc2V0KHU4IGVwbnVtLCB1MTYgb2Zmc2V0KQ0K K3sNCisJcmV0dXJuIE1US19NVVNCX1RYRlVOQ0FERFIgKyBvZmZzZXQgKyA4ICogZXBudW07DQor fQ0KKw0KK3N0YXRpYyB1OCBtdGtfbXVzYl9jbGVhcmIodm9pZCBfX2lvbWVtICphZGRyLCB1bnNp Z25lZCBpbnQgb2Zmc2V0KQ0KK3sNCisJdTggZGF0YTsNCisNCisJLyogVzFDICovDQorCWRhdGEg PSBtdXNiX3JlYWRiKGFkZHIsIG9mZnNldCk7DQorCW11c2Jfd3JpdGViKGFkZHIsIG9mZnNldCwg ZGF0YSk7DQorCXJldHVybiBkYXRhOw0KK30NCisNCitzdGF0aWMgdTE2IG10a19tdXNiX2NsZWFy dyh2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIGludCBvZmZzZXQpDQorew0KKwl1MTYgZGF0 YTsNCisNCisJLyogVzFDICovDQorCWRhdGEgPSBtdXNiX3JlYWR3KGFkZHIsIG9mZnNldCk7DQor CW11c2Jfd3JpdGV3KGFkZHIsIG9mZnNldCwgZGF0YSk7DQorCXJldHVybiBkYXRhOw0KK30NCisN CitzdGF0aWMgaW50IG10a19tdXNiX3NldF9tb2RlKHN0cnVjdCBtdXNiICptdXNiLCB1OCBtb2Rl KQ0KK3sNCisJc3RydWN0IGRldmljZSAqZGV2ID0gbXVzYi0+Y29udHJvbGxlcjsNCisJc3RydWN0 IG10a19nbHVlICpnbHVlID0gZGV2X2dldF9kcnZkYXRhKGRldi0+cGFyZW50KTsNCisJZW51bSBw aHlfbW9kZSBuZXdfbW9kZTsNCisJZW51bSB1c2Jfcm9sZSBuZXdfcm9sZTsNCisNCisJc3dpdGNo IChtb2RlKSB7DQorCWNhc2UgTVVTQl9IT1NUOg0KKwkJbmV3X21vZGUgPSBQSFlfTU9ERV9VU0Jf SE9TVDsNCisJCW5ld19yb2xlID0gVVNCX1JPTEVfSE9TVDsNCisJCWJyZWFrOw0KKwljYXNlIE1V U0JfUEVSSVBIRVJBTDoNCisJCW5ld19tb2RlID0gUEhZX01PREVfVVNCX0RFVklDRTsNCisJCW5l d19yb2xlID0gVVNCX1JPTEVfREVWSUNFOw0KKwkJYnJlYWs7DQorCWNhc2UgTVVTQl9PVEc6DQor CQluZXdfbW9kZSA9IFBIWV9NT0RFX1VTQl9PVEc7DQorCQluZXdfcm9sZSA9IFVTQl9ST0xFX05P TkU7DQorCQlicmVhazsNCisJZGVmYXVsdDoNCisJCWRldl9lcnIoZ2x1ZS0+ZGV2LCAiSW52YWxp ZCBtb2RlIHJlcXVlc3RcbiIpOw0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJaWYgKGds dWUtPnBoeV9tb2RlID09IG5ld19tb2RlKQ0KKwkJcmV0dXJuIDA7DQorDQorCWlmIChtdXNiLT5w b3J0X21vZGUgIT0gTVVTQl9PVEcpIHsNCisJCWRldl9lcnIoZ2x1ZS0+ZGV2LCAiRG9lcyBub3Qg c3VwcG9ydCBjaGFuZ2luZyBtb2Rlc1xuIik7DQorCQlyZXR1cm4gLUVJTlZBTDsNCisJfQ0KKw0K KwlnbHVlLT5yb2xlID0gbmV3X3JvbGU7DQorCW11c2JfdXNiX3JvbGVfc3hfc2V0KGRldiwgZ2x1 ZS0+cm9sZSk7DQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgaW50IG10a19tdXNiX2luaXQo c3RydWN0IG11c2IgKm11c2IpDQorew0KKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBtdXNiLT5jb250 cm9sbGVyOw0KKwlzdHJ1Y3QgbXRrX2dsdWUgKmdsdWUgPSBkZXZfZ2V0X2RydmRhdGEoZGV2LT5w YXJlbnQpOw0KKwlpbnQgcmV0Ow0KKw0KKwlnbHVlLT5tdXNiID0gbXVzYjsNCisJbXVzYi0+cGh5 ID0gZ2x1ZS0+cGh5Ow0KKwltdXNiLT54Y2VpdiA9IGdsdWUtPnhjZWl2Ow0KKwltdXNiLT5pc19o b3N0ID0gZmFsc2U7DQorCW11c2ItPmlzciA9IG10a19tdXNiX2ludGVycnVwdDsNCisNCisJLyog U2V0IFRYL1JYIHRvZ2dsZSBlbmFibGUgKi8NCisJbXVzYl93cml0ZXcobXVzYi0+bXJlZ3MsIE1V U0JfVFhUT0dFTiwgTVRLX1RPR0dMRV9FTik7DQorCW11c2Jfd3JpdGV3KG11c2ItPm1yZWdzLCBN VVNCX1JYVE9HRU4sIE1US19UT0dHTEVfRU4pOw0KKw0KKwlpZiAobXVzYi0+cG9ydF9tb2RlID09 IE1VU0JfT1RHKSB7DQorCQlyZXQgPSBtdGtfb3RnX3N3aXRjaF9pbml0KGdsdWUpOw0KKwkJaWYg KHJldCkNCisJCQlyZXR1cm4gcmV0Ow0KKwl9DQorDQorCXJldCA9IHBoeV9pbml0KGdsdWUtPnBo eSk7DQorCWlmIChyZXQpDQorCQlnb3RvIGVycl9waHlfaW5pdDsNCisNCisJcmV0ID0gcGh5X3Bv d2VyX29uKGdsdWUtPnBoeSk7DQorCWlmIChyZXQpDQorCQlnb3RvIGVycl9waHlfcG93ZXJfb247 DQorDQorCXBoeV9zZXRfbW9kZShnbHVlLT5waHksIGdsdWUtPnBoeV9tb2RlKTsNCisNCisjaWYg ZGVmaW5lZChDT05GSUdfVVNCX0lOVkVOVFJBX0RNQSkNCisJbXVzYl93cml0ZWwobXVzYi0+bXJl Z3MsIE1VU0JfSFNETUFfSU5UUiwNCisJCSAgICBETUFfSU5UUl9TVEFUVVNfTVNLIHwgRE1BX0lO VFJfVU5NQVNLX1NFVF9NU0spOw0KKyNlbmRpZg0KKwltdXNiX3dyaXRlbChtdXNiLT5tcmVncywg VVNCX0wxSU5UTSwgVFhfSU5UX1NUQVRVUyB8IFJYX0lOVF9TVEFUVVMgfA0KKwkJICAgIFVTQkNP TV9JTlRfU1RBVFVTIHwgRE1BX0lOVF9TVEFUVVMpOw0KKwlyZXR1cm4gMDsNCisNCitlcnJfcGh5 X3Bvd2VyX29uOg0KKwlwaHlfZXhpdChnbHVlLT5waHkpOw0KK2Vycl9waHlfaW5pdDoNCisJbXRr X290Z19zd2l0Y2hfZXhpdChnbHVlKTsNCisJcmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIHUx NiBtdGtfbXVzYl9nZXRfdG9nZ2xlKHN0cnVjdCBtdXNiX3FoICpxaCwgaW50IGlzX291dCkNCit7 DQorCXN0cnVjdCBtdXNiICptdXNiID0gcWgtPmh3X2VwLT5tdXNiOw0KKwl1OCBlcG51bSA9IHFo LT5od19lcC0+ZXBudW07DQorCXUxNiB0b2dnbGU7DQorDQorCXRvZ2dsZSA9IG11c2JfcmVhZHco bXVzYi0+bXJlZ3MsIGlzX291dCA/IE1VU0JfVFhUT0cgOiBNVVNCX1JYVE9HKTsNCisJcmV0dXJu IHRvZ2dsZSAmICgxIDw8IGVwbnVtKTsNCit9DQorDQorc3RhdGljIHUxNiBtdGtfbXVzYl9zZXRf dG9nZ2xlKHN0cnVjdCBtdXNiX3FoICpxaCwgaW50IGlzX291dCwgc3RydWN0IHVyYiAqdXJiKQ0K K3sNCisJc3RydWN0IG11c2IgKm11c2IgPSBxaC0+aHdfZXAtPm11c2I7DQorCXU4IGVwbnVtID0g cWgtPmh3X2VwLT5lcG51bTsNCisJdTE2IHZhbHVlLCB0b2dnbGU7DQorDQorCXRvZ2dsZSA9IHVz Yl9nZXR0b2dnbGUodXJiLT5kZXYsIHFoLT5lcG51bSwgaXNfb3V0KTsNCisNCisJaWYgKGlzX291 dCkgew0KKwkJdmFsdWUgPSBtdXNiX3JlYWR3KG11c2ItPm1yZWdzLCBNVVNCX1RYVE9HKTsNCisJ CXZhbHVlIHw9IHRvZ2dsZSA8PCBlcG51bTsNCisJCW11c2Jfd3JpdGV3KG11c2ItPm1yZWdzLCBN VVNCX1RYVE9HLCB2YWx1ZSk7DQorCX0gZWxzZSB7DQorCQl2YWx1ZSA9IG11c2JfcmVhZHcobXVz Yi0+bXJlZ3MsIE1VU0JfUlhUT0cpOw0KKwkJdmFsdWUgfD0gdG9nZ2xlIDw8IGVwbnVtOw0KKwkJ bXVzYl93cml0ZXcobXVzYi0+bXJlZ3MsIE1VU0JfUlhUT0csIHZhbHVlKTsNCisJfQ0KKw0KKwly ZXR1cm4gMDsNCit9DQorDQorc3RhdGljIGludCBtdGtfbXVzYl9leGl0KHN0cnVjdCBtdXNiICpt dXNiKQ0KK3sNCisJc3RydWN0IGRldmljZSAqZGV2ID0gbXVzYi0+Y29udHJvbGxlcjsNCisJc3Ry dWN0IG10a19nbHVlICpnbHVlID0gZGV2X2dldF9kcnZkYXRhKGRldi0+cGFyZW50KTsNCisNCisJ bXRrX290Z19zd2l0Y2hfZXhpdChnbHVlKTsNCisJcGh5X3Bvd2VyX29mZihnbHVlLT5waHkpOw0K KwlwaHlfZXhpdChnbHVlLT5waHkpOw0KKwltdGtfbXVzYl9jbGtzX2Rpc2FibGUoZ2x1ZSk7DQor DQorCXBtX3J1bnRpbWVfcHV0X3N5bmMoZGV2KTsNCisJcG1fcnVudGltZV9kaXNhYmxlKGRldik7 DQorCXJldHVybiAwOw0KK30NCisNCitzdGF0aWMgY29uc3Qgc3RydWN0IG11c2JfcGxhdGZvcm1f b3BzIG10a19tdXNiX29wcyA9IHsNCisJLnF1aXJrcyA9IE1VU0JfRE1BX0lOVkVOVFJBLA0KKwku aW5pdCA9IG10a19tdXNiX2luaXQsDQorCS5nZXRfdG9nZ2xlID0gbXRrX211c2JfZ2V0X3RvZ2ds ZSwNCisJLnNldF90b2dnbGUgPSBtdGtfbXVzYl9zZXRfdG9nZ2xlLA0KKwkuZXhpdCA9IG10a19t dXNiX2V4aXQsDQorI2lmZGVmIENPTkZJR19VU0JfSU5WRU5UUkFfRE1BDQorCS5kbWFfaW5pdCA9 IG11c2Joc19kbWFfY29udHJvbGxlcl9jcmVhdGVfbm9pcnEsDQorCS5kbWFfZXhpdCA9IG11c2Jo c19kbWFfY29udHJvbGxlcl9kZXN0cm95LA0KKyNlbmRpZg0KKwkuY2xlYXJiID0gbXRrX211c2Jf Y2xlYXJiLA0KKwkuY2xlYXJ3ID0gbXRrX211c2JfY2xlYXJ3LA0KKwkuYnVzY3RsX29mZnNldCA9 IG10a19tdXNiX2J1c2N0bF9vZmZzZXQsDQorCS5zZXRfbW9kZSA9IG10a19tdXNiX3NldF9tb2Rl LA0KK307DQorDQorI2RlZmluZSBNVEtfTVVTQl9NQVhfRVBfTlVNCTgNCisjZGVmaW5lIE1US19N VVNCX1JBTV9CSVRTCTExDQorDQorc3RhdGljIHN0cnVjdCBtdXNiX2ZpZm9fY2ZnIG10a19tdXNi X21vZGVfY2ZnW10gPSB7DQorCXsgLmh3X2VwX251bSA9IDEsIC5zdHlsZSA9IEZJRk9fVFgsIC5t YXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDEsIC5zdHlsZSA9IEZJRk9fUlgs IC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDIsIC5zdHlsZSA9IEZJRk9f VFgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDIsIC5zdHlsZSA9IEZJ Rk9fUlgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDMsIC5zdHlsZSA9 IEZJRk9fVFgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDMsIC5zdHls ZSA9IEZJRk9fUlgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDQsIC5z dHlsZSA9IEZJRk9fVFgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9IDQs IC5zdHlsZSA9IEZJRk9fUlgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251bSA9 IDUsIC5zdHlsZSA9IEZJRk9fVFgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2VwX251 bSA9IDUsIC5zdHlsZSA9IEZJRk9fUlgsIC5tYXhwYWNrZXQgPSA1MTIsIH0sDQorCXsgLmh3X2Vw X251bSA9IDYsIC5zdHlsZSA9IEZJRk9fVFgsIC5tYXhwYWNrZXQgPSAxMDI0LCB9LA0KKwl7IC5o d19lcF9udW0gPSA2LCAuc3R5bGUgPSBGSUZPX1JYLCAubWF4cGFja2V0ID0gMTAyNCwgfSwNCisJ eyAuaHdfZXBfbnVtID0gNywgLnN0eWxlID0gRklGT19UWCwgLm1heHBhY2tldCA9IDUxMiwgfSwN CisJeyAuaHdfZXBfbnVtID0gNywgLnN0eWxlID0gRklGT19SWCwgLm1heHBhY2tldCA9IDY0LCB9 LA0KK307DQorDQorc3RhdGljIGNvbnN0IHN0cnVjdCBtdXNiX2hkcmNfY29uZmlnIG10a19tdXNi X2hkcmNfY29uZmlnID0gew0KKwkuZmlmb19jZmcgPSBtdGtfbXVzYl9tb2RlX2NmZywNCisJLmZp Zm9fY2ZnX3NpemUgPSBBUlJBWV9TSVpFKG10a19tdXNiX21vZGVfY2ZnKSwNCisJLm11bHRpcG9p bnQgPSB0cnVlLA0KKwkuZHluX2ZpZm8gPSB0cnVlLA0KKwkubnVtX2VwcyA9IE1US19NVVNCX01B WF9FUF9OVU0sDQorCS5yYW1fYml0cyA9IE1US19NVVNCX1JBTV9CSVRTLA0KK307DQorDQorc3Rh dGljIGNvbnN0IHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2VfaW5mbyBtdGtfZGV2X2luZm8gPSB7DQor CS5uYW1lID0gIm11c2ItaGRyYyIsDQorCS5pZCA9IFBMQVRGT1JNX0RFVklEX0FVVE8sDQorCS5k bWFfbWFzayA9IERNQV9CSVRfTUFTSygzMiksDQorfTsNCisNCitzdGF0aWMgaW50IG10a19tdXNi X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQorew0KKwlzdHJ1Y3QgbXVzYl9o ZHJjX3BsYXRmb3JtX2RhdGEgKnBkYXRhOw0KKwlzdHJ1Y3QgbXRrX2dsdWUgKmdsdWU7DQorCXN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2VfaW5mbyBwaW5mbzsNCisJc3RydWN0IGRldmljZSAqZGV2ID0g JnBkZXYtPmRldjsNCisJc3RydWN0IGRldmljZV9ub2RlICpucCA9IGRldi0+b2Zfbm9kZTsNCisJ aW50IHJldCA9IC1FTk9NRU07DQorDQorCWdsdWUgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2Yo KmdsdWUpLCBHRlBfS0VSTkVMKTsNCisJaWYgKCFnbHVlKQ0KKwkJcmV0dXJuIC1FTk9NRU07DQor DQorCWdsdWUtPmRldiA9IGRldjsNCisJcGRhdGEgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2Yo KnBkYXRhKSwgR0ZQX0tFUk5FTCk7DQorCWlmICghcGRhdGEpDQorCQlyZXR1cm4gLUVOT01FTTsN CisNCisJcmV0ID0gb2ZfcGxhdGZvcm1fcG9wdWxhdGUobnAsIE5VTEwsIE5VTEwsIGRldik7DQor CWlmIChyZXQpIHsNCisJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIGNyZWF0ZSBjaGlsZCBkZXZp Y2VzIGF0ICVwXG4iLCBucCk7DQorCQlyZXR1cm4gcmV0Ow0KKwl9DQorDQorCXJldCA9IG10a19t dXNiX2Nsa3NfZ2V0KGdsdWUpOw0KKwlpZiAocmV0KQ0KKwkJcmV0dXJuIHJldDsNCisNCisJcGRh dGEtPmNvbmZpZyA9ICZtdGtfbXVzYl9oZHJjX2NvbmZpZzsNCisJcGRhdGEtPnBsYXRmb3JtX29w cyA9ICZtdGtfbXVzYl9vcHM7DQorCXBkYXRhLT5tb2RlID0gdXNiX2dldF9kcl9tb2RlKGRldik7 DQorDQorCWlmIChJU19FTkFCTEVEKENPTkZJR19VU0JfTVVTQl9IT1NUKSkNCisJCXBkYXRhLT5t b2RlID0gVVNCX0RSX01PREVfSE9TVDsNCisJZWxzZSBpZiAoSVNfRU5BQkxFRChDT05GSUdfVVNC X01VU0JfR0FER0VUKSkNCisJCXBkYXRhLT5tb2RlID0gVVNCX0RSX01PREVfUEVSSVBIRVJBTDsN CisNCisJc3dpdGNoIChwZGF0YS0+bW9kZSkgew0KKwljYXNlIFVTQl9EUl9NT0RFX0hPU1Q6DQor CQlnbHVlLT5waHlfbW9kZSA9IFBIWV9NT0RFX1VTQl9IT1NUOw0KKwkJZ2x1ZS0+cm9sZSA9IFVT Ql9ST0xFX0hPU1Q7DQorCQlicmVhazsNCisJY2FzZSBVU0JfRFJfTU9ERV9QRVJJUEhFUkFMOg0K KwkJZ2x1ZS0+cGh5X21vZGUgPSBQSFlfTU9ERV9VU0JfREVWSUNFOw0KKwkJZ2x1ZS0+cm9sZSA9 IFVTQl9ST0xFX0RFVklDRTsNCisJCWJyZWFrOw0KKwljYXNlIFVTQl9EUl9NT0RFX09URzoNCisJ CWdsdWUtPnBoeV9tb2RlID0gUEhZX01PREVfVVNCX09URzsNCisJCWdsdWUtPnJvbGUgPSBVU0Jf Uk9MRV9OT05FOw0KKwkJYnJlYWs7DQorCWRlZmF1bHQ6DQorCQlkZXZfZXJyKCZwZGV2LT5kZXYs ICJFcnJvciAnZHJfbW9kZScgcHJvcGVydHlcbiIpOw0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0N CisNCisJZ2x1ZS0+cGh5ID0gZGV2bV9vZl9waHlfZ2V0X2J5X2luZGV4KGRldiwgbnAsIDApOw0K KwlpZiAoSVNfRVJSKGdsdWUtPnBoeSkpIHsNCisJCWRldl9lcnIoZGV2LCAiZmFpbCB0byBnZXR0 aW5nIHBoeSAlbGRcbiIsDQorCQkJUFRSX0VSUihnbHVlLT5waHkpKTsNCisJCXJldHVybiBQVFJf RVJSKGdsdWUtPnBoeSk7DQorCX0NCisNCisJZ2x1ZS0+dXNiX3BoeSA9IHVzYl9waHlfZ2VuZXJp Y19yZWdpc3RlcigpOw0KKwlpZiAoSVNfRVJSKGdsdWUtPnVzYl9waHkpKSB7DQorCQlkZXZfZXJy KGRldiwgImZhaWwgdG8gcmVnaXN0ZXJpbmcgdXNiLXBoeSAlbGRcbiIsDQorCQkJUFRSX0VSUihn bHVlLT51c2JfcGh5KSk7DQorCQlyZXR1cm4gUFRSX0VSUihnbHVlLT51c2JfcGh5KTsNCisJfQ0K Kw0KKwlnbHVlLT54Y2VpdiA9IGRldm1fdXNiX2dldF9waHkoZGV2LCBVU0JfUEhZX1RZUEVfVVNC Mik7DQorCWlmIChJU19FUlIoZ2x1ZS0+eGNlaXYpKSB7DQorCQlkZXZfZXJyKGRldiwgImZhaWwg dG8gZ2V0dGluZyB1c2ItcGh5ICVkXG4iLCByZXQpOw0KKwkJcmV0ID0gUFRSX0VSUihnbHVlLT54 Y2Vpdik7DQorCQlnb3RvIGVycl91bnJlZ2lzdGVyX3VzYl9waHk7DQorCX0NCisNCisJcGxhdGZv cm1fc2V0X2RydmRhdGEocGRldiwgZ2x1ZSk7DQorCXBtX3J1bnRpbWVfZW5hYmxlKGRldik7DQor CXBtX3J1bnRpbWVfZ2V0X3N5bmMoZGV2KTsNCisNCisJcmV0ID0gbXRrX211c2JfY2xrc19lbmFi bGUoZ2x1ZSk7DQorCWlmIChyZXQpDQorCQlnb3RvIGVycl9lbmFibGVfY2xrOw0KKw0KKwlwaW5m byA9IG10a19kZXZfaW5mbzsNCisJcGluZm8ucGFyZW50ID0gZGV2Ow0KKwlwaW5mby5yZXMgPSBw ZGV2LT5yZXNvdXJjZTsNCisJcGluZm8ubnVtX3JlcyA9IHBkZXYtPm51bV9yZXNvdXJjZXM7DQor CXBpbmZvLmRhdGEgPSBwZGF0YTsNCisJcGluZm8uc2l6ZV9kYXRhID0gc2l6ZW9mKCpwZGF0YSk7 DQorDQorCWdsdWUtPm11c2JfcGRldiA9IHBsYXRmb3JtX2RldmljZV9yZWdpc3Rlcl9mdWxsKCZw aW5mbyk7DQorCWlmIChJU19FUlIoZ2x1ZS0+bXVzYl9wZGV2KSkgew0KKwkJcmV0ID0gUFRSX0VS UihnbHVlLT5tdXNiX3BkZXYpOw0KKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIg bXVzYiBkZXZpY2U6ICVkXG4iLCByZXQpOw0KKwkJZ290byBlcnJfZGV2aWNlX3JlZ2lzdGVyOw0K Kwl9DQorDQorCXJldHVybiAwOw0KKw0KK2Vycl9kZXZpY2VfcmVnaXN0ZXI6DQorCW10a19tdXNi X2Nsa3NfZGlzYWJsZShnbHVlKTsNCitlcnJfZW5hYmxlX2NsazoNCisJcG1fcnVudGltZV9wdXRf c3luYyhkZXYpOw0KKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2KTsNCitlcnJfdW5yZWdpc3Rlcl91 c2JfcGh5Og0KKwl1c2JfcGh5X2dlbmVyaWNfdW5yZWdpc3RlcihnbHVlLT51c2JfcGh5KTsNCisJ cmV0dXJuIHJldDsNCit9DQorDQorc3RhdGljIGludCBtdGtfbXVzYl9yZW1vdmUoc3RydWN0IHBs YXRmb3JtX2RldmljZSAqcGRldikNCit7DQorCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IHBsYXRm b3JtX2dldF9kcnZkYXRhKHBkZXYpOw0KKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICp1c2JfcGh5 ID0gZ2x1ZS0+dXNiX3BoeTsNCisNCisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIoZ2x1ZS0+ bXVzYl9wZGV2KTsNCisJdXNiX3BoeV9nZW5lcmljX3VucmVnaXN0ZXIodXNiX3BoeSk7DQorDQor CXJldHVybiAwOw0KK30NCisNCisjaWZkZWYgQ09ORklHX09GDQorc3RhdGljIGNvbnN0IHN0cnVj dCBvZl9kZXZpY2VfaWQgbXRrX211c2JfbWF0Y2hbXSA9IHsNCisJey5jb21wYXRpYmxlID0gIm1l ZGlhdGVrLG10ay1tdXNiIix9LA0KKwl7fSwNCit9Ow0KK01PRFVMRV9ERVZJQ0VfVEFCTEUob2Ys IG10a19tdXNiX21hdGNoKTsNCisjZW5kaWYNCisNCitzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2Ry aXZlciBtdGtfbXVzYl9kcml2ZXIgPSB7DQorCS5wcm9iZSA9IG10a19tdXNiX3Byb2JlLA0KKwku cmVtb3ZlID0gbXRrX211c2JfcmVtb3ZlLA0KKwkuZHJpdmVyID0gew0KKwkJICAgLm5hbWUgPSAi bXVzYi1tdGsiLA0KKwkJICAgLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKG10a19tdXNi X21hdGNoKSwNCisJfSwNCit9Ow0KKw0KK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIobXRrX211c2Jf ZHJpdmVyKTsNCisNCitNT0RVTEVfREVTQ1JJUFRJT04oIk1lZGlhVGVrIE1VU0IgR2x1ZSBMYXll ciIpOw0KK01PRFVMRV9BVVRIT1IoIk1pbiBHdW8gPG1pbi5ndW9AbWVkaWF0ZWsuY29tPiIpOw0K K01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsNCi0tIA0KMi4yNC4wDQo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DD94C43603 for ; Wed, 11 Dec 2019 01:59:07 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 59FC5205ED for ; Wed, 11 Dec 2019 01:59:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="d6TTbryd"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="FVja0oTD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 59FC5205ED Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=auzCwKXcb3s7+ejdiDQbZo10RUG06zcSbMo/dwO7y+s=; b=d6TTbrydrCSThp LGFzI4OlM0qjbczy8fIxVXz9dN3xswlAfmCk7jqwBEZn2II4OlCSXzryAD/w3W8LRCF9e6aFFdayx x/nmh5ZBgLT/BMJd7O7upJBhU+Pl/MroGEtsvxIU6fM88GjmWwHvPH3v3wEvACo2/78KoU5iItix3 5a5gA/tj0rVxvkmj49DikO0oN7aNIC+3/lcdtHPRUI1/Iysn7bCwLEVD0OEpJH0ucAzx3QWUsBWEk 3xAgs2svX30VQnnIu10K5WCyc4vmyW5ljB4DS9OujmAgSvYZXgUst4do5FSqCfBZVnCs9Heh3BOvI f3SuPsmPPuJt6Rn7RByQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ierHO-0007HU-I6; Wed, 11 Dec 2019 01:59:06 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ierGm-0006Z8-TY; Wed, 11 Dec 2019 01:58:31 +0000 X-UUID: 28f20b2fc6b74574ac054f4d6f023349-20191210 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=tlAzxBX9ycjTVdOifSbzxIms9Y9rG2W7CX+ujLd3EZ0=; b=FVja0oTDok/fyCj9ngjsRMaXFTvkiLbGhbG5Jh3oq9dcNld1sp367U66ZzvhBa2gAXSNbuEbuej6svFD4gjA7F/Ef21IJY5noCVkF4k+XMg4DnydQY0hIPjuPonbMgROqOKpcxGgb8N2F2aMCPnu7YXedJmF1VyVNEj5YnU5h4U=; X-UUID: 28f20b2fc6b74574ac054f4d6f023349-20191210 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1124349356; Tue, 10 Dec 2019 17:58:23 -0800 Received: from MTKMBS31N2.mediatek.inc (172.27.4.87) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 17:55:20 -0800 Received: from mtkcas09.mediatek.inc (172.21.101.178) by MTKMBS31N2.mediatek.inc (172.27.4.87) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Wed, 11 Dec 2019 09:54:04 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkcas09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Wed, 11 Dec 2019 09:54:55 +0800 From: To: Bin Liu , Rob Herring Subject: [PATCH v9 6/6] usb: musb: Add support for MediaTek musb controller Date: Wed, 11 Dec 2019 09:54:46 +0800 Message-ID: <20191211015446.11477-7-min.guo@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20191211015446.11477-1-min.guo@mediatek.com> References: <20191211015446.11477-1-min.guo@mediatek.com> MIME-Version: 1.0 X-TM-SNTS-SMTP: 0E7D616F6EE3390380FA359D3DFADACE75E7945CE4BA4AF9E345364A01F2D4402000:8 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191210_175828_986842_F4D6A755 X-CRM114-Status: GOOD ( 18.68 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Yonglong Wu , hdegoede@redhat.com, tony@atomide.com, Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Matthias Brugger , Alan Stern , Min Guo , chunfeng.yun@mediatek.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Min Guo This adds support for MediaTek musb controller in host, peripheral and otg mode. There are some quirk of MediaTek musb controller, such as: -W1C interrupt status registers -Private data toggle registers -No dedicated DMA interrupt line Signed-off-by: Min Guo Signed-off-by: Yonglong Wu --- changes in v9: 1. no changes changes in v8: 1. no changes changes in v7: 1. no changes changes in v6: 1. Add of_platform_populate in probe to populate connector platform_devices from device tree data 2. Replace extcon with usb role switch mechanism to support dual-role mode 3. Remove set vbus function changes in v5: 1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending interrupts 2. Make musb_clearb/w() return the value of musb_readb/w() 3. Add driver to get child nodes of usb connector and extcon device changes in v4: 1. no changes changes in v3: suggested by Bin: 1. Remove 'u8/u16 data' parameter in clearb/w() hooks 2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status changes in v2: suggested by Bin: 1. Add summarize of MediaTek musb controller differences in the commit log 2. Add "|| COMPILE_TEST" in Kconfig 3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c 4. Replace musb_readl() with musb_readw() to read 16bit toggle register --- drivers/usb/musb/Kconfig | 9 +- drivers/usb/musb/Makefile | 1 + drivers/usb/musb/mediatek.c | 582 ++++++++++++++++++++++++++++++++++++ 3 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb/mediatek.c diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 52f8e2b57ad5..767c5da90912 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -116,6 +116,13 @@ config USB_MUSB_JZ4740 depends on USB_MUSB_GADGET depends on USB=n || USB_OTG_BLACKLIST_HUB +config USB_MUSB_MEDIATEK + tristate "MediaTek platforms" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on NOP_USB_XCEIV + depends on GENERIC_PHY + select USB_ROLE_SWITCH + config USB_MUSB_AM335X_CHILD tristate @@ -142,7 +149,7 @@ config USB_UX500_DMA config USB_INVENTRA_DMA bool 'Inventra' - depends on USB_MUSB_OMAP2PLUS + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK help Enable DMA transfers using Mentor's engine. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 3a88c79e650c..63d82d0fab67 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o +obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c new file mode 100644 index 000000000000..3df8d7ef0847 --- /dev/null +++ b/drivers/usb/musb/mediatek.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 MediaTek Inc. + * + * Author: + * Min Guo + * Yonglong Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include "musb_core.h" +#include "musb_dma.h" + +#define USB_L1INTS 0x00a0 +#define USB_L1INTM 0x00a4 +#define MTK_MUSB_TXFUNCADDR 0x0480 + +/* MediaTek controller toggle enable and status reg */ +#define MUSB_RXTOG 0x80 +#define MUSB_RXTOGEN 0x82 +#define MUSB_TXTOG 0x84 +#define MUSB_TXTOGEN 0x86 +#define MTK_TOGGLE_EN GENMASK(15, 0) + +#define TX_INT_STATUS BIT(0) +#define RX_INT_STATUS BIT(1) +#define USBCOM_INT_STATUS BIT(2) +#define DMA_INT_STATUS BIT(3) + +#define DMA_INTR_STATUS_MSK GENMASK(7, 0) +#define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) + +struct mtk_glue { + struct device *dev; + struct musb *musb; + struct platform_device *musb_pdev; + struct platform_device *usb_phy; + struct phy *phy; + struct usb_phy *xceiv; + enum phy_mode phy_mode; + struct clk *main; + struct clk *mcu; + struct clk *univpll; + enum usb_role role; + struct usb_role_switch *role_sw; +}; + +static int mtk_musb_clks_get(struct mtk_glue *glue) +{ + struct device *dev = glue->dev; + + glue->main = devm_clk_get(dev, "main"); + if (IS_ERR(glue->main)) { + dev_err(dev, "fail to get main clock\n"); + return PTR_ERR(glue->main); + } + + glue->mcu = devm_clk_get(dev, "mcu"); + if (IS_ERR(glue->mcu)) { + dev_err(dev, "fail to get mcu clock\n"); + return PTR_ERR(glue->mcu); + } + + glue->univpll = devm_clk_get(dev, "univpll"); + if (IS_ERR(glue->univpll)) { + dev_err(dev, "fail to get univpll clock\n"); + return PTR_ERR(glue->univpll); + } + + return 0; +} + +static int mtk_musb_clks_enable(struct mtk_glue *glue) +{ + int ret; + + ret = clk_prepare_enable(glue->main); + if (ret) { + dev_err(glue->dev, "failed to enable main clock\n"); + goto err_main_clk; + } + + ret = clk_prepare_enable(glue->mcu); + if (ret) { + dev_err(glue->dev, "failed to enable mcu clock\n"); + goto err_mcu_clk; + } + + ret = clk_prepare_enable(glue->univpll); + if (ret) { + dev_err(glue->dev, "failed to enable univpll clock\n"); + goto err_univpll_clk; + } + + return 0; + +err_univpll_clk: + clk_disable_unprepare(glue->mcu); +err_mcu_clk: + clk_disable_unprepare(glue->main); +err_main_clk: + return ret; +} + +static void mtk_musb_clks_disable(struct mtk_glue *glue) +{ + clk_disable_unprepare(glue->univpll); + clk_disable_unprepare(glue->mcu); + clk_disable_unprepare(glue->main); +} + +static int musb_usb_role_sx_set(struct device *dev, enum usb_role role) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + struct musb *musb = glue->musb; + u8 devctl = readb(musb->mregs + MUSB_DEVCTL); + enum usb_role new_role; + + if (role == glue->role) + return 0; + + switch (role) { + case USB_ROLE_HOST: + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; + glue->phy_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + MUSB_HST_MODE(musb); + break; + case USB_ROLE_DEVICE: + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + glue->phy_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + MUSB_DEV_MODE(musb); + break; + case USB_ROLE_NONE: + glue->phy_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role != USB_ROLE_NONE) + phy_power_off(glue->phy); + + break; + default: + dev_err(glue->dev, "Invalid State\n"); + return -EINVAL; + } + + glue->role = new_role; + phy_set_mode(glue->phy, glue->phy_mode); + + return 0; +} + +static enum usb_role musb_usb_role_sx_get(struct device *dev) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + + return glue->role; +} + +static int mtk_otg_switch_init(struct mtk_glue *glue) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + + role_sx_desc.set = musb_usb_role_sx_set; + role_sx_desc.get = musb_usb_role_sx_get; + role_sx_desc.fwnode = dev_fwnode(glue->dev); + glue->role_sw = usb_role_switch_register(glue->dev, &role_sx_desc); + + return PTR_ERR_OR_ZERO(glue->role_sw); +} + +static void mtk_otg_switch_exit(struct mtk_glue *glue) +{ + return usb_role_switch_unregister(glue->role_sw); +} + +static irqreturn_t generic_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + + spin_lock_irqsave(&musb->lock, flags); + musb->int_usb = musb_clearb(musb->mregs, MUSB_INTRUSB); + musb->int_rx = musb_clearw(musb->mregs, MUSB_INTRRX); + musb->int_tx = musb_clearw(musb->mregs, MUSB_INTRTX); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval = musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return retval; +} + +static irqreturn_t mtk_musb_interrupt(int irq, void *dev_id) +{ + irqreturn_t retval = IRQ_NONE; + struct musb *musb = (struct musb *)dev_id; + u32 l1_ints; + + l1_ints = musb_readl(musb->mregs, USB_L1INTS) & + musb_readl(musb->mregs, USB_L1INTM); + + if (l1_ints & (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS)) + retval = generic_interrupt(irq, musb); + +#if defined(CONFIG_USB_INVENTRA_DMA) + if (l1_ints & DMA_INT_STATUS) + retval = dma_controller_irq(irq, musb->dma_controller); +#endif + return retval; +} + +static u32 mtk_musb_busctl_offset(u8 epnum, u16 offset) +{ + return MTK_MUSB_TXFUNCADDR + offset + 8 * epnum; +} + +static u8 mtk_musb_clearb(void __iomem *addr, unsigned int offset) +{ + u8 data; + + /* W1C */ + data = musb_readb(addr, offset); + musb_writeb(addr, offset, data); + return data; +} + +static u16 mtk_musb_clearw(void __iomem *addr, unsigned int offset) +{ + u16 data; + + /* W1C */ + data = musb_readw(addr, offset); + musb_writew(addr, offset, data); + return data; +} + +static int mtk_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + enum phy_mode new_mode; + enum usb_role new_role; + + switch (mode) { + case MUSB_HOST: + new_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + break; + case MUSB_PERIPHERAL: + new_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + break; + case MUSB_OTG: + new_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + break; + default: + dev_err(glue->dev, "Invalid mode request\n"); + return -EINVAL; + } + + if (glue->phy_mode == new_mode) + return 0; + + if (musb->port_mode != MUSB_OTG) { + dev_err(glue->dev, "Does not support changing modes\n"); + return -EINVAL; + } + + glue->role = new_role; + musb_usb_role_sx_set(dev, glue->role); + return 0; +} + +static int mtk_musb_init(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + int ret; + + glue->musb = musb; + musb->phy = glue->phy; + musb->xceiv = glue->xceiv; + musb->is_host = false; + musb->isr = mtk_musb_interrupt; + + /* Set TX/RX toggle enable */ + musb_writew(musb->mregs, MUSB_TXTOGEN, MTK_TOGGLE_EN); + musb_writew(musb->mregs, MUSB_RXTOGEN, MTK_TOGGLE_EN); + + if (musb->port_mode == MUSB_OTG) { + ret = mtk_otg_switch_init(glue); + if (ret) + return ret; + } + + ret = phy_init(glue->phy); + if (ret) + goto err_phy_init; + + ret = phy_power_on(glue->phy); + if (ret) + goto err_phy_power_on; + + phy_set_mode(glue->phy, glue->phy_mode); + +#if defined(CONFIG_USB_INVENTRA_DMA) + musb_writel(musb->mregs, MUSB_HSDMA_INTR, + DMA_INTR_STATUS_MSK | DMA_INTR_UNMASK_SET_MSK); +#endif + musb_writel(musb->mregs, USB_L1INTM, TX_INT_STATUS | RX_INT_STATUS | + USBCOM_INT_STATUS | DMA_INT_STATUS); + return 0; + +err_phy_power_on: + phy_exit(glue->phy); +err_phy_init: + mtk_otg_switch_exit(glue); + return ret; +} + +static u16 mtk_musb_get_toggle(struct musb_qh *qh, int is_out) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 toggle; + + toggle = musb_readw(musb->mregs, is_out ? MUSB_TXTOG : MUSB_RXTOG); + return toggle & (1 << epnum); +} + +static u16 mtk_musb_set_toggle(struct musb_qh *qh, int is_out, struct urb *urb) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 value, toggle; + + toggle = usb_gettoggle(urb->dev, qh->epnum, is_out); + + if (is_out) { + value = musb_readw(musb->mregs, MUSB_TXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_TXTOG, value); + } else { + value = musb_readw(musb->mregs, MUSB_RXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_RXTOG, value); + } + + return 0; +} + +static int mtk_musb_exit(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + + mtk_otg_switch_exit(glue); + phy_power_off(glue->phy); + phy_exit(glue->phy); + mtk_musb_clks_disable(glue); + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return 0; +} + +static const struct musb_platform_ops mtk_musb_ops = { + .quirks = MUSB_DMA_INVENTRA, + .init = mtk_musb_init, + .get_toggle = mtk_musb_get_toggle, + .set_toggle = mtk_musb_set_toggle, + .exit = mtk_musb_exit, +#ifdef CONFIG_USB_INVENTRA_DMA + .dma_init = musbhs_dma_controller_create_noirq, + .dma_exit = musbhs_dma_controller_destroy, +#endif + .clearb = mtk_musb_clearb, + .clearw = mtk_musb_clearw, + .busctl_offset = mtk_musb_busctl_offset, + .set_mode = mtk_musb_set_mode, +}; + +#define MTK_MUSB_MAX_EP_NUM 8 +#define MTK_MUSB_RAM_BITS 11 + +static struct musb_fifo_cfg mtk_musb_mode_cfg[] = { + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 1024, }, + { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 1024, }, + { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 64, }, +}; + +static const struct musb_hdrc_config mtk_musb_hdrc_config = { + .fifo_cfg = mtk_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(mtk_musb_mode_cfg), + .multipoint = true, + .dyn_fifo = true, + .num_eps = MTK_MUSB_MAX_EP_NUM, + .ram_bits = MTK_MUSB_RAM_BITS, +}; + +static const struct platform_device_info mtk_dev_info = { + .name = "musb-hdrc", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = DMA_BIT_MASK(32), +}; + +static int mtk_musb_probe(struct platform_device *pdev) +{ + struct musb_hdrc_platform_data *pdata; + struct mtk_glue *glue; + struct platform_device_info pinfo; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret = -ENOMEM; + + glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); + if (!glue) + return -ENOMEM; + + glue->dev = dev; + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to create child devices at %p\n", np); + return ret; + } + + ret = mtk_musb_clks_get(glue); + if (ret) + return ret; + + pdata->config = &mtk_musb_hdrc_config; + pdata->platform_ops = &mtk_musb_ops; + pdata->mode = usb_get_dr_mode(dev); + + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) + pdata->mode = USB_DR_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_MUSB_GADGET)) + pdata->mode = USB_DR_MODE_PERIPHERAL; + + switch (pdata->mode) { + case USB_DR_MODE_HOST: + glue->phy_mode = PHY_MODE_USB_HOST; + glue->role = USB_ROLE_HOST; + break; + case USB_DR_MODE_PERIPHERAL: + glue->phy_mode = PHY_MODE_USB_DEVICE; + glue->role = USB_ROLE_DEVICE; + break; + case USB_DR_MODE_OTG: + glue->phy_mode = PHY_MODE_USB_OTG; + glue->role = USB_ROLE_NONE; + break; + default: + dev_err(&pdev->dev, "Error 'dr_mode' property\n"); + return -EINVAL; + } + + glue->phy = devm_of_phy_get_by_index(dev, np, 0); + if (IS_ERR(glue->phy)) { + dev_err(dev, "fail to getting phy %ld\n", + PTR_ERR(glue->phy)); + return PTR_ERR(glue->phy); + } + + glue->usb_phy = usb_phy_generic_register(); + if (IS_ERR(glue->usb_phy)) { + dev_err(dev, "fail to registering usb-phy %ld\n", + PTR_ERR(glue->usb_phy)); + return PTR_ERR(glue->usb_phy); + } + + glue->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + if (IS_ERR(glue->xceiv)) { + dev_err(dev, "fail to getting usb-phy %d\n", ret); + ret = PTR_ERR(glue->xceiv); + goto err_unregister_usb_phy; + } + + platform_set_drvdata(pdev, glue); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + ret = mtk_musb_clks_enable(glue); + if (ret) + goto err_enable_clk; + + pinfo = mtk_dev_info; + pinfo.parent = dev; + pinfo.res = pdev->resource; + pinfo.num_res = pdev->num_resources; + pinfo.data = pdata; + pinfo.size_data = sizeof(*pdata); + + glue->musb_pdev = platform_device_register_full(&pinfo); + if (IS_ERR(glue->musb_pdev)) { + ret = PTR_ERR(glue->musb_pdev); + dev_err(dev, "failed to register musb device: %d\n", ret); + goto err_device_register; + } + + return 0; + +err_device_register: + mtk_musb_clks_disable(glue); +err_enable_clk: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +err_unregister_usb_phy: + usb_phy_generic_unregister(glue->usb_phy); + return ret; +} + +static int mtk_musb_remove(struct platform_device *pdev) +{ + struct mtk_glue *glue = platform_get_drvdata(pdev); + struct platform_device *usb_phy = glue->usb_phy; + + platform_device_unregister(glue->musb_pdev); + usb_phy_generic_unregister(usb_phy); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id mtk_musb_match[] = { + {.compatible = "mediatek,mtk-musb",}, + {}, +}; +MODULE_DEVICE_TABLE(of, mtk_musb_match); +#endif + +static struct platform_driver mtk_musb_driver = { + .probe = mtk_musb_probe, + .remove = mtk_musb_remove, + .driver = { + .name = "musb-mtk", + .of_match_table = of_match_ptr(mtk_musb_match), + }, +}; + +module_platform_driver(mtk_musb_driver); + +MODULE_DESCRIPTION("MediaTek MUSB Glue Layer"); +MODULE_AUTHOR("Min Guo "); +MODULE_LICENSE("GPL v2"); -- 2.24.0 _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,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 01898C43603 for ; Wed, 11 Dec 2019 01:58:56 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 981622073B for ; Wed, 11 Dec 2019 01:58:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="fwboGjqG"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="FVja0oTD" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 981622073B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9S1H/DkfQ7xoK2dBhfxoArnTCkQ032KLLp5wQsTs5ds=; b=fwboGjqGaHAv4z sNWiGiMpsCEjYICSJ9QiiVu2wOmIPi9fW5ALry4M77avvP+CiFtEVivzZ9xqruxGT5UnRfDpDdm71 N82IX88fAWANbEUgRtvX1AhSpzeSK4SCb/ofQ8rYJbacot4xfaufjLQSQur3QpQxerBfsV0flJwHS B322+wOvl3JgDwV1mD+4G6XTmovo7bwuTNO3ZXwELNs4z2vgdrHfbZgTfmGGyE7xpQbHz2LjcH7x5 znEXTAVQqf9cWTLgUh4DQVFTiK9q7fJepXEUDkT5dBubbICrcfAnkal5xr83qFQEb14GYFmGZc32r iVd7y2/QItrBsO5yxQiQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ierHB-000726-O3; Wed, 11 Dec 2019 01:58:53 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ierGm-0006Z8-TY; Wed, 11 Dec 2019 01:58:31 +0000 X-UUID: 28f20b2fc6b74574ac054f4d6f023349-20191210 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=tlAzxBX9ycjTVdOifSbzxIms9Y9rG2W7CX+ujLd3EZ0=; b=FVja0oTDok/fyCj9ngjsRMaXFTvkiLbGhbG5Jh3oq9dcNld1sp367U66ZzvhBa2gAXSNbuEbuej6svFD4gjA7F/Ef21IJY5noCVkF4k+XMg4DnydQY0hIPjuPonbMgROqOKpcxGgb8N2F2aMCPnu7YXedJmF1VyVNEj5YnU5h4U=; X-UUID: 28f20b2fc6b74574ac054f4d6f023349-20191210 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1124349356; Tue, 10 Dec 2019 17:58:23 -0800 Received: from MTKMBS31N2.mediatek.inc (172.27.4.87) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 17:55:20 -0800 Received: from mtkcas09.mediatek.inc (172.21.101.178) by MTKMBS31N2.mediatek.inc (172.27.4.87) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Wed, 11 Dec 2019 09:54:04 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkcas09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Wed, 11 Dec 2019 09:54:55 +0800 From: To: Bin Liu , Rob Herring Subject: [PATCH v9 6/6] usb: musb: Add support for MediaTek musb controller Date: Wed, 11 Dec 2019 09:54:46 +0800 Message-ID: <20191211015446.11477-7-min.guo@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20191211015446.11477-1-min.guo@mediatek.com> References: <20191211015446.11477-1-min.guo@mediatek.com> MIME-Version: 1.0 X-TM-SNTS-SMTP: 0E7D616F6EE3390380FA359D3DFADACE75E7945CE4BA4AF9E345364A01F2D4402000:8 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191210_175828_986842_F4D6A755 X-CRM114-Status: GOOD ( 18.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Yonglong Wu , hdegoede@redhat.com, tony@atomide.com, Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Matthias Brugger , Alan Stern , Min Guo , chunfeng.yun@mediatek.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Min Guo This adds support for MediaTek musb controller in host, peripheral and otg mode. There are some quirk of MediaTek musb controller, such as: -W1C interrupt status registers -Private data toggle registers -No dedicated DMA interrupt line Signed-off-by: Min Guo Signed-off-by: Yonglong Wu --- changes in v9: 1. no changes changes in v8: 1. no changes changes in v7: 1. no changes changes in v6: 1. Add of_platform_populate in probe to populate connector platform_devices from device tree data 2. Replace extcon with usb role switch mechanism to support dual-role mode 3. Remove set vbus function changes in v5: 1. Replace musb_readb() with musb_clearb() to clear common/tx/rx pending interrupts 2. Make musb_clearb/w() return the value of musb_readb/w() 3. Add driver to get child nodes of usb connector and extcon device changes in v4: 1. no changes changes in v3: suggested by Bin: 1. Remove 'u8/u16 data' parameter in clearb/w() hooks 2. Replace musb_readb/w() with musb_clearb/w() to clear interrupts status changes in v2: suggested by Bin: 1. Add summarize of MediaTek musb controller differences in the commit log 2. Add "|| COMPILE_TEST" in Kconfig 3. Move MediaTek's private toggle registers from musb_regs.h to mediatek.c 4. Replace musb_readl() with musb_readw() to read 16bit toggle register --- drivers/usb/musb/Kconfig | 9 +- drivers/usb/musb/Makefile | 1 + drivers/usb/musb/mediatek.c | 582 ++++++++++++++++++++++++++++++++++++ 3 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb/mediatek.c diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 52f8e2b57ad5..767c5da90912 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -116,6 +116,13 @@ config USB_MUSB_JZ4740 depends on USB_MUSB_GADGET depends on USB=n || USB_OTG_BLACKLIST_HUB +config USB_MUSB_MEDIATEK + tristate "MediaTek platforms" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on NOP_USB_XCEIV + depends on GENERIC_PHY + select USB_ROLE_SWITCH + config USB_MUSB_AM335X_CHILD tristate @@ -142,7 +149,7 @@ config USB_UX500_DMA config USB_INVENTRA_DMA bool 'Inventra' - depends on USB_MUSB_OMAP2PLUS + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK help Enable DMA transfers using Mentor's engine. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 3a88c79e650c..63d82d0fab67 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o +obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c new file mode 100644 index 000000000000..3df8d7ef0847 --- /dev/null +++ b/drivers/usb/musb/mediatek.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 MediaTek Inc. + * + * Author: + * Min Guo + * Yonglong Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include "musb_core.h" +#include "musb_dma.h" + +#define USB_L1INTS 0x00a0 +#define USB_L1INTM 0x00a4 +#define MTK_MUSB_TXFUNCADDR 0x0480 + +/* MediaTek controller toggle enable and status reg */ +#define MUSB_RXTOG 0x80 +#define MUSB_RXTOGEN 0x82 +#define MUSB_TXTOG 0x84 +#define MUSB_TXTOGEN 0x86 +#define MTK_TOGGLE_EN GENMASK(15, 0) + +#define TX_INT_STATUS BIT(0) +#define RX_INT_STATUS BIT(1) +#define USBCOM_INT_STATUS BIT(2) +#define DMA_INT_STATUS BIT(3) + +#define DMA_INTR_STATUS_MSK GENMASK(7, 0) +#define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) + +struct mtk_glue { + struct device *dev; + struct musb *musb; + struct platform_device *musb_pdev; + struct platform_device *usb_phy; + struct phy *phy; + struct usb_phy *xceiv; + enum phy_mode phy_mode; + struct clk *main; + struct clk *mcu; + struct clk *univpll; + enum usb_role role; + struct usb_role_switch *role_sw; +}; + +static int mtk_musb_clks_get(struct mtk_glue *glue) +{ + struct device *dev = glue->dev; + + glue->main = devm_clk_get(dev, "main"); + if (IS_ERR(glue->main)) { + dev_err(dev, "fail to get main clock\n"); + return PTR_ERR(glue->main); + } + + glue->mcu = devm_clk_get(dev, "mcu"); + if (IS_ERR(glue->mcu)) { + dev_err(dev, "fail to get mcu clock\n"); + return PTR_ERR(glue->mcu); + } + + glue->univpll = devm_clk_get(dev, "univpll"); + if (IS_ERR(glue->univpll)) { + dev_err(dev, "fail to get univpll clock\n"); + return PTR_ERR(glue->univpll); + } + + return 0; +} + +static int mtk_musb_clks_enable(struct mtk_glue *glue) +{ + int ret; + + ret = clk_prepare_enable(glue->main); + if (ret) { + dev_err(glue->dev, "failed to enable main clock\n"); + goto err_main_clk; + } + + ret = clk_prepare_enable(glue->mcu); + if (ret) { + dev_err(glue->dev, "failed to enable mcu clock\n"); + goto err_mcu_clk; + } + + ret = clk_prepare_enable(glue->univpll); + if (ret) { + dev_err(glue->dev, "failed to enable univpll clock\n"); + goto err_univpll_clk; + } + + return 0; + +err_univpll_clk: + clk_disable_unprepare(glue->mcu); +err_mcu_clk: + clk_disable_unprepare(glue->main); +err_main_clk: + return ret; +} + +static void mtk_musb_clks_disable(struct mtk_glue *glue) +{ + clk_disable_unprepare(glue->univpll); + clk_disable_unprepare(glue->mcu); + clk_disable_unprepare(glue->main); +} + +static int musb_usb_role_sx_set(struct device *dev, enum usb_role role) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + struct musb *musb = glue->musb; + u8 devctl = readb(musb->mregs + MUSB_DEVCTL); + enum usb_role new_role; + + if (role == glue->role) + return 0; + + switch (role) { + case USB_ROLE_HOST: + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; + glue->phy_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + MUSB_HST_MODE(musb); + break; + case USB_ROLE_DEVICE: + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + glue->phy_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + MUSB_DEV_MODE(musb); + break; + case USB_ROLE_NONE: + glue->phy_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role != USB_ROLE_NONE) + phy_power_off(glue->phy); + + break; + default: + dev_err(glue->dev, "Invalid State\n"); + return -EINVAL; + } + + glue->role = new_role; + phy_set_mode(glue->phy, glue->phy_mode); + + return 0; +} + +static enum usb_role musb_usb_role_sx_get(struct device *dev) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + + return glue->role; +} + +static int mtk_otg_switch_init(struct mtk_glue *glue) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + + role_sx_desc.set = musb_usb_role_sx_set; + role_sx_desc.get = musb_usb_role_sx_get; + role_sx_desc.fwnode = dev_fwnode(glue->dev); + glue->role_sw = usb_role_switch_register(glue->dev, &role_sx_desc); + + return PTR_ERR_OR_ZERO(glue->role_sw); +} + +static void mtk_otg_switch_exit(struct mtk_glue *glue) +{ + return usb_role_switch_unregister(glue->role_sw); +} + +static irqreturn_t generic_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + + spin_lock_irqsave(&musb->lock, flags); + musb->int_usb = musb_clearb(musb->mregs, MUSB_INTRUSB); + musb->int_rx = musb_clearw(musb->mregs, MUSB_INTRRX); + musb->int_tx = musb_clearw(musb->mregs, MUSB_INTRTX); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval = musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return retval; +} + +static irqreturn_t mtk_musb_interrupt(int irq, void *dev_id) +{ + irqreturn_t retval = IRQ_NONE; + struct musb *musb = (struct musb *)dev_id; + u32 l1_ints; + + l1_ints = musb_readl(musb->mregs, USB_L1INTS) & + musb_readl(musb->mregs, USB_L1INTM); + + if (l1_ints & (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS)) + retval = generic_interrupt(irq, musb); + +#if defined(CONFIG_USB_INVENTRA_DMA) + if (l1_ints & DMA_INT_STATUS) + retval = dma_controller_irq(irq, musb->dma_controller); +#endif + return retval; +} + +static u32 mtk_musb_busctl_offset(u8 epnum, u16 offset) +{ + return MTK_MUSB_TXFUNCADDR + offset + 8 * epnum; +} + +static u8 mtk_musb_clearb(void __iomem *addr, unsigned int offset) +{ + u8 data; + + /* W1C */ + data = musb_readb(addr, offset); + musb_writeb(addr, offset, data); + return data; +} + +static u16 mtk_musb_clearw(void __iomem *addr, unsigned int offset) +{ + u16 data; + + /* W1C */ + data = musb_readw(addr, offset); + musb_writew(addr, offset, data); + return data; +} + +static int mtk_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + enum phy_mode new_mode; + enum usb_role new_role; + + switch (mode) { + case MUSB_HOST: + new_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + break; + case MUSB_PERIPHERAL: + new_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + break; + case MUSB_OTG: + new_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + break; + default: + dev_err(glue->dev, "Invalid mode request\n"); + return -EINVAL; + } + + if (glue->phy_mode == new_mode) + return 0; + + if (musb->port_mode != MUSB_OTG) { + dev_err(glue->dev, "Does not support changing modes\n"); + return -EINVAL; + } + + glue->role = new_role; + musb_usb_role_sx_set(dev, glue->role); + return 0; +} + +static int mtk_musb_init(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + int ret; + + glue->musb = musb; + musb->phy = glue->phy; + musb->xceiv = glue->xceiv; + musb->is_host = false; + musb->isr = mtk_musb_interrupt; + + /* Set TX/RX toggle enable */ + musb_writew(musb->mregs, MUSB_TXTOGEN, MTK_TOGGLE_EN); + musb_writew(musb->mregs, MUSB_RXTOGEN, MTK_TOGGLE_EN); + + if (musb->port_mode == MUSB_OTG) { + ret = mtk_otg_switch_init(glue); + if (ret) + return ret; + } + + ret = phy_init(glue->phy); + if (ret) + goto err_phy_init; + + ret = phy_power_on(glue->phy); + if (ret) + goto err_phy_power_on; + + phy_set_mode(glue->phy, glue->phy_mode); + +#if defined(CONFIG_USB_INVENTRA_DMA) + musb_writel(musb->mregs, MUSB_HSDMA_INTR, + DMA_INTR_STATUS_MSK | DMA_INTR_UNMASK_SET_MSK); +#endif + musb_writel(musb->mregs, USB_L1INTM, TX_INT_STATUS | RX_INT_STATUS | + USBCOM_INT_STATUS | DMA_INT_STATUS); + return 0; + +err_phy_power_on: + phy_exit(glue->phy); +err_phy_init: + mtk_otg_switch_exit(glue); + return ret; +} + +static u16 mtk_musb_get_toggle(struct musb_qh *qh, int is_out) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 toggle; + + toggle = musb_readw(musb->mregs, is_out ? MUSB_TXTOG : MUSB_RXTOG); + return toggle & (1 << epnum); +} + +static u16 mtk_musb_set_toggle(struct musb_qh *qh, int is_out, struct urb *urb) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 value, toggle; + + toggle = usb_gettoggle(urb->dev, qh->epnum, is_out); + + if (is_out) { + value = musb_readw(musb->mregs, MUSB_TXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_TXTOG, value); + } else { + value = musb_readw(musb->mregs, MUSB_RXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_RXTOG, value); + } + + return 0; +} + +static int mtk_musb_exit(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + + mtk_otg_switch_exit(glue); + phy_power_off(glue->phy); + phy_exit(glue->phy); + mtk_musb_clks_disable(glue); + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return 0; +} + +static const struct musb_platform_ops mtk_musb_ops = { + .quirks = MUSB_DMA_INVENTRA, + .init = mtk_musb_init, + .get_toggle = mtk_musb_get_toggle, + .set_toggle = mtk_musb_set_toggle, + .exit = mtk_musb_exit, +#ifdef CONFIG_USB_INVENTRA_DMA + .dma_init = musbhs_dma_controller_create_noirq, + .dma_exit = musbhs_dma_controller_destroy, +#endif + .clearb = mtk_musb_clearb, + .clearw = mtk_musb_clearw, + .busctl_offset = mtk_musb_busctl_offset, + .set_mode = mtk_musb_set_mode, +}; + +#define MTK_MUSB_MAX_EP_NUM 8 +#define MTK_MUSB_RAM_BITS 11 + +static struct musb_fifo_cfg mtk_musb_mode_cfg[] = { + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 1024, }, + { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 1024, }, + { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 64, }, +}; + +static const struct musb_hdrc_config mtk_musb_hdrc_config = { + .fifo_cfg = mtk_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(mtk_musb_mode_cfg), + .multipoint = true, + .dyn_fifo = true, + .num_eps = MTK_MUSB_MAX_EP_NUM, + .ram_bits = MTK_MUSB_RAM_BITS, +}; + +static const struct platform_device_info mtk_dev_info = { + .name = "musb-hdrc", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = DMA_BIT_MASK(32), +}; + +static int mtk_musb_probe(struct platform_device *pdev) +{ + struct musb_hdrc_platform_data *pdata; + struct mtk_glue *glue; + struct platform_device_info pinfo; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret = -ENOMEM; + + glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); + if (!glue) + return -ENOMEM; + + glue->dev = dev; + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to create child devices at %p\n", np); + return ret; + } + + ret = mtk_musb_clks_get(glue); + if (ret) + return ret; + + pdata->config = &mtk_musb_hdrc_config; + pdata->platform_ops = &mtk_musb_ops; + pdata->mode = usb_get_dr_mode(dev); + + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) + pdata->mode = USB_DR_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_MUSB_GADGET)) + pdata->mode = USB_DR_MODE_PERIPHERAL; + + switch (pdata->mode) { + case USB_DR_MODE_HOST: + glue->phy_mode = PHY_MODE_USB_HOST; + glue->role = USB_ROLE_HOST; + break; + case USB_DR_MODE_PERIPHERAL: + glue->phy_mode = PHY_MODE_USB_DEVICE; + glue->role = USB_ROLE_DEVICE; + break; + case USB_DR_MODE_OTG: + glue->phy_mode = PHY_MODE_USB_OTG; + glue->role = USB_ROLE_NONE; + break; + default: + dev_err(&pdev->dev, "Error 'dr_mode' property\n"); + return -EINVAL; + } + + glue->phy = devm_of_phy_get_by_index(dev, np, 0); + if (IS_ERR(glue->phy)) { + dev_err(dev, "fail to getting phy %ld\n", + PTR_ERR(glue->phy)); + return PTR_ERR(glue->phy); + } + + glue->usb_phy = usb_phy_generic_register(); + if (IS_ERR(glue->usb_phy)) { + dev_err(dev, "fail to registering usb-phy %ld\n", + PTR_ERR(glue->usb_phy)); + return PTR_ERR(glue->usb_phy); + } + + glue->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + if (IS_ERR(glue->xceiv)) { + dev_err(dev, "fail to getting usb-phy %d\n", ret); + ret = PTR_ERR(glue->xceiv); + goto err_unregister_usb_phy; + } + + platform_set_drvdata(pdev, glue); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + ret = mtk_musb_clks_enable(glue); + if (ret) + goto err_enable_clk; + + pinfo = mtk_dev_info; + pinfo.parent = dev; + pinfo.res = pdev->resource; + pinfo.num_res = pdev->num_resources; + pinfo.data = pdata; + pinfo.size_data = sizeof(*pdata); + + glue->musb_pdev = platform_device_register_full(&pinfo); + if (IS_ERR(glue->musb_pdev)) { + ret = PTR_ERR(glue->musb_pdev); + dev_err(dev, "failed to register musb device: %d\n", ret); + goto err_device_register; + } + + return 0; + +err_device_register: + mtk_musb_clks_disable(glue); +err_enable_clk: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +err_unregister_usb_phy: + usb_phy_generic_unregister(glue->usb_phy); + return ret; +} + +static int mtk_musb_remove(struct platform_device *pdev) +{ + struct mtk_glue *glue = platform_get_drvdata(pdev); + struct platform_device *usb_phy = glue->usb_phy; + + platform_device_unregister(glue->musb_pdev); + usb_phy_generic_unregister(usb_phy); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id mtk_musb_match[] = { + {.compatible = "mediatek,mtk-musb",}, + {}, +}; +MODULE_DEVICE_TABLE(of, mtk_musb_match); +#endif + +static struct platform_driver mtk_musb_driver = { + .probe = mtk_musb_probe, + .remove = mtk_musb_remove, + .driver = { + .name = "musb-mtk", + .of_match_table = of_match_ptr(mtk_musb_match), + }, +}; + +module_platform_driver(mtk_musb_driver); + +MODULE_DESCRIPTION("MediaTek MUSB Glue Layer"); +MODULE_AUTHOR("Min Guo "); +MODULE_LICENSE("GPL v2"); -- 2.24.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel