xref: /openbmc/phosphor-mboxd/mboxd_lpc.c (revision 07a76843)
1e39c9163SSuraj Jitindar Singh /*
2e39c9163SSuraj Jitindar Singh  * Mailbox Daemon LPC Helpers
3e39c9163SSuraj Jitindar Singh  *
4e39c9163SSuraj Jitindar Singh  * Copyright 2016 IBM
5e39c9163SSuraj Jitindar Singh  *
6e39c9163SSuraj Jitindar Singh  * Licensed under the Apache License, Version 2.0 (the "License");
7e39c9163SSuraj Jitindar Singh  * you may not use this file except in compliance with the License.
8e39c9163SSuraj Jitindar Singh  * You may obtain a copy of the License at
9e39c9163SSuraj Jitindar Singh  *
10e39c9163SSuraj Jitindar Singh  * http://www.apache.org/licenses/LICENSE-2.0
11e39c9163SSuraj Jitindar Singh  *
12e39c9163SSuraj Jitindar Singh  * Unless required by applicable law or agreed to in writing, software
13e39c9163SSuraj Jitindar Singh  * distributed under the License is distributed on an "AS IS" BASIS,
14e39c9163SSuraj Jitindar Singh  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15e39c9163SSuraj Jitindar Singh  * See the License for the specific language governing permissions and
16e39c9163SSuraj Jitindar Singh  * limitations under the License.
17e39c9163SSuraj Jitindar Singh  *
18e39c9163SSuraj Jitindar Singh  */
19e39c9163SSuraj Jitindar Singh 
20e39c9163SSuraj Jitindar Singh #define _GNU_SOURCE
21e39c9163SSuraj Jitindar Singh #include <assert.h>
22e39c9163SSuraj Jitindar Singh #include <errno.h>
23e39c9163SSuraj Jitindar Singh #include <fcntl.h>
24e39c9163SSuraj Jitindar Singh #include <getopt.h>
25e39c9163SSuraj Jitindar Singh #include <limits.h>
26e39c9163SSuraj Jitindar Singh #include <poll.h>
27e39c9163SSuraj Jitindar Singh #include <stdbool.h>
28e39c9163SSuraj Jitindar Singh #include <stdint.h>
29e39c9163SSuraj Jitindar Singh #include <stdio.h>
30e39c9163SSuraj Jitindar Singh #include <stdlib.h>
31e39c9163SSuraj Jitindar Singh #include <string.h>
32e39c9163SSuraj Jitindar Singh #include <syslog.h>
33e39c9163SSuraj Jitindar Singh #include <signal.h>
34e39c9163SSuraj Jitindar Singh #include <sys/ioctl.h>
35e39c9163SSuraj Jitindar Singh #include <sys/mman.h>
36e39c9163SSuraj Jitindar Singh #include <sys/stat.h>
37e39c9163SSuraj Jitindar Singh #include <sys/timerfd.h>
38e39c9163SSuraj Jitindar Singh #include <sys/types.h>
39e39c9163SSuraj Jitindar Singh #include <time.h>
40e39c9163SSuraj Jitindar Singh #include <unistd.h>
41e39c9163SSuraj Jitindar Singh #include <inttypes.h>
42e39c9163SSuraj Jitindar Singh 
43e39c9163SSuraj Jitindar Singh #include "mbox.h"
44e39c9163SSuraj Jitindar Singh #include "common.h"
45e39c9163SSuraj Jitindar Singh #include "mboxd_lpc.h"
46e39c9163SSuraj Jitindar Singh #include "mboxd_flash.h"
47e39c9163SSuraj Jitindar Singh #include <linux/aspeed-lpc-ctrl.h>
48e39c9163SSuraj Jitindar Singh 
49e39c9163SSuraj Jitindar Singh #define LPC_CTRL_PATH		"/dev/aspeed-lpc-ctrl"
50e39c9163SSuraj Jitindar Singh 
51*07a76843SAndrew Jeffery int __init_lpc_dev(struct mbox_context *context, const char *path)
52e39c9163SSuraj Jitindar Singh {
53e39c9163SSuraj Jitindar Singh 	struct aspeed_lpc_ctrl_mapping map = {
54e39c9163SSuraj Jitindar Singh 		.window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
55e39c9163SSuraj Jitindar Singh 		.window_id = 0, /* There's only one */
56e39c9163SSuraj Jitindar Singh 		.flags = 0,
57e39c9163SSuraj Jitindar Singh 		.addr = 0,
58e39c9163SSuraj Jitindar Singh 		.offset = 0,
59e39c9163SSuraj Jitindar Singh 		.size = 0
60e39c9163SSuraj Jitindar Singh 	};
61e39c9163SSuraj Jitindar Singh 	int fd;
62e39c9163SSuraj Jitindar Singh 
63e39c9163SSuraj Jitindar Singh 	/* Open LPC Device */
64*07a76843SAndrew Jeffery 	MSG_OUT("Opening %s\n", path);
65*07a76843SAndrew Jeffery 	fd = open(path, O_RDWR | O_SYNC);
66e39c9163SSuraj Jitindar Singh 	if (fd < 0) {
67e39c9163SSuraj Jitindar Singh 		MSG_ERR("Couldn't open %s with flags O_RDWR: %s\n",
68*07a76843SAndrew Jeffery 			path, strerror(errno));
69e39c9163SSuraj Jitindar Singh 		return -errno;
70e39c9163SSuraj Jitindar Singh 	}
71e39c9163SSuraj Jitindar Singh 
72e39c9163SSuraj Jitindar Singh 	context->fds[LPC_CTRL_FD].fd = fd;
73e39c9163SSuraj Jitindar Singh 
74e39c9163SSuraj Jitindar Singh 	/* Find Size of Reserved Memory Region */
75e39c9163SSuraj Jitindar Singh 	MSG_OUT("Getting buffer size...\n");
76e39c9163SSuraj Jitindar Singh 	if (ioctl(fd, ASPEED_LPC_CTRL_IOCTL_GET_SIZE, &map) < 0) {
77e39c9163SSuraj Jitindar Singh 		MSG_ERR("Couldn't get lpc control buffer size: %s\n",
78e39c9163SSuraj Jitindar Singh 			strerror(errno));
79e39c9163SSuraj Jitindar Singh 		return -errno;
80e39c9163SSuraj Jitindar Singh 	}
81e39c9163SSuraj Jitindar Singh 
82e39c9163SSuraj Jitindar Singh 	context->mem_size = map.size;
83e39c9163SSuraj Jitindar Singh 	/* Map at the top of the 28-bit LPC firmware address space-0 */
84e39c9163SSuraj Jitindar Singh 	context->lpc_base = 0x0FFFFFFF & -context->mem_size;
85e39c9163SSuraj Jitindar Singh 
86e39c9163SSuraj Jitindar Singh 	/* mmap the Reserved Memory Region */
87*07a76843SAndrew Jeffery 	MSG_OUT("Mapping %s for %u\n", path, context->mem_size);
88e39c9163SSuraj Jitindar Singh 	context->mem = mmap(NULL, context->mem_size, PROT_READ | PROT_WRITE,
89e39c9163SSuraj Jitindar Singh 				MAP_SHARED, fd, 0);
90e39c9163SSuraj Jitindar Singh 	if (context->mem == MAP_FAILED) {
91e39c9163SSuraj Jitindar Singh 		MSG_ERR("Didn't manage to mmap %s: %s\n", LPC_CTRL_PATH,
92e39c9163SSuraj Jitindar Singh 			strerror(errno));
93e39c9163SSuraj Jitindar Singh 		return -errno;
94e39c9163SSuraj Jitindar Singh 	}
95e39c9163SSuraj Jitindar Singh 
96e39c9163SSuraj Jitindar Singh 	return 0;
97e39c9163SSuraj Jitindar Singh }
98e39c9163SSuraj Jitindar Singh 
99*07a76843SAndrew Jeffery int init_lpc_dev(struct mbox_context *context)
100*07a76843SAndrew Jeffery {
101*07a76843SAndrew Jeffery 	return __init_lpc_dev(context, LPC_CTRL_PATH);
102*07a76843SAndrew Jeffery }
103*07a76843SAndrew Jeffery 
104e39c9163SSuraj Jitindar Singh void free_lpc_dev(struct mbox_context *context)
105e39c9163SSuraj Jitindar Singh {
106e39c9163SSuraj Jitindar Singh 	if (context->mem) {
107e39c9163SSuraj Jitindar Singh 		munmap(context->mem, context->mem_size);
108e39c9163SSuraj Jitindar Singh 	}
109e39c9163SSuraj Jitindar Singh 	close(context->fds[LPC_CTRL_FD].fd);
110e39c9163SSuraj Jitindar Singh }
111e39c9163SSuraj Jitindar Singh 
112e39c9163SSuraj Jitindar Singh /*
113e39c9163SSuraj Jitindar Singh  * point_to_flash() - Point the lpc bus mapping to the actual flash device
114e39c9163SSuraj Jitindar Singh  * @context:	The mbox context pointer
115e39c9163SSuraj Jitindar Singh  *
116e39c9163SSuraj Jitindar Singh  * Return:	0 on success otherwise negative error code
117e39c9163SSuraj Jitindar Singh  */
118e39c9163SSuraj Jitindar Singh int point_to_flash(struct mbox_context *context)
119e39c9163SSuraj Jitindar Singh {
120e39c9163SSuraj Jitindar Singh 	struct aspeed_lpc_ctrl_mapping map = {
121e39c9163SSuraj Jitindar Singh 		.window_type = ASPEED_LPC_CTRL_WINDOW_FLASH,
122e39c9163SSuraj Jitindar Singh 		.window_id = 0, /* Theres only one */
123e39c9163SSuraj Jitindar Singh 		.flags = 0,
124e39c9163SSuraj Jitindar Singh 		/*
125e39c9163SSuraj Jitindar Singh 		 * The mask is because the top nibble is the host LPC FW space,
126e39c9163SSuraj Jitindar Singh 		 * we want space 0.
127e39c9163SSuraj Jitindar Singh 		 */
128e39c9163SSuraj Jitindar Singh 		.addr = 0x0FFFFFFF & -context->flash_size,
129e39c9163SSuraj Jitindar Singh 		.offset = 0,
130e39c9163SSuraj Jitindar Singh 		.size = context->flash_size
131e39c9163SSuraj Jitindar Singh 	};
132e39c9163SSuraj Jitindar Singh 
133e39c9163SSuraj Jitindar Singh 	if (context->state & MAPS_FLASH) {
134e39c9163SSuraj Jitindar Singh 		return 0; /* LPC Bus already points to flash */
135e39c9163SSuraj Jitindar Singh 	}
136e39c9163SSuraj Jitindar Singh 	/* Don't let the host access flash while we're suspended */
137e39c9163SSuraj Jitindar Singh 	if (context->state & STATE_SUSPENDED) {
138e39c9163SSuraj Jitindar Singh 		MSG_ERR("Can't point lpc mapping to flash while suspended\n");
139e39c9163SSuraj Jitindar Singh 		return -MBOX_R_PARAM_ERROR;
140e39c9163SSuraj Jitindar Singh 	}
141e39c9163SSuraj Jitindar Singh 
142e39c9163SSuraj Jitindar Singh 	MSG_OUT("Pointing HOST LPC bus at the actual flash\n");
143e39c9163SSuraj Jitindar Singh 	MSG_OUT("Assuming %dMB of flash: HOST LPC 0x%08x\n",
144e39c9163SSuraj Jitindar Singh 		context->flash_size >> 20, map.addr);
145e39c9163SSuraj Jitindar Singh 
146e39c9163SSuraj Jitindar Singh 	if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP, &map)
147e39c9163SSuraj Jitindar Singh 			== -1) {
148e39c9163SSuraj Jitindar Singh 		MSG_ERR("Failed to point the LPC BUS at the actual flash: %s\n",
149e39c9163SSuraj Jitindar Singh 			strerror(errno));
150e39c9163SSuraj Jitindar Singh 		return -MBOX_R_SYSTEM_ERROR;
151e39c9163SSuraj Jitindar Singh 	}
152e39c9163SSuraj Jitindar Singh 
153e39c9163SSuraj Jitindar Singh 	context->state = ACTIVE_MAPS_FLASH;
154e39c9163SSuraj Jitindar Singh 	/*
155e39c9163SSuraj Jitindar Singh 	 * Since the host now has access to the flash it can change it out from
156e39c9163SSuraj Jitindar Singh 	 * under us
157e39c9163SSuraj Jitindar Singh 	 */
158e39c9163SSuraj Jitindar Singh 	return set_flash_bytemap(context, 0, context->flash_size, FLASH_DIRTY);
159e39c9163SSuraj Jitindar Singh }
160e39c9163SSuraj Jitindar Singh 
161e39c9163SSuraj Jitindar Singh /*
162e39c9163SSuraj Jitindar Singh  * point_to_memory() - Point the lpc bus mapping to the reserved memory region
163e39c9163SSuraj Jitindar Singh  * @context:	The mbox context pointer
164e39c9163SSuraj Jitindar Singh  *
165e39c9163SSuraj Jitindar Singh  * Return:	0 on success otherwise negative error code
166e39c9163SSuraj Jitindar Singh  */
167e39c9163SSuraj Jitindar Singh int point_to_memory(struct mbox_context *context)
168e39c9163SSuraj Jitindar Singh {
169e39c9163SSuraj Jitindar Singh 	struct aspeed_lpc_ctrl_mapping map = {
170e39c9163SSuraj Jitindar Singh 		.window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
171e39c9163SSuraj Jitindar Singh 		.window_id = 0, /* There's only one */
172e39c9163SSuraj Jitindar Singh 		.flags = 0,
173e39c9163SSuraj Jitindar Singh 		.addr = context->lpc_base,
174e39c9163SSuraj Jitindar Singh 		.offset = 0,
175e39c9163SSuraj Jitindar Singh 		.size = context->mem_size
176e39c9163SSuraj Jitindar Singh 	};
177e39c9163SSuraj Jitindar Singh 
178e39c9163SSuraj Jitindar Singh 	if (context->state & MAPS_MEM) {
179e39c9163SSuraj Jitindar Singh 		return 0; /* LPC Bus already points to reserved memory area */
180e39c9163SSuraj Jitindar Singh 	}
181e39c9163SSuraj Jitindar Singh 
182e39c9163SSuraj Jitindar Singh 	MSG_OUT("Pointing HOST LPC bus at memory region %p of size 0x%.8x\n",
183e39c9163SSuraj Jitindar Singh 			context->mem, context->mem_size);
184e39c9163SSuraj Jitindar Singh 	MSG_OUT("LPC address 0x%.8x\n", map.addr);
185e39c9163SSuraj Jitindar Singh 
186e39c9163SSuraj Jitindar Singh 	if (ioctl(context->fds[LPC_CTRL_FD].fd, ASPEED_LPC_CTRL_IOCTL_MAP,
187e39c9163SSuraj Jitindar Singh 		  &map)) {
188e39c9163SSuraj Jitindar Singh 		MSG_ERR("Failed to point the LPC BUS to memory: %s\n",
189e39c9163SSuraj Jitindar Singh 			strerror(errno));
190e39c9163SSuraj Jitindar Singh 		return -MBOX_R_SYSTEM_ERROR;
191e39c9163SSuraj Jitindar Singh 	}
192e39c9163SSuraj Jitindar Singh 
193e39c9163SSuraj Jitindar Singh 	/* LPC now maps memory (keep suspended state) */
194e39c9163SSuraj Jitindar Singh 	context->state = MAPS_MEM | (context->state & STATE_SUSPENDED);
195e39c9163SSuraj Jitindar Singh 
196e39c9163SSuraj Jitindar Singh 	return 0;
197e39c9163SSuraj Jitindar Singh }
198