aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h3
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c20
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c39
3 files changed, 62 insertions, 0 deletions
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 4000de429430..e7fd2877c19c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -244,6 +244,8 @@ struct hisi_sas_hw {
244 struct domain_device *device); 244 struct domain_device *device);
245 int (*soft_reset)(struct hisi_hba *hisi_hba); 245 int (*soft_reset)(struct hisi_hba *hisi_hba);
246 u32 (*get_phys_state)(struct hisi_hba *hisi_hba); 246 u32 (*get_phys_state)(struct hisi_hba *hisi_hba);
247 int (*write_gpio)(struct hisi_hba *hisi_hba, u8 reg_type,
248 u8 reg_index, u8 reg_count, u8 *write_data);
247 int max_command_entries; 249 int max_command_entries;
248 int complete_hdr_size; 250 int complete_hdr_size;
249}; 251};
@@ -257,6 +259,7 @@ struct hisi_hba {
257 struct device *dev; 259 struct device *dev;
258 260
259 void __iomem *regs; 261 void __iomem *regs;
262 void __iomem *sgpio_regs;
260 struct regmap *ctrl; 263 struct regmap *ctrl;
261 u32 ctrl_reset_reg; 264 u32 ctrl_reset_reg;
262 u32 ctrl_reset_sts_reg; 265 u32 ctrl_reset_sts_reg;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index e3e7285f5eb1..791462d7fbfc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1634,6 +1634,18 @@ static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
1634{ 1634{
1635} 1635}
1636 1636
1637static int hisi_sas_write_gpio(struct sas_ha_struct *sha, u8 reg_type,
1638 u8 reg_index, u8 reg_count, u8 *write_data)
1639{
1640 struct hisi_hba *hisi_hba = sha->lldd_ha;
1641
1642 if (!hisi_hba->hw->write_gpio)
1643 return -EOPNOTSUPP;
1644
1645 return hisi_hba->hw->write_gpio(hisi_hba, reg_type,
1646 reg_index, reg_count, write_data);
1647}
1648
1637static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy) 1649static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
1638{ 1650{
1639 phy->phy_attached = 0; 1651 phy->phy_attached = 0;
@@ -1731,6 +1743,7 @@ static struct sas_domain_function_template hisi_sas_transport_ops = {
1731 .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha, 1743 .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha,
1732 .lldd_port_formed = hisi_sas_port_formed, 1744 .lldd_port_formed = hisi_sas_port_formed,
1733 .lldd_port_deformed = hisi_sas_port_deformed, 1745 .lldd_port_deformed = hisi_sas_port_deformed,
1746 .lldd_write_gpio = hisi_sas_write_gpio,
1734}; 1747};
1735 1748
1736void hisi_sas_init_mem(struct hisi_hba *hisi_hba) 1749void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
@@ -2055,6 +2068,13 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
2055 if (IS_ERR(hisi_hba->regs)) 2068 if (IS_ERR(hisi_hba->regs))
2056 goto err_out; 2069 goto err_out;
2057 2070
2071 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
2072 if (res) {
2073 hisi_hba->sgpio_regs = devm_ioremap_resource(dev, res);
2074 if (IS_ERR(hisi_hba->sgpio_regs))
2075 goto err_out;
2076 }
2077
2058 if (hisi_sas_alloc(hisi_hba, shost)) { 2078 if (hisi_sas_alloc(hisi_hba, shost)) {
2059 hisi_sas_free(hisi_hba); 2079 hisi_sas_free(hisi_hba);
2060 goto err_out; 2080 goto err_out;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index ebee2e463245..4ccb61e2ae5c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -3474,6 +3474,44 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
3474 return 0; 3474 return 0;
3475} 3475}
3476 3476
3477static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
3478 u8 reg_index, u8 reg_count, u8 *write_data)
3479{
3480 struct device *dev = hisi_hba->dev;
3481 int phy_no, count;
3482
3483 if (!hisi_hba->sgpio_regs)
3484 return -EOPNOTSUPP;
3485
3486 switch (reg_type) {
3487 case SAS_GPIO_REG_TX:
3488 count = reg_count * 4;
3489 count = min(count, hisi_hba->n_phy);
3490
3491 for (phy_no = 0; phy_no < count; phy_no++) {
3492 /*
3493 * GPIO_TX[n] register has the highest numbered drive
3494 * of the four in the first byte and the lowest
3495 * numbered drive in the fourth byte.
3496 * See SFF-8485 Rev. 0.7 Table 24.
3497 */
3498 void __iomem *reg_addr = hisi_hba->sgpio_regs +
3499 reg_index * 4 + phy_no;
3500 int data_idx = phy_no + 3 - (phy_no % 4) * 2;
3501
3502 writeb(write_data[data_idx], reg_addr);
3503 }
3504
3505 break;
3506 default:
3507 dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
3508 reg_type);
3509 return -EINVAL;
3510 }
3511
3512 return 0;
3513}
3514
3477static const struct hisi_sas_hw hisi_sas_v2_hw = { 3515static const struct hisi_sas_hw hisi_sas_v2_hw = {
3478 .hw_init = hisi_sas_v2_init, 3516 .hw_init = hisi_sas_v2_init,
3479 .setup_itct = setup_itct_v2_hw, 3517 .setup_itct = setup_itct_v2_hw,
@@ -3501,6 +3539,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
3501 .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr), 3539 .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr),
3502 .soft_reset = soft_reset_v2_hw, 3540 .soft_reset = soft_reset_v2_hw,
3503 .get_phys_state = get_phys_state_v2_hw, 3541 .get_phys_state = get_phys_state_v2_hw,
3542 .write_gpio = write_gpio_v2_hw,
3504}; 3543};
3505 3544
3506static int hisi_sas_v2_probe(struct platform_device *pdev) 3545static int hisi_sas_v2_probe(struct platform_device *pdev)