crypto: ccp - Add ACPI support

Add support for ACPI to the CCP platform driver.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Tom Lendacky 2015-02-03 13:07:29 -06:00 коммит произвёл Herbert Xu
Родитель be03a3a096
Коммит 6c50634340
2 изменённых файлов: 93 добавлений и 5 удалений

Просмотреть файл

@ -391,7 +391,7 @@ config CRYPTO_DEV_ATMEL_SHA
config CRYPTO_DEV_CCP config CRYPTO_DEV_CCP
bool "Support for AMD Cryptographic Coprocessor" bool "Support for AMD Cryptographic Coprocessor"
depends on ((X86 && PCI) || ARM64) && HAS_IOMEM depends on ((X86 && PCI) || (ARM64 && (OF_ADDRESS || ACPI))) && HAS_IOMEM
default n default n
help help
The AMD Cryptographic Coprocessor provides hardware support The AMD Cryptographic Coprocessor provides hardware support

Просмотреть файл

@ -23,9 +23,16 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ccp.h> #include <linux/ccp.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h>
#include <linux/acpi.h>
#include "ccp-dev.h" #include "ccp-dev.h"
struct ccp_platform {
int use_acpi;
int coherent;
};
static int ccp_get_irq(struct ccp_device *ccp) static int ccp_get_irq(struct ccp_device *ccp)
{ {
struct device *dev = ccp->dev; struct device *dev = ccp->dev;
@ -83,10 +90,64 @@ static struct resource *ccp_find_mmio_area(struct ccp_device *ccp)
return NULL; return NULL;
} }
#ifdef CONFIG_ACPI
static int ccp_acpi_support(struct ccp_device *ccp)
{
struct ccp_platform *ccp_platform = ccp->dev_specific;
struct acpi_device *adev = ACPI_COMPANION(ccp->dev);
acpi_handle handle;
acpi_status status;
unsigned long long data;
int cca;
/* Retrieve the device cache coherency value */
handle = adev->handle;
do {
status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
if (!ACPI_FAILURE(status)) {
cca = data;
break;
}
} while (!ACPI_FAILURE(status));
if (ACPI_FAILURE(status)) {
dev_err(ccp->dev, "error obtaining acpi coherency value\n");
return -EINVAL;
}
ccp_platform->coherent = !!cca;
return 0;
}
#else /* CONFIG_ACPI */
static int ccp_acpi_support(struct ccp_device *ccp)
{
return -EINVAL;
}
#endif
#ifdef CONFIG_OF
static int ccp_of_support(struct ccp_device *ccp)
{
struct ccp_platform *ccp_platform = ccp->dev_specific;
ccp_platform->coherent = of_dma_is_coherent(ccp->dev->of_node);
return 0;
}
#else
static int ccp_of_support(struct ccp_device *ccp)
{
return -EINVAL;
}
#endif
static int ccp_platform_probe(struct platform_device *pdev) static int ccp_platform_probe(struct platform_device *pdev)
{ {
struct ccp_device *ccp; struct ccp_device *ccp;
struct ccp_platform *ccp_platform;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct acpi_device *adev = ACPI_COMPANION(dev);
struct resource *ior; struct resource *ior;
int ret; int ret;
@ -95,10 +156,16 @@ static int ccp_platform_probe(struct platform_device *pdev)
if (!ccp) if (!ccp)
goto e_err; goto e_err;
ccp->dev_specific = NULL; ccp_platform = devm_kzalloc(dev, sizeof(*ccp_platform), GFP_KERNEL);
if (!ccp_platform)
goto e_err;
ccp->dev_specific = ccp_platform;
ccp->get_irq = ccp_get_irqs; ccp->get_irq = ccp_get_irqs;
ccp->free_irq = ccp_free_irqs; ccp->free_irq = ccp_free_irqs;
ccp_platform->use_acpi = (!adev || acpi_disabled) ? 0 : 1;
ior = ccp_find_mmio_area(ccp); ior = ccp_find_mmio_area(ccp);
ccp->io_map = devm_ioremap_resource(dev, ior); ccp->io_map = devm_ioremap_resource(dev, ior);
if (IS_ERR(ccp->io_map)) { if (IS_ERR(ccp->io_map)) {
@ -115,7 +182,14 @@ static int ccp_platform_probe(struct platform_device *pdev)
goto e_err; goto e_err;
} }
if (of_property_read_bool(dev->of_node, "dma-coherent")) if (ccp_platform->use_acpi)
ret = ccp_acpi_support(ccp);
else
ret = ccp_of_support(ccp);
if (ret)
goto e_err;
if (ccp_platform->coherent)
ccp->axcache = CACHE_WB_NO_ALLOC; ccp->axcache = CACHE_WB_NO_ALLOC;
else else
ccp->axcache = CACHE_NONE; ccp->axcache = CACHE_NONE;
@ -197,15 +271,29 @@ static int ccp_platform_resume(struct platform_device *pdev)
} }
#endif #endif
static const struct of_device_id ccp_platform_ids[] = { #ifdef CONFIG_ACPI
static const struct acpi_device_id ccp_acpi_match[] = {
{ "AMDI0C00", 0 },
{ },
};
#endif
#ifdef CONFIG_OF
static const struct of_device_id ccp_of_match[] = {
{ .compatible = "amd,ccp-seattle-v1a" }, { .compatible = "amd,ccp-seattle-v1a" },
{ }, { },
}; };
#endif
static struct platform_driver ccp_platform_driver = { static struct platform_driver ccp_platform_driver = {
.driver = { .driver = {
.name = "AMD Cryptographic Coprocessor", .name = "AMD Cryptographic Coprocessor",
.of_match_table = ccp_platform_ids, #ifdef CONFIG_ACPI
.acpi_match_table = ccp_acpi_match,
#endif
#ifdef CONFIG_OF
.of_match_table = ccp_of_match,
#endif
}, },
.probe = ccp_platform_probe, .probe = ccp_platform_probe,
.remove = ccp_platform_remove, .remove = ccp_platform_remove,