aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiaofei Tan <tanxiaofei@huawei.com>2018-01-17 11:46:53 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2018-01-22 20:03:59 -0500
commit6379c56070b9ee32ae2b3efa51e121242042e72d (patch)
tree333622491f3425dd5643ec103cb7175aca9c9796
parent56ad7fcd4f058f74db8f4b08dd4e61a52bd8feba (diff)
scsi: hisi_sas: directly attached disk LED feature for v2 hw
This patch implements LED feature of directly attached disk for v2 hw. As libsas has provided an interface lldd_write_gpio() for this feature, we just need realise the interface following SPGIO API. We use an CPLD to finish the hardware part of this feature, and the base address of CPLD should be configured through ACPI or DT tables. Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-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)