1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 NetXen, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/conf.h>
  29 #include <sys/debug.h>
  30 #include <sys/stropts.h>
  31 #include <sys/stream.h>
  32 #include <sys/strlog.h>
  33 #include <sys/kmem.h>
  34 #include <sys/stat.h>
  35 #include <sys/kstat.h>
  36 #include <sys/vtrace.h>
  37 #include <sys/dlpi.h>
  38 #include <sys/strsun.h>
  39 #include <sys/ethernet.h>
  40 #include <sys/modctl.h>
  41 #include <sys/errno.h>
  42 #include <sys/dditypes.h>
  43 #include <sys/ddi.h>
  44 #include <sys/sunddi.h>
  45 #include <sys/sysmacros.h>
  46 #include <sys/pci.h>
  47 
  48 #include "unm_nic.h"
  49 #include "unm_nic_hw.h"
  50 #include "nic_cmn.h"
  51 #include "unm_nic_ioctl.h"
  52 #include "nic_phan_reg.h"
  53 
  54 struct crb_addr_pair {
  55         long    addr, data;
  56 };
  57 
  58 #define MAX_CRB_XFORM   60
  59 #define ADDR_ERROR      ((unsigned long)0xffffffff)
  60 
  61 #define crb_addr_transform(name)                                \
  62                 crb_addr_xform[UNM_HW_PX_MAP_CRB_##name] =              \
  63                 UNM_HW_CRB_HUB_AGT_ADR_##name << 20
  64 
  65 static unsigned int crb_addr_xform[MAX_CRB_XFORM];
  66 
  67 static void
  68 crb_addr_transform_setup(void)
  69 {
  70                 crb_addr_transform(XDMA);
  71                 crb_addr_transform(TIMR);
  72                 crb_addr_transform(SRE);
  73                 crb_addr_transform(SQN3);
  74                 crb_addr_transform(SQN2);
  75                 crb_addr_transform(SQN1);
  76                 crb_addr_transform(SQN0);
  77                 crb_addr_transform(SQS3);
  78                 crb_addr_transform(SQS2);
  79                 crb_addr_transform(SQS1);
  80                 crb_addr_transform(SQS0);
  81                 crb_addr_transform(RPMX7);
  82                 crb_addr_transform(RPMX6);
  83                 crb_addr_transform(RPMX5);
  84                 crb_addr_transform(RPMX4);
  85                 crb_addr_transform(RPMX3);
  86                 crb_addr_transform(RPMX2);
  87                 crb_addr_transform(RPMX1);
  88                 crb_addr_transform(RPMX0);
  89                 crb_addr_transform(ROMUSB);
  90                 crb_addr_transform(SN);
  91                 crb_addr_transform(QMN);
  92                 crb_addr_transform(QMS);
  93                 crb_addr_transform(PGNI);
  94                 crb_addr_transform(PGND);
  95                 crb_addr_transform(PGN3);
  96                 crb_addr_transform(PGN2);
  97                 crb_addr_transform(PGN1);
  98                 crb_addr_transform(PGN0);
  99                 crb_addr_transform(PGSI);
 100                 crb_addr_transform(PGSD);
 101                 crb_addr_transform(PGS3);
 102                 crb_addr_transform(PGS2);
 103                 crb_addr_transform(PGS1);
 104                 crb_addr_transform(PGS0);
 105                 crb_addr_transform(PS);
 106                 crb_addr_transform(PH);
 107                 crb_addr_transform(NIU);
 108                 crb_addr_transform(I2Q);
 109                 crb_addr_transform(EG);
 110                 crb_addr_transform(MN);
 111                 crb_addr_transform(MS);
 112                 crb_addr_transform(CAS2);
 113                 crb_addr_transform(CAS1);
 114                 crb_addr_transform(CAS0);
 115                 crb_addr_transform(CAM);
 116                 crb_addr_transform(C2C1);
 117                 crb_addr_transform(C2C0);
 118                 crb_addr_transform(SMB);
 119                 crb_addr_transform(OCM0);
 120 
 121         /*
 122          * Used only in P3 just define it for P2 also.
 123          */
 124         crb_addr_transform(I2C0);
 125 }
 126 
 127 /*
 128  * decode_crb_addr(0 - utility to translate from internal Phantom CRB address
 129  * to external PCI CRB address.
 130  */
 131 static unsigned long
 132 decode_crb_addr(unsigned long addr)
 133 {
 134         int i;
 135         unsigned long base_addr, offset, pci_base;
 136 
 137         crb_addr_transform_setup();
 138 
 139         pci_base = ADDR_ERROR;
 140         base_addr = addr & 0xfff00000;
 141         offset = addr & 0x000fffff;
 142 
 143         for (i = 0; i < MAX_CRB_XFORM; i++) {
 144                 if (crb_addr_xform[i] == base_addr) {
 145                         pci_base = i << 20;
 146                         break;
 147                 }
 148         }
 149 
 150         if (pci_base == ADDR_ERROR) {
 151                 return (pci_base);
 152         } else {
 153                 return (pci_base + offset);
 154         }
 155 }
 156 
 157 static long rom_max_timeout = 100;
 158 static long rom_lock_timeout = 10000;
 159 
 160 static int
 161 rom_lock(unm_adapter *adapter)
 162 {
 163         uint32_t done = 0;
 164         long timeout = 0;
 165 
 166         while (!done) {
 167                 /* acquire semaphore2 from PCI HW block */
 168                 unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
 169                 if (done == 1)
 170                         break;
 171                 if (timeout >= rom_lock_timeout) {
 172                         cmn_err(CE_WARN, "%s%d rom_lock timed out %d %ld\n",
 173                             adapter->name, adapter->instance, done, timeout);
 174                         return (-1);
 175                 }
 176                 timeout++;
 177         }
 178         unm_nic_reg_write(adapter, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
 179         return (0);
 180 }
 181 
 182 static void
 183 rom_unlock(unm_adapter *adapter)
 184 {
 185         uint32_t val;
 186 
 187         /* release semaphore2 */
 188         unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
 189 }
 190 
 191 static int
 192 wait_rom_done(unm_adapter *adapter)
 193 {
 194         long timeout = 0;
 195         long done = 0;
 196 
 197         while (done == 0) {
 198                 unm_nic_reg_read(adapter, UNM_ROMUSB_GLB_STATUS, &done);
 199                 done &= 2;
 200                 timeout++;
 201                 if (timeout >= rom_max_timeout) {
 202                         cmn_err(CE_WARN,
 203                             "Timeout reached waiting for rom done");
 204                         return (-1);
 205                 }
 206         }
 207         return (0);
 208 }
 209 
 210 static int
 211 do_rom_fast_read(unm_adapter *adapter, int addr, int *valp)
 212 {
 213         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ADDRESS, addr);
 214         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
 215         drv_usecwait(100);   /* prevent bursting on CRB */
 216         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
 217         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_INSTR_OPCODE, 0xb);
 218         if (wait_rom_done(adapter) != DDI_SUCCESS) {
 219                 cmn_err(CE_WARN, "Error waiting for rom done\n");
 220                 return (-1);
 221         }
 222 
 223         // reset abyte_cnt and dummy_byte_cnt
 224         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
 225         drv_usecwait(100);   /* prevent bursting on CRB */
 226         unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
 227 
 228         unm_nic_reg_read(adapter, UNM_ROMUSB_ROM_RDATA, valp);
 229         return (0);
 230 }
 231 
 232 int
 233 rom_fast_read(struct unm_adapter_s *adapter, int addr, int *valp)
 234 {
 235         int ret;
 236 
 237         if (rom_lock(adapter) != 0) {
 238                 cmn_err(CE_WARN, "%s(%d)rom_lock failed\n",
 239                     __FUNCTION__, __LINE__);
 240                 return (-1);
 241         }
 242 
 243         ret = do_rom_fast_read(adapter, addr, valp);
 244         if (ret != 0) {
 245                 cmn_err(CE_WARN, "%s do_rom_fast_read returned: %d\n",
 246                     __FUNCTION__, __LINE__);
 247                 return (-1);
 248         }
 249         rom_unlock(adapter);
 250         return (ret);
 251 }
 252 
 253 int
 254 pinit_from_rom(struct unm_adapter_s *adapter, int verbose)
 255 {
 256         int     addr, val, status, i, init_delay = 0, n;
 257         struct crb_addr_pair    *buf;
 258         unsigned long   off;
 259         unsigned int    offset;
 260 
 261         status = unm_nic_get_board_info(adapter);
 262         if (status)
 263                 cmn_err(CE_WARN, "%s: pinit_from_rom: Error getting brdinfo\n",
 264                     unm_nic_driver_name);
 265 
 266         UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET, 0xffffffff, adapter);
 267 
 268         if (verbose) {
 269                 int     val;
 270                 if (rom_fast_read(adapter, 0x4008, &val) == 0)
 271                         cmn_err(CE_WARN, "P2 ROM board type: 0x%08x\n", val);
 272                 else
 273                         cmn_err(CE_WARN, "Could not read board type\n");
 274                 if (rom_fast_read(adapter, 0x400c, &val) == 0)
 275                         cmn_err(CE_WARN, "ROM board  num: 0x%08x\n", val);
 276                 else
 277                         cmn_err(CE_WARN, "Could not read board number\n");
 278                 if (rom_fast_read(adapter, 0x4010, &val) == 0)
 279                         cmn_err(CE_WARN, "ROM chip   num: 0x%08x\n", val);
 280                 else
 281                         cmn_err(CE_WARN, "Could not read chip number\n");
 282         }
 283 
 284         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 285                 if (rom_fast_read(adapter, 0, &n) != 0 ||
 286                     (unsigned int)n != 0xcafecafe ||
 287                     rom_fast_read(adapter, 4, &n) != 0) {
 288                         cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
 289                             "n: %08x\n", unm_nic_driver_name, n);
 290                         return (-1);
 291                 }
 292 
 293                 offset = n & 0xffffU;
 294                 n = (n >> 16) & 0xffffU;
 295         } else {
 296                 if (rom_fast_read(adapter, 0, &n) != 0 ||
 297                     !(n & 0x80000000)) {
 298                         cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
 299                             "n: %08x\n", unm_nic_driver_name, n);
 300                         return (-1);
 301                 }
 302                 offset = 1;
 303                 n &= ~0x80000000;
 304         }
 305 
 306         if (n  >= 1024) {
 307                 cmn_err(CE_WARN, "%s: %s:n=0x%x Card flash not initialized\n",
 308                     unm_nic_driver_name, __FUNCTION__, n);
 309                 return (-1);
 310         }
 311 
 312         if (verbose)
 313                 cmn_err(CE_WARN, "%s: %d CRB init values found in ROM.\n",
 314                     unm_nic_driver_name, n);
 315 
 316         buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
 317         if (buf == NULL) {
 318                 cmn_err(CE_WARN, "%s: pinit_from_rom: Unable to get memory\n",
 319                     unm_nic_driver_name);
 320                 return (-1);
 321         }
 322 
 323         for (i = 0; i < n; i++) {
 324                 if (rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
 325                     rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
 326                         kmem_free(buf, n * sizeof (struct crb_addr_pair));
 327                         return (-1);
 328                 }
 329 
 330                 buf[i].addr = addr;
 331                 buf[i].data = val;
 332 
 333                 if (verbose)
 334                         cmn_err(CE_WARN, "%s: PCI:     0x%08x == 0x%08x\n",
 335                             unm_nic_driver_name,
 336                             (unsigned int)decode_crb_addr(
 337                             (unsigned long)addr), val);
 338         }
 339 
 340         for (i = 0; i < n; i++) {
 341                 off = decode_crb_addr((unsigned long)buf[i].addr) +
 342                     UNM_PCI_CRBSPACE;
 343                 /* skipping cold reboot MAGIC */
 344                 if (off == UNM_CAM_RAM(0x1fc)) {
 345                         continue;
 346                 }
 347 
 348                 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 349                         /* do not reset PCI */
 350                         if (off == (ROMUSB_GLB + 0xbc)) {
 351                                 continue;
 352                         }
 353                         if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
 354                                 continue;
 355                         if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
 356                                 continue;
 357                         if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
 358                                 continue;
 359                         if (off == (UNM_CRB_PEG_NET_1 + 0x18)) {
 360                                 buf[i].data = 0x1020;
 361                         }
 362                         /* skip the function enable register */
 363                         if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
 364                                 continue;
 365                         }
 366                         if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
 367                                 continue;
 368                         }
 369 
 370                         if ((off & 0x0ff00000) == UNM_CRB_SMB) {
 371                                 continue;
 372                         }
 373 
 374                 }
 375 
 376                 if (off == ADDR_ERROR) {
 377                         cmn_err(CE_WARN, "%s: Err: Unknown addr: 0x%08lx\n",
 378                             unm_nic_driver_name, buf[i].addr);
 379                         continue;
 380                 }
 381 
 382                 /* After writing this register, HW needs time for CRB */
 383                 /* to quiet down (else crb_window returns 0xffffffff) */
 384                 if (off == UNM_ROMUSB_GLB_SW_RESET) {
 385                         init_delay = 1;
 386 
 387                         if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 388                                 /* hold xdma in reset also */
 389                                 buf[i].data = 0x8000ff;
 390                         }
 391                 }
 392 
 393                 adapter->unm_nic_hw_write_wx(adapter, off, &buf[i].data, 4);
 394 
 395                 if (init_delay == 1) {
 396                         nx_msleep(1000);        /* Sleep 1000 msecs */
 397                         init_delay = 0;
 398                 }
 399 
 400                 nx_msleep(1);                   /* Sleep 1 msec */
 401         }
 402 
 403         kmem_free(buf, n * sizeof (struct crb_addr_pair));
 404 
 405         // disable_peg_cache_all
 406         // unreset_net_cache
 407         if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 408                 val = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
 409                     adapter);
 410                 UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
 411                     (val & 0xffffff0f), adapter);
 412         }
 413 
 414         // p2dn replyCount
 415         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0xec, 0x1e, adapter);
 416         // disable_peg_cache 0
 417         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0x4c, 8, adapter);
 418         // disable_peg_cache 1
 419         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_I+0x4c, 8, adapter);
 420 
 421         // peg_clr_all
 422         // peg_clr 0
 423         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0x8, 0, adapter);
 424         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0xc, 0, adapter);
 425         // peg_clr 1
 426         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0x8, 0, adapter);
 427         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0xc, 0, adapter);
 428         // peg_clr 2
 429         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0x8, 0, adapter);
 430         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0xc, 0, adapter);
 431         // peg_clr 3
 432         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0x8, 0, adapter);
 433         UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0xc, 0, adapter);
 434 
 435         return (0);
 436 }
 437 
 438 int
 439 phantom_init(struct unm_adapter_s *adapter, int pegtune_val)
 440 {
 441         u32     val = 0;
 442         int     retries = 120;
 443 
 444         if (!pegtune_val) {
 445                 do {
 446                         val = adapter->unm_nic_pci_read_normalize(adapter,
 447                             CRB_CMDPEG_STATE);
 448 
 449                         if ((val == PHAN_INITIALIZE_COMPLETE) ||
 450                             (val == PHAN_INITIALIZE_ACK))
 451                                 return (DDI_SUCCESS);
 452 
 453                         /* 500 msec wait */
 454                         drv_usecwait(500000);
 455                 } while (--retries > 0);
 456 
 457                 if (!retries) {
 458                         val = adapter->unm_nic_pci_read_normalize(adapter,
 459                             UNM_ROMUSB_GLB_PEGTUNE_DONE);
 460                         cmn_err(CE_WARN, "WARNING: Initial boot wait loop"
 461                             "failed...state:%d\n", val);
 462                         return (DDI_FAILURE);
 463                 }
 464         }
 465 
 466         return (DDI_SUCCESS);
 467 }
 468 
 469 int
 470 load_from_flash(struct unm_adapter_s *adapter)
 471 {
 472         int  i;
 473         long data, size = 0;
 474         long flashaddr = BOOTLD_START, memaddr = BOOTLD_START;
 475 
 476         size = (IMAGE_START - BOOTLD_START)/4;
 477 
 478         if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 479                 data = 1;
 480                 adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
 481                     &data, 4);
 482         }
 483 
 484         for (i = 0; i < size; i++) {
 485                 if (rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
 486                         cmn_err(CE_WARN, "Error in rom_fast_read: "
 487                             "Will skip loading flash image\n");
 488                         return (DDI_FAILURE);
 489                 }
 490 
 491                 adapter->unm_nic_pci_mem_write(adapter, memaddr, &data, 4);
 492                 flashaddr += 4;
 493                 memaddr += 4;
 494         }
 495 
 496         drv_usecwait(100);
 497         UNM_READ_LOCK(&adapter->adapter_lock);
 498 
 499         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 500                 data = 0x80001d;
 501                 adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
 502                     &data, 4);
 503         } else {
 504                 data = 0x3fff;
 505                 adapter->unm_nic_hw_write_wx(adapter,
 506                     UNM_ROMUSB_GLB_CHIP_CLK_CTRL, &data, 4);
 507                 data = 0;
 508                 adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
 509                     &data, 4);
 510         }
 511 
 512         UNM_READ_UNLOCK(&adapter->adapter_lock);
 513         return (DDI_SUCCESS);
 514 }