Exemple #1
0
static int __devinit mvs_64xx_init(struct mvs_info *mvi)
{
	void __iomem *regs = mvi->regs;
	int i;
	u32 tmp, cctl;

	if (mvi->pdev && mvi->pdev->revision == 0)
		mvi->flags |= MVF_PHY_PWR_FIX;
	if (!(mvi->flags & MVF_FLAG_SOC)) {
		mvs_show_pcie_usage(mvi);
		tmp = mvs_64xx_chip_reset(mvi);
		if (tmp)
			return tmp;
	} else {
		tmp = mr32(MVS_PHY_CTL);
		tmp &= ~PCTL_PWR_OFF;
		tmp |= PCTL_PHY_DSBL;
		mw32(MVS_PHY_CTL, tmp);
	}

	/* Init Chip */
	/* make sure RST is set; HBA_RST /should/ have done that for us */
	cctl = mr32(MVS_CTL) & 0xFFFF;
	if (cctl & CCTL_RST)
		cctl &= ~CCTL_RST;
	else
		mw32_f(MVS_CTL, cctl | CCTL_RST);

	if (!(mvi->flags & MVF_FLAG_SOC)) {
		/* write to device control _AND_ device status register */
		pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
		tmp &= ~PRD_REQ_MASK;
		tmp |= PRD_REQ_SIZE;
		pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp);

		pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
		tmp &= ~PCTL_PWR_OFF;
		tmp &= ~PCTL_PHY_DSBL;
		pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);

		pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
		tmp &= PCTL_PWR_OFF;
		tmp &= ~PCTL_PHY_DSBL;
		pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
	} else {
		tmp = mr32(MVS_PHY_CTL);
		tmp &= ~PCTL_PWR_OFF;
		tmp |= PCTL_COM_ON;
		tmp &= ~PCTL_PHY_DSBL;
		tmp |= PCTL_LINK_RST;
		mw32(MVS_PHY_CTL, tmp);
		msleep(100);
		tmp &= ~PCTL_LINK_RST;
		mw32(MVS_PHY_CTL, tmp);
		msleep(100);
	}

	/* reset control */
	mw32(MVS_PCS, 0);		/* MVS_PCS */
	/* init phys */
	mvs_64xx_phy_hacks(mvi);

	/* enable auto port detection */
	mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);

	mw32(MVS_CMD_LIST_LO, mvi->slot_dma);
	mw32(MVS_CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);

	mw32(MVS_RX_FIS_LO, mvi->rx_fis_dma);
	mw32(MVS_RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);

	mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ);
	mw32(MVS_TX_LO, mvi->tx_dma);
	mw32(MVS_TX_HI, (mvi->tx_dma >> 16) >> 16);

	mw32(MVS_RX_CFG, MVS_RX_RING_SZ);
	mw32(MVS_RX_LO, mvi->rx_dma);
	mw32(MVS_RX_HI, (mvi->rx_dma >> 16) >> 16);

	for (i = 0; i < mvi->chip->n_phy; i++) {
		/* set phy local SAS address */
		/* should set little endian SAS address to 64xx chip */
		mvs_set_sas_addr(mvi, i, PHYR_ADDR_LO, PHYR_ADDR_HI,
				cpu_to_be64(mvi->phy[i].dev_sas_addr));

		mvs_64xx_enable_xmt(mvi, i);

		mvs_64xx_phy_reset(mvi, i, 1);
		msleep(500);
		mvs_64xx_detect_porttype(mvi, i);
	}
	if (mvi->flags & MVF_FLAG_SOC) {
		/* set select registers */
		writel(0x0E008000, regs + 0x000);
		writel(0x59000008, regs + 0x004);
		writel(0x20, regs + 0x008);
		writel(0x20, regs + 0x00c);
		writel(0x20, regs + 0x010);
		writel(0x20, regs + 0x014);
		writel(0x20, regs + 0x018);
		writel(0x20, regs + 0x01c);
	}
	for (i = 0; i < mvi->chip->n_phy; i++) {
		/* clear phy int status */
		tmp = mvs_read_port_irq_stat(mvi, i);
		tmp &= ~PHYEV_SIG_FIS;
		mvs_write_port_irq_stat(mvi, i, tmp);

		/* set phy int mask */
		tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS |
			PHYEV_ID_DONE | PHYEV_DCDR_ERR | PHYEV_CRC_ERR |
			PHYEV_DEC_ERR;
		mvs_write_port_irq_mask(mvi, i, tmp);

		msleep(100);
		mvs_update_phyinfo(mvi, i, 1);
	}

	/* FIXME: update wide port bitmaps */

	/* little endian for open address and command table, etc. */
	/*
	 * it seems that ( from the spec ) turning on big-endian won't
	 * do us any good on big-endian machines, need further confirmation
	 */
	cctl = mr32(MVS_CTL);
	cctl |= CCTL_ENDIAN_CMD;
	cctl |= CCTL_ENDIAN_DATA;
	cctl &= ~CCTL_ENDIAN_OPEN;
	cctl |= CCTL_ENDIAN_RSP;
	mw32_f(MVS_CTL, cctl);

	/* reset CMD queue */
	tmp = mr32(MVS_PCS);
	tmp |= PCS_CMD_RST;
	mw32(MVS_PCS, tmp);
	/* interrupt coalescing may cause missing HW interrput in some case,
	 * and the max count is 0x1ff, while our max slot is 0x200,
	 * it will make count 0.
	 */
	tmp = 0;
	mw32(MVS_INT_COAL, tmp);

	tmp = 0x100;
	mw32(MVS_INT_COAL_TMOUT, tmp);

	/* ladies and gentlemen, start your engines */
	mw32(MVS_TX_CFG, 0);
	mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
	mw32(MVS_RX_CFG, MVS_RX_RING_SZ | RX_EN);
	/* enable CMD/CMPL_Q/RESP mode */
	mw32(MVS_PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN |
		PCS_CMD_EN | PCS_CMD_STOP_ERR);

	/* enable completion queue interrupt */
	tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
		CINT_DMA_PCIE);

	mw32(MVS_INT_MASK, tmp);

	/* Enable SRS interrupt */
	mw32(MVS_INT_MASK_SRS_0, 0xFFFF);

	return 0;
}
Exemple #2
0
static int __devinit mvs_64xx_init(struct mvs_info *mvi)
{
    void __iomem *regs = mvi->regs;
    int i;
    u32 tmp, cctl;

    if (mvi->pdev && mvi->pdev->revision == 0)
        mvi->flags |= MVF_PHY_PWR_FIX;
    if (!(mvi->flags & MVF_FLAG_SOC)) {
        mvs_show_pcie_usage(mvi);
        tmp = mvs_64xx_chip_reset(mvi);
        if (tmp)
            return tmp;
    } else {
        tmp = mr32(MVS_PHY_CTL);
        tmp &= ~PCTL_PWR_OFF;
        tmp |= PCTL_PHY_DSBL;
        mw32(MVS_PHY_CTL, tmp);
    }



    cctl = mr32(MVS_CTL) & 0xFFFF;
    if (cctl & CCTL_RST)
        cctl &= ~CCTL_RST;
    else
        mw32_f(MVS_CTL, cctl | CCTL_RST);

    if (!(mvi->flags & MVF_FLAG_SOC)) {

        pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
        tmp &= ~PRD_REQ_MASK;
        tmp |= PRD_REQ_SIZE;
        pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp);

        pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
        tmp &= ~PCTL_PWR_OFF;
        tmp &= ~PCTL_PHY_DSBL;
        pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);

        pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp);
        tmp &= PCTL_PWR_OFF;
        tmp &= ~PCTL_PHY_DSBL;
        pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
    } else {
        tmp = mr32(MVS_PHY_CTL);
        tmp &= ~PCTL_PWR_OFF;
        tmp |= PCTL_COM_ON;
        tmp &= ~PCTL_PHY_DSBL;
        tmp |= PCTL_LINK_RST;
        mw32(MVS_PHY_CTL, tmp);
        msleep(100);
        tmp &= ~PCTL_LINK_RST;
        mw32(MVS_PHY_CTL, tmp);
        msleep(100);
    }


    mw32(MVS_PCS, 0);

    mvs_64xx_phy_hacks(mvi);


    mw32(MVS_GBL_PORT_TYPE, MODE_AUTO_DET_EN);

    mw32(MVS_CMD_LIST_LO, mvi->slot_dma);
    mw32(MVS_CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);

    mw32(MVS_RX_FIS_LO, mvi->rx_fis_dma);
    mw32(MVS_RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);

    mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ);
    mw32(MVS_TX_LO, mvi->tx_dma);
    mw32(MVS_TX_HI, (mvi->tx_dma >> 16) >> 16);

    mw32(MVS_RX_CFG, MVS_RX_RING_SZ);
    mw32(MVS_RX_LO, mvi->rx_dma);
    mw32(MVS_RX_HI, (mvi->rx_dma >> 16) >> 16);

    for (i = 0; i < mvi->chip->n_phy; i++) {


        mvs_set_sas_addr(mvi, i, PHYR_ADDR_LO, PHYR_ADDR_HI,
                         cpu_to_be64(mvi->phy[i].dev_sas_addr));

        mvs_64xx_enable_xmt(mvi, i);

        mvs_64xx_phy_reset(mvi, i, 1);
        msleep(500);
        mvs_64xx_detect_porttype(mvi, i);
    }
    if (mvi->flags & MVF_FLAG_SOC) {

        writel(0x0E008000, regs + 0x000);
        writel(0x59000008, regs + 0x004);
        writel(0x20, regs + 0x008);
        writel(0x20, regs + 0x00c);
        writel(0x20, regs + 0x010);
        writel(0x20, regs + 0x014);
        writel(0x20, regs + 0x018);
        writel(0x20, regs + 0x01c);
    }
    for (i = 0; i < mvi->chip->n_phy; i++) {

        tmp = mvs_read_port_irq_stat(mvi, i);
        tmp &= ~PHYEV_SIG_FIS;
        mvs_write_port_irq_stat(mvi, i, tmp);


        tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS |
              PHYEV_ID_DONE | PHYEV_DCDR_ERR | PHYEV_CRC_ERR |
              PHYEV_DEC_ERR;
        mvs_write_port_irq_mask(mvi, i, tmp);

        msleep(100);
        mvs_update_phyinfo(mvi, i, 1);
    }





    cctl = mr32(MVS_CTL);
    cctl |= CCTL_ENDIAN_CMD;
    cctl |= CCTL_ENDIAN_DATA;
    cctl &= ~CCTL_ENDIAN_OPEN;
    cctl |= CCTL_ENDIAN_RSP;
    mw32_f(MVS_CTL, cctl);


    tmp = mr32(MVS_PCS);
    tmp |= PCS_CMD_RST;
    mw32(MVS_PCS, tmp);

    tmp = 0;
    mw32(MVS_INT_COAL, tmp);

    tmp = 0x100;
    mw32(MVS_INT_COAL_TMOUT, tmp);


    mw32(MVS_TX_CFG, 0);
    mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
    mw32(MVS_RX_CFG, MVS_RX_RING_SZ | RX_EN);

    mw32(MVS_PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN |
         PCS_CMD_EN | PCS_CMD_STOP_ERR);


    tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
           CINT_DMA_PCIE);

    mw32(MVS_INT_MASK, tmp);


    mw32(MVS_INT_MASK_SRS_0, 0xFFFF);

    return 0;
}