summaryrefslogtreecommitdiff
path: root/aoc.h
blob: cfcf011e54c96158a66ecaa25ab80b79e8ad2f91 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
/*
 * Google Whitechapel AoC Core Driver
 *
 * Copyright (c) 2019 Google LLC
 *
 * 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 <linux/device.h>
#include <linux/sizes.h>
#include "aoc_ipc_core.h"
#include "uapi/aoc.h"

#ifdef __KERNEL__

struct aoc_service_dev;
typedef void (*aoc_service_dev_handler)(struct aoc_service_dev *d);

struct aoc_service_dev {
	struct device dev;
	wait_queue_head_t read_queue;
	wait_queue_head_t write_queue;

	aoc_service *service;
	void *ipc_base;
	aoc_service_dev_handler handler;
	void *prvdata;
	uint64_t suspend_rx_count;

	uint8_t mbox_index;
	uint8_t service_index;

	bool dead;
	bool wake_capable;
};

#define AOC_DEVICE(_d) container_of((_d), struct aoc_service_dev, dev)

phys_addr_t aoc_service_ring_base_phys_addr(struct aoc_service_dev *dev, aoc_direction dir,
					    size_t *out_size);
phys_addr_t aoc_get_heap_base_phys_addr(struct aoc_service_dev *dev, aoc_direction dir,
					    size_t *out_size);
ssize_t aoc_service_read(struct aoc_service_dev *dev, uint8_t *buffer,
			 size_t count, bool block);
ssize_t aoc_service_read_timeout(struct aoc_service_dev *dev, uint8_t *buffer,
				 size_t count, long timeout);
ssize_t aoc_service_write(struct aoc_service_dev *dev, const uint8_t *buffer,
			  size_t count, bool block);
ssize_t aoc_service_write_timeout(struct aoc_service_dev *dev, const uint8_t *buffer,
				  size_t count, long timeout);
int aoc_service_can_read(struct aoc_service_dev *dev);
int aoc_service_can_write(struct aoc_service_dev *dev);
void aoc_service_set_read_blocked(struct aoc_service_dev *dev);
void aoc_service_set_write_blocked(struct aoc_service_dev *dev);
wait_queue_head_t *aoc_service_get_read_queue(struct aoc_service_dev *dev);
wait_queue_head_t *aoc_service_get_write_queue(struct aoc_service_dev *dev);

/*
 * Returns true if data was flushed, false if no data was flushed
 */
bool aoc_service_flush_read_data(struct aoc_service_dev *dev);

struct aoc_driver {
	struct device_driver drv;

	/* Array of service names to match against.  Last entry must be NULL */
	const char * const *service_names;
	int (*probe)(struct aoc_service_dev *dev);
	int (*remove)(struct aoc_service_dev *dev);
};
#define AOC_DRIVER(_d) container_of((_d), struct aoc_driver, drv)

int aoc_driver_register(struct aoc_driver *driver);
void aoc_driver_unregister(struct aoc_driver *driver);

typedef int (*aoc_map_handler)(u32 handle, phys_addr_t p, size_t size,
				bool mapped, void *ctx);
void aoc_set_map_handler(struct aoc_service_dev *dev, aoc_map_handler handler,
			 void *ctx);
void aoc_remove_map_handler(struct aoc_service_dev *dev);
void aoc_trigger_watchdog(const char *reason);

#define AOC_SERVICE_NAME_LENGTH 32

/* Rings should have the ring flag set, slots = 1, size = ring size
 * tx/rx stats for rings are measured in bytes, otherwise msg sends
 */
#define AOC_MAX_ENDPOINTS 64
#define AOC_ENDPOINT_NONE 0xffffffff

/* Offset from the beginning of the DRAM region for the firmware to be stored */
#define AOC_CHARDEV_NAME "aoc"

#define AOC_DOWNCALL_DOORBELL 12

#define AOC_GPIO_BASE 0xB70000

#define AOC_PCU_BASE 0xB00000
#define AOC_PCU_DB_SET_OFFSET 0xD004
#define AOC_PCU_DB_CLR_OFFSET 0xD008
#define AOC_PCU_REVISION_OFFSET 0xF000
#define AOC_PCU_RESET_CONTROL_OFFSET 0x0
#define AOC_PCU_RESET_CONTROL_RESET_VALUE 0x0
#define AOC_PCU_WATCHDOG_CONTROL_OFFSET 0x3000
#define AOC_PCU_WATCHDOG_KEY_OFFSET 0x3004
#define AOC_PCU_WATCHDOG_VALUE_OFFSET 0x3008

#define AOC_PCU_WATCHDOG_KEY_UNLOCK 0xA55AA55A
#define AOC_PCU_WATCHDOG_CONTROL_KEY_ENABLED_MASK 0x4

#define AOC_BINARY_DRAM_BASE 0x98000000
#define AOC_BINARY_LOAD_ADDRESS 0x98000000
#define AOC_BINARY_DRAM_OFFSET (AOC_BINARY_LOAD_ADDRESS - AOC_BINARY_DRAM_BASE)

#define AOC_PARAMETER_MAGIC 0x0a0cda7a
enum AOC_FIRMWARE_INFORMATION {
	kAOCBoardID = 0x1001,
	kAOCBoardRevision = 0x1002,
	kAOCSRAMRepaired = 0x1003,
	kAOCASVTableVersion = 0x1004,
	kAOCCarveoutAddress = 0x1005,
	kAOCCarveoutSize = 0x1006,
	kAOCSensorDirectHeapAddress = 0x1007,
	kAOCSensorDirectHeapSize = 0x1008,
	kAOCForceVNOM = 0x1009,
	kAOCDisableMM = 0x100A,
	kAOCEnableUART = 0x100B,
	kAOCPlaybackHeapAddress = 0x100C,
	kAOCPlaybackHeapSize = 0x100D,
	kAOCCaptureHeapAddress = 0x100E,
	kAOCCaptureHeapSize = 0x100F,
};

#define module_aoc_driver(__aoc_driver)                                        \
	module_driver(__aoc_driver, aoc_driver_register, aoc_driver_unregister)

#endif /* __KERNEL__ */