diff options
| -rw-r--r-- | drivers/ata/ahci_imx.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index 1c69e88c5a13..6822e2f33f7e 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
| 24 | #include <linux/ahci_platform.h> | 24 | #include <linux/ahci_platform.h> |
| 25 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
| 26 | #include <linux/of_gpio.h> | ||
| 26 | #include <linux/mfd/syscon.h> | 27 | #include <linux/mfd/syscon.h> |
| 27 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> | 28 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> |
| 28 | #include <linux/libata.h> | 29 | #include <linux/libata.h> |
| @@ -53,12 +54,49 @@ enum { | |||
| 53 | /* Clock Reset Register */ | 54 | /* Clock Reset Register */ |
| 54 | IMX_CLOCK_RESET = 0x7f3f, | 55 | IMX_CLOCK_RESET = 0x7f3f, |
| 55 | IMX_CLOCK_RESET_RESET = 1 << 0, | 56 | IMX_CLOCK_RESET_RESET = 1 << 0, |
| 57 | /* IMX8QM HSIO AHCI definitions */ | ||
| 58 | IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET = 0x03, | ||
| 59 | IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET = 0x09, | ||
| 60 | IMX8QM_SATA_PHY_IMPED_RATIO_85OHM = 0x6c, | ||
| 61 | IMX8QM_LPCG_PHYX2_OFFSET = 0x00000, | ||
| 62 | IMX8QM_CSR_PHYX2_OFFSET = 0x90000, | ||
| 63 | IMX8QM_CSR_PHYX1_OFFSET = 0xa0000, | ||
| 64 | IMX8QM_CSR_PHYX_STTS0_OFFSET = 0x4, | ||
| 65 | IMX8QM_CSR_PCIEA_OFFSET = 0xb0000, | ||
| 66 | IMX8QM_CSR_PCIEB_OFFSET = 0xc0000, | ||
| 67 | IMX8QM_CSR_SATA_OFFSET = 0xd0000, | ||
| 68 | IMX8QM_CSR_PCIE_CTRL2_OFFSET = 0x8, | ||
| 69 | IMX8QM_CSR_MISC_OFFSET = 0xe0000, | ||
| 70 | |||
| 71 | IMX8QM_LPCG_PHYX2_PCLK0_MASK = (0x3 << 16), | ||
| 72 | IMX8QM_LPCG_PHYX2_PCLK1_MASK = (0x3 << 20), | ||
| 73 | IMX8QM_PHY_APB_RSTN_0 = BIT(0), | ||
| 74 | IMX8QM_PHY_MODE_SATA = BIT(19), | ||
| 75 | IMX8QM_PHY_MODE_MASK = (0xf << 17), | ||
| 76 | IMX8QM_PHY_PIPE_RSTN_0 = BIT(24), | ||
| 77 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0 = BIT(25), | ||
| 78 | IMX8QM_PHY_PIPE_RSTN_1 = BIT(26), | ||
| 79 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1 = BIT(27), | ||
| 80 | IMX8QM_STTS0_LANE0_TX_PLL_LOCK = BIT(4), | ||
| 81 | IMX8QM_MISC_IOB_RXENA = BIT(0), | ||
| 82 | IMX8QM_MISC_IOB_TXENA = BIT(1), | ||
| 83 | IMX8QM_MISC_PHYX1_EPCS_SEL = BIT(12), | ||
| 84 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 = BIT(24), | ||
| 85 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 = BIT(25), | ||
| 86 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 = BIT(28), | ||
| 87 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0 = BIT(29), | ||
| 88 | IMX8QM_SATA_CTRL_RESET_N = BIT(12), | ||
| 89 | IMX8QM_SATA_CTRL_EPCS_PHYRESET_N = BIT(7), | ||
| 90 | IMX8QM_CTRL_BUTTON_RST_N = BIT(21), | ||
| 91 | IMX8QM_CTRL_POWER_UP_RST_N = BIT(23), | ||
| 92 | IMX8QM_CTRL_LTSSM_ENABLE = BIT(4), | ||
| 56 | }; | 93 | }; |
| 57 | 94 | ||
| 58 | enum ahci_imx_type { | 95 | enum ahci_imx_type { |
| 59 | AHCI_IMX53, | 96 | AHCI_IMX53, |
| 60 | AHCI_IMX6Q, | 97 | AHCI_IMX6Q, |
| 61 | AHCI_IMX6QP, | 98 | AHCI_IMX6QP, |
| 99 | AHCI_IMX8QM, | ||
| 62 | }; | 100 | }; |
| 63 | 101 | ||
| 64 | struct imx_ahci_priv { | 102 | struct imx_ahci_priv { |
| @@ -67,10 +105,18 @@ struct imx_ahci_priv { | |||
| 67 | struct clk *sata_clk; | 105 | struct clk *sata_clk; |
| 68 | struct clk *sata_ref_clk; | 106 | struct clk *sata_ref_clk; |
| 69 | struct clk *ahb_clk; | 107 | struct clk *ahb_clk; |
| 108 | struct clk *epcs_tx_clk; | ||
| 109 | struct clk *epcs_rx_clk; | ||
| 110 | struct clk *phy_apbclk; | ||
| 111 | struct clk *phy_pclk0; | ||
| 112 | struct clk *phy_pclk1; | ||
| 113 | void __iomem *phy_base; | ||
| 114 | int clkreq_gpio; | ||
| 70 | struct regmap *gpr; | 115 | struct regmap *gpr; |
| 71 | bool no_device; | 116 | bool no_device; |
| 72 | bool first_time; | 117 | bool first_time; |
| 73 | u32 phy_params; | 118 | u32 phy_params; |
| 119 | u32 imped_ratio; | ||
| 74 | }; | 120 | }; |
| 75 | 121 | ||
| 76 | static int ahci_imx_hotplug; | 122 | static int ahci_imx_hotplug; |
| @@ -407,6 +453,207 @@ static struct attribute *fsl_sata_ahci_attrs[] = { | |||
| 407 | }; | 453 | }; |
| 408 | ATTRIBUTE_GROUPS(fsl_sata_ahci); | 454 | ATTRIBUTE_GROUPS(fsl_sata_ahci); |
| 409 | 455 | ||
| 456 | static int imx8_sata_enable(struct ahci_host_priv *hpriv) | ||
| 457 | { | ||
| 458 | u32 val, reg; | ||
| 459 | int i, ret; | ||
| 460 | struct imx_ahci_priv *imxpriv = hpriv->plat_data; | ||
| 461 | struct device *dev = &imxpriv->ahci_pdev->dev; | ||
| 462 | |||
| 463 | /* configure the hsio for sata */ | ||
| 464 | ret = clk_prepare_enable(imxpriv->phy_pclk0); | ||
| 465 | if (ret < 0) { | ||
| 466 | dev_err(dev, "can't enable phy_pclk0.\n"); | ||
| 467 | return ret; | ||
| 468 | } | ||
| 469 | ret = clk_prepare_enable(imxpriv->phy_pclk1); | ||
| 470 | if (ret < 0) { | ||
| 471 | dev_err(dev, "can't enable phy_pclk1.\n"); | ||
| 472 | goto disable_phy_pclk0; | ||
| 473 | } | ||
| 474 | ret = clk_prepare_enable(imxpriv->epcs_tx_clk); | ||
| 475 | if (ret < 0) { | ||
| 476 | dev_err(dev, "can't enable epcs_tx_clk.\n"); | ||
| 477 | goto disable_phy_pclk1; | ||
| 478 | } | ||
| 479 | ret = clk_prepare_enable(imxpriv->epcs_rx_clk); | ||
| 480 | if (ret < 0) { | ||
| 481 | dev_err(dev, "can't enable epcs_rx_clk.\n"); | ||
| 482 | goto disable_epcs_tx_clk; | ||
| 483 | } | ||
| 484 | ret = clk_prepare_enable(imxpriv->phy_apbclk); | ||
| 485 | if (ret < 0) { | ||
| 486 | dev_err(dev, "can't enable phy_apbclk.\n"); | ||
| 487 | goto disable_epcs_rx_clk; | ||
| 488 | } | ||
| 489 | /* Configure PHYx2 PIPE_RSTN */ | ||
| 490 | regmap_read(imxpriv->gpr, IMX8QM_CSR_PCIEA_OFFSET + | ||
| 491 | IMX8QM_CSR_PCIE_CTRL2_OFFSET, &val); | ||
| 492 | if ((val & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { | ||
| 493 | /* The link of the PCIEA of HSIO is down */ | ||
| 494 | regmap_update_bits(imxpriv->gpr, | ||
| 495 | IMX8QM_CSR_PHYX2_OFFSET, | ||
| 496 | IMX8QM_PHY_PIPE_RSTN_0 | | ||
| 497 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0, | ||
| 498 | IMX8QM_PHY_PIPE_RSTN_0 | | ||
| 499 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_0); | ||
| 500 | } | ||
| 501 | regmap_read(imxpriv->gpr, IMX8QM_CSR_PCIEB_OFFSET + | ||
| 502 | IMX8QM_CSR_PCIE_CTRL2_OFFSET, ®); | ||
| 503 | if ((reg & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { | ||
| 504 | /* The link of the PCIEB of HSIO is down */ | ||
| 505 | regmap_update_bits(imxpriv->gpr, | ||
| 506 | IMX8QM_CSR_PHYX2_OFFSET, | ||
| 507 | IMX8QM_PHY_PIPE_RSTN_1 | | ||
| 508 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1, | ||
| 509 | IMX8QM_PHY_PIPE_RSTN_1 | | ||
| 510 | IMX8QM_PHY_PIPE_RSTN_OVERRIDE_1); | ||
| 511 | } | ||
| 512 | if (((reg | val) & IMX8QM_CTRL_LTSSM_ENABLE) == 0) { | ||
| 513 | /* The links of both PCIA and PCIEB of HSIO are down */ | ||
| 514 | regmap_update_bits(imxpriv->gpr, | ||
| 515 | IMX8QM_LPCG_PHYX2_OFFSET, | ||
| 516 | IMX8QM_LPCG_PHYX2_PCLK0_MASK | | ||
| 517 | IMX8QM_LPCG_PHYX2_PCLK1_MASK, | ||
| 518 | 0); | ||
| 519 | } | ||
| 520 | |||
| 521 | /* set PWR_RST and BT_RST of csr_pciea */ | ||
| 522 | val = IMX8QM_CSR_PCIEA_OFFSET + IMX8QM_CSR_PCIE_CTRL2_OFFSET; | ||
| 523 | regmap_update_bits(imxpriv->gpr, | ||
| 524 | val, | ||
| 525 | IMX8QM_CTRL_BUTTON_RST_N, | ||
| 526 | IMX8QM_CTRL_BUTTON_RST_N); | ||
| 527 | regmap_update_bits(imxpriv->gpr, | ||
| 528 | val, | ||
| 529 | IMX8QM_CTRL_POWER_UP_RST_N, | ||
| 530 | IMX8QM_CTRL_POWER_UP_RST_N); | ||
| 531 | |||
| 532 | /* PHYX1_MODE to SATA */ | ||
| 533 | regmap_update_bits(imxpriv->gpr, | ||
| 534 | IMX8QM_CSR_PHYX1_OFFSET, | ||
| 535 | IMX8QM_PHY_MODE_MASK, | ||
| 536 | IMX8QM_PHY_MODE_SATA); | ||
| 537 | |||
| 538 | /* | ||
| 539 | * BIT0 RXENA 1, BIT1 TXENA 0 | ||
| 540 | * BIT12 PHY_X1_EPCS_SEL 1. | ||
| 541 | */ | ||
| 542 | regmap_update_bits(imxpriv->gpr, | ||
| 543 | IMX8QM_CSR_MISC_OFFSET, | ||
| 544 | IMX8QM_MISC_IOB_RXENA, | ||
| 545 | IMX8QM_MISC_IOB_RXENA); | ||
| 546 | regmap_update_bits(imxpriv->gpr, | ||
| 547 | IMX8QM_CSR_MISC_OFFSET, | ||
| 548 | IMX8QM_MISC_IOB_TXENA, | ||
| 549 | 0); | ||
| 550 | regmap_update_bits(imxpriv->gpr, | ||
| 551 | IMX8QM_CSR_MISC_OFFSET, | ||
| 552 | IMX8QM_MISC_PHYX1_EPCS_SEL, | ||
| 553 | IMX8QM_MISC_PHYX1_EPCS_SEL); | ||
| 554 | /* | ||
| 555 | * It is possible, for PCIe and SATA are sharing | ||
| 556 | * the same clock source, HPLL or external oscillator. | ||
| 557 | * When PCIe is in low power modes (L1.X or L2 etc), | ||
| 558 | * the clock source can be turned off. In this case, | ||
| 559 | * if this clock source is required to be toggling by | ||
| 560 | * SATA, then SATA functions will be abnormal. | ||
| 561 | * Set the override here to avoid it. | ||
| 562 | */ | ||
| 563 | regmap_update_bits(imxpriv->gpr, | ||
| 564 | IMX8QM_CSR_MISC_OFFSET, | ||
| 565 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 | | ||
| 566 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 | | ||
| 567 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 | | ||
| 568 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0, | ||
| 569 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_1 | | ||
| 570 | IMX8QM_MISC_CLKREQN_OUT_OVERRIDE_0 | | ||
| 571 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_1 | | ||
| 572 | IMX8QM_MISC_CLKREQN_IN_OVERRIDE_0); | ||
| 573 | |||
| 574 | /* clear PHY RST, then set it */ | ||
| 575 | regmap_update_bits(imxpriv->gpr, | ||
| 576 | IMX8QM_CSR_SATA_OFFSET, | ||
| 577 | IMX8QM_SATA_CTRL_EPCS_PHYRESET_N, | ||
| 578 | 0); | ||
| 579 | |||
| 580 | regmap_update_bits(imxpriv->gpr, | ||
| 581 | IMX8QM_CSR_SATA_OFFSET, | ||
| 582 | IMX8QM_SATA_CTRL_EPCS_PHYRESET_N, | ||
| 583 | IMX8QM_SATA_CTRL_EPCS_PHYRESET_N); | ||
| 584 | |||
| 585 | /* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */ | ||
| 586 | regmap_update_bits(imxpriv->gpr, | ||
| 587 | IMX8QM_CSR_SATA_OFFSET, | ||
| 588 | IMX8QM_SATA_CTRL_RESET_N, | ||
| 589 | IMX8QM_SATA_CTRL_RESET_N); | ||
| 590 | udelay(1); | ||
| 591 | regmap_update_bits(imxpriv->gpr, | ||
| 592 | IMX8QM_CSR_SATA_OFFSET, | ||
| 593 | IMX8QM_SATA_CTRL_RESET_N, | ||
| 594 | 0); | ||
| 595 | regmap_update_bits(imxpriv->gpr, | ||
| 596 | IMX8QM_CSR_SATA_OFFSET, | ||
| 597 | IMX8QM_SATA_CTRL_RESET_N, | ||
| 598 | IMX8QM_SATA_CTRL_RESET_N); | ||
| 599 | |||
| 600 | /* APB reset */ | ||
| 601 | regmap_update_bits(imxpriv->gpr, | ||
| 602 | IMX8QM_CSR_PHYX1_OFFSET, | ||
| 603 | IMX8QM_PHY_APB_RSTN_0, | ||
| 604 | IMX8QM_PHY_APB_RSTN_0); | ||
| 605 | |||
| 606 | for (i = 0; i < 100; i++) { | ||
| 607 | reg = IMX8QM_CSR_PHYX1_OFFSET + | ||
| 608 | IMX8QM_CSR_PHYX_STTS0_OFFSET; | ||
| 609 | regmap_read(imxpriv->gpr, reg, &val); | ||
| 610 | val &= IMX8QM_STTS0_LANE0_TX_PLL_LOCK; | ||
| 611 | if (val == IMX8QM_STTS0_LANE0_TX_PLL_LOCK) | ||
| 612 | break; | ||
| 613 | udelay(1); | ||
| 614 | } | ||
| 615 | |||
| 616 | if (val != IMX8QM_STTS0_LANE0_TX_PLL_LOCK) { | ||
| 617 | dev_err(dev, "TX PLL of the PHY is not locked\n"); | ||
| 618 | ret = -ENODEV; | ||
| 619 | } else { | ||
| 620 | writeb(imxpriv->imped_ratio, imxpriv->phy_base + | ||
| 621 | IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET); | ||
| 622 | writeb(imxpriv->imped_ratio, imxpriv->phy_base + | ||
| 623 | IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET); | ||
| 624 | reg = readb(imxpriv->phy_base + | ||
| 625 | IMX8QM_SATA_PHY_RX_IMPED_RATIO_OFFSET); | ||
| 626 | if (unlikely(reg != imxpriv->imped_ratio)) | ||
| 627 | dev_info(dev, "Can't set PHY RX impedance ratio.\n"); | ||
| 628 | reg = readb(imxpriv->phy_base + | ||
| 629 | IMX8QM_SATA_PHY_TX_IMPED_RATIO_OFFSET); | ||
| 630 | if (unlikely(reg != imxpriv->imped_ratio)) | ||
| 631 | dev_info(dev, "Can't set PHY TX impedance ratio.\n"); | ||
| 632 | usleep_range(50, 100); | ||
| 633 | |||
| 634 | /* | ||
| 635 | * To reduce the power consumption, gate off | ||
| 636 | * the PHY clks | ||
| 637 | */ | ||
| 638 | clk_disable_unprepare(imxpriv->phy_apbclk); | ||
| 639 | clk_disable_unprepare(imxpriv->phy_pclk1); | ||
| 640 | clk_disable_unprepare(imxpriv->phy_pclk0); | ||
| 641 | return ret; | ||
| 642 | } | ||
| 643 | |||
| 644 | clk_disable_unprepare(imxpriv->phy_apbclk); | ||
| 645 | disable_epcs_rx_clk: | ||
| 646 | clk_disable_unprepare(imxpriv->epcs_rx_clk); | ||
| 647 | disable_epcs_tx_clk: | ||
| 648 | clk_disable_unprepare(imxpriv->epcs_tx_clk); | ||
| 649 | disable_phy_pclk1: | ||
| 650 | clk_disable_unprepare(imxpriv->phy_pclk1); | ||
| 651 | disable_phy_pclk0: | ||
| 652 | clk_disable_unprepare(imxpriv->phy_pclk0); | ||
| 653 | |||
| 654 | return ret; | ||
| 655 | } | ||
| 656 | |||
| 410 | static int imx_sata_enable(struct ahci_host_priv *hpriv) | 657 | static int imx_sata_enable(struct ahci_host_priv *hpriv) |
| 411 | { | 658 | { |
| 412 | struct imx_ahci_priv *imxpriv = hpriv->plat_data; | 659 | struct imx_ahci_priv *imxpriv = hpriv->plat_data; |
| @@ -454,6 +701,8 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv) | |||
| 454 | dev_err(dev, "failed to reset phy: %d\n", ret); | 701 | dev_err(dev, "failed to reset phy: %d\n", ret); |
| 455 | goto disable_clk; | 702 | goto disable_clk; |
| 456 | } | 703 | } |
| 704 | } else if (imxpriv->type == AHCI_IMX8QM) { | ||
| 705 | ret = imx8_sata_enable(hpriv); | ||
| 457 | } | 706 | } |
| 458 | 707 | ||
| 459 | usleep_range(1000, 2000); | 708 | usleep_range(1000, 2000); |
| @@ -491,6 +740,11 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv) | |||
| 491 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); | 740 | !IMX6Q_GPR13_SATA_MPLL_CLK_EN); |
| 492 | break; | 741 | break; |
| 493 | 742 | ||
| 743 | case AHCI_IMX8QM: | ||
| 744 | clk_disable_unprepare(imxpriv->epcs_rx_clk); | ||
| 745 | clk_disable_unprepare(imxpriv->epcs_tx_clk); | ||
| 746 | break; | ||
| 747 | |||
| 494 | default: | 748 | default: |
| 495 | break; | 749 | break; |
| 496 | } | 750 | } |
| @@ -567,6 +821,7 @@ static const struct of_device_id imx_ahci_of_match[] = { | |||
| 567 | { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, | 821 | { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, |
| 568 | { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, | 822 | { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, |
| 569 | { .compatible = "fsl,imx6qp-ahci", .data = (void *)AHCI_IMX6QP }, | 823 | { .compatible = "fsl,imx6qp-ahci", .data = (void *)AHCI_IMX6QP }, |
| 824 | { .compatible = "fsl,imx8qm-ahci", .data = (void *)AHCI_IMX8QM }, | ||
| 570 | {}, | 825 | {}, |
| 571 | }; | 826 | }; |
| 572 | MODULE_DEVICE_TABLE(of, imx_ahci_of_match); | 827 | MODULE_DEVICE_TABLE(of, imx_ahci_of_match); |
| @@ -734,6 +989,79 @@ static struct scsi_host_template ahci_platform_sht = { | |||
| 734 | AHCI_SHT(DRV_NAME), | 989 | AHCI_SHT(DRV_NAME), |
| 735 | }; | 990 | }; |
| 736 | 991 | ||
| 992 | static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv) | ||
| 993 | { | ||
| 994 | int ret; | ||
| 995 | struct resource *phy_res; | ||
| 996 | struct platform_device *pdev = imxpriv->ahci_pdev; | ||
| 997 | struct device_node *np = dev->of_node; | ||
| 998 | |||
| 999 | if (of_property_read_u32(np, "fsl,phy-imp", &imxpriv->imped_ratio)) | ||
| 1000 | imxpriv->imped_ratio = IMX8QM_SATA_PHY_IMPED_RATIO_85OHM; | ||
| 1001 | phy_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); | ||
| 1002 | if (phy_res) { | ||
| 1003 | imxpriv->phy_base = devm_ioremap(dev, phy_res->start, | ||
| 1004 | resource_size(phy_res)); | ||
| 1005 | if (!imxpriv->phy_base) { | ||
| 1006 | dev_err(dev, "error with ioremap\n"); | ||
| 1007 | return -ENOMEM; | ||
| 1008 | } | ||
| 1009 | } else { | ||
| 1010 | dev_err(dev, "missing *phy* reg region.\n"); | ||
| 1011 | return -ENOMEM; | ||
| 1012 | } | ||
| 1013 | imxpriv->gpr = | ||
| 1014 | syscon_regmap_lookup_by_phandle(np, "hsio"); | ||
| 1015 | if (IS_ERR(imxpriv->gpr)) { | ||
| 1016 | dev_err(dev, "unable to find gpr registers\n"); | ||
| 1017 | return PTR_ERR(imxpriv->gpr); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | imxpriv->epcs_tx_clk = devm_clk_get(dev, "epcs_tx"); | ||
| 1021 | if (IS_ERR(imxpriv->epcs_tx_clk)) { | ||
| 1022 | dev_err(dev, "can't get epcs_tx_clk clock.\n"); | ||
| 1023 | return PTR_ERR(imxpriv->epcs_tx_clk); | ||
| 1024 | } | ||
| 1025 | imxpriv->epcs_rx_clk = devm_clk_get(dev, "epcs_rx"); | ||
| 1026 | if (IS_ERR(imxpriv->epcs_rx_clk)) { | ||
| 1027 | dev_err(dev, "can't get epcs_rx_clk clock.\n"); | ||
| 1028 | return PTR_ERR(imxpriv->epcs_rx_clk); | ||
| 1029 | } | ||
| 1030 | imxpriv->phy_pclk0 = devm_clk_get(dev, "phy_pclk0"); | ||
| 1031 | if (IS_ERR(imxpriv->phy_pclk0)) { | ||
| 1032 | dev_err(dev, "can't get phy_pclk0 clock.\n"); | ||
| 1033 | return PTR_ERR(imxpriv->phy_pclk0); | ||
| 1034 | } | ||
| 1035 | imxpriv->phy_pclk1 = devm_clk_get(dev, "phy_pclk1"); | ||
| 1036 | if (IS_ERR(imxpriv->phy_pclk1)) { | ||
| 1037 | dev_err(dev, "can't get phy_pclk1 clock.\n"); | ||
| 1038 | return PTR_ERR(imxpriv->phy_pclk1); | ||
| 1039 | } | ||
| 1040 | imxpriv->phy_apbclk = devm_clk_get(dev, "phy_apbclk"); | ||
| 1041 | if (IS_ERR(imxpriv->phy_apbclk)) { | ||
| 1042 | dev_err(dev, "can't get phy_apbclk clock.\n"); | ||
| 1043 | return PTR_ERR(imxpriv->phy_apbclk); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* Fetch GPIO, then enable the external OSC */ | ||
| 1047 | imxpriv->clkreq_gpio = of_get_named_gpio(np, "clkreq-gpio", 0); | ||
| 1048 | if (gpio_is_valid(imxpriv->clkreq_gpio)) { | ||
| 1049 | ret = devm_gpio_request_one(dev, imxpriv->clkreq_gpio, | ||
| 1050 | GPIOF_OUT_INIT_LOW, | ||
| 1051 | "SATA CLKREQ"); | ||
| 1052 | if (ret == -EBUSY) { | ||
| 1053 | dev_info(dev, "clkreq had been initialized.\n"); | ||
| 1054 | } else if (ret) { | ||
| 1055 | dev_err(dev, "%d unable to get clkreq.\n", ret); | ||
| 1056 | return ret; | ||
| 1057 | } | ||
| 1058 | } else if (imxpriv->clkreq_gpio == -EPROBE_DEFER) { | ||
| 1059 | return imxpriv->clkreq_gpio; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | return 0; | ||
| 1063 | } | ||
| 1064 | |||
| 737 | static int imx_ahci_probe(struct platform_device *pdev) | 1065 | static int imx_ahci_probe(struct platform_device *pdev) |
| 738 | { | 1066 | { |
| 739 | struct device *dev = &pdev->dev; | 1067 | struct device *dev = &pdev->dev; |
| @@ -793,6 +1121,10 @@ static int imx_ahci_probe(struct platform_device *pdev) | |||
| 793 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | | 1121 | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | |
| 794 | IMX6Q_GPR13_SATA_SPD_MODE_3P0G | | 1122 | IMX6Q_GPR13_SATA_SPD_MODE_3P0G | |
| 795 | reg_value; | 1123 | reg_value; |
| 1124 | } else if (imxpriv->type == AHCI_IMX8QM) { | ||
| 1125 | ret = imx8_sata_probe(dev, imxpriv); | ||
| 1126 | if (ret) | ||
| 1127 | return ret; | ||
| 796 | } | 1128 | } |
| 797 | 1129 | ||
| 798 | hpriv = ahci_platform_get_resources(pdev); | 1130 | hpriv = ahci_platform_get_resources(pdev); |
