From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chanwoo Choi Subject: Re: [v13.1 PATCH 2/5] phy: Add USB Type-C PHY driver for rk3399 Date: Tue, 23 Aug 2016 14:44:54 +0900 Message-ID: <57BBE2D6.8050102@samsung.com> References: <1471928576-12941-1-git-send-email-zyw@rock-chips.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-reply-to: <1471928576-12941-1-git-send-email-zyw-TNX95d0MmH7DzftRWevZcw@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+glpar-linux-rockchip=m.gmane.org-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org To: Chris Zhong , groeck-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org, =?UTF-8?B?SGVpa28=?= =?UTF-8?B?IFN0w7xibmVy?= , kishon-l0cyMroinI0@public.gmane.org Cc: dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org, yzq-TNX95d0MmH7DzftRWevZcw@public.gmane.org, briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, tfiga-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org, kever.yang-TNX95d0MmH7DzftRWevZcw@public.gmane.org, linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, "cpgs (cpgs-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org)" , wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org, groeck-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org, marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org List-Id: linux-rockchip.vger.kernel.org SGkgQ2hyaXMsCgpUaGUgbmFtZSBvZiAnU3VwZXJTcGVlZCcgcHJvcGVydHkgaXMgY2hhbmdlZApm cm9tIEVYVENPTl9QUk9QX1VTQl9TVVBFUlNQRUVEIHRvIEVYVENPTl9QUk9QX1VTQl9TUy4KClRo ZSBuYW1lIGNoYW5nZSB3YXMgZGlzY3Vzc2VkIG9uIG1haWwgdGhyZWFkWzFdLgoKQWxzbywgdGhp cyBkcml2ZXIgZGVwZW5kIG9uIHRoZSBleHRjb24gZ2l0IHJlcG9zaXRvcnkuClNvLCBJIGNyZWF0 ZWQgdGhlIGltbXV0YWJsZSBicmFuY2goaWItZXh0Y29uLXBoeS00LjkpWzJdIGZvciBwaHkgZnJh bWV3b3JrCnRvIHByZXZlbnQgdGhlIGJ1aWxkIGVycm9yIGJlZm9yZSBtZXJnaW5nIHRoZSBMaW51 cyBnaXQgcmVwb3NpdG9yeS4KClsxXSBodHRwczovL2xrbWwub3JnL2xrbWwvMjAxNi84LzE3LzYy MgpbMl0gZ2l0Oi8vZ2l0Lmtlcm5lbC5vcmcvcHViL3NjbS9saW51eC9rZXJuZWwvZ2l0L2NoYW53 b28vZXh0Y29uLmdpdCBpYi1leHRjb24tcGh5LTQuOQoKUmVnYXJkcywKQ2hhbndvbyBDaG9pCgpP biAyMDE264WEIDA47JuUIDIz7J28IDE0OjAyLCBDaHJpcyBaaG9uZyB3cm90ZToKPiBBZGQgYSBQ SFkgcHJvdmlkZXIgZHJpdmVyIGZvciB0aGUgcmszMzk5IFNvQyBUeXBlLWMgUEhZLiBUaGUgVVNC Cj4gVHlwZS1DIFBIWSBpcyBkZXNpZ25lZCB0byBzdXBwb3J0IHRoZSBVU0IzIGFuZCBEUCBhcHBs aWNhdGlvbnMuCj4gVGhlIFVTQjMgb3BlcmF0ZXMgaW4gU3VwZXJTcGVlZCBtb2RlIGFuZCB0aGUg RFAgY2FuIG9wZXJhdGUgYXQgUkJSLAo+IEhCUiBhbmQgSEJSMiBkYXRhIHJhdGVzLiBUaGlzIGRy aXZlciBjcmVhdGUgMiBQSFkgZGV2aWNlcyBzZXBhcmF0ZWx5Cj4gZm9yIFVTQjMgYW5kIERpc3Bs eVBvcnQsIGFuZCByZWdpc3RlcnMgdGhlbSB1bmRlciB0aGUgY2hpbGQgbm9kZS4KPiAKPiBTaWdu ZWQtb2ZmLWJ5OiBDaHJpcyBaaG9uZyA8enl3QHJvY2stY2hpcHMuY29tPgo+IFNpZ25lZC1vZmYt Ynk6IEtldmVyIFlhbmcgPGtldmVyLnlhbmdAcm9jay1jaGlwcy5jb20+Cj4gUmV2aWV3ZWQtYnk6 IEd1ZW50ZXIgUm9lY2sgPGdyb2Vja0BjaHJvbWl1bS5vcmc+Cj4gVGVzdGVkLWJ5OiBHdWVudGVy IFJvZWNrIDxncm9lY2tAY2hyb21pdW0ub3JnPgo+IAo+IC0tLQo+IAo+IENoYW5nZXMgaW4gdjEz LjE6Cj4gLSBhZGQgc29tZSBkZXNjcmlwdGlvbiBpbiBmcm9udCBvZiBkcml2ZXIKPiAtIGNoYW5n ZSBuYW1lIG9mIHVzYiB0byB1c2IzCj4gLSBhZGQgYSBVU0IzIFJYIHJlZ2lzdGVyIGNvbmZpZ3Vy YXRpb24KPiAKPiBDaGFuZ2VzIGluIHYxMzoKPiAtIGRvIG5vdCByZXR1cm4gZXJyIGlmIG5vdGhp bmcgY29ubmVjdGVkIHdpdGggVHlwZS1DLCB3aGVuIHVzYiBwaHkgcG93ZXIgb24sCj4gICBzaW5j ZSB0aGUgVVNCIGNvcmUgZHJpdmVyIHdpbGwgY2FsbCBwaHkgcG93ZXIgd2l0aG91dCBVU0IzIGRl dmljZSBjb25uZWN0ZWQuCj4gCj4gQ2hhbmdlcyBpbiB2MTI6Cj4gLSBlbmFibGUgRFArVVNCMyBt b2RlLCBvbmx5IHdoZW4gRVhUQ09OX1BST1BfVVNCX1NVUEVSU1BFRUQgZXF1YWwgMQo+ICAgYW5k IERQIGlzIGF0dGFjaGVkCj4gCj4gQ2hhbmdlcyBpbiB2MTE6Cj4gLSBtYWtlIGEgY2xlYXJlciBk ZW1hcmNhdGlvbiBiZXR3ZWVuIHVzYiBwaHkgYW5kIGRwIHBoeS4KPiAKPiBDaGFuZ2VzIGluIHYx MDoKPiAtIGRvIG5vdCBjb250cm9sIGRwIHNlbGVjdCBhbmQgaHBkIGNvbmZpZyBpbiBwaHkgZHJp dmVyCj4gCj4gQ2hhbmdlcyBpbiB2OToKPiAtIHRoZSBuZXdfbW9kZSBzaG91bGQgYmUgaW50IG5v dCB1OAo+IC0gbW92ZSBtdXRleF9sb2NrKCZ0Y3BoeS0+bG9jayk7IHRvIGVhcmxpZXIgcGxhY2Uu IGluCj4gICByb2NrY2hpcF91c2IzX3BoeV9wb3dlcl9vZmYKPiAtIGJldHRlciBtdXRleCBsb2Nr IGZvciBwaHkgbW9kZSBhbmQgZmxpcAo+IC0gc3BsaXQgdGhlIFR5cGUtQyBQSFkgaW50byB0d28g UEhZczogVVNCMyBhbmQgRFAKPiAKPiBDaGFuZ2VzIGluIHY4Ogo+IC0gc2V0IHRoZSBkZWZhdWx0 IGNhYmxlIGlkIHRvIEVYVENPTl9VU0JfSE9TVAo+IC0gb3B0aW1pemF0aW9uIEVycm9yIGxvZwo+ IAo+IENoYW5nZXMgaW4gdjc6Cj4gLSBzdXBwb3J0IG5ldyBBUEkgb2YgZXh0Y29uCj4gCj4gQ2hh bmdlcyBpbiB2NjoKPiAtIGRlbGV0ZSB0aGUgc3VwcG9ydCBvZiBQSU5fQVNTSUdOX0EvQgo+IC0g c2V0IHRoZSBkZWZhdWx0IG1vZGUgdG8gTU9ERV9ERlBfVVNCCj4gLSBkaXNhYmxlIERQIFBMTCBh dCBVU0IzIG9ubHkgbW9kZQo+IAo+IENoYW5nZXMgaW4gdjU6Cj4gLSBzdXBwb3J0IGdldCBwcm9w ZXJ0eSBmcm9tIGV4dGNvbgo+IC0gcmVtb3ZlIFBJTiBBU1NJR04gQS9CIHN1cHBvcnQKPiAKPiBD aGFuZ2VzIGluIHY0Ogo+IC0gc2VsZWN0IEVYVENPTgo+IC0gdXNlIHBoeSBmcmFtZXdvcmsgdG8g Y29udHJvbCB0aGUgVVNCMyBhbmQgRFAgZnVuY3Rpb24KPiAtIHJlbmFtZSBQSU5fTUFQXyB0byBQ SU5fQVNTSUdOXwo+IAo+IENoYW5nZXMgaW4gdjM6Cj4gLSByZW1vdmUgdGhlIHBoeSBmcmFtZXdv cmsoS2lzaG9uIFZpamF5IEFicmFoYW0gSSkKPiAtIGFkZCBwYXJlbnRoZXNlcyBhcm91bmQgdGhl IG1hY3JvCj4gLSB1c2UgYSBzaW5nbGUgc3BhY2UgYmV0d2VlbiB0eXBlIGFuZCBuYW1lCj4gLSBh ZGQgc3BhY2VzIGFmdGVyIG9wZW5pbmcgYW5kIGJlZm9yZSBjbG9zaW5nIGJyYWNlcy4KPiAtIHVz ZSB1MTYgZm9yIHJlZ2lzdGVyIHZhbHVlCj4gLSByZW1vdmUgdHlwZS1jIHBoeSBoZWFkZXIgZmls ZQo+IC0gQ29kaW5nU3R5bGUgb3B0aW1pemF0aW9uCj4gLSB1c2Ugc29tZSBjYWJsZSBleHRjb24g dG8gZ2V0IHR5cGUtYyBwb3J0IGluZm9ybWF0aW9uCj4gLSBhZGQgYSBleHRjb24gdG8gbm90aWZ5 IERpc3BsYXkgUG9ydAo+IAo+IENoYW5nZXMgaW4gdjI6Cj4gLSBzZWxlY3QgUkVTRVRfQ09OVFJP TExFUgo+IC0gYWxwaGFiZXRpYyBvcmRlcgo+IC0gbW9kaWZ5IHNvbWUgc3BlbGxpbmcgbWlzdGFr ZXMKPiAtIG1ha2UgbW9kZSBjbGVhbmVyCj4gLSB1c2UgYm9vbCBmb3IgZW5hYmxlL2Rpc2FibGUK PiAtIGNoZWNrIGFsbCBvZiB0aGUgcmV0dXJuIHZhbHVlCj4gLSByZXR1cm4gYSBiZXR0ZXIgZXJy IG51bWJlcgo+IC0gdXNlIG1vcmUgcmVhZHhfcG9sbF90aW1lb3V0KCkKPiAtIGNsa19kaXNhYmxl X3VucHJlcGFyZSh0Y3BoeS0+Y2xrX3JlZik7Cj4gLSByZW1vdmUgdW51c2UgZnVuY3Rpb25zLCBy b2NrY2hpcF90eXBlY19waHlfcG93ZXJfb24vb2ZmCj4gLSByZW1vdmUgdW5uZWNlc3NhcnkgdHlw ZWNhc3QgZnJvbSB2b2lkICoKPiAtIHVzZSBkdHMgbm9kZSB0byBkaXN0aW5ndWlzaCBiZXR3ZWVu IHBoeXMuCj4gCj4gQ2hhbmdlcyBpbiB2MToKPiAtIHVwZGF0ZSB0aGUgbGljZW5jZSBub3RlCj4g LSBpbml0IGNvcmUgY2xvY2sgdG8gNTBNSHoKPiAtIHVzZSBleHRjb24gQVBJCj4gLSByZW1vdmUg dW51c2VkIGdsb2JhbAo+IC0gYWRkIHNvbWUgY29tbWVudHMgZm9yIG1hZ2ljIG51bQo+IC0gY2hh bmdlIHVzbGVlcF9yYW5nZSgxMDAwLCAyMDAwKSB0b3VzbGVlcF9yYW5nZSgxMDAwLCAxMDUwKQo+ IC0gcmVtb3ZlIF9fZnVuY19fIGZyb20gZGV2X2Vycgo+IC0gcmV0dXJuIGVyciBudW1iZXIgd2hl biBnZXQgY2xrIGZhaWxlZAo+IC0gcmVtb3ZlIEFERFJfQURKIGRlZmluZQo+IC0gdXNlIGRldm1f Y2xrX2dldCgmcGRldi0+ZGV2LCAidGNwZGNvcmUiKQo+IAo+ICBkcml2ZXJzL3BoeS9LY29uZmln ICAgICAgICAgICAgICB8ICAgIDkgKwo+ICBkcml2ZXJzL3BoeS9NYWtlZmlsZSAgICAgICAgICAg ICB8ICAgIDEgKwo+ICBkcml2ZXJzL3BoeS9waHktcm9ja2NoaXAtdHlwZWMuYyB8IDEwMTMgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgMyBmaWxlcyBjaGFuZ2VkLCAx MDIzIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvcGh5L3BoeS1y b2NrY2hpcC10eXBlYy5jCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGh5L0tjb25maWcgYi9k cml2ZXJzL3BoeS9LY29uZmlnCj4gaW5kZXggNDJmM2UzMC4uYzc3NWZkNyAxMDA2NDQKPiAtLS0g YS9kcml2ZXJzL3BoeS9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9waHkvS2NvbmZpZwo+IEBAIC0z NDgsNiArMzQ4LDE1IEBAIGNvbmZpZyBQSFlfUk9DS0NISVBfUENJRQo+ICAJaGVscAo+ICAJICBF bmFibGUgdGhpcyB0byBzdXBwb3J0IHRoZSBSb2NrY2hpcCBQQ0llIFBIWS4KPiAgCj4gK2NvbmZp ZyBQSFlfUk9DS0NISVBfVFlQRUMKPiArCXRyaXN0YXRlICJSb2NrY2hpcCBUWVBFQyBQSFkgRHJp dmVyIgo+ICsJZGVwZW5kcyBvbiBPRiAmJiAoQVJDSF9ST0NLQ0hJUCB8fCBDT01QSUxFX1RFU1Qp Cj4gKwlzZWxlY3QgRVhUQ09OCj4gKwlzZWxlY3QgR0VORVJJQ19QSFkKPiArCXNlbGVjdCBSRVNF VF9DT05UUk9MTEVSCj4gKwloZWxwCj4gKwkgIEVuYWJsZSB0aGlzIHRvIHN1cHBvcnQgdGhlIFJv Y2tjaGlwIFVTQiBUWVBFQyBQSFkuCj4gKwo+ICBjb25maWcgUEhZX1NUX1NQRUFSMTMxMF9NSVBI WQo+ICAJdHJpc3RhdGUgIlNUIFNQRUFSMTMxMC1NSVBIWSBkcml2ZXIiCj4gIAlzZWxlY3QgR0VO RVJJQ19QSFkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9waHkvTWFrZWZpbGUgYi9kcml2ZXJzL3Bo eS9NYWtlZmlsZQo+IGluZGV4IGZiYjkxZTcuLjVkNThiNjMgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVy cy9waHkvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL3BoeS9NYWtlZmlsZQo+IEBAIC0zOSw2ICsz OSw3IEBAIG9iai0kKENPTkZJR19QSFlfUk9DS0NISVBfSU5OT19VU0IyKQkrPSBwaHktcm9ja2No aXAtaW5uby11c2IyLm8KPiAgb2JqLSQoQ09ORklHX1BIWV9ST0NLQ0hJUF9FTU1DKSArPSBwaHkt cm9ja2NoaXAtZW1tYy5vCj4gIG9iai0kKENPTkZJR19QSFlfUk9DS0NISVBfUENJRSkgKz0gcGh5 LXJvY2tjaGlwLXBjaWUubwo+ICBvYmotJChDT05GSUdfUEhZX1JPQ0tDSElQX0RQKQkJKz0gcGh5 LXJvY2tjaGlwLWRwLm8KPiArb2JqLSQoQ09ORklHX1BIWV9ST0NLQ0hJUF9UWVBFQykgKz0gcGh5 LXJvY2tjaGlwLXR5cGVjLm8KPiAgb2JqLSQoQ09ORklHX1BIWV9RQ09NX0lQUTgwNlhfU0FUQSkJ Kz0gcGh5LXFjb20taXBxODA2eC1zYXRhLm8KPiAgb2JqLSQoQ09ORklHX1BIWV9TVF9TUEVBUjEz MTBfTUlQSFkpCSs9IHBoeS1zcGVhcjEzMTAtbWlwaHkubwo+ICBvYmotJChDT05GSUdfUEhZX1NU X1NQRUFSMTM0MF9NSVBIWSkJKz0gcGh5LXNwZWFyMTM0MC1taXBoeS5vCj4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvcGh5L3BoeS1yb2NrY2hpcC10eXBlYy5jIGIvZHJpdmVycy9waHkvcGh5LXJvY2tj aGlwLXR5cGVjLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLmZmZjFi MjcKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9waHkvcGh5LXJvY2tjaGlwLXR5cGVj LmMKPiBAQCAtMCwwICsxLDEwMTMgQEAKPiArLyoKPiArICogQ29weXJpZ2h0IChDKSBGdXpob3Ug Um9ja2NoaXAgRWxlY3Ryb25pY3MgQ28uTHRkCj4gKyAqIEF1dGhvcjogQ2hyaXMgWmhvbmcgPHp5 d0Byb2NrLWNoaXBzLmNvbT4KPiArICogICAgICAgICBLZXZlciBZYW5nIDxrZXZlci55YW5nQHJv Y2stY2hpcHMuY29tPgo+ICsgKgo+ICsgKiBUaGlzIHNvZnR3YXJlIGlzIGxpY2Vuc2VkIHVuZGVy IHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljCj4gKyAqIExpY2Vuc2UgdmVyc2lv biAyLCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgYW5kCj4g KyAqIG1heSBiZSBjb3BpZWQsIGRpc3RyaWJ1dGVkLCBhbmQgbW9kaWZpZWQgdW5kZXIgdGhvc2Ug dGVybXMuCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7 IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFRo ZSBST0NLQ0hJUCBUeXBlLUMgUEhZIGhhcyB0d28gUExMIGNsb2Nrcy4gVGhlIGZpcnN0IFBMTCBj bG9jawo+ICsgKiBpcyB1c2VkIGZvciBVU0IzLCB0aGUgc2Vjb25kIFBMTCBjbG9jayBpcyB1c2Vk IGZvciBEUC4gVGhpcyBUeXBlLUMgUEhZIGhhcwo+ICsgKiAzIHdvcmtpbmcgbW9kZXM6IFVTQjMg b25seSBtb2RlLCBEUCBvbmx5IG1vZGUsIGFuZCBVU0IzK0RQIG1vZGUuCj4gKyAqIEF0IFVTQjMg b25seSBtb2RlLCBib3RoIFBMTCBjbG9ja3MgbmVlZCB0byBiZSBpbml0aWFsaXplZCwgdGhpcyBh bGxvd3MgdGhlCj4gKyAqIFBIWSB0byBzd2l0Y2ggbW9kZSBiZXR3ZWVuIFVTQjMgYW5kIFVTQjMr RFAsIHdpdGhvdXQgZGlzY29ubmVjdGluZyB0aGUgVVNCCj4gKyAqIGRldmljZS4KPiArICogSW4g VGhlIERQIG9ubHkgbW9kZSwgb25seSB0aGUgRFAgUExMIG5lZWRzIHRvIGJlIHBvd2VyZWQgb24s IGFuZCB0aGUgNCBsYW5lcwo+ICsgKiBhcmUgYWxsIHVzZWQgZm9yIERQLgo+ICsgKgo+ICsgKiBU aGlzIGRyaXZlciBnZXRzIGV4dGNvbiBjYWJsZSBzdGF0ZSBhbmQgcHJvcGVydHksIHRoZW4gZGVj aWRlcyB3aGljaCBtb2RlIHRvCj4gKyAqIHNlbGVjdDoKPiArICoKPiArICogMS4gVVNCMyBvbmx5 IG1vZGU6Cj4gKyAqICAgIEVYVENPTl9VU0Igb3IgRVhUQ09OX1VTQl9IT1NUIHN0YXRlIGlzIHRy dWUsIGFuZAo+ICsgKiAgICBFWFRDT05fUFJPUF9VU0JfU1VQRVJTUEVFRCBwcm9wZXJ0eSBpcyB0 cnVlLgo+ICsgKiAgICBFWFRDT05fRElTUF9EUCBzdGF0ZSBpcyBmYWxzZS4KPiArICoKPiArICog Mi4gRFAgb25seSBtb2RlOgo+ICsgKiAgICBFWFRDT05fRElTUF9EUCBzdGF0ZSBpcyB0cnVlLCBh bmQKPiArICogICAgRVhUQ09OX1BST1BfVVNCX1NVUEVSU1BFRUQgcHJvcGVydHkgaXMgZmFsc2Uu Cj4gKyAqICAgIElmIEVYVENPTl9VU0JfSE9TVCBzdGF0ZSBpcyB0cnVlLCBpdCBpcyBEUCArIFVT QjIgbW9kZSwgc2luY2UgdGhlIFVTQjIgcGh5Cj4gKyAqICAgIGlzIGEgc2VwYXJhdGUgcGh5LCBz byB0aGlzIGNhc2UgaXMgc3RpbGwgRFAgb25seSBtb2RlLgo+ICsgKgo+ICsgKiAzLiBVU0IzK0RQ IG1vZGU6Cj4gKyAqICAgIEVYVENPTl9VU0JfSE9TVCBhbmQgRVhUQ09OX0RJU1BfRFAgYXJlIGJv dGggdHJ1ZSwgYW5kCj4gKyAqICAgIEVYVENPTl9QUk9QX1VTQl9TVVBFUlNQRUVEIHByb3BlcnR5 IGlzIHRydWUuCj4gKyAqCj4gKyAqIFRoaXMgVHlwZS1DIFBIWSBkcml2ZXIgc3VwcG9ydHMgbm9y bWFsIGFuZCBmbGlwIG9yaWVudGF0aW9uLiBUaGUgb3JpZW50YXRpb24KPiArICogaXMgcmVwb3J0 ZWQgYnkgdGhlIEVYVENPTl9QUk9QX1VTQl9UWVBFQ19QT0xBUklUWSBwcm9wZXJ0eTogdHJ1ZSBp cyBmbGlwCj4gKyAqIG9yaWVudGF0aW9uLCBmYWxzZSBpcyBub3JtYWwgb3JpZW50YXRpb24uCj4g KyAqCj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvY2xrLXByb3ZpZGVyLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+ICsjaW5jbHVk ZSA8bGludXgvZXh0Y29uLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+ICsjaW5jbHVkZSA8 bGludXgvaW9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KPiArI2luY2x1ZGUg PGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KPiArI2luY2x1ZGUg PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9hZGRyZXNzLmg+Cj4gKyNpbmNsdWRl IDxsaW51eC9vZl9wbGF0Zm9ybS5oPgo+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNl Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3Jlc2V0 Lmg+Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvbWZkL3N5c2Nvbi5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvcGh5L3BoeS5oPgo+ICsKPiArI2RlZmluZSBDTU5fU1NNX0JBTkRHQVAJCQkoMHgyMSA8PCAy KQo+ICsjZGVmaW5lIENNTl9TU01fQklBUwkJCSgweDIyIDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BM TFNNMF9QTExFTgkJKDB4MjkgPDwgMikKPiArI2RlZmluZSBDTU5fUExMU00wX1BMTFBSRQkJKDB4 MmEgPDwgMikKPiArI2RlZmluZSBDTU5fUExMU00wX1BMTFZSRUYJCSgweDJiIDw8IDIpCj4gKyNk ZWZpbmUgQ01OX1BMTFNNMF9QTExMT0NLCQkoMHgyYyA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTExT TTFfUExMRU4JCSgweDMxIDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTFNNMV9QTExQUkUJCSgweDMy IDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTFNNMV9QTExWUkVGCQkoMHgzMyA8PCAyKQo+ICsjZGVm aW5lIENNTl9QTExTTTFfUExMTE9DSwkJKDB4MzQgPDwgMikKPiArI2RlZmluZSBDTU5fUExMU00x X1VTRVJfREVGX0NUUkwJKDB4MzcgPDwgMikKPiArI2RlZmluZSBDTU5fSUNBTF9PVlJECQkJKDB4 YzEgPDwgMikKPiArI2RlZmluZSBDTU5fUExMMF9WQ09DQUxfT1ZSRAkJKDB4ODMgPDwgMikKPiAr I2RlZmluZSBDTU5fUExMMF9WQ09DQUxfSU5JVAkJKDB4ODQgPDwgMikKPiArI2RlZmluZSBDTU5f UExMMF9WQ09DQUxfSVRFUgkJKDB4ODUgPDwgMikKPiArI2RlZmluZSBDTU5fUExMMF9MT0NLX1JF RkNOVF9TVEFSVAkoMHg5MCA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwwX0xPQ0tfUExMQ05UX1NU QVJUCSgweDkyIDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTDBfTE9DS19QTExDTlRfVEhSCSgweDkz IDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTDBfSU5URElWCQkJKDB4OTQgPDwgMikKPiArI2RlZmlu ZSBDTU5fUExMMF9GUkFDRElWCQkoMHg5NSA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwwX0hJR0hf VEhSCQkoMHg5NiA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwwX0RTTV9ESUFHCQkoMHg5NyA8PCAy KQo+ICsjZGVmaW5lIENNTl9QTEwwX1NTX0NUUkwxCQkoMHg5OCA8PCAyKQo+ICsjZGVmaW5lIENN Tl9QTEwwX1NTX0NUUkwyCQkoMHg5OSA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwxX1ZDT0NBTF9T VEFSVAkJKDB4YTEgPDwgMikKPiArI2RlZmluZSBDTU5fUExMMV9WQ09DQUxfT1ZSRAkJKDB4YTMg PDwgMikKPiArI2RlZmluZSBDTU5fUExMMV9WQ09DQUxfSU5JVAkJKDB4YTQgPDwgMikKPiArI2Rl ZmluZSBDTU5fUExMMV9WQ09DQUxfSVRFUgkJKDB4YTUgPDwgMikKPiArI2RlZmluZSBDTU5fUExM MV9MT0NLX1JFRkNOVF9TVEFSVAkoMHhiMCA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwxX0xPQ0tf UExMQ05UX1NUQVJUCSgweGIyIDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTDFfTE9DS19QTExDTlRf VEhSCSgweGIzIDw8IDIpCj4gKyNkZWZpbmUgQ01OX1BMTDFfSU5URElWCQkJKDB4YjQgPDwgMikK PiArI2RlZmluZSBDTU5fUExMMV9GUkFDRElWCQkoMHhiNSA8PCAyKQo+ICsjZGVmaW5lIENNTl9Q TEwxX0hJR0hfVEhSCQkoMHhiNiA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwxX0RTTV9ESUFHCQko MHhiNyA8PCAyKQo+ICsjZGVmaW5lIENNTl9QTEwxX1NTX0NUUkwxCQkoMHhiOCA8PCAyKQo+ICsj ZGVmaW5lIENNTl9QTEwxX1NTX0NUUkwyCQkoMHhiOSA8PCAyKQo+ICsjZGVmaW5lIENNTl9SWENB TF9PVlJECQkJKDB4ZDEgPDwgMikKPiArI2RlZmluZSBDTU5fVFhQVUNBTF9DVFJMCQkoMHhlMCA8 PCAyKQo+ICsjZGVmaW5lIENNTl9UWFBVQ0FMX09WUkQJCSgweGUxIDw8IDIpCj4gKyNkZWZpbmUg Q01OX1RYUERDQUxfT1ZSRAkJKDB4ZjEgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwwX0ZC SF9PVlJECQkoMHgxYzAgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwwX0ZCTF9PVlJECQko MHgxYzEgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwwX09WUkQJCSgweDFjMiA8PCAyKQo+ ICsjZGVmaW5lIENNTl9ESUFHX1BMTDBfVjJJX1RVTkUJCSgweDFjNSA8PCAyKQo+ICsjZGVmaW5l IENNTl9ESUFHX1BMTDBfQ1BfVFVORQkJKDB4MWM2IDw8IDIpCj4gKyNkZWZpbmUgQ01OX0RJQUdf UExMMF9MRl9QUk9HCQkoMHgxYzcgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX0ZCSF9P VlJECQkoMHgxZDAgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX0ZCTF9PVlJECQkoMHgx ZDEgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX09WUkQJCSgweDFkMiA8PCAyKQo+ICsj ZGVmaW5lIENNTl9ESUFHX1BMTDFfVjJJX1RVTkUJCSgweDFkNSA8PCAyKQo+ICsjZGVmaW5lIENN Tl9ESUFHX1BMTDFfQ1BfVFVORQkJKDB4MWQ2IDw8IDIpCj4gKyNkZWZpbmUgQ01OX0RJQUdfUExM MV9MRl9QUk9HCQkoMHgxZDcgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX1BUQVRJU19U VU5FMQkoMHgxZDggPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX1BUQVRJU19UVU5FMgko MHgxZDkgPDwgMikKPiArI2RlZmluZSBDTU5fRElBR19QTEwxX0lOQ0xLX0NUUkwJKDB4MWRhIDw8 IDIpCj4gKyNkZWZpbmUgQ01OX0RJQUdfSFNDTEtfU0VMCQkoMHgxZTAgPDwgMikKPiArCj4gKyNk ZWZpbmUgWENWUl9QU01fUkNUUkwobikJCSgoMHg0MDAxIHwgKChuKSA8PCA5KSkgPDwgMikKPiAr I2RlZmluZSBYQ1ZSX1BTTV9DQUxfVE1SKG4pCQkoKDB4NDAwMiB8ICgobikgPDwgOSkpIDw8IDIp Cj4gKyNkZWZpbmUgWENWUl9QU01fQTBJTl9UTVIobikJCSgoMHg0MDAzIHwgKChuKSA8PCA5KSkg PDwgMikKPiArI2RlZmluZSBUWF9UWENDX0NBTF9TQ0xSX01VTFQobikJKCgweDQwNDcgfCAoKG4p IDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX1RYQ0NfQ1BPU1RfTVVMVF8wMChuKQkoKDB4NDA0 YyB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfVFhDQ19DUE9TVF9NVUxUXzAxKG4p CSgoMHg0MDRkIHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBUWF9UWENDX0NQT1NUX01V TFRfMTAobikJKCgweDQwNGUgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX1RYQ0Nf Q1BPU1RfTVVMVF8xMShuKQkoKDB4NDA0ZiB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUg VFhfVFhDQ19NR05GU19NVUxUXzAwMChuKQkoKDB4NDA1MCB8ICgobikgPDwgOSkpIDw8IDIpCj4g KyNkZWZpbmUgVFhfVFhDQ19NR05GU19NVUxUXzAwMShuKQkoKDB4NDA1MSB8ICgobikgPDwgOSkp IDw8IDIpCj4gKyNkZWZpbmUgVFhfVFhDQ19NR05GU19NVUxUXzAxMChuKQkoKDB4NDA1MiB8ICgo bikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfVFhDQ19NR05GU19NVUxUXzAxMShuKQkoKDB4 NDA1MyB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfVFhDQ19NR05GU19NVUxUXzEw MChuKQkoKDB4NDA1NCB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfVFhDQ19NR05G U19NVUxUXzEwMShuKQkoKDB4NDA1NSB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhf VFhDQ19NR05GU19NVUxUXzExMChuKQkoKDB4NDA1NiB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNk ZWZpbmUgVFhfVFhDQ19NR05GU19NVUxUXzExMShuKQkoKDB4NDA1NyB8ICgobikgPDwgOSkpIDw8 IDIpCj4gKyNkZWZpbmUgWENWUl9ESUFHX1BMTERSQ19DVFJMKG4pCSgoMHg0MGUwIHwgKChuKSA8 PCA5KSkgPDwgMikKPiArI2RlZmluZSBYQ1ZSX0RJQUdfQklESV9DVFJMKG4pCQkoKDB4NDBlOCB8 ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgWENWUl9ESUFHX0xBTkVfRkNNX0VOX01HTihu KQkoKDB4NDBmMiB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfUFNDX0EwKG4pCQkJ KCgweDQxMDAgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX1BTQ19BMShuKQkJCSgo MHg0MTAxIHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBUWF9QU0NfQTIobikJCQkoKDB4 NDEwMiB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfUFNDX0EzKG4pCQkJKCgweDQx MDMgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX1JDVkRFVF9DVFJMKG4pCQkoKDB4 NDEyMCB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfUkNWREVUX0VOX1RNUihuKQkJ KCgweDQxMjIgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX1JDVkRFVF9TVF9UTVIo bikJCSgoMHg0MTIzIHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBUWF9ESUFHX1RYX0RS VihuKQkJKCgweDQxZTEgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFRYX0RJQUdfQkdS RUZfUFJFRFJWX0RFTEFZCSgweDQxZTcgPDwgMikKPiArI2RlZmluZSBUWF9BTkFfQ1RSTF9SRUdf MQkJKDB4NTAyMCA8PCAyKQo+ICsjZGVmaW5lIFRYX0FOQV9DVFJMX1JFR18yCQkoMHg1MDIxIDw8 IDIpCj4gKyNkZWZpbmUgVFhEQV9DT0VGRl9DQUxDX0NUUkwJCSgweDUwMjIgPDwgMikKPiArI2Rl ZmluZSBUWF9ESUdfQ1RSTF9SRUdfMgkJKDB4NTAyNCA8PCAyKQo+ICsjZGVmaW5lIFRYREFfQ1lB X0FVWERBX0NZQQkJKDB4NTAyNSA8PCAyKQo+ICsjZGVmaW5lIFRYX0FOQV9DVFJMX1JFR18zCQko MHg1MDI2IDw8IDIpCj4gKyNkZWZpbmUgVFhfQU5BX0NUUkxfUkVHXzQJCSgweDUwMjcgPDwgMikK PiArI2RlZmluZSBUWF9BTkFfQ1RSTF9SRUdfNQkJKDB4NTAyOSA8PCAyKQo+ICsKPiArI2RlZmlu ZSBSWF9QU0NfQTAobikJCQkoKDB4ODAwMCB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUg UlhfUFNDX0ExKG4pCQkJKCgweDgwMDEgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFJY X1BTQ19BMihuKQkJCSgoMHg4MDAyIHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBSWF9Q U0NfQTMobikJCQkoKDB4ODAwMyB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgUlhfUFND X0NBTChuKQkJCSgoMHg4MDA2IHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBSWF9QU0Nf UkRZKG4pCQkJKCgweDgwMDcgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFJYX0lRUElf SUxMX0NBTF9PVlJECQkoMHg4MDIzIDw8IDIpCj4gKyNkZWZpbmUgUlhfRVBJX0lMTF9DQUxfT1ZS RAkJKDB4ODAzMyA8PCAyKQo+ICsjZGVmaW5lIFJYX1NEQ0FMMF9PVlJECQkJKDB4ODA0MSA8PCAy KQo+ICsjZGVmaW5lIFJYX1NEQ0FMMV9PVlJECQkJKDB4ODA0OSA8PCAyKQo+ICsjZGVmaW5lIFJY X1NMQ19JTklUCQkJKDB4ODA2ZCA8PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19SVU4JCQkoMHg4MDZl IDw8IDIpCj4gKyNkZWZpbmUgUlhfQ0RSTEZfQ05GRzIJCQkoMHg4MDgxIDw8IDIpCj4gKyNkZWZp bmUgUlhfU0lHREVUX0hMX0ZJTFRfVE1SKG4pCSgoMHg4MDkwIHwgKChuKSA8PCA5KSkgPDwgMikK PiArI2RlZmluZSBSWF9TTENfSU9QMF9PVlJECQkoMHg4MTAxIDw8IDIpCj4gKyNkZWZpbmUgUlhf U0xDX0lPUDFfT1ZSRAkJKDB4ODEwNSA8PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19RT1AwX09WUkQJ CSgweDgxMDkgPDwgMikKPiArI2RlZmluZSBSWF9TTENfUU9QMV9PVlJECQkoMHg4MTBkIDw8IDIp Cj4gKyNkZWZpbmUgUlhfU0xDX0VPUDBfT1ZSRAkJKDB4ODExMSA8PCAyKQo+ICsjZGVmaW5lIFJY X1NMQ19FT1AxX09WUkQJCSgweDgxMTUgPDwgMikKPiArI2RlZmluZSBSWF9TTENfSU9OMF9PVlJE CQkoMHg4MTE5IDw8IDIpCj4gKyNkZWZpbmUgUlhfU0xDX0lPTjFfT1ZSRAkJKDB4ODExZCA8PCAy KQo+ICsjZGVmaW5lIFJYX1NMQ19RT04wX09WUkQJCSgweDgxMjEgPDwgMikKPiArI2RlZmluZSBS WF9TTENfUU9OMV9PVlJECQkoMHg4MTI1IDw8IDIpCj4gKyNkZWZpbmUgUlhfU0xDX0VPTjBfT1ZS RAkJKDB4ODEyOSA8PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19FT04xX09WUkQJCSgweDgxMmQgPDwg MikKPiArI2RlZmluZSBSWF9TTENfSUVQMF9PVlJECQkoMHg4MTMxIDw8IDIpCj4gKyNkZWZpbmUg UlhfU0xDX0lFUDFfT1ZSRAkJKDB4ODEzNSA8PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19RRVAwX09W UkQJCSgweDgxMzkgPDwgMikKPiArI2RlZmluZSBSWF9TTENfUUVQMV9PVlJECQkoMHg4MTNkIDw8 IDIpCj4gKyNkZWZpbmUgUlhfU0xDX0VFUDBfT1ZSRAkJKDB4ODE0MSA8PCAyKQo+ICsjZGVmaW5l IFJYX1NMQ19FRVAxX09WUkQJCSgweDgxNDUgPDwgMikKPiArI2RlZmluZSBSWF9TTENfSUVOMF9P VlJECQkoMHg4MTQ5IDw8IDIpCj4gKyNkZWZpbmUgUlhfU0xDX0lFTjFfT1ZSRAkJKDB4ODE0ZCA8 PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19RRU4wX09WUkQJCSgweDgxNTEgPDwgMikKPiArI2RlZmlu ZSBSWF9TTENfUUVOMV9PVlJECQkoMHg4MTU1IDw8IDIpCj4gKyNkZWZpbmUgUlhfU0xDX0VFTjBf T1ZSRAkJKDB4ODE1OSA8PCAyKQo+ICsjZGVmaW5lIFJYX1NMQ19FRU4xX09WUkQJCSgweDgxNWQg PDwgMikKPiArI2RlZmluZSBSWF9SRUVfQ1RSTF9EQVRBX01BU0sobikJKCgweDgxYmIgfCAoKG4p IDw8IDkpKSA8PCAyKQo+ICsjZGVmaW5lIFJYX0RJQUdfU0lHREVUX1RVTkUobikJCSgoMHg4MWRj IHwgKChuKSA8PCA5KSkgPDwgMikKPiArI2RlZmluZSBSWF9ESUFHX1NDMkNfREVMQVkJCSgweDgx ZTEgPDwgMikKPiArCj4gKyNkZWZpbmUgUE1BX0xBTkVfQ0ZHCQkJKDB4YzAwMCA8PCAyKQo+ICsj ZGVmaW5lIFBJUEVfQ01OX0NUUkwxCQkJKDB4YzAwMSA8PCAyKQo+ICsjZGVmaW5lIFBJUEVfQ01O X0NUUkwyCQkJKDB4YzAwMiA8PCAyKQo+ICsjZGVmaW5lIFBJUEVfQ09NX0xPQ0tfQ0ZHMQkJKDB4 YzAwMyA8PCAyKQo+ICsjZGVmaW5lIFBJUEVfQ09NX0xPQ0tfQ0ZHMgkJKDB4YzAwNCA8PCAyKQo+ ICsjZGVmaW5lIFBJUEVfUkNWX0RFVF9JTkgJCSgweGMwMDUgPDwgMikKPiArI2RlZmluZSBEUF9N T0RFX0NUTAkJCSgweGMwMDggPDwgMikKPiArI2RlZmluZSBEUF9DTEtfQ1RMCQkJKDB4YzAwOSA8 PCAyKQo+ICsjZGVmaW5lIFNUUwkJCQkoMHhjMDBGIDw8IDIpCj4gKyNkZWZpbmUgUEhZX0lTT19D TU5fQ1RSTAkJKDB4YzAxMCA8PCAyKQo+ICsjZGVmaW5lIFBIWV9EUF9UWF9DVEwJCQkoMHhjNDA4 IDw8IDIpCj4gKyNkZWZpbmUgUE1BX0NNTl9DVFJMMQkJCSgweGM4MDAgPDwgMikKPiArI2RlZmlu ZSBQSFlfUE1BX0lTT19DTU5fQ1RSTAkJKDB4YzgxMCA8PCAyKQo+ICsjZGVmaW5lIFBIWV9JU09M QVRJT05fQ1RSTAkJKDB4YzgxZiA8PCAyKQo+ICsjZGVmaW5lIFBIWV9QTUFfSVNPX1hDVlJfQ1RS TChuKQkoKDB4Y2MxMSB8ICgobikgPDwgNikpIDw8IDIpCj4gKyNkZWZpbmUgUEhZX1BNQV9JU09f TElOS19NT0RFKG4pCSgoMHhjYzEyIHwgKChuKSA8PCA2KSkgPDwgMikKPiArI2RlZmluZSBQSFlf UE1BX0lTT19QV1JTVF9DVFJMKG4pCSgoMHhjYzEzIHwgKChuKSA8PCA2KSkgPDwgMikKPiArI2Rl ZmluZSBQSFlfUE1BX0lTT19UWF9EQVRBX0xPKG4pCSgoMHhjYzE0IHwgKChuKSA8PCA2KSkgPDwg MikKPiArI2RlZmluZSBQSFlfUE1BX0lTT19UWF9EQVRBX0hJKG4pCSgoMHhjYzE1IHwgKChuKSA8 PCA2KSkgPDwgMikKPiArI2RlZmluZSBQSFlfUE1BX0lTT19SWF9EQVRBX0xPKG4pCSgoMHhjYzE2 IHwgKChuKSA8PCA2KSkgPDwgMikKPiArI2RlZmluZSBQSFlfUE1BX0lTT19SWF9EQVRBX0hJKG4p CSgoMHhjYzE3IHwgKChuKSA8PCA2KSkgPDwgMikKPiArI2RlZmluZSBUWF9CSVNUX0NUUkwobikJ CQkoKDB4NDE0MCB8ICgobikgPDwgOSkpIDw8IDIpCj4gKyNkZWZpbmUgVFhfQklTVF9VRERXUihu KQkJKCgweDQxNDEgfCAoKG4pIDw8IDkpKSA8PCAyKQo+ICsKPiArLyoKPiArICogU2VsZWN0cyB3 aGljaCBQTEwgY2xvY2sgd2lsbCBiZSBkcml2ZW4gb24gdGhlIGFuYWxvZyBoaWdoIHNwZWVkCj4g KyAqIGNsb2NrIDA6IFBMTCAwIGRpdiAxCj4gKyAqIGNsb2NrIDE6IFBMTCAxIGRpdiAyCj4gKyAq Lwo+ICsjZGVmaW5lIENMS19QTExfQ09ORklHCQkJMFgzMAo+ICsjZGVmaW5lIENMS19QTExfTUFT SwkJCTB4MzMKPiArCj4gKyNkZWZpbmUgQ01OX1JFQURZCQkJQklUKDApCj4gKwo+ICsjZGVmaW5l IERQX1BMTF9DTE9DS19FTkFCTEUJCUJJVCgyKQo+ICsjZGVmaW5lIERQX1BMTF9FTkFCTEUJCQlC SVQoMCkKPiArI2RlZmluZSBEUF9QTExfREFUQV9SQVRFX1JCUgkJKCgyIDw8IDEyKSB8ICg0IDw8 IDgpKQo+ICsjZGVmaW5lIERQX1BMTF9EQVRBX1JBVEVfSEJSCQkoKDIgPDwgMTIpIHwgKDQgPDwg OCkpCj4gKyNkZWZpbmUgRFBfUExMX0RBVEFfUkFURV9IQlIyCQkoKDEgPDwgMTIpIHwgKDIgPDwg OCkpCj4gKwo+ICsjZGVmaW5lIERQX01PREVfQTAJCQlCSVQoNCkKPiArI2RlZmluZSBEUF9NT0RF X0EyCQkJQklUKDYpCj4gKyNkZWZpbmUgRFBfTU9ERV9FTlRFUl9BMAkJMHhjMTAxCj4gKyNkZWZp bmUgRFBfTU9ERV9FTlRFUl9BMgkJMHhjMTA0Cj4gKwo+ICsjZGVmaW5lIFBIWV9NT0RFX1NFVF9U SU1FT1VUCQkxMDAwMDAKPiArCj4gKyNkZWZpbmUgUElOX0FTU0lHTl9DX0UJCQkweDUxZDkKPiAr I2RlZmluZSBQSU5fQVNTSUdOX0RfRgkJCTB4NTEwMAo+ICsKPiArI2RlZmluZSBNT0RFX0RJU0NP Tk5FQ1QJCQkwCj4gKyNkZWZpbmUgTU9ERV9VRlBfVVNCCQkJQklUKDApCj4gKyNkZWZpbmUgTU9E RV9ERlBfVVNCCQkJQklUKDEpCj4gKyNkZWZpbmUgTU9ERV9ERlBfRFAJCQlCSVQoMikKPiArCj4g K3N0cnVjdCB1c2IzcGh5X3JlZyB7Cj4gKwl1MzIgb2Zmc2V0Owo+ICsJdTMyIGVuYWJsZV9iaXQ7 Cj4gKwl1MzIgd3JpdGVfZW5hYmxlOwo+ICt9Owo+ICsKPiArc3RydWN0IHJvY2tjaGlwX3VzYjNw aHlfcG9ydF9jZmcgewo+ICsJc3RydWN0IHVzYjNwaHlfcmVnIHR5cGVjX2Nvbm5fZGlyOwo+ICsJ c3RydWN0IHVzYjNwaHlfcmVnIHVzYjN0b3VzYjJfZW47Cj4gKwlzdHJ1Y3QgdXNiM3BoeV9yZWcg ZXh0ZXJuYWxfcHNtOwo+ICsJc3RydWN0IHVzYjNwaHlfcmVnIHBpcGVfc3RhdHVzOwo+ICt9Owo+ ICsKPiArc3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSB7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXY7 Cj4gKwl2b2lkIF9faW9tZW0gKmJhc2U7Cj4gKwlzdHJ1Y3QgZXh0Y29uX2RldiAqZXh0Y29uOwo+ ICsJc3RydWN0IHJlZ21hcCAqZ3JmX3JlZ3M7Cj4gKwlzdHJ1Y3QgY2xrICpjbGtfY29yZTsKPiAr CXN0cnVjdCBjbGsgKmNsa19yZWY7Cj4gKwlzdHJ1Y3QgcmVzZXRfY29udHJvbCAqdXBoeV9yc3Q7 Cj4gKwlzdHJ1Y3QgcmVzZXRfY29udHJvbCAqcGlwZV9yc3Q7Cj4gKwlzdHJ1Y3QgcmVzZXRfY29u dHJvbCAqdGNwaHlfcnN0Owo+ICsJc3RydWN0IHJvY2tjaGlwX3VzYjNwaHlfcG9ydF9jZmcgcG9y dF9jZmdzOwo+ICsJLyogbXV0ZXggdG8gcHJvdGVjdCBhY2Nlc3MgdG8gaW5kaXZpZHVhbCBQSFlz ICovCj4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsKPiArCj4gKwlib29sIGZsaXA7Cj4gKwl1OCBtb2Rl Owo+ICt9Owo+ICsKPiArc3RydWN0IHBoeV9yZWcgewo+ICsJdTE2IHZhbHVlOwo+ICsJdTMyIGFk ZHI7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgcGh5X3JlZyB1c2IzX3BsbF9jZmdbXSA9IHsKPiArCXsg MHhmMCwJCUNNTl9QTEwwX1ZDT0NBTF9JTklUIH0sCj4gKwl7IDB4MTgsCQlDTU5fUExMMF9WQ09D QUxfSVRFUiB9LAo+ICsJeyAweGQwLAkJQ01OX1BMTDBfSU5URElWIH0sCj4gKwl7IDB4NGE0YSwJ Q01OX1BMTDBfRlJBQ0RJViB9LAo+ICsJeyAweDM0LAkJQ01OX1BMTDBfSElHSF9USFIgfSwKPiAr CXsgMHgxZWUsCUNNTl9QTEwwX1NTX0NUUkwxIH0sCj4gKwl7IDB4N2YwMywJQ01OX1BMTDBfU1Nf Q1RSTDIgfSwKPiArCXsgMHgyMCwJCUNNTl9QTEwwX0RTTV9ESUFHIH0sCj4gKwl7IDAsCQlDTU5f RElBR19QTEwwX09WUkQgfSwKPiArCXsgMCwJCUNNTl9ESUFHX1BMTDBfRkJIX09WUkQgfSwKPiAr CXsgMCwJCUNNTl9ESUFHX1BMTDBfRkJMX09WUkQgfSwKPiArCXsgMHg3LAkJQ01OX0RJQUdfUExM MF9WMklfVFVORSB9LAo+ICsJeyAweDQ1LAkJQ01OX0RJQUdfUExMMF9DUF9UVU5FIH0sCj4gKwl7 IDB4OCwJCUNNTl9ESUFHX1BMTDBfTEZfUFJPRyB9LAo+ICt9Owo+ICsKPiArc3RydWN0IHBoeV9y ZWcgZHBfcGxsX2NmZ1tdID0gewo+ICsJeyAweGYwLAkJQ01OX1BMTDFfVkNPQ0FMX0lOSVQgfSwK PiArCXsgMHgxOCwJCUNNTl9QTEwxX1ZDT0NBTF9JVEVSIH0sCj4gKwl7IDB4MzBiOSwJQ01OX1BM TDFfVkNPQ0FMX1NUQVJUIH0sCj4gKwl7IDB4MjFjLAlDTU5fUExMMV9JTlRESVYgfSwKPiArCXsg MCwJCUNNTl9QTEwxX0ZSQUNESVYgfSwKPiArCXsgMHg1LAkJQ01OX1BMTDFfSElHSF9USFIgfSwK PiArCXsgMHgzNSwJCUNNTl9QTEwxX1NTX0NUUkwxIH0sCj4gKwl7IDB4N2YxZSwJQ01OX1BMTDFf U1NfQ1RSTDIgfSwKPiArCXsgMHgyMCwJCUNNTl9QTEwxX0RTTV9ESUFHIH0sCj4gKwl7IDAsCQlD TU5fUExMU00xX1VTRVJfREVGX0NUUkwgfSwKPiArCXsgMCwJCUNNTl9ESUFHX1BMTDFfT1ZSRCB9 LAo+ICsJeyAwLAkJQ01OX0RJQUdfUExMMV9GQkhfT1ZSRCB9LAo+ICsJeyAwLAkJQ01OX0RJQUdf UExMMV9GQkxfT1ZSRCB9LAo+ICsJeyAweDYsCQlDTU5fRElBR19QTEwxX1YySV9UVU5FIH0sCj4g Kwl7IDB4NDUsCQlDTU5fRElBR19QTEwxX0NQX1RVTkUgfSwKPiArCXsgMHg4LAkJQ01OX0RJQUdf UExMMV9MRl9QUk9HIH0sCj4gKwl7IDB4MTAwLAlDTU5fRElBR19QTEwxX1BUQVRJU19UVU5FMSB9 LAo+ICsJeyAweDcsCQlDTU5fRElBR19QTEwxX1BUQVRJU19UVU5FMiB9LAo+ICsJeyAweDQsCQlD TU5fRElBR19QTEwxX0lOQ0xLX0NUUkwgfSwKPiArfTsKPiArCj4gK3N0YXRpYyB2b2lkIHRjcGh5 X2NmZ18yNG0oc3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSAqdGNwaHkpCj4gK3sKPiArCXUzMiBp LCByZGF0YTsKPiArCj4gKwkvKgo+ICsJICogY21uX3JlZl9jbGtfc2VsID0gMywgc2VsZWN0IHRo ZSAyNE1oeiBmb3IgY2xrIHBhcmVudAo+ICsJICogY21uX3BzbV9jbGtfZGlnX2RpdiA9IDIsIHNl dCB0aGUgY2xrIGRpdmlzaW9uIHRvIDIKPiArCSAqLwo+ICsJd3JpdGVsKDB4ODMwLCB0Y3BoeS0+ YmFzZSArIFBNQV9DTU5fQ1RSTDEpOwo+ICsJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykgewo+ICsJ CS8qCj4gKwkJICogVGhlIGZvbGxvd2luZyBQSFkgY29uZmlndXJhdGlvbiBhc3N1bWVzIGEgMjQg TUh6IHJlZmVyZW5jZQo+ICsJCSAqIGNsb2NrLgo+ICsJCSAqLwo+ICsJCXdyaXRlbCgweDkwLCB0 Y3BoeS0+YmFzZSArIFhDVlJfRElBR19MQU5FX0ZDTV9FTl9NR04oaSkpOwo+ICsJCXdyaXRlbCgw eDk2MCwgdGNwaHktPmJhc2UgKyBUWF9SQ1ZERVRfRU5fVE1SKGkpKTsKPiArCQl3cml0ZWwoMHgz MCwgdGNwaHktPmJhc2UgKyBUWF9SQ1ZERVRfU1RfVE1SKGkpKTsKPiArCX0KPiArCj4gKwlyZGF0 YSA9IHJlYWRsKHRjcGh5LT5iYXNlICsgQ01OX0RJQUdfSFNDTEtfU0VMKTsKPiArCXJkYXRhICY9 IH5DTEtfUExMX01BU0s7Cj4gKwlyZGF0YSB8PSBDTEtfUExMX0NPTkZJRzsKPiArCXdyaXRlbChy ZGF0YSwgdGNwaHktPmJhc2UgKyBDTU5fRElBR19IU0NMS19TRUwpOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCB0Y3BoeV9jZmdfdXNiM19wbGwoc3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSAqdGNw aHkpCj4gK3sKPiArCXUzMiBpOwo+ICsKPiArCS8qIGxvYWQgdGhlIGNvbmZpZ3VyYXRpb24gb2Yg UExMMCAqLwo+ICsJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUodXNiM19wbGxfY2ZnKTsgaSsr KQo+ICsJCXdyaXRlbCh1c2IzX3BsbF9jZmdbaV0udmFsdWUsCj4gKwkJICAgICAgIHRjcGh5LT5i YXNlICsgdXNiM19wbGxfY2ZnW2ldLmFkZHIpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB0Y3Bo eV9jZmdfZHBfcGxsKHN0cnVjdCByb2NrY2hpcF90eXBlY19waHkgKnRjcGh5KQo+ICt7Cj4gKwl1 MzIgaTsKPiArCj4gKwkvKiBzZXQgdGhlIGRlZmF1bHQgbW9kZSB0byBSQlIgKi8KPiArCXdyaXRl bChEUF9QTExfQ0xPQ0tfRU5BQkxFIHwgRFBfUExMX0VOQUJMRSB8IERQX1BMTF9EQVRBX1JBVEVf UkJSLAo+ICsJICAgICAgIHRjcGh5LT5iYXNlICsgRFBfQ0xLX0NUTCk7Cj4gKwo+ICsJLyogbG9h ZCB0aGUgY29uZmlndXJhdGlvbiBvZiBQTEwxICovCj4gKwlmb3IgKGkgPSAwOyBpIDwgQVJSQVlf U0laRShkcF9wbGxfY2ZnKTsgaSsrKQo+ICsJCXdyaXRlbChkcF9wbGxfY2ZnW2ldLnZhbHVlLCB0 Y3BoeS0+YmFzZSArIGRwX3BsbF9jZmdbaV0uYWRkcik7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk IHRjcGh5X3R4X3VzYjNfY2ZnX2xhbmUoc3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSAqdGNwaHks IHUzMiBsYW5lKQo+ICt7Cj4gKwl3cml0ZWwoMHg3Nzk5LCB0Y3BoeS0+YmFzZSArIFRYX1BTQ19B MChsYW5lKSk7Cj4gKwl3cml0ZWwoMHg3Nzk4LCB0Y3BoeS0+YmFzZSArIFRYX1BTQ19BMShsYW5l KSk7Cj4gKwl3cml0ZWwoMHg1MDk4LCB0Y3BoeS0+YmFzZSArIFRYX1BTQ19BMihsYW5lKSk7Cj4g Kwl3cml0ZWwoMHg1MDk4LCB0Y3BoeS0+YmFzZSArIFRYX1BTQ19BMyhsYW5lKSk7Cj4gKwl3cml0 ZWwoMCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX01HTkZTX01VTFRfMDAwKGxhbmUpKTsKPiArCXdy aXRlbCgweGJmLCB0Y3BoeS0+YmFzZSArIFhDVlJfRElBR19CSURJX0NUUkwobGFuZSkpOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgdm9pZCB0Y3BoeV9yeF91c2IzX2NmZ19sYW5lKHN0cnVjdCByb2NrY2hp cF90eXBlY19waHkgKnRjcGh5LCB1MzIgbGFuZSkKPiArewo+ICsJd3JpdGVsKDB4YTZmZCwgdGNw aHktPmJhc2UgKyBSWF9QU0NfQTAobGFuZSkpOwo+ICsJd3JpdGVsKDB4YTZmZCwgdGNwaHktPmJh c2UgKyBSWF9QU0NfQTEobGFuZSkpOwo+ICsJd3JpdGVsKDB4YTQxMCwgdGNwaHktPmJhc2UgKyBS WF9QU0NfQTIobGFuZSkpOwo+ICsJd3JpdGVsKDB4MjQxMCwgdGNwaHktPmJhc2UgKyBSWF9QU0Nf QTMobGFuZSkpOwo+ICsJd3JpdGVsKDB4MjNmZiwgdGNwaHktPmJhc2UgKyBSWF9QU0NfQ0FMKGxh bmUpKTsKPiArCXdyaXRlbCgweDEzLCB0Y3BoeS0+YmFzZSArIFJYX1NJR0RFVF9ITF9GSUxUX1RN UihsYW5lKSk7Cj4gKwl3cml0ZWwoMHgwM2U3LCB0Y3BoeS0+YmFzZSArIFJYX1JFRV9DVFJMX0RB VEFfTUFTSyhsYW5lKSk7Cj4gKwl3cml0ZWwoMHgxMDA0LCB0Y3BoeS0+YmFzZSArIFJYX0RJQUdf U0lHREVUX1RVTkUobGFuZSkpOwo+ICsJd3JpdGVsKDB4MjAxMCwgdGNwaHktPmJhc2UgKyBSWF9Q U0NfUkRZKGxhbmUpKTsKPiArCXdyaXRlbCgweGZiLCB0Y3BoeS0+YmFzZSArIFhDVlJfRElBR19C SURJX0NUUkwobGFuZSkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB0Y3BoeV9kcF9jZmdfbGFu ZShzdHJ1Y3Qgcm9ja2NoaXBfdHlwZWNfcGh5ICp0Y3BoeSwgdTMyIGxhbmUpCj4gK3sKPiArCXUx NiByZGF0YTsKPiArCj4gKwl3cml0ZWwoMHhiZWZjLCB0Y3BoeS0+YmFzZSArIFhDVlJfUFNNX1JD VFJMKGxhbmUpKTsKPiArCXdyaXRlbCgweDY3OTksIHRjcGh5LT5iYXNlICsgVFhfUFNDX0EwKGxh bmUpKTsKPiArCXdyaXRlbCgweDY3OTgsIHRjcGh5LT5iYXNlICsgVFhfUFNDX0ExKGxhbmUpKTsK PiArCXdyaXRlbCgweDk4LCB0Y3BoeS0+YmFzZSArIFRYX1BTQ19BMihsYW5lKSk7Cj4gKwl3cml0 ZWwoMHg5OCwgdGNwaHktPmJhc2UgKyBUWF9QU0NfQTMobGFuZSkpOwo+ICsKPiArCXdyaXRlbCgw LCB0Y3BoeS0+YmFzZSArIFRYX1RYQ0NfTUdORlNfTVVMVF8wMDAobGFuZSkpOwo+ICsJd3JpdGVs KDAsIHRjcGh5LT5iYXNlICsgVFhfVFhDQ19NR05GU19NVUxUXzAwMShsYW5lKSk7Cj4gKwl3cml0 ZWwoMCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX01HTkZTX01VTFRfMDEwKGxhbmUpKTsKPiArCXdy aXRlbCgwLCB0Y3BoeS0+YmFzZSArIFRYX1RYQ0NfTUdORlNfTVVMVF8wMTEobGFuZSkpOwo+ICsJ d3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhfVFhDQ19NR05GU19NVUxUXzEwMChsYW5lKSk7Cj4g Kwl3cml0ZWwoMCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX01HTkZTX01VTFRfMTAxKGxhbmUpKTsK PiArCXdyaXRlbCgwLCB0Y3BoeS0+YmFzZSArIFRYX1RYQ0NfTUdORlNfTVVMVF8xMTAobGFuZSkp Owo+ICsJd3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhfVFhDQ19NR05GU19NVUxUXzExMShsYW5l KSk7Cj4gKwl3cml0ZWwoMCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX0NQT1NUX01VTFRfMTAobGFu ZSkpOwo+ICsJd3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhfVFhDQ19DUE9TVF9NVUxUXzAxKGxh bmUpKTsKPiArCXdyaXRlbCgwLCB0Y3BoeS0+YmFzZSArIFRYX1RYQ0NfQ1BPU1RfTVVMVF8wMChs YW5lKSk7Cj4gKwl3cml0ZWwoMCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX0NQT1NUX01VTFRfMTEo bGFuZSkpOwo+ICsKPiArCXdyaXRlbCgweDEyOCwgdGNwaHktPmJhc2UgKyBUWF9UWENDX0NBTF9T Q0xSX01VTFQobGFuZSkpOwo+ICsJd3JpdGVsKDB4NDAwLCB0Y3BoeS0+YmFzZSArIFRYX0RJQUdf VFhfRFJWKGxhbmUpKTsKPiArCj4gKwlyZGF0YSA9IHJlYWRsKHRjcGh5LT5iYXNlICsgWENWUl9E SUFHX1BMTERSQ19DVFJMKGxhbmUpKTsKPiArCXJkYXRhID0gKHJkYXRhICYgMHg4ZmZmKSB8IDB4 NjAwMDsKPiArCXdyaXRlbChyZGF0YSwgdGNwaHktPmJhc2UgKyBYQ1ZSX0RJQUdfUExMRFJDX0NU UkwobGFuZSkpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCBwcm9wZXJ0eV9lbmFibGUo c3RydWN0IHJvY2tjaGlwX3R5cGVjX3BoeSAqdGNwaHksCj4gKwkJCQkgIGNvbnN0IHN0cnVjdCB1 c2IzcGh5X3JlZyAqcmVnLCBib29sIGVuKQo+ICt7Cj4gKwl1MzIgbWFzayA9IDEgPDwgcmVnLT53 cml0ZV9lbmFibGU7Cj4gKwl1MzIgdmFsID0gZW4gPDwgcmVnLT5lbmFibGVfYml0Owo+ICsKPiAr CXJldHVybiByZWdtYXBfd3JpdGUodGNwaHktPmdyZl9yZWdzLCByZWctPm9mZnNldCwgdmFsIHwg bWFzayk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHRjcGh5X2RwX2F1eF9jYWxpYnJhdGlvbihz dHJ1Y3Qgcm9ja2NoaXBfdHlwZWNfcGh5ICp0Y3BoeSkKPiArewo+ICsJdTE2IHJkYXRhLCByZGF0 YTIsIHZhbDsKPiArCj4gKwkvKiBkaXNhYmxlIHR4ZGFfY2FsX2xhdGNoX2VuIGZvciByZXdyaXRl IHRoZSBjYWxpYnJhdGlvbiB2YWx1ZXMgKi8KPiArCXJkYXRhID0gcmVhZGwodGNwaHktPmJhc2Ug KyBUWF9BTkFfQ1RSTF9SRUdfMSk7Cj4gKwl2YWwgPSByZGF0YSAmIDB4ZGZmZjsKPiArCXdyaXRl bCh2YWwsIHRjcGh5LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzEpOwo+ICsKPiArCS8qCj4gKwkg KiByZWFkIGEgcmVzaXN0b3IgY2FsaWJyYXRpb24gY29kZSBmcm9tIENNTl9UWFBVQ0FMX0NUUkxb NjowXSBhbmQKPiArCSAqIHdyaXRlIGl0IHRvIFRYX0RJR19DVFJMX1JFR18yWzY6MF0sIGFuZCBk ZWxheSAxbXMgdG8gbWFrZSBzdXJlIGl0Cj4gKwkgKiB3b3Jrcy4KPiArCSAqLwo+ICsJcmRhdGEg PSByZWFkbCh0Y3BoeS0+YmFzZSArIFRYX0RJR19DVFJMX1JFR18yKTsKPiArCXJkYXRhID0gcmRh dGEgJiAweGZmYzA7Cj4gKwo+ICsJcmRhdGEyID0gcmVhZGwodGNwaHktPmJhc2UgKyBDTU5fVFhQ VUNBTF9DVFJMKTsKPiArCXJkYXRhMiA9IHJkYXRhMiAmIDB4M2Y7Cj4gKwo+ICsJdmFsID0gcmRh dGEgfCByZGF0YTI7Cj4gKwl3cml0ZWwodmFsLCB0Y3BoeS0+YmFzZSArIFRYX0RJR19DVFJMX1JF R18yKTsKPiArCXVzbGVlcF9yYW5nZSgxMDAwLCAxMDUwKTsKPiArCj4gKwkvKgo+ICsJICogRW5h YmxlIHNpZ25hbCBmb3IgbGF0Y2ggdGhhdCBzYW1wbGUgYW5kIGhvbGRzIGNhbGlicmF0aW9uIHZh bHVlcy4KPiArCSAqIEFjdGl2YXRlIHRoaXMgc2lnbmFsIGZvciAxIGNsb2NrIGN5Y2xlIHRvIHNh bXBsZSBuZXcgY2FsaWJyYXRpb24KPiArCSAqIHZhbHVlcy4KPiArCSAqLwo+ICsJcmRhdGEgPSBy ZWFkbCh0Y3BoeS0+YmFzZSArIFRYX0FOQV9DVFJMX1JFR18xKTsKPiArCXZhbCA9IHJkYXRhIHwg MHgyMDAwOwo+ICsJd3JpdGVsKHZhbCwgdGNwaHktPmJhc2UgKyBUWF9BTkFfQ1RSTF9SRUdfMSk7 Cj4gKwl1c2xlZXBfcmFuZ2UoMTUwLCAyMDApOwo+ICsKPiArCS8qIHNldCBUWCBWb2x0YWdlIExl dmVsIGFuZCBUWCBEZWVtcGhhc2lzIHRvIDAgKi8KPiArCXdyaXRlbCgwLCB0Y3BoeS0+YmFzZSAr IFBIWV9EUF9UWF9DVEwpOwo+ICsJLyogcmUtZW5hYmxlIGRlY2FwICovCj4gKwl3cml0ZWwoMHgx MDAsIHRjcGh5LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzIpOwo+ICsJd3JpdGVsKDB4MzAwLCB0 Y3BoeS0+YmFzZSArIFRYX0FOQV9DVFJMX1JFR18yKTsKPiArCXdyaXRlbCgweDIwMDgsIHRjcGh5 LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzEpOwo+ICsJd3JpdGVsKDB4MjAxOCwgdGNwaHktPmJh c2UgKyBUWF9BTkFfQ1RSTF9SRUdfMSk7Cj4gKwo+ICsJd3JpdGVsKDAsIHRjcGh5LT5iYXNlICsg VFhfQU5BX0NUUkxfUkVHXzUpOwo+ICsKPiArCS8qCj4gKwkgKiBQcm9ncmFtcyB0eGRhX2Rydl9s ZG9fcHJvZ1sxNTowXSwgU2V0cyBkcml2ZXIgTERPCj4gKwkgKiB2b2x0YWdlIDE2J2gxMDAxIGZv ciBEUC1BVVgtVFggYW5kIFJYCj4gKwkgKi8KPiArCXdyaXRlbCgweDEwMDEsIHRjcGh5LT5iYXNl ICsgVFhfQU5BX0NUUkxfUkVHXzQpOwo+ICsKPiArCS8qIHJlLWVuYWJsZXMgQmFuZGdhcCByZWZl cmVuY2UgZm9yIExETyAqLwo+ICsJd3JpdGVsKDB4MjA5OCwgdGNwaHktPmJhc2UgKyBUWF9BTkFf Q1RSTF9SRUdfMSk7Cj4gKwl3cml0ZWwoMHgyMTk4LCB0Y3BoeS0+YmFzZSArIFRYX0FOQV9DVFJM X1JFR18xKTsKPiArCj4gKwkvKgo+ICsJICogcmUtZW5hYmxlcyB0aGUgdHJhbnNtaXR0ZXIgcHJl LWRyaXZlciwgZHJpdmVyIGRhdGEgc2VsZWN0aW9uIE1VWCwKPiArCSAqIGFuZCByZWNlaXZlciBk ZXRlY3QgY2lyY3VpdHMuCj4gKwkgKi8KPiArCXdyaXRlbCgweDMwMSwgdGNwaHktPmJhc2UgKyBU WF9BTkFfQ1RSTF9SRUdfMik7Cj4gKwl3cml0ZWwoMHgzMDMsIHRjcGh5LT5iYXNlICsgVFhfQU5B X0NUUkxfUkVHXzIpOwo+ICsKPiArCS8qCj4gKwkgKiBCSVQgMTI6IENvbnRyb2xzIGF1eGRhX3Bv bGFyaXR5LCB3aGljaCBzZWxlY3RzIHRoZSBwb2xhcml0eSBvZiB0aGUKPiArCSAqIHhjdnI6Cj4g KwkgKiAxLCBSZXZlcnNlcyB0aGUgcG9sYXJpdHkgKElmIFRZUEVDLCBQdWxscyB1cHMgYXV4X3Ag YW5kIHB1bGwKPiArCSAqIGRvd24gYXV4X20pCj4gKwkgKiAwLCBOb3JtYWwgcG9sYXJpdHkgKGlm IFRZUEVfQywgcHVsbHMgdXAgYXV4X20gYW5kIHB1bGxzIGRvd24KPiArCSAqIGF1eF9wKQo+ICsJ ICovCj4gKwl2YWwgPSAweGEwNzg7Cj4gKwlpZiAoIXRjcGh5LT5mbGlwKQo+ICsJCXZhbCB8PSBC SVQoMTIpOwo+ICsJd3JpdGVsKHZhbCwgdGNwaHktPmJhc2UgKyBUWF9BTkFfQ1RSTF9SRUdfMSk7 Cj4gKwo+ICsJd3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzMpOwo+ICsJ d3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzQpOwo+ICsJd3JpdGVsKDAs IHRjcGh5LT5iYXNlICsgVFhfQU5BX0NUUkxfUkVHXzUpOwo+ICsKPiArCS8qCj4gKwkgKiBDb250 cm9scyBsb3dfcG93ZXJfc3dpbmdfZW4sIHNldCB0aGUgdm9sdGFnZSBzd2luZyBvZiB0aGUgZHJp dmVyCj4gKwkgKiB0byA0MDBtdi4gVGhlIHZhbHVlcwliZWxvdyBhcmUgcGVhayB0byBwZWFrIChk aWZmZXJlbnRpYWwpIHZhbHVlcy4KPiArCSAqLwo+ICsJd3JpdGVsKDQsIHRjcGh5LT5iYXNlICsg VFhEQV9DT0VGRl9DQUxDX0NUUkwpOwo+ICsJd3JpdGVsKDAsIHRjcGh5LT5iYXNlICsgVFhEQV9D WUFfQVVYREFfQ1lBKTsKPiArCj4gKwkvKiBDb250cm9scyB0eF9oaWdoX3pfdG1fZW4gKi8KPiAr CXZhbCA9IHJlYWRsKHRjcGh5LT5iYXNlICsgVFhfRElHX0NUUkxfUkVHXzIpOwo+ICsJdmFsIHw9 IEJJVCgxNSk7Cj4gKwl3cml0ZWwodmFsLCB0Y3BoeS0+YmFzZSArIFRYX0RJR19DVFJMX1JFR18y KTsKPiArfQo+ICsKPiArc3RhdGljIGludCB0Y3BoeV9waHlfaW5pdChzdHJ1Y3Qgcm9ja2NoaXBf dHlwZWNfcGh5ICp0Y3BoeSwgdTggbW9kZSkKPiArewo+ICsJc3RydWN0IHJvY2tjaGlwX3VzYjNw aHlfcG9ydF9jZmcgKmNmZyA9ICZ0Y3BoeS0+cG9ydF9jZmdzOwo+ICsJaW50IHJldCwgaTsKPiAr CXUzMiB2YWw7Cj4gKwo+ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKHRjcGh5LT5jbGtfY29y ZSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vycih0Y3BoeS0+ZGV2LCAiRmFpbGVkIHRvIHBy ZXBhcmVfZW5hYmxlIGNvcmUgY2xvY2tcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKHRjcGh5LT5jbGtfcmVmKTsKPiArCWlmIChyZXQp IHsKPiArCQlkZXZfZXJyKHRjcGh5LT5kZXYsICJGYWlsZWQgdG8gcHJlcGFyZV9lbmFibGUgcmVm IGNsb2NrXG4iKTsKPiArCQlnb3RvIGVycl9jbGtfY29yZTsKPiArCX0KPiArCj4gKwlyZXNldF9j b250cm9sX2RlYXNzZXJ0KHRjcGh5LT50Y3BoeV9yc3QpOwo+ICsKPiArCXByb3BlcnR5X2VuYWJs ZSh0Y3BoeSwgJmNmZy0+dHlwZWNfY29ubl9kaXIsIHRjcGh5LT5mbGlwKTsKPiArCj4gKwl0Y3Bo eV9jZmdfMjRtKHRjcGh5KTsKPiArCj4gKwlpZiAobW9kZSA9PSBNT0RFX0RGUF9EUCkgewo+ICsJ CXRjcGh5X2NmZ19kcF9wbGwodGNwaHkpOwo+ICsJCWZvciAoaSA9IDA7IGkgPCA0OyBpKyspCj4g KwkJCXRjcGh5X2RwX2NmZ19sYW5lKHRjcGh5LCBpKTsKPiArCj4gKwkJd3JpdGVsKFBJTl9BU1NJ R05fQ19FLCB0Y3BoeS0+YmFzZSArIFBNQV9MQU5FX0NGRyk7Cj4gKwl9IGVsc2Ugewo+ICsJCXRj cGh5X2NmZ191c2IzX3BsbCh0Y3BoeSk7Cj4gKwkJdGNwaHlfY2ZnX2RwX3BsbCh0Y3BoeSk7Cj4g KwkJaWYgKHRjcGh5LT5mbGlwKSB7Cj4gKwkJCXRjcGh5X3R4X3VzYjNfY2ZnX2xhbmUodGNwaHks IDMpOwo+ICsJCQl0Y3BoeV9yeF91c2IzX2NmZ19sYW5lKHRjcGh5LCAyKTsKPiArCQkJdGNwaHlf ZHBfY2ZnX2xhbmUodGNwaHksIDApOwo+ICsJCQl0Y3BoeV9kcF9jZmdfbGFuZSh0Y3BoeSwgMSk7 Cj4gKwkJfSBlbHNlIHsKPiArCQkJdGNwaHlfdHhfdXNiM19jZmdfbGFuZSh0Y3BoeSwgMCk7Cj4g KwkJCXRjcGh5X3J4X3VzYjNfY2ZnX2xhbmUodGNwaHksIDEpOwo+ICsJCQl0Y3BoeV9kcF9jZmdf bGFuZSh0Y3BoeSwgMik7Cj4gKwkJCXRjcGh5X2RwX2NmZ19sYW5lKHRjcGh5LCAzKTsKPiArCQl9 Cj4gKwo+ICsJCXdyaXRlbChQSU5fQVNTSUdOX0RfRiwgdGNwaHktPmJhc2UgKyBQTUFfTEFORV9D RkcpOwo+ICsJfQo+ICsKPiArCXdyaXRlbChEUF9NT0RFX0VOVEVSX0EyLCB0Y3BoeS0+YmFzZSAr IERQX01PREVfQ1RMKTsKPiArCj4gKwlyZXNldF9jb250cm9sX2RlYXNzZXJ0KHRjcGh5LT51cGh5 X3JzdCk7Cj4gKwo+ICsJcmV0ID0gcmVhZHhfcG9sbF90aW1lb3V0KHJlYWRsLCB0Y3BoeS0+YmFz ZSArIFBNQV9DTU5fQ1RSTDEsCj4gKwkJCQkgdmFsLCB2YWwgJiBDTU5fUkVBRFksIDEwLAo+ICsJ CQkJIFBIWV9NT0RFX1NFVF9USU1FT1VUKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2Vy cih0Y3BoeS0+ZGV2LCAid2FpdCBwbWEgcmVhZHkgdGltZW91dFxuIik7Cj4gKwkJcmV0ID0gLUVU SU1FRE9VVDsKPiArCQlnb3RvIGVycl93YWl0X3BtYTsKPiArCX0KPiArCj4gKwlyZXNldF9jb250 cm9sX2RlYXNzZXJ0KHRjcGh5LT5waXBlX3JzdCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gKwo+ICtl cnJfd2FpdF9wbWE6Cj4gKwlyZXNldF9jb250cm9sX2Fzc2VydCh0Y3BoeS0+dXBoeV9yc3QpOwo+ ICsJcmVzZXRfY29udHJvbF9hc3NlcnQodGNwaHktPnRjcGh5X3JzdCk7Cj4gKwljbGtfZGlzYWJs ZV91bnByZXBhcmUodGNwaHktPmNsa19yZWYpOwo+ICtlcnJfY2xrX2NvcmU6Cj4gKwljbGtfZGlz YWJsZV91bnByZXBhcmUodGNwaHktPmNsa19jb3JlKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiAr Cj4gK3N0YXRpYyB2b2lkIHRjcGh5X3BoeV9kZWluaXQoc3RydWN0IHJvY2tjaGlwX3R5cGVjX3Bo eSAqdGNwaHkpCj4gK3sKPiArCXJlc2V0X2NvbnRyb2xfYXNzZXJ0KHRjcGh5LT50Y3BoeV9yc3Qp Owo+ICsJcmVzZXRfY29udHJvbF9hc3NlcnQodGNwaHktPnVwaHlfcnN0KTsKPiArCXJlc2V0X2Nv bnRyb2xfYXNzZXJ0KHRjcGh5LT5waXBlX3JzdCk7Cj4gKwljbGtfZGlzYWJsZV91bnByZXBhcmUo dGNwaHktPmNsa19jb3JlKTsKPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZSh0Y3BoeS0+Y2xrX3Jl Zik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdGNwaHlfZ2V0X21vZGUoc3RydWN0IHJvY2tjaGlw X3R5cGVjX3BoeSAqdGNwaHkpCj4gK3sKPiArCXN0cnVjdCBleHRjb25fZGV2ICplZGV2ID0gdGNw aHktPmV4dGNvbjsKPiArCXVuaW9uIGV4dGNvbl9wcm9wZXJ0eV92YWx1ZSBwcm9wZXJ0eTsKPiAr CXVuc2lnbmVkIGludCBpZDsKPiArCWJvb2wgZGZwLCB1ZnAsIGRwOwo+ICsJdTggbW9kZTsKPiAr CWludCByZXQ7Cj4gKwo+ICsJdWZwID0gZXh0Y29uX2dldF9zdGF0ZShlZGV2LCBFWFRDT05fVVNC KTsKPiArCWRmcCA9IGV4dGNvbl9nZXRfc3RhdGUoZWRldiwgRVhUQ09OX1VTQl9IT1NUKTsKPiAr CWRwID0gZXh0Y29uX2dldF9zdGF0ZShlZGV2LCBFWFRDT05fRElTUF9EUCk7Cj4gKwo+ICsJbW9k ZSA9IE1PREVfREZQX1VTQjsKPiArCWlkID0gRVhUQ09OX1VTQl9IT1NUOwo+ICsKPiArCWlmICh1 ZnApIHsKPiArCQltb2RlID0gTU9ERV9VRlBfVVNCOwo+ICsJCWlkID0gRVhUQ09OX1VTQjsKPiAr CX0gZWxzZSBpZiAoZHApIHsKPiArCQltb2RlID0gTU9ERV9ERlBfRFA7Cj4gKwkJaWQgPSBFWFRD T05fRElTUF9EUDsKPiArCj4gKwkJcmV0ID0gZXh0Y29uX2dldF9wcm9wZXJ0eShlZGV2LCBpZCwg RVhUQ09OX1BST1BfVVNCX1NVUEVSU1BFRUQsCj4gKwkJCQkJICAmcHJvcGVydHkpOwo+ICsJCWlm IChyZXQpIHsKPiArCQkJZGV2X2Vycih0Y3BoeS0+ZGV2LCAiZ2V0IHN1cGVyc3BlZWQgcHJvcGVy dHkgZmFpbGVkXG4iKTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwo+ICsJCWlmIChwcm9w ZXJ0eS5pbnR2YWwpCj4gKwkJCW1vZGUgfD0gTU9ERV9ERlBfVVNCOwo+ICsJfQo+ICsKPiArCXJl dCA9IGV4dGNvbl9nZXRfcHJvcGVydHkoZWRldiwgaWQsIEVYVENPTl9QUk9QX1VTQl9UWVBFQ19Q T0xBUklUWSwKPiArCQkJCSAgJnByb3BlcnR5KTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJy KHRjcGh5LT5kZXYsICJnZXQgcG9sYXJpdHkgcHJvcGVydHkgZmFpbGVkXG4iKTsKPiArCQlyZXR1 cm4gcmV0Owo+ICsJfQo+ICsKPiArCXRjcGh5LT5mbGlwID0gcHJvcGVydHkuaW50dmFsID8gMSA6 IDA7Cj4gKwo+ICsJcmV0dXJuIG1vZGU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcm9ja2NoaXBf dXNiM19waHlfcG93ZXJfb24oc3RydWN0IHBoeSAqcGh5KQo+ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2No aXBfdHlwZWNfcGh5ICp0Y3BoeSA9IHBoeV9nZXRfZHJ2ZGF0YShwaHkpOwo+ICsJc3RydWN0IHJv Y2tjaGlwX3VzYjNwaHlfcG9ydF9jZmcgKmNmZyA9ICZ0Y3BoeS0+cG9ydF9jZmdzOwo+ICsJY29u c3Qgc3RydWN0IHVzYjNwaHlfcmVnICpyZWcgPSAmY2ZnLT5waXBlX3N0YXR1czsKPiArCWludCB0 aW1lb3V0LCBuZXdfbW9kZSwgcmV0ID0gMDsKPiArCXUzMiB2YWw7Cj4gKwo+ICsJbXV0ZXhfbG9j aygmdGNwaHktPmxvY2spOwo+ICsKPiArCW5ld19tb2RlID0gdGNwaHlfZ2V0X21vZGUodGNwaHkp Owo+ICsJaWYgKG5ld19tb2RlIDwgMCkgewo+ICsJCXJldCA9IG5ld19tb2RlOwo+ICsJCWdvdG8g dW5sb2NrX3JldDsKPiArCX0KPiArCj4gKwkvKiBEUC1vbmx5IG1vZGU7IGZhbGwgYmFjayB0byBV U0IyICovCj4gKwlpZiAoIShuZXdfbW9kZSAmIChNT0RFX0RGUF9VU0IgfCBNT0RFX1VGUF9VU0Ip KSkKPiArCQlnb3RvIHVubG9ja19yZXQ7Cj4gKwo+ICsJaWYgKHRjcGh5LT5tb2RlID09IG5ld19t b2RlKQo+ICsJCWdvdG8gdW5sb2NrX3JldDsKPiArCj4gKwlpZiAodGNwaHktPm1vZGUgPT0gTU9E RV9ESVNDT05ORUNUKQo+ICsJCXRjcGh5X3BoeV9pbml0KHRjcGh5LCBuZXdfbW9kZSk7Cj4gKwo+ ICsJLyogd2FpdCBUQ1BIWSBmb3IgcGlwZSByZWFkeSAqLwo+ICsJZm9yICh0aW1lb3V0ID0gMDsg dGltZW91dCA8IDEwMDsgdGltZW91dCsrKSB7Cj4gKwkJcmVnbWFwX3JlYWQodGNwaHktPmdyZl9y ZWdzLCByZWctPm9mZnNldCwgJnZhbCk7Cj4gKwkJaWYgKCEodmFsICYgQklUKHJlZy0+ZW5hYmxl X2JpdCkpKSB7Cj4gKwkJCXRjcGh5LT5tb2RlIHw9IG5ld19tb2RlICYgKE1PREVfREZQX1VTQiB8 IE1PREVfVUZQX1VTQik7Cj4gKwkJCWdvdG8gdW5sb2NrX3JldDsKPiArCQl9Cj4gKwkJdXNsZWVw X3JhbmdlKDEwLCAyMCk7Cj4gKwl9Cj4gKwo+ICsJaWYgKHRjcGh5LT5tb2RlID09IE1PREVfRElT Q09OTkVDVCkKPiArCQl0Y3BoeV9waHlfZGVpbml0KHRjcGh5KTsKPiArCj4gKwlyZXQgPSAtRVRJ TUVET1VUOwo+ICsKPiArdW5sb2NrX3JldDoKPiArCW11dGV4X3VubG9jaygmdGNwaHktPmxvY2sp Owo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCByb2NrY2hpcF91c2IzX3Bo eV9wb3dlcl9vZmYoc3RydWN0IHBoeSAqcGh5KQo+ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfdHlw ZWNfcGh5ICp0Y3BoeSA9IHBoeV9nZXRfZHJ2ZGF0YShwaHkpOwo+ICsKPiArCW11dGV4X2xvY2so JnRjcGh5LT5sb2NrKTsKPiArCj4gKwlpZiAodGNwaHktPm1vZGUgPT0gTU9ERV9ESVNDT05ORUNU KQo+ICsJCWdvdG8gdW5sb2NrOwo+ICsKPiArCXRjcGh5LT5tb2RlICY9IH4oTU9ERV9VRlBfVVNC IHwgTU9ERV9ERlBfVVNCKTsKPiArCWlmICh0Y3BoeS0+bW9kZSA9PSBNT0RFX0RJU0NPTk5FQ1Qp Cj4gKwkJdGNwaHlfcGh5X2RlaW5pdCh0Y3BoeSk7Cj4gKwo+ICt1bmxvY2s6Cj4gKwltdXRleF91 bmxvY2soJnRjcGh5LT5sb2NrKTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29u c3Qgc3RydWN0IHBoeV9vcHMgcm9ja2NoaXBfdXNiM19waHlfb3BzID0gewo+ICsJLnBvd2VyX29u CT0gcm9ja2NoaXBfdXNiM19waHlfcG93ZXJfb24sCj4gKwkucG93ZXJfb2ZmCT0gcm9ja2NoaXBf dXNiM19waHlfcG93ZXJfb2ZmLAo+ICsJLm93bmVyCQk9IFRISVNfTU9EVUxFLAo+ICt9Owo+ICsK PiArc3RhdGljIGludCByb2NrY2hpcF9kcF9waHlfcG93ZXJfb24oc3RydWN0IHBoeSAqcGh5KQo+ ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfdHlwZWNfcGh5ICp0Y3BoeSA9IHBoeV9nZXRfZHJ2ZGF0 YShwaHkpOwo+ICsJaW50IG5ld19tb2RlLCByZXQgPSAwOwo+ICsJdTMyIHZhbDsKPiArCj4gKwlt dXRleF9sb2NrKCZ0Y3BoeS0+bG9jayk7Cj4gKwo+ICsJbmV3X21vZGUgPSB0Y3BoeV9nZXRfbW9k ZSh0Y3BoeSk7Cj4gKwlpZiAobmV3X21vZGUgPCAwKSB7Cj4gKwkJcmV0ID0gbmV3X21vZGU7Cj4g KwkJZ290byB1bmxvY2tfcmV0Owo+ICsJfQo+ICsKPiArCWlmICghKG5ld19tb2RlICYgTU9ERV9E RlBfRFApKSB7Cj4gKwkJcmV0ID0gLUVOT0RFVjsKPiArCQlnb3RvIHVubG9ja19yZXQ7Cj4gKwl9 Cj4gKwo+ICsJaWYgKHRjcGh5LT5tb2RlID09IG5ld19tb2RlKQo+ICsJCWdvdG8gdW5sb2NrX3Jl dDsKPiArCj4gKwkvKgo+ICsJICogSWYgdGhlIFBIWSBoYXMgYmVlbiBwb3dlciBvbiwgYnV0IHRo ZSBtb2RlIGlzIG5vdCBEUCBvbmx5IG1vZGUsCj4gKwkgKiByZS1pbml0IHRoZSBQSFkgZm9yIHNl dHRpbmcgYWxsIG9mIDQgbGFuZXMgdG8gRFAuCj4gKwkgKi8KPiArCWlmIChuZXdfbW9kZSA9PSBN T0RFX0RGUF9EUCAmJiB0Y3BoeS0+bW9kZSAhPSBNT0RFX0RJU0NPTk5FQ1QpIHsKPiArCQl0Y3Bo eV9waHlfZGVpbml0KHRjcGh5KTsKPiArCQl0Y3BoeV9waHlfaW5pdCh0Y3BoeSwgbmV3X21vZGUp Owo+ICsJfSBlbHNlIGlmICh0Y3BoeS0+bW9kZSA9PSBNT0RFX0RJU0NPTk5FQ1QpIHsKPiArCQl0 Y3BoeV9waHlfaW5pdCh0Y3BoeSwgbmV3X21vZGUpOwo+ICsJfQo+ICsKPiArCXJldCA9IHJlYWR4 X3BvbGxfdGltZW91dChyZWFkbCwgdGNwaHktPmJhc2UgKyBEUF9NT0RFX0NUTCwKPiArCQkJCSB2 YWwsIHZhbCAmIERQX01PREVfQTIsIDEwMDAsCj4gKwkJCQkgUEhZX01PREVfU0VUX1RJTUVPVVQp Owo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKHRjcGh5LT5kZXYsICJmYWlsZWQgdG8g d2FpdCBUQ1BIWSBlbnRlciBBMlxuIik7Cj4gKwkJZ290byBwb3dlcl9vbl9maW5pc2g7Cj4gKwl9 Cj4gKwo+ICsJdGNwaHlfZHBfYXV4X2NhbGlicmF0aW9uKHRjcGh5KTsKPiArCj4gKwl3cml0ZWwo RFBfTU9ERV9FTlRFUl9BMCwgdGNwaHktPmJhc2UgKyBEUF9NT0RFX0NUTCk7Cj4gKwo+ICsJcmV0 ID0gcmVhZHhfcG9sbF90aW1lb3V0KHJlYWRsLCB0Y3BoeS0+YmFzZSArIERQX01PREVfQ1RMLAo+ ICsJCQkJIHZhbCwgdmFsICYgRFBfTU9ERV9BMCwgMTAwMCwKPiArCQkJCSBQSFlfTU9ERV9TRVRf VElNRU9VVCk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCXdyaXRlbChEUF9NT0RFX0VOVEVSX0Ey LCB0Y3BoeS0+YmFzZSArIERQX01PREVfQ1RMKTsKPiArCQlkZXZfZXJyKHRjcGh5LT5kZXYsICJm YWlsZWQgdG8gd2FpdCBUQ1BIWSBlbnRlciBBMFxuIik7Cj4gKwkJZ290byBwb3dlcl9vbl9maW5p c2g7Cj4gKwl9Cj4gKwo+ICsJdGNwaHktPm1vZGUgfD0gTU9ERV9ERlBfRFA7Cj4gKwo+ICtwb3dl cl9vbl9maW5pc2g6Cj4gKwlpZiAodGNwaHktPm1vZGUgPT0gTU9ERV9ESVNDT05ORUNUKQo+ICsJ CXRjcGh5X3BoeV9kZWluaXQodGNwaHkpOwo+ICt1bmxvY2tfcmV0Ogo+ICsJbXV0ZXhfdW5sb2Nr KCZ0Y3BoeS0+bG9jayk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJv Y2tjaGlwX2RwX3BoeV9wb3dlcl9vZmYoc3RydWN0IHBoeSAqcGh5KQo+ICt7Cj4gKwlzdHJ1Y3Qg cm9ja2NoaXBfdHlwZWNfcGh5ICp0Y3BoeSA9IHBoeV9nZXRfZHJ2ZGF0YShwaHkpOwo+ICsKPiAr CW11dGV4X2xvY2soJnRjcGh5LT5sb2NrKTsKPiArCj4gKwlpZiAodGNwaHktPm1vZGUgPT0gTU9E RV9ESVNDT05ORUNUKQo+ICsJCWdvdG8gdW5sb2NrOwo+ICsKPiArCXRjcGh5LT5tb2RlICY9IH5N T0RFX0RGUF9EUDsKPiArCj4gKwl3cml0ZWwoRFBfTU9ERV9FTlRFUl9BMiwgdGNwaHktPmJhc2Ug KyBEUF9NT0RFX0NUTCk7Cj4gKwo+ICsJaWYgKHRjcGh5LT5tb2RlID09IE1PREVfRElTQ09OTkVD VCkKPiArCQl0Y3BoeV9waHlfZGVpbml0KHRjcGh5KTsKPiArCj4gK3VubG9jazoKPiArCW11dGV4 X3VubG9jaygmdGNwaHktPmxvY2spOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgcGh5X29wcyByb2NrY2hpcF9kcF9waHlfb3BzID0gewo+ICsJLnBvd2VyX29u CT0gcm9ja2NoaXBfZHBfcGh5X3Bvd2VyX29uLAo+ICsJLnBvd2VyX29mZgk9IHJvY2tjaGlwX2Rw X3BoeV9wb3dlcl9vZmYsCj4gKwkub3duZXIJCT0gVEhJU19NT0RVTEUsCj4gK307Cj4gKwo+ICtz dGF0aWMgaW50IHRjcGh5X2dldF9wYXJhbShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCSAgIHN0 cnVjdCB1c2IzcGh5X3JlZyAqcmVnLAo+ICsJCQkgICBjb25zdCBjaGFyICpuYW1lKQo+ICt7Cj4g Kwl1MzIgYnVmZmVyWzNdOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBvZl9wcm9wZXJ0eV9y ZWFkX3UzMl9hcnJheShkZXYtPm9mX25vZGUsIG5hbWUsIGJ1ZmZlciwgMyk7Cj4gKwlpZiAocmV0 KSB7Cj4gKwkJZGV2X2VycihkZXYsICJDYW4gbm90IHBhcnNlICVzXG4iLCBuYW1lKTsKPiArCQly ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJlZy0+b2Zmc2V0ID0gYnVmZmVyWzBdOwo+ICsJcmVn LT5lbmFibGVfYml0ID0gYnVmZmVyWzFdOwo+ICsJcmVnLT53cml0ZV9lbmFibGUgPSBidWZmZXJb Ml07Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB0Y3BoeV9wYXJzZV9kdChz dHJ1Y3Qgcm9ja2NoaXBfdHlwZWNfcGh5ICp0Y3BoeSwKPiArCQkJICBzdHJ1Y3QgZGV2aWNlICpk ZXYpCj4gK3sKPiArCXN0cnVjdCByb2NrY2hpcF91c2IzcGh5X3BvcnRfY2ZnICpjZmcgPSAmdGNw aHktPnBvcnRfY2ZnczsKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0gdGNwaHlfZ2V0X3BhcmFt KGRldiwgJmNmZy0+dHlwZWNfY29ubl9kaXIsCj4gKwkJCSAgICAgICJyb2NrY2hpcCx0eXBlYy1j b25uLWRpciIpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCXJldCA9IHRj cGh5X2dldF9wYXJhbShkZXYsICZjZmctPnVzYjN0b3VzYjJfZW4sCj4gKwkJCSAgICAgICJyb2Nr Y2hpcCx1c2IzdG91c2IyLWVuIik7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ ICsJcmV0ID0gdGNwaHlfZ2V0X3BhcmFtKGRldiwgJmNmZy0+ZXh0ZXJuYWxfcHNtLAo+ICsJCQkg ICAgICAicm9ja2NoaXAsZXh0ZXJuYWwtcHNtIik7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiBy ZXQ7Cj4gKwo+ICsJcmV0ID0gdGNwaHlfZ2V0X3BhcmFtKGRldiwgJmNmZy0+cGlwZV9zdGF0dXMs Cj4gKwkJCSAgICAgICJyb2NrY2hpcCxwaXBlLXN0YXR1cyIpOwo+ICsJaWYgKHJldCkKPiArCQly ZXR1cm4gcmV0Owo+ICsKPiArCXRjcGh5LT5ncmZfcmVncyA9IHN5c2Nvbl9yZWdtYXBfbG9va3Vw X2J5X3BoYW5kbGUoZGV2LT5vZl9ub2RlLAo+ICsJCQkJCQkJICAicm9ja2NoaXAsZ3JmIik7Cj4g KwlpZiAoSVNfRVJSKHRjcGh5LT5ncmZfcmVncykpIHsKPiArCQlkZXZfZXJyKGRldiwgImNvdWxk IG5vdCBmaW5kIGdyZiBkdCBub2RlXG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUih0Y3BoeS0+Z3Jm X3JlZ3MpOwo+ICsJfQo+ICsKPiArCXRjcGh5LT5jbGtfY29yZSA9IGRldm1fY2xrX2dldChkZXYs ICJ0Y3BkY29yZSIpOwo+ICsJaWYgKElTX0VSUih0Y3BoeS0+Y2xrX2NvcmUpKSB7Cj4gKwkJZGV2 X2VycihkZXYsICJjb3VsZCBub3QgZ2V0IHVwaHkgY29yZSBjbG9ja1xuIik7Cj4gKwkJcmV0dXJu IFBUUl9FUlIodGNwaHktPmNsa19jb3JlKTsKPiArCX0KPiArCj4gKwl0Y3BoeS0+Y2xrX3JlZiA9 IGRldm1fY2xrX2dldChkZXYsICJ0Y3BkcGh5LXJlZiIpOwo+ICsJaWYgKElTX0VSUih0Y3BoeS0+ Y2xrX3JlZikpIHsKPiArCQlkZXZfZXJyKGRldiwgImNvdWxkIG5vdCBnZXQgdXBoeSByZWYgY2xv Y2tcbiIpOwo+ICsJCXJldHVybiBQVFJfRVJSKHRjcGh5LT5jbGtfcmVmKTsKPiArCX0KPiArCj4g Kwl0Y3BoeS0+dXBoeV9yc3QgPSBkZXZtX3Jlc2V0X2NvbnRyb2xfZ2V0KGRldiwgInVwaHkiKTsK PiArCWlmIChJU19FUlIodGNwaHktPnVwaHlfcnN0KSkgewo+ICsJCWRldl9lcnIoZGV2LCAibm8g dXBoeV9yc3QgcmVzZXQgY29udHJvbCBmb3VuZFxuIik7Cj4gKwkJcmV0dXJuIFBUUl9FUlIodGNw aHktPnVwaHlfcnN0KTsKPiArCX0KPiArCj4gKwl0Y3BoeS0+cGlwZV9yc3QgPSBkZXZtX3Jlc2V0 X2NvbnRyb2xfZ2V0KGRldiwgInVwaHktcGlwZSIpOwo+ICsJaWYgKElTX0VSUih0Y3BoeS0+cGlw ZV9yc3QpKSB7Cj4gKwkJZGV2X2VycihkZXYsICJubyBwaXBlX3JzdCByZXNldCBjb250cm9sIGZv dW5kXG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUih0Y3BoeS0+cGlwZV9yc3QpOwo+ICsJfQo+ICsK PiArCXRjcGh5LT50Y3BoeV9yc3QgPSBkZXZtX3Jlc2V0X2NvbnRyb2xfZ2V0KGRldiwgInVwaHkt dGNwaHkiKTsKPiArCWlmIChJU19FUlIodGNwaHktPnRjcGh5X3JzdCkpIHsKPiArCQlkZXZfZXJy KGRldiwgIm5vIHRjcGh5X3JzdCByZXNldCBjb250cm9sIGZvdW5kXG4iKTsKPiArCQlyZXR1cm4g UFRSX0VSUih0Y3BoeS0+dGNwaHlfcnN0KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgdHlwZWNfcGh5X3ByZV9pbml0KHN0cnVjdCByb2NrY2hpcF90eXBl Y19waHkgKnRjcGh5KQo+ICt7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfdXNiM3BoeV9wb3J0X2NmZyAq Y2ZnID0gJnRjcGh5LT5wb3J0X2NmZ3M7Cj4gKwo+ICsJcmVzZXRfY29udHJvbF9hc3NlcnQodGNw aHktPnRjcGh5X3JzdCk7Cj4gKwlyZXNldF9jb250cm9sX2Fzc2VydCh0Y3BoeS0+dXBoeV9yc3Qp Owo+ICsJcmVzZXRfY29udHJvbF9hc3NlcnQodGNwaHktPnBpcGVfcnN0KTsKPiArCj4gKwkvKiBz ZWxlY3QgZXh0ZXJuYWwgcHNtIGNsb2NrICovCj4gKwlwcm9wZXJ0eV9lbmFibGUodGNwaHksICZj ZmctPmV4dGVybmFsX3BzbSwgMSk7Cj4gKwlwcm9wZXJ0eV9lbmFibGUodGNwaHksICZjZmctPnVz YjN0b3VzYjJfZW4sIDApOwo+ICsKPiArCXRjcGh5LT5tb2RlID0gTU9ERV9ESVNDT05ORUNUOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJvY2tjaGlwX3R5cGVjX3BoeV9wcm9iZShzdHJ1Y3QgcGxh dGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ ZGV2Owo+ICsJc3RydWN0IGRldmljZV9ub2RlICpucCA9IGRldi0+b2Zfbm9kZTsKPiArCXN0cnVj dCBkZXZpY2Vfbm9kZSAqY2hpbGRfbnA7Cj4gKwlzdHJ1Y3Qgcm9ja2NoaXBfdHlwZWNfcGh5ICp0 Y3BoeTsKPiArCXN0cnVjdCBwaHlfcHJvdmlkZXIgKnBoeV9wcm92aWRlcjsKPiArCXN0cnVjdCBy ZXNvdXJjZSAqcmVzOwo+ICsJaW50IHJldDsKPiArCj4gKwl0Y3BoeSA9IGRldm1fa3phbGxvYyhk ZXYsIHNpemVvZigqdGNwaHkpLCBHRlBfS0VSTkVMKTsKPiArCWlmICghdGNwaHkpCj4gKwkJcmV0 dXJuIC1FTk9NRU07Cj4gKwo+ICsJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElP UkVTT1VSQ0VfTUVNLCAwKTsKPiArCXRjcGh5LT5iYXNlID0gZGV2bV9pb3JlbWFwX3Jlc291cmNl KGRldiwgcmVzKTsKPiArCWlmIChJU19FUlIodGNwaHktPmJhc2UpKQo+ICsJCXJldHVybiBQVFJf RVJSKHRjcGh5LT5iYXNlKTsKPiArCj4gKwlyZXQgPSB0Y3BoeV9wYXJzZV9kdCh0Y3BoeSwgZGV2 KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwl0Y3BoeS0+ZGV2ID0gZGV2 Owo+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgdGNwaHkpOwo+ICsJbXV0ZXhfaW5pdCgm dGNwaHktPmxvY2spOwo+ICsKPiArCXR5cGVjX3BoeV9wcmVfaW5pdCh0Y3BoeSk7Cj4gKwo+ICsJ dGNwaHktPmV4dGNvbiA9IGV4dGNvbl9nZXRfZWRldl9ieV9waGFuZGxlKGRldiwgMCk7Cj4gKwlp ZiAoSVNfRVJSKHRjcGh5LT5leHRjb24pKSB7Cj4gKwkJaWYgKFBUUl9FUlIodGNwaHktPmV4dGNv bikgIT0gLUVQUk9CRV9ERUZFUikKPiArCQkJZGV2X2VycihkZXYsICJJbnZhbGlkIG9yIG1pc3Np bmcgZXh0Y29uXG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUih0Y3BoeS0+ZXh0Y29uKTsKPiArCX0K PiArCj4gKwlmb3JfZWFjaF9hdmFpbGFibGVfY2hpbGRfb2Zfbm9kZShucCwgY2hpbGRfbnApIHsK PiArCQlzdHJ1Y3QgcGh5ICpwaHk7Cj4gKwo+ICsJCWlmICghb2Zfbm9kZV9jbXAoY2hpbGRfbnAt Pm5hbWUsICJkcC1wb3J0IikpCj4gKwkJCXBoeSA9IGRldm1fcGh5X2NyZWF0ZShkZXYsIGNoaWxk X25wLAo+ICsJCQkJCSAgICAgICZyb2NrY2hpcF9kcF9waHlfb3BzKTsKPiArCQllbHNlIGlmICgh b2Zfbm9kZV9jbXAoY2hpbGRfbnAtPm5hbWUsICJ1c2IzLXBvcnQiKSkKPiArCQkJcGh5ID0gZGV2 bV9waHlfY3JlYXRlKGRldiwgY2hpbGRfbnAsCj4gKwkJCQkJICAgICAgJnJvY2tjaGlwX3VzYjNf cGh5X29wcyk7Cj4gKwkJZWxzZQo+ICsJCQljb250aW51ZTsKPiArCj4gKwkJaWYgKElTX0VSUihw aHkpKSB7Cj4gKwkJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIGNyZWF0ZSBwaHk6ICVzXG4iLAo+ ICsJCQkJY2hpbGRfbnAtPm5hbWUpOwo+ICsJCQlyZXR1cm4gUFRSX0VSUihwaHkpOwo+ICsJCX0K PiArCj4gKwkJcGh5X3NldF9kcnZkYXRhKHBoeSwgdGNwaHkpOwo+ICsJfQo+ICsKPiArCXBoeV9w cm92aWRlciA9IGRldm1fb2ZfcGh5X3Byb3ZpZGVyX3JlZ2lzdGVyKGRldiwgb2ZfcGh5X3NpbXBs ZV94bGF0ZSk7Cj4gKwlpZiAoSVNfRVJSKHBoeV9wcm92aWRlcikpIHsKPiArCQlkZXZfZXJyKGRl diwgIkZhaWxlZCB0byByZWdpc3RlciBwaHkgcHJvdmlkZXJcbiIpOwo+ICsJCXJldHVybiBQVFJf RVJSKHBoeV9wcm92aWRlcik7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0 YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIHJvY2tjaGlwX3R5cGVjX3BoeV9kdF9pZHNb XSA9IHsKPiArCXsgLmNvbXBhdGlibGUgPSAicm9ja2NoaXAscmszMzk5LXR5cGVjLXBoeSIgfSwK PiArCXt9Cj4gK307Cj4gKwo+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCByb2NrY2hpcF90eXBl Y19waHlfZHRfaWRzKTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIHJvY2tj aGlwX3R5cGVjX3BoeV9kcml2ZXIgPSB7Cj4gKwkucHJvYmUJCT0gcm9ja2NoaXBfdHlwZWNfcGh5 X3Byb2JlLAo+ICsJLmRyaXZlcgkJPSB7Cj4gKwkJLm5hbWUJPSAicm9ja2NoaXAtdHlwZWMtcGh5 IiwKPiArCQkub2ZfbWF0Y2hfdGFibGUgPSByb2NrY2hpcF90eXBlY19waHlfZHRfaWRzLAo+ICsJ fSwKPiArfTsKPiArCj4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIocm9ja2NoaXBfdHlwZWNfcGh5 X2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJDaHJpcyBaaG9uZyA8enl3QHJvY2stY2hp cHMuY29tPiIpOwo+ICtNT0RVTEVfQVVUSE9SKCJLZXZlciBZYW5nIDxrZXZlci55YW5nQHJvY2st Y2hpcHMuY29tPiIpOwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIlJvY2tjaGlwIFVTQiBUWVBFLUMg UEhZIGRyaXZlciIpOwo+ICtNT0RVTEVfTElDRU5TRSgiR1BMIHYyIik7Cj4gCgoKLS0gCkJlc3Qg UmVnYXJkcywKQ2hhbndvbyBDaG9pCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpMaW51eC1yb2NrY2hpcCBtYWlsaW5nIGxpc3QKTGludXgtcm9ja2NoaXBA bGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xp c3RpbmZvL2xpbnV4LXJvY2tjaGlwCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: cw00.choi@samsung.com (Chanwoo Choi) Date: Tue, 23 Aug 2016 14:44:54 +0900 Subject: [v13.1 PATCH 2/5] phy: Add USB Type-C PHY driver for rk3399 In-Reply-To: <1471928576-12941-1-git-send-email-zyw@rock-chips.com> References: <1471928576-12941-1-git-send-email-zyw@rock-chips.com> Message-ID: <57BBE2D6.8050102@samsung.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Chris, The name of 'SuperSpeed' property is changed from EXTCON_PROP_USB_SUPERSPEED to EXTCON_PROP_USB_SS. The name change was discussed on mail thread[1]. Also, this driver depend on the extcon git repository. So, I created the immutable branch(ib-extcon-phy-4.9)[2] for phy framework to prevent the build error before merging the Linus git repository. [1] https://lkml.org/lkml/2016/8/17/622 [2] git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git ib-extcon-phy-4.9 Regards, Chanwoo Choi On 2016? 08? 23? 14:02, Chris Zhong wrote: > Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB > Type-C PHY is designed to support the USB3 and DP applications. > The USB3 operates in SuperSpeed mode and the DP can operate at RBR, > HBR and HBR2 data rates. This driver create 2 PHY devices separately > for USB3 and DisplyPort, and registers them under the child node. > > Signed-off-by: Chris Zhong > Signed-off-by: Kever Yang > Reviewed-by: Guenter Roeck > Tested-by: Guenter Roeck > > --- > > Changes in v13.1: > - add some description in front of driver > - change name of usb to usb3 > - add a USB3 RX register configuration > > Changes in v13: > - do not return err if nothing connected with Type-C, when usb phy power on, > since the USB core driver will call phy power without USB3 device connected. > > Changes in v12: > - enable DP+USB3 mode, only when EXTCON_PROP_USB_SUPERSPEED equal 1 > and DP is attached > > Changes in v11: > - make a clearer demarcation between usb phy and dp phy. > > Changes in v10: > - do not control dp select and hpd config in phy driver > > Changes in v9: > - the new_mode should be int not u8 > - move mutex_lock(&tcphy->lock); to earlier place. in > rockchip_usb3_phy_power_off > - better mutex lock for phy mode and flip > - split the Type-C PHY into two PHYs: USB3 and DP > > Changes in v8: > - set the default cable id to EXTCON_USB_HOST > - optimization Error log > > Changes in v7: > - support new API of extcon > > Changes in v6: > - delete the support of PIN_ASSIGN_A/B > - set the default mode to MODE_DFP_USB > - disable DP PLL at USB3 only mode > > Changes in v5: > - support get property from extcon > - remove PIN ASSIGN A/B support > > Changes in v4: > - select EXTCON > - use phy framework to control the USB3 and DP function > - rename PIN_MAP_ to PIN_ASSIGN_ > > Changes in v3: > - remove the phy framework(Kishon Vijay Abraham I) > - add parentheses around the macro > - use a single space between type and name > - add spaces after opening and before closing braces. > - use u16 for register value > - remove type-c phy header file > - CodingStyle optimization > - use some cable extcon to get type-c port information > - add a extcon to notify Display Port > > Changes in v2: > - select RESET_CONTROLLER > - alphabetic order > - modify some spelling mistakes > - make mode cleaner > - use bool for enable/disable > - check all of the return value > - return a better err number > - use more readx_poll_timeout() > - clk_disable_unprepare(tcphy->clk_ref); > - remove unuse functions, rockchip_typec_phy_power_on/off > - remove unnecessary typecast from void * > - use dts node to distinguish between phys. > > Changes in v1: > - update the licence note > - init core clock to 50MHz > - use extcon API > - remove unused global > - add some comments for magic num > - change usleep_range(1000, 2000) tousleep_range(1000, 1050) > - remove __func__ from dev_err > - return err number when get clk failed > - remove ADDR_ADJ define > - use devm_clk_get(&pdev->dev, "tcpdcore") > > drivers/phy/Kconfig | 9 + > drivers/phy/Makefile | 1 + > drivers/phy/phy-rockchip-typec.c | 1013 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 1023 insertions(+) > create mode 100644 drivers/phy/phy-rockchip-typec.c > > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig > index 42f3e30..c775fd7 100644 > --- a/drivers/phy/Kconfig > +++ b/drivers/phy/Kconfig > @@ -348,6 +348,15 @@ config PHY_ROCKCHIP_PCIE > help > Enable this to support the Rockchip PCIe PHY. > > +config PHY_ROCKCHIP_TYPEC > + tristate "Rockchip TYPEC PHY Driver" > + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) > + select EXTCON > + select GENERIC_PHY > + select RESET_CONTROLLER > + help > + Enable this to support the Rockchip USB TYPEC PHY. > + > config PHY_ST_SPEAR1310_MIPHY > tristate "ST SPEAR1310-MIPHY driver" > select GENERIC_PHY > diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile > index fbb91e7..5d58b63 100644 > --- a/drivers/phy/Makefile > +++ b/drivers/phy/Makefile > @@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o > obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o > obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o > obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o > +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o > obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o > obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o > obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o > diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c > new file mode 100644 > index 0000000..fff1b27 > --- /dev/null > +++ b/drivers/phy/phy-rockchip-typec.c > @@ -0,0 +1,1013 @@ > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author: Chris Zhong > + * Kever Yang > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * The ROCKCHIP Type-C PHY has two PLL clocks. The first PLL clock > + * is used for USB3, the second PLL clock is used for DP. This Type-C PHY has > + * 3 working modes: USB3 only mode, DP only mode, and USB3+DP mode. > + * At USB3 only mode, both PLL clocks need to be initialized, this allows the > + * PHY to switch mode between USB3 and USB3+DP, without disconnecting the USB > + * device. > + * In The DP only mode, only the DP PLL needs to be powered on, and the 4 lanes > + * are all used for DP. > + * > + * This driver gets extcon cable state and property, then decides which mode to > + * select: > + * > + * 1. USB3 only mode: > + * EXTCON_USB or EXTCON_USB_HOST state is true, and > + * EXTCON_PROP_USB_SUPERSPEED property is true. > + * EXTCON_DISP_DP state is false. > + * > + * 2. DP only mode: > + * EXTCON_DISP_DP state is true, and > + * EXTCON_PROP_USB_SUPERSPEED property is false. > + * If EXTCON_USB_HOST state is true, it is DP + USB2 mode, since the USB2 phy > + * is a separate phy, so this case is still DP only mode. > + * > + * 3. USB3+DP mode: > + * EXTCON_USB_HOST and EXTCON_DISP_DP are both true, and > + * EXTCON_PROP_USB_SUPERSPEED property is true. > + * > + * This Type-C PHY driver supports normal and flip orientation. The orientation > + * is reported by the EXTCON_PROP_USB_TYPEC_POLARITY property: true is flip > + * orientation, false is normal orientation. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#define CMN_SSM_BANDGAP (0x21 << 2) > +#define CMN_SSM_BIAS (0x22 << 2) > +#define CMN_PLLSM0_PLLEN (0x29 << 2) > +#define CMN_PLLSM0_PLLPRE (0x2a << 2) > +#define CMN_PLLSM0_PLLVREF (0x2b << 2) > +#define CMN_PLLSM0_PLLLOCK (0x2c << 2) > +#define CMN_PLLSM1_PLLEN (0x31 << 2) > +#define CMN_PLLSM1_PLLPRE (0x32 << 2) > +#define CMN_PLLSM1_PLLVREF (0x33 << 2) > +#define CMN_PLLSM1_PLLLOCK (0x34 << 2) > +#define CMN_PLLSM1_USER_DEF_CTRL (0x37 << 2) > +#define CMN_ICAL_OVRD (0xc1 << 2) > +#define CMN_PLL0_VCOCAL_OVRD (0x83 << 2) > +#define CMN_PLL0_VCOCAL_INIT (0x84 << 2) > +#define CMN_PLL0_VCOCAL_ITER (0x85 << 2) > +#define CMN_PLL0_LOCK_REFCNT_START (0x90 << 2) > +#define CMN_PLL0_LOCK_PLLCNT_START (0x92 << 2) > +#define CMN_PLL0_LOCK_PLLCNT_THR (0x93 << 2) > +#define CMN_PLL0_INTDIV (0x94 << 2) > +#define CMN_PLL0_FRACDIV (0x95 << 2) > +#define CMN_PLL0_HIGH_THR (0x96 << 2) > +#define CMN_PLL0_DSM_DIAG (0x97 << 2) > +#define CMN_PLL0_SS_CTRL1 (0x98 << 2) > +#define CMN_PLL0_SS_CTRL2 (0x99 << 2) > +#define CMN_PLL1_VCOCAL_START (0xa1 << 2) > +#define CMN_PLL1_VCOCAL_OVRD (0xa3 << 2) > +#define CMN_PLL1_VCOCAL_INIT (0xa4 << 2) > +#define CMN_PLL1_VCOCAL_ITER (0xa5 << 2) > +#define CMN_PLL1_LOCK_REFCNT_START (0xb0 << 2) > +#define CMN_PLL1_LOCK_PLLCNT_START (0xb2 << 2) > +#define CMN_PLL1_LOCK_PLLCNT_THR (0xb3 << 2) > +#define CMN_PLL1_INTDIV (0xb4 << 2) > +#define CMN_PLL1_FRACDIV (0xb5 << 2) > +#define CMN_PLL1_HIGH_THR (0xb6 << 2) > +#define CMN_PLL1_DSM_DIAG (0xb7 << 2) > +#define CMN_PLL1_SS_CTRL1 (0xb8 << 2) > +#define CMN_PLL1_SS_CTRL2 (0xb9 << 2) > +#define CMN_RXCAL_OVRD (0xd1 << 2) > +#define CMN_TXPUCAL_CTRL (0xe0 << 2) > +#define CMN_TXPUCAL_OVRD (0xe1 << 2) > +#define CMN_TXPDCAL_OVRD (0xf1 << 2) > +#define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) > +#define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) > +#define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) > +#define CMN_DIAG_PLL0_V2I_TUNE (0x1c5 << 2) > +#define CMN_DIAG_PLL0_CP_TUNE (0x1c6 << 2) > +#define CMN_DIAG_PLL0_LF_PROG (0x1c7 << 2) > +#define CMN_DIAG_PLL1_FBH_OVRD (0x1d0 << 2) > +#define CMN_DIAG_PLL1_FBL_OVRD (0x1d1 << 2) > +#define CMN_DIAG_PLL1_OVRD (0x1d2 << 2) > +#define CMN_DIAG_PLL1_V2I_TUNE (0x1d5 << 2) > +#define CMN_DIAG_PLL1_CP_TUNE (0x1d6 << 2) > +#define CMN_DIAG_PLL1_LF_PROG (0x1d7 << 2) > +#define CMN_DIAG_PLL1_PTATIS_TUNE1 (0x1d8 << 2) > +#define CMN_DIAG_PLL1_PTATIS_TUNE2 (0x1d9 << 2) > +#define CMN_DIAG_PLL1_INCLK_CTRL (0x1da << 2) > +#define CMN_DIAG_HSCLK_SEL (0x1e0 << 2) > + > +#define XCVR_PSM_RCTRL(n) ((0x4001 | ((n) << 9)) << 2) > +#define XCVR_PSM_CAL_TMR(n) ((0x4002 | ((n) << 9)) << 2) > +#define XCVR_PSM_A0IN_TMR(n) ((0x4003 | ((n) << 9)) << 2) > +#define TX_TXCC_CAL_SCLR_MULT(n) ((0x4047 | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_00(n) ((0x404c | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_01(n) ((0x404d | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_10(n) ((0x404e | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_11(n) ((0x404f | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_000(n) ((0x4050 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_001(n) ((0x4051 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_010(n) ((0x4052 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_011(n) ((0x4053 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_100(n) ((0x4054 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_101(n) ((0x4055 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_110(n) ((0x4056 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_111(n) ((0x4057 | ((n) << 9)) << 2) > +#define XCVR_DIAG_PLLDRC_CTRL(n) ((0x40e0 | ((n) << 9)) << 2) > +#define XCVR_DIAG_BIDI_CTRL(n) ((0x40e8 | ((n) << 9)) << 2) > +#define XCVR_DIAG_LANE_FCM_EN_MGN(n) ((0x40f2 | ((n) << 9)) << 2) > +#define TX_PSC_A0(n) ((0x4100 | ((n) << 9)) << 2) > +#define TX_PSC_A1(n) ((0x4101 | ((n) << 9)) << 2) > +#define TX_PSC_A2(n) ((0x4102 | ((n) << 9)) << 2) > +#define TX_PSC_A3(n) ((0x4103 | ((n) << 9)) << 2) > +#define TX_RCVDET_CTRL(n) ((0x4120 | ((n) << 9)) << 2) > +#define TX_RCVDET_EN_TMR(n) ((0x4122 | ((n) << 9)) << 2) > +#define TX_RCVDET_ST_TMR(n) ((0x4123 | ((n) << 9)) << 2) > +#define TX_DIAG_TX_DRV(n) ((0x41e1 | ((n) << 9)) << 2) > +#define TX_DIAG_BGREF_PREDRV_DELAY (0x41e7 << 2) > +#define TX_ANA_CTRL_REG_1 (0x5020 << 2) > +#define TX_ANA_CTRL_REG_2 (0x5021 << 2) > +#define TXDA_COEFF_CALC_CTRL (0x5022 << 2) > +#define TX_DIG_CTRL_REG_2 (0x5024 << 2) > +#define TXDA_CYA_AUXDA_CYA (0x5025 << 2) > +#define TX_ANA_CTRL_REG_3 (0x5026 << 2) > +#define TX_ANA_CTRL_REG_4 (0x5027 << 2) > +#define TX_ANA_CTRL_REG_5 (0x5029 << 2) > + > +#define RX_PSC_A0(n) ((0x8000 | ((n) << 9)) << 2) > +#define RX_PSC_A1(n) ((0x8001 | ((n) << 9)) << 2) > +#define RX_PSC_A2(n) ((0x8002 | ((n) << 9)) << 2) > +#define RX_PSC_A3(n) ((0x8003 | ((n) << 9)) << 2) > +#define RX_PSC_CAL(n) ((0x8006 | ((n) << 9)) << 2) > +#define RX_PSC_RDY(n) ((0x8007 | ((n) << 9)) << 2) > +#define RX_IQPI_ILL_CAL_OVRD (0x8023 << 2) > +#define RX_EPI_ILL_CAL_OVRD (0x8033 << 2) > +#define RX_SDCAL0_OVRD (0x8041 << 2) > +#define RX_SDCAL1_OVRD (0x8049 << 2) > +#define RX_SLC_INIT (0x806d << 2) > +#define RX_SLC_RUN (0x806e << 2) > +#define RX_CDRLF_CNFG2 (0x8081 << 2) > +#define RX_SIGDET_HL_FILT_TMR(n) ((0x8090 | ((n) << 9)) << 2) > +#define RX_SLC_IOP0_OVRD (0x8101 << 2) > +#define RX_SLC_IOP1_OVRD (0x8105 << 2) > +#define RX_SLC_QOP0_OVRD (0x8109 << 2) > +#define RX_SLC_QOP1_OVRD (0x810d << 2) > +#define RX_SLC_EOP0_OVRD (0x8111 << 2) > +#define RX_SLC_EOP1_OVRD (0x8115 << 2) > +#define RX_SLC_ION0_OVRD (0x8119 << 2) > +#define RX_SLC_ION1_OVRD (0x811d << 2) > +#define RX_SLC_QON0_OVRD (0x8121 << 2) > +#define RX_SLC_QON1_OVRD (0x8125 << 2) > +#define RX_SLC_EON0_OVRD (0x8129 << 2) > +#define RX_SLC_EON1_OVRD (0x812d << 2) > +#define RX_SLC_IEP0_OVRD (0x8131 << 2) > +#define RX_SLC_IEP1_OVRD (0x8135 << 2) > +#define RX_SLC_QEP0_OVRD (0x8139 << 2) > +#define RX_SLC_QEP1_OVRD (0x813d << 2) > +#define RX_SLC_EEP0_OVRD (0x8141 << 2) > +#define RX_SLC_EEP1_OVRD (0x8145 << 2) > +#define RX_SLC_IEN0_OVRD (0x8149 << 2) > +#define RX_SLC_IEN1_OVRD (0x814d << 2) > +#define RX_SLC_QEN0_OVRD (0x8151 << 2) > +#define RX_SLC_QEN1_OVRD (0x8155 << 2) > +#define RX_SLC_EEN0_OVRD (0x8159 << 2) > +#define RX_SLC_EEN1_OVRD (0x815d << 2) > +#define RX_REE_CTRL_DATA_MASK(n) ((0x81bb | ((n) << 9)) << 2) > +#define RX_DIAG_SIGDET_TUNE(n) ((0x81dc | ((n) << 9)) << 2) > +#define RX_DIAG_SC2C_DELAY (0x81e1 << 2) > + > +#define PMA_LANE_CFG (0xc000 << 2) > +#define PIPE_CMN_CTRL1 (0xc001 << 2) > +#define PIPE_CMN_CTRL2 (0xc002 << 2) > +#define PIPE_COM_LOCK_CFG1 (0xc003 << 2) > +#define PIPE_COM_LOCK_CFG2 (0xc004 << 2) > +#define PIPE_RCV_DET_INH (0xc005 << 2) > +#define DP_MODE_CTL (0xc008 << 2) > +#define DP_CLK_CTL (0xc009 << 2) > +#define STS (0xc00F << 2) > +#define PHY_ISO_CMN_CTRL (0xc010 << 2) > +#define PHY_DP_TX_CTL (0xc408 << 2) > +#define PMA_CMN_CTRL1 (0xc800 << 2) > +#define PHY_PMA_ISO_CMN_CTRL (0xc810 << 2) > +#define PHY_ISOLATION_CTRL (0xc81f << 2) > +#define PHY_PMA_ISO_XCVR_CTRL(n) ((0xcc11 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_LINK_MODE(n) ((0xcc12 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_PWRST_CTRL(n) ((0xcc13 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_TX_DATA_LO(n) ((0xcc14 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_TX_DATA_HI(n) ((0xcc15 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_RX_DATA_LO(n) ((0xcc16 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_RX_DATA_HI(n) ((0xcc17 | ((n) << 6)) << 2) > +#define TX_BIST_CTRL(n) ((0x4140 | ((n) << 9)) << 2) > +#define TX_BIST_UDDWR(n) ((0x4141 | ((n) << 9)) << 2) > + > +/* > + * Selects which PLL clock will be driven on the analog high speed > + * clock 0: PLL 0 div 1 > + * clock 1: PLL 1 div 2 > + */ > +#define CLK_PLL_CONFIG 0X30 > +#define CLK_PLL_MASK 0x33 > + > +#define CMN_READY BIT(0) > + > +#define DP_PLL_CLOCK_ENABLE BIT(2) > +#define DP_PLL_ENABLE BIT(0) > +#define DP_PLL_DATA_RATE_RBR ((2 << 12) | (4 << 8)) > +#define DP_PLL_DATA_RATE_HBR ((2 << 12) | (4 << 8)) > +#define DP_PLL_DATA_RATE_HBR2 ((1 << 12) | (2 << 8)) > + > +#define DP_MODE_A0 BIT(4) > +#define DP_MODE_A2 BIT(6) > +#define DP_MODE_ENTER_A0 0xc101 > +#define DP_MODE_ENTER_A2 0xc104 > + > +#define PHY_MODE_SET_TIMEOUT 100000 > + > +#define PIN_ASSIGN_C_E 0x51d9 > +#define PIN_ASSIGN_D_F 0x5100 > + > +#define MODE_DISCONNECT 0 > +#define MODE_UFP_USB BIT(0) > +#define MODE_DFP_USB BIT(1) > +#define MODE_DFP_DP BIT(2) > + > +struct usb3phy_reg { > + u32 offset; > + u32 enable_bit; > + u32 write_enable; > +}; > + > +struct rockchip_usb3phy_port_cfg { > + struct usb3phy_reg typec_conn_dir; > + struct usb3phy_reg usb3tousb2_en; > + struct usb3phy_reg external_psm; > + struct usb3phy_reg pipe_status; > +}; > + > +struct rockchip_typec_phy { > + struct device *dev; > + void __iomem *base; > + struct extcon_dev *extcon; > + struct regmap *grf_regs; > + struct clk *clk_core; > + struct clk *clk_ref; > + struct reset_control *uphy_rst; > + struct reset_control *pipe_rst; > + struct reset_control *tcphy_rst; > + struct rockchip_usb3phy_port_cfg port_cfgs; > + /* mutex to protect access to individual PHYs */ > + struct mutex lock; > + > + bool flip; > + u8 mode; > +}; > + > +struct phy_reg { > + u16 value; > + u32 addr; > +}; > + > +struct phy_reg usb3_pll_cfg[] = { > + { 0xf0, CMN_PLL0_VCOCAL_INIT }, > + { 0x18, CMN_PLL0_VCOCAL_ITER }, > + { 0xd0, CMN_PLL0_INTDIV }, > + { 0x4a4a, CMN_PLL0_FRACDIV }, > + { 0x34, CMN_PLL0_HIGH_THR }, > + { 0x1ee, CMN_PLL0_SS_CTRL1 }, > + { 0x7f03, CMN_PLL0_SS_CTRL2 }, > + { 0x20, CMN_PLL0_DSM_DIAG }, > + { 0, CMN_DIAG_PLL0_OVRD }, > + { 0, CMN_DIAG_PLL0_FBH_OVRD }, > + { 0, CMN_DIAG_PLL0_FBL_OVRD }, > + { 0x7, CMN_DIAG_PLL0_V2I_TUNE }, > + { 0x45, CMN_DIAG_PLL0_CP_TUNE }, > + { 0x8, CMN_DIAG_PLL0_LF_PROG }, > +}; > + > +struct phy_reg dp_pll_cfg[] = { > + { 0xf0, CMN_PLL1_VCOCAL_INIT }, > + { 0x18, CMN_PLL1_VCOCAL_ITER }, > + { 0x30b9, CMN_PLL1_VCOCAL_START }, > + { 0x21c, CMN_PLL1_INTDIV }, > + { 0, CMN_PLL1_FRACDIV }, > + { 0x5, CMN_PLL1_HIGH_THR }, > + { 0x35, CMN_PLL1_SS_CTRL1 }, > + { 0x7f1e, CMN_PLL1_SS_CTRL2 }, > + { 0x20, CMN_PLL1_DSM_DIAG }, > + { 0, CMN_PLLSM1_USER_DEF_CTRL }, > + { 0, CMN_DIAG_PLL1_OVRD }, > + { 0, CMN_DIAG_PLL1_FBH_OVRD }, > + { 0, CMN_DIAG_PLL1_FBL_OVRD }, > + { 0x6, CMN_DIAG_PLL1_V2I_TUNE }, > + { 0x45, CMN_DIAG_PLL1_CP_TUNE }, > + { 0x8, CMN_DIAG_PLL1_LF_PROG }, > + { 0x100, CMN_DIAG_PLL1_PTATIS_TUNE1 }, > + { 0x7, CMN_DIAG_PLL1_PTATIS_TUNE2 }, > + { 0x4, CMN_DIAG_PLL1_INCLK_CTRL }, > +}; > + > +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy) > +{ > + u32 i, rdata; > + > + /* > + * cmn_ref_clk_sel = 3, select the 24Mhz for clk parent > + * cmn_psm_clk_dig_div = 2, set the clk division to 2 > + */ > + writel(0x830, tcphy->base + PMA_CMN_CTRL1); > + for (i = 0; i < 4; i++) { > + /* > + * The following PHY configuration assumes a 24 MHz reference > + * clock. > + */ > + writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i)); > + writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i)); > + writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i)); > + } > + > + rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL); > + rdata &= ~CLK_PLL_MASK; > + rdata |= CLK_PLL_CONFIG; > + writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL); > +} > + > +static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy) > +{ > + u32 i; > + > + /* load the configuration of PLL0 */ > + for (i = 0; i < ARRAY_SIZE(usb3_pll_cfg); i++) > + writel(usb3_pll_cfg[i].value, > + tcphy->base + usb3_pll_cfg[i].addr); > +} > + > +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy) > +{ > + u32 i; > + > + /* set the default mode to RBR */ > + writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR, > + tcphy->base + DP_CLK_CTL); > + > + /* load the configuration of PLL1 */ > + for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++) > + writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr); > +} > + > +static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + writel(0x7799, tcphy->base + TX_PSC_A0(lane)); > + writel(0x7798, tcphy->base + TX_PSC_A1(lane)); > + writel(0x5098, tcphy->base + TX_PSC_A2(lane)); > + writel(0x5098, tcphy->base + TX_PSC_A3(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); > + writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); > +} > + > +static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + writel(0xa6fd, tcphy->base + RX_PSC_A0(lane)); > + writel(0xa6fd, tcphy->base + RX_PSC_A1(lane)); > + writel(0xa410, tcphy->base + RX_PSC_A2(lane)); > + writel(0x2410, tcphy->base + RX_PSC_A3(lane)); > + writel(0x23ff, tcphy->base + RX_PSC_CAL(lane)); > + writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane)); > + writel(0x03e7, tcphy->base + RX_REE_CTRL_DATA_MASK(lane)); > + writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane)); > + writel(0x2010, tcphy->base + RX_PSC_RDY(lane)); > + writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); > +} > + > +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + u16 rdata; > + > + writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane)); > + writel(0x6799, tcphy->base + TX_PSC_A0(lane)); > + writel(0x6798, tcphy->base + TX_PSC_A1(lane)); > + writel(0x98, tcphy->base + TX_PSC_A2(lane)); > + writel(0x98, tcphy->base + TX_PSC_A3(lane)); > + > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane)); > + > + writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane)); > + writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane)); > + > + rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); > + rdata = (rdata & 0x8fff) | 0x6000; > + writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); > +} > + > +static inline int property_enable(struct rockchip_typec_phy *tcphy, > + const struct usb3phy_reg *reg, bool en) > +{ > + u32 mask = 1 << reg->write_enable; > + u32 val = en << reg->enable_bit; > + > + return regmap_write(tcphy->grf_regs, reg->offset, val | mask); > +} > + > +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) > +{ > + u16 rdata, rdata2, val; > + > + /* disable txda_cal_latch_en for rewrite the calibration values */ > + rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); > + val = rdata & 0xdfff; > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + > + /* > + * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and > + * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it > + * works. > + */ > + rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2); > + rdata = rdata & 0xffc0; > + > + rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL); > + rdata2 = rdata2 & 0x3f; > + > + val = rdata | rdata2; > + writel(val, tcphy->base + TX_DIG_CTRL_REG_2); > + usleep_range(1000, 1050); > + > + /* > + * Enable signal for latch that sample and holds calibration values. > + * Activate this signal for 1 clock cycle to sample new calibration > + * values. > + */ > + rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); > + val = rdata | 0x2000; > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + usleep_range(150, 200); > + > + /* set TX Voltage Level and TX Deemphasis to 0 */ > + writel(0, tcphy->base + PHY_DP_TX_CTL); > + /* re-enable decap */ > + writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1); > + writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1); > + > + writel(0, tcphy->base + TX_ANA_CTRL_REG_5); > + > + /* > + * Programs txda_drv_ldo_prog[15:0], Sets driver LDO > + * voltage 16'h1001 for DP-AUX-TX and RX > + */ > + writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4); > + > + /* re-enables Bandgap reference for LDO */ > + writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1); > + writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1); > + > + /* > + * re-enables the transmitter pre-driver, driver data selection MUX, > + * and receiver detect circuits. > + */ > + writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2); > + > + /* > + * BIT 12: Controls auxda_polarity, which selects the polarity of the > + * xcvr: > + * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull > + * down aux_m) > + * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down > + * aux_p) > + */ > + val = 0xa078; > + if (!tcphy->flip) > + val |= BIT(12); > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + > + writel(0, tcphy->base + TX_ANA_CTRL_REG_3); > + writel(0, tcphy->base + TX_ANA_CTRL_REG_4); > + writel(0, tcphy->base + TX_ANA_CTRL_REG_5); > + > + /* > + * Controls low_power_swing_en, set the voltage swing of the driver > + * to 400mv. The values below are peak to peak (differential) values. > + */ > + writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL); > + writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA); > + > + /* Controls tx_high_z_tm_en */ > + val = readl(tcphy->base + TX_DIG_CTRL_REG_2); > + val |= BIT(15); > + writel(val, tcphy->base + TX_DIG_CTRL_REG_2); > +} > + > +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + int ret, i; > + u32 val; > + > + ret = clk_prepare_enable(tcphy->clk_core); > + if (ret) { > + dev_err(tcphy->dev, "Failed to prepare_enable core clock\n"); > + return ret; > + } > + > + ret = clk_prepare_enable(tcphy->clk_ref); > + if (ret) { > + dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n"); > + goto err_clk_core; > + } > + > + reset_control_deassert(tcphy->tcphy_rst); > + > + property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); > + > + tcphy_cfg_24m(tcphy); > + > + if (mode == MODE_DFP_DP) { > + tcphy_cfg_dp_pll(tcphy); > + for (i = 0; i < 4; i++) > + tcphy_dp_cfg_lane(tcphy, i); > + > + writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG); > + } else { > + tcphy_cfg_usb3_pll(tcphy); > + tcphy_cfg_dp_pll(tcphy); > + if (tcphy->flip) { > + tcphy_tx_usb3_cfg_lane(tcphy, 3); > + tcphy_rx_usb3_cfg_lane(tcphy, 2); > + tcphy_dp_cfg_lane(tcphy, 0); > + tcphy_dp_cfg_lane(tcphy, 1); > + } else { > + tcphy_tx_usb3_cfg_lane(tcphy, 0); > + tcphy_rx_usb3_cfg_lane(tcphy, 1); > + tcphy_dp_cfg_lane(tcphy, 2); > + tcphy_dp_cfg_lane(tcphy, 3); > + } > + > + writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG); > + } > + > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + > + reset_control_deassert(tcphy->uphy_rst); > + > + ret = readx_poll_timeout(readl, tcphy->base + PMA_CMN_CTRL1, > + val, val & CMN_READY, 10, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + dev_err(tcphy->dev, "wait pma ready timeout\n"); > + ret = -ETIMEDOUT; > + goto err_wait_pma; > + } > + > + reset_control_deassert(tcphy->pipe_rst); > + > + return 0; > + > +err_wait_pma: > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->tcphy_rst); > + clk_disable_unprepare(tcphy->clk_ref); > +err_clk_core: > + clk_disable_unprepare(tcphy->clk_core); > + return ret; > +} > + > +static void tcphy_phy_deinit(struct rockchip_typec_phy *tcphy) > +{ > + reset_control_assert(tcphy->tcphy_rst); > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->pipe_rst); > + clk_disable_unprepare(tcphy->clk_core); > + clk_disable_unprepare(tcphy->clk_ref); > +} > + > +static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) > +{ > + struct extcon_dev *edev = tcphy->extcon; > + union extcon_property_value property; > + unsigned int id; > + bool dfp, ufp, dp; > + u8 mode; > + int ret; > + > + ufp = extcon_get_state(edev, EXTCON_USB); > + dfp = extcon_get_state(edev, EXTCON_USB_HOST); > + dp = extcon_get_state(edev, EXTCON_DISP_DP); > + > + mode = MODE_DFP_USB; > + id = EXTCON_USB_HOST; > + > + if (ufp) { > + mode = MODE_UFP_USB; > + id = EXTCON_USB; > + } else if (dp) { > + mode = MODE_DFP_DP; > + id = EXTCON_DISP_DP; > + > + ret = extcon_get_property(edev, id, EXTCON_PROP_USB_SUPERSPEED, > + &property); > + if (ret) { > + dev_err(tcphy->dev, "get superspeed property failed\n"); > + return ret; > + } > + > + if (property.intval) > + mode |= MODE_DFP_USB; > + } > + > + ret = extcon_get_property(edev, id, EXTCON_PROP_USB_TYPEC_POLARITY, > + &property); > + if (ret) { > + dev_err(tcphy->dev, "get polarity property failed\n"); > + return ret; > + } > + > + tcphy->flip = property.intval ? 1 : 0; > + > + return mode; > +} > + > +static int rockchip_usb3_phy_power_on(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + const struct usb3phy_reg *reg = &cfg->pipe_status; > + int timeout, new_mode, ret = 0; > + u32 val; > + > + mutex_lock(&tcphy->lock); > + > + new_mode = tcphy_get_mode(tcphy); > + if (new_mode < 0) { > + ret = new_mode; > + goto unlock_ret; > + } > + > + /* DP-only mode; fall back to USB2 */ > + if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB))) > + goto unlock_ret; > + > + if (tcphy->mode == new_mode) > + goto unlock_ret; > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_init(tcphy, new_mode); > + > + /* wait TCPHY for pipe ready */ > + for (timeout = 0; timeout < 100; timeout++) { > + regmap_read(tcphy->grf_regs, reg->offset, &val); > + if (!(val & BIT(reg->enable_bit))) { > + tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB); > + goto unlock_ret; > + } > + usleep_range(10, 20); > + } > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > + ret = -ETIMEDOUT; > + > +unlock_ret: > + mutex_unlock(&tcphy->lock); > + return ret; > +} > + > +static int rockchip_usb3_phy_power_off(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + > + mutex_lock(&tcphy->lock); > + > + if (tcphy->mode == MODE_DISCONNECT) > + goto unlock; > + > + tcphy->mode &= ~(MODE_UFP_USB | MODE_DFP_USB); > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > +unlock: > + mutex_unlock(&tcphy->lock); > + return 0; > +} > + > +static const struct phy_ops rockchip_usb3_phy_ops = { > + .power_on = rockchip_usb3_phy_power_on, > + .power_off = rockchip_usb3_phy_power_off, > + .owner = THIS_MODULE, > +}; > + > +static int rockchip_dp_phy_power_on(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + int new_mode, ret = 0; > + u32 val; > + > + mutex_lock(&tcphy->lock); > + > + new_mode = tcphy_get_mode(tcphy); > + if (new_mode < 0) { > + ret = new_mode; > + goto unlock_ret; > + } > + > + if (!(new_mode & MODE_DFP_DP)) { > + ret = -ENODEV; > + goto unlock_ret; > + } > + > + if (tcphy->mode == new_mode) > + goto unlock_ret; > + > + /* > + * If the PHY has been power on, but the mode is not DP only mode, > + * re-init the PHY for setting all of 4 lanes to DP. > + */ > + if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) { > + tcphy_phy_deinit(tcphy); > + tcphy_phy_init(tcphy, new_mode); > + } else if (tcphy->mode == MODE_DISCONNECT) { > + tcphy_phy_init(tcphy, new_mode); > + } > + > + ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, > + val, val & DP_MODE_A2, 1000, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n"); > + goto power_on_finish; > + } > + > + tcphy_dp_aux_calibration(tcphy); > + > + writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL); > + > + ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, > + val, val & DP_MODE_A0, 1000, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n"); > + goto power_on_finish; > + } > + > + tcphy->mode |= MODE_DFP_DP; > + > +power_on_finish: > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > +unlock_ret: > + mutex_unlock(&tcphy->lock); > + return ret; > +} > + > +static int rockchip_dp_phy_power_off(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + > + mutex_lock(&tcphy->lock); > + > + if (tcphy->mode == MODE_DISCONNECT) > + goto unlock; > + > + tcphy->mode &= ~MODE_DFP_DP; > + > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > +unlock: > + mutex_unlock(&tcphy->lock); > + return 0; > +} > + > +static const struct phy_ops rockchip_dp_phy_ops = { > + .power_on = rockchip_dp_phy_power_on, > + .power_off = rockchip_dp_phy_power_off, > + .owner = THIS_MODULE, > +}; > + > +static int tcphy_get_param(struct device *dev, > + struct usb3phy_reg *reg, > + const char *name) > +{ > + u32 buffer[3]; > + int ret; > + > + ret = of_property_read_u32_array(dev->of_node, name, buffer, 3); > + if (ret) { > + dev_err(dev, "Can not parse %s\n", name); > + return ret; > + } > + > + reg->offset = buffer[0]; > + reg->enable_bit = buffer[1]; > + reg->write_enable = buffer[2]; > + return 0; > +} > + > +static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy, > + struct device *dev) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + int ret; > + > + ret = tcphy_get_param(dev, &cfg->typec_conn_dir, > + "rockchip,typec-conn-dir"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->usb3tousb2_en, > + "rockchip,usb3tousb2-en"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->external_psm, > + "rockchip,external-psm"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->pipe_status, > + "rockchip,pipe-status"); > + if (ret) > + return ret; > + > + tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node, > + "rockchip,grf"); > + if (IS_ERR(tcphy->grf_regs)) { > + dev_err(dev, "could not find grf dt node\n"); > + return PTR_ERR(tcphy->grf_regs); > + } > + > + tcphy->clk_core = devm_clk_get(dev, "tcpdcore"); > + if (IS_ERR(tcphy->clk_core)) { > + dev_err(dev, "could not get uphy core clock\n"); > + return PTR_ERR(tcphy->clk_core); > + } > + > + tcphy->clk_ref = devm_clk_get(dev, "tcpdphy-ref"); > + if (IS_ERR(tcphy->clk_ref)) { > + dev_err(dev, "could not get uphy ref clock\n"); > + return PTR_ERR(tcphy->clk_ref); > + } > + > + tcphy->uphy_rst = devm_reset_control_get(dev, "uphy"); > + if (IS_ERR(tcphy->uphy_rst)) { > + dev_err(dev, "no uphy_rst reset control found\n"); > + return PTR_ERR(tcphy->uphy_rst); > + } > + > + tcphy->pipe_rst = devm_reset_control_get(dev, "uphy-pipe"); > + if (IS_ERR(tcphy->pipe_rst)) { > + dev_err(dev, "no pipe_rst reset control found\n"); > + return PTR_ERR(tcphy->pipe_rst); > + } > + > + tcphy->tcphy_rst = devm_reset_control_get(dev, "uphy-tcphy"); > + if (IS_ERR(tcphy->tcphy_rst)) { > + dev_err(dev, "no tcphy_rst reset control found\n"); > + return PTR_ERR(tcphy->tcphy_rst); > + } > + > + return 0; > +} > + > +static void typec_phy_pre_init(struct rockchip_typec_phy *tcphy) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + > + reset_control_assert(tcphy->tcphy_rst); > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->pipe_rst); > + > + /* select external psm clock */ > + property_enable(tcphy, &cfg->external_psm, 1); > + property_enable(tcphy, &cfg->usb3tousb2_en, 0); > + > + tcphy->mode = MODE_DISCONNECT; > +} > + > +static int rockchip_typec_phy_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node *np = dev->of_node; > + struct device_node *child_np; > + struct rockchip_typec_phy *tcphy; > + struct phy_provider *phy_provider; > + struct resource *res; > + int ret; > + > + tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL); > + if (!tcphy) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + tcphy->base = devm_ioremap_resource(dev, res); > + if (IS_ERR(tcphy->base)) > + return PTR_ERR(tcphy->base); > + > + ret = tcphy_parse_dt(tcphy, dev); > + if (ret) > + return ret; > + > + tcphy->dev = dev; > + platform_set_drvdata(pdev, tcphy); > + mutex_init(&tcphy->lock); > + > + typec_phy_pre_init(tcphy); > + > + tcphy->extcon = extcon_get_edev_by_phandle(dev, 0); > + if (IS_ERR(tcphy->extcon)) { > + if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER) > + dev_err(dev, "Invalid or missing extcon\n"); > + return PTR_ERR(tcphy->extcon); > + } > + > + for_each_available_child_of_node(np, child_np) { > + struct phy *phy; > + > + if (!of_node_cmp(child_np->name, "dp-port")) > + phy = devm_phy_create(dev, child_np, > + &rockchip_dp_phy_ops); > + else if (!of_node_cmp(child_np->name, "usb3-port")) > + phy = devm_phy_create(dev, child_np, > + &rockchip_usb3_phy_ops); > + else > + continue; > + > + if (IS_ERR(phy)) { > + dev_err(dev, "failed to create phy: %s\n", > + child_np->name); > + return PTR_ERR(phy); > + } > + > + phy_set_drvdata(phy, tcphy); > + } > + > + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); > + if (IS_ERR(phy_provider)) { > + dev_err(dev, "Failed to register phy provider\n"); > + return PTR_ERR(phy_provider); > + } > + > + return 0; > +} > + > +static const struct of_device_id rockchip_typec_phy_dt_ids[] = { > + { .compatible = "rockchip,rk3399-typec-phy" }, > + {} > +}; > + > +MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids); > + > +static struct platform_driver rockchip_typec_phy_driver = { > + .probe = rockchip_typec_phy_probe, > + .driver = { > + .name = "rockchip-typec-phy", > + .of_match_table = rockchip_typec_phy_dt_ids, > + }, > +}; > + > +module_platform_driver(rockchip_typec_phy_driver); > + > +MODULE_AUTHOR("Chris Zhong "); > +MODULE_AUTHOR("Kever Yang "); > +MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver"); > +MODULE_LICENSE("GPL v2"); > -- Best Regards, Chanwoo Choi From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755795AbcHWFzE (ORCPT ); Tue, 23 Aug 2016 01:55:04 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:48221 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753423AbcHWFzC (ORCPT ); Tue, 23 Aug 2016 01:55:02 -0400 MIME-version: 1.0 Content-type: text/plain; charset=UTF-8 X-AuditID: cbfee68d-f79286d000007a9a-09-57bbe2d7ebeb Content-transfer-encoding: 8BIT Message-id: <57BBE2D6.8050102@samsung.com> Date: Tue, 23 Aug 2016 14:44:54 +0900 From: Chanwoo Choi Organization: Samsung Electronics User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 To: Chris Zhong , groeck@google.com, =?UTF-8?B?SGVpa28=?= =?UTF-8?B?IFN0w7xibmVy?= , kishon@ti.com Cc: linux-rockchip@lists.infradead.org, yzq@rock-chips.com, linux-kernel@vger.kernel.org, briannorris@chromium.org, dianders@chromium.org, tfiga@chromium.org, kever.yang@rock-chips.com, marcheu@chromium.org, groeck@chromium.org, wulf@rock-chips.com, linux-arm-kernel@lists.infradead.org, "cpgs (cpgs@samsung.com)" Subject: Re: [v13.1 PATCH 2/5] phy: Add USB Type-C PHY driver for rk3399 References: <1471928576-12941-1-git-send-email-zyw@rock-chips.com> In-reply-to: <1471928576-12941-1-git-send-email-zyw@rock-chips.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrBIsWRmVeSWpSXmKPExsWyRsSkUPf6o93hBpceC1ps+vie1eLlIU2L s8sOslmcerWM2aJ30RIWi/+PXrNabJv+k83iwtMeNotNj6+xWlzeNYfN4tOD/8wW8w79ZrT4 3PqPzWLV2uPMFnPXLWGzmP9gB7ODgMfshossHgs2lXpsXlLv8XfWfhaPvi2rGD22X5vH7HH8 xnYmj8+b5AI4orhsUlJzMstSi/TtErgyGu8HF9zfzlSxZMZr5gbGfz8Zuxg5OSQETCR+L9kA ZYtJXLi3nq2LkYtDSGAFo8Sq8y+YYIpWrm1mhkjMYpS409HCApLgFRCU+DH5HpDNwcEsIC9x 5FI2SJhZQF1i0rxFUPUPGCW63l5lgqjXkpi/+xlYL4uAqsTavx1gcTag+P4XN9hAbH4BRYmr Px4zgswUFYiQ6D5RCTJHRKCTUWJL4xQWEIdZ4BqTxOR/P8CKhAU8JO79y4ZYdp9R4vLEe+wg cU4BZ4n117xB4hICOzgktp27yQyxWEDi2+RDYEdLCMhKbDrADPGkpMTBFTdYJjCKz0Ly2iyE 12YheW0BI/MqRtHUguSC4qT0IkO94sTc4tK8dL3k/NxNjMAEcPrfs94djLcPWB9iFOBgVOLh 3cG+O1yINbGsuDL3EKMp0BETmaVEk/OBaSavJN7Q2MzIwtTE1NjI3NJMSZxXUepnsJBAemJJ anZqakFqUXxRaU5q8SFGJg5OqQZGl0cRC+9cDF/x5aum/KTNd9IKg4wZlhxjjfV4f4l5+3G2 H7Xut8UWXLiQq8nePzlILiftzpZTcX3pXAxTNO+uLZpzivdl4A0FVb0gcYUlHfFCcv8quPnV 3/Vp9B/cIT7HTd0/4dTtneeyDEP4Pq15p/v64LIb641muaa+f7TmR4by8QmnZ7m+U2Ipzkg0 1GIuKk4EAFRKzAT7AgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrKKsWRmVeSWpSXmKPExsVy+t9jQd3rj3aHG2y+yGqx6eN7VouXhzQt zi47yGZx6tUyZoveRUtYLP4/es1qsW36TzaLC0972Cw2Pb7GanF51xw2i08P/jNbzDv0m9Hi c+s/NotVa48zW8xdt4TNYv6DHcwOAh6zGy6yeCzYVOqxeUm9x99Z+1k8+rasYvTYfm0es8fx G9uZPD5vkgvgiGpgtMlITUxJLVJIzUvOT8nMS7dV8g6Od443NTMw1DW0tDBXUshLzE21VXLx CdB1y8wBekBJoSwxpxQoFJBYXKykb4dpQmiIm64FTGOErm9IEFyPkQEaSFjDmNF4P7jg/nam iiUzXjM3MP77ydjFyMkhIWAisXJtMzOELSZx4d56ti5GLg4hgVmMEnc6WlhAErwCghI/Jt8D sjk4mAXkJY5cygYJMwuoS0yat4gZov4Bo0TX26tMEPVaEvN3PwPrZRFQlVj7twMszgYU3//i BhuIzS+gKHH1x2NGkJmiAhES3ScqQeaICHQySmxpnMIC4jALXGOSmPzvB1iRsICHxL1/2RDL 7jNKXJ54jx0kzingLLH+mvcERsFZSE6dhXDqLCSnLmBkXsUokVqQXFCclJ5rlJdarlecmFtc mpeul5yfu4kRnGSeSe9gPLzL/RCjAAejEg/vjbzd4UKsiWXFlbmHGCU4mJVEeL/cBwrxpiRW VqUW5ccXleakFh9iNAX6dSKzlGhyPjAB5pXEGxqbmBlZGpkbWhgZmyuJ8z7+vy5MSCA9sSQ1 OzW1ILUIpo+Jg1OqgdHq7GfDi1wfeW5vSwpV1hMtPfpX9uSxz5venz2otUJ//oQQE9WrCXnX HPLTlJR+re8JCml5XPB0/rsdwnx+5TErZ9ldKmO5da9vj5/ompkeiasC2zsD17NxWflM5tjw MjLdoMPLqe6q9y32fVLs2v12whUXxIQnLJM/ariiS2Vt3HOnSmP2bUosxRmJhlrMRcWJAFWX Y31IAwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Chris, The name of 'SuperSpeed' property is changed from EXTCON_PROP_USB_SUPERSPEED to EXTCON_PROP_USB_SS. The name change was discussed on mail thread[1]. Also, this driver depend on the extcon git repository. So, I created the immutable branch(ib-extcon-phy-4.9)[2] for phy framework to prevent the build error before merging the Linus git repository. [1] https://lkml.org/lkml/2016/8/17/622 [2] git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git ib-extcon-phy-4.9 Regards, Chanwoo Choi On 2016년 08월 23일 14:02, Chris Zhong wrote: > Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB > Type-C PHY is designed to support the USB3 and DP applications. > The USB3 operates in SuperSpeed mode and the DP can operate at RBR, > HBR and HBR2 data rates. This driver create 2 PHY devices separately > for USB3 and DisplyPort, and registers them under the child node. > > Signed-off-by: Chris Zhong > Signed-off-by: Kever Yang > Reviewed-by: Guenter Roeck > Tested-by: Guenter Roeck > > --- > > Changes in v13.1: > - add some description in front of driver > - change name of usb to usb3 > - add a USB3 RX register configuration > > Changes in v13: > - do not return err if nothing connected with Type-C, when usb phy power on, > since the USB core driver will call phy power without USB3 device connected. > > Changes in v12: > - enable DP+USB3 mode, only when EXTCON_PROP_USB_SUPERSPEED equal 1 > and DP is attached > > Changes in v11: > - make a clearer demarcation between usb phy and dp phy. > > Changes in v10: > - do not control dp select and hpd config in phy driver > > Changes in v9: > - the new_mode should be int not u8 > - move mutex_lock(&tcphy->lock); to earlier place. in > rockchip_usb3_phy_power_off > - better mutex lock for phy mode and flip > - split the Type-C PHY into two PHYs: USB3 and DP > > Changes in v8: > - set the default cable id to EXTCON_USB_HOST > - optimization Error log > > Changes in v7: > - support new API of extcon > > Changes in v6: > - delete the support of PIN_ASSIGN_A/B > - set the default mode to MODE_DFP_USB > - disable DP PLL at USB3 only mode > > Changes in v5: > - support get property from extcon > - remove PIN ASSIGN A/B support > > Changes in v4: > - select EXTCON > - use phy framework to control the USB3 and DP function > - rename PIN_MAP_ to PIN_ASSIGN_ > > Changes in v3: > - remove the phy framework(Kishon Vijay Abraham I) > - add parentheses around the macro > - use a single space between type and name > - add spaces after opening and before closing braces. > - use u16 for register value > - remove type-c phy header file > - CodingStyle optimization > - use some cable extcon to get type-c port information > - add a extcon to notify Display Port > > Changes in v2: > - select RESET_CONTROLLER > - alphabetic order > - modify some spelling mistakes > - make mode cleaner > - use bool for enable/disable > - check all of the return value > - return a better err number > - use more readx_poll_timeout() > - clk_disable_unprepare(tcphy->clk_ref); > - remove unuse functions, rockchip_typec_phy_power_on/off > - remove unnecessary typecast from void * > - use dts node to distinguish between phys. > > Changes in v1: > - update the licence note > - init core clock to 50MHz > - use extcon API > - remove unused global > - add some comments for magic num > - change usleep_range(1000, 2000) tousleep_range(1000, 1050) > - remove __func__ from dev_err > - return err number when get clk failed > - remove ADDR_ADJ define > - use devm_clk_get(&pdev->dev, "tcpdcore") > > drivers/phy/Kconfig | 9 + > drivers/phy/Makefile | 1 + > drivers/phy/phy-rockchip-typec.c | 1013 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 1023 insertions(+) > create mode 100644 drivers/phy/phy-rockchip-typec.c > > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig > index 42f3e30..c775fd7 100644 > --- a/drivers/phy/Kconfig > +++ b/drivers/phy/Kconfig > @@ -348,6 +348,15 @@ config PHY_ROCKCHIP_PCIE > help > Enable this to support the Rockchip PCIe PHY. > > +config PHY_ROCKCHIP_TYPEC > + tristate "Rockchip TYPEC PHY Driver" > + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) > + select EXTCON > + select GENERIC_PHY > + select RESET_CONTROLLER > + help > + Enable this to support the Rockchip USB TYPEC PHY. > + > config PHY_ST_SPEAR1310_MIPHY > tristate "ST SPEAR1310-MIPHY driver" > select GENERIC_PHY > diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile > index fbb91e7..5d58b63 100644 > --- a/drivers/phy/Makefile > +++ b/drivers/phy/Makefile > @@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o > obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o > obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o > obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o > +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o > obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o > obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o > obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o > diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c > new file mode 100644 > index 0000000..fff1b27 > --- /dev/null > +++ b/drivers/phy/phy-rockchip-typec.c > @@ -0,0 +1,1013 @@ > +/* > + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd > + * Author: Chris Zhong > + * Kever Yang > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * The ROCKCHIP Type-C PHY has two PLL clocks. The first PLL clock > + * is used for USB3, the second PLL clock is used for DP. This Type-C PHY has > + * 3 working modes: USB3 only mode, DP only mode, and USB3+DP mode. > + * At USB3 only mode, both PLL clocks need to be initialized, this allows the > + * PHY to switch mode between USB3 and USB3+DP, without disconnecting the USB > + * device. > + * In The DP only mode, only the DP PLL needs to be powered on, and the 4 lanes > + * are all used for DP. > + * > + * This driver gets extcon cable state and property, then decides which mode to > + * select: > + * > + * 1. USB3 only mode: > + * EXTCON_USB or EXTCON_USB_HOST state is true, and > + * EXTCON_PROP_USB_SUPERSPEED property is true. > + * EXTCON_DISP_DP state is false. > + * > + * 2. DP only mode: > + * EXTCON_DISP_DP state is true, and > + * EXTCON_PROP_USB_SUPERSPEED property is false. > + * If EXTCON_USB_HOST state is true, it is DP + USB2 mode, since the USB2 phy > + * is a separate phy, so this case is still DP only mode. > + * > + * 3. USB3+DP mode: > + * EXTCON_USB_HOST and EXTCON_DISP_DP are both true, and > + * EXTCON_PROP_USB_SUPERSPEED property is true. > + * > + * This Type-C PHY driver supports normal and flip orientation. The orientation > + * is reported by the EXTCON_PROP_USB_TYPEC_POLARITY property: true is flip > + * orientation, false is normal orientation. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#define CMN_SSM_BANDGAP (0x21 << 2) > +#define CMN_SSM_BIAS (0x22 << 2) > +#define CMN_PLLSM0_PLLEN (0x29 << 2) > +#define CMN_PLLSM0_PLLPRE (0x2a << 2) > +#define CMN_PLLSM0_PLLVREF (0x2b << 2) > +#define CMN_PLLSM0_PLLLOCK (0x2c << 2) > +#define CMN_PLLSM1_PLLEN (0x31 << 2) > +#define CMN_PLLSM1_PLLPRE (0x32 << 2) > +#define CMN_PLLSM1_PLLVREF (0x33 << 2) > +#define CMN_PLLSM1_PLLLOCK (0x34 << 2) > +#define CMN_PLLSM1_USER_DEF_CTRL (0x37 << 2) > +#define CMN_ICAL_OVRD (0xc1 << 2) > +#define CMN_PLL0_VCOCAL_OVRD (0x83 << 2) > +#define CMN_PLL0_VCOCAL_INIT (0x84 << 2) > +#define CMN_PLL0_VCOCAL_ITER (0x85 << 2) > +#define CMN_PLL0_LOCK_REFCNT_START (0x90 << 2) > +#define CMN_PLL0_LOCK_PLLCNT_START (0x92 << 2) > +#define CMN_PLL0_LOCK_PLLCNT_THR (0x93 << 2) > +#define CMN_PLL0_INTDIV (0x94 << 2) > +#define CMN_PLL0_FRACDIV (0x95 << 2) > +#define CMN_PLL0_HIGH_THR (0x96 << 2) > +#define CMN_PLL0_DSM_DIAG (0x97 << 2) > +#define CMN_PLL0_SS_CTRL1 (0x98 << 2) > +#define CMN_PLL0_SS_CTRL2 (0x99 << 2) > +#define CMN_PLL1_VCOCAL_START (0xa1 << 2) > +#define CMN_PLL1_VCOCAL_OVRD (0xa3 << 2) > +#define CMN_PLL1_VCOCAL_INIT (0xa4 << 2) > +#define CMN_PLL1_VCOCAL_ITER (0xa5 << 2) > +#define CMN_PLL1_LOCK_REFCNT_START (0xb0 << 2) > +#define CMN_PLL1_LOCK_PLLCNT_START (0xb2 << 2) > +#define CMN_PLL1_LOCK_PLLCNT_THR (0xb3 << 2) > +#define CMN_PLL1_INTDIV (0xb4 << 2) > +#define CMN_PLL1_FRACDIV (0xb5 << 2) > +#define CMN_PLL1_HIGH_THR (0xb6 << 2) > +#define CMN_PLL1_DSM_DIAG (0xb7 << 2) > +#define CMN_PLL1_SS_CTRL1 (0xb8 << 2) > +#define CMN_PLL1_SS_CTRL2 (0xb9 << 2) > +#define CMN_RXCAL_OVRD (0xd1 << 2) > +#define CMN_TXPUCAL_CTRL (0xe0 << 2) > +#define CMN_TXPUCAL_OVRD (0xe1 << 2) > +#define CMN_TXPDCAL_OVRD (0xf1 << 2) > +#define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) > +#define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) > +#define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) > +#define CMN_DIAG_PLL0_V2I_TUNE (0x1c5 << 2) > +#define CMN_DIAG_PLL0_CP_TUNE (0x1c6 << 2) > +#define CMN_DIAG_PLL0_LF_PROG (0x1c7 << 2) > +#define CMN_DIAG_PLL1_FBH_OVRD (0x1d0 << 2) > +#define CMN_DIAG_PLL1_FBL_OVRD (0x1d1 << 2) > +#define CMN_DIAG_PLL1_OVRD (0x1d2 << 2) > +#define CMN_DIAG_PLL1_V2I_TUNE (0x1d5 << 2) > +#define CMN_DIAG_PLL1_CP_TUNE (0x1d6 << 2) > +#define CMN_DIAG_PLL1_LF_PROG (0x1d7 << 2) > +#define CMN_DIAG_PLL1_PTATIS_TUNE1 (0x1d8 << 2) > +#define CMN_DIAG_PLL1_PTATIS_TUNE2 (0x1d9 << 2) > +#define CMN_DIAG_PLL1_INCLK_CTRL (0x1da << 2) > +#define CMN_DIAG_HSCLK_SEL (0x1e0 << 2) > + > +#define XCVR_PSM_RCTRL(n) ((0x4001 | ((n) << 9)) << 2) > +#define XCVR_PSM_CAL_TMR(n) ((0x4002 | ((n) << 9)) << 2) > +#define XCVR_PSM_A0IN_TMR(n) ((0x4003 | ((n) << 9)) << 2) > +#define TX_TXCC_CAL_SCLR_MULT(n) ((0x4047 | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_00(n) ((0x404c | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_01(n) ((0x404d | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_10(n) ((0x404e | ((n) << 9)) << 2) > +#define TX_TXCC_CPOST_MULT_11(n) ((0x404f | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_000(n) ((0x4050 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_001(n) ((0x4051 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_010(n) ((0x4052 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_011(n) ((0x4053 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_100(n) ((0x4054 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_101(n) ((0x4055 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_110(n) ((0x4056 | ((n) << 9)) << 2) > +#define TX_TXCC_MGNFS_MULT_111(n) ((0x4057 | ((n) << 9)) << 2) > +#define XCVR_DIAG_PLLDRC_CTRL(n) ((0x40e0 | ((n) << 9)) << 2) > +#define XCVR_DIAG_BIDI_CTRL(n) ((0x40e8 | ((n) << 9)) << 2) > +#define XCVR_DIAG_LANE_FCM_EN_MGN(n) ((0x40f2 | ((n) << 9)) << 2) > +#define TX_PSC_A0(n) ((0x4100 | ((n) << 9)) << 2) > +#define TX_PSC_A1(n) ((0x4101 | ((n) << 9)) << 2) > +#define TX_PSC_A2(n) ((0x4102 | ((n) << 9)) << 2) > +#define TX_PSC_A3(n) ((0x4103 | ((n) << 9)) << 2) > +#define TX_RCVDET_CTRL(n) ((0x4120 | ((n) << 9)) << 2) > +#define TX_RCVDET_EN_TMR(n) ((0x4122 | ((n) << 9)) << 2) > +#define TX_RCVDET_ST_TMR(n) ((0x4123 | ((n) << 9)) << 2) > +#define TX_DIAG_TX_DRV(n) ((0x41e1 | ((n) << 9)) << 2) > +#define TX_DIAG_BGREF_PREDRV_DELAY (0x41e7 << 2) > +#define TX_ANA_CTRL_REG_1 (0x5020 << 2) > +#define TX_ANA_CTRL_REG_2 (0x5021 << 2) > +#define TXDA_COEFF_CALC_CTRL (0x5022 << 2) > +#define TX_DIG_CTRL_REG_2 (0x5024 << 2) > +#define TXDA_CYA_AUXDA_CYA (0x5025 << 2) > +#define TX_ANA_CTRL_REG_3 (0x5026 << 2) > +#define TX_ANA_CTRL_REG_4 (0x5027 << 2) > +#define TX_ANA_CTRL_REG_5 (0x5029 << 2) > + > +#define RX_PSC_A0(n) ((0x8000 | ((n) << 9)) << 2) > +#define RX_PSC_A1(n) ((0x8001 | ((n) << 9)) << 2) > +#define RX_PSC_A2(n) ((0x8002 | ((n) << 9)) << 2) > +#define RX_PSC_A3(n) ((0x8003 | ((n) << 9)) << 2) > +#define RX_PSC_CAL(n) ((0x8006 | ((n) << 9)) << 2) > +#define RX_PSC_RDY(n) ((0x8007 | ((n) << 9)) << 2) > +#define RX_IQPI_ILL_CAL_OVRD (0x8023 << 2) > +#define RX_EPI_ILL_CAL_OVRD (0x8033 << 2) > +#define RX_SDCAL0_OVRD (0x8041 << 2) > +#define RX_SDCAL1_OVRD (0x8049 << 2) > +#define RX_SLC_INIT (0x806d << 2) > +#define RX_SLC_RUN (0x806e << 2) > +#define RX_CDRLF_CNFG2 (0x8081 << 2) > +#define RX_SIGDET_HL_FILT_TMR(n) ((0x8090 | ((n) << 9)) << 2) > +#define RX_SLC_IOP0_OVRD (0x8101 << 2) > +#define RX_SLC_IOP1_OVRD (0x8105 << 2) > +#define RX_SLC_QOP0_OVRD (0x8109 << 2) > +#define RX_SLC_QOP1_OVRD (0x810d << 2) > +#define RX_SLC_EOP0_OVRD (0x8111 << 2) > +#define RX_SLC_EOP1_OVRD (0x8115 << 2) > +#define RX_SLC_ION0_OVRD (0x8119 << 2) > +#define RX_SLC_ION1_OVRD (0x811d << 2) > +#define RX_SLC_QON0_OVRD (0x8121 << 2) > +#define RX_SLC_QON1_OVRD (0x8125 << 2) > +#define RX_SLC_EON0_OVRD (0x8129 << 2) > +#define RX_SLC_EON1_OVRD (0x812d << 2) > +#define RX_SLC_IEP0_OVRD (0x8131 << 2) > +#define RX_SLC_IEP1_OVRD (0x8135 << 2) > +#define RX_SLC_QEP0_OVRD (0x8139 << 2) > +#define RX_SLC_QEP1_OVRD (0x813d << 2) > +#define RX_SLC_EEP0_OVRD (0x8141 << 2) > +#define RX_SLC_EEP1_OVRD (0x8145 << 2) > +#define RX_SLC_IEN0_OVRD (0x8149 << 2) > +#define RX_SLC_IEN1_OVRD (0x814d << 2) > +#define RX_SLC_QEN0_OVRD (0x8151 << 2) > +#define RX_SLC_QEN1_OVRD (0x8155 << 2) > +#define RX_SLC_EEN0_OVRD (0x8159 << 2) > +#define RX_SLC_EEN1_OVRD (0x815d << 2) > +#define RX_REE_CTRL_DATA_MASK(n) ((0x81bb | ((n) << 9)) << 2) > +#define RX_DIAG_SIGDET_TUNE(n) ((0x81dc | ((n) << 9)) << 2) > +#define RX_DIAG_SC2C_DELAY (0x81e1 << 2) > + > +#define PMA_LANE_CFG (0xc000 << 2) > +#define PIPE_CMN_CTRL1 (0xc001 << 2) > +#define PIPE_CMN_CTRL2 (0xc002 << 2) > +#define PIPE_COM_LOCK_CFG1 (0xc003 << 2) > +#define PIPE_COM_LOCK_CFG2 (0xc004 << 2) > +#define PIPE_RCV_DET_INH (0xc005 << 2) > +#define DP_MODE_CTL (0xc008 << 2) > +#define DP_CLK_CTL (0xc009 << 2) > +#define STS (0xc00F << 2) > +#define PHY_ISO_CMN_CTRL (0xc010 << 2) > +#define PHY_DP_TX_CTL (0xc408 << 2) > +#define PMA_CMN_CTRL1 (0xc800 << 2) > +#define PHY_PMA_ISO_CMN_CTRL (0xc810 << 2) > +#define PHY_ISOLATION_CTRL (0xc81f << 2) > +#define PHY_PMA_ISO_XCVR_CTRL(n) ((0xcc11 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_LINK_MODE(n) ((0xcc12 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_PWRST_CTRL(n) ((0xcc13 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_TX_DATA_LO(n) ((0xcc14 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_TX_DATA_HI(n) ((0xcc15 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_RX_DATA_LO(n) ((0xcc16 | ((n) << 6)) << 2) > +#define PHY_PMA_ISO_RX_DATA_HI(n) ((0xcc17 | ((n) << 6)) << 2) > +#define TX_BIST_CTRL(n) ((0x4140 | ((n) << 9)) << 2) > +#define TX_BIST_UDDWR(n) ((0x4141 | ((n) << 9)) << 2) > + > +/* > + * Selects which PLL clock will be driven on the analog high speed > + * clock 0: PLL 0 div 1 > + * clock 1: PLL 1 div 2 > + */ > +#define CLK_PLL_CONFIG 0X30 > +#define CLK_PLL_MASK 0x33 > + > +#define CMN_READY BIT(0) > + > +#define DP_PLL_CLOCK_ENABLE BIT(2) > +#define DP_PLL_ENABLE BIT(0) > +#define DP_PLL_DATA_RATE_RBR ((2 << 12) | (4 << 8)) > +#define DP_PLL_DATA_RATE_HBR ((2 << 12) | (4 << 8)) > +#define DP_PLL_DATA_RATE_HBR2 ((1 << 12) | (2 << 8)) > + > +#define DP_MODE_A0 BIT(4) > +#define DP_MODE_A2 BIT(6) > +#define DP_MODE_ENTER_A0 0xc101 > +#define DP_MODE_ENTER_A2 0xc104 > + > +#define PHY_MODE_SET_TIMEOUT 100000 > + > +#define PIN_ASSIGN_C_E 0x51d9 > +#define PIN_ASSIGN_D_F 0x5100 > + > +#define MODE_DISCONNECT 0 > +#define MODE_UFP_USB BIT(0) > +#define MODE_DFP_USB BIT(1) > +#define MODE_DFP_DP BIT(2) > + > +struct usb3phy_reg { > + u32 offset; > + u32 enable_bit; > + u32 write_enable; > +}; > + > +struct rockchip_usb3phy_port_cfg { > + struct usb3phy_reg typec_conn_dir; > + struct usb3phy_reg usb3tousb2_en; > + struct usb3phy_reg external_psm; > + struct usb3phy_reg pipe_status; > +}; > + > +struct rockchip_typec_phy { > + struct device *dev; > + void __iomem *base; > + struct extcon_dev *extcon; > + struct regmap *grf_regs; > + struct clk *clk_core; > + struct clk *clk_ref; > + struct reset_control *uphy_rst; > + struct reset_control *pipe_rst; > + struct reset_control *tcphy_rst; > + struct rockchip_usb3phy_port_cfg port_cfgs; > + /* mutex to protect access to individual PHYs */ > + struct mutex lock; > + > + bool flip; > + u8 mode; > +}; > + > +struct phy_reg { > + u16 value; > + u32 addr; > +}; > + > +struct phy_reg usb3_pll_cfg[] = { > + { 0xf0, CMN_PLL0_VCOCAL_INIT }, > + { 0x18, CMN_PLL0_VCOCAL_ITER }, > + { 0xd0, CMN_PLL0_INTDIV }, > + { 0x4a4a, CMN_PLL0_FRACDIV }, > + { 0x34, CMN_PLL0_HIGH_THR }, > + { 0x1ee, CMN_PLL0_SS_CTRL1 }, > + { 0x7f03, CMN_PLL0_SS_CTRL2 }, > + { 0x20, CMN_PLL0_DSM_DIAG }, > + { 0, CMN_DIAG_PLL0_OVRD }, > + { 0, CMN_DIAG_PLL0_FBH_OVRD }, > + { 0, CMN_DIAG_PLL0_FBL_OVRD }, > + { 0x7, CMN_DIAG_PLL0_V2I_TUNE }, > + { 0x45, CMN_DIAG_PLL0_CP_TUNE }, > + { 0x8, CMN_DIAG_PLL0_LF_PROG }, > +}; > + > +struct phy_reg dp_pll_cfg[] = { > + { 0xf0, CMN_PLL1_VCOCAL_INIT }, > + { 0x18, CMN_PLL1_VCOCAL_ITER }, > + { 0x30b9, CMN_PLL1_VCOCAL_START }, > + { 0x21c, CMN_PLL1_INTDIV }, > + { 0, CMN_PLL1_FRACDIV }, > + { 0x5, CMN_PLL1_HIGH_THR }, > + { 0x35, CMN_PLL1_SS_CTRL1 }, > + { 0x7f1e, CMN_PLL1_SS_CTRL2 }, > + { 0x20, CMN_PLL1_DSM_DIAG }, > + { 0, CMN_PLLSM1_USER_DEF_CTRL }, > + { 0, CMN_DIAG_PLL1_OVRD }, > + { 0, CMN_DIAG_PLL1_FBH_OVRD }, > + { 0, CMN_DIAG_PLL1_FBL_OVRD }, > + { 0x6, CMN_DIAG_PLL1_V2I_TUNE }, > + { 0x45, CMN_DIAG_PLL1_CP_TUNE }, > + { 0x8, CMN_DIAG_PLL1_LF_PROG }, > + { 0x100, CMN_DIAG_PLL1_PTATIS_TUNE1 }, > + { 0x7, CMN_DIAG_PLL1_PTATIS_TUNE2 }, > + { 0x4, CMN_DIAG_PLL1_INCLK_CTRL }, > +}; > + > +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy) > +{ > + u32 i, rdata; > + > + /* > + * cmn_ref_clk_sel = 3, select the 24Mhz for clk parent > + * cmn_psm_clk_dig_div = 2, set the clk division to 2 > + */ > + writel(0x830, tcphy->base + PMA_CMN_CTRL1); > + for (i = 0; i < 4; i++) { > + /* > + * The following PHY configuration assumes a 24 MHz reference > + * clock. > + */ > + writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i)); > + writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i)); > + writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i)); > + } > + > + rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL); > + rdata &= ~CLK_PLL_MASK; > + rdata |= CLK_PLL_CONFIG; > + writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL); > +} > + > +static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy) > +{ > + u32 i; > + > + /* load the configuration of PLL0 */ > + for (i = 0; i < ARRAY_SIZE(usb3_pll_cfg); i++) > + writel(usb3_pll_cfg[i].value, > + tcphy->base + usb3_pll_cfg[i].addr); > +} > + > +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy) > +{ > + u32 i; > + > + /* set the default mode to RBR */ > + writel(DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE | DP_PLL_DATA_RATE_RBR, > + tcphy->base + DP_CLK_CTL); > + > + /* load the configuration of PLL1 */ > + for (i = 0; i < ARRAY_SIZE(dp_pll_cfg); i++) > + writel(dp_pll_cfg[i].value, tcphy->base + dp_pll_cfg[i].addr); > +} > + > +static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + writel(0x7799, tcphy->base + TX_PSC_A0(lane)); > + writel(0x7798, tcphy->base + TX_PSC_A1(lane)); > + writel(0x5098, tcphy->base + TX_PSC_A2(lane)); > + writel(0x5098, tcphy->base + TX_PSC_A3(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); > + writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); > +} > + > +static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + writel(0xa6fd, tcphy->base + RX_PSC_A0(lane)); > + writel(0xa6fd, tcphy->base + RX_PSC_A1(lane)); > + writel(0xa410, tcphy->base + RX_PSC_A2(lane)); > + writel(0x2410, tcphy->base + RX_PSC_A3(lane)); > + writel(0x23ff, tcphy->base + RX_PSC_CAL(lane)); > + writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane)); > + writel(0x03e7, tcphy->base + RX_REE_CTRL_DATA_MASK(lane)); > + writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane)); > + writel(0x2010, tcphy->base + RX_PSC_RDY(lane)); > + writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); > +} > + > +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) > +{ > + u16 rdata; > + > + writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane)); > + writel(0x6799, tcphy->base + TX_PSC_A0(lane)); > + writel(0x6798, tcphy->base + TX_PSC_A1(lane)); > + writel(0x98, tcphy->base + TX_PSC_A2(lane)); > + writel(0x98, tcphy->base + TX_PSC_A3(lane)); > + > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane)); > + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane)); > + writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane)); > + > + writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane)); > + writel(0x400, tcphy->base + TX_DIAG_TX_DRV(lane)); > + > + rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); > + rdata = (rdata & 0x8fff) | 0x6000; > + writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane)); > +} > + > +static inline int property_enable(struct rockchip_typec_phy *tcphy, > + const struct usb3phy_reg *reg, bool en) > +{ > + u32 mask = 1 << reg->write_enable; > + u32 val = en << reg->enable_bit; > + > + return regmap_write(tcphy->grf_regs, reg->offset, val | mask); > +} > + > +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) > +{ > + u16 rdata, rdata2, val; > + > + /* disable txda_cal_latch_en for rewrite the calibration values */ > + rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); > + val = rdata & 0xdfff; > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + > + /* > + * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and > + * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it > + * works. > + */ > + rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2); > + rdata = rdata & 0xffc0; > + > + rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL); > + rdata2 = rdata2 & 0x3f; > + > + val = rdata | rdata2; > + writel(val, tcphy->base + TX_DIG_CTRL_REG_2); > + usleep_range(1000, 1050); > + > + /* > + * Enable signal for latch that sample and holds calibration values. > + * Activate this signal for 1 clock cycle to sample new calibration > + * values. > + */ > + rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); > + val = rdata | 0x2000; > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + usleep_range(150, 200); > + > + /* set TX Voltage Level and TX Deemphasis to 0 */ > + writel(0, tcphy->base + PHY_DP_TX_CTL); > + /* re-enable decap */ > + writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1); > + writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1); > + > + writel(0, tcphy->base + TX_ANA_CTRL_REG_5); > + > + /* > + * Programs txda_drv_ldo_prog[15:0], Sets driver LDO > + * voltage 16'h1001 for DP-AUX-TX and RX > + */ > + writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4); > + > + /* re-enables Bandgap reference for LDO */ > + writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1); > + writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1); > + > + /* > + * re-enables the transmitter pre-driver, driver data selection MUX, > + * and receiver detect circuits. > + */ > + writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2); > + writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2); > + > + /* > + * BIT 12: Controls auxda_polarity, which selects the polarity of the > + * xcvr: > + * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull > + * down aux_m) > + * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down > + * aux_p) > + */ > + val = 0xa078; > + if (!tcphy->flip) > + val |= BIT(12); > + writel(val, tcphy->base + TX_ANA_CTRL_REG_1); > + > + writel(0, tcphy->base + TX_ANA_CTRL_REG_3); > + writel(0, tcphy->base + TX_ANA_CTRL_REG_4); > + writel(0, tcphy->base + TX_ANA_CTRL_REG_5); > + > + /* > + * Controls low_power_swing_en, set the voltage swing of the driver > + * to 400mv. The values below are peak to peak (differential) values. > + */ > + writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL); > + writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA); > + > + /* Controls tx_high_z_tm_en */ > + val = readl(tcphy->base + TX_DIG_CTRL_REG_2); > + val |= BIT(15); > + writel(val, tcphy->base + TX_DIG_CTRL_REG_2); > +} > + > +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + int ret, i; > + u32 val; > + > + ret = clk_prepare_enable(tcphy->clk_core); > + if (ret) { > + dev_err(tcphy->dev, "Failed to prepare_enable core clock\n"); > + return ret; > + } > + > + ret = clk_prepare_enable(tcphy->clk_ref); > + if (ret) { > + dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n"); > + goto err_clk_core; > + } > + > + reset_control_deassert(tcphy->tcphy_rst); > + > + property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); > + > + tcphy_cfg_24m(tcphy); > + > + if (mode == MODE_DFP_DP) { > + tcphy_cfg_dp_pll(tcphy); > + for (i = 0; i < 4; i++) > + tcphy_dp_cfg_lane(tcphy, i); > + > + writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG); > + } else { > + tcphy_cfg_usb3_pll(tcphy); > + tcphy_cfg_dp_pll(tcphy); > + if (tcphy->flip) { > + tcphy_tx_usb3_cfg_lane(tcphy, 3); > + tcphy_rx_usb3_cfg_lane(tcphy, 2); > + tcphy_dp_cfg_lane(tcphy, 0); > + tcphy_dp_cfg_lane(tcphy, 1); > + } else { > + tcphy_tx_usb3_cfg_lane(tcphy, 0); > + tcphy_rx_usb3_cfg_lane(tcphy, 1); > + tcphy_dp_cfg_lane(tcphy, 2); > + tcphy_dp_cfg_lane(tcphy, 3); > + } > + > + writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG); > + } > + > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + > + reset_control_deassert(tcphy->uphy_rst); > + > + ret = readx_poll_timeout(readl, tcphy->base + PMA_CMN_CTRL1, > + val, val & CMN_READY, 10, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + dev_err(tcphy->dev, "wait pma ready timeout\n"); > + ret = -ETIMEDOUT; > + goto err_wait_pma; > + } > + > + reset_control_deassert(tcphy->pipe_rst); > + > + return 0; > + > +err_wait_pma: > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->tcphy_rst); > + clk_disable_unprepare(tcphy->clk_ref); > +err_clk_core: > + clk_disable_unprepare(tcphy->clk_core); > + return ret; > +} > + > +static void tcphy_phy_deinit(struct rockchip_typec_phy *tcphy) > +{ > + reset_control_assert(tcphy->tcphy_rst); > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->pipe_rst); > + clk_disable_unprepare(tcphy->clk_core); > + clk_disable_unprepare(tcphy->clk_ref); > +} > + > +static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) > +{ > + struct extcon_dev *edev = tcphy->extcon; > + union extcon_property_value property; > + unsigned int id; > + bool dfp, ufp, dp; > + u8 mode; > + int ret; > + > + ufp = extcon_get_state(edev, EXTCON_USB); > + dfp = extcon_get_state(edev, EXTCON_USB_HOST); > + dp = extcon_get_state(edev, EXTCON_DISP_DP); > + > + mode = MODE_DFP_USB; > + id = EXTCON_USB_HOST; > + > + if (ufp) { > + mode = MODE_UFP_USB; > + id = EXTCON_USB; > + } else if (dp) { > + mode = MODE_DFP_DP; > + id = EXTCON_DISP_DP; > + > + ret = extcon_get_property(edev, id, EXTCON_PROP_USB_SUPERSPEED, > + &property); > + if (ret) { > + dev_err(tcphy->dev, "get superspeed property failed\n"); > + return ret; > + } > + > + if (property.intval) > + mode |= MODE_DFP_USB; > + } > + > + ret = extcon_get_property(edev, id, EXTCON_PROP_USB_TYPEC_POLARITY, > + &property); > + if (ret) { > + dev_err(tcphy->dev, "get polarity property failed\n"); > + return ret; > + } > + > + tcphy->flip = property.intval ? 1 : 0; > + > + return mode; > +} > + > +static int rockchip_usb3_phy_power_on(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + const struct usb3phy_reg *reg = &cfg->pipe_status; > + int timeout, new_mode, ret = 0; > + u32 val; > + > + mutex_lock(&tcphy->lock); > + > + new_mode = tcphy_get_mode(tcphy); > + if (new_mode < 0) { > + ret = new_mode; > + goto unlock_ret; > + } > + > + /* DP-only mode; fall back to USB2 */ > + if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB))) > + goto unlock_ret; > + > + if (tcphy->mode == new_mode) > + goto unlock_ret; > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_init(tcphy, new_mode); > + > + /* wait TCPHY for pipe ready */ > + for (timeout = 0; timeout < 100; timeout++) { > + regmap_read(tcphy->grf_regs, reg->offset, &val); > + if (!(val & BIT(reg->enable_bit))) { > + tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB); > + goto unlock_ret; > + } > + usleep_range(10, 20); > + } > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > + ret = -ETIMEDOUT; > + > +unlock_ret: > + mutex_unlock(&tcphy->lock); > + return ret; > +} > + > +static int rockchip_usb3_phy_power_off(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + > + mutex_lock(&tcphy->lock); > + > + if (tcphy->mode == MODE_DISCONNECT) > + goto unlock; > + > + tcphy->mode &= ~(MODE_UFP_USB | MODE_DFP_USB); > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > +unlock: > + mutex_unlock(&tcphy->lock); > + return 0; > +} > + > +static const struct phy_ops rockchip_usb3_phy_ops = { > + .power_on = rockchip_usb3_phy_power_on, > + .power_off = rockchip_usb3_phy_power_off, > + .owner = THIS_MODULE, > +}; > + > +static int rockchip_dp_phy_power_on(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + int new_mode, ret = 0; > + u32 val; > + > + mutex_lock(&tcphy->lock); > + > + new_mode = tcphy_get_mode(tcphy); > + if (new_mode < 0) { > + ret = new_mode; > + goto unlock_ret; > + } > + > + if (!(new_mode & MODE_DFP_DP)) { > + ret = -ENODEV; > + goto unlock_ret; > + } > + > + if (tcphy->mode == new_mode) > + goto unlock_ret; > + > + /* > + * If the PHY has been power on, but the mode is not DP only mode, > + * re-init the PHY for setting all of 4 lanes to DP. > + */ > + if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) { > + tcphy_phy_deinit(tcphy); > + tcphy_phy_init(tcphy, new_mode); > + } else if (tcphy->mode == MODE_DISCONNECT) { > + tcphy_phy_init(tcphy, new_mode); > + } > + > + ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, > + val, val & DP_MODE_A2, 1000, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + dev_err(tcphy->dev, "failed to wait TCPHY enter A2\n"); > + goto power_on_finish; > + } > + > + tcphy_dp_aux_calibration(tcphy); > + > + writel(DP_MODE_ENTER_A0, tcphy->base + DP_MODE_CTL); > + > + ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, > + val, val & DP_MODE_A0, 1000, > + PHY_MODE_SET_TIMEOUT); > + if (ret < 0) { > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n"); > + goto power_on_finish; > + } > + > + tcphy->mode |= MODE_DFP_DP; > + > +power_on_finish: > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > +unlock_ret: > + mutex_unlock(&tcphy->lock); > + return ret; > +} > + > +static int rockchip_dp_phy_power_off(struct phy *phy) > +{ > + struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); > + > + mutex_lock(&tcphy->lock); > + > + if (tcphy->mode == MODE_DISCONNECT) > + goto unlock; > + > + tcphy->mode &= ~MODE_DFP_DP; > + > + writel(DP_MODE_ENTER_A2, tcphy->base + DP_MODE_CTL); > + > + if (tcphy->mode == MODE_DISCONNECT) > + tcphy_phy_deinit(tcphy); > + > +unlock: > + mutex_unlock(&tcphy->lock); > + return 0; > +} > + > +static const struct phy_ops rockchip_dp_phy_ops = { > + .power_on = rockchip_dp_phy_power_on, > + .power_off = rockchip_dp_phy_power_off, > + .owner = THIS_MODULE, > +}; > + > +static int tcphy_get_param(struct device *dev, > + struct usb3phy_reg *reg, > + const char *name) > +{ > + u32 buffer[3]; > + int ret; > + > + ret = of_property_read_u32_array(dev->of_node, name, buffer, 3); > + if (ret) { > + dev_err(dev, "Can not parse %s\n", name); > + return ret; > + } > + > + reg->offset = buffer[0]; > + reg->enable_bit = buffer[1]; > + reg->write_enable = buffer[2]; > + return 0; > +} > + > +static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy, > + struct device *dev) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + int ret; > + > + ret = tcphy_get_param(dev, &cfg->typec_conn_dir, > + "rockchip,typec-conn-dir"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->usb3tousb2_en, > + "rockchip,usb3tousb2-en"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->external_psm, > + "rockchip,external-psm"); > + if (ret) > + return ret; > + > + ret = tcphy_get_param(dev, &cfg->pipe_status, > + "rockchip,pipe-status"); > + if (ret) > + return ret; > + > + tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node, > + "rockchip,grf"); > + if (IS_ERR(tcphy->grf_regs)) { > + dev_err(dev, "could not find grf dt node\n"); > + return PTR_ERR(tcphy->grf_regs); > + } > + > + tcphy->clk_core = devm_clk_get(dev, "tcpdcore"); > + if (IS_ERR(tcphy->clk_core)) { > + dev_err(dev, "could not get uphy core clock\n"); > + return PTR_ERR(tcphy->clk_core); > + } > + > + tcphy->clk_ref = devm_clk_get(dev, "tcpdphy-ref"); > + if (IS_ERR(tcphy->clk_ref)) { > + dev_err(dev, "could not get uphy ref clock\n"); > + return PTR_ERR(tcphy->clk_ref); > + } > + > + tcphy->uphy_rst = devm_reset_control_get(dev, "uphy"); > + if (IS_ERR(tcphy->uphy_rst)) { > + dev_err(dev, "no uphy_rst reset control found\n"); > + return PTR_ERR(tcphy->uphy_rst); > + } > + > + tcphy->pipe_rst = devm_reset_control_get(dev, "uphy-pipe"); > + if (IS_ERR(tcphy->pipe_rst)) { > + dev_err(dev, "no pipe_rst reset control found\n"); > + return PTR_ERR(tcphy->pipe_rst); > + } > + > + tcphy->tcphy_rst = devm_reset_control_get(dev, "uphy-tcphy"); > + if (IS_ERR(tcphy->tcphy_rst)) { > + dev_err(dev, "no tcphy_rst reset control found\n"); > + return PTR_ERR(tcphy->tcphy_rst); > + } > + > + return 0; > +} > + > +static void typec_phy_pre_init(struct rockchip_typec_phy *tcphy) > +{ > + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; > + > + reset_control_assert(tcphy->tcphy_rst); > + reset_control_assert(tcphy->uphy_rst); > + reset_control_assert(tcphy->pipe_rst); > + > + /* select external psm clock */ > + property_enable(tcphy, &cfg->external_psm, 1); > + property_enable(tcphy, &cfg->usb3tousb2_en, 0); > + > + tcphy->mode = MODE_DISCONNECT; > +} > + > +static int rockchip_typec_phy_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node *np = dev->of_node; > + struct device_node *child_np; > + struct rockchip_typec_phy *tcphy; > + struct phy_provider *phy_provider; > + struct resource *res; > + int ret; > + > + tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL); > + if (!tcphy) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + tcphy->base = devm_ioremap_resource(dev, res); > + if (IS_ERR(tcphy->base)) > + return PTR_ERR(tcphy->base); > + > + ret = tcphy_parse_dt(tcphy, dev); > + if (ret) > + return ret; > + > + tcphy->dev = dev; > + platform_set_drvdata(pdev, tcphy); > + mutex_init(&tcphy->lock); > + > + typec_phy_pre_init(tcphy); > + > + tcphy->extcon = extcon_get_edev_by_phandle(dev, 0); > + if (IS_ERR(tcphy->extcon)) { > + if (PTR_ERR(tcphy->extcon) != -EPROBE_DEFER) > + dev_err(dev, "Invalid or missing extcon\n"); > + return PTR_ERR(tcphy->extcon); > + } > + > + for_each_available_child_of_node(np, child_np) { > + struct phy *phy; > + > + if (!of_node_cmp(child_np->name, "dp-port")) > + phy = devm_phy_create(dev, child_np, > + &rockchip_dp_phy_ops); > + else if (!of_node_cmp(child_np->name, "usb3-port")) > + phy = devm_phy_create(dev, child_np, > + &rockchip_usb3_phy_ops); > + else > + continue; > + > + if (IS_ERR(phy)) { > + dev_err(dev, "failed to create phy: %s\n", > + child_np->name); > + return PTR_ERR(phy); > + } > + > + phy_set_drvdata(phy, tcphy); > + } > + > + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); > + if (IS_ERR(phy_provider)) { > + dev_err(dev, "Failed to register phy provider\n"); > + return PTR_ERR(phy_provider); > + } > + > + return 0; > +} > + > +static const struct of_device_id rockchip_typec_phy_dt_ids[] = { > + { .compatible = "rockchip,rk3399-typec-phy" }, > + {} > +}; > + > +MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids); > + > +static struct platform_driver rockchip_typec_phy_driver = { > + .probe = rockchip_typec_phy_probe, > + .driver = { > + .name = "rockchip-typec-phy", > + .of_match_table = rockchip_typec_phy_dt_ids, > + }, > +}; > + > +module_platform_driver(rockchip_typec_phy_driver); > + > +MODULE_AUTHOR("Chris Zhong "); > +MODULE_AUTHOR("Kever Yang "); > +MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver"); > +MODULE_LICENSE("GPL v2"); > -- Best Regards, Chanwoo Choi