From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 737C5C10F14 for ; Tue, 16 Apr 2019 09:45:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4D42020693 for ; Tue, 16 Apr 2019 09:45:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726895AbfDPJpC (ORCPT ); Tue, 16 Apr 2019 05:45:02 -0400 Received: from relmlor2.renesas.com ([210.160.252.172]:48370 "EHLO relmlie6.idc.renesas.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728862AbfDPJpC (ORCPT ); Tue, 16 Apr 2019 05:45:02 -0400 X-IronPort-AV: E=Sophos;i="5.60,357,1549897200"; d="scan'208";a="13206170" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 16 Apr 2019 18:44:59 +0900 Received: from be1yocto.ree.adwin.renesas.com (unknown [172.29.43.62]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id D63DC4038495; Tue, 16 Apr 2019 18:44:56 +0900 (JST) From: Biju Das To: Heikki Krogerus , Chunfeng Yun Cc: Biju Das , Greg Kroah-Hartman , Felipe Balbi , linux-usb@vger.kernel.org, Simon Horman , Yoshihiro Shimoda , Geert Uytterhoeven , Chris Paterson , Fabrizio Castro , linux-renesas-soc@vger.kernel.org Subject: [PATCH V4 3/7] usb: typec: driver for TI HD3SS3220 USB Type-C DRP port controller Date: Tue, 16 Apr 2019 10:38:03 +0100 Message-Id: <1555407487-35394-4-git-send-email-biju.das@bp.renesas.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1555407487-35394-1-git-send-email-biju.das@bp.renesas.com> References: <1555407487-35394-1-git-send-email-biju.das@bp.renesas.com> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Driver for TI HD3SS3220 USB Type-C DRP port controller. The driver currently registers the port and supports data role swapping. Signed-off-by: Biju Das --- Note: This patch has compilation dependency on https://patchwork.kernel.org/patch/10882555/ V3-->V4 * Incorporated Chunfeng Yun's review comment * Used fwnode API's to get usb role switch handle. V2-->V3 * Used the new api "usb_role_switch by node" for getting remote endpoint associated with Type-C USB DRP port controller devices. V1-->V2 * Driver uses usb role class instead of extcon for dual role switch and also handles connect/disconnect events. --- drivers/usb/typec/Kconfig | 10 ++ drivers/usb/typec/Makefile | 1 + drivers/usb/typec/hd3ss3220.c | 263 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 drivers/usb/typec/hd3ss3220.c diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 89d9193..92a3717 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -50,6 +50,16 @@ source "drivers/usb/typec/tcpm/Kconfig" source "drivers/usb/typec/ucsi/Kconfig" +config TYPEC_HD3SS3220 + tristate "TI HD3SS3220 Type-C DRP Port controller driver" + depends on I2C + help + Say Y or M here if your system has TI HD3SS3220 Type-C DRP Port + controller driver. + + If you choose to build this driver as a dynamically linked module, the + module will be called hd3ss3220.ko. + config TYPEC_TPS6598X tristate "TI TPS6598x USB Power Delivery controller driver" depends on I2C diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile index 6696b72..7753a5c3 100644 --- a/drivers/usb/typec/Makefile +++ b/drivers/usb/typec/Makefile @@ -4,5 +4,6 @@ typec-y := class.o mux.o bus.o obj-$(CONFIG_TYPEC) += altmodes/ obj-$(CONFIG_TYPEC_TCPM) += tcpm/ obj-$(CONFIG_TYPEC_UCSI) += ucsi/ +obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o obj-$(CONFIG_TYPEC) += mux/ diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c new file mode 100644 index 0000000..e98a38f --- /dev/null +++ b/drivers/usb/typec/hd3ss3220.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI HD3SS3220 Type-C DRP Port Controller Driver + * + * Copyright (C) 2019 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HD3SS3220_REG_CN_STAT_CTRL 0x09 +#define HD3SS3220_REG_GEN_CTRL 0x0A +#define HD3SS3220_REG_DEV_REV 0xA0 + +/* Register HD3SS3220_REG_CN_STAT_CTRL*/ +#define HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK (BIT(7) | BIT(6)) +#define HD3SS3220_REG_CN_STAT_CTRL_AS_DFP BIT(6) +#define HD3SS3220_REG_CN_STAT_CTRL_AS_UFP BIT(7) +#define HD3SS3220_REG_CN_STAT_CTRL_TO_ACCESSORY (BIT(7) | BIT(6)) +#define HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS BIT(4) + +/* Register HD3SS3220_REG_GEN_CTRL*/ +#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK (BIT(2) | BIT(1)) +#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT 0x00 +#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK BIT(1) +#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC (BIT(2) | BIT(1)) + +struct hd3ss3220 { + struct device *dev; + struct regmap *regmap; + struct usb_role_switch *role_sw; + struct typec_port *port; + struct typec_capability typec_cap; +}; + +static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int src_pref) +{ + return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, + HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK, + src_pref); +} + +static enum usb_role hd3ss3220_get_attached_state(struct hd3ss3220 *hd3ss3220) +{ + unsigned int reg_val; + enum usb_role attached_state; + int ret; + + ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, + ®_val); + if (ret < 0) + return ret; + + switch (reg_val & HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK) { + case HD3SS3220_REG_CN_STAT_CTRL_AS_DFP: + attached_state = USB_ROLE_HOST; + break; + case HD3SS3220_REG_CN_STAT_CTRL_AS_UFP: + attached_state = USB_ROLE_DEVICE; + break; + default: + attached_state = USB_ROLE_NONE; + } + + return attached_state; +} + +static int hd3ss3220_dr_set(const struct typec_capability *cap, + enum typec_data_role role) +{ + struct hd3ss3220 *hd3ss3220 = container_of(cap, struct hd3ss3220, + typec_cap); + enum usb_role role_val; + int pref, ret = 0; + + if (role == TYPEC_HOST) { + role_val = USB_ROLE_HOST; + pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC; + } else { + role_val = USB_ROLE_DEVICE; + pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK; + } + + ret = hd3ss3220_set_source_pref(hd3ss3220, pref); + usleep_range(10, 100); + + usb_role_switch_set_role(hd3ss3220->role_sw, role_val); + typec_set_data_role(hd3ss3220->port, role); + + return ret; +} + +static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220) +{ + enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220); + + usb_role_switch_set_role(hd3ss3220->role_sw, role_state); + if (role_state == USB_ROLE_NONE) + hd3ss3220_set_source_pref(hd3ss3220, + HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT); + + switch (role_state) { + case USB_ROLE_HOST: + typec_set_data_role(hd3ss3220->port, TYPEC_HOST); + break; + case USB_ROLE_DEVICE: + typec_set_data_role(hd3ss3220->port, TYPEC_DEVICE); + break; + default: + break; + } +} + +irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220) +{ + int err; + + hd3ss3220_set_role(hd3ss3220); + err = regmap_update_bits_base(hd3ss3220->regmap, + HD3SS3220_REG_CN_STAT_CTRL, + HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS, + HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS, + NULL, false, true); + if (err < 0) + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static irqreturn_t hd3ss3220_irq_handler(int irq, void *data) +{ + struct i2c_client *client = to_i2c_client(data); + struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client); + + return hd3ss3220_irq(hd3ss3220); +} + +static const struct regmap_config config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0A, +}; + +static int hd3ss3220_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct hd3ss3220 *hd3ss3220; + struct fwnode_handle *parent, *child; + int ret; + unsigned int data; + + hd3ss3220 = devm_kzalloc(&client->dev, sizeof(struct hd3ss3220), + GFP_KERNEL); + if (!hd3ss3220) + return -ENOMEM; + + i2c_set_clientdata(client, hd3ss3220); + + hd3ss3220->dev = &client->dev; + hd3ss3220->regmap = devm_regmap_init_i2c(client, &config); + if (IS_ERR(hd3ss3220->regmap)) + return PTR_ERR(hd3ss3220->regmap); + + hd3ss3220_set_source_pref(hd3ss3220, + HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT); + child = fwnode_graph_get_next_endpoint(dev_fwnode(hd3ss3220->dev), + NULL); + parent = fwnode_graph_get_remote_port_parent(child); + hd3ss3220->role_sw = fwnode_usb_role_switch_get(parent); + if (IS_ERR_OR_NULL(hd3ss3220->role_sw)) { + fwnode_handle_put(child); + fwnode_handle_put(parent); + return PTR_ERR(hd3ss3220->role_sw); + } + + fwnode_handle_put(child); + fwnode_handle_put(parent); + + hd3ss3220->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; + hd3ss3220->typec_cap.dr_set = hd3ss3220_dr_set; + hd3ss3220->typec_cap.type = TYPEC_PORT_DRP; + hd3ss3220->typec_cap.data = TYPEC_PORT_DRD; + + hd3ss3220->port = typec_register_port(&client->dev, + &hd3ss3220->typec_cap); + if (IS_ERR(hd3ss3220->port)) + return PTR_ERR(hd3ss3220->port); + + hd3ss3220_set_role(hd3ss3220); + if (client->irq > 0) { + ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, + &data); + if (ret < 0) + goto error; + + if (data & HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS) { + ret = regmap_write(hd3ss3220->regmap, + HD3SS3220_REG_CN_STAT_CTRL, + data | HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS); + if (ret < 0) + goto error; + } + + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, + hd3ss3220_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "hd3ss3220", &client->dev); + if (ret) + goto error; + } + + ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV); + if (ret < 0) + goto error; + + dev_info(&client->dev, "probed revision=0x%x\n", ret); + + return 0; +error: + typec_unregister_port(hd3ss3220->port); + usb_role_switch_put(hd3ss3220->role_sw); + + return ret; +} + +static int hd3ss3220_remove(struct i2c_client *client) +{ + struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client); + + typec_unregister_port(hd3ss3220->port); + usb_role_switch_put(hd3ss3220->role_sw); + + return 0; +} + +static const struct of_device_id dev_ids[] = { + { .compatible = "ti,hd3ss3220"}, + {} +}; +MODULE_DEVICE_TABLE(of, dev_ids); + +static struct i2c_driver hd3ss3220_driver = { + .driver = { + .name = "hd3ss3220", + .of_match_table = of_match_ptr(dev_ids), + }, + .probe = hd3ss3220_probe, + .remove = hd3ss3220_remove, +}; + +module_i2c_driver(hd3ss3220_driver); + +MODULE_AUTHOR("Biju Das "); +MODULE_DESCRIPTION("TI HD3SS3220 DRP Port Controller Driver"); +MODULE_LICENSE("GPL"); -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [V4,3/7] usb: typec: driver for TI HD3SS3220 USB Type-C DRP port controller From: Biju Das Message-Id: <1555407487-35394-4-git-send-email-biju.das@bp.renesas.com> Date: Tue, 16 Apr 2019 10:38:03 +0100 To: Heikki Krogerus , Chunfeng Yun Cc: Biju Das , Greg Kroah-Hartman , Felipe Balbi , linux-usb@vger.kernel.org, Simon Horman , Yoshihiro Shimoda , Geert Uytterhoeven , Chris Paterson , Fabrizio Castro , linux-renesas-soc@vger.kernel.org List-ID: RHJpdmVyIGZvciBUSSBIRDNTUzMyMjAgVVNCIFR5cGUtQyBEUlAgcG9ydCBjb250cm9sbGVyLgoK VGhlIGRyaXZlciBjdXJyZW50bHkgcmVnaXN0ZXJzIHRoZSBwb3J0IGFuZCBzdXBwb3J0cyBkYXRh IHJvbGUgc3dhcHBpbmcuCgpTaWduZWQtb2ZmLWJ5OiBCaWp1IERhcyA8YmlqdS5kYXNAYnAucmVu ZXNhcy5jb20+Ci0tLQogTm90ZTogVGhpcyBwYXRjaCBoYXMgY29tcGlsYXRpb24gZGVwZW5kZW5j eSBvbiAKIGh0dHBzOi8vcGF0Y2h3b3JrLmtlcm5lbC5vcmcvcGF0Y2gvMTA4ODI1NTUvCiAKIFYz LS0+VjQKICAgKiBJbmNvcnBvcmF0ZWQgQ2h1bmZlbmcgWXVuJ3MgcmV2aWV3IGNvbW1lbnQKICAg KiBVc2VkIGZ3bm9kZSBBUEkncyB0byBnZXQgdXNiIHJvbGUgc3dpdGNoIGhhbmRsZS4KIAogVjIt LT5WMwogICAqIFVzZWQgdGhlIG5ldyBhcGkgInVzYl9yb2xlX3N3aXRjaCBieSBub2RlIiBmb3Ig Z2V0dGluZwogICAgIHJlbW90ZSBlbmRwb2ludCBhc3NvY2lhdGVkIHdpdGggVHlwZS1DIFVTQiBE UlAgcG9ydAogICAgIGNvbnRyb2xsZXIgZGV2aWNlcy4KIFYxLS0+VjIKICAgKiBEcml2ZXIgdXNl cyB1c2Igcm9sZSBjbGFzcyBpbnN0ZWFkIG9mIGV4dGNvbiBmb3IgZHVhbCByb2xlIHN3aXRjaAog ICAgIGFuZCBhbHNvIGhhbmRsZXMgY29ubmVjdC9kaXNjb25uZWN0IGV2ZW50cy4KLS0tCiBkcml2 ZXJzL3VzYi90eXBlYy9LY29uZmlnICAgICB8ICAxMCArKwogZHJpdmVycy91c2IvdHlwZWMvTWFr ZWZpbGUgICAgfCAgIDEgKwogZHJpdmVycy91c2IvdHlwZWMvaGQzc3MzMjIwLmMgfCAyNjMgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiAzIGZpbGVzIGNoYW5nZWQs IDI3NCBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvdHlwZWMv aGQzc3MzMjIwLmMKCmRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi90eXBlYy9LY29uZmlnIGIvZHJp dmVycy91c2IvdHlwZWMvS2NvbmZpZwppbmRleCA4OWQ5MTkzLi45MmEzNzE3IDEwMDY0NAotLS0g YS9kcml2ZXJzL3VzYi90eXBlYy9LY29uZmlnCisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL0tjb25m aWcKQEAgLTUwLDYgKzUwLDE2IEBAIHNvdXJjZSAiZHJpdmVycy91c2IvdHlwZWMvdGNwbS9LY29u ZmlnIgogCiBzb3VyY2UgImRyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvS2NvbmZpZyIKIAorY29uZmln IFRZUEVDX0hEM1NTMzIyMAorCXRyaXN0YXRlICJUSSBIRDNTUzMyMjAgVHlwZS1DIERSUCBQb3J0 IGNvbnRyb2xsZXIgZHJpdmVyIgorCWRlcGVuZHMgb24gSTJDCisJaGVscAorCSAgU2F5IFkgb3Ig TSBoZXJlIGlmIHlvdXIgc3lzdGVtIGhhcyBUSSBIRDNTUzMyMjAgVHlwZS1DIERSUCBQb3J0CisJ ICBjb250cm9sbGVyIGRyaXZlci4KKworCSAgSWYgeW91IGNob29zZSB0byBidWlsZCB0aGlzIGRy aXZlciBhcyBhIGR5bmFtaWNhbGx5IGxpbmtlZCBtb2R1bGUsIHRoZQorCSAgbW9kdWxlIHdpbGwg YmUgY2FsbGVkIGhkM3NzMzIyMC5rby4KKwogY29uZmlnIFRZUEVDX1RQUzY1OThYCiAJdHJpc3Rh dGUgIlRJIFRQUzY1OTh4IFVTQiBQb3dlciBEZWxpdmVyeSBjb250cm9sbGVyIGRyaXZlciIKIAlk ZXBlbmRzIG9uIEkyQwpkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvdHlwZWMvTWFrZWZpbGUgYi9k cml2ZXJzL3VzYi90eXBlYy9NYWtlZmlsZQppbmRleCA2Njk2YjcyLi43NzUzYTVjMyAxMDA2NDQK LS0tIGEvZHJpdmVycy91c2IvdHlwZWMvTWFrZWZpbGUKKysrIGIvZHJpdmVycy91c2IvdHlwZWMv TWFrZWZpbGUKQEAgLTQsNSArNCw2IEBAIHR5cGVjLXkJCQkJOj0gY2xhc3MubyBtdXgubyBidXMu bwogb2JqLSQoQ09ORklHX1RZUEVDKQkJKz0gYWx0bW9kZXMvCiBvYmotJChDT05GSUdfVFlQRUNf VENQTSkJKz0gdGNwbS8KIG9iai0kKENPTkZJR19UWVBFQ19VQ1NJKQkrPSB1Y3NpLworb2JqLSQo Q09ORklHX1RZUEVDX0hEM1NTMzIyMCkJKz0gaGQzc3MzMjIwLm8KIG9iai0kKENPTkZJR19UWVBF Q19UUFM2NTk4WCkJKz0gdHBzNjU5OHgubwogb2JqLSQoQ09ORklHX1RZUEVDKQkJKz0gbXV4Lwpk aWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvdHlwZWMvaGQzc3MzMjIwLmMgYi9kcml2ZXJzL3VzYi90 eXBlYy9oZDNzczMyMjAuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5lOThh MzhmCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy91c2IvdHlwZWMvaGQzc3MzMjIwLmMKQEAg LTAsMCArMSwyNjMgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKworLyoK KyAqIFRJIEhEM1NTMzIyMCBUeXBlLUMgRFJQIFBvcnQgQ29udHJvbGxlciBEcml2ZXIKKyAqCisg KiBDb3B5cmlnaHQgKEMpIDIwMTkgUmVuZXNhcyBFbGVjdHJvbmljcyBDb3JwLgorICovCisKKyNp bmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9pMmMuaD4KKyNpbmNsdWRl IDxsaW51eC91c2Ivcm9sZS5oPgorI2luY2x1ZGUgPGxpbnV4L2lycXJldHVybi5oPgorI2luY2x1 ZGUgPGxpbnV4L2ludGVycnVwdC5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1 ZGUgPGxpbnV4L3JlZ21hcC5oPgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKyNpbmNsdWRlIDxs aW51eC91c2IvdHlwZWMuaD4KKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgorCisjZGVmaW5lIEhE M1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMCTB4MDkKKyNkZWZpbmUgSEQzU1MzMjIwX1JFR19HRU5f Q1RSTAkJMHgwQQorI2RlZmluZSBIRDNTUzMyMjBfUkVHX0RFVl9SRVYJCTB4QTAKKworLyogUmVn aXN0ZXIgSEQzU1MzMjIwX1JFR19DTl9TVEFUX0NUUkwqLworI2RlZmluZSBIRDNTUzMyMjBfUkVH X0NOX1NUQVRfQ1RSTF9BVFRBQ0hFRF9TVEFURV9NQVNLCShCSVQoNykgfCBCSVQoNikpCisjZGVm aW5lIEhEM1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMX0FTX0RGUAkJQklUKDYpCisjZGVmaW5lIEhE M1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMX0FTX1VGUAkJQklUKDcpCisjZGVmaW5lIEhEM1NTMzIy MF9SRUdfQ05fU1RBVF9DVFJMX1RPX0FDQ0VTU09SWQkJKEJJVCg3KSB8IEJJVCg2KSkKKyNkZWZp bmUgSEQzU1MzMjIwX1JFR19DTl9TVEFUX0NUUkxfSU5UX1NUQVRVUwkJQklUKDQpCisKKy8qIFJl Z2lzdGVyIEhEM1NTMzIyMF9SRUdfR0VOX0NUUkwqLworI2RlZmluZSBIRDNTUzMyMjBfUkVHX0dF Tl9DVFJMX1NSQ19QUkVGX01BU0sJCShCSVQoMikgfCBCSVQoMSkpCisjZGVmaW5lIEhEM1NTMzIy MF9SRUdfR0VOX0NUUkxfU1JDX1BSRUZfRFJQX0RFRkFVTFQJMHgwMAorI2RlZmluZSBIRDNTUzMy MjBfUkVHX0dFTl9DVFJMX1NSQ19QUkVGX0RSUF9UUllfU05LCUJJVCgxKQorI2RlZmluZSBIRDNT UzMyMjBfUkVHX0dFTl9DVFJMX1NSQ19QUkVGX0RSUF9UUllfU1JDCShCSVQoMikgfCBCSVQoMSkp CisKK3N0cnVjdCBoZDNzczMyMjAgeworCXN0cnVjdCBkZXZpY2UgKmRldjsKKwlzdHJ1Y3QgcmVn bWFwICpyZWdtYXA7CisJc3RydWN0IHVzYl9yb2xlX3N3aXRjaAkqcm9sZV9zdzsKKwlzdHJ1Y3Qg dHlwZWNfcG9ydCAqcG9ydDsKKwlzdHJ1Y3QgdHlwZWNfY2FwYWJpbGl0eSB0eXBlY19jYXA7Cit9 OworCitzdGF0aWMgaW50IGhkM3NzMzIyMF9zZXRfc291cmNlX3ByZWYoc3RydWN0IGhkM3NzMzIy MCAqaGQzc3MzMjIwLCBpbnQgc3JjX3ByZWYpCit7CisJcmV0dXJuIHJlZ21hcF91cGRhdGVfYml0 cyhoZDNzczMyMjAtPnJlZ21hcCwgSEQzU1MzMjIwX1JFR19HRU5fQ1RSTCwKKwkJCQkgIEhEM1NT MzIyMF9SRUdfR0VOX0NUUkxfU1JDX1BSRUZfTUFTSywKKwkJCQkgIHNyY19wcmVmKTsKK30KKwor c3RhdGljIGVudW0gdXNiX3JvbGUgaGQzc3MzMjIwX2dldF9hdHRhY2hlZF9zdGF0ZShzdHJ1Y3Qg aGQzc3MzMjIwICpoZDNzczMyMjApCit7CisJdW5zaWduZWQgaW50IHJlZ192YWw7CisJZW51bSB1 c2Jfcm9sZSBhdHRhY2hlZF9zdGF0ZTsKKwlpbnQgcmV0OworCisJcmV0ID0gcmVnbWFwX3JlYWQo aGQzc3MzMjIwLT5yZWdtYXAsIEhEM1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMLAorCQkJICAmcmVn X3ZhbCk7CisJaWYgKHJldCA8IDApCisJCXJldHVybiByZXQ7CisKKwlzd2l0Y2ggKHJlZ192YWwg JiBIRDNTUzMyMjBfUkVHX0NOX1NUQVRfQ1RSTF9BVFRBQ0hFRF9TVEFURV9NQVNLKSB7CisJY2Fz ZSBIRDNTUzMyMjBfUkVHX0NOX1NUQVRfQ1RSTF9BU19ERlA6CisJCWF0dGFjaGVkX3N0YXRlID0g VVNCX1JPTEVfSE9TVDsKKwlicmVhazsKKwljYXNlIEhEM1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJM X0FTX1VGUDoKKwkJYXR0YWNoZWRfc3RhdGUgPSBVU0JfUk9MRV9ERVZJQ0U7CisJYnJlYWs7CisJ ZGVmYXVsdDoKKwkJYXR0YWNoZWRfc3RhdGUgPSBVU0JfUk9MRV9OT05FOworCX0KKworCXJldHVy biBhdHRhY2hlZF9zdGF0ZTsKK30KKworc3RhdGljIGludCBoZDNzczMyMjBfZHJfc2V0KGNvbnN0 IHN0cnVjdCB0eXBlY19jYXBhYmlsaXR5ICpjYXAsCisJCQkgICAgZW51bSB0eXBlY19kYXRhX3Jv bGUgcm9sZSkKK3sKKwlzdHJ1Y3QgaGQzc3MzMjIwICpoZDNzczMyMjAgPSBjb250YWluZXJfb2Yo Y2FwLCBzdHJ1Y3QgaGQzc3MzMjIwLAorCQkJCQkJICAgdHlwZWNfY2FwKTsKKwllbnVtIHVzYl9y b2xlIHJvbGVfdmFsOworCWludCBwcmVmLCByZXQgPSAwOworCisJaWYgKHJvbGUgPT0gVFlQRUNf SE9TVCkgeworCQlyb2xlX3ZhbCA9IFVTQl9ST0xFX0hPU1Q7CisJCXByZWYgPSBIRDNTUzMyMjBf UkVHX0dFTl9DVFJMX1NSQ19QUkVGX0RSUF9UUllfU1JDOworCX0gZWxzZSB7CisJCXJvbGVfdmFs ID0gVVNCX1JPTEVfREVWSUNFOworCQlwcmVmID0gSEQzU1MzMjIwX1JFR19HRU5fQ1RSTF9TUkNf UFJFRl9EUlBfVFJZX1NOSzsKKwl9CisKKwlyZXQgPSBoZDNzczMyMjBfc2V0X3NvdXJjZV9wcmVm KGhkM3NzMzIyMCwgcHJlZik7CisJdXNsZWVwX3JhbmdlKDEwLCAxMDApOworCisJdXNiX3JvbGVf c3dpdGNoX3NldF9yb2xlKGhkM3NzMzIyMC0+cm9sZV9zdywgcm9sZV92YWwpOworCXR5cGVjX3Nl dF9kYXRhX3JvbGUoaGQzc3MzMjIwLT5wb3J0LCByb2xlKTsKKworCXJldHVybiByZXQ7Cit9CisK K3N0YXRpYyB2b2lkIGhkM3NzMzIyMF9zZXRfcm9sZShzdHJ1Y3QgaGQzc3MzMjIwICpoZDNzczMy MjApCit7CisJZW51bSB1c2Jfcm9sZSByb2xlX3N0YXRlID0gaGQzc3MzMjIwX2dldF9hdHRhY2hl ZF9zdGF0ZShoZDNzczMyMjApOworCisJdXNiX3JvbGVfc3dpdGNoX3NldF9yb2xlKGhkM3NzMzIy MC0+cm9sZV9zdywgcm9sZV9zdGF0ZSk7CisJaWYgKHJvbGVfc3RhdGUgPT0gVVNCX1JPTEVfTk9O RSkKKwkJaGQzc3MzMjIwX3NldF9zb3VyY2VfcHJlZihoZDNzczMyMjAsCisJCQkJSEQzU1MzMjIw X1JFR19HRU5fQ1RSTF9TUkNfUFJFRl9EUlBfREVGQVVMVCk7CisKKwlzd2l0Y2ggKHJvbGVfc3Rh dGUpIHsKKwljYXNlIFVTQl9ST0xFX0hPU1Q6CisJCXR5cGVjX3NldF9kYXRhX3JvbGUoaGQzc3Mz MjIwLT5wb3J0LCBUWVBFQ19IT1NUKTsKKwkJYnJlYWs7CisJY2FzZSBVU0JfUk9MRV9ERVZJQ0U6 CisJCXR5cGVjX3NldF9kYXRhX3JvbGUoaGQzc3MzMjIwLT5wb3J0LCBUWVBFQ19ERVZJQ0UpOwor CQlicmVhazsKKwlkZWZhdWx0OgorCQlicmVhazsKKwl9Cit9CisKK2lycXJldHVybl90IGhkM3Nz MzIyMF9pcnEoc3RydWN0IGhkM3NzMzIyMCAqaGQzc3MzMjIwKQoreworCWludCBlcnI7CisKKwlo ZDNzczMyMjBfc2V0X3JvbGUoaGQzc3MzMjIwKTsKKwllcnIgPSByZWdtYXBfdXBkYXRlX2JpdHNf YmFzZShoZDNzczMyMjAtPnJlZ21hcCwKKwkJCQkgICAgICBIRDNTUzMyMjBfUkVHX0NOX1NUQVRf Q1RSTCwKKwkJCQkgICAgICBIRDNTUzMyMjBfUkVHX0NOX1NUQVRfQ1RSTF9JTlRfU1RBVFVTLAor CQkJCSAgICAgIEhEM1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMX0lOVF9TVEFUVVMsCisJCQkJICAg ICAgTlVMTCwgZmFsc2UsIHRydWUpOworCWlmIChlcnIgPCAwKQorCQlyZXR1cm4gSVJRX05PTkU7 CisKKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cit9CisKK3N0YXRpYyBpcnFyZXR1cm5fdCBoZDNzczMy MjBfaXJxX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgaTJjX2NsaWVu dCAqY2xpZW50ID0gdG9faTJjX2NsaWVudChkYXRhKTsKKwlzdHJ1Y3QgaGQzc3MzMjIwICpoZDNz czMyMjAgPSBpMmNfZ2V0X2NsaWVudGRhdGEoY2xpZW50KTsKKworCXJldHVybiBoZDNzczMyMjBf aXJxKGhkM3NzMzIyMCk7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmVnbWFwX2NvbmZpZyBj b25maWcgPSB7CisJLnJlZ19iaXRzID0gOCwKKwkudmFsX2JpdHMgPSA4LAorCS5tYXhfcmVnaXN0 ZXIgPSAweDBBLAorfTsKKworc3RhdGljIGludCBoZDNzczMyMjBfcHJvYmUoc3RydWN0IGkyY19j bGllbnQgKmNsaWVudCwKKwkJY29uc3Qgc3RydWN0IGkyY19kZXZpY2VfaWQgKmlkKQoreworCXN0 cnVjdCBoZDNzczMyMjAgKmhkM3NzMzIyMDsKKwlzdHJ1Y3QgZndub2RlX2hhbmRsZSAqcGFyZW50 LCAqY2hpbGQ7CisJaW50IHJldDsKKwl1bnNpZ25lZCBpbnQgZGF0YTsKKworCWhkM3NzMzIyMCA9 IGRldm1fa3phbGxvYygmY2xpZW50LT5kZXYsIHNpemVvZihzdHJ1Y3QgaGQzc3MzMjIwKSwKKwkJ CQkgR0ZQX0tFUk5FTCk7CisJaWYgKCFoZDNzczMyMjApCisJCXJldHVybiAtRU5PTUVNOworCisJ aTJjX3NldF9jbGllbnRkYXRhKGNsaWVudCwgaGQzc3MzMjIwKTsKKworCWhkM3NzMzIyMC0+ZGV2 ID0gJmNsaWVudC0+ZGV2OworCWhkM3NzMzIyMC0+cmVnbWFwID0gZGV2bV9yZWdtYXBfaW5pdF9p MmMoY2xpZW50LCAmY29uZmlnKTsKKwlpZiAoSVNfRVJSKGhkM3NzMzIyMC0+cmVnbWFwKSkKKwkJ cmV0dXJuIFBUUl9FUlIoaGQzc3MzMjIwLT5yZWdtYXApOworCisJaGQzc3MzMjIwX3NldF9zb3Vy Y2VfcHJlZihoZDNzczMyMjAsCisJCQkJICBIRDNTUzMyMjBfUkVHX0dFTl9DVFJMX1NSQ19QUkVG X0RSUF9ERUZBVUxUKTsKKwljaGlsZCA9IGZ3bm9kZV9ncmFwaF9nZXRfbmV4dF9lbmRwb2ludChk ZXZfZndub2RlKGhkM3NzMzIyMC0+ZGV2KSwKKwkJCQkJICAgICAgIE5VTEwpOworCXBhcmVudCA9 IGZ3bm9kZV9ncmFwaF9nZXRfcmVtb3RlX3BvcnRfcGFyZW50KGNoaWxkKTsKKwloZDNzczMyMjAt PnJvbGVfc3cgPSBmd25vZGVfdXNiX3JvbGVfc3dpdGNoX2dldChwYXJlbnQpOworCWlmIChJU19F UlJfT1JfTlVMTChoZDNzczMyMjAtPnJvbGVfc3cpKSB7CisJCWZ3bm9kZV9oYW5kbGVfcHV0KGNo aWxkKTsKKwkJZndub2RlX2hhbmRsZV9wdXQocGFyZW50KTsKKwkJcmV0dXJuIFBUUl9FUlIoaGQz c3MzMjIwLT5yb2xlX3N3KTsKKwl9CisKKwlmd25vZGVfaGFuZGxlX3B1dChjaGlsZCk7CisJZndu b2RlX2hhbmRsZV9wdXQocGFyZW50KTsKKworCWhkM3NzMzIyMC0+dHlwZWNfY2FwLnByZWZlcl9y b2xlID0gVFlQRUNfTk9fUFJFRkVSUkVEX1JPTEU7CisJaGQzc3MzMjIwLT50eXBlY19jYXAuZHJf c2V0ID0gaGQzc3MzMjIwX2RyX3NldDsKKwloZDNzczMyMjAtPnR5cGVjX2NhcC50eXBlID0gVFlQ RUNfUE9SVF9EUlA7CisJaGQzc3MzMjIwLT50eXBlY19jYXAuZGF0YSA9IFRZUEVDX1BPUlRfRFJE OworCisJaGQzc3MzMjIwLT5wb3J0ID0gdHlwZWNfcmVnaXN0ZXJfcG9ydCgmY2xpZW50LT5kZXYs CisJCQkJCSAgICAgICZoZDNzczMyMjAtPnR5cGVjX2NhcCk7CisJaWYgKElTX0VSUihoZDNzczMy MjAtPnBvcnQpKQorCQlyZXR1cm4gUFRSX0VSUihoZDNzczMyMjAtPnBvcnQpOworCisJaGQzc3Mz MjIwX3NldF9yb2xlKGhkM3NzMzIyMCk7CisJaWYgKGNsaWVudC0+aXJxID4gMCkgeworCQlyZXQg PSByZWdtYXBfcmVhZChoZDNzczMyMjAtPnJlZ21hcCwgSEQzU1MzMjIwX1JFR19DTl9TVEFUX0NU UkwsCisJCQkJICAmZGF0YSk7CisJCWlmIChyZXQgPCAwKQorCQkJZ290byBlcnJvcjsKKworCQlp ZiAoZGF0YSAmIEhEM1NTMzIyMF9SRUdfQ05fU1RBVF9DVFJMX0lOVF9TVEFUVVMpIHsKKwkJCXJl dCA9IHJlZ21hcF93cml0ZShoZDNzczMyMjAtPnJlZ21hcCwKKwkJCQlIRDNTUzMyMjBfUkVHX0NO X1NUQVRfQ1RSTCwKKwkJCQlkYXRhIHwgSEQzU1MzMjIwX1JFR19DTl9TVEFUX0NUUkxfSU5UX1NU QVRVUyk7CisJCQlpZiAocmV0IDwgMCkKKwkJCQlnb3RvIGVycm9yOworCQl9CisKKwkJcmV0ID0g ZGV2bV9yZXF1ZXN0X3RocmVhZGVkX2lycSgmY2xpZW50LT5kZXYsIGNsaWVudC0+aXJxLCBOVUxM LAorCQkJCQloZDNzczMyMjBfaXJxX2hhbmRsZXIsCisJCQkJCUlSUUZfVFJJR0dFUl9GQUxMSU5H IHwgSVJRRl9PTkVTSE9ULAorCQkJCQkiaGQzc3MzMjIwIiwgJmNsaWVudC0+ZGV2KTsKKwkJaWYg KHJldCkKKwkJCWdvdG8gZXJyb3I7CisJfQorCisJcmV0ID0gaTJjX3NtYnVzX3JlYWRfYnl0ZV9k YXRhKGNsaWVudCwgSEQzU1MzMjIwX1JFR19ERVZfUkVWKTsKKwlpZiAocmV0IDwgMCkKKwkJZ290 byBlcnJvcjsKKworCWRldl9pbmZvKCZjbGllbnQtPmRldiwgInByb2JlZCByZXZpc2lvbj0weCV4 XG4iLCByZXQpOworCisJcmV0dXJuIDA7CitlcnJvcjoKKwl0eXBlY191bnJlZ2lzdGVyX3BvcnQo aGQzc3MzMjIwLT5wb3J0KTsKKwl1c2Jfcm9sZV9zd2l0Y2hfcHV0KGhkM3NzMzIyMC0+cm9sZV9z dyk7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGhkM3NzMzIyMF9yZW1vdmUoc3Ry dWN0IGkyY19jbGllbnQgKmNsaWVudCkKK3sKKwlzdHJ1Y3QgaGQzc3MzMjIwICpoZDNzczMyMjAg PSBpMmNfZ2V0X2NsaWVudGRhdGEoY2xpZW50KTsKKworCXR5cGVjX3VucmVnaXN0ZXJfcG9ydCho ZDNzczMyMjAtPnBvcnQpOworCXVzYl9yb2xlX3N3aXRjaF9wdXQoaGQzc3MzMjIwLT5yb2xlX3N3 KTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBk ZXZfaWRzW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJ0aSxoZDNzczMyMjAifSwKKwl7fQorfTsK K01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIGRldl9pZHMpOworCitzdGF0aWMgc3RydWN0IGkyY19k cml2ZXIgaGQzc3MzMjIwX2RyaXZlciA9IHsKKwkuZHJpdmVyID0geworCQkubmFtZSA9ICJoZDNz czMyMjAiLAorCQkub2ZfbWF0Y2hfdGFibGUgPSBvZl9tYXRjaF9wdHIoZGV2X2lkcyksCisJfSwK KwkucHJvYmUgPSBoZDNzczMyMjBfcHJvYmUsCisJLnJlbW92ZSA9ICBoZDNzczMyMjBfcmVtb3Zl LAorfTsKKworbW9kdWxlX2kyY19kcml2ZXIoaGQzc3MzMjIwX2RyaXZlcik7CisKK01PRFVMRV9B VVRIT1IoIkJpanUgRGFzIDxiaWp1LmRhc0BicC5yZW5lc2FzLmNvbT4iKTsKK01PRFVMRV9ERVND UklQVElPTigiVEkgSEQzU1MzMjIwIERSUCBQb3J0IENvbnRyb2xsZXIgRHJpdmVyIik7CitNT0RV TEVfTElDRU5TRSgiR1BMIik7Cg==