linux/drivers/scsi/bfa/bfa_ioc_cb.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
   3 * All rights reserved
   4 * www.brocade.com
   5 *
   6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License (GPL) Version 2 as
  10 * published by the Free Software Foundation
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18#include "bfad_drv.h"
  19#include "bfa_ioc.h"
  20#include "bfi_reg.h"
  21#include "bfa_defs.h"
  22
  23BFA_TRC_FILE(CNA, IOC_CB);
  24
  25/*
  26 * forward declarations
  27 */
  28static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
  29static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
  30static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
  31static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc);
  32static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix);
  33static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc);
  34static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc);
  35static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc);
  36static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc);
  37static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc);
  38static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc);
  39static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc);
  40
  41static struct bfa_ioc_hwif_s hwif_cb;
  42
  43/*
  44 * Called from bfa_ioc_attach() to map asic specific calls.
  45 */
  46void
  47bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
  48{
  49        hwif_cb.ioc_pll_init = bfa_ioc_cb_pll_init;
  50        hwif_cb.ioc_firmware_lock = bfa_ioc_cb_firmware_lock;
  51        hwif_cb.ioc_firmware_unlock = bfa_ioc_cb_firmware_unlock;
  52        hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init;
  53        hwif_cb.ioc_map_port = bfa_ioc_cb_map_port;
  54        hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set;
  55        hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail;
  56        hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset;
  57        hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start;
  58        hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join;
  59        hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave;
  60        hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack;
  61        hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete;
  62
  63        ioc->ioc_hwif = &hwif_cb;
  64}
  65
  66/*
  67 * Return true if firmware of current driver matches the running firmware.
  68 */
  69static bfa_boolean_t
  70bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
  71{
  72        return BFA_TRUE;
  73}
  74
  75static void
  76bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc)
  77{
  78}
  79
  80/*
  81 * Notify other functions on HB failure.
  82 */
  83static void
  84bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc)
  85{
  86        writel(~0U, ioc->ioc_regs.err_set);
  87        readl(ioc->ioc_regs.err_set);
  88}
  89
  90/*
  91 * Host to LPU mailbox message addresses
  92 */
  93static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = {
  94        { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
  95        { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }
  96};
  97
  98/*
  99 * Host <-> LPU mailbox command/status registers
 100 */
 101static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
 102
 103        { HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
 104        { HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
 105};
 106
 107static void
 108bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc)
 109{
 110        void __iomem *rb;
 111        int             pcifn = bfa_ioc_pcifn(ioc);
 112
 113        rb = bfa_ioc_bar0(ioc);
 114
 115        ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
 116        ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
 117        ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
 118
 119        if (ioc->port_id == 0) {
 120                ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
 121                ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
 122                ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG;
 123        } else {
 124                ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
 125                ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
 126                ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG);
 127        }
 128
 129        /*
 130         * Host <-> LPU mailbox command/status registers
 131         */
 132        ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd[pcifn].hfn;
 133        ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd[pcifn].lpu;
 134
 135        /*
 136         * PSS control registers
 137         */
 138        ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
 139        ioc->ioc_regs.pss_err_status_reg = (rb + PSS_ERR_STATUS_REG);
 140        ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_LCLK_CTL_REG);
 141        ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_SCLK_CTL_REG);
 142
 143        /*
 144         * IOC semaphore registers and serialization
 145         */
 146        ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
 147        ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG);
 148
 149        /*
 150         * sram memory access
 151         */
 152        ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
 153        ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
 154
 155        /*
 156         * err set reg : for notification of hb failure
 157         */
 158        ioc->ioc_regs.err_set = (rb + ERR_SET_REG);
 159}
 160
 161/*
 162 * Initialize IOC to port mapping.
 163 */
 164
 165static void
 166bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
 167{
 168        /*
 169         * For crossbow, port id is same as pci function.
 170         */
 171        ioc->port_id = bfa_ioc_pcifn(ioc);
 172
 173        bfa_trc(ioc, ioc->port_id);
 174}
 175
 176/*
 177 * Set interrupt mode for a function: INTX or MSIX
 178 */
 179static void
 180bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
 181{
 182}
 183
 184/*
 185 * Synchronized IOC failure processing routines
 186 */
 187static bfa_boolean_t
 188bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc)
 189{
 190        return bfa_ioc_cb_sync_complete(ioc);
 191}
 192
 193/*
 194 * Cleanup hw semaphore and usecnt registers
 195 */
 196static void
 197bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc)
 198{
 199
 200        /*
 201         * Read the hw sem reg to make sure that it is locked
 202         * before we clear it. If it is not locked, writing 1
 203         * will lock it instead of clearing it.
 204         */
 205        readl(ioc->ioc_regs.ioc_sem_reg);
 206        writel(1, ioc->ioc_regs.ioc_sem_reg);
 207}
 208
 209/*
 210 * Synchronized IOC failure processing routines
 211 */
 212static void
 213bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc)
 214{
 215}
 216
 217static void
 218bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc)
 219{
 220}
 221
 222static void
 223bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc)
 224{
 225        writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
 226}
 227
 228static bfa_boolean_t
 229bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc)
 230{
 231        uint32_t fwstate, alt_fwstate;
 232        fwstate = readl(ioc->ioc_regs.ioc_fwstate);
 233
 234        /*
 235         * At this point, this IOC is hoding the hw sem in the
 236         * start path (fwcheck) OR in the disable/enable path
 237         * OR to check if the other IOC has acknowledged failure.
 238         *
 239         * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL
 240         * or in MEMTEST states. In a normal scenario, this IOC
 241         * can not be in OP state when this function is called.
 242         *
 243         * However, this IOC could still be in OP state when
 244         * the OS driver is starting up, if the OptROM code has
 245         * left it in that state.
 246         *
 247         * If we had marked this IOC's fwstate as BFI_IOC_FAIL
 248         * in the failure case and now, if the fwstate is not
 249         * BFI_IOC_FAIL it implies that the other PCI fn have
 250         * reinitialized the ASIC or this IOC got disabled, so
 251         * return TRUE.
 252         */
 253        if (fwstate == BFI_IOC_UNINIT ||
 254                fwstate == BFI_IOC_INITING ||
 255                fwstate == BFI_IOC_DISABLED ||
 256                fwstate == BFI_IOC_MEMTEST ||
 257                fwstate == BFI_IOC_OP)
 258                return BFA_TRUE;
 259        else {
 260                alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate);
 261                if (alt_fwstate == BFI_IOC_FAIL ||
 262                        alt_fwstate == BFI_IOC_DISABLED ||
 263                        alt_fwstate == BFI_IOC_UNINIT ||
 264                        alt_fwstate == BFI_IOC_INITING ||
 265                        alt_fwstate == BFI_IOC_MEMTEST)
 266                        return BFA_TRUE;
 267                else
 268                        return BFA_FALSE;
 269        }
 270}
 271
 272bfa_status_t
 273bfa_ioc_cb_pll_init(void __iomem *rb, enum bfi_asic_mode fcmode)
 274{
 275        u32     pll_sclk, pll_fclk;
 276
 277        pll_sclk = __APP_PLL_SCLK_ENABLE | __APP_PLL_SCLK_LRESETN |
 278                __APP_PLL_SCLK_P0_1(3U) |
 279                __APP_PLL_SCLK_JITLMT0_1(3U) |
 280                __APP_PLL_SCLK_CNTLMT0_1(3U);
 281        pll_fclk = __APP_PLL_LCLK_ENABLE | __APP_PLL_LCLK_LRESETN |
 282                __APP_PLL_LCLK_RSEL200500 | __APP_PLL_LCLK_P0_1(3U) |
 283                __APP_PLL_LCLK_JITLMT0_1(3U) |
 284                __APP_PLL_LCLK_CNTLMT0_1(3U);
 285        writel(BFI_IOC_UNINIT, (rb + BFA_IOC0_STATE_REG));
 286        writel(BFI_IOC_UNINIT, (rb + BFA_IOC1_STATE_REG));
 287        writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
 288        writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
 289        writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
 290        writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
 291        writel(0xffffffffU, (rb + HOSTFN0_INT_MSK));
 292        writel(0xffffffffU, (rb + HOSTFN1_INT_MSK));
 293        writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
 294        writel(__APP_PLL_SCLK_BYPASS | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
 295                        rb + APP_PLL_SCLK_CTL_REG);
 296        writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
 297        writel(__APP_PLL_LCLK_BYPASS | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
 298                        rb + APP_PLL_LCLK_CTL_REG);
 299        udelay(2);
 300        writel(__APP_PLL_SCLK_LOGIC_SOFT_RESET, rb + APP_PLL_SCLK_CTL_REG);
 301        writel(__APP_PLL_LCLK_LOGIC_SOFT_RESET, rb + APP_PLL_LCLK_CTL_REG);
 302        writel(pll_sclk | __APP_PLL_SCLK_LOGIC_SOFT_RESET,
 303                        rb + APP_PLL_SCLK_CTL_REG);
 304        writel(pll_fclk | __APP_PLL_LCLK_LOGIC_SOFT_RESET,
 305                        rb + APP_PLL_LCLK_CTL_REG);
 306        udelay(2000);
 307        writel(0xffffffffU, (rb + HOSTFN0_INT_STATUS));
 308        writel(0xffffffffU, (rb + HOSTFN1_INT_STATUS));
 309        writel(pll_sclk, (rb + APP_PLL_SCLK_CTL_REG));
 310        writel(pll_fclk, (rb + APP_PLL_LCLK_CTL_REG));
 311
 312        return BFA_STATUS_OK;
 313}
 314