1*718cf2ccSPedro F. Giffuni /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro F. Giffuni * 4088fc971SDavid C Somayajulu * Copyright (c) 2011-2013 Qlogic Corporation 50bc7cf6fSBjoern A. Zeeb * All rights reserved. 60bc7cf6fSBjoern A. Zeeb * 70bc7cf6fSBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without 80bc7cf6fSBjoern A. Zeeb * modification, are permitted provided that the following conditions 90bc7cf6fSBjoern A. Zeeb * are met: 100bc7cf6fSBjoern A. Zeeb * 110bc7cf6fSBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright 120bc7cf6fSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer. 130bc7cf6fSBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright 140bc7cf6fSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the 150bc7cf6fSBjoern A. Zeeb * documentation and/or other materials provided with the distribution. 160bc7cf6fSBjoern A. Zeeb * 170bc7cf6fSBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 180bc7cf6fSBjoern A. Zeeb * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 190bc7cf6fSBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 200bc7cf6fSBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 210bc7cf6fSBjoern A. Zeeb * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 220bc7cf6fSBjoern A. Zeeb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 230bc7cf6fSBjoern A. Zeeb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 240bc7cf6fSBjoern A. Zeeb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 250bc7cf6fSBjoern A. Zeeb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 260bc7cf6fSBjoern A. Zeeb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 270bc7cf6fSBjoern A. Zeeb * POSSIBILITY OF SUCH DAMAGE. 280bc7cf6fSBjoern A. Zeeb */ 290bc7cf6fSBjoern A. Zeeb /* 300bc7cf6fSBjoern A. Zeeb * File : qla_misc.c 310bc7cf6fSBjoern A. Zeeb * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 320bc7cf6fSBjoern A. Zeeb */ 330bc7cf6fSBjoern A. Zeeb 340bc7cf6fSBjoern A. Zeeb #include <sys/cdefs.h> 350bc7cf6fSBjoern A. Zeeb __FBSDID("$FreeBSD$"); 360bc7cf6fSBjoern A. Zeeb 370bc7cf6fSBjoern A. Zeeb #include "qla_os.h" 380bc7cf6fSBjoern A. Zeeb #include "qla_reg.h" 390bc7cf6fSBjoern A. Zeeb #include "qla_hw.h" 400bc7cf6fSBjoern A. Zeeb #include "qla_def.h" 410bc7cf6fSBjoern A. Zeeb #include "qla_reg.h" 420bc7cf6fSBjoern A. Zeeb #include "qla_inline.h" 430bc7cf6fSBjoern A. Zeeb #include "qla_glbl.h" 440bc7cf6fSBjoern A. Zeeb #include "qla_dbg.h" 450bc7cf6fSBjoern A. Zeeb 460bc7cf6fSBjoern A. Zeeb /* 470bc7cf6fSBjoern A. Zeeb * structure encapsulating the value to read/write to offchip memory 480bc7cf6fSBjoern A. Zeeb */ 490bc7cf6fSBjoern A. Zeeb typedef struct _offchip_mem_val { 500bc7cf6fSBjoern A. Zeeb uint32_t data_lo; 510bc7cf6fSBjoern A. Zeeb uint32_t data_hi; 520bc7cf6fSBjoern A. Zeeb uint32_t data_ulo; 530bc7cf6fSBjoern A. Zeeb uint32_t data_uhi; 540bc7cf6fSBjoern A. Zeeb } offchip_mem_val_t; 550bc7cf6fSBjoern A. Zeeb 560bc7cf6fSBjoern A. Zeeb #define Q8_ADDR_UNDEFINED 0xFFFFFFFF 570bc7cf6fSBjoern A. Zeeb 580bc7cf6fSBjoern A. Zeeb /* 590bc7cf6fSBjoern A. Zeeb * The index to this table is Bits 20-27 of the indirect register address 600bc7cf6fSBjoern A. Zeeb */ 610bc7cf6fSBjoern A. Zeeb static uint32_t indirect_to_base_map[] = 620bc7cf6fSBjoern A. Zeeb { 630bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x00 */ 640bc7cf6fSBjoern A. Zeeb 0x77300000, /* 0x01 */ 650bc7cf6fSBjoern A. Zeeb 0x29500000, /* 0x02 */ 660bc7cf6fSBjoern A. Zeeb 0x2A500000, /* 0x03 */ 670bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x04 */ 680bc7cf6fSBjoern A. Zeeb 0x0D000000, /* 0x05 */ 690bc7cf6fSBjoern A. Zeeb 0x1B100000, /* 0x06 */ 700bc7cf6fSBjoern A. Zeeb 0x0E600000, /* 0x07 */ 710bc7cf6fSBjoern A. Zeeb 0x0E000000, /* 0x08 */ 720bc7cf6fSBjoern A. Zeeb 0x0E100000, /* 0x09 */ 730bc7cf6fSBjoern A. Zeeb 0x0E200000, /* 0x0A */ 740bc7cf6fSBjoern A. Zeeb 0x0E300000, /* 0x0B */ 750bc7cf6fSBjoern A. Zeeb 0x42000000, /* 0x0C */ 760bc7cf6fSBjoern A. Zeeb 0x41700000, /* 0x0D */ 770bc7cf6fSBjoern A. Zeeb 0x42100000, /* 0x0E */ 780bc7cf6fSBjoern A. Zeeb 0x34B00000, /* 0x0F */ 790bc7cf6fSBjoern A. Zeeb 0x40500000, /* 0x10 */ 800bc7cf6fSBjoern A. Zeeb 0x34000000, /* 0x11 */ 810bc7cf6fSBjoern A. Zeeb 0x34100000, /* 0x12 */ 820bc7cf6fSBjoern A. Zeeb 0x34200000, /* 0x13 */ 830bc7cf6fSBjoern A. Zeeb 0x34300000, /* 0x14 */ 840bc7cf6fSBjoern A. Zeeb 0x34500000, /* 0x15 */ 850bc7cf6fSBjoern A. Zeeb 0x34400000, /* 0x16 */ 860bc7cf6fSBjoern A. Zeeb 0x3C000000, /* 0x17 */ 870bc7cf6fSBjoern A. Zeeb 0x3C100000, /* 0x18 */ 880bc7cf6fSBjoern A. Zeeb 0x3C200000, /* 0x19 */ 890bc7cf6fSBjoern A. Zeeb 0x3C300000, /* 0x1A */ 900bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x1B */ 910bc7cf6fSBjoern A. Zeeb 0x3C400000, /* 0x1C */ 920bc7cf6fSBjoern A. Zeeb 0x41000000, /* 0x1D */ 930bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x1E */ 940bc7cf6fSBjoern A. Zeeb 0x0D100000, /* 0x1F */ 950bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x20 */ 960bc7cf6fSBjoern A. Zeeb 0x77300000, /* 0x21 */ 970bc7cf6fSBjoern A. Zeeb 0x41600000, /* 0x22 */ 980bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x23 */ 990bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x24 */ 1000bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x25 */ 1010bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x26 */ 1020bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x27 */ 1030bc7cf6fSBjoern A. Zeeb 0x41700000, /* 0x28 */ 1040bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x29 */ 1050bc7cf6fSBjoern A. Zeeb 0x08900000, /* 0x2A */ 1060bc7cf6fSBjoern A. Zeeb 0x70A00000, /* 0x2B */ 1070bc7cf6fSBjoern A. Zeeb 0x70B00000, /* 0x2C */ 1080bc7cf6fSBjoern A. Zeeb 0x70C00000, /* 0x2D */ 1090bc7cf6fSBjoern A. Zeeb 0x08D00000, /* 0x2E */ 1100bc7cf6fSBjoern A. Zeeb 0x08E00000, /* 0x2F */ 1110bc7cf6fSBjoern A. Zeeb 0x70F00000, /* 0x30 */ 1120bc7cf6fSBjoern A. Zeeb 0x40500000, /* 0x31 */ 1130bc7cf6fSBjoern A. Zeeb 0x42000000, /* 0x32 */ 1140bc7cf6fSBjoern A. Zeeb 0x42100000, /* 0x33 */ 1150bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x34 */ 1160bc7cf6fSBjoern A. Zeeb 0x08800000, /* 0x35 */ 1170bc7cf6fSBjoern A. Zeeb 0x09100000, /* 0x36 */ 1180bc7cf6fSBjoern A. Zeeb 0x71200000, /* 0x37 */ 1190bc7cf6fSBjoern A. Zeeb 0x40600000, /* 0x38 */ 1200bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x39 */ 1210bc7cf6fSBjoern A. Zeeb 0x71800000, /* 0x3A */ 1220bc7cf6fSBjoern A. Zeeb 0x19900000, /* 0x3B */ 1230bc7cf6fSBjoern A. Zeeb 0x1A900000, /* 0x3C */ 1240bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x3D */ 1250bc7cf6fSBjoern A. Zeeb 0x34600000, /* 0x3E */ 1260bc7cf6fSBjoern A. Zeeb Q8_ADDR_UNDEFINED, /* 0x3F */ 1270bc7cf6fSBjoern A. Zeeb }; 1280bc7cf6fSBjoern A. Zeeb 1290bc7cf6fSBjoern A. Zeeb /* 1300bc7cf6fSBjoern A. Zeeb * Address Translation Table for CRB to offsets from PCI BAR0 1310bc7cf6fSBjoern A. Zeeb */ 1320bc7cf6fSBjoern A. Zeeb typedef struct _crb_to_pci { 1330bc7cf6fSBjoern A. Zeeb uint32_t crb_addr; 1340bc7cf6fSBjoern A. Zeeb uint32_t pci_addr; 1350bc7cf6fSBjoern A. Zeeb } crb_to_pci_t; 1360bc7cf6fSBjoern A. Zeeb 1370bc7cf6fSBjoern A. Zeeb static crb_to_pci_t crbinit_to_pciaddr[] = { 1380bc7cf6fSBjoern A. Zeeb {(0x088 << 20), (0x035 << 20)}, 1390bc7cf6fSBjoern A. Zeeb {(0x089 << 20), (0x02A << 20)}, 1400bc7cf6fSBjoern A. Zeeb {(0x08D << 20), (0x02E << 20)}, 1410bc7cf6fSBjoern A. Zeeb {(0x08E << 20), (0x02F << 20)}, 1420bc7cf6fSBjoern A. Zeeb {(0x0C6 << 20), (0x023 << 20)}, 1430bc7cf6fSBjoern A. Zeeb {(0x0C7 << 20), (0x024 << 20)}, 1440bc7cf6fSBjoern A. Zeeb {(0x0C8 << 20), (0x025 << 20)}, 1450bc7cf6fSBjoern A. Zeeb {(0x0D0 << 20), (0x005 << 20)}, 1460bc7cf6fSBjoern A. Zeeb {(0x0D1 << 20), (0x01F << 20)}, 1470bc7cf6fSBjoern A. Zeeb {(0x0E0 << 20), (0x008 << 20)}, 1480bc7cf6fSBjoern A. Zeeb {(0x0E1 << 20), (0x009 << 20)}, 1490bc7cf6fSBjoern A. Zeeb {(0x0E2 << 20), (0x00A << 20)}, 1500bc7cf6fSBjoern A. Zeeb {(0x0E3 << 20), (0x00B << 20)}, 1510bc7cf6fSBjoern A. Zeeb {(0x0E6 << 20), (0x007 << 20)}, 1520bc7cf6fSBjoern A. Zeeb {(0x199 << 20), (0x03B << 20)}, 1530bc7cf6fSBjoern A. Zeeb {(0x1B1 << 20), (0x006 << 20)}, 1540bc7cf6fSBjoern A. Zeeb {(0x295 << 20), (0x002 << 20)}, 1550bc7cf6fSBjoern A. Zeeb {(0x29A << 20), (0x000 << 20)}, 1560bc7cf6fSBjoern A. Zeeb {(0x2A5 << 20), (0x003 << 20)}, 1570bc7cf6fSBjoern A. Zeeb {(0x340 << 20), (0x011 << 20)}, 1580bc7cf6fSBjoern A. Zeeb {(0x341 << 20), (0x012 << 20)}, 1590bc7cf6fSBjoern A. Zeeb {(0x342 << 20), (0x013 << 20)}, 1600bc7cf6fSBjoern A. Zeeb {(0x343 << 20), (0x014 << 20)}, 1610bc7cf6fSBjoern A. Zeeb {(0x344 << 20), (0x016 << 20)}, 1620bc7cf6fSBjoern A. Zeeb {(0x345 << 20), (0x015 << 20)}, 1630bc7cf6fSBjoern A. Zeeb {(0x3C0 << 20), (0x017 << 20)}, 1640bc7cf6fSBjoern A. Zeeb {(0x3C1 << 20), (0x018 << 20)}, 1650bc7cf6fSBjoern A. Zeeb {(0x3C2 << 20), (0x019 << 20)}, 1660bc7cf6fSBjoern A. Zeeb {(0x3C3 << 20), (0x01A << 20)}, 1670bc7cf6fSBjoern A. Zeeb {(0x3C4 << 20), (0x01C << 20)}, 1680bc7cf6fSBjoern A. Zeeb {(0x3C5 << 20), (0x01B << 20)}, 1690bc7cf6fSBjoern A. Zeeb {(0x405 << 20), (0x031 << 20)}, 1700bc7cf6fSBjoern A. Zeeb {(0x406 << 20), (0x038 << 20)}, 1710bc7cf6fSBjoern A. Zeeb {(0x410 << 20), (0x01D << 20)}, 1720bc7cf6fSBjoern A. Zeeb {(0x416 << 20), (0x022 << 20)}, 1730bc7cf6fSBjoern A. Zeeb {(0x417 << 20), (0x028 << 20)}, 1740bc7cf6fSBjoern A. Zeeb {(0x420 << 20), (0x032 << 20)}, 1750bc7cf6fSBjoern A. Zeeb {(0x421 << 20), (0x033 << 20)}, 1760bc7cf6fSBjoern A. Zeeb {(0x700 << 20), (0x00C << 20)}, 1770bc7cf6fSBjoern A. Zeeb {(0x701 << 20), (0x00D << 20)}, 1780bc7cf6fSBjoern A. Zeeb {(0x702 << 20), (0x00E << 20)}, 1790bc7cf6fSBjoern A. Zeeb {(0x703 << 20), (0x00F << 20)}, 1800bc7cf6fSBjoern A. Zeeb {(0x704 << 20), (0x010 << 20)}, 1810bc7cf6fSBjoern A. Zeeb {(0x70A << 20), (0x02B << 20)}, 1820bc7cf6fSBjoern A. Zeeb {(0x70B << 20), (0x02C << 20)}, 1830bc7cf6fSBjoern A. Zeeb {(0x70C << 20), (0x02D << 20)}, 1840bc7cf6fSBjoern A. Zeeb {(0x70F << 20), (0x030 << 20)}, 1850bc7cf6fSBjoern A. Zeeb {(0x718 << 20), (0x03A << 20)}, 1860bc7cf6fSBjoern A. Zeeb {(0x758 << 20), (0x026 << 20)}, 1870bc7cf6fSBjoern A. Zeeb {(0x759 << 20), (0x027 << 20)}, 1880bc7cf6fSBjoern A. Zeeb {(0x773 << 20), (0x001 << 20)} 1890bc7cf6fSBjoern A. Zeeb }; 1900bc7cf6fSBjoern A. Zeeb 1910bc7cf6fSBjoern A. Zeeb #define Q8_INVALID_ADDRESS (-1) 1920bc7cf6fSBjoern A. Zeeb #define Q8_ADDR_MASK (0xFFF << 20) 1930bc7cf6fSBjoern A. Zeeb 1940bc7cf6fSBjoern A. Zeeb typedef struct _addr_val { 1950bc7cf6fSBjoern A. Zeeb uint32_t addr; 1960bc7cf6fSBjoern A. Zeeb uint32_t value; 1970bc7cf6fSBjoern A. Zeeb uint32_t pci_addr; 1980bc7cf6fSBjoern A. Zeeb uint32_t ind_addr; 1990bc7cf6fSBjoern A. Zeeb } addr_val_t; 2000bc7cf6fSBjoern A. Zeeb 2010bc7cf6fSBjoern A. Zeeb /* 2020bc7cf6fSBjoern A. Zeeb * Name: qla_rdwr_indreg32 2030bc7cf6fSBjoern A. Zeeb * Function: Read/Write an Indirect Register 2040bc7cf6fSBjoern A. Zeeb */ 2050bc7cf6fSBjoern A. Zeeb int 2060bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd) 2070bc7cf6fSBjoern A. Zeeb { 2080bc7cf6fSBjoern A. Zeeb uint32_t offset; 2090bc7cf6fSBjoern A. Zeeb int count = 100; 2100bc7cf6fSBjoern A. Zeeb 2110bc7cf6fSBjoern A. Zeeb offset = (addr & 0xFFF00000) >> 20; 2120bc7cf6fSBjoern A. Zeeb 2130bc7cf6fSBjoern A. Zeeb if (offset > 0x3F) { 2140bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n", 2150bc7cf6fSBjoern A. Zeeb __func__, addr); 2160bc7cf6fSBjoern A. Zeeb return -1; 2170bc7cf6fSBjoern A. Zeeb } 2180bc7cf6fSBjoern A. Zeeb 2190bc7cf6fSBjoern A. Zeeb offset = indirect_to_base_map[offset]; 2200bc7cf6fSBjoern A. Zeeb if (offset == Q8_ADDR_UNDEFINED) { 2210bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n", 2220bc7cf6fSBjoern A. Zeeb __func__, addr); 2230bc7cf6fSBjoern A. Zeeb return -1; 2240bc7cf6fSBjoern A. Zeeb } 2250bc7cf6fSBjoern A. Zeeb 2260bc7cf6fSBjoern A. Zeeb offset = offset | (addr & 0x000F0000); 2270bc7cf6fSBjoern A. Zeeb 2280bc7cf6fSBjoern A. Zeeb if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) { 2290bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__); 2300bc7cf6fSBjoern A. Zeeb return (-1); 2310bc7cf6fSBjoern A. Zeeb } 2320bc7cf6fSBjoern A. Zeeb 2330bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset); 2340bc7cf6fSBjoern A. Zeeb 2350bc7cf6fSBjoern A. Zeeb while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) { 2360bc7cf6fSBjoern A. Zeeb count--; 2370bc7cf6fSBjoern A. Zeeb if (!count) { 2380bc7cf6fSBjoern A. Zeeb qla_sem_unlock(ha, Q8_SEM7_UNLOCK); 2390bc7cf6fSBjoern A. Zeeb return -1; 2400bc7cf6fSBjoern A. Zeeb } 2410bc7cf6fSBjoern A. Zeeb 2420bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 1); 2430bc7cf6fSBjoern A. Zeeb } 2440bc7cf6fSBjoern A. Zeeb 2450bc7cf6fSBjoern A. Zeeb if (rd) { 2460bc7cf6fSBjoern A. Zeeb *val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000)); 2470bc7cf6fSBjoern A. Zeeb } else { 2480bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val); 2490bc7cf6fSBjoern A. Zeeb } 2500bc7cf6fSBjoern A. Zeeb 2510bc7cf6fSBjoern A. Zeeb qla_sem_unlock(ha, Q8_SEM7_UNLOCK); 2520bc7cf6fSBjoern A. Zeeb return 0; 2530bc7cf6fSBjoern A. Zeeb } 2540bc7cf6fSBjoern A. Zeeb 2550bc7cf6fSBjoern A. Zeeb /* 2560bc7cf6fSBjoern A. Zeeb * Name: qla_rdwr_offchip_mem 2570bc7cf6fSBjoern A. Zeeb * Function: Read/Write OffChip Memory 2580bc7cf6fSBjoern A. Zeeb */ 2590bc7cf6fSBjoern A. Zeeb static int 2600bc7cf6fSBjoern A. Zeeb qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val, 2610bc7cf6fSBjoern A. Zeeb uint32_t rd) 2620bc7cf6fSBjoern A. Zeeb { 2630bc7cf6fSBjoern A. Zeeb uint32_t count = 100; 2640bc7cf6fSBjoern A. Zeeb uint32_t data; 2650bc7cf6fSBjoern A. Zeeb 2660bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr); 2670bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32)); 2680bc7cf6fSBjoern A. Zeeb 2690bc7cf6fSBjoern A. Zeeb if (!rd) { 2700bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo); 2710bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi); 2720bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo); 2730bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi); 2740bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */ 2750bc7cf6fSBjoern A. Zeeb } else { 2760bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */ 2770bc7cf6fSBjoern A. Zeeb } 2780bc7cf6fSBjoern A. Zeeb 2790bc7cf6fSBjoern A. Zeeb while (count--) { 2800bc7cf6fSBjoern A. Zeeb data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL); 2810bc7cf6fSBjoern A. Zeeb if (!(data & BIT_3)) { 2820bc7cf6fSBjoern A. Zeeb if (rd) { 2830bc7cf6fSBjoern A. Zeeb val->data_lo = READ_OFFSET32(ha, \ 2840bc7cf6fSBjoern A. Zeeb Q8_MIU_TEST_AGT_RDDATA_LO); 2850bc7cf6fSBjoern A. Zeeb val->data_hi = READ_OFFSET32(ha, \ 2860bc7cf6fSBjoern A. Zeeb Q8_MIU_TEST_AGT_RDDATA_HI); 2870bc7cf6fSBjoern A. Zeeb val->data_ulo = READ_OFFSET32(ha, \ 2880bc7cf6fSBjoern A. Zeeb Q8_MIU_TEST_AGT_RDDATA_ULO); 2890bc7cf6fSBjoern A. Zeeb val->data_uhi = READ_OFFSET32(ha, \ 2900bc7cf6fSBjoern A. Zeeb Q8_MIU_TEST_AGT_RDDATA_UHI); 2910bc7cf6fSBjoern A. Zeeb } 2920bc7cf6fSBjoern A. Zeeb return 0; 2930bc7cf6fSBjoern A. Zeeb } else 2940bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 1); 2950bc7cf6fSBjoern A. Zeeb } 2960bc7cf6fSBjoern A. Zeeb 2970bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data); 2980bc7cf6fSBjoern A. Zeeb return (-1); 2990bc7cf6fSBjoern A. Zeeb } 3000bc7cf6fSBjoern A. Zeeb 3010bc7cf6fSBjoern A. Zeeb /* 3020bc7cf6fSBjoern A. Zeeb * Name: qla_rd_flash32 3030bc7cf6fSBjoern A. Zeeb * Function: Read Flash Memory 3040bc7cf6fSBjoern A. Zeeb */ 3050bc7cf6fSBjoern A. Zeeb int 3060bc7cf6fSBjoern A. Zeeb qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data) 3070bc7cf6fSBjoern A. Zeeb { 3080bc7cf6fSBjoern A. Zeeb uint32_t val; 3090bc7cf6fSBjoern A. Zeeb uint32_t count = 100; 3100bc7cf6fSBjoern A. Zeeb 3110bc7cf6fSBjoern A. Zeeb if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) { 3120bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__); 3130bc7cf6fSBjoern A. Zeeb return (-1); 3140bc7cf6fSBjoern A. Zeeb } 3150bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5); 3160bc7cf6fSBjoern A. Zeeb 3170bc7cf6fSBjoern A. Zeeb val = addr; 3180bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0); 3190bc7cf6fSBjoern A. Zeeb val = 0; 3200bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0); 3210bc7cf6fSBjoern A. Zeeb val = 3; 3220bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 3230bc7cf6fSBjoern A. Zeeb 3240bc7cf6fSBjoern A. Zeeb QLA_USEC_DELAY(100); 3250bc7cf6fSBjoern A. Zeeb 3260bc7cf6fSBjoern A. Zeeb val = ROM_OPCODE_FAST_RD; 3270bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 3280bc7cf6fSBjoern A. Zeeb 3290bc7cf6fSBjoern A. Zeeb while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) { 3300bc7cf6fSBjoern A. Zeeb count--; 3310bc7cf6fSBjoern A. Zeeb if (!count) { 3320bc7cf6fSBjoern A. Zeeb qla_sem_unlock(ha, Q8_SEM7_UNLOCK); 3330bc7cf6fSBjoern A. Zeeb return -1; 3340bc7cf6fSBjoern A. Zeeb } 3350bc7cf6fSBjoern A. Zeeb } 3360bc7cf6fSBjoern A. Zeeb 3370bc7cf6fSBjoern A. Zeeb val = 0; 3380bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0); 3390bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 3400bc7cf6fSBjoern A. Zeeb 3410bc7cf6fSBjoern A. Zeeb QLA_USEC_DELAY(100); 3420bc7cf6fSBjoern A. Zeeb 3430bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1); 3440bc7cf6fSBjoern A. Zeeb 3450bc7cf6fSBjoern A. Zeeb qla_sem_unlock(ha, Q8_SEM2_UNLOCK); 3460bc7cf6fSBjoern A. Zeeb return 0; 3470bc7cf6fSBjoern A. Zeeb } 3480bc7cf6fSBjoern A. Zeeb 349088fc971SDavid C Somayajulu static int 350088fc971SDavid C Somayajulu qla_p3p_sem_lock2(qla_host_t *ha) 351088fc971SDavid C Somayajulu { 352088fc971SDavid C Somayajulu if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) { 353088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__); 354088fc971SDavid C Somayajulu return (-1); 355088fc971SDavid C Somayajulu } 356088fc971SDavid C Somayajulu WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5); 357088fc971SDavid C Somayajulu return (0); 358088fc971SDavid C Somayajulu } 359088fc971SDavid C Somayajulu 3600bc7cf6fSBjoern A. Zeeb /* 3610bc7cf6fSBjoern A. Zeeb * Name: qla_int_to_pci_addr_map 3620bc7cf6fSBjoern A. Zeeb * Function: Convert's Internal(CRB) Address to Indirect Address 3630bc7cf6fSBjoern A. Zeeb */ 3640bc7cf6fSBjoern A. Zeeb static uint32_t 3650bc7cf6fSBjoern A. Zeeb qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr) 3660bc7cf6fSBjoern A. Zeeb { 3670bc7cf6fSBjoern A. Zeeb uint32_t crb_to_pci_table_size, i; 3680bc7cf6fSBjoern A. Zeeb uint32_t addr; 3690bc7cf6fSBjoern A. Zeeb 3700bc7cf6fSBjoern A. Zeeb crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t); 3710bc7cf6fSBjoern A. Zeeb addr = int_addr & Q8_ADDR_MASK; 3720bc7cf6fSBjoern A. Zeeb 3730bc7cf6fSBjoern A. Zeeb for (i = 0; i < crb_to_pci_table_size; i++) { 3740bc7cf6fSBjoern A. Zeeb if (crbinit_to_pciaddr[i].crb_addr == addr) { 3750bc7cf6fSBjoern A. Zeeb addr = (int_addr & ~Q8_ADDR_MASK) | 3760bc7cf6fSBjoern A. Zeeb crbinit_to_pciaddr[i].pci_addr; 3770bc7cf6fSBjoern A. Zeeb return (addr); 3780bc7cf6fSBjoern A. Zeeb } 3790bc7cf6fSBjoern A. Zeeb } 3800bc7cf6fSBjoern A. Zeeb return (Q8_INVALID_ADDRESS); 3810bc7cf6fSBjoern A. Zeeb } 3820bc7cf6fSBjoern A. Zeeb 3830bc7cf6fSBjoern A. Zeeb /* 3840bc7cf6fSBjoern A. Zeeb * Name: qla_filter_pci_addr 3850bc7cf6fSBjoern A. Zeeb * Function: Filter's out Indirect Addresses which are not writeable 3860bc7cf6fSBjoern A. Zeeb */ 3870bc7cf6fSBjoern A. Zeeb static uint32_t 3880bc7cf6fSBjoern A. Zeeb qla_filter_pci_addr(qla_host_t *ha, uint32_t addr) 3890bc7cf6fSBjoern A. Zeeb { 3900bc7cf6fSBjoern A. Zeeb if ((addr == Q8_INVALID_ADDRESS) || 3910bc7cf6fSBjoern A. Zeeb (addr == 0x00112040) || 3920bc7cf6fSBjoern A. Zeeb (addr == 0x00112048) || 3930bc7cf6fSBjoern A. Zeeb ((addr & 0xFFFF0FFF) == 0x001100C4) || 3940bc7cf6fSBjoern A. Zeeb ((addr & 0xFFFF0FFF) == 0x001100C8) || 3950bc7cf6fSBjoern A. Zeeb ((addr & 0x0FF00000) == 0x00200000) || 3960bc7cf6fSBjoern A. Zeeb (addr == 0x022021FC) || 3970bc7cf6fSBjoern A. Zeeb (addr == 0x0330001C) || 3980bc7cf6fSBjoern A. Zeeb (addr == 0x03300024) || 3990bc7cf6fSBjoern A. Zeeb (addr == 0x033000A8) || 4000bc7cf6fSBjoern A. Zeeb (addr == 0x033000C8) || 4010bc7cf6fSBjoern A. Zeeb (addr == 0x033000BC) || 4020bc7cf6fSBjoern A. Zeeb ((addr & 0x0FF00000) == 0x03A00000) || 4030bc7cf6fSBjoern A. Zeeb (addr == 0x03B0001C)) 4040bc7cf6fSBjoern A. Zeeb return (Q8_INVALID_ADDRESS); 4050bc7cf6fSBjoern A. Zeeb else 4060bc7cf6fSBjoern A. Zeeb return (addr); 4070bc7cf6fSBjoern A. Zeeb } 4080bc7cf6fSBjoern A. Zeeb 4090bc7cf6fSBjoern A. Zeeb /* 4100bc7cf6fSBjoern A. Zeeb * Name: qla_crb_init 4110bc7cf6fSBjoern A. Zeeb * Function: CRB Initialization - first step in the initialization after reset 4120bc7cf6fSBjoern A. Zeeb * Essentially reads the address/value pairs from address = 0x00 and 4130bc7cf6fSBjoern A. Zeeb * writes the value into address in the addr/value pair. 4140bc7cf6fSBjoern A. Zeeb */ 4150bc7cf6fSBjoern A. Zeeb static int 4160bc7cf6fSBjoern A. Zeeb qla_crb_init(qla_host_t *ha) 4170bc7cf6fSBjoern A. Zeeb { 418088fc971SDavid C Somayajulu uint32_t val = 0, sig = 0; 4190bc7cf6fSBjoern A. Zeeb uint32_t offset, count, i; 4200bc7cf6fSBjoern A. Zeeb addr_val_t *addr_val_map, *avmap; 4210bc7cf6fSBjoern A. Zeeb 4220bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, 0, &sig); 4237c864d7dSDimitry Andric QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig)); 4240bc7cf6fSBjoern A. Zeeb 4250bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, 4, &val); 4260bc7cf6fSBjoern A. Zeeb QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val)); 4270bc7cf6fSBjoern A. Zeeb 4280bc7cf6fSBjoern A. Zeeb count = val >> 16; 4290bc7cf6fSBjoern A. Zeeb offset = val & 0xFFFF; 4300bc7cf6fSBjoern A. Zeeb offset = offset << 2; 4310bc7cf6fSBjoern A. Zeeb 4320bc7cf6fSBjoern A. Zeeb QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n", 4330bc7cf6fSBjoern A. Zeeb __func__, sig, val, count)); 4340bc7cf6fSBjoern A. Zeeb 4350bc7cf6fSBjoern A. Zeeb addr_val_map = avmap = malloc((sizeof(addr_val_t) * count), 4360bc7cf6fSBjoern A. Zeeb M_QLA8XXXBUF, M_NOWAIT); 4370bc7cf6fSBjoern A. Zeeb 4380bc7cf6fSBjoern A. Zeeb if (addr_val_map == NULL) { 4390bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, "%s: malloc failed\n", __func__); 4400bc7cf6fSBjoern A. Zeeb return (-1); 4410bc7cf6fSBjoern A. Zeeb } 4420bc7cf6fSBjoern A. Zeeb memset(avmap, 0, (sizeof(addr_val_t) * count)); 4430bc7cf6fSBjoern A. Zeeb 4440bc7cf6fSBjoern A. Zeeb count = count << 1; 4450bc7cf6fSBjoern A. Zeeb for (i = 0; i < count; ) { 4460bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value); 4470bc7cf6fSBjoern A. Zeeb i++; 4480bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr); 4490bc7cf6fSBjoern A. Zeeb i++; 4500bc7cf6fSBjoern A. Zeeb 4510bc7cf6fSBjoern A. Zeeb avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr); 4520bc7cf6fSBjoern A. Zeeb avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr); 4530bc7cf6fSBjoern A. Zeeb 4540bc7cf6fSBjoern A. Zeeb QL_DPRINT2((ha->pci_dev, 4550bc7cf6fSBjoern A. Zeeb "%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n", 4560bc7cf6fSBjoern A. Zeeb __func__, (i >> 1), avmap->addr, avmap->pci_addr, 4570bc7cf6fSBjoern A. Zeeb avmap->ind_addr, avmap->value)); 4580bc7cf6fSBjoern A. Zeeb 4590bc7cf6fSBjoern A. Zeeb if (avmap->ind_addr != Q8_INVALID_ADDRESS) { 4600bc7cf6fSBjoern A. Zeeb qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0); 4610bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 1); 4620bc7cf6fSBjoern A. Zeeb } 4630bc7cf6fSBjoern A. Zeeb avmap++; 4640bc7cf6fSBjoern A. Zeeb } 4650bc7cf6fSBjoern A. Zeeb 4660bc7cf6fSBjoern A. Zeeb free (addr_val_map, M_QLA8XXXBUF); 4670bc7cf6fSBjoern A. Zeeb return (0); 4680bc7cf6fSBjoern A. Zeeb } 4690bc7cf6fSBjoern A. Zeeb 4700bc7cf6fSBjoern A. Zeeb /* 4710bc7cf6fSBjoern A. Zeeb * Name: qla_init_peg_regs 4720bc7cf6fSBjoern A. Zeeb * Function: Protocol Engine Register Initialization 4730bc7cf6fSBjoern A. Zeeb */ 4740bc7cf6fSBjoern A. Zeeb static void 4750bc7cf6fSBjoern A. Zeeb qla_init_peg_regs(qla_host_t *ha) 4760bc7cf6fSBjoern A. Zeeb { 4770bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E); 4780bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008); 4790bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008); 4800bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000); 4810bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000); 4820bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000); 4830bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000); 4840bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000); 4850bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000); 4860bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000); 4870bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000); 4880bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000); 4890bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000); 4900bc7cf6fSBjoern A. Zeeb } 4910bc7cf6fSBjoern A. Zeeb 4920bc7cf6fSBjoern A. Zeeb /* 4930bc7cf6fSBjoern A. Zeeb * Name: qla_load_fw_from_flash 4940bc7cf6fSBjoern A. Zeeb * Function: Reads the Bootloader from Flash and Loads into Offchip Memory 4950bc7cf6fSBjoern A. Zeeb */ 4960bc7cf6fSBjoern A. Zeeb static void 4970bc7cf6fSBjoern A. Zeeb qla_load_fw_from_flash(qla_host_t *ha) 4980bc7cf6fSBjoern A. Zeeb { 4990bc7cf6fSBjoern A. Zeeb uint64_t mem_off = 0x10000; 5000bc7cf6fSBjoern A. Zeeb uint32_t flash_off = 0x10000; 5010bc7cf6fSBjoern A. Zeeb uint32_t count; 5020bc7cf6fSBjoern A. Zeeb offchip_mem_val_t val; 5030bc7cf6fSBjoern A. Zeeb 5040bc7cf6fSBjoern A. Zeeb 5050bc7cf6fSBjoern A. Zeeb /* only bootloader needs to be loaded into memory */ 5060bc7cf6fSBjoern A. Zeeb for (count = 0; count < 0x20000 ; ) { 5070bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, flash_off, &val.data_lo); 5080bc7cf6fSBjoern A. Zeeb count = count + 4; 5090bc7cf6fSBjoern A. Zeeb flash_off = flash_off + 4; 5100bc7cf6fSBjoern A. Zeeb 5110bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, flash_off, &val.data_hi); 5120bc7cf6fSBjoern A. Zeeb count = count + 4; 5130bc7cf6fSBjoern A. Zeeb flash_off = flash_off + 4; 5140bc7cf6fSBjoern A. Zeeb 5150bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, flash_off, &val.data_ulo); 5160bc7cf6fSBjoern A. Zeeb count = count + 4; 5170bc7cf6fSBjoern A. Zeeb flash_off = flash_off + 4; 5180bc7cf6fSBjoern A. Zeeb 5190bc7cf6fSBjoern A. Zeeb qla_rd_flash32(ha, flash_off, &val.data_uhi); 5200bc7cf6fSBjoern A. Zeeb count = count + 4; 5210bc7cf6fSBjoern A. Zeeb flash_off = flash_off + 4; 5220bc7cf6fSBjoern A. Zeeb 5230bc7cf6fSBjoern A. Zeeb qla_rdwr_offchip_mem(ha, mem_off, &val, 0); 5240bc7cf6fSBjoern A. Zeeb 5250bc7cf6fSBjoern A. Zeeb mem_off = mem_off + 16; 5260bc7cf6fSBjoern A. Zeeb } 5270bc7cf6fSBjoern A. Zeeb return; 5280bc7cf6fSBjoern A. Zeeb } 5290bc7cf6fSBjoern A. Zeeb 5300bc7cf6fSBjoern A. Zeeb /* 5310bc7cf6fSBjoern A. Zeeb * Name: qla_init_from_flash 5320bc7cf6fSBjoern A. Zeeb * Function: Performs Initialization which consists of the following sequence 5330bc7cf6fSBjoern A. Zeeb * - reset 5340bc7cf6fSBjoern A. Zeeb * - CRB Init 5350bc7cf6fSBjoern A. Zeeb * - Peg Init 5360bc7cf6fSBjoern A. Zeeb * - Read the Bootloader from Flash and Load into Offchip Memory 5370bc7cf6fSBjoern A. Zeeb * - Kick start the bootloader which loads the rest of the firmware 5380bc7cf6fSBjoern A. Zeeb * and performs the remaining steps in the initialization process. 5390bc7cf6fSBjoern A. Zeeb */ 5400bc7cf6fSBjoern A. Zeeb static int 5410bc7cf6fSBjoern A. Zeeb qla_init_from_flash(qla_host_t *ha) 5420bc7cf6fSBjoern A. Zeeb { 5430bc7cf6fSBjoern A. Zeeb uint32_t delay = 300; 5440bc7cf6fSBjoern A. Zeeb uint32_t data; 5450bc7cf6fSBjoern A. Zeeb 5460bc7cf6fSBjoern A. Zeeb qla_hw_reset(ha); 5470bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 5480bc7cf6fSBjoern A. Zeeb 5490bc7cf6fSBjoern A. Zeeb qla_crb_init(ha); 5500bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 10); 5510bc7cf6fSBjoern A. Zeeb 5520bc7cf6fSBjoern A. Zeeb qla_init_peg_regs(ha); 5530bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 10); 5540bc7cf6fSBjoern A. Zeeb 5550bc7cf6fSBjoern A. Zeeb qla_load_fw_from_flash(ha); 5560bc7cf6fSBjoern A. Zeeb 5570bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000); 5580bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020); 5590bc7cf6fSBjoern A. Zeeb WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E); 5600bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 5610bc7cf6fSBjoern A. Zeeb 5620bc7cf6fSBjoern A. Zeeb do { 5630bc7cf6fSBjoern A. Zeeb data = READ_OFFSET32(ha, Q8_CMDPEG_STATE); 5640bc7cf6fSBjoern A. Zeeb 5650bc7cf6fSBjoern A. Zeeb QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n", 5660bc7cf6fSBjoern A. Zeeb __func__, ha->pci_func, data)); 5670bc7cf6fSBjoern A. Zeeb if (data == CMDPEG_PHAN_INIT_COMPLETE) { 5680bc7cf6fSBjoern A. Zeeb QL_DPRINT2((ha->pci_dev, 5690bc7cf6fSBjoern A. Zeeb "%s: func[%d] init complete\n", 5700bc7cf6fSBjoern A. Zeeb __func__, ha->pci_func)); 5710bc7cf6fSBjoern A. Zeeb return(0); 5720bc7cf6fSBjoern A. Zeeb } 5730bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 5740bc7cf6fSBjoern A. Zeeb } while (delay--); 5750bc7cf6fSBjoern A. Zeeb 5760bc7cf6fSBjoern A. Zeeb device_printf(ha->pci_dev, 5770bc7cf6fSBjoern A. Zeeb "%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]" 5780bc7cf6fSBjoern A. Zeeb " HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]" 5790bc7cf6fSBjoern A. Zeeb " CMDPEG_STATE[0x%08x]\n", 5800bc7cf6fSBjoern A. Zeeb __func__, ha->pci_func, 5810bc7cf6fSBjoern A. Zeeb (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)), 5820bc7cf6fSBjoern A. Zeeb (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)), 5830bc7cf6fSBjoern A. Zeeb (READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)), 5840bc7cf6fSBjoern A. Zeeb (READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data); 5850bc7cf6fSBjoern A. Zeeb 5860bc7cf6fSBjoern A. Zeeb return (-1); 5870bc7cf6fSBjoern A. Zeeb } 5880bc7cf6fSBjoern A. Zeeb 5890bc7cf6fSBjoern A. Zeeb /* 5900bc7cf6fSBjoern A. Zeeb * Name: qla_init_hw 5910bc7cf6fSBjoern A. Zeeb * Function: Initializes P3+ hardware. 5920bc7cf6fSBjoern A. Zeeb */ 5930bc7cf6fSBjoern A. Zeeb int 5940bc7cf6fSBjoern A. Zeeb qla_init_hw(qla_host_t *ha) 5950bc7cf6fSBjoern A. Zeeb { 5960bc7cf6fSBjoern A. Zeeb device_t dev; 5970bc7cf6fSBjoern A. Zeeb int ret = 0; 5980bc7cf6fSBjoern A. Zeeb uint32_t val, delay = 300; 5990bc7cf6fSBjoern A. Zeeb 6000bc7cf6fSBjoern A. Zeeb dev = ha->pci_dev; 6010bc7cf6fSBjoern A. Zeeb 6020bc7cf6fSBjoern A. Zeeb QL_DPRINT1((dev, "%s: enter\n", __func__)); 6030bc7cf6fSBjoern A. Zeeb 6040bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 6050bc7cf6fSBjoern A. Zeeb 6060bc7cf6fSBjoern A. Zeeb if (ha->pci_func & 0x1) { 6070bc7cf6fSBjoern A. Zeeb while ((ha->pci_func & 0x1) && delay--) { 6080bc7cf6fSBjoern A. Zeeb val = READ_OFFSET32(ha, Q8_CMDPEG_STATE); 6090bc7cf6fSBjoern A. Zeeb 6100bc7cf6fSBjoern A. Zeeb if (val == CMDPEG_PHAN_INIT_COMPLETE) { 6110bc7cf6fSBjoern A. Zeeb QL_DPRINT2((dev, 6120bc7cf6fSBjoern A. Zeeb "%s: func = %d init complete\n", 6130bc7cf6fSBjoern A. Zeeb __func__, ha->pci_func)); 6140bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 6150bc7cf6fSBjoern A. Zeeb goto qla_init_exit; 6160bc7cf6fSBjoern A. Zeeb } 6170bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 6180bc7cf6fSBjoern A. Zeeb } 6190bc7cf6fSBjoern A. Zeeb return (-1); 6200bc7cf6fSBjoern A. Zeeb } 6210bc7cf6fSBjoern A. Zeeb 6220bc7cf6fSBjoern A. Zeeb val = READ_OFFSET32(ha, Q8_CMDPEG_STATE); 6230bc7cf6fSBjoern A. Zeeb 6240bc7cf6fSBjoern A. Zeeb if (val != CMDPEG_PHAN_INIT_COMPLETE) { 6250bc7cf6fSBjoern A. Zeeb ret = qla_init_from_flash(ha); 6260bc7cf6fSBjoern A. Zeeb qla_mdelay(__func__, 100); 627088fc971SDavid C Somayajulu } else { 628088fc971SDavid C Somayajulu ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR); 629088fc971SDavid C Somayajulu ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR); 630088fc971SDavid C Somayajulu ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB); 631088fc971SDavid C Somayajulu 632088fc971SDavid C Somayajulu if (qla_rd_flash32(ha, 0x100004, &val) == 0) { 633088fc971SDavid C Somayajulu 634088fc971SDavid C Somayajulu if (((val & 0xFF) != ha->fw_ver_major) || 635088fc971SDavid C Somayajulu (((val >> 8) & 0xFF) != ha->fw_ver_minor) || 636088fc971SDavid C Somayajulu (((val >> 16) & 0xFF) != ha->fw_ver_sub)) { 637088fc971SDavid C Somayajulu 638088fc971SDavid C Somayajulu ret = qla_init_from_flash(ha); 639088fc971SDavid C Somayajulu qla_mdelay(__func__, 100); 640088fc971SDavid C Somayajulu } 641088fc971SDavid C Somayajulu } 6420bc7cf6fSBjoern A. Zeeb } 6430bc7cf6fSBjoern A. Zeeb 6440bc7cf6fSBjoern A. Zeeb qla_init_exit: 6450bc7cf6fSBjoern A. Zeeb ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR); 6460bc7cf6fSBjoern A. Zeeb ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR); 6470bc7cf6fSBjoern A. Zeeb ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB); 6480bc7cf6fSBjoern A. Zeeb ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD); 6490bc7cf6fSBjoern A. Zeeb 6500bc7cf6fSBjoern A. Zeeb return (ret); 6510bc7cf6fSBjoern A. Zeeb } 6520bc7cf6fSBjoern A. Zeeb 653088fc971SDavid C Somayajulu static int 654088fc971SDavid C Somayajulu qla_wait_for_flash_busy(qla_host_t *ha) 655088fc971SDavid C Somayajulu { 656088fc971SDavid C Somayajulu uint32_t count = 100; 657088fc971SDavid C Somayajulu uint32_t val; 658088fc971SDavid C Somayajulu 659088fc971SDavid C Somayajulu QLA_USEC_DELAY(100); 660088fc971SDavid C Somayajulu 661088fc971SDavid C Somayajulu while (count--) { 662088fc971SDavid C Somayajulu val = READ_OFFSET32(ha, Q8_ROM_STATUS); 663088fc971SDavid C Somayajulu 664088fc971SDavid C Somayajulu if (val & BIT_1) 665088fc971SDavid C Somayajulu return 0; 666088fc971SDavid C Somayajulu qla_mdelay(__func__, 1); 667088fc971SDavid C Somayajulu } 668088fc971SDavid C Somayajulu return -1; 669088fc971SDavid C Somayajulu } 670088fc971SDavid C Somayajulu 671088fc971SDavid C Somayajulu static int 672088fc971SDavid C Somayajulu qla_flash_write_enable(qla_host_t *ha) 673088fc971SDavid C Somayajulu { 674088fc971SDavid C Somayajulu uint32_t val, rval; 675088fc971SDavid C Somayajulu 676088fc971SDavid C Somayajulu val = 0; 677088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 678088fc971SDavid C Somayajulu 679088fc971SDavid C Somayajulu val = ROM_OPCODE_WR_ENABLE; 680088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 681088fc971SDavid C Somayajulu 682088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 683088fc971SDavid C Somayajulu 684088fc971SDavid C Somayajulu if (rval) 685088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 686088fc971SDavid C Somayajulu 687088fc971SDavid C Somayajulu return (rval); 688088fc971SDavid C Somayajulu } 689088fc971SDavid C Somayajulu 690088fc971SDavid C Somayajulu static int 691088fc971SDavid C Somayajulu qla_flash_unprotect(qla_host_t *ha) 692088fc971SDavid C Somayajulu { 693088fc971SDavid C Somayajulu uint32_t val, rval; 694088fc971SDavid C Somayajulu 695088fc971SDavid C Somayajulu if (qla_flash_write_enable(ha) != 0) 696088fc971SDavid C Somayajulu return(-1); 697088fc971SDavid C Somayajulu 698088fc971SDavid C Somayajulu val = 0; 699088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0); 700088fc971SDavid C Somayajulu 701088fc971SDavid C Somayajulu val = ROM_OPCODE_WR_STATUS_REG; 702088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 703088fc971SDavid C Somayajulu 704088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 705088fc971SDavid C Somayajulu 706088fc971SDavid C Somayajulu if (rval) { 707088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 708088fc971SDavid C Somayajulu return rval; 709088fc971SDavid C Somayajulu } 710088fc971SDavid C Somayajulu 711088fc971SDavid C Somayajulu if (qla_flash_write_enable(ha) != 0) 712088fc971SDavid C Somayajulu return(-1); 713088fc971SDavid C Somayajulu 714088fc971SDavid C Somayajulu val = 0; 715088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0); 716088fc971SDavid C Somayajulu 717088fc971SDavid C Somayajulu val = ROM_OPCODE_WR_STATUS_REG; 718088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 719088fc971SDavid C Somayajulu 720088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 721088fc971SDavid C Somayajulu 722088fc971SDavid C Somayajulu if (rval) 723088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 724088fc971SDavid C Somayajulu 725088fc971SDavid C Somayajulu return rval; 726088fc971SDavid C Somayajulu } 727088fc971SDavid C Somayajulu 728088fc971SDavid C Somayajulu static int 729088fc971SDavid C Somayajulu qla_flash_protect(qla_host_t *ha) 730088fc971SDavid C Somayajulu { 731088fc971SDavid C Somayajulu uint32_t val, rval; 732088fc971SDavid C Somayajulu 733088fc971SDavid C Somayajulu if (qla_flash_write_enable(ha) != 0) 734088fc971SDavid C Somayajulu return(-1); 735088fc971SDavid C Somayajulu 736088fc971SDavid C Somayajulu val = 0x9C; 737088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0); 738088fc971SDavid C Somayajulu 739088fc971SDavid C Somayajulu val = ROM_OPCODE_WR_STATUS_REG; 740088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 741088fc971SDavid C Somayajulu 742088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 743088fc971SDavid C Somayajulu 744088fc971SDavid C Somayajulu if (rval) 745088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 746088fc971SDavid C Somayajulu 747088fc971SDavid C Somayajulu return rval; 748088fc971SDavid C Somayajulu } 749088fc971SDavid C Somayajulu 750088fc971SDavid C Somayajulu static uint32_t 751088fc971SDavid C Somayajulu qla_flash_get_status(qla_host_t *ha) 752088fc971SDavid C Somayajulu { 753088fc971SDavid C Somayajulu uint32_t count = 1000; 754088fc971SDavid C Somayajulu uint32_t val, rval; 755088fc971SDavid C Somayajulu 756088fc971SDavid C Somayajulu while (count--) { 757088fc971SDavid C Somayajulu val = 0; 758088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 759088fc971SDavid C Somayajulu 760088fc971SDavid C Somayajulu val = ROM_OPCODE_RD_STATUS_REG; 761088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 762088fc971SDavid C Somayajulu 763088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 764088fc971SDavid C Somayajulu 765088fc971SDavid C Somayajulu if (rval == 0) { 766088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1); 767088fc971SDavid C Somayajulu 768088fc971SDavid C Somayajulu if ((val & BIT_0) == 0) 769088fc971SDavid C Somayajulu return (val); 770088fc971SDavid C Somayajulu } 771088fc971SDavid C Somayajulu qla_mdelay(__func__, 1); 772088fc971SDavid C Somayajulu } 773088fc971SDavid C Somayajulu return -1; 774088fc971SDavid C Somayajulu } 775088fc971SDavid C Somayajulu 776088fc971SDavid C Somayajulu static int 777088fc971SDavid C Somayajulu qla_wait_for_flash_unprotect(qla_host_t *ha) 778088fc971SDavid C Somayajulu { 779088fc971SDavid C Somayajulu uint32_t delay = 1000; 780088fc971SDavid C Somayajulu 781088fc971SDavid C Somayajulu while (delay--) { 782088fc971SDavid C Somayajulu 783088fc971SDavid C Somayajulu if (qla_flash_get_status(ha) == 0) 784088fc971SDavid C Somayajulu return 0; 785088fc971SDavid C Somayajulu 786088fc971SDavid C Somayajulu qla_mdelay(__func__, 1); 787088fc971SDavid C Somayajulu } 788088fc971SDavid C Somayajulu 789088fc971SDavid C Somayajulu return -1; 790088fc971SDavid C Somayajulu } 791088fc971SDavid C Somayajulu 792088fc971SDavid C Somayajulu static int 793088fc971SDavid C Somayajulu qla_wait_for_flash_protect(qla_host_t *ha) 794088fc971SDavid C Somayajulu { 795088fc971SDavid C Somayajulu uint32_t delay = 1000; 796088fc971SDavid C Somayajulu 797088fc971SDavid C Somayajulu while (delay--) { 798088fc971SDavid C Somayajulu 799088fc971SDavid C Somayajulu if (qla_flash_get_status(ha) == 0x9C) 800088fc971SDavid C Somayajulu return 0; 801088fc971SDavid C Somayajulu 802088fc971SDavid C Somayajulu qla_mdelay(__func__, 1); 803088fc971SDavid C Somayajulu } 804088fc971SDavid C Somayajulu 805088fc971SDavid C Somayajulu return -1; 806088fc971SDavid C Somayajulu } 807088fc971SDavid C Somayajulu 808088fc971SDavid C Somayajulu static int 809088fc971SDavid C Somayajulu qla_erase_flash_sector(qla_host_t *ha, uint32_t start) 810088fc971SDavid C Somayajulu { 811088fc971SDavid C Somayajulu uint32_t val; 812088fc971SDavid C Somayajulu int rval; 813088fc971SDavid C Somayajulu 814088fc971SDavid C Somayajulu if (qla_flash_write_enable(ha) != 0) 815088fc971SDavid C Somayajulu return(-1); 816088fc971SDavid C Somayajulu 817088fc971SDavid C Somayajulu val = start; 818088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0); 819088fc971SDavid C Somayajulu 820088fc971SDavid C Somayajulu val = 3; 821088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 822088fc971SDavid C Somayajulu 823088fc971SDavid C Somayajulu val = ROM_OPCODE_SECTOR_ERASE; 824088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 825088fc971SDavid C Somayajulu 826088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 827088fc971SDavid C Somayajulu 828088fc971SDavid C Somayajulu if (rval) 829088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 830088fc971SDavid C Somayajulu return rval; 831088fc971SDavid C Somayajulu } 832088fc971SDavid C Somayajulu 833088fc971SDavid C Somayajulu #define Q8_FLASH_SECTOR_SIZE 0x10000 834088fc971SDavid C Somayajulu int 835088fc971SDavid C Somayajulu qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size) 836088fc971SDavid C Somayajulu { 837088fc971SDavid C Somayajulu int rval = 0; 838088fc971SDavid C Somayajulu uint32_t start; 839088fc971SDavid C Somayajulu 840088fc971SDavid C Somayajulu if (off & (Q8_FLASH_SECTOR_SIZE -1)) 841088fc971SDavid C Somayajulu return -1; 842088fc971SDavid C Somayajulu 843088fc971SDavid C Somayajulu if ((rval = qla_p3p_sem_lock2(ha))) 844088fc971SDavid C Somayajulu goto qla_erase_flash_exit; 845088fc971SDavid C Somayajulu 846088fc971SDavid C Somayajulu if ((rval = qla_flash_unprotect(ha))) 847088fc971SDavid C Somayajulu goto qla_erase_flash_unlock_exit; 848088fc971SDavid C Somayajulu 849088fc971SDavid C Somayajulu if ((rval = qla_wait_for_flash_unprotect(ha))) 850088fc971SDavid C Somayajulu goto qla_erase_flash_unlock_exit; 851088fc971SDavid C Somayajulu 852088fc971SDavid C Somayajulu for (start = off; start < (off + size); start = start + 0x10000) { 853088fc971SDavid C Somayajulu if (qla_erase_flash_sector(ha, start)) { 854088fc971SDavid C Somayajulu rval = -1; 855088fc971SDavid C Somayajulu break; 856088fc971SDavid C Somayajulu } 857088fc971SDavid C Somayajulu } 858088fc971SDavid C Somayajulu 859088fc971SDavid C Somayajulu rval = qla_flash_protect(ha); 860088fc971SDavid C Somayajulu 861088fc971SDavid C Somayajulu qla_erase_flash_unlock_exit: 862088fc971SDavid C Somayajulu qla_sem_unlock(ha, Q8_SEM2_UNLOCK); 863088fc971SDavid C Somayajulu 864088fc971SDavid C Somayajulu qla_erase_flash_exit: 865088fc971SDavid C Somayajulu return (rval); 866088fc971SDavid C Somayajulu } 867088fc971SDavid C Somayajulu 868088fc971SDavid C Somayajulu static int 869088fc971SDavid C Somayajulu qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data) 870088fc971SDavid C Somayajulu { 871088fc971SDavid C Somayajulu uint32_t val; 872088fc971SDavid C Somayajulu int rval = 0; 873088fc971SDavid C Somayajulu 874088fc971SDavid C Somayajulu val = data; 875088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0); 876088fc971SDavid C Somayajulu 877088fc971SDavid C Somayajulu val = off; 878088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0); 879088fc971SDavid C Somayajulu 880088fc971SDavid C Somayajulu val = 3; 881088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 882088fc971SDavid C Somayajulu 883088fc971SDavid C Somayajulu val = ROM_OPCODE_PROG_PAGE; 884088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 885088fc971SDavid C Somayajulu 886088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 887088fc971SDavid C Somayajulu 888088fc971SDavid C Somayajulu if (rval) 889088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: failed \n", __func__); 890088fc971SDavid C Somayajulu 891088fc971SDavid C Somayajulu return rval; 892088fc971SDavid C Somayajulu } 893088fc971SDavid C Somayajulu 894088fc971SDavid C Somayajulu static int 895088fc971SDavid C Somayajulu qla_flash_wait_for_write_complete(qla_host_t *ha) 896088fc971SDavid C Somayajulu { 897088fc971SDavid C Somayajulu uint32_t val, count = 1000; 898088fc971SDavid C Somayajulu int rval = 0; 899088fc971SDavid C Somayajulu 900088fc971SDavid C Somayajulu while (count--) { 901088fc971SDavid C Somayajulu 902088fc971SDavid C Somayajulu val = 0; 903088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0); 904088fc971SDavid C Somayajulu 905088fc971SDavid C Somayajulu val = ROM_OPCODE_RD_STATUS_REG; 906088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0); 907088fc971SDavid C Somayajulu 908088fc971SDavid C Somayajulu 909088fc971SDavid C Somayajulu rval = qla_wait_for_flash_busy(ha); 910088fc971SDavid C Somayajulu 911088fc971SDavid C Somayajulu if (rval == 0) { 912088fc971SDavid C Somayajulu qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1); 913088fc971SDavid C Somayajulu 914088fc971SDavid C Somayajulu if ((val & BIT_0) == 0) 915088fc971SDavid C Somayajulu return (0); 916088fc971SDavid C Somayajulu } 917088fc971SDavid C Somayajulu qla_mdelay(__func__, 1); 918088fc971SDavid C Somayajulu } 919088fc971SDavid C Somayajulu return -1; 920088fc971SDavid C Somayajulu } 921088fc971SDavid C Somayajulu 922088fc971SDavid C Somayajulu static int 923088fc971SDavid C Somayajulu qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data) 924088fc971SDavid C Somayajulu { 925088fc971SDavid C Somayajulu if (qla_flash_write_enable(ha) != 0) 926088fc971SDavid C Somayajulu return(-1); 927088fc971SDavid C Somayajulu 928088fc971SDavid C Somayajulu if (qla_flash_write32(ha, off, data) != 0) 929088fc971SDavid C Somayajulu return -1; 930088fc971SDavid C Somayajulu 931088fc971SDavid C Somayajulu if (qla_flash_wait_for_write_complete(ha)) 932088fc971SDavid C Somayajulu return -1; 933088fc971SDavid C Somayajulu 934088fc971SDavid C Somayajulu return 0; 935088fc971SDavid C Somayajulu } 936088fc971SDavid C Somayajulu 937088fc971SDavid C Somayajulu 938088fc971SDavid C Somayajulu static int 939088fc971SDavid C Somayajulu qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size, 940088fc971SDavid C Somayajulu uint32_t pattern) 941088fc971SDavid C Somayajulu { 942088fc971SDavid C Somayajulu int rval = 0; 943088fc971SDavid C Somayajulu uint32_t start; 944088fc971SDavid C Somayajulu 945088fc971SDavid C Somayajulu 946088fc971SDavid C Somayajulu if ((rval = qla_p3p_sem_lock2(ha))) 947088fc971SDavid C Somayajulu goto qla_wr_pattern_exit; 948088fc971SDavid C Somayajulu 949088fc971SDavid C Somayajulu if ((rval = qla_flash_unprotect(ha))) 950088fc971SDavid C Somayajulu goto qla_wr_pattern_unlock_exit; 951088fc971SDavid C Somayajulu 952088fc971SDavid C Somayajulu if ((rval = qla_wait_for_flash_unprotect(ha))) 953088fc971SDavid C Somayajulu goto qla_wr_pattern_unlock_exit; 954088fc971SDavid C Somayajulu 955088fc971SDavid C Somayajulu for (start = off; start < (off + size); start = start + 4) { 956088fc971SDavid C Somayajulu if (qla_flash_write(ha, start, pattern)) { 957088fc971SDavid C Somayajulu rval = -1; 958088fc971SDavid C Somayajulu break; 959088fc971SDavid C Somayajulu } 960088fc971SDavid C Somayajulu } 961088fc971SDavid C Somayajulu 962088fc971SDavid C Somayajulu rval = qla_flash_protect(ha); 963088fc971SDavid C Somayajulu 964088fc971SDavid C Somayajulu if (rval == 0) 965088fc971SDavid C Somayajulu rval = qla_wait_for_flash_protect(ha); 966088fc971SDavid C Somayajulu 967088fc971SDavid C Somayajulu qla_wr_pattern_unlock_exit: 968088fc971SDavid C Somayajulu qla_sem_unlock(ha, Q8_SEM2_UNLOCK); 969088fc971SDavid C Somayajulu 970088fc971SDavid C Somayajulu qla_wr_pattern_exit: 971088fc971SDavid C Somayajulu return (rval); 972088fc971SDavid C Somayajulu } 973088fc971SDavid C Somayajulu 974088fc971SDavid C Somayajulu static int 975088fc971SDavid C Somayajulu qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size, 976088fc971SDavid C Somayajulu void *data) 977088fc971SDavid C Somayajulu { 978088fc971SDavid C Somayajulu int rval = 0; 979088fc971SDavid C Somayajulu uint32_t start; 980088fc971SDavid C Somayajulu uint32_t *data32 = data; 981088fc971SDavid C Somayajulu 982088fc971SDavid C Somayajulu 983088fc971SDavid C Somayajulu if ((rval = qla_p3p_sem_lock2(ha))) 984088fc971SDavid C Somayajulu goto qla_wr_pattern_exit; 985088fc971SDavid C Somayajulu 986088fc971SDavid C Somayajulu if ((rval = qla_flash_unprotect(ha))) 987088fc971SDavid C Somayajulu goto qla_wr_pattern_unlock_exit; 988088fc971SDavid C Somayajulu 989088fc971SDavid C Somayajulu if ((rval = qla_wait_for_flash_unprotect(ha))) 990088fc971SDavid C Somayajulu goto qla_wr_pattern_unlock_exit; 991088fc971SDavid C Somayajulu 992088fc971SDavid C Somayajulu for (start = off; start < (off + size); start = start + 4) { 993088fc971SDavid C Somayajulu 994088fc971SDavid C Somayajulu if (*data32 != 0xFFFFFFFF) { 995088fc971SDavid C Somayajulu if (qla_flash_write(ha, start, *data32)) { 996088fc971SDavid C Somayajulu rval = -1; 997088fc971SDavid C Somayajulu break; 998088fc971SDavid C Somayajulu } 999088fc971SDavid C Somayajulu } 1000088fc971SDavid C Somayajulu data32++; 1001088fc971SDavid C Somayajulu } 1002088fc971SDavid C Somayajulu 1003088fc971SDavid C Somayajulu rval = qla_flash_protect(ha); 1004088fc971SDavid C Somayajulu 1005088fc971SDavid C Somayajulu if (rval == 0) 1006088fc971SDavid C Somayajulu rval = qla_wait_for_flash_protect(ha); 1007088fc971SDavid C Somayajulu 1008088fc971SDavid C Somayajulu qla_wr_pattern_unlock_exit: 1009088fc971SDavid C Somayajulu qla_sem_unlock(ha, Q8_SEM2_UNLOCK); 1010088fc971SDavid C Somayajulu 1011088fc971SDavid C Somayajulu qla_wr_pattern_exit: 1012088fc971SDavid C Somayajulu return (rval); 1013088fc971SDavid C Somayajulu } 1014088fc971SDavid C Somayajulu 1015088fc971SDavid C Somayajulu int 1016088fc971SDavid C Somayajulu qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf, 1017088fc971SDavid C Somayajulu uint32_t pattern) 1018088fc971SDavid C Somayajulu { 1019088fc971SDavid C Somayajulu int rval = 0; 1020088fc971SDavid C Somayajulu void *data; 1021088fc971SDavid C Somayajulu 1022088fc971SDavid C Somayajulu 1023088fc971SDavid C Somayajulu if (size == 0) 1024088fc971SDavid C Somayajulu return 0; 1025088fc971SDavid C Somayajulu 1026088fc971SDavid C Somayajulu size = size << 2; 1027088fc971SDavid C Somayajulu 1028088fc971SDavid C Somayajulu if (buf == NULL) { 1029088fc971SDavid C Somayajulu rval = qla_flash_write_pattern(ha, off, size, pattern); 1030088fc971SDavid C Somayajulu return (rval); 1031088fc971SDavid C Somayajulu } 1032088fc971SDavid C Somayajulu 1033088fc971SDavid C Somayajulu if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) { 1034088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s: malloc failed \n", __func__); 1035088fc971SDavid C Somayajulu rval = -1; 1036088fc971SDavid C Somayajulu goto qla_wr_flash_buffer_exit; 1037088fc971SDavid C Somayajulu } 1038088fc971SDavid C Somayajulu 1039088fc971SDavid C Somayajulu if ((rval = copyin(buf, data, size))) { 1040088fc971SDavid C Somayajulu device_printf(ha->pci_dev, "%s copyin failed\n", __func__); 1041088fc971SDavid C Somayajulu goto qla_wr_flash_buffer_free_exit; 1042088fc971SDavid C Somayajulu } 1043088fc971SDavid C Somayajulu 1044088fc971SDavid C Somayajulu rval = qla_flash_write_data(ha, off, size, data); 1045088fc971SDavid C Somayajulu 1046088fc971SDavid C Somayajulu qla_wr_flash_buffer_free_exit: 1047088fc971SDavid C Somayajulu free(data, M_QLA8XXXBUF); 1048088fc971SDavid C Somayajulu 1049088fc971SDavid C Somayajulu qla_wr_flash_buffer_exit: 1050088fc971SDavid C Somayajulu return (rval); 1051088fc971SDavid C Somayajulu } 1052088fc971SDavid C Somayajulu 1053