blob: b5789f878560383dace7bd3341306909e77b6885 [file] [log] [blame]
Brijesh Singh2a6170d2017-12-04 10:57:28 -06001/*
2 * AMD Platform Security Processor (PSP) interface
3 *
4 * Copyright (C) 2016-2017 Advanced Micro Devices, Inc.
5 *
6 * Author: Brijesh Singh <brijesh.singh@amd.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/kthread.h>
16#include <linux/sched.h>
17#include <linux/interrupt.h>
18#include <linux/spinlock.h>
19#include <linux/spinlock_types.h>
20#include <linux/types.h>
21#include <linux/mutex.h>
22#include <linux/delay.h>
23#include <linux/hw_random.h>
24#include <linux/ccp.h>
25
26#include "sp-dev.h"
27#include "psp-dev.h"
28
29static struct psp_device *psp_alloc_struct(struct sp_device *sp)
30{
31 struct device *dev = sp->dev;
32 struct psp_device *psp;
33
34 psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
35 if (!psp)
36 return NULL;
37
38 psp->dev = dev;
39 psp->sp = sp;
40
41 snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
42
43 return psp;
44}
45
46static irqreturn_t psp_irq_handler(int irq, void *data)
47{
48 return IRQ_HANDLED;
49}
50
51int psp_dev_init(struct sp_device *sp)
52{
53 struct device *dev = sp->dev;
54 struct psp_device *psp;
55 int ret;
56
57 ret = -ENOMEM;
58 psp = psp_alloc_struct(sp);
59 if (!psp)
60 goto e_err;
61
62 sp->psp_data = psp;
63
64 psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
65 if (!psp->vdata) {
66 ret = -ENODEV;
67 dev_err(dev, "missing driver data\n");
68 goto e_err;
69 }
70
71 psp->io_regs = sp->io_map + psp->vdata->offset;
72
73 /* Disable and clear interrupts until ready */
74 iowrite32(0, psp->io_regs + PSP_P2CMSG_INTEN);
75 iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTSTS);
76
77 /* Request an irq */
78 ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
79 if (ret) {
80 dev_err(dev, "psp: unable to allocate an IRQ\n");
81 goto e_err;
82 }
83
84 if (sp->set_psp_master_device)
85 sp->set_psp_master_device(sp);
86
87 /* Enable interrupt */
88 iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTEN);
89
90 return 0;
91
92e_err:
93 sp->psp_data = NULL;
94
95 dev_notice(dev, "psp initialization failed\n");
96
97 return ret;
98}
99
100void psp_dev_destroy(struct sp_device *sp)
101{
102 struct psp_device *psp = sp->psp_data;
103
104 sp_free_psp_irq(sp, psp);
105}