Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2015, 2016 Intel Corporation.
0004  */
0005 
0006 #include <linux/delay.h>
0007 #include "hfi.h"
0008 #include "common.h"
0009 #include "eprom.h"
0010 
0011 /*
0012  * The EPROM is logically divided into three partitions:
0013  *  partition 0: the first 128K, visible from PCI ROM BAR
0014  *  partition 1: 4K config file (sector size)
0015  *  partition 2: the rest
0016  */
0017 #define P0_SIZE (128 * 1024)
0018 #define P1_SIZE   (4 * 1024)
0019 #define P1_START P0_SIZE
0020 #define P2_START (P0_SIZE + P1_SIZE)
0021 
0022 /* controller page size, in bytes */
0023 #define EP_PAGE_SIZE 256
0024 #define EP_PAGE_MASK (EP_PAGE_SIZE - 1)
0025 #define EP_PAGE_DWORDS (EP_PAGE_SIZE / sizeof(u32))
0026 
0027 /* controller commands */
0028 #define CMD_SHIFT 24
0029 #define CMD_NOP             (0)
0030 #define CMD_READ_DATA(addr)     ((0x03 << CMD_SHIFT) | addr)
0031 #define CMD_RELEASE_POWERDOWN_NOID  ((0xab << CMD_SHIFT))
0032 
0033 /* controller interface speeds */
0034 #define EP_SPEED_FULL 0x2   /* full speed */
0035 
0036 /*
0037  * How long to wait for the EPROM to become available, in ms.
0038  * The spec 32 Mb EPROM takes around 40s to erase then write.
0039  * Double it for safety.
0040  */
0041 #define EPROM_TIMEOUT 80000 /* ms */
0042 
0043 /*
0044  * Read a 256 byte (64 dword) EPROM page.
0045  * All callers have verified the offset is at a page boundary.
0046  */
0047 static void read_page(struct hfi1_devdata *dd, u32 offset, u32 *result)
0048 {
0049     int i;
0050 
0051     write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_READ_DATA(offset));
0052     for (i = 0; i < EP_PAGE_DWORDS; i++)
0053         result[i] = (u32)read_csr(dd, ASIC_EEP_DATA);
0054     write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_NOP); /* close open page */
0055 }
0056 
0057 /*
0058  * Read length bytes starting at offset from the start of the EPROM.
0059  */
0060 static int read_length(struct hfi1_devdata *dd, u32 start, u32 len, void *dest)
0061 {
0062     u32 buffer[EP_PAGE_DWORDS];
0063     u32 end;
0064     u32 start_offset;
0065     u32 read_start;
0066     u32 bytes;
0067 
0068     if (len == 0)
0069         return 0;
0070 
0071     end = start + len;
0072 
0073     /*
0074      * Make sure the read range is not outside of the controller read
0075      * command address range.  Note that '>' is correct below - the end
0076      * of the range is OK if it stops at the limit, but no higher.
0077      */
0078     if (end > (1 << CMD_SHIFT))
0079         return -EINVAL;
0080 
0081     /* read the first partial page */
0082     start_offset = start & EP_PAGE_MASK;
0083     if (start_offset) {
0084         /* partial starting page */
0085 
0086         /* align and read the page that contains the start */
0087         read_start = start & ~EP_PAGE_MASK;
0088         read_page(dd, read_start, buffer);
0089 
0090         /* the rest of the page is available data */
0091         bytes = EP_PAGE_SIZE - start_offset;
0092 
0093         if (len <= bytes) {
0094             /* end is within this page */
0095             memcpy(dest, (u8 *)buffer + start_offset, len);
0096             return 0;
0097         }
0098 
0099         memcpy(dest, (u8 *)buffer + start_offset, bytes);
0100 
0101         start += bytes;
0102         len -= bytes;
0103         dest += bytes;
0104     }
0105     /* start is now page aligned */
0106 
0107     /* read whole pages */
0108     while (len >= EP_PAGE_SIZE) {
0109         read_page(dd, start, buffer);
0110         memcpy(dest, buffer, EP_PAGE_SIZE);
0111 
0112         start += EP_PAGE_SIZE;
0113         len -= EP_PAGE_SIZE;
0114         dest += EP_PAGE_SIZE;
0115     }
0116 
0117     /* read the last partial page */
0118     if (len) {
0119         read_page(dd, start, buffer);
0120         memcpy(dest, buffer, len);
0121     }
0122 
0123     return 0;
0124 }
0125 
0126 /*
0127  * Initialize the EPROM handler.
0128  */
0129 int eprom_init(struct hfi1_devdata *dd)
0130 {
0131     int ret = 0;
0132 
0133     /* only the discrete chip has an EPROM */
0134     if (dd->pcidev->device != PCI_DEVICE_ID_INTEL0)
0135         return 0;
0136 
0137     /*
0138      * It is OK if both HFIs reset the EPROM as long as they don't
0139      * do it at the same time.
0140      */
0141     ret = acquire_chip_resource(dd, CR_EPROM, EPROM_TIMEOUT);
0142     if (ret) {
0143         dd_dev_err(dd,
0144                "%s: unable to acquire EPROM resource, no EPROM support\n",
0145                __func__);
0146         goto done_asic;
0147     }
0148 
0149     /* reset EPROM to be sure it is in a good state */
0150 
0151     /* set reset */
0152     write_csr(dd, ASIC_EEP_CTL_STAT, ASIC_EEP_CTL_STAT_EP_RESET_SMASK);
0153     /* clear reset, set speed */
0154     write_csr(dd, ASIC_EEP_CTL_STAT,
0155           EP_SPEED_FULL << ASIC_EEP_CTL_STAT_RATE_SPI_SHIFT);
0156 
0157     /* wake the device with command "release powerdown NoID" */
0158     write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_RELEASE_POWERDOWN_NOID);
0159 
0160     dd->eprom_available = true;
0161     release_chip_resource(dd, CR_EPROM);
0162 done_asic:
0163     return ret;
0164 }
0165 
0166 /* magic character sequence that begins an image */
0167 #define IMAGE_START_MAGIC "APO="
0168 
0169 /* magic character sequence that might trail an image */
0170 #define IMAGE_TRAIL_MAGIC "egamiAPO"
0171 
0172 /* EPROM file types */
0173 #define HFI1_EFT_PLATFORM_CONFIG 2
0174 
0175 /* segment size - 128 KiB */
0176 #define SEG_SIZE (128 * 1024)
0177 
0178 struct hfi1_eprom_footer {
0179     u32 oprom_size;     /* size of the oprom, in bytes */
0180     u16 num_table_entries;
0181     u16 version;        /* version of this footer */
0182     u32 magic;      /* must be last */
0183 };
0184 
0185 struct hfi1_eprom_table_entry {
0186     u32 type;       /* file type */
0187     u32 offset;     /* file offset from start of EPROM */
0188     u32 size;       /* file size, in bytes */
0189 };
0190 
0191 /*
0192  * Calculate the max number of table entries that will fit within a directory
0193  * buffer of size 'dir_size'.
0194  */
0195 #define MAX_TABLE_ENTRIES(dir_size) \
0196     (((dir_size) - sizeof(struct hfi1_eprom_footer)) / \
0197         sizeof(struct hfi1_eprom_table_entry))
0198 
0199 #define DIRECTORY_SIZE(n) (sizeof(struct hfi1_eprom_footer) + \
0200     (sizeof(struct hfi1_eprom_table_entry) * (n)))
0201 
0202 #define MAGIC4(a, b, c, d) ((d) << 24 | (c) << 16 | (b) << 8 | (a))
0203 #define FOOTER_MAGIC MAGIC4('e', 'p', 'r', 'm')
0204 #define FOOTER_VERSION 1
0205 
0206 /*
0207  * Read all of partition 1.  The actual file is at the front.  Adjust
0208  * the returned size if a trailing image magic is found.
0209  */
0210 static int read_partition_platform_config(struct hfi1_devdata *dd, void **data,
0211                       u32 *size)
0212 {
0213     void *buffer;
0214     void *p;
0215     u32 length;
0216     int ret;
0217 
0218     buffer = kmalloc(P1_SIZE, GFP_KERNEL);
0219     if (!buffer)
0220         return -ENOMEM;
0221 
0222     ret = read_length(dd, P1_START, P1_SIZE, buffer);
0223     if (ret) {
0224         kfree(buffer);
0225         return ret;
0226     }
0227 
0228     /* config partition is valid only if it starts with IMAGE_START_MAGIC */
0229     if (memcmp(buffer, IMAGE_START_MAGIC, strlen(IMAGE_START_MAGIC))) {
0230         kfree(buffer);
0231         return -ENOENT;
0232     }
0233 
0234     /* scan for image magic that may trail the actual data */
0235     p = strnstr(buffer, IMAGE_TRAIL_MAGIC, P1_SIZE);
0236     if (p)
0237         length = p - buffer;
0238     else
0239         length = P1_SIZE;
0240 
0241     *data = buffer;
0242     *size = length;
0243     return 0;
0244 }
0245 
0246 /*
0247  * The segment magic has been checked.  There is a footer and table of
0248  * contents present.
0249  *
0250  * directory is a u32 aligned buffer of size EP_PAGE_SIZE.
0251  */
0252 static int read_segment_platform_config(struct hfi1_devdata *dd,
0253                     void *directory, void **data, u32 *size)
0254 {
0255     struct hfi1_eprom_footer *footer;
0256     struct hfi1_eprom_table_entry *table;
0257     struct hfi1_eprom_table_entry *entry;
0258     void *buffer = NULL;
0259     void *table_buffer = NULL;
0260     int ret, i;
0261     u32 directory_size;
0262     u32 seg_base, seg_offset;
0263     u32 bytes_available, ncopied, to_copy;
0264 
0265     /* the footer is at the end of the directory */
0266     footer = (struct hfi1_eprom_footer *)
0267             (directory + EP_PAGE_SIZE - sizeof(*footer));
0268 
0269     /* make sure the structure version is supported */
0270     if (footer->version != FOOTER_VERSION)
0271         return -EINVAL;
0272 
0273     /* oprom size cannot be larger than a segment */
0274     if (footer->oprom_size >= SEG_SIZE)
0275         return -EINVAL;
0276 
0277     /* the file table must fit in a segment with the oprom */
0278     if (footer->num_table_entries >
0279             MAX_TABLE_ENTRIES(SEG_SIZE - footer->oprom_size))
0280         return -EINVAL;
0281 
0282     /* find the file table start, which precedes the footer */
0283     directory_size = DIRECTORY_SIZE(footer->num_table_entries);
0284     if (directory_size <= EP_PAGE_SIZE) {
0285         /* the file table fits into the directory buffer handed in */
0286         table = (struct hfi1_eprom_table_entry *)
0287                 (directory + EP_PAGE_SIZE - directory_size);
0288     } else {
0289         /* need to allocate and read more */
0290         table_buffer = kmalloc(directory_size, GFP_KERNEL);
0291         if (!table_buffer)
0292             return -ENOMEM;
0293         ret = read_length(dd, SEG_SIZE - directory_size,
0294                   directory_size, table_buffer);
0295         if (ret)
0296             goto done;
0297         table = table_buffer;
0298     }
0299 
0300     /* look for the platform configuration file in the table */
0301     for (entry = NULL, i = 0; i < footer->num_table_entries; i++) {
0302         if (table[i].type == HFI1_EFT_PLATFORM_CONFIG) {
0303             entry = &table[i];
0304             break;
0305         }
0306     }
0307     if (!entry) {
0308         ret = -ENOENT;
0309         goto done;
0310     }
0311 
0312     /*
0313      * Sanity check on the configuration file size - it should never
0314      * be larger than 4 KiB.
0315      */
0316     if (entry->size > (4 * 1024)) {
0317         dd_dev_err(dd, "Bad configuration file size 0x%x\n",
0318                entry->size);
0319         ret = -EINVAL;
0320         goto done;
0321     }
0322 
0323     /* check for bogus offset and size that wrap when added together */
0324     if (entry->offset + entry->size < entry->offset) {
0325         dd_dev_err(dd,
0326                "Bad configuration file start + size 0x%x+0x%x\n",
0327                entry->offset, entry->size);
0328         ret = -EINVAL;
0329         goto done;
0330     }
0331 
0332     /* allocate the buffer to return */
0333     buffer = kmalloc(entry->size, GFP_KERNEL);
0334     if (!buffer) {
0335         ret = -ENOMEM;
0336         goto done;
0337     }
0338 
0339     /*
0340      * Extract the file by looping over segments until it is fully read.
0341      */
0342     seg_offset = entry->offset % SEG_SIZE;
0343     seg_base = entry->offset - seg_offset;
0344     ncopied = 0;
0345     while (ncopied < entry->size) {
0346         /* calculate data bytes available in this segment */
0347 
0348         /* start with the bytes from the current offset to the end */
0349         bytes_available = SEG_SIZE - seg_offset;
0350         /* subtract off footer and table from segment 0 */
0351         if (seg_base == 0) {
0352             /*
0353              * Sanity check: should not have a starting point
0354              * at or within the directory.
0355              */
0356             if (bytes_available <= directory_size) {
0357                 dd_dev_err(dd,
0358                        "Bad configuration file - offset 0x%x within footer+table\n",
0359                        entry->offset);
0360                 ret = -EINVAL;
0361                 goto done;
0362             }
0363             bytes_available -= directory_size;
0364         }
0365 
0366         /* calculate bytes wanted */
0367         to_copy = entry->size - ncopied;
0368 
0369         /* max out at the available bytes in this segment */
0370         if (to_copy > bytes_available)
0371             to_copy = bytes_available;
0372 
0373         /*
0374          * Read from the EPROM.
0375          *
0376          * The sanity check for entry->offset is done in read_length().
0377          * The EPROM offset is validated against what the hardware
0378          * addressing supports.  In addition, if the offset is larger
0379          * than the actual EPROM, it silently wraps.  It will work
0380          * fine, though the reader may not get what they expected
0381          * from the EPROM.
0382          */
0383         ret = read_length(dd, seg_base + seg_offset, to_copy,
0384                   buffer + ncopied);
0385         if (ret)
0386             goto done;
0387 
0388         ncopied += to_copy;
0389 
0390         /* set up for next segment */
0391         seg_offset = footer->oprom_size;
0392         seg_base += SEG_SIZE;
0393     }
0394 
0395     /* success */
0396     ret = 0;
0397     *data = buffer;
0398     *size = entry->size;
0399 
0400 done:
0401     kfree(table_buffer);
0402     if (ret)
0403         kfree(buffer);
0404     return ret;
0405 }
0406 
0407 /*
0408  * Read the platform configuration file from the EPROM.
0409  *
0410  * On success, an allocated buffer containing the data and its size are
0411  * returned.  It is up to the caller to free this buffer.
0412  *
0413  * Return value:
0414  *   0        - success
0415  *   -ENXIO   - no EPROM is available
0416  *   -EBUSY   - not able to acquire access to the EPROM
0417  *   -ENOENT  - no recognizable file written
0418  *   -ENOMEM  - buffer could not be allocated
0419  *   -EINVAL  - invalid EPROM contentents found
0420  */
0421 int eprom_read_platform_config(struct hfi1_devdata *dd, void **data, u32 *size)
0422 {
0423     u32 directory[EP_PAGE_DWORDS]; /* aligned buffer */
0424     int ret;
0425 
0426     if (!dd->eprom_available)
0427         return -ENXIO;
0428 
0429     ret = acquire_chip_resource(dd, CR_EPROM, EPROM_TIMEOUT);
0430     if (ret)
0431         return -EBUSY;
0432 
0433     /* read the last page of the segment for the EPROM format magic */
0434     ret = read_length(dd, SEG_SIZE - EP_PAGE_SIZE, EP_PAGE_SIZE, directory);
0435     if (ret)
0436         goto done;
0437 
0438     /* last dword of the segment contains a magic value */
0439     if (directory[EP_PAGE_DWORDS - 1] == FOOTER_MAGIC) {
0440         /* segment format */
0441         ret = read_segment_platform_config(dd, directory, data, size);
0442     } else {
0443         /* partition format */
0444         ret = read_partition_platform_config(dd, data, size);
0445     }
0446 
0447 done:
0448     release_chip_resource(dd, CR_EPROM);
0449     return ret;
0450 }