Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }