Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is provided under a dual BSD/GPLv2 license.  When using or
0003  * redistributing this file, you may do so under either license.
0004  *
0005  * GPL LICENSE SUMMARY
0006  *
0007  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
0008  *
0009  * This program is free software; you can redistribute it and/or modify
0010  * it under the terms of version 2 of the GNU General Public License as
0011  * published by the Free Software Foundation.
0012  *
0013  * This program is distributed in the hope that it will be useful, but
0014  * WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  * General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU General Public License
0019  * along with this program; if not, write to the Free Software
0020  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
0021  * The full GNU General Public License is included in this distribution
0022  * in the file called LICENSE.GPL.
0023  */
0024 
0025 /* probe_roms - scan for oem parameters */
0026 
0027 #include <linux/kernel.h>
0028 #include <linux/firmware.h>
0029 #include <linux/uaccess.h>
0030 #include <linux/efi.h>
0031 #include <asm/probe_roms.h>
0032 
0033 #include "isci.h"
0034 #include "task.h"
0035 #include "probe_roms.h"
0036 
0037 static efi_char16_t isci_efivar_name[] = {
0038     'R', 's', 't', 'S', 'c', 'u', 'O'
0039 };
0040 
0041 struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
0042 {
0043     void __iomem *oprom = pci_map_biosrom(pdev);
0044     struct isci_orom *rom = NULL;
0045     size_t len, i;
0046     int j;
0047     char oem_sig[4];
0048     struct isci_oem_hdr oem_hdr;
0049     u8 *tmp, sum;
0050 
0051     if (!oprom)
0052         return NULL;
0053 
0054     len = pci_biosrom_size(pdev);
0055     rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL);
0056     if (!rom) {
0057         pci_unmap_biosrom(oprom);
0058         dev_warn(&pdev->dev,
0059              "Unable to allocate memory for orom\n");
0060         return NULL;
0061     }
0062 
0063     for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) {
0064         memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE);
0065 
0066         /* we think we found the OEM table */
0067         if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) {
0068             size_t copy_len;
0069 
0070             memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr));
0071 
0072             copy_len = min(oem_hdr.len - sizeof(oem_hdr),
0073                        sizeof(*rom));
0074 
0075             memcpy_fromio(rom,
0076                       oprom + i + sizeof(oem_hdr),
0077                       copy_len);
0078 
0079             /* calculate checksum */
0080             tmp = (u8 *)&oem_hdr;
0081             for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++)
0082                 sum += *tmp;
0083 
0084             tmp = (u8 *)rom;
0085             for (j = 0; j < sizeof(*rom); j++, tmp++)
0086                 sum += *tmp;
0087 
0088             if (sum != 0) {
0089                 dev_warn(&pdev->dev,
0090                      "OEM table checksum failed\n");
0091                 continue;
0092             }
0093 
0094             /* keep going if that's not the oem param table */
0095             if (memcmp(rom->hdr.signature,
0096                    ISCI_ROM_SIG,
0097                    ISCI_ROM_SIG_SIZE) != 0)
0098                 continue;
0099 
0100             dev_info(&pdev->dev,
0101                  "OEM parameter table found in OROM\n");
0102             break;
0103         }
0104     }
0105 
0106     if (i >= len) {
0107         dev_err(&pdev->dev, "oprom parse error\n");
0108         rom = NULL;
0109     }
0110     pci_unmap_biosrom(oprom);
0111 
0112     return rom;
0113 }
0114 
0115 struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
0116 {
0117     struct isci_orom *orom = NULL, *data;
0118     int i, j;
0119 
0120     if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
0121         return NULL;
0122 
0123     if (fw->size < sizeof(*orom))
0124         goto out;
0125 
0126     data = (struct isci_orom *)fw->data;
0127 
0128     if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
0129             strlen(ISCI_ROM_SIG)) != 0)
0130         goto out;
0131 
0132     orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
0133     if (!orom)
0134         goto out;
0135 
0136     memcpy(orom, fw->data, fw->size);
0137 
0138     if (is_c0(pdev) || is_c1(pdev))
0139         goto out;
0140 
0141     /*
0142      * deprecated: override default amp_control for pre-preproduction
0143      * silicon revisions
0144      */
0145     for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
0146         for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
0147             orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
0148             orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03;
0149             orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03;
0150             orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03;
0151         }
0152  out:
0153     release_firmware(fw);
0154 
0155     return orom;
0156 }
0157 
0158 static struct efi *get_efi(void)
0159 {
0160 #ifdef CONFIG_EFI
0161     return &efi;
0162 #else
0163     return NULL;
0164 #endif
0165 }
0166 
0167 struct isci_orom *isci_get_efi_var(struct pci_dev *pdev)
0168 {
0169     efi_status_t status;
0170     struct isci_orom *rom;
0171     struct isci_oem_hdr *oem_hdr;
0172     u8 *tmp, sum;
0173     int j;
0174     unsigned long data_len;
0175     u8 *efi_data;
0176     u32 efi_attrib = 0;
0177 
0178     data_len = 1024;
0179     efi_data = devm_kzalloc(&pdev->dev, data_len, GFP_KERNEL);
0180     if (!efi_data) {
0181         dev_warn(&pdev->dev,
0182              "Unable to allocate memory for EFI data\n");
0183         return NULL;
0184     }
0185 
0186     rom = (struct isci_orom *)(efi_data + sizeof(struct isci_oem_hdr));
0187 
0188     if (get_efi())
0189         status = get_efi()->get_variable(isci_efivar_name,
0190                          &ISCI_EFI_VENDOR_GUID,
0191                          &efi_attrib,
0192                          &data_len,
0193                          efi_data);
0194     else
0195         status = EFI_NOT_FOUND;
0196 
0197     if (status != EFI_SUCCESS) {
0198         dev_warn(&pdev->dev,
0199              "Unable to obtain EFI var data for OEM parms\n");
0200         return NULL;
0201     }
0202 
0203     oem_hdr = (struct isci_oem_hdr *)efi_data;
0204 
0205     if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) {
0206         dev_warn(&pdev->dev,
0207              "Invalid OEM header signature\n");
0208         return NULL;
0209     }
0210 
0211     /* calculate checksum */
0212     tmp = (u8 *)efi_data;
0213     for (j = 0, sum = 0; j < (sizeof(*oem_hdr) + sizeof(*rom)); j++, tmp++)
0214         sum += *tmp;
0215 
0216     if (sum != 0) {
0217         dev_warn(&pdev->dev,
0218              "OEM table checksum failed\n");
0219         return NULL;
0220     }
0221 
0222     if (memcmp(rom->hdr.signature,
0223            ISCI_ROM_SIG,
0224            ISCI_ROM_SIG_SIZE) != 0) {
0225         dev_warn(&pdev->dev,
0226              "Invalid OEM table signature\n");
0227         return NULL;
0228     }
0229 
0230     return rom;
0231 }