isci: cleanup silicon revision detection
Perform checking per-pci device (even though all systems will only have 1 pci device in this generation), and delete support for silicon that does not report a proper revision (i.e. A0). Reported-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
4e4dca3de9
commit
dc00c8b694
5 changed files with 31 additions and 73 deletions
|
@ -1886,6 +1886,7 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
|
||||||
static void sci_controller_afe_initialization(struct isci_host *ihost)
|
static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
{
|
{
|
||||||
const struct sci_oem_params *oem = &ihost->oem_parameters;
|
const struct sci_oem_params *oem = &ihost->oem_parameters;
|
||||||
|
struct pci_dev *pdev = ihost->pdev;
|
||||||
u32 afe_status;
|
u32 afe_status;
|
||||||
u32 phy_id;
|
u32 phy_id;
|
||||||
|
|
||||||
|
@ -1893,7 +1894,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
|
writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
|
||||||
if (is_b0()) {
|
if (is_b0(pdev)) {
|
||||||
/* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
|
/* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
|
||||||
* Timer, PM Stagger Timer */
|
* Timer, PM Stagger Timer */
|
||||||
writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2);
|
writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2);
|
||||||
|
@ -1901,17 +1902,15 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure bias currents to normal */
|
/* Configure bias currents to normal */
|
||||||
if (is_a0())
|
if (is_a2(pdev))
|
||||||
writel(0x00005500, &ihost->scu_registers->afe.afe_bias_control);
|
|
||||||
else if (is_a2())
|
|
||||||
writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
|
writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
|
||||||
else if (is_b0() || is_c0())
|
else if (is_b0(pdev) || is_c0(pdev))
|
||||||
writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
|
writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
|
||||||
|
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
|
||||||
/* Enable PLL */
|
/* Enable PLL */
|
||||||
if (is_b0() || is_c0())
|
if (is_b0(pdev) || is_c0(pdev))
|
||||||
writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
|
writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
|
||||||
else
|
else
|
||||||
writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
|
writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
|
||||||
|
@ -1924,7 +1923,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
} while ((afe_status & 0x00001000) == 0);
|
} while ((afe_status & 0x00001000) == 0);
|
||||||
|
|
||||||
if (is_a0() || is_a2()) {
|
if (is_a2(pdev)) {
|
||||||
/* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
|
/* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
|
||||||
writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
|
writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
@ -1933,11 +1932,11 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
|
for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
|
||||||
const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
|
const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
|
||||||
|
|
||||||
if (is_b0()) {
|
if (is_b0(pdev)) {
|
||||||
/* Configure transmitter SSC parameters */
|
/* Configure transmitter SSC parameters */
|
||||||
writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
} else if (is_c0()) {
|
} else if (is_c0(pdev)) {
|
||||||
/* Configure transmitter SSC parameters */
|
/* Configure transmitter SSC parameters */
|
||||||
writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
@ -1961,11 +1960,9 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
/*
|
/*
|
||||||
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
|
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
|
||||||
* & increase TX int & ext bias 20%....(0xe85c) */
|
* & increase TX int & ext bias 20%....(0xe85c) */
|
||||||
if (is_a0())
|
if (is_a2(pdev))
|
||||||
writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
|
||||||
else if (is_a2())
|
|
||||||
writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||||
else if (is_b0()) {
|
else if (is_b0(pdev)) {
|
||||||
/* Power down TX and RX (PWRDNTX and PWRDNRX) */
|
/* Power down TX and RX (PWRDNTX and PWRDNRX) */
|
||||||
writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
@ -1985,7 +1982,7 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
}
|
}
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
|
||||||
if (is_a0() || is_a2()) {
|
if (is_a2(pdev)) {
|
||||||
/* Enable TX equalization (0xe824) */
|
/* Enable TX equalization (0xe824) */
|
||||||
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
|
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
@ -1998,11 +1995,9 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
|
|
||||||
/* Leave DFE/FFE on */
|
/* Leave DFE/FFE on */
|
||||||
if (is_a0())
|
if (is_a2(pdev))
|
||||||
writel(0x3F09983F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
|
||||||
else if (is_a2())
|
|
||||||
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
||||||
else if (is_b0()) {
|
else if (is_b0(pdev)) {
|
||||||
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
|
||||||
udelay(AFE_REGISTER_WRITE_DELAY);
|
udelay(AFE_REGISTER_WRITE_DELAY);
|
||||||
/* Enable TX equalization (0xe824) */
|
/* Enable TX equalization (0xe824) */
|
||||||
|
|
|
@ -416,33 +416,25 @@ static inline struct device *scirdev_to_dev(struct isci_remote_device *idev)
|
||||||
return &idev->isci_port->isci_host->pdev->dev;
|
return &idev->isci_port->isci_host->pdev->dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
static inline bool is_a2(struct pci_dev *pdev)
|
||||||
ISCI_SI_REVA0,
|
|
||||||
ISCI_SI_REVA2,
|
|
||||||
ISCI_SI_REVB0,
|
|
||||||
ISCI_SI_REVC0
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int isci_si_rev;
|
|
||||||
|
|
||||||
static inline bool is_a0(void)
|
|
||||||
{
|
{
|
||||||
return isci_si_rev == ISCI_SI_REVA0;
|
if (pdev->revision < 4)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_a2(void)
|
static inline bool is_b0(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
return isci_si_rev == ISCI_SI_REVA2;
|
if (pdev->revision == 4)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_b0(void)
|
static inline bool is_c0(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
return isci_si_rev == ISCI_SI_REVB0;
|
if (pdev->revision >= 5)
|
||||||
}
|
return true;
|
||||||
|
return false;
|
||||||
static inline bool is_c0(void)
|
|
||||||
{
|
|
||||||
return isci_si_rev > ISCI_SI_REVB0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sci_controller_post_request(struct isci_host *ihost,
|
void sci_controller_post_request(struct isci_host *ihost,
|
||||||
|
|
|
@ -85,10 +85,6 @@ MODULE_DEVICE_TABLE(pci, isci_id_table);
|
||||||
|
|
||||||
/* linux isci specific settings */
|
/* linux isci specific settings */
|
||||||
|
|
||||||
int isci_si_rev = ISCI_SI_REVA2;
|
|
||||||
module_param(isci_si_rev, int, 0);
|
|
||||||
MODULE_PARM_DESC(isci_si_rev, "(deprecated) override default si rev (0: A0 1: A2 2: B0)");
|
|
||||||
|
|
||||||
unsigned char no_outbound_task_to = 20;
|
unsigned char no_outbound_task_to = 20;
|
||||||
module_param(no_outbound_task_to, byte, 0);
|
module_param(no_outbound_task_to, byte, 0);
|
||||||
MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
|
MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
|
||||||
|
@ -435,32 +431,6 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_si_rev(struct pci_dev *pdev)
|
|
||||||
{
|
|
||||||
switch (pdev->revision) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
/* if the id is ambiguous don't update isci_si_rev */
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
isci_si_rev = ISCI_SI_REVA2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
isci_si_rev = ISCI_SI_REVB0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case 5:
|
|
||||||
isci_si_rev = ISCI_SI_REVC0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n",
|
|
||||||
isci_si_rev == ISCI_SI_REVA0 ? "A0" :
|
|
||||||
isci_si_rev == ISCI_SI_REVA2 ? "A2" :
|
|
||||||
isci_si_rev == ISCI_SI_REVB0 ? "B0" : "C0", pdev->revision);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
{
|
{
|
||||||
struct isci_pci_info *pci_info;
|
struct isci_pci_info *pci_info;
|
||||||
|
@ -470,7 +440,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
|
||||||
struct isci_orom *orom = NULL;
|
struct isci_orom *orom = NULL;
|
||||||
char *source = "(platform)";
|
char *source = "(platform)";
|
||||||
|
|
||||||
check_si_rev(pdev);
|
dev_info(&pdev->dev, "driver configured for rev: %d silicon\n",
|
||||||
|
pdev->revision);
|
||||||
|
|
||||||
pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
|
pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
|
||||||
if (!pci_info)
|
if (!pci_info)
|
||||||
|
|
|
@ -211,7 +211,7 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
|
||||||
llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
|
llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
|
||||||
writel(llctl, &iphy->link_layer_registers->link_layer_control);
|
writel(llctl, &iphy->link_layer_registers->link_layer_control);
|
||||||
|
|
||||||
if (is_a0() || is_a2()) {
|
if (is_a2(ihost->pdev)) {
|
||||||
/* Program the max ARB time for the PHY to 700us so we inter-operate with
|
/* Program the max ARB time for the PHY to 700us so we inter-operate with
|
||||||
* the PMC expander which shuts down PHYs if the expander PHY generates too
|
* the PMC expander which shuts down PHYs if the expander PHY generates too
|
||||||
* many breaks. This time value will guarantee that the initiator PHY will
|
* many breaks. This time value will guarantee that the initiator PHY will
|
||||||
|
|
|
@ -146,13 +146,13 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw
|
||||||
|
|
||||||
memcpy(orom, fw->data, fw->size);
|
memcpy(orom, fw->data, fw->size);
|
||||||
|
|
||||||
|
if (is_c0(pdev))
|
||||||
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* deprecated: override default amp_control for pre-preproduction
|
* deprecated: override default amp_control for pre-preproduction
|
||||||
* silicon revisions
|
* silicon revisions
|
||||||
*/
|
*/
|
||||||
if (isci_si_rev <= ISCI_SI_REVB0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
|
for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
|
||||||
for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
|
for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
|
||||||
orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
|
orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
|
||||||
|
|
Loading…
Add table
Reference in a new issue