0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/device.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/ioport.h>
0015 #include <linux/dma-mapping.h>
0016 #include <linux/kthread.h>
0017 #include <linux/sched.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/delay.h>
0021 #include <linux/ccp.h>
0022 #include <linux/of.h>
0023 #include <linux/of_address.h>
0024 #include <linux/acpi.h>
0025
0026 #include "ccp-dev.h"
0027
0028 struct sp_platform {
0029 int coherent;
0030 unsigned int irq_count;
0031 };
0032
0033 static const struct sp_dev_vdata dev_vdata[] = {
0034 {
0035 .bar = 0,
0036 #ifdef CONFIG_CRYPTO_DEV_SP_CCP
0037 .ccp_vdata = &ccpv3_platform,
0038 #endif
0039 },
0040 };
0041
0042 #ifdef CONFIG_ACPI
0043 static const struct acpi_device_id sp_acpi_match[] = {
0044 { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
0045 { },
0046 };
0047 MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
0048 #endif
0049
0050 #ifdef CONFIG_OF
0051 static const struct of_device_id sp_of_match[] = {
0052 { .compatible = "amd,ccp-seattle-v1a",
0053 .data = (const void *)&dev_vdata[0] },
0054 { },
0055 };
0056 MODULE_DEVICE_TABLE(of, sp_of_match);
0057 #endif
0058
0059 static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
0060 {
0061 #ifdef CONFIG_OF
0062 const struct of_device_id *match;
0063
0064 match = of_match_node(sp_of_match, pdev->dev.of_node);
0065 if (match && match->data)
0066 return (struct sp_dev_vdata *)match->data;
0067 #endif
0068 return NULL;
0069 }
0070
0071 static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
0072 {
0073 #ifdef CONFIG_ACPI
0074 const struct acpi_device_id *match;
0075
0076 match = acpi_match_device(sp_acpi_match, &pdev->dev);
0077 if (match && match->driver_data)
0078 return (struct sp_dev_vdata *)match->driver_data;
0079 #endif
0080 return NULL;
0081 }
0082
0083 static int sp_get_irqs(struct sp_device *sp)
0084 {
0085 struct sp_platform *sp_platform = sp->dev_specific;
0086 struct device *dev = sp->dev;
0087 struct platform_device *pdev = to_platform_device(dev);
0088 int ret;
0089
0090 sp_platform->irq_count = platform_irq_count(pdev);
0091
0092 ret = platform_get_irq(pdev, 0);
0093 if (ret < 0) {
0094 dev_notice(dev, "unable to get IRQ (%d)\n", ret);
0095 return ret;
0096 }
0097
0098 sp->psp_irq = ret;
0099 if (sp_platform->irq_count == 1) {
0100 sp->ccp_irq = ret;
0101 } else {
0102 ret = platform_get_irq(pdev, 1);
0103 if (ret < 0) {
0104 dev_notice(dev, "unable to get IRQ (%d)\n", ret);
0105 return ret;
0106 }
0107
0108 sp->ccp_irq = ret;
0109 }
0110
0111 return 0;
0112 }
0113
0114 static int sp_platform_probe(struct platform_device *pdev)
0115 {
0116 struct sp_device *sp;
0117 struct sp_platform *sp_platform;
0118 struct device *dev = &pdev->dev;
0119 enum dev_dma_attr attr;
0120 int ret;
0121
0122 ret = -ENOMEM;
0123 sp = sp_alloc_struct(dev);
0124 if (!sp)
0125 goto e_err;
0126
0127 sp_platform = devm_kzalloc(dev, sizeof(*sp_platform), GFP_KERNEL);
0128 if (!sp_platform)
0129 goto e_err;
0130
0131 sp->dev_specific = sp_platform;
0132 sp->dev_vdata = pdev->dev.of_node ? sp_get_of_version(pdev)
0133 : sp_get_acpi_version(pdev);
0134 if (!sp->dev_vdata) {
0135 ret = -ENODEV;
0136 dev_err(dev, "missing driver data\n");
0137 goto e_err;
0138 }
0139
0140 sp->io_map = devm_platform_ioremap_resource(pdev, 0);
0141 if (IS_ERR(sp->io_map)) {
0142 ret = PTR_ERR(sp->io_map);
0143 goto e_err;
0144 }
0145
0146 attr = device_get_dma_attr(dev);
0147 if (attr == DEV_DMA_NOT_SUPPORTED) {
0148 dev_err(dev, "DMA is not supported");
0149 goto e_err;
0150 }
0151
0152 sp_platform->coherent = (attr == DEV_DMA_COHERENT);
0153 if (sp_platform->coherent)
0154 sp->axcache = CACHE_WB_NO_ALLOC;
0155 else
0156 sp->axcache = CACHE_NONE;
0157
0158 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
0159 if (ret) {
0160 dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
0161 goto e_err;
0162 }
0163
0164 ret = sp_get_irqs(sp);
0165 if (ret)
0166 goto e_err;
0167
0168 dev_set_drvdata(dev, sp);
0169
0170 ret = sp_init(sp);
0171 if (ret)
0172 goto e_err;
0173
0174 dev_notice(dev, "enabled\n");
0175
0176 return 0;
0177
0178 e_err:
0179 dev_notice(dev, "initialization failed\n");
0180 return ret;
0181 }
0182
0183 static int sp_platform_remove(struct platform_device *pdev)
0184 {
0185 struct device *dev = &pdev->dev;
0186 struct sp_device *sp = dev_get_drvdata(dev);
0187
0188 sp_destroy(sp);
0189
0190 dev_notice(dev, "disabled\n");
0191
0192 return 0;
0193 }
0194
0195 #ifdef CONFIG_PM
0196 static int sp_platform_suspend(struct platform_device *pdev,
0197 pm_message_t state)
0198 {
0199 struct device *dev = &pdev->dev;
0200 struct sp_device *sp = dev_get_drvdata(dev);
0201
0202 return sp_suspend(sp);
0203 }
0204
0205 static int sp_platform_resume(struct platform_device *pdev)
0206 {
0207 struct device *dev = &pdev->dev;
0208 struct sp_device *sp = dev_get_drvdata(dev);
0209
0210 return sp_resume(sp);
0211 }
0212 #endif
0213
0214 static struct platform_driver sp_platform_driver = {
0215 .driver = {
0216 .name = "ccp",
0217 #ifdef CONFIG_ACPI
0218 .acpi_match_table = sp_acpi_match,
0219 #endif
0220 #ifdef CONFIG_OF
0221 .of_match_table = sp_of_match,
0222 #endif
0223 },
0224 .probe = sp_platform_probe,
0225 .remove = sp_platform_remove,
0226 #ifdef CONFIG_PM
0227 .suspend = sp_platform_suspend,
0228 .resume = sp_platform_resume,
0229 #endif
0230 };
0231
0232 int sp_platform_init(void)
0233 {
0234 return platform_driver_register(&sp_platform_driver);
0235 }
0236
0237 void sp_platform_exit(void)
0238 {
0239 platform_driver_unregister(&sp_platform_driver);
0240 }