1*4fe996c2SAndrew Jeffery // SPDX-License-Identifier: Apache-2.0
2*4fe996c2SAndrew Jeffery // Copyright (C) 2018 IBM Corp.
3e39c9163SSuraj Jitindar Singh
4e39c9163SSuraj Jitindar Singh #define _GNU_SOURCE
5e39c9163SSuraj Jitindar Singh #include <assert.h>
6e39c9163SSuraj Jitindar Singh #include <errno.h>
7e39c9163SSuraj Jitindar Singh #include <fcntl.h>
8e39c9163SSuraj Jitindar Singh #include <getopt.h>
9e39c9163SSuraj Jitindar Singh #include <limits.h>
10e39c9163SSuraj Jitindar Singh #include <poll.h>
11e39c9163SSuraj Jitindar Singh #include <stdbool.h>
12e39c9163SSuraj Jitindar Singh #include <stdint.h>
13e39c9163SSuraj Jitindar Singh #include <stdio.h>
14e39c9163SSuraj Jitindar Singh #include <stdlib.h>
15e39c9163SSuraj Jitindar Singh #include <string.h>
16e39c9163SSuraj Jitindar Singh #include <syslog.h>
17e39c9163SSuraj Jitindar Singh #include <signal.h>
18e39c9163SSuraj Jitindar Singh #include <sys/ioctl.h>
19e39c9163SSuraj Jitindar Singh #include <sys/mman.h>
20e39c9163SSuraj Jitindar Singh #include <sys/stat.h>
21e39c9163SSuraj Jitindar Singh #include <sys/timerfd.h>
22e39c9163SSuraj Jitindar Singh #include <sys/types.h>
23e39c9163SSuraj Jitindar Singh #include <time.h>
24e39c9163SSuraj Jitindar Singh #include <unistd.h>
25e39c9163SSuraj Jitindar Singh #include <inttypes.h>
26e39c9163SSuraj Jitindar Singh
27e39c9163SSuraj Jitindar Singh #include "mbox.h"
28e39c9163SSuraj Jitindar Singh #include "common.h"
29e39c9163SSuraj Jitindar Singh #include "mboxd_lpc.h"
30e39c9163SSuraj Jitindar Singh #include "mboxd_flash.h"
31e39c9163SSuraj Jitindar Singh #include <linux/aspeed-lpc-ctrl.h>
32e39c9163SSuraj Jitindar Singh
33e39c9163SSuraj Jitindar Singh #define LPC_CTRL_PATH "/dev/aspeed-lpc-ctrl"
34e39c9163SSuraj Jitindar Singh
__init_lpc_dev(struct mbox_context * context,const char * path)3507a76843SAndrew Jeffery int __init_lpc_dev(struct mbox_context *context, const char *path)
36e39c9163SSuraj Jitindar Singh {
37e39c9163SSuraj Jitindar Singh struct aspeed_lpc_ctrl_mapping map = {
38e39c9163SSuraj Jitindar Singh .window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
39e39c9163SSuraj Jitindar Singh .window_id = 0, /* There's only one */
40e39c9163SSuraj Jitindar Singh .flags = 0,
41e39c9163SSuraj Jitindar Singh .addr = 0,
42e39c9163SSuraj Jitindar Singh .offset = 0,
43e39c9163SSuraj Jitindar Singh .size = 0
44e39c9163SSuraj Jitindar Singh };
45e39c9163SSuraj Jitindar Singh int fd;
46e39c9163SSuraj Jitindar Singh
47e39c9163SSuraj Jitindar Singh /* Open LPC Device */
4828519598SSuraj Jitindar Singh MSG_DBG("Opening %s\n", path);
4907a76843SAndrew Jeffery fd = open(path, O_RDWR | O_SYNC);
50e39c9163SSuraj Jitindar Singh if (fd < 0) {
51e39c9163SSuraj Jitindar Singh MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n",
5207a76843SAndrew Jeffery path, strerror(errno));
53e39c9163SSuraj Jitindar Singh return -errno;
54e39c9163SSuraj Jitindar Singh }
55e39c9163SSuraj Jitindar Singh
56e39c9163SSuraj Jitindar Singh context->fds[LPC_CTRL_FD].fd = fd;
57e39c9163SSuraj Jitindar Singh
58e39c9163SSuraj Jitindar Singh /* Find Size of Reserved Memory Region */
5928519598SSuraj Jitindar Singh MSG_DBG("Getting buffer size...\n");
60e39c9163SSuraj Jitindar Singh if (ioctl(fd, ASPEED_LPC_CTRL_IOCTL_GET_SIZE, &map) < 0) {
61e39c9163SSuraj Jitindar Singh MSG_ERR("Couldn't get lpc control buffer size: %s\n",
62e39c9163SSuraj Jitindar Singh strerror(errno));
63e39c9163SSuraj Jitindar Singh return -errno;
64e39c9163SSuraj Jitindar Singh }
65e39c9163SSuraj Jitindar Singh
66e39c9163SSuraj Jitindar Singh context->mem_size = map.size;
67e39c9163SSuraj Jitindar Singh /* Map at the top of the 28-bit LPC firmware address space-0 */
68e39c9163SSuraj Jitindar Singh context->lpc_base = 0x0FFFFFFF & -context->mem_size;
69e39c9163SSuraj Jitindar Singh
70e39c9163SSuraj Jitindar Singh /* mmap the Reserved Memory Region */
7128519598SSuraj Jitindar Singh MSG_DBG("Mapping in 0x%.8x bytes of %s\n", context->mem_size, path);
72e39c9163SSuraj Jitindar Singh context->mem = mmap(NULL, context->mem_size, PROT_READ | PROT_WRITE,
73e39c9163SSuraj Jitindar Singh MAP_SHARED, fd, 0);
74e39c9163SSuraj Jitindar Singh if (context->mem == MAP_FAILED) {
75093d65adSAndrew Jeffery MSG_ERR("Failed to map %s: %s\n", path, strerror(errno));
76e39c9163SSuraj Jitindar Singh return -errno;
77e39c9163SSuraj Jitindar Singh }
78e39c9163SSuraj Jitindar Singh
79e39c9163SSuraj Jitindar Singh return 0;
80e39c9163SSuraj Jitindar Singh }
81e39c9163SSuraj Jitindar Singh
init_lpc_dev(struct mbox_context * context)8207a76843SAndrew Jeffery int init_lpc_dev(struct mbox_context *context)
8307a76843SAndrew Jeffery {
8407a76843SAndrew Jeffery return __init_lpc_dev(context, LPC_CTRL_PATH);
8507a76843SAndrew Jeffery }
8607a76843SAndrew Jeffery
free_lpc_dev(struct mbox_context * context)87e39c9163SSuraj Jitindar Singh void free_lpc_dev(struct mbox_context *context)
88e39c9163SSuraj Jitindar Singh {
89e39c9163SSuraj Jitindar Singh if (context->mem) {
90e39c9163SSuraj Jitindar Singh munmap(context->mem, context->mem_size);
91e39c9163SSuraj Jitindar Singh }
92e39c9163SSuraj Jitindar Singh close(context->fds[LPC_CTRL_FD].fd);
93e39c9163SSuraj Jitindar Singh }
94e39c9163SSuraj Jitindar Singh
95e39c9163SSuraj Jitindar Singh /*
96e39c9163SSuraj Jitindar Singh * point_to_flash() - Point the lpc bus mapping to the actual flash device
97e39c9163SSuraj Jitindar Singh * @context: The mbox context pointer
98e39c9163SSuraj Jitindar Singh *
99e39c9163SSuraj Jitindar Singh * Return: 0 on success otherwise negative error code
100e39c9163SSuraj Jitindar Singh */
point_to_flash(struct mbox_context * context)101e39c9163SSuraj Jitindar Singh int point_to_flash(struct mbox_context *context)
102e39c9163SSuraj Jitindar Singh {
103e39c9163SSuraj Jitindar Singh struct aspeed_lpc_ctrl_mapping map = {
104e39c9163SSuraj Jitindar Singh .window_type = ASPEED_LPC_CTRL_WINDOW_FLASH,
105e39c9163SSuraj Jitindar Singh .window_id = 0, /* Theres only one */
106e39c9163SSuraj Jitindar Singh .flags = 0,
107e39c9163SSuraj Jitindar Singh /*
108e39c9163SSuraj Jitindar Singh * The mask is because the top nibble is the host LPC FW space,
109e39c9163SSuraj Jitindar Singh * we want space 0.
110e39c9163SSuraj Jitindar Singh */
111e39c9163SSuraj Jitindar Singh .addr = 0x0FFFFFFF & -context->flash_size,
112e39c9163SSuraj Jitindar Singh .offset = 0,
113e39c9163SSuraj Jitindar Singh .size = context->flash_size
114e39c9163SSuraj Jitindar Singh };
115e39c9163SSuraj Jitindar Singh
116e39c9163SSuraj Jitindar Singh if (context->state & MAPS_FLASH) {
117e39c9163SSuraj Jitindar Singh return 0; /* LPC Bus already points to flash */
118e39c9163SSuraj Jitindar Singh }
119e39c9163SSuraj Jitindar Singh /* Don't let the host access flash while we're suspended */
120e39c9163SSuraj Jitindar Singh if (context->state & STATE_SUSPENDED) {
121e39c9163SSuraj Jitindar Singh MSG_ERR("Can't point lpc mapping to flash while suspended\n");
122e39c9163SSuraj Jitindar Singh return -MBOX_R_PARAM_ERROR;
123e39c9163SSuraj Jitindar Singh }
124e39c9163SSuraj Jitindar Singh
12528519598SSuraj Jitindar Singh MSG_INFO("Pointing HOST LPC bus at the flash\n");
12628519598SSuraj Jitindar Singh MSG_INFO("Assuming %dMB of flash: HOST LPC 0x%08x\n",
127e39c9163SSuraj Jitindar Singh context->flash_size >> 20, map.addr);
128e39c9163SSuraj Jitindar Singh
129e39c9163SSuraj Jitindar Singh if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP, &map)
130e39c9163SSuraj Jitindar Singh == -1) {
131e39c9163SSuraj Jitindar Singh MSG_ERR("Failed to point the LPC BUS at the actual flash: %s\n",
132e39c9163SSuraj Jitindar Singh strerror(errno));
133e39c9163SSuraj Jitindar Singh return -MBOX_R_SYSTEM_ERROR;
134e39c9163SSuraj Jitindar Singh }
135e39c9163SSuraj Jitindar Singh
136e39c9163SSuraj Jitindar Singh context->state = ACTIVE_MAPS_FLASH;
137e39c9163SSuraj Jitindar Singh /*
138e39c9163SSuraj Jitindar Singh * Since the host now has access to the flash it can change it out from
139e39c9163SSuraj Jitindar Singh * under us
140e39c9163SSuraj Jitindar Singh */
141e39c9163SSuraj Jitindar Singh return set_flash_bytemap(context, 0, context->flash_size, FLASH_DIRTY);
142e39c9163SSuraj Jitindar Singh }
143e39c9163SSuraj Jitindar Singh
144e39c9163SSuraj Jitindar Singh /*
145e39c9163SSuraj Jitindar Singh * point_to_memory() - Point the lpc bus mapping to the reserved memory region
146e39c9163SSuraj Jitindar Singh * @context: The mbox context pointer
147e39c9163SSuraj Jitindar Singh *
148e39c9163SSuraj Jitindar Singh * Return: 0 on success otherwise negative error code
149e39c9163SSuraj Jitindar Singh */
point_to_memory(struct mbox_context * context)150e39c9163SSuraj Jitindar Singh int point_to_memory(struct mbox_context *context)
151e39c9163SSuraj Jitindar Singh {
152e39c9163SSuraj Jitindar Singh struct aspeed_lpc_ctrl_mapping map = {
153e39c9163SSuraj Jitindar Singh .window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
154e39c9163SSuraj Jitindar Singh .window_id = 0, /* There's only one */
155e39c9163SSuraj Jitindar Singh .flags = 0,
156e39c9163SSuraj Jitindar Singh .addr = context->lpc_base,
157e39c9163SSuraj Jitindar Singh .offset = 0,
158e39c9163SSuraj Jitindar Singh .size = context->mem_size
159e39c9163SSuraj Jitindar Singh };
160e39c9163SSuraj Jitindar Singh
161e39c9163SSuraj Jitindar Singh if (context->state & MAPS_MEM) {
162e39c9163SSuraj Jitindar Singh return 0; /* LPC Bus already points to reserved memory area */
163e39c9163SSuraj Jitindar Singh }
164e39c9163SSuraj Jitindar Singh
16528519598SSuraj Jitindar Singh MSG_INFO("Pointing HOST LPC bus at memory region %p of size 0x%.8x\n",
166e39c9163SSuraj Jitindar Singh context->mem, context->mem_size);
16728519598SSuraj Jitindar Singh MSG_INFO("LPC address 0x%.8x\n", map.addr);
168e39c9163SSuraj Jitindar Singh
169e39c9163SSuraj Jitindar Singh if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP,
170e39c9163SSuraj Jitindar Singh &map)) {
171e39c9163SSuraj Jitindar Singh MSG_ERR("Failed to point the LPC BUS to memory: %s\n",
172e39c9163SSuraj Jitindar Singh strerror(errno));
173e39c9163SSuraj Jitindar Singh return -MBOX_R_SYSTEM_ERROR;
174e39c9163SSuraj Jitindar Singh }
175e39c9163SSuraj Jitindar Singh
176e39c9163SSuraj Jitindar Singh /* LPC now maps memory (keep suspended state) */
177e39c9163SSuraj Jitindar Singh context->state = MAPS_MEM | (context->state & STATE_SUSPENDED);
178e39c9163SSuraj Jitindar Singh
179e39c9163SSuraj Jitindar Singh return 0;
180e39c9163SSuraj Jitindar Singh }
181