xref: /openbmc/phosphor-mboxd/mboxd_lpc.c (revision acdbdd14)
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