summaryrefslogtreecommitdiff
path: root/core/tee/se/reader/passthru_reader/driver.c
blob: 4d82b89e0ec91b98e199d5108c9cf2fcdb48ef8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2014, Linaro Limited
 * All rights reserved.
 */

#include <platform_config.h>
#include <io.h>
#include <initcall.h>
#include <tee/se/reader/interface.h>
#include <mm/core_memprot.h>

#include <trace.h>

#include <stdlib.h>

#include "pcsc.h"
#include "reader.h"

struct pcsc_context {
	uint32_t mmio_base;
	uint8_t num_readers;
	struct pcsc_reader *readers;
};
static struct pcsc_context pcsc_context;

register_phys_mem(MEM_AREA_IO_SEC, PCSC_BASE, 0x1000);

static uint32_t pcsc_read_reg(struct pcsc_context *ctx, uint8_t offset)
{
	return read32(ctx->mmio_base + offset);
}

static void pcsc_write_reg(struct pcsc_context *ctx, uint8_t offset,
		uint32_t value) __attribute__((unused));
static void pcsc_write_reg(struct pcsc_context *ctx, uint8_t offset,
		uint32_t value)
{
	write32(ctx->mmio_base + offset, value);
}

static TEE_Result populate_readers(struct pcsc_context *ctx)
{
	int i;
	uint32_t reader_mmio_base = ctx->mmio_base + PCSC_REG_MAX;
	TEE_Result ret;

	ctx->readers = malloc(sizeof(struct pcsc_reader) * ctx->num_readers);
	if (!ctx->readers)
		return TEE_ERROR_OUT_OF_MEMORY;

	for (i = 0; i < ctx->num_readers; i++) {
		uint32_t mmio_base =
			reader_mmio_base + (i * PCSC_REG_READER_MAX);
		struct pcsc_reader *r = &ctx->readers[i];

		init_reader(r, i, mmio_base);
		ret = tee_se_manager_register_reader(&r->se_reader);
		if (ret != TEE_SUCCESS)
			goto err_rollback;
	}

	return TEE_SUCCESS;

err_rollback:
	i--;
	while (i) {
		tee_se_manager_unregister_reader(&ctx->readers[i].se_reader);
		i--;
	}
	free(ctx->readers);
	return ret;
}

static void context_init(struct pcsc_context *ctx)
{
	ctx->mmio_base = (vaddr_t)phys_to_virt(PCSC_BASE, MEM_AREA_IO_SEC);
	if (ctx->mmio_base) {
		ctx->num_readers = pcsc_read_reg(ctx, PCSC_REG_NUM_READERS);
		DMSG("%d reader detected", ctx->num_readers);
	}
}

static TEE_Result pcsc_passthru_reader_init(void)
{
	TEE_Result ret;
	struct pcsc_context *ctx = &pcsc_context;

	context_init(ctx);

	ret = populate_readers(ctx);
	if (ret != TEE_SUCCESS)
		return ret;

	return TEE_SUCCESS;
}

driver_init(pcsc_passthru_reader_init);