[PATCH v2 0/2] TypeC Connector Class driver improvements
Changes in v2: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" * Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" * New patch added. Azhar Shaikh (2): platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect drivers/platform/chrome/cros_ec_typec.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.1
[PATCH v2 1/2] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of DFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh Cc: Prashant Malani Reviewed-by: Prashant Malani --- drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3eae01f4c9f7..eb4713b7ae14 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -590,7 +590,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect
On disconnect port partner is removed and usb role is set to NONE. But then in cros_typec_port_update() the role is set again. Avoid this by moving usb_role_switch_set_role() to cros_typec_configure_mux(). Signed-off-by: Azhar Shaikh Suggested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_typec.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index eb4713b7ae14..df97431b2275 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -515,6 +515,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); + if (ret) + return ret; + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { @@ -589,9 +595,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - resp.role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v2 2/2] platform/chrome: cros_ec_typec: Avoid setting usb role during disconnect
On disconnect port partner is removed and usb role is set to NONE. But then in cros_typec_port_update() the role is set again. Avoid this by moving usb_role_switch_set_role() to cros_typec_configure_mux(). Signed-off-by: Azhar Shaikh Suggested-by: Prashant Malani --- drivers/platform/chrome/cros_ec_typec.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index eb4713b7ae14..df97431b2275 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -515,6 +515,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); + if (ret) + return ret; + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { @@ -589,9 +595,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - resp.role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v2 1/2] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of DFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh Cc: Prashant Malani Reviewed-by: Prashant Malani --- drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3eae01f4c9f7..eb4713b7ae14 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -590,7 +590,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v2 0/2] TypeC Connector Class driver improvements
Changes in v2: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" * Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" * New patch added. Azhar Shaikh (2): platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect drivers/platform/chrome/cros_ec_typec.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.1
[PATCH v3 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps
As per USB Type-C Spec R2.0 section 4.5.1.2 (Connecting Sources and Sinks) and section 4.5.2.2 (Connection State Machine Requirements), the typical flow for configuring a device connected to a typeC port is as below: 1. Source/sink detection 2. Orientation 3. Data role 4. VCONN 5. VBUS (USB Type-C currents) 6. The connector is now configured. We can start the PD communication that should lead into configuration of the mux if we enter a mode. But in existing code data role was set after the connector and mux are already configured. So fix this by following the spec to set the data role before the connector and mux are configured. Signed-off-by: Azhar Shaikh --- Changes in v3: - New patch added drivers/platform/chrome/cros_ec_typec.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 2b43e1176e73..9e4fad9ca59e 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -516,6 +516,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); + if (ret) + return ret; + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { @@ -533,12 +539,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - if (ret) - return ret; - - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) -- 2.17.1
[PATCH v3 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect
On disconnect port partner is removed and usb role is set to NONE. But then in cros_typec_port_update() the role is set again. Avoid this by moving usb_role_switch_set_role() to cros_typec_configure_mux(). Signed-off-by: Azhar Shaikh --- Changes in v3: - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. Changes in v2: - New patch added drivers/platform/chrome/cros_ec_typec.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 06108212ee94..2b43e1176e73 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -533,7 +533,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - return ret; + if (ret) + return ret; + + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) @@ -590,9 +595,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - resp.role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v3 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of DFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh --- Changes in v3: - No changes Changes in v2: - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3fcd27ec9ad8..06108212ee94 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -591,7 +591,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v3 0/3] TypeC Connector Class driver improvements
Changes in v3: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - No change * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - New patch added Changes in v2: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - New patch added. Azhar Shaikh (3): platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect platform/chrome: cros_ec_typec: Re-order connector configuration steps drivers/platform/chrome/cros_ec_typec.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.1
[PATCH] xhci-pci: Allow host runtime PM as default for Intel Alder Lake xHCI
From: Abhijeet Rao In the same way as Intel Tiger Lake TCSS (Type-C Subsystem) the Alder Lake TCSS xHCI needs to be runtime suspended whenever possible to allow the TCSS hardware block to enter D3cold and thus save energy. Signed-off-by: Abhijeet Rao Signed-off-by: Nikunj A. Dadhania Signed-off-by: Azhar Shaikh --- drivers/usb/host/xhci-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5bbccc9a0179..a858add8436c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -57,6 +57,7 @@ #define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI0x461e #define PCI_DEVICE_ID_AMD_PROMONTORYA_40x43b9 #define PCI_DEVICE_ID_AMD_PROMONTORYA_30x43ba @@ -243,7 +244,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || -pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI)) +pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || +pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; if (pdev->vendor == PCI_VENDOR_ID_ETRON && -- 2.17.1
[PATCH 2/2] mmc: sdhci-pci: Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel controllers
Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel SD card controllers. Signed-off-by: Azhar Shaikh --- drivers/mmc/host/sdhci-pci-core.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 86560d5..4a58a80 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -423,16 +423,15 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) { - slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | +MMC_CAP_AGGRESSIVE_PM; slot->cd_idx = 0; slot->cd_override_level = true; if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD || slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXTM_SD || slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD || - slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) { + slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) slot->host->mmc_host_ops.get_cd = bxt_get_cd; - slot->host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM; - } return 0; } -- 1.9.1
[PATCH 1/2] mmc: sdhci-acpi: Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel controllers
Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel SD card controllers. Signed-off-by: Azhar Shaikh --- drivers/mmc/host/sdhci-acpi.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 9dcb704..a15d237 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -263,10 +263,8 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, /* Platform specific code during sd probe slot goes here */ - if (hid && !strcmp(hid, "80865ACA")) { + if (hid && !strcmp(hid, "80865ACA")) host->mmc_host_ops.get_cd = bxt_get_cd; - host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM; - } return 0; } @@ -302,7 +300,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | SDHCI_QUIRK2_STOP_WITH_TC, - .caps= MMC_CAP_WAIT_WHILE_BUSY, + .caps= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, .probe_slot = sdhci_acpi_sd_probe_slot, }; -- 1.9.1
[PATCH v2 2/2] mmc: sdhci-pci: Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel controllers
Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel SD card controllers. Signed-off-by: Azhar Shaikh --- Changes in v2: - Rebased the patch on top of 'next' branch. - No code change. drivers/mmc/host/sdhci-pci-core.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 6c0440e..833072b 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -630,16 +630,15 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) { byt_read_dsm(slot); - slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | +MMC_CAP_AGGRESSIVE_PM; slot->cd_idx = 0; slot->cd_override_level = true; if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD || slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXTM_SD || slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD || - slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) { + slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) slot->host->mmc_host_ops.get_cd = bxt_get_cd; - slot->host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM; - } return 0; } -- 1.9.1
[PATCH v2 1/2] mmc: sdhci-acpi: Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel controllers
Set MMC_CAP_AGGRESSIVE_PM for BYT-related Intel SD card controllers. Signed-off-by: Azhar Shaikh --- Changes in v2: - Rebased the patch on top of 'next' branch. - No code change. drivers/mmc/host/sdhci-acpi.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 665c5f3..c6a9a1b 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -263,10 +263,8 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, /* Platform specific code during sd probe slot goes here */ - if (hid && !strcmp(hid, "80865ACA")) { + if (hid && !strcmp(hid, "80865ACA")) host->mmc_host_ops.get_cd = bxt_get_cd; - host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM; - } return 0; } @@ -302,7 +300,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | SDHCI_QUIRK2_STOP_WITH_TC, - .caps= MMC_CAP_WAIT_WHILE_BUSY, + .caps= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, .probe_slot = sdhci_acpi_sd_probe_slot, }; -- 1.9.1
[PATCH] mfd: intel-lpss: Do not put device in reset state on suspend
Commit 41a3da2b8e163 ("mfd: intel-lpss: Save register context on suspend") saved the register context while going to suspend and also put the device in reset state. Due to the resetting of device, system cannot enter S3/S0ix states when no_console_suspend flag is enabled. The system and serial console both hang. The resetting of device is not needed while going to suspend. Hence remove this code. Fixes: 41a3da2b8e163 ("mfd: intel-lpss: Save register context on suspend") Signed-off-by: Azhar Shaikh --- drivers/mfd/intel-lpss.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 41b1138..70c646b 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -502,9 +502,6 @@ int intel_lpss_suspend(struct device *dev) for (i = 0; i < LPSS_PRIV_REG_COUNT; i++) lpss->priv_ctx[i] = readl(lpss->priv + i * 4); - /* Put the device into reset state */ - writel(0, lpss->priv + LPSS_PRIV_RESETS); - return 0; } EXPORT_SYMBOL_GPL(intel_lpss_suspend); -- 2.10.1
[PATCH v3] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Add CONFIG_X86 around disable_lpc_clk_run () and enable_lpc_clk_run() to avoid - build breakage on architectures which do not implement kmap_atomic_pfn() Changes from v2: - Use ioremap()/iounmap() instead of kmap_atomic_pfn()/kunmap_atomic() - Move is_bsw() and all macros from tpm.h to tpm_tis.c file. - Add the is_bsw() check in disable_lpc_clk_run() and enable_lpc_clk_run() - instead of adding it in each read/write API. drivers/char/tpm/tpm.h | 4 ++ drivers/char/tpm/tpm_tis.c | 103 + 2 files changed, 107 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..6b769fbc4407 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..6e32b4c7c70d 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -89,13 +89,89 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +#ifdef CONFIG_X86 +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} +#else +static inline bool is_bsw(void) +{ + return false; +} +#endif + +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define ILB_REMAP_SIZE 0x100 +#define LPC_CNTRL_REG_OFFSET0x84 +#define LPC_CLKRUN_EN (1 << 2) + +void __iomem *ilb_base_addr; + +/** + * disable_lpc_clk_run() - clear LPC CLKRUN_EN i.e. clocks will be free running + */ +static void disable_lpc_clk_run(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); + + /* Make sure the above write is completed */ + wmb(); +} + +/** + * enable_lpc_clk_run() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void enable_lpc_clk_run(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); + + /* Make sure the above write is completed */ + wmb(); +} + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + disable_lpc_clk_run(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + enable_lpc_clk_run(); + return 0; } @@ -104,8 +180,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + disable_lpc_clk_run(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + enable_lpc_clk_run(); + return 0; } @@ -113,7 +194,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + disable_lpc_clk_run(); + *result = ioread16(phy->iobase + addr); + + enable_lpc_clk_run(); + return 0; } @@ -121,7 +207,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + disable_lpc_clk_run(); + *result = ioread32(phy->iobase + addr); + + enable_lpc_clk_run(); + return 0; } @@ -129,7 +220,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + disable_lpc_clk_run(); + iowrite32(value, phy->iobase + addr); + + enable_lpc_clk_run(); + return 0; } @@ -191,6 +287,10 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev)
[PATCH] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm.h | 20 +++ drivers/char/tpm/tpm_tis.c | 85 ++ 2 files changed, 105 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..98032a22317e 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, @@ -436,6 +440,22 @@ struct tpm_buf { u8 *data; }; +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define LPC_CNTRL_REG_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) + +#ifdef CONFIG_X86 +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} +#else +static inline bool is_bsw(void) +{ + return false; +} +#endif + static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) { struct tpm_input_header *head; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..25ead56382c0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -89,13 +89,70 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +/** + * disable_lpc_clk_run() - clear LPC CLKRUN_EN i.e. clocks will be free running + */ +static void disable_lpc_clk_run(void) +{ + u32 clkrun_val; + void __iomem *ilb_base_addr = NULL; + + ilb_base_addr = (void __iomem *) + kmap_atomic_pfn(INTEL_LEGACY_BLK_BASE_ADDR >> PAGE_SHIFT); + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + kunmap_atomic(ilb_base_addr); + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); +} + +/** + * enable_lpc_clk_run() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void enable_lpc_clk_run(void) +{ + u32 clkrun_val; + void __iomem *ilb_base_addr = NULL; + + ilb_base_addr = (void __iomem *) + kmap_atomic_pfn(INTEL_LEGACY_BLK_BASE_ADDR >> PAGE_SHIFT); + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + kunmap_atomic(ilb_base_addr); + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); +} + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -104,8 +161,15 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -113,7 +177,14 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + *result = ioread16(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -121,7 +192,14 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + *result = ioread32(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -129,7 +207,14 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + iowrite32(value, phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } -- 1.9.1
[PATCH v2] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Add CONFIG_X86 around disable_lpc_clk_run () and enable_lpc_clk_run() to avoid - build breakage on architectures which do not implement kmap_atomic_pfn() drivers/char/tpm/tpm.h | 20 ++ drivers/char/tpm/tpm_tis.c | 94 ++ 2 files changed, 114 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..98032a22317e 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, @@ -436,6 +440,22 @@ struct tpm_buf { u8 *data; }; +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define LPC_CNTRL_REG_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) + +#ifdef CONFIG_X86 +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} +#else +static inline bool is_bsw(void) +{ + return false; +} +#endif + static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) { struct tpm_input_header *head; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..0c1496340a18 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -89,13 +89,79 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +#ifdef CONFIG_X86 +/** + * disable_lpc_clk_run() - clear LPC CLKRUN_EN i.e. clocks will be free running + */ +static void disable_lpc_clk_run(void) +{ + u32 clkrun_val; + void __iomem *ilb_base_addr = NULL; + + ilb_base_addr = (void __iomem *) + kmap_atomic_pfn(INTEL_LEGACY_BLK_BASE_ADDR >> PAGE_SHIFT); + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + kunmap_atomic(ilb_base_addr); + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); +} + +/** + * enable_lpc_clk_run() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void enable_lpc_clk_run(void) +{ + u32 clkrun_val; + void __iomem *ilb_base_addr = NULL; + + ilb_base_addr = (void __iomem *) + kmap_atomic_pfn(INTEL_LEGACY_BLK_BASE_ADDR >> PAGE_SHIFT); + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + kunmap_atomic(ilb_base_addr); + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0x80, 0xCC); +} +#else +static void disable_lpc_clk_run(void) +{ +} +static void enable_lpc_clk_run(void) +{ +} +#endif + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -104,8 +170,15 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -113,7 +186,14 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + *result = ioread16(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -121,7 +201,14 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + if (is_bsw()) + disable_lpc_clk_run(); + *result = ioread32(phy->iobase + addr); + + if (is_bsw()) + enable_lpc_clk_run(); + return 0; } @@ -129,7 +216,14 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
[PATCH] tpm: Fix the ioremap() call for Braswell systems
ioremap() for Intel Braswell processors was done in tpm_tis_pnp_init(). But before this function gets called, platform driver 'tis_drv' gets registered and its probe function tpm_tis_plat_probe() is invoked, which does a TPM access. Now for Braswell processors tpm_platform_begin_xfer() will do an ioread32() without having a mapped address, which will lead to a bad I/O access warning. Hence move the ioremap() call from tpm_tis_pnp_init() to init_tis() before registering the 'tis_drv' or basically before any TPM access. Accordingly also move the iounmap() call from tpm_tis_pnp_remove() to cleanup_tis(). Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm_tis.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 506e62ca3576..3224db80816a 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -330,12 +330,6 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, else tpm_info.irq = -1; -#ifdef CONFIG_X86 - if (is_bsw()) - ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, - ILB_REMAP_SIZE); -#endif - return tpm_tis_init(&pnp_dev->dev, &tpm_info); } @@ -359,12 +353,6 @@ static void tpm_tis_pnp_remove(struct pnp_dev *dev) tpm_chip_unregister(chip); tpm_tis_remove(chip); - -#ifdef CONFIG_X86 - if (is_bsw()) - iounmap(ilb_base_addr); -#endif - } static struct pnp_driver tis_pnp_driver = { @@ -472,6 +460,11 @@ static int __init init_tis(void) if (rc) goto err_force; +#ifdef CONFIG_X86 + if (is_bsw()) + ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, + ILB_REMAP_SIZE); +#endif rc = platform_driver_register(&tis_drv); if (rc) goto err_platform; @@ -499,6 +492,10 @@ static void __exit cleanup_tis(void) pnp_unregister_driver(&tis_pnp_driver); platform_driver_unregister(&tis_drv); +#ifdef CONFIG_X86 + if (is_bsw()) + iounmap(ilb_base_addr); +#endif if (force_pdev) platform_device_unregister(force_pdev); } -- 1.9.1
[PATCH v2] tpm: Fix the ioremap() call for Braswell systems
ioremap() for Intel Braswell processors was done in tpm_tis_pnp_init(). But before this function gets called, platform driver 'tis_drv' gets registered and its probe function tpm_tis_plat_probe() is invoked, which does a TPM access. Now for Braswell processors tpm_platform_begin_xfer() will do an ioread32() without having a mapped address, which will lead to a bad I/O access warning. Hence move the ioremap() call from tpm_tis_pnp_init() to init_tis() before registering the 'tis_drv' or basically before any TPM access. Accordingly also move the iounmap() call from tpm_tis_pnp_remove() to cleanup_tis() after all TPM access are completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Do error handling in init_ts(). - Update the commit message. drivers/char/tpm/tpm_tis.c | 25 + 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 506e62ca3576..d97ce22267fb 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -330,12 +330,6 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, else tpm_info.irq = -1; -#ifdef CONFIG_X86 - if (is_bsw()) - ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, - ILB_REMAP_SIZE); -#endif - return tpm_tis_init(&pnp_dev->dev, &tpm_info); } @@ -359,12 +353,6 @@ static void tpm_tis_pnp_remove(struct pnp_dev *dev) tpm_chip_unregister(chip); tpm_tis_remove(chip); - -#ifdef CONFIG_X86 - if (is_bsw()) - iounmap(ilb_base_addr); -#endif - } static struct pnp_driver tis_pnp_driver = { @@ -472,6 +460,11 @@ static int __init init_tis(void) if (rc) goto err_force; +#ifdef CONFIG_X86 + if (is_bsw()) + ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, + ILB_REMAP_SIZE); +#endif rc = platform_driver_register(&tis_drv); if (rc) goto err_platform; @@ -490,6 +483,10 @@ static int __init init_tis(void) err_platform: if (force_pdev) platform_device_unregister(force_pdev); +#ifdef CONFIG_X86 + if (is_bsw()) + iounmap(ilb_base_addr); +#endif err_force: return rc; } @@ -499,6 +496,10 @@ static void __exit cleanup_tis(void) pnp_unregister_driver(&tis_pnp_driver); platform_driver_unregister(&tis_drv); +#ifdef CONFIG_X86 + if (is_bsw()) + iounmap(ilb_base_addr); +#endif if (force_pdev) platform_device_unregister(force_pdev); } -- 1.9.1
[PATCH v5 0/2] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Changes from v4: - The numbering of patches is now interchanged. - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - Had to move ilb_base_addr to tpm_tis_data, from tpm_tis_tcg_phy. Since the ioremapping of ilb_base_addr had to be done before any TPM access, hence moved the variable to tpm_tis_data. - Also move the ioremapping of ilb_base_addr from tpm_tis_init() to tpm_tis_core_init() i.e. before any TPM access is done. - Rename marco LPC_CNTRL_REG_OFFSET to LPC_CNTRL_OFFSET - Update the commit message. - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove the functions tpm_platform_begin_xfer() and tpm_platform_end_xfer() - Move the code from these functions to tpm_tis_clkrun_enable(). Azhar Shaikh (2): tpm_tis: Move ilb_base_addr to tpm_tis_data tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() drivers/char/tpm/tpm-interface.c | 6 ++ drivers/char/tpm/tpm_tis.c | 121 ++- drivers/char/tpm/tpm_tis_core.c | 111 +-- drivers/char/tpm/tpm_tis_core.h | 17 ++ include/linux/tpm.h | 1 + 5 files changed, 147 insertions(+), 109 deletions(-) -- 1.9.1
[PATCH v5 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside the flow of TPM command processing, disable and re-enable CLKRUN protocol for every TPM access. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 86 +--- drivers/char/tpm/tpm_tis_core.c | 95 +--- drivers/char/tpm/tpm_tis_core.h | 4 ++ include/linux/tpm.h | 1 + 5 files changed, 111 insertions(+), 81 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index ebe0a1d36d8c..6e19e3dd98e4 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 923f8f2cbaca..d29add49b033 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev) } #endif -#ifdef CONFIG_X86 -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) - -/** - * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running - */ -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Disable LPC CLKRUN# */ - clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} - -/** - * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off - */ -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Enable LPC CLKRUN# */ - clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} -#else -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ -} - -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ -} -#endif - static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -228,12 +165,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 ad
[PATCH v5 1/2] tpm_tis: Move ilb_base_addr to tpm_tis_data
Move static variable ilb_base_addr to tpm_tis_data. Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm_tis.c | 75 +++-- drivers/char/tpm/tpm_tis_core.c | 16 - drivers/char/tpm/tpm_tis_core.h | 13 +++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..923f8f2cbaca 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,33 +134,24 @@ static int check_acpi_tpm2(struct device *dev) #endif #ifdef CONFIG_X86 -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 -#define LPC_CNTRL_REG_OFFSET0x84 -#define LPC_CLKRUN_EN (1 << 2) - -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} +#define LPC_CNTRL_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -173,18 +164,18 @@ static void tpm_platform_begin_xfer(void) /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -194,16 +185,11 @@ static void tpm_platform_end_xfer(void) } #else -static inline bool is_bsw(void) -{ - return false; -} - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +199,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +214,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -242,11 +228,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread16(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -255,11 +241,11 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread32(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -268,11 +254,11 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); iowrite32(value, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -351,9 +337,13 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_
[PATCH v4 2/2] tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy
Move the static variable ilb_base_addr to tpm_tis_tcg_phy. Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm_tis.c | 67 ++ 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 76a7b64195c8..d87b37c5404b 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -46,6 +46,7 @@ struct tpm_info { struct tpm_tis_tcg_phy { struct tpm_tis_data priv; void __iomem *iobase; + void __iomem *ilb_base_addr; bool begin_xfer_done; }; @@ -134,19 +135,22 @@ static int check_acpi_tpm2(struct device *dev) } #endif +static inline bool is_bsw(void) +{ #ifdef CONFIG_X86 + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +#else + return false; +#endif +} + #define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 #define ILB_REMAP_SIZE 0x100 + +#ifdef CONFIG_X86 #define LPC_CNTRL_REG_OFFSET0x84 #define LPC_CLKRUN_EN (1 << 2) -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} - /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running * @data: struct tpm_tis_data instance @@ -160,11 +164,11 @@ static void tpm_platform_begin_xfer(struct tpm_tis_data *data) phy->begin_xfer_done)) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(phy->ilb_base_addr + LPC_CNTRL_REG_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, phy->ilb_base_addr + LPC_CNTRL_REG_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -185,15 +189,16 @@ static void tpm_platform_begin_xfer(struct tpm_tis_data *data) static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; + struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); if (!is_bsw() || (data->flags & TPM_TIS_CLK_ENABLE)) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(phy->ilb_base_addr + LPC_CNTRL_REG_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, phy->ilb_base_addr + LPC_CNTRL_REG_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -204,10 +209,6 @@ static void tpm_platform_end_xfer(struct tpm_tis_data *data) } #else -static inline bool is_bsw(void) -{ - return false; -} static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } @@ -311,14 +312,25 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info) if (IS_ERR(phy->iobase)) return PTR_ERR(phy->iobase); + if (is_bsw()) { + phy->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, + ILB_REMAP_SIZE); + if (!phy->ilb_base_addr) + return -ENOMEM; + } + if (interrupts) irq = tpm_info->irq; if (itpm || is_itpm(ACPI_COMPANION(dev))) phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND; - return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg, + rc = tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg, ACPI_HANDLE(dev)); + if (rc && is_bsw()) + iounmap(phy->ilb_base_addr); + + return rc; } static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); @@ -359,9 +371,14 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, static void tpm_tis_pnp_remove(struct pnp_dev *dev) { struct tpm_chip *chip = pnp_get_drvdata(dev); + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(priv); tpm_chip_unregister(chip); tpm_tis_remove(chip); + + if (is_bsw()) + iounmap(phy->ilb_base_addr); } static struct pnp_driver tis_pnp_driver = { @@ -408,10 +425,15 @@ static int tpm_tis_plat_probe(struct platform_device *pdev) static int tpm_tis_plat_remove(struct platform_device *pdev) { struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(priv); tpm_chip_unregister(chip); tpm_tis_remove(chip); + if (is_bsw()) + iounmap(phy->
[PATCH v4 0/2] ] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Azhar Shaikh (2): tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 111 ++- drivers/char/tpm/tpm_tis_core.c | 21 drivers/char/tpm/tpm_tis_core.h | 1 + include/linux/tpm.h | 1 + 5 files changed, 93 insertions(+), 47 deletions(-) -- 1.9.1
[PATCH v4 1/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside the flow of TPM command processing, disable and re-enable CLKRUN protocol for every TPM access. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 6 ++ drivers/char/tpm/tpm_tis.c | 44 drivers/char/tpm/tpm_tis_core.c | 21 +++ drivers/char/tpm/tpm_tis_core.h | 1 + include/linux/tpm.h | 1 + 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1d6729be4cd6..4661a810eab7 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..76a7b64195c8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -46,6 +46,7 @@ struct tpm_info { struct tpm_tis_tcg_phy { struct tpm_tis_data priv; void __iomem *iobase; + bool begin_xfer_done; }; static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *data) @@ -148,12 +149,15 @@ static inline bool is_bsw(void) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running + * @data: struct tpm_tis_data instance */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; + struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - if (!is_bsw()) + if (!is_bsw() || ((data->flags & TPM_TIS_CLK_ENABLE) && + phy->begin_xfer_done)) return; clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); @@ -168,16 +172,21 @@ static void tpm_platform_begin_xfer(void) */ outb(0xCC, 0x80); + if (!(data->flags & TPM_TIS_CLK_ENABLE)) + phy->begin_xfer_done = false; + else + phy->begin_xfer_done = true; } /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off + * @data: struct tpm_tis_data instance */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; - if (!is_bsw()) + if (!is_bsw() || (data->flags & TPM_TIS_CLK_ENABLE)) return; clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); @@ -193,17 +202,16 @@ static void tpm_platform_end_xfer(void) outb(0xCC, 0x80); } + #else static inline bool is_bsw(void) { return false; } - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } - -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +221,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +236,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iow
[PATCH v4] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Add CONFIG_X86 around disable_lpc_clk_run() and enable_lpc_clk_run() to avoid - build breakage on architectures which do not implement kmap_atomic_pfn() Changes from v2: - Use ioremap()/iounmap() instead of kmap_atomic_pfn()/kunmap_atomic() - Move is_bsw() and all macros from tpm.h to tpm_tis.c file. - Add the is_bsw() check in disable_lpc_clk_run() and enable_lpc_clk_run() - instead of adding it in each read/write API. Changes from v3: - Move the code under #ifdef CONFIG_X86 and create stub functions for everything else - Rename the functions disable_lpc_clk_run() -> tpm_platform_begin_xfer() and - enable_lpc_clk_run() -> tpm_platform_end_xfer() - Remove wmb() - Correct the parameters for outb() drivers/char/tpm/tpm.h | 4 ++ drivers/char/tpm/tpm_tis.c | 112 + 2 files changed, 116 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..6b769fbc4407 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..ce6f1a8b0510 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -89,13 +89,93 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +#ifdef CONFIG_X86 +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define ILB_REMAP_SIZE 0x100 +#define LPC_CNTRL_REG_OFFSET0x84 +#define LPC_CLKRUN_EN (1 << 2) + +void __iomem *ilb_base_addr; + +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} + +/** + * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running + */ +static void tpm_platform_begin_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} + +/** + * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void tpm_platform_end_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} +#else +static inline bool is_bsw(void) +{ + return false; +} + +static void tpm_platform_begin_xfer(void) +{ +} + +static void tpm_platform_end_xfer(void) +{ +} +#endif + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -104,8 +184,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -113,7 +198,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread16(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -121,7 +211,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread32(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -129,7 +224,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); +
[PATCH v4] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Add CONFIG_X86 around disable_lpc_clk_run () and enable_lpc_clk_run() to avoid - build breakage on architectures which do not implement kmap_atomic_pfn() Changes from v2: - Use ioremap()/iounmap() instead of kmap_atomic_pfn()/kunmap_atomic() - Move is_bsw() and all macros from tpm.h to tpm_tis.c file. - Add the is_bsw() check in disable_lpc_clk_run() and enable_lpc_clk_run() - instead of adding it in each read/write API. Changes from v3: - Move the code under #ifdef CONFIG_X86 and create stub functions for everything else - Rename the functions disable_lpc_clk_run() -> tpm_platform_begin_xfer() and - enable_lpc_clk_run() -> tpm_platform_end_xfer() - Remove wmb() drivers/char/tpm/tpm.h | 4 ++ drivers/char/tpm/tpm_tis.c | 112 + 2 files changed, 116 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..6b769fbc4407 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..ce6f1a8b0510 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -89,13 +89,93 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +#ifdef CONFIG_X86 +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define ILB_REMAP_SIZE 0x100 +#define LPC_CNTRL_REG_OFFSET0x84 +#define LPC_CLKRUN_EN (1 << 2) + +void __iomem *ilb_base_addr; + +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} + +/** + * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running + */ +static void tpm_platform_begin_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} + +/** + * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void tpm_platform_end_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} +#else +static inline bool is_bsw(void) +{ + return false; +} + +static void tpm_platform_begin_xfer(void) +{ +} + +static void tpm_platform_end_xfer(void) +{ +} +#endif + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -104,8 +184,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -113,7 +198,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread16(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -121,7 +211,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread32(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -129,7 +224,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); +
[PATCH v5] tpm: Enable CLKRUN protocol for Braswell systems
To overcome a hardware limitation on Intel Braswell systems, disable CLKRUN protocol during TPM transactions and re-enable once the transaction is completed. Signed-off-by: Azhar Shaikh --- Changes from v1: - Add CONFIG_X86 around disable_lpc_clk_run() and enable_lpc_clk_run() to avoid - build breakage on architectures which do not implement kmap_atomic_pfn() Changes from v2: - Use ioremap()/iounmap() instead of kmap_atomic_pfn()/kunmap_atomic() - Move is_bsw() and all macros from tpm.h to tpm_tis.c file. - Add the is_bsw() check in disable_lpc_clk_run() and enable_lpc_clk_run() - instead of adding it in each read/write API. Changes from v3: - Move the code under #ifdef CONFIG_X86 and create stub functions for everything else - Rename the functions disable_lpc_clk_run() -> tpm_platform_begin_xfer() and - enable_lpc_clk_run() -> tpm_platform_end_xfer() - Remove wmb() - Correct the parameters for outb() Changes from v4: - Rebased to apply on git://git.infradead.org/users/jjs/linux-tpmdd.git drivers/char/tpm/tpm.h | 4 ++ drivers/char/tpm/tpm_tis.c | 112 + 2 files changed, 116 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 1df0521138d3..cdd261383dea 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_X86 +#include +#endif + enum tpm_const { TPM_MINOR = 224,/* officially assigned */ TPM_BUFSIZE = 4096, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index b14d4aa97af8..506e62ca3576 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev) } #endif +#ifdef CONFIG_X86 +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 +#define ILB_REMAP_SIZE 0x100 +#define LPC_CNTRL_REG_OFFSET0x84 +#define LPC_CLKRUN_EN (1 << 2) + +void __iomem *ilb_base_addr; + +static inline bool is_bsw(void) +{ + return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); +} + +/** + * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running + */ +static void tpm_platform_begin_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Disable LPC CLKRUN# */ + clkrun_val &= ~LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} + +/** + * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off + */ +static void tpm_platform_end_xfer(void) +{ + u32 clkrun_val; + + if (!is_bsw()) + return; + + clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* Enable LPC CLKRUN# */ + clkrun_val |= LPC_CLKRUN_EN; + iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + + /* +* Write any random value on port 0x80 which is on LPC, to make +* sure LPC clock is running before sending any TPM command. +*/ + outb(0xCC, 0x80); + +} +#else +static inline bool is_bsw(void) +{ + return false; +} + +static void tpm_platform_begin_xfer(void) +{ +} + +static void tpm_platform_end_xfer(void) +{ +} +#endif + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) *result++ = ioread8(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -147,8 +227,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + while (len--) iowrite8(*value++, phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -156,7 +241,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread16(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -164,7 +254,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + tpm_platform_begin_xfer(); + *result = ioread32(phy->iobase + addr); + + tpm_platform_end_xfer(); + return 0; } @@ -172,7 +267,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr,
[PATCH v6 1/2] tpm_tis: Move ilb_base_addr to tpm_tis_data
Move static variable ilb_base_addr to tpm_tis_data. Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm_tis.c | 75 +++-- drivers/char/tpm/tpm_tis_core.c | 16 - drivers/char/tpm/tpm_tis_core.h | 13 +++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..923f8f2cbaca 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,33 +134,24 @@ static int check_acpi_tpm2(struct device *dev) #endif #ifdef CONFIG_X86 -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 -#define LPC_CNTRL_REG_OFFSET0x84 -#define LPC_CLKRUN_EN (1 << 2) - -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} +#define LPC_CNTRL_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -173,18 +164,18 @@ static void tpm_platform_begin_xfer(void) /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -194,16 +185,11 @@ static void tpm_platform_end_xfer(void) } #else -static inline bool is_bsw(void) -{ - return false; -} - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +199,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +214,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -242,11 +228,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread16(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -255,11 +241,11 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread32(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -268,11 +254,11 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); iowrite32(value, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -351,9 +337,13 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_
[PATCH v6 0/2] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Changes from v4: - The numbering of patches is now interchanged. - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - Had to move ilb_base_addr to tpm_tis_data, from tpm_tis_tcg_phy. Since the ioremapping of ilb_base_addr had to be done before any TPM access, hence moved the variable to tpm_tis_data. - Also move the ioremapping of ilb_base_addr from tpm_tis_init() to tpm_tis_core_init() i.e. before any TPM access is done. - Rename marco LPC_CNTRL_REG_OFFSET to LPC_CNTRL_OFFSET - Update the commit message. - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove the functions tpm_platform_begin_xfer() and tpm_platform_end_xfer() - Move the code from these functions to tpm_tis_clkrun_enable(). Changes from v5: - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Update the commit message. Azhar Shaikh (2): tpm_tis: Move ilb_base_addr to tpm_tis_data tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() drivers/char/tpm/tpm-interface.c | 6 ++ drivers/char/tpm/tpm_tis.c | 121 ++- drivers/char/tpm/tpm_tis_core.c | 111 +-- drivers/char/tpm/tpm_tis_core.h | 17 ++ include/linux/tpm.h | 1 + 5 files changed, 147 insertions(+), 109 deletions(-) -- 1.9.1
[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside TPM command flow, add a higher level of disabling and re-enabling the CLKRUN protocol, instead of doing for every TPM transaction. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 86 +--- drivers/char/tpm/tpm_tis_core.c | 95 +--- drivers/char/tpm/tpm_tis_core.h | 4 ++ include/linux/tpm.h | 1 + 5 files changed, 111 insertions(+), 81 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index ebe0a1d36d8c..6e19e3dd98e4 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 923f8f2cbaca..d29add49b033 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev) } #endif -#ifdef CONFIG_X86 -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) - -/** - * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running - */ -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Disable LPC CLKRUN# */ - clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} - -/** - * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off - */ -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Enable LPC CLKRUN# */ - clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} -#else -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ -} - -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ -} -#endif - static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -228,12 +165,11 @
[PATCH] tpm: Fix the driver cleanup code
Commit 3c1701339284353c41 ("tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()") added code which accessed chip->ops, even after it was set to NULL in tpm_del_char_device(), called from tpm_chip_unregister() in error / driver exit paths. So fix this code. Fixes: 3c1701339284353c41 ("tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()") Suggested-by: Javier Martinez Canillas Suggested-by: Jason Gunthorpe Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm-chip.c | 5 + drivers/char/tpm/tpm.h | 1 + drivers/char/tpm/tpm_tis.c | 8 ++-- drivers/char/tpm/tpm_tis_core.c | 23 +++ drivers/char/tpm/tpm_tis_spi.c | 1 + 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 0a62c19937b6..c88ec9a32a7e 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -346,6 +346,10 @@ static void tpm_del_char_device(struct tpm_chip *chip) down_write(&chip->ops_sem); if (chip->flags & TPM_CHIP_FLAG_TPM2) tpm2_shutdown(chip, TPM2_SU_CLEAR); + if (chip->flags & TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS) { + up_write(&chip->ops_sem); + return; + } chip->ops = NULL; up_write(&chip->ops_sem); } @@ -454,6 +458,7 @@ int tpm_chip_register(struct tpm_chip *chip) rc = tpm_add_legacy_sysfs(chip); if (rc) { + chip->flags |= TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS; tpm_chip_unregister(chip); return rc; } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f895fba4e20d..dc2a532649e0 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -183,6 +183,7 @@ enum tpm_chip_flags { TPM_CHIP_FLAG_VIRTUAL = BIT(3), TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), TPM_CHIP_FLAG_ALWAYS_POWERED= BIT(5), + TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS = BIT(6), }; struct tpm_bios_log { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index d29add49b033..a146ef4e499b 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -273,11 +273,9 @@ static void tpm_tis_pnp_remove(struct pnp_dev *dev) struct tpm_chip *chip = pnp_get_drvdata(dev); struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + chip->flags |= TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS; tpm_chip_unregister(chip); tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); - } static struct pnp_driver tis_pnp_driver = { @@ -326,12 +324,10 @@ static int tpm_tis_plat_remove(struct platform_device *pdev) struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + chip->flags |= TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS; tpm_chip_unregister(chip); tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); - return 0; } diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index c2227983ed88..d9099281fc2e 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -727,6 +727,14 @@ void tpm_tis_remove(struct tpm_chip *chip) if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); + + if (chip->flags & TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS) { + down_write(&chip->ops_sem); + chip->ops = NULL; + up_write(&chip->ops_sem); + } + if (priv->ilb_base_addr) + iounmap(priv->ilb_base_addr); } EXPORT_SYMBOL_GPL(tpm_tis_remove); @@ -922,21 +930,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, } rc = tpm_chip_register(chip); - if (rc && is_bsw()) - iounmap(priv->ilb_base_addr); + if (rc) + goto out_err; if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); - return rc; -out_err: - tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); + return 0; - if (chip->ops->clk_enable != NULL) +out_err: + if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL)) chip->ops->clk_enable(chip, false); + tpm_tis_remove(chip); + return rc; } EXPORT_SYMBOL_GPL(tpm_tis_core_init); diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 424ff2fde1f2..79c18cfc6519 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -221,6 +221,7 @@ static int tpm_tis_spi_remove(struct spi_device *dev)
[PATCH v2] tpm: Fix the driver cleanup code
Commit 3c1701339284353c41 ("tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()") added code which accessed chip->ops, even after it was set to NULL in tpm_del_char_device(), called from tpm_chip_unregister() in error / driver exit paths. So fix this code. Fixes: 3c1701339284353c41 ("tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()") Suggested-by: Javier Martinez Canillas Suggested-by: Jason Gunthorpe Signed-off-by: Azhar Shaikh --- Changes in v2: - Remove TPM_CHIP_FLAG_DO_NOT_CLEAR_OPS flag, instead call tpm_tis_clkrun_enable() directly in tpm_tis_remove() - Add comment to tpm_tis_clkrun_enable() drivers/char/tpm/tpm_tis.c | 6 -- drivers/char/tpm/tpm_tis_core.c | 29 + 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index d29add49b033..c847fc69a2fc 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -275,9 +275,6 @@ static void tpm_tis_pnp_remove(struct pnp_dev *dev) tpm_chip_unregister(chip); tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); - } static struct pnp_driver tis_pnp_driver = { @@ -329,9 +326,6 @@ static int tpm_tis_plat_remove(struct platform_device *pdev) tpm_chip_unregister(chip); tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); - return 0; } diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index c2227983ed88..519e4a78c8f8 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -37,6 +37,8 @@ */ #define TPM_POLL_SLEEP 1 /* msec */ +static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value); + static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, bool check_cancel, bool *canceled) { @@ -716,8 +718,7 @@ void tpm_tis_remove(struct tpm_chip *chip) u32 interrupt; int rc; - if (chip->ops->clk_enable != NULL) - chip->ops->clk_enable(chip, true); + tpm_tis_clkrun_enable(chip, true); rc = tpm_tis_read32(priv, reg, &interrupt); if (rc < 0) @@ -725,8 +726,10 @@ void tpm_tis_remove(struct tpm_chip *chip) tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); - if (chip->ops->clk_enable != NULL) - chip->ops->clk_enable(chip, false); + tpm_tis_clkrun_enable(chip, false); + + if (priv->ilb_base_addr) + iounmap(priv->ilb_base_addr); } EXPORT_SYMBOL_GPL(tpm_tis_remove); @@ -736,6 +739,9 @@ void tpm_tis_remove(struct tpm_chip *chip) * @chip: TPM chip to use * @value: 1 - Disable CLKRUN protocol, so that clocks are free running * 0 - Enable CLKRUN protocol + * + * Call this function directly in tpm_tis_remove() in error or driver removal + * path, since the chip->ops is set to NULL in tpm_chip_unregister(). */ static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value) { @@ -922,21 +928,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, } rc = tpm_chip_register(chip); - if (rc && is_bsw()) - iounmap(priv->ilb_base_addr); + if (rc) + goto out_err; if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); - return rc; -out_err: - tpm_tis_remove(chip); - if (is_bsw()) - iounmap(priv->ilb_base_addr); + return 0; - if (chip->ops->clk_enable != NULL) +out_err: + if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL)) chip->ops->clk_enable(chip, false); + tpm_tis_remove(chip); + return rc; } EXPORT_SYMBOL_GPL(tpm_tis_core_init); -- 1.9.1
[PATCH v6 1/2] tpm_tis: Move ilb_base_addr to tpm_tis_data
Move static variable ilb_base_addr to tpm_tis_data. Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm_tis.c | 75 +++-- drivers/char/tpm/tpm_tis_core.c | 16 - drivers/char/tpm/tpm_tis_core.h | 13 +++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..923f8f2cbaca 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,33 +134,24 @@ static int check_acpi_tpm2(struct device *dev) #endif #ifdef CONFIG_X86 -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 -#define LPC_CNTRL_REG_OFFSET0x84 -#define LPC_CLKRUN_EN (1 << 2) - -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} +#define LPC_CNTRL_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -173,18 +164,18 @@ static void tpm_platform_begin_xfer(void) /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -194,16 +185,11 @@ static void tpm_platform_end_xfer(void) } #else -static inline bool is_bsw(void) -{ - return false; -} - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +199,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +214,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -242,11 +228,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread16(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -255,11 +241,11 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread32(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -268,11 +254,11 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); iowrite32(value, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -351,9 +337,13 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_
[PATCH v6 0/2] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Changes from v4: - The numbering of patches is now interchanged. - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - Had to move ilb_base_addr to tpm_tis_data, from tpm_tis_tcg_phy. Since the ioremapping of ilb_base_addr had to be done before any TPM access, hence moved the variable to tpm_tis_data. - Also move the ioremapping of ilb_base_addr from tpm_tis_init() to tpm_tis_core_init() i.e. before any TPM access is done. - Rename marco LPC_CNTRL_REG_OFFSET to LPC_CNTRL_OFFSET - Update the commit message. - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove the functions tpm_platform_begin_xfer() and tpm_platform_end_xfer() - Move the code from these functions to tpm_tis_clkrun_enable(). Changes from v5: - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Update the commit message. Azhar Shaikh (2): tpm_tis: Move ilb_base_addr to tpm_tis_data tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() drivers/char/tpm/tpm-interface.c | 6 ++ drivers/char/tpm/tpm_tis.c | 121 ++- drivers/char/tpm/tpm_tis_core.c | 111 +-- drivers/char/tpm/tpm_tis_core.h | 17 ++ include/linux/tpm.h | 1 + 5 files changed, 147 insertions(+), 109 deletions(-) -- 1.9.1
[PATCH v6 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside TPM command flow, add a higher level of disabling and re-enabling the CLKRUN protocol, instead of doing for every TPM transaction. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 86 +--- drivers/char/tpm/tpm_tis_core.c | 95 +--- drivers/char/tpm/tpm_tis_core.h | 4 ++ include/linux/tpm.h | 1 + 5 files changed, 111 insertions(+), 81 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index ebe0a1d36d8c..6e19e3dd98e4 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -413,6 +413,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -489,6 +492,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 923f8f2cbaca..d29add49b033 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev) } #endif -#ifdef CONFIG_X86 -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) - -/** - * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running - */ -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Disable LPC CLKRUN# */ - clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} - -/** - * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off - */ -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Enable LPC CLKRUN# */ - clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} -#else -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ -} - -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ -} -#endif - static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -228,12 +165,11 @
[PATCH v6 0/2] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Changes from v4: - The numbering of patches is now interchanged. - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - Had to move ilb_base_addr to tpm_tis_data, from tpm_tis_tcg_phy. Since the ioremapping of ilb_base_addr had to be done before any TPM access, hence moved the variable to tpm_tis_data. - Also move the ioremapping of ilb_base_addr from tpm_tis_init() to tpm_tis_core_init() i.e. before any TPM access is done. - Rename marco LPC_CNTRL_REG_OFFSET to LPC_CNTRL_OFFSET - Update the commit message. - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove the functions tpm_platform_begin_xfer() and tpm_platform_end_xfer() - Move the code from these functions to tpm_tis_clkrun_enable(). Changes from v5: - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Update the commit message. Changes from v6: - - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - chip->ops was set to NULL in tpm_del_char_device() called from tpm_chip_unregister() in error/driver exit path. Fix this code. (Suggested by Javier Martinez Canillas and Jason Gunthorpe) - Add a comment in tpm_tis_clkrun_enable() function. Azhar Shaikh (2): tpm_tis: Move ilb_base_addr to tpm_tis_data tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() drivers/char/tpm/tpm-interface.c | 6 ++ drivers/char/tpm/tpm_tis.c | 121 ++- drivers/char/tpm/tpm_tis_core.c | 111 +-- drivers/char/tpm/tpm_tis_core.h | 17 ++ include/linux/tpm.h | 1 + 5 files changed, 147 insertions(+), 109 deletions(-) -- 1.9.1
[PATCH v7 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside TPM command flow, add a higher level of disabling and re-enabling the CLKRUN protocol, instead of doing for every TPM transaction. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh --- drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 92 - drivers/char/tpm/tpm_tis_core.c | 108 +++ drivers/char/tpm/tpm_tis_core.h | 4 ++ include/linux/tpm.h | 1 + 5 files changed, 119 insertions(+), 92 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index af355bd97bea..76df4fbcf089 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -425,6 +425,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -501,6 +504,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 923f8f2cbaca..c847fc69a2fc 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev) } #endif -#ifdef CONFIG_X86 -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) - -/** - * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running - */ -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Disable LPC CLKRUN# */ - clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} - -/** - * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off - */ -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Enable LPC CLKRUN# */ - clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} -#else -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ -} - -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ -} -#endif - static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -228,12 +165,11 @
[PATCH v7 1/2] tpm_tis: Move ilb_base_addr to tpm_tis_data
Move static variable ilb_base_addr to tpm_tis_data. Signed-off-by: Azhar Shaikh Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis.c | 75 +++-- drivers/char/tpm/tpm_tis_core.c | 16 - drivers/char/tpm/tpm_tis_core.h | 13 +++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..923f8f2cbaca 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,33 +134,24 @@ static int check_acpi_tpm2(struct device *dev) #endif #ifdef CONFIG_X86 -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 -#define LPC_CNTRL_REG_OFFSET0x84 -#define LPC_CLKRUN_EN (1 << 2) - -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} +#define LPC_CNTRL_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -173,18 +164,18 @@ static void tpm_platform_begin_xfer(void) /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -194,16 +185,11 @@ static void tpm_platform_end_xfer(void) } #else -static inline bool is_bsw(void) -{ - return false; -} - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +199,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +214,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -242,11 +228,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread16(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -255,11 +241,11 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread32(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -268,11 +254,11 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); iowrite32(value, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data
[PATCH v8 1/2] tpm_tis: Move ilb_base_addr to tpm_tis_data
Move static variable ilb_base_addr to tpm_tis_data. Signed-off-by: Azhar Shaikh Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis.c | 75 +++-- drivers/char/tpm/tpm_tis_core.c | 16 - drivers/char/tpm/tpm_tis_core.h | 13 +++ 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..923f8f2cbaca 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -134,33 +134,24 @@ static int check_acpi_tpm2(struct device *dev) #endif #ifdef CONFIG_X86 -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 -#define LPC_CNTRL_REG_OFFSET0x84 -#define LPC_CLKRUN_EN (1 << 2) - -static void __iomem *ilb_base_addr; - -static inline bool is_bsw(void) -{ - return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); -} +#define LPC_CNTRL_OFFSET 0x84 +#define LPC_CLKRUN_EN (1 << 2) /** * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running */ -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Disable LPC CLKRUN# */ clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -173,18 +164,18 @@ static void tpm_platform_begin_xfer(void) /** * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off */ -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { u32 clkrun_val; if (!is_bsw()) return; - clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); + clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); /* Enable LPC CLKRUN# */ clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); + iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); /* * Write any random value on port 0x80 which is on LPC, to make @@ -194,16 +185,11 @@ static void tpm_platform_end_xfer(void) } #else -static inline bool is_bsw(void) -{ - return false; -} - -static void tpm_platform_begin_xfer(void) +static void tpm_platform_begin_xfer(struct tpm_tis_data *data) { } -static void tpm_platform_end_xfer(void) +static void tpm_platform_end_xfer(struct tpm_tis_data *data) { } #endif @@ -213,12 +199,12 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -228,12 +214,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); while (len--) iowrite8(*value++, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -242,11 +228,11 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread16(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -255,11 +241,11 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); *result = ioread32(phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data); return 0; } @@ -268,11 +254,11 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(); + tpm_platform_begin_xfer(data); iowrite32(value, phy->iobase + addr); - tpm_platform_end_xfer(); + tpm_platform_end_xfer(data
[PATCH v8 0/2] Fix corner cases with disabling CLKRUN in tpm_tis
Changes from v1: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Add NULL checks before calling clk_toggle callback - Use IS_ENABLED instead of ifdef in tpm_tis_clkrun_toggle() - Do not call tpm_platform_begin_xfer() and tpm_platform_end_xfer() from tpm_tis_clkrun_toggle(). Make them static again. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - This is a new patch in this series as per suggestion from Jason. - Is the current implementation ok or I should move the code in tpm_tis_pnp_remove() and tpm_tis_plat_remove() inside tpm_tis_remove(). That way all the unmapping can be done in one place, instead of 3 different places now. Also the unmapping in tpm_tis_init() can be moved to tpm_tis_remove(), since in case of error tpm_tis_core_init() calls tpm_tis_remove(). Kindly suggest. Changes from v2: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - No changes - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - Updated is_bsw() function to have the #ifdef CONFIG_X86 check within the function itself. Also removed the #ifdef CONFIG_X86 from all other places around is_bsw() Changes from v3: - Patch 1: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Change function name from clk_toggle to clk_enable - Update the commit message. - Patch 2: "tpm_tis: Move ilb_base_addr to tpm_tis_tcg_phy" - No changes Changes from v4: - The numbering of patches is now interchanged. - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - Had to move ilb_base_addr to tpm_tis_data, from tpm_tis_tcg_phy. Since the ioremapping of ilb_base_addr had to be done before any TPM access, hence moved the variable to tpm_tis_data. - Also move the ioremapping of ilb_base_addr from tpm_tis_init() to tpm_tis_core_init() i.e. before any TPM access is done. - Rename marco LPC_CNTRL_REG_OFFSET to LPC_CNTRL_OFFSET - Update the commit message. - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove the functions tpm_platform_begin_xfer() and tpm_platform_end_xfer() - Move the code from these functions to tpm_tis_clkrun_enable(). Changes from v5: - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Update the commit message. Changes from v6: - - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - chip->ops was set to NULL in tpm_del_char_device() called from tpm_chip_unregister() in error/driver exit path. Fix this code. (Suggested by Javier Martinez Canillas and Jason Gunthorpe) - Add a comment in tpm_tis_clkrun_enable() function. Changes from v7: - Patch 1: "tpm_tis: Move ilb_base_addr to tpm_tis_data" - No changes - Patch 2: "tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()" - Remove unused variables warnings from tpm_tis_pnp_remove() and tpm_tis_plat_remove() (Suggested by Stephen Rothwell ) Azhar Shaikh (2): tpm_tis: Move ilb_base_addr to tpm_tis_data tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd() drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 113 -- drivers/char/tpm/tpm_tis_core.c | 114 --- drivers/char/tpm/tpm_tis_core.h | 17 ++ include/linux/tpm.h | 1 + 5 files changed, 142 insertions(+), 109 deletions(-) -- 1.9.1
[PATCH v8 2/2] tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
Commit 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") disabled CLKRUN protocol during TPM transactions and re-enabled once the transaction is completed. But there were still some corner cases observed where, reading of TPM header failed for savestate command while going to suspend, which resulted in suspend failure. To fix this issue keep the CLKRUN protocol disabled for the entire duration of a single TPM command and not disabling and re-enabling again for every TPM transaction. For the other TPM accesses outside TPM command flow, add a higher level of disabling and re-enabling the CLKRUN protocol, instead of doing for every TPM transaction. Fixes: 5e572cab92f0bb5 ("tpm: Enable CLKRUN protocol for Braswell systems") Signed-off-by: Azhar Shaikh Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 6 +++ drivers/char/tpm/tpm_tis.c | 94 -- drivers/char/tpm/tpm_tis_core.c | 108 +++ drivers/char/tpm/tpm_tis_core.h | 4 ++ include/linux/tpm.h | 1 + 5 files changed, 119 insertions(+), 94 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index af355bd97bea..76df4fbcf089 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -425,6 +425,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, if (chip->dev.parent) pm_runtime_get_sync(chip->dev.parent); + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, true); + /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; @@ -501,6 +504,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, chip->locality = -1; } out_no_locality: + if (chip->ops->clk_enable != NULL) + chip->ops->clk_enable(chip, false); + if (chip->dev.parent) pm_runtime_put_sync(chip->dev.parent); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 923f8f2cbaca..1bcbf355141e 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -133,79 +133,17 @@ static int check_acpi_tpm2(struct device *dev) } #endif -#ifdef CONFIG_X86 -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) - -/** - * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running - */ -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Disable LPC CLKRUN# */ - clkrun_val &= ~LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} - -/** - * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off - */ -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ - u32 clkrun_val; - - if (!is_bsw()) - return; - - clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* Enable LPC CLKRUN# */ - clkrun_val |= LPC_CLKRUN_EN; - iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); - - /* -* Write any random value on port 0x80 which is on LPC, to make -* sure LPC clock is running before sending any TPM command. -*/ - outb(0xCC, 0x80); - -} -#else -static void tpm_platform_begin_xfer(struct tpm_tis_data *data) -{ -} - -static void tpm_platform_end_xfer(struct tpm_tis_data *data) -{ -} -#endif - static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) *result++ = ioread8(phy->iobase + addr); - tpm_platform_end_xfer(data); - return 0; } @@ -214,13 +152,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, { struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); - tpm_platform_begin_xfer(data); + if (is_bsw() && !(data->flags & TPM_TIS_CLK_ENABLE)) + WARN(1, "CLKRUN not enabled!\n"); while (len--) iowrite8(*value++, phy->iobase + addr); -
[PATCH] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of UFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh Cc: Prashant Malani --- drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3eae01f4c9f7..eb4713b7ae14 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -590,7 +590,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v4 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect
On disconnect port partner is removed and usb role is set to NONE. But then in cros_typec_port_update() the role is set again. Avoid this by moving usb_role_switch_set_role() to cros_typec_configure_mux(). Suggested-by: Prashant Malani Signed-off-by: Azhar Shaikh --- Changes in v4: - Added Suggested-by from v2. Changes in v3: - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. Changes in v2: - New patch added drivers/platform/chrome/cros_ec_typec.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 06108212ee94..2b43e1176e73 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -533,7 +533,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - return ret; + if (ret) + return ret; + + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) @@ -590,9 +595,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - resp.role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps
As per USB Type-C Spec R2.0 section 4.5.1.2 (Connecting Sources and Sinks) and section 4.5.2.2 (Connection State Machine Requirements), the typical flow for configuring a device connected to a typeC port is as below: 1. Source/sink detection 2. Orientation 3. Data role 4. VCONN 5. VBUS (USB Type-C currents) 6. The connector is now configured. We can start the PD communication that should lead into configuration of the mux if we enter a mode. But in existing code data role was set after the connector and mux are already configured. So fix this by following the spec to set the data role before the connector and mux are configured. Signed-off-by: Azhar Shaikh --- Changes in v4: - No change Changes in v3: - New patch added drivers/platform/chrome/cros_ec_typec.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 2b43e1176e73..9e4fad9ca59e 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -516,6 +516,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); + if (ret) + return ret; + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { @@ -533,12 +539,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - if (ret) - return ret; - - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) -- 2.17.1
[PATCH v4 0/3] TypeC Connector Class driver improvements
Changes in v4: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Remove extra line between Fixes and Signed-off tag. - Added Reviewed-by and Cc tags from v1 and v2. * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Added Suggested-by from v2. * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - No change Changes in v3: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - No change * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - New patch added Changes in v2: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - New patch added. Azhar Shaikh (3): platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect platform/chrome: cros_ec_typec: Re-order connector configuration steps drivers/platform/chrome/cros_ec_typec.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.1
[PATCH v4 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of DFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh Cc: Prashant Malani Reviewed-by: Prashant Malani Reviewed-by: Heikki Krogerus --- Changes in v4: - Remove extra line between Fixes and Signed-off tag. - Added Reviewed-by and Cc tags from v1 and v2. Changes in v3: - No changes Changes in v2: - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 3fcd27ec9ad8..06108212ee94 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -591,7 +591,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v5 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps
As per USB Type-C Spec R2.0 section 4.5.1.2 (Connecting Sources and Sinks) and section 4.5.2.2 (Connection State Machine Requirements), the typical flow for configuring a device connected to a typeC port is as below: 1. Source/sink detection 2. Orientation 3. Data role 4. VCONN 5. VBUS (USB Type-C currents) 6. The connector is now configured. We can start the PD communication that should lead into configuration of the mux if we enter a mode. But in existing code data role was set after the connector and mux are already configured. So fix this by following the spec to set the data role before the connector and mux are configured. Signed-off-by: Azhar Shaikh Reviewed-by: Prashant Malani Reviewed-by: Heikki Krogerus --- Changes in v5: - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 - Added Reviewed-by from v4 Changes in v4: - No change Changes in v3: - New patch added drivers/platform/chrome/cros_ec_typec.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 39989069decf..31be31161350 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -545,6 +545,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, if (ret) return ret; + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); + if (ret) + return ret; + if (mux_flags & USB_PD_MUX_USB4_ENABLED) { ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl); } else if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { @@ -564,12 +570,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - if (ret) - return ret; - - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) -- 2.17.1
[PATCH v5 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
usb_role_switch_set_role() has the second argument as enum for usb_role. Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent. This eventually translates to USB_ROLE_NONE in case of UFP and USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of DFP. Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control") Signed-off-by: Azhar Shaikh Cc: Prashant Malani Reviewed-by: Prashant Malani Reviewed-by: Heikki Krogerus --- Changes in v5: - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 Changes in v4: - Remove extra line between Fixes and Signed-off tag. - Added Reviewed-by and Cc tags from v1 and v2. Changes in v3: - No changes Changes in v2: - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' drivers/platform/chrome/cros_ec_typec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 585f27e2b362..739a1c846949 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -622,7 +622,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); + resp.role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v5 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect
On disconnect port partner is removed and usb role is set to NONE. But then in cros_typec_port_update() the role is set again. Avoid this by moving usb_role_switch_set_role() to cros_typec_configure_mux(). Suggested-by: Prashant Malani Signed-off-by: Azhar Shaikh Reviewed-by: Heikki Krogerus --- Changes in v5: - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 - Added Reviewed-by from v4 Changes in v4: - Added Suggested-by from v2. Changes in v3: - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. Changes in v2: - New patch added drivers/platform/chrome/cros_ec_typec.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c index 739a1c846949..39989069decf 100644 --- a/drivers/platform/chrome/cros_ec_typec.c +++ b/drivers/platform/chrome/cros_ec_typec.c @@ -564,7 +564,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, ret = -ENOTSUPP; } - return ret; + if (ret) + return ret; + + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA + ? USB_ROLE_HOST : USB_ROLE_DEVICE); } static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) @@ -621,9 +626,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) if (ret) dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); - return usb_role_switch_set_role(typec->ports[port_num]->role_sw, - resp.role & PD_CTRL_RESP_ROLE_DATA - ? USB_ROLE_HOST : USB_ROLE_DEVICE); + return ret; } static int cros_typec_get_cmd_version(struct cros_typec_data *typec) -- 2.17.1
[PATCH v5 0/3] TypeC Connector Class driver improvements
Changes in v5: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 - Added Reviewed-by from v4 * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - Rebased on top of https://lkml.org/lkml/2020/7/10/1063 - Added Reviewed-by from v4 Changes in v4: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Remove extra line between Fixes and Signed-off tag. - Added Reviewed-by and Cc tags from v1 and v2. * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Added Suggested-by from v2. * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - No change Changes in v3: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - No change * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - Move the location of calling usb_role_switch_set_role() to end of function in cros_typec_configure_mux() to avoid any change in code flow. * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector configuration steps" - New patch added Changes in v2: * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()" - Update the commit message to change 'USB_ROLE_HOST in case of UFP.' to 'USB_ROLE_HOST in case of DFP.' * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect" - New patch added. Azhar Shaikh (3): platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect platform/chrome: cros_ec_typec: Re-order connector configuration steps drivers/platform/chrome/cros_ec_typec.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) -- 2.17.1