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