^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright(c) 2015, 2016 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file is provided under a dual BSD/GPLv2 license. When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * GPL LICENSE SUMMARY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * it under the terms of version 2 of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This program is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * BSD LICENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * - Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * - Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - Neither the name of Intel Corporation nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * contributors may be used to endorse or promote products derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "hfi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include "eprom.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * The EPROM is logically divided into three partitions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * partition 0: the first 128K, visible from PCI ROM BAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * partition 1: 4K config file (sector size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * partition 2: the rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define P0_SIZE (128 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define P1_SIZE (4 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define P1_START P0_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define P2_START (P0_SIZE + P1_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* controller page size, in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define EP_PAGE_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define EP_PAGE_MASK (EP_PAGE_SIZE - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define EP_PAGE_DWORDS (EP_PAGE_SIZE / sizeof(u32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* controller commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CMD_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CMD_NOP (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* controller interface speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define EP_SPEED_FULL 0x2 /* full speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * How long to wait for the EPROM to become available, in ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * The spec 32 Mb EPROM takes around 40s to erase then write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Double it for safety.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define EPROM_TIMEOUT 80000 /* ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Read a 256 byte (64 dword) EPROM page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * All callers have verified the offset is at a page boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void read_page(struct hfi1_devdata *dd, u32 offset, u32 *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_READ_DATA(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (i = 0; i < EP_PAGE_DWORDS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) result[i] = (u32)read_csr(dd, ASIC_EEP_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_NOP); /* close open page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Read length bytes starting at offset from the start of the EPROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int read_length(struct hfi1_devdata *dd, u32 start, u32 len, void *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 buffer[EP_PAGE_DWORDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 start_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 read_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u32 bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) end = start + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Make sure the read range is not outside of the controller read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * command address range. Note that '>' is correct below - the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * of the range is OK if it stops at the limit, but no higher.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (end > (1 << CMD_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* read the first partial page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) start_offset = start & EP_PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (start_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* partial starting page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* align and read the page that contains the start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) read_start = start & ~EP_PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) read_page(dd, read_start, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* the rest of the page is available data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) bytes = EP_PAGE_SIZE - start_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (len <= bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* end is within this page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) memcpy(dest, (u8 *)buffer + start_offset, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) memcpy(dest, (u8 *)buffer + start_offset, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) start += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) len -= bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dest += bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* start is now page aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* read whole pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) while (len >= EP_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) read_page(dd, start, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) memcpy(dest, buffer, EP_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) start += EP_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) len -= EP_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dest += EP_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* read the last partial page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) read_page(dd, start, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) memcpy(dest, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Initialize the EPROM handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int eprom_init(struct hfi1_devdata *dd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* only the discrete chip has an EPROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (dd->pcidev->device != PCI_DEVICE_ID_INTEL0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * It is OK if both HFIs reset the EPROM as long as they don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * do it at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ret = acquire_chip_resource(dd, CR_EPROM, EPROM_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dd_dev_err(dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "%s: unable to acquire EPROM resource, no EPROM support\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto done_asic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* reset EPROM to be sure it is in a good state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* set reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) write_csr(dd, ASIC_EEP_CTL_STAT, ASIC_EEP_CTL_STAT_EP_RESET_SMASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* clear reset, set speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) write_csr(dd, ASIC_EEP_CTL_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) EP_SPEED_FULL << ASIC_EEP_CTL_STAT_RATE_SPI_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* wake the device with command "release powerdown NoID" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_RELEASE_POWERDOWN_NOID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dd->eprom_available = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) release_chip_resource(dd, CR_EPROM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) done_asic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* magic character sequence that begins an image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #define IMAGE_START_MAGIC "APO="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* magic character sequence that might trail an image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define IMAGE_TRAIL_MAGIC "egamiAPO"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* EPROM file types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define HFI1_EFT_PLATFORM_CONFIG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* segment size - 128 KiB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define SEG_SIZE (128 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct hfi1_eprom_footer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u32 oprom_size; /* size of the oprom, in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u16 num_table_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u16 version; /* version of this footer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u32 magic; /* must be last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct hfi1_eprom_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 type; /* file type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u32 offset; /* file offset from start of EPROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 size; /* file size, in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * Calculate the max number of table entries that will fit within a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * buffer of size 'dir_size'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define MAX_TABLE_ENTRIES(dir_size) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (((dir_size) - sizeof(struct hfi1_eprom_footer)) / \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sizeof(struct hfi1_eprom_table_entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define DIRECTORY_SIZE(n) (sizeof(struct hfi1_eprom_footer) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) (sizeof(struct hfi1_eprom_table_entry) * (n)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define MAGIC4(a, b, c, d) ((d) << 24 | (c) << 16 | (b) << 8 | (a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define FOOTER_MAGIC MAGIC4('e', 'p', 'r', 'm')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #define FOOTER_VERSION 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * Read all of partition 1. The actual file is at the front. Adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * the returned size if a trailing image magic is found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int read_partition_platform_config(struct hfi1_devdata *dd, void **data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) void *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u32 length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) buffer = kmalloc(P1_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = read_length(dd, P1_START, P1_SIZE, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* config partition is valid only if it starts with IMAGE_START_MAGIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (memcmp(buffer, IMAGE_START_MAGIC, strlen(IMAGE_START_MAGIC))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* scan for image magic that may trail the actual data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) p = strnstr(buffer, IMAGE_TRAIL_MAGIC, P1_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) length = p - buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) length = P1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *data = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *size = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * The segment magic has been checked. There is a footer and table of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * contents present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * directory is a u32 aligned buffer of size EP_PAGE_SIZE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int read_segment_platform_config(struct hfi1_devdata *dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) void *directory, void **data, u32 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct hfi1_eprom_footer *footer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct hfi1_eprom_table_entry *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct hfi1_eprom_table_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) void *buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void *table_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 directory_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u32 seg_base, seg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u32 bytes_available, ncopied, to_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* the footer is at the end of the directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) footer = (struct hfi1_eprom_footer *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) (directory + EP_PAGE_SIZE - sizeof(*footer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* make sure the structure version is supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (footer->version != FOOTER_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* oprom size cannot be larger than a segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (footer->oprom_size >= SEG_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* the file table must fit in a segment with the oprom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (footer->num_table_entries >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) MAX_TABLE_ENTRIES(SEG_SIZE - footer->oprom_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* find the file table start, which precedes the footer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) directory_size = DIRECTORY_SIZE(footer->num_table_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (directory_size <= EP_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* the file table fits into the directory buffer handed in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) table = (struct hfi1_eprom_table_entry *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) (directory + EP_PAGE_SIZE - directory_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* need to allocate and read more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) table_buffer = kmalloc(directory_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!table_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ret = read_length(dd, SEG_SIZE - directory_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) directory_size, table_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) table = table_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* look for the platform configuration file in the table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) for (entry = NULL, i = 0; i < footer->num_table_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (table[i].type == HFI1_EFT_PLATFORM_CONFIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) entry = &table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Sanity check on the configuration file size - it should never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * be larger than 4 KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (entry->size > (4 * 1024)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dd_dev_err(dd, "Bad configuration file size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* check for bogus offset and size that wrap when added together */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (entry->offset + entry->size < entry->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dd_dev_err(dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "Bad configuration file start + size 0x%x+0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) entry->offset, entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* allocate the buffer to return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) buffer = kmalloc(entry->size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Extract the file by looping over segments until it is fully read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) seg_offset = entry->offset % SEG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) seg_base = entry->offset - seg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ncopied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) while (ncopied < entry->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* calculate data bytes available in this segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* start with the bytes from the current offset to the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) bytes_available = SEG_SIZE - seg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* subtract off footer and table from segment 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (seg_base == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * Sanity check: should not have a starting point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * at or within the directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (bytes_available <= directory_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) dd_dev_err(dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) "Bad configuration file - offset 0x%x within footer+table\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) entry->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) bytes_available -= directory_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* calculate bytes wanted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) to_copy = entry->size - ncopied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* max out at the available bytes in this segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (to_copy > bytes_available)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) to_copy = bytes_available;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Read from the EPROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * The sanity check for entry->offset is done in read_length().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * The EPROM offset is validated against what the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * addressing supports. In addition, if the offset is larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * than the actual EPROM, it silently wraps. It will work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * fine, though the reader may not get what they expected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * from the EPROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ret = read_length(dd, seg_base + seg_offset, to_copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) buffer + ncopied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ncopied += to_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* set up for next segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) seg_offset = footer->oprom_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) seg_base += SEG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *data = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) *size = entry->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) kfree(table_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * Read the platform configuration file from the EPROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * On success, an allocated buffer containing the data and its size are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * returned. It is up to the caller to free this buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Return value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * -ENXIO - no EPROM is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * -EBUSY - not able to acquire access to the EPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * -ENOENT - no recognizable file written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * -ENOMEM - buffer could not be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * -EINVAL - invalid EPROM contentents found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int eprom_read_platform_config(struct hfi1_devdata *dd, void **data, u32 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) u32 directory[EP_PAGE_DWORDS]; /* aligned buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (!dd->eprom_available)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ret = acquire_chip_resource(dd, CR_EPROM, EPROM_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* read the last page of the segment for the EPROM format magic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) ret = read_length(dd, SEG_SIZE - EP_PAGE_SIZE, EP_PAGE_SIZE, directory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* last dword of the segment contains a magic value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (directory[EP_PAGE_DWORDS - 1] == FOOTER_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* segment format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret = read_segment_platform_config(dd, directory, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* partition format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ret = read_partition_platform_config(dd, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) release_chip_resource(dd, CR_EPROM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }