diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index a74af0d7703a..2bed3e926f80 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -18,7 +18,8 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ hygon/psp-dev.o \ hygon/csv-dev.o \ hygon/ring-buffer.o \ - hygon/vpsp.o + hygon/vpsp.o \ + hygon/sp-dev.o ccp-$(CONFIG_TDM_DEV_HYGON) += hygon/tdm-dev.o diff --git a/drivers/crypto/ccp/hygon/psp-dev.c b/drivers/crypto/ccp/hygon/psp-dev.c index c150aa163a7a..d6133c0f8602 100644 --- a/drivers/crypto/ccp/hygon/psp-dev.c +++ b/drivers/crypto/ccp/hygon/psp-dev.c @@ -739,3 +739,40 @@ int sp_request_hygon_psp_irq(struct sp_device *sp, irq_handler_t handler, } #endif /* CONFIG_HYGON_PSP2CPU_CMD */ + +#ifdef CONFIG_PM_SLEEP + +void hygon_psp_dev_freeze(struct sp_device *sp) +{ + struct psp_device *psp; + + if (!psp_master) + return; + + psp = sp->psp_data; + if (psp == psp_master) + psp_pci_exit(); +} + +void hygon_psp_dev_thaw(struct sp_device *sp) +{ + struct psp_device *psp; + + if (!psp_master) + return; + + psp = sp->psp_data; + + /* re-enable interrupt */ + iowrite32(-1, psp->io_regs + psp->vdata->inten_reg); + + if (psp == psp_master) + psp_pci_init(); +} + +void hygon_psp_dev_restore(struct sp_device *sp) +{ + hygon_psp_dev_thaw(sp); +} + +#endif diff --git a/drivers/crypto/ccp/hygon/psp-dev.h b/drivers/crypto/ccp/hygon/psp-dev.h index f60a112881be..57dca0b73157 100644 --- a/drivers/crypto/ccp/hygon/psp-dev.h +++ b/drivers/crypto/ccp/hygon/psp-dev.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "sp-dev.h" @@ -71,4 +72,10 @@ int fixup_hygon_psp_caps(struct psp_device *psp); int sp_request_hygon_psp_irq(struct sp_device *sp, irq_handler_t handler, const char *name, void *data); +#ifdef CONFIG_PM_SLEEP +void hygon_psp_dev_freeze(struct sp_device *sp); +void hygon_psp_dev_thaw(struct sp_device *sp); +void hygon_psp_dev_restore(struct sp_device *sp); +#endif + #endif /* __CCP_HYGON_PSP_DEV_H__ */ diff --git a/drivers/crypto/ccp/hygon/sp-dev.c b/drivers/crypto/ccp/hygon/sp-dev.c new file mode 100644 index 000000000000..727ffd16421e --- /dev/null +++ b/drivers/crypto/ccp/hygon/sp-dev.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * HYGON Platform Security Processor (PSP) interface + * + * Copyright (C) 2024 Hygon Info Technologies Ltd. + * + * Author: Zhaowei Bai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "sp-dev.h" + +#ifdef CONFIG_PM_SLEEP + +int hygon_sp_suspend(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_suspend(sp); + + return 0; +} + +int hygon_sp_resume(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_resume(sp); + + return 0; +} + +int hygon_sp_freeze(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_suspend(sp); + + if (sp->dev_vdata->psp_vdata) + hygon_psp_dev_freeze(sp); + + return 0; +} + +int hygon_sp_thaw(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_resume(sp); + + if (sp->dev_vdata->psp_vdata) + hygon_psp_dev_thaw(sp); + + return 0; +} + +int hygon_sp_poweroff(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_suspend(sp); + + return 0; +} + +int hygon_sp_restore(struct sp_device *sp) +{ + if (sp->dev_vdata->ccp_vdata) + ccp_dev_resume(sp); + + if (sp->dev_vdata->psp_vdata) + hygon_psp_dev_restore(sp); + + return 0; +} + +#endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/crypto/ccp/hygon/sp-dev.h b/drivers/crypto/ccp/hygon/sp-dev.h index e1996fc3b7c6..b11c2f225e10 100644 --- a/drivers/crypto/ccp/hygon/sp-dev.h +++ b/drivers/crypto/ccp/hygon/sp-dev.h @@ -15,6 +15,7 @@ #include "../ccp-dev.h" #include "../sp-dev.h" +#include "psp-dev.h" #ifdef CONFIG_X86_64 static inline bool is_vendor_hygon(void) @@ -27,4 +28,17 @@ static inline bool is_vendor_hygon(void) { return false; } extern const struct sp_dev_vdata hygon_dev_vdata[]; +#ifdef CONFIG_PM_SLEEP + +int hygon_sp_suspend(struct sp_device *sp); +int hygon_sp_resume(struct sp_device *sp); +int hygon_sp_freeze(struct sp_device *sp); +int hygon_sp_thaw(struct sp_device *sp); +int hygon_sp_poweroff(struct sp_device *sp); +int hygon_sp_restore(struct sp_device *sp); + +void hygon_set_pm_cb(struct pci_driver *drv); + +#endif + #endif /* __CCP_HYGON_SP_DEV_H__ */ diff --git a/drivers/crypto/ccp/hygon/sp-pci.c b/drivers/crypto/ccp/hygon/sp-pci.c index 691127a0007b..88b42522bc23 100644 --- a/drivers/crypto/ccp/hygon/sp-pci.c +++ b/drivers/crypto/ccp/hygon/sp-pci.c @@ -72,3 +72,63 @@ const struct sp_dev_vdata hygon_dev_vdata[] = { #endif }, }; + +#ifdef CONFIG_PM_SLEEP + +static int hygon_sp_pci_suspend(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_suspend(sp); +} + +static int hygon_sp_pci_resume(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_resume(sp); +} + +static int hygon_sp_pci_freeze(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_freeze(sp); +} + +static int hygon_sp_pci_thaw(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_thaw(sp); +} + +static int hygon_sp_pci_poweroff(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_poweroff(sp); +} + +static int hygon_sp_pci_restore(struct device *dev) +{ + struct sp_device *sp = dev_get_drvdata(dev); + + return hygon_sp_restore(sp); +} + +static const struct dev_pm_ops hygon_pm_ops = { + .suspend = hygon_sp_pci_suspend, + .resume = hygon_sp_pci_resume, + .freeze = hygon_sp_pci_freeze, + .thaw = hygon_sp_pci_thaw, + .poweroff = hygon_sp_pci_poweroff, + .restore = hygon_sp_pci_restore, +}; + +void hygon_set_pm_cb(struct pci_driver *drv) +{ + drv->driver.pm = &hygon_pm_ops; +} + +#endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index d093ff250910..dc8e1c24a1d1 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -602,6 +602,11 @@ static struct pci_driver sp_pci_driver = { int sp_pci_init(void) { +#ifdef CONFIG_PM_SLEEP + /* Set pm driver callbacks for Hygon secure processor */ + if (is_vendor_hygon()) + hygon_set_pm_cb(&sp_pci_driver); +#endif return pci_register_driver(&sp_pci_driver); }