Loading arch/arm/boot/dts/qcom/msm8996.dtsi +126 −0 Original line number Diff line number Diff line Loading @@ -2560,6 +2560,132 @@ qcom,ipa-advertise-sg-support; }; pcie_ep: qcom,pcie-ep@00600000 { compatible = "qcom,pcie-ep"; reg = <0x0c001000 0x1000>, <0x0c000000 0xf1d>, <0x0c000f20 0xa8>, <0x00600000 0x2000>, <0x00034000 0x4000>, <0x00607000 0x1000>; reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio"; #address-cells = <0>; interrupt-parent = <&pcie_ep>; interrupts = <0 1 2 3 4>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; interrupt-map = <0 &intc 0 0 247 0 1 &intc 0 0 249 0 2 &intc 0 0 253 0 3 &intc 0 0 254 0 4 &intc 0 0 49 0>; interrupt-names ="int_pm_turnoff", "int_dstate_change", "int_link_up", "int_link_down", "int_global"; pinctrl-names = "default"; pinctrl-0 = <&pcie0_clkreq_default &pcie0_perst_default &pcie0_wake_default>; clkreq-gpio = <&tlmm 36 0>; perst-gpio = <&tlmm 35 0>; wake-gpio = <&tlmm 37 0>; gdsc-vdd-supply = <&gdsc_pcie_0>; vreg-1.8-supply = <&pm8994_l12>; vreg-0.9-supply = <&pm8994_l28>; qcom,vreg-0.9-voltage-level = <925000 925000 24000>; clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>, <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>, <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>, <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>, <&clock_gcc clk_gcc_pcie_0_aux_clk>, <&clock_gcc clk_gcc_pcie_clkref_clk>, <&clock_gcc clk_gcc_pcie_phy_reset>, <&clock_gcc clk_gcc_pcie_phy_cfg_ahb_clk>, <&clock_gcc clk_gcc_pcie_phy_aux_clk>; clock-names = "pcie_0_pipe_clk", "pcie_0_cfg_ahb_clk", "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk", "pcie_0_aux_clk", "pcie_0_ldo", "pcie_0_phy_reset", "pcie_0_phy_cfg_ahb_clk", "pcie_0_phy_aux_clk"; resets = <&clock_gcc PCIE_PHY_BCR>, <&clock_gcc PCIE_PHY_COM_BCR>, <&clock_gcc PCIE_PHY_NOCSR_COM_PHY_BCR>, <&clock_gcc PCIE_0_PHY_BCR>; reset-names = "pcie_phy_reset", "pcie_phy_com_reset", "pcie_phy_nocsr_com_phy_reset","pcie_0_phy_reset"; max-clock-frequency-hz = <0>, <0>, <0>, <0>, <1010526>, <0>, <0>, <0>, <0>; qcom,msm-bus,name = "pcie-ep"; qcom,msm-bus,num-cases = <2>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <45 512 0 0>, <45 512 500 800>; qcom,pcie-link-speed = <0>; qcom,pcie-phy-ver = <4>; qcom,pcie-perst-enum; qcom,phy-status-reg = <0x448>; qcom,phy-sequence = <0x400 0x01 0x00 0x404 0x01 0x00 0x00AC 0x00 0x00 0x0034 0x18 0x00 0x0174 0x30 0x00 0x00B4 0x20 0x00 0x1094 0x06 0x00 0x00D0 0x19 0x00 0x0078 0x3F 0x00 0x0084 0x1A 0x00 0x0090 0x00 0x00 0x010C 0x00 0x00 0x0108 0xFF 0x00 0x019C 0x01 0x00 0x018C 0x00 0x00 0x0050 0x04 0x00 0x004C 0xff 0x00 0x00C8 0x42 0x00 0x0128 0x00 0x00 0x0148 0x3f 0x00 0x0144 0xff 0x00 0x000C 0x01 0x00 0x0070 0x0f 0x00 0x0048 0x0f 0x00 0x1248 0x4B 0x00 0x120C 0x0A 0x00 0x1200 0x0A 0x00 0x121C 0x04 0x00 0x1210 0x04 0x00 0x12D8 0x01 0x00 0x12DC 0x00 0x00 0x12E0 0xDB 0x00 0x12D4 0x77 0x00 0x130C 0x80 0x00 0x1310 0x1C 0x00 0x1314 0x03 0x00 0x131C 0x14 0x00 0x1054 0x02 0x00 0x1068 0x45 0x00 0x10AC 0x12 0x00 0x0194 0x06 0x00 0x1454 0x00 0x00 0x1404 0x00 0x00 0x400 0x00 0x00 0x408 0x03 0x00>; status = "disabled"; }; qcom_rng: qrng@83000 { compatible = "qcom,msm-rng"; reg = <0x83000 0x1000>; Loading drivers/platform/msm/ep_pcie/ep_pcie_com.h +22 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -101,6 +101,14 @@ #define PCIE20_AUX_CLK_FREQ_REG 0xB40 #define PCIE20_MHISTATUS 0x148 #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174 #define PCIE20_PARF_CFG_BITS 0x210 #define PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3C #define PCIE20_DEVICE_ID_VENDOR_ID_REG 0x0 #define PCIE20_L1_SUBSTATES_REG 0xB44 #define PERST_TIMEOUT_US_MIN 1000 #define PERST_TIMEOUT_US_MAX 1000 #define PERST_CHECK_MAX_COUNT 30000 Loading @@ -126,7 +134,7 @@ #define EP_PCIE_LOG_PAGES 50 #define EP_PCIE_MAX_VREG 2 #define EP_PCIE_MAX_CLK 6 #define EP_PCIE_MAX_CLK 8 #define EP_PCIE_MAX_PIPE_CLK 1 #define EP_PCIE_ERROR -30655 Loading Loading @@ -255,6 +263,12 @@ struct ep_pcie_irq_info_t { u32 num; }; struct ep_pcie_phy_info_t { u32 offset; u32 val; u32 delay; }; /* pcie endpoint device structure */ struct ep_pcie_dev_t { struct platform_device *pdev; Loading @@ -278,6 +292,9 @@ struct ep_pcie_dev_t { u32 link_speed; bool active_config; bool aggregated_irq; u32 phy_status_reg; u32 phy_len; struct ep_pcie_phy_info_t *phy_sequence; u32 rev; u32 phy_rev; Loading Loading @@ -356,5 +373,7 @@ extern bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev); extern void ep_pcie_reg_dump(struct ep_pcie_dev_t *dev, u32 sel, bool linkdown); extern void ep_pcie_debugfs_init(struct ep_pcie_dev_t *ep_dev); extern void ep_pcie_debugfs_exit(void); #ifdef CONFIG_ARCH_MSM8996 extern void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev); #endif #endif drivers/platform/msm/ep_pcie/ep_pcie_core.c +161 −7 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -64,7 +64,9 @@ static struct ep_pcie_clk_info_t {NULL, "pcie_0_slv_axi_clk", 0, true}, {NULL, "pcie_0_aux_clk", 1000000, true}, {NULL, "pcie_0_ldo", 0, true}, {NULL, "pcie_0_phy_reset", 0, false} {NULL, "pcie_0_phy_reset", 0, false}, {NULL, "pcie_0_phy_cfg_ahb_clk", 0, false}, {NULL, "pcie_0_phy_aux_clk", 0, false} }; static struct ep_pcie_clk_info_t Loading Loading @@ -131,12 +133,19 @@ static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev) info = &dev->gpio[i]; if (!info->num) { if (i == EP_PCIE_GPIO_MDM2AP) { EP_PCIE_DBG(dev, "PCIe V%d: gpio %s does not exist.\n", dev->rev, info->name); continue; } else { EP_PCIE_ERR(dev, "PCIe V%d: the number of gpio %s is invalid\n", dev->rev, info->name); rc = -EINVAL; break; } } rc = gpio_request(info->num, info->name); if (rc) { Loading Loading @@ -451,6 +460,109 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev) ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); } #ifdef CONFIG_ARCH_MSM8996 static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) { u32 regval; EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); /* Configure PCIe to endpoint mode */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x0); /* adjust DBI base address */ writel_relaxed(0x0C000000, dev->parf + PCIE20_PARF_DBI_BASE_ADDR); /* Configure PCIe core to support 1GB aperture */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_SLV_ADDR_SPACE_SIZE, 0x40000000); /* Disable the debouncers */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DB_CTRL, 0x73); /* Enable Auxiliary Power Detect */ ep_pcie_write_mask(dev->parf + PCIE20_PARF_SYS_CTRL, 0x10, BIT(4)); /* Enable the bit to exit l1ss when sending LTR and MSI */ ep_pcie_write_mask(dev->parf + PCIE20_PARF_CFG_BITS, 0x2, BIT(1)); /* Enable CS for RO(CS) register writes */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0)); /* Set the INT_LINE Register field to 0 */ ep_pcie_write_mask(dev->dm_core + PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG, 0xff, 0); /* Set the PMC Register - to support PME in D0, D3hot and D3cold */ ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0xF8000000, BIT(31) | BIT(30) | BIT(27)); /* Set the frequency for the AUX clock to 19.2MHz */ ep_pcie_write_mask(dev->dm_core + PCIE20_AUX_CLK_FREQ_REG, 0x3FF, BIT(4) | BIT(2)); /* Set the Endpoint L0s Acceptable Latency to 1us (max) */ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES, 0x1C0, BIT(8) | BIT(7) | BIT(6)); /* Set the Endpoint L1 Acceptable Latency to 2 us (max) */ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES, 0xE00, BIT(11) | BIT(10) | BIT(9)); /* Set the L0s Exit Latency to 2us-4us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x38000, BIT(17) | BIT(16)); /* Set the L1 Exit Latency to be 32us-64 us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x7000, BIT(14) | BIT(13)); /* Enable Clock Power Management */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x40000, BIT(18)); /* Disable CS for RO(CS) register writes */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); /* Enable writes for RO(CS2) */ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, 0, BIT(0)); /* Set the Common Clock L0s Exit Latency to 2us-4us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x38000, BIT(17) | BIT(16)); /* Set the Common Clock L1 Exit Latency to be 32us-64 us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x7000, BIT(14) | BIT(13)); /* Disable writes for RO(CS2) */ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, BIT(0), 0); /* T_Power_Off */ ep_pcie_write_mask(dev->dm_core + PCIE20_L1_SUBSTATES_REG, BIT(1) | BIT(0), 0); /* Set Device ID and Vendor ID */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0)); ep_pcie_write_reg(dev->dm_core, PCIE20_DEVICE_ID_VENDOR_ID_REG, 0x030217cb); ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); /* Configure link speed */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CONTROL2_LINK_STATUS2, 0xf, dev->link_speed); /* Configure BARs */ ep_pcie_bar_init(dev); /* Enable MHI clocks */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_MHI_CLOCK_RESET_CTRL, BIT(1) | BIT(0)); ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS, 0x0); ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2); } #else static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) { EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); Loading Loading @@ -578,6 +690,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14); } #endif static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev) { Loading Loading @@ -694,6 +807,32 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev, EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); of_get_property(pdev->dev.of_node, "qcom,phy-sequence", &cnt); if (cnt) { dev->phy_sequence = (struct ep_pcie_phy_info_t *) devm_kzalloc(&pdev->dev, cnt, GFP_KERNEL); if (dev->phy_sequence) { dev->phy_len = cnt / sizeof(*dev->phy_sequence); of_property_read_u32_array(pdev->dev.of_node, "qcom,phy-sequence", (unsigned int *)dev->phy_sequence, cnt / sizeof(dev->phy_sequence->offset)); } else { EP_PCIE_ERR(dev, "PCIe V%d: Failed to alloc mem for phy seq.\n", dev->rev); ret = -ENOMEM; goto out; } } else { EP_PCIE_DBG(dev, "PCIe V%d: phy sequence is not present in DT.\n", dev->rev); } cnt = of_property_count_strings((&pdev->dev)->of_node, "clock-names"); if (cnt > 0) { Loading Loading @@ -782,6 +921,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev, EP_PCIE_DBG(dev, "GPIO %s is not supported in this configuration.\n", gpio_info->name); ret = 0; } } Loading Loading @@ -1070,6 +1210,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) EP_PCIE_INFO(dev, "PCIe V%d: PCIe PHY is ready!\n", dev->rev); } #ifdef CONFIG_ARCH_MSM8996 ep_pcie_phy_bringup_port(dev); #endif ep_pcie_core_init(dev); ep_pcie_config_inbound_iatu(dev); Loading Loading @@ -1977,6 +2120,17 @@ static int ep_pcie_probe(struct platform_device *pdev) EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-link-speed:%d.\n", ep_pcie_dev.rev, ep_pcie_dev.link_speed); ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,phy-status-reg", &ep_pcie_dev.phy_status_reg); if (ret) EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg does not exist.\n", ep_pcie_dev.rev); else EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg:0x%x.\n", ep_pcie_dev.rev, ep_pcie_dev.phy_status_reg); ep_pcie_dev.phy_rev = 1; ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,pcie-phy-ver", Loading drivers/platform/msm/ep_pcie/ep_pcie_phy.c +42 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,7 @@ /* * MSM PCIe PHY endpoint mode */ #include <linux/delay.h> #include "ep_pcie_com.h" #include "ep_pcie_phy.h" Loading @@ -23,6 +24,28 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev) "PCIe V%d: PHY V%d: Initializing 14nm QMP phy - 100MHz\n", dev->rev, dev->phy_rev); if (dev->phy_sequence) { int i; struct ep_pcie_phy_info_t *phy_seq; EP_PCIE_DBG(dev, "PCIe V%d: PHY V%d: process the sequence specified by DT.!\n", dev->rev, dev->phy_rev); i = dev->phy_len; phy_seq = dev->phy_sequence; while (i--) { ep_pcie_write_reg(dev->phy, phy_seq->offset, phy_seq->val); if (phy_seq->delay) usleep_range(phy_seq->delay, phy_seq->delay + 1); phy_seq++; } return; } ep_pcie_write_reg(dev->phy, PCIE_PHY_SW_RESET, 0x01); ep_pcie_write_reg(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01); Loading Loading @@ -104,10 +127,26 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev) ep_pcie_write_reg(dev->phy, PCIE_PHY_START_CONTROL, 0x03); } #ifdef CONFIG_ARCH_MSM8996 void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev) { ep_pcie_write_reg(dev->phy, PCIE_PORT_POWER_DOWN_CONTROL, 0x03); ep_pcie_write_reg(dev->phy, PCIE_PORT_SW_RESET, 0x0); ep_pcie_write_reg(dev->phy, PCIE_PORT_START_CONTROL, 0x0a); } #endif bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev) { if (readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS) & BIT(6)) return false; u32 offset; if (dev->phy_status_reg) offset = dev->phy_status_reg; else offset = PCIE_PHY_PCS_STATUS; if (readl_relaxed(dev->phy + offset) & BIT(0)) return true; else return false; } drivers/platform/msm/ep_pcie/ep_pcie_phy.h +31 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -460,4 +460,34 @@ #define PCIE_PHY_LFPS_PER_TIMER_VAL 0x9EC #define PCIE_PHY_SIGDET_STARTUP_TIMER_VAL 0x9F0 #define PCIE_PHY_LOCK_DETECT_CONFIG4 0x9F4 #ifdef CONFIG_ARCH_MSM8996 #define QSERDES_TX_RES_CODE_LANE_OFFSET 0x1054 #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x1068 #define QSERDES_TX_LANE_MODE 0x1094 #define QSERDES_TX_RCV_DETECT_LVL_2 0x10AC #define QSERDES_RX_UCDR_FO_GAIN_HALF 0x1200 #define QSERDES_RX_UCDR_FO_GAIN 0x120C #define QSERDES_RX_UCDR_SO_GAIN_HALF 0x1210 #define QSERDES_RX_UCDR_SO_GAIN 0x121C #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x1248 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 0x12D4 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x12D8 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x12DC #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x12E0 #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x130C #define QSERDES_RX_SIGDET_ENABLES 0x1310 #define QSERDES_RX_SIGDET_CNTRL 0x1314 #define QSERDES_RX_SIGDET_LVL 0x1318 #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x131C #define PCIE_PHY_SW_RESET 0x400 #define PCIE_PHY_POWER_DOWN_CONTROL 0x404 #define PCIE_PHY_START_CONTROL 0x408 #define PCIE_PHY_ENDPOINT_REFCLK_DRIVE 0x1454 #define PCIE_PHY_PWRUP_RESET_DLY_TIME_AUXCLK 0x14A0 #define PCIE_PORT_ENDPOINT_REFCLK_DRIVE 0x1454 #define PCIE_PORT_POWER_DOWN_CONTROL 0x1404 #define PCIE_PORT_SW_RESET 0x1400 #define PCIE_PORT_START_CONTROL 0x1408 #define PCIE_COM_PCS_READY_STATUS 0x448 #endif #endif Loading
arch/arm/boot/dts/qcom/msm8996.dtsi +126 −0 Original line number Diff line number Diff line Loading @@ -2560,6 +2560,132 @@ qcom,ipa-advertise-sg-support; }; pcie_ep: qcom,pcie-ep@00600000 { compatible = "qcom,pcie-ep"; reg = <0x0c001000 0x1000>, <0x0c000000 0xf1d>, <0x0c000f20 0xa8>, <0x00600000 0x2000>, <0x00034000 0x4000>, <0x00607000 0x1000>; reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio"; #address-cells = <0>; interrupt-parent = <&pcie_ep>; interrupts = <0 1 2 3 4>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; interrupt-map = <0 &intc 0 0 247 0 1 &intc 0 0 249 0 2 &intc 0 0 253 0 3 &intc 0 0 254 0 4 &intc 0 0 49 0>; interrupt-names ="int_pm_turnoff", "int_dstate_change", "int_link_up", "int_link_down", "int_global"; pinctrl-names = "default"; pinctrl-0 = <&pcie0_clkreq_default &pcie0_perst_default &pcie0_wake_default>; clkreq-gpio = <&tlmm 36 0>; perst-gpio = <&tlmm 35 0>; wake-gpio = <&tlmm 37 0>; gdsc-vdd-supply = <&gdsc_pcie_0>; vreg-1.8-supply = <&pm8994_l12>; vreg-0.9-supply = <&pm8994_l28>; qcom,vreg-0.9-voltage-level = <925000 925000 24000>; clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>, <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>, <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>, <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>, <&clock_gcc clk_gcc_pcie_0_aux_clk>, <&clock_gcc clk_gcc_pcie_clkref_clk>, <&clock_gcc clk_gcc_pcie_phy_reset>, <&clock_gcc clk_gcc_pcie_phy_cfg_ahb_clk>, <&clock_gcc clk_gcc_pcie_phy_aux_clk>; clock-names = "pcie_0_pipe_clk", "pcie_0_cfg_ahb_clk", "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk", "pcie_0_aux_clk", "pcie_0_ldo", "pcie_0_phy_reset", "pcie_0_phy_cfg_ahb_clk", "pcie_0_phy_aux_clk"; resets = <&clock_gcc PCIE_PHY_BCR>, <&clock_gcc PCIE_PHY_COM_BCR>, <&clock_gcc PCIE_PHY_NOCSR_COM_PHY_BCR>, <&clock_gcc PCIE_0_PHY_BCR>; reset-names = "pcie_phy_reset", "pcie_phy_com_reset", "pcie_phy_nocsr_com_phy_reset","pcie_0_phy_reset"; max-clock-frequency-hz = <0>, <0>, <0>, <0>, <1010526>, <0>, <0>, <0>, <0>; qcom,msm-bus,name = "pcie-ep"; qcom,msm-bus,num-cases = <2>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <45 512 0 0>, <45 512 500 800>; qcom,pcie-link-speed = <0>; qcom,pcie-phy-ver = <4>; qcom,pcie-perst-enum; qcom,phy-status-reg = <0x448>; qcom,phy-sequence = <0x400 0x01 0x00 0x404 0x01 0x00 0x00AC 0x00 0x00 0x0034 0x18 0x00 0x0174 0x30 0x00 0x00B4 0x20 0x00 0x1094 0x06 0x00 0x00D0 0x19 0x00 0x0078 0x3F 0x00 0x0084 0x1A 0x00 0x0090 0x00 0x00 0x010C 0x00 0x00 0x0108 0xFF 0x00 0x019C 0x01 0x00 0x018C 0x00 0x00 0x0050 0x04 0x00 0x004C 0xff 0x00 0x00C8 0x42 0x00 0x0128 0x00 0x00 0x0148 0x3f 0x00 0x0144 0xff 0x00 0x000C 0x01 0x00 0x0070 0x0f 0x00 0x0048 0x0f 0x00 0x1248 0x4B 0x00 0x120C 0x0A 0x00 0x1200 0x0A 0x00 0x121C 0x04 0x00 0x1210 0x04 0x00 0x12D8 0x01 0x00 0x12DC 0x00 0x00 0x12E0 0xDB 0x00 0x12D4 0x77 0x00 0x130C 0x80 0x00 0x1310 0x1C 0x00 0x1314 0x03 0x00 0x131C 0x14 0x00 0x1054 0x02 0x00 0x1068 0x45 0x00 0x10AC 0x12 0x00 0x0194 0x06 0x00 0x1454 0x00 0x00 0x1404 0x00 0x00 0x400 0x00 0x00 0x408 0x03 0x00>; status = "disabled"; }; qcom_rng: qrng@83000 { compatible = "qcom,msm-rng"; reg = <0x83000 0x1000>; Loading
drivers/platform/msm/ep_pcie/ep_pcie_com.h +22 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -101,6 +101,14 @@ #define PCIE20_AUX_CLK_FREQ_REG 0xB40 #define PCIE20_MHISTATUS 0x148 #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174 #define PCIE20_PARF_CFG_BITS 0x210 #define PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3C #define PCIE20_DEVICE_ID_VENDOR_ID_REG 0x0 #define PCIE20_L1_SUBSTATES_REG 0xB44 #define PERST_TIMEOUT_US_MIN 1000 #define PERST_TIMEOUT_US_MAX 1000 #define PERST_CHECK_MAX_COUNT 30000 Loading @@ -126,7 +134,7 @@ #define EP_PCIE_LOG_PAGES 50 #define EP_PCIE_MAX_VREG 2 #define EP_PCIE_MAX_CLK 6 #define EP_PCIE_MAX_CLK 8 #define EP_PCIE_MAX_PIPE_CLK 1 #define EP_PCIE_ERROR -30655 Loading Loading @@ -255,6 +263,12 @@ struct ep_pcie_irq_info_t { u32 num; }; struct ep_pcie_phy_info_t { u32 offset; u32 val; u32 delay; }; /* pcie endpoint device structure */ struct ep_pcie_dev_t { struct platform_device *pdev; Loading @@ -278,6 +292,9 @@ struct ep_pcie_dev_t { u32 link_speed; bool active_config; bool aggregated_irq; u32 phy_status_reg; u32 phy_len; struct ep_pcie_phy_info_t *phy_sequence; u32 rev; u32 phy_rev; Loading Loading @@ -356,5 +373,7 @@ extern bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev); extern void ep_pcie_reg_dump(struct ep_pcie_dev_t *dev, u32 sel, bool linkdown); extern void ep_pcie_debugfs_init(struct ep_pcie_dev_t *ep_dev); extern void ep_pcie_debugfs_exit(void); #ifdef CONFIG_ARCH_MSM8996 extern void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev); #endif #endif
drivers/platform/msm/ep_pcie/ep_pcie_core.c +161 −7 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -64,7 +64,9 @@ static struct ep_pcie_clk_info_t {NULL, "pcie_0_slv_axi_clk", 0, true}, {NULL, "pcie_0_aux_clk", 1000000, true}, {NULL, "pcie_0_ldo", 0, true}, {NULL, "pcie_0_phy_reset", 0, false} {NULL, "pcie_0_phy_reset", 0, false}, {NULL, "pcie_0_phy_cfg_ahb_clk", 0, false}, {NULL, "pcie_0_phy_aux_clk", 0, false} }; static struct ep_pcie_clk_info_t Loading Loading @@ -131,12 +133,19 @@ static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev) info = &dev->gpio[i]; if (!info->num) { if (i == EP_PCIE_GPIO_MDM2AP) { EP_PCIE_DBG(dev, "PCIe V%d: gpio %s does not exist.\n", dev->rev, info->name); continue; } else { EP_PCIE_ERR(dev, "PCIe V%d: the number of gpio %s is invalid\n", dev->rev, info->name); rc = -EINVAL; break; } } rc = gpio_request(info->num, info->name); if (rc) { Loading Loading @@ -451,6 +460,109 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev) ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); } #ifdef CONFIG_ARCH_MSM8996 static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) { u32 regval; EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); /* Configure PCIe to endpoint mode */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x0); /* adjust DBI base address */ writel_relaxed(0x0C000000, dev->parf + PCIE20_PARF_DBI_BASE_ADDR); /* Configure PCIe core to support 1GB aperture */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_SLV_ADDR_SPACE_SIZE, 0x40000000); /* Disable the debouncers */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DB_CTRL, 0x73); /* Enable Auxiliary Power Detect */ ep_pcie_write_mask(dev->parf + PCIE20_PARF_SYS_CTRL, 0x10, BIT(4)); /* Enable the bit to exit l1ss when sending LTR and MSI */ ep_pcie_write_mask(dev->parf + PCIE20_PARF_CFG_BITS, 0x2, BIT(1)); /* Enable CS for RO(CS) register writes */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0)); /* Set the INT_LINE Register field to 0 */ ep_pcie_write_mask(dev->dm_core + PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG, 0xff, 0); /* Set the PMC Register - to support PME in D0, D3hot and D3cold */ ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR, 0xF8000000, BIT(31) | BIT(30) | BIT(27)); /* Set the frequency for the AUX clock to 19.2MHz */ ep_pcie_write_mask(dev->dm_core + PCIE20_AUX_CLK_FREQ_REG, 0x3FF, BIT(4) | BIT(2)); /* Set the Endpoint L0s Acceptable Latency to 1us (max) */ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES, 0x1C0, BIT(8) | BIT(7) | BIT(6)); /* Set the Endpoint L1 Acceptable Latency to 2 us (max) */ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES, 0xE00, BIT(11) | BIT(10) | BIT(9)); /* Set the L0s Exit Latency to 2us-4us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x38000, BIT(17) | BIT(16)); /* Set the L1 Exit Latency to be 32us-64 us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x7000, BIT(14) | BIT(13)); /* Enable Clock Power Management */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x40000, BIT(18)); /* Disable CS for RO(CS) register writes */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); /* Enable writes for RO(CS2) */ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, 0, BIT(0)); /* Set the Common Clock L0s Exit Latency to 2us-4us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x38000, BIT(17) | BIT(16)); /* Set the Common Clock L1 Exit Latency to be 32us-64 us = 0x6 */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES, 0x7000, BIT(14) | BIT(13)); /* Disable writes for RO(CS2) */ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, BIT(0), 0); /* T_Power_Off */ ep_pcie_write_mask(dev->dm_core + PCIE20_L1_SUBSTATES_REG, BIT(1) | BIT(0), 0); /* Set Device ID and Vendor ID */ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0)); ep_pcie_write_reg(dev->dm_core, PCIE20_DEVICE_ID_VENDOR_ID_REG, 0x030217cb); ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0); /* Configure link speed */ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CONTROL2_LINK_STATUS2, 0xf, dev->link_speed); /* Configure BARs */ ep_pcie_bar_init(dev); /* Enable MHI clocks */ ep_pcie_write_reg(dev->parf, PCIE20_PARF_MHI_CLOCK_RESET_CTRL, BIT(1) | BIT(0)); ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS, 0x0); ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2); } #else static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) { EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); Loading Loading @@ -578,6 +690,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev) ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14); } #endif static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev) { Loading Loading @@ -694,6 +807,32 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev, EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); of_get_property(pdev->dev.of_node, "qcom,phy-sequence", &cnt); if (cnt) { dev->phy_sequence = (struct ep_pcie_phy_info_t *) devm_kzalloc(&pdev->dev, cnt, GFP_KERNEL); if (dev->phy_sequence) { dev->phy_len = cnt / sizeof(*dev->phy_sequence); of_property_read_u32_array(pdev->dev.of_node, "qcom,phy-sequence", (unsigned int *)dev->phy_sequence, cnt / sizeof(dev->phy_sequence->offset)); } else { EP_PCIE_ERR(dev, "PCIe V%d: Failed to alloc mem for phy seq.\n", dev->rev); ret = -ENOMEM; goto out; } } else { EP_PCIE_DBG(dev, "PCIe V%d: phy sequence is not present in DT.\n", dev->rev); } cnt = of_property_count_strings((&pdev->dev)->of_node, "clock-names"); if (cnt > 0) { Loading Loading @@ -782,6 +921,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev, EP_PCIE_DBG(dev, "GPIO %s is not supported in this configuration.\n", gpio_info->name); ret = 0; } } Loading Loading @@ -1070,6 +1210,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) EP_PCIE_INFO(dev, "PCIe V%d: PCIe PHY is ready!\n", dev->rev); } #ifdef CONFIG_ARCH_MSM8996 ep_pcie_phy_bringup_port(dev); #endif ep_pcie_core_init(dev); ep_pcie_config_inbound_iatu(dev); Loading Loading @@ -1977,6 +2120,17 @@ static int ep_pcie_probe(struct platform_device *pdev) EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-link-speed:%d.\n", ep_pcie_dev.rev, ep_pcie_dev.link_speed); ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,phy-status-reg", &ep_pcie_dev.phy_status_reg); if (ret) EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg does not exist.\n", ep_pcie_dev.rev); else EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg:0x%x.\n", ep_pcie_dev.rev, ep_pcie_dev.phy_status_reg); ep_pcie_dev.phy_rev = 1; ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,pcie-phy-ver", Loading
drivers/platform/msm/ep_pcie/ep_pcie_phy.c +42 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,7 @@ /* * MSM PCIe PHY endpoint mode */ #include <linux/delay.h> #include "ep_pcie_com.h" #include "ep_pcie_phy.h" Loading @@ -23,6 +24,28 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev) "PCIe V%d: PHY V%d: Initializing 14nm QMP phy - 100MHz\n", dev->rev, dev->phy_rev); if (dev->phy_sequence) { int i; struct ep_pcie_phy_info_t *phy_seq; EP_PCIE_DBG(dev, "PCIe V%d: PHY V%d: process the sequence specified by DT.!\n", dev->rev, dev->phy_rev); i = dev->phy_len; phy_seq = dev->phy_sequence; while (i--) { ep_pcie_write_reg(dev->phy, phy_seq->offset, phy_seq->val); if (phy_seq->delay) usleep_range(phy_seq->delay, phy_seq->delay + 1); phy_seq++; } return; } ep_pcie_write_reg(dev->phy, PCIE_PHY_SW_RESET, 0x01); ep_pcie_write_reg(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01); Loading Loading @@ -104,10 +127,26 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev) ep_pcie_write_reg(dev->phy, PCIE_PHY_START_CONTROL, 0x03); } #ifdef CONFIG_ARCH_MSM8996 void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev) { ep_pcie_write_reg(dev->phy, PCIE_PORT_POWER_DOWN_CONTROL, 0x03); ep_pcie_write_reg(dev->phy, PCIE_PORT_SW_RESET, 0x0); ep_pcie_write_reg(dev->phy, PCIE_PORT_START_CONTROL, 0x0a); } #endif bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev) { if (readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS) & BIT(6)) return false; u32 offset; if (dev->phy_status_reg) offset = dev->phy_status_reg; else offset = PCIE_PHY_PCS_STATUS; if (readl_relaxed(dev->phy + offset) & BIT(0)) return true; else return false; }
drivers/platform/msm/ep_pcie/ep_pcie_phy.h +31 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -460,4 +460,34 @@ #define PCIE_PHY_LFPS_PER_TIMER_VAL 0x9EC #define PCIE_PHY_SIGDET_STARTUP_TIMER_VAL 0x9F0 #define PCIE_PHY_LOCK_DETECT_CONFIG4 0x9F4 #ifdef CONFIG_ARCH_MSM8996 #define QSERDES_TX_RES_CODE_LANE_OFFSET 0x1054 #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x1068 #define QSERDES_TX_LANE_MODE 0x1094 #define QSERDES_TX_RCV_DETECT_LVL_2 0x10AC #define QSERDES_RX_UCDR_FO_GAIN_HALF 0x1200 #define QSERDES_RX_UCDR_FO_GAIN 0x120C #define QSERDES_RX_UCDR_SO_GAIN_HALF 0x1210 #define QSERDES_RX_UCDR_SO_GAIN 0x121C #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x1248 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 0x12D4 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x12D8 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x12DC #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x12E0 #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x130C #define QSERDES_RX_SIGDET_ENABLES 0x1310 #define QSERDES_RX_SIGDET_CNTRL 0x1314 #define QSERDES_RX_SIGDET_LVL 0x1318 #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x131C #define PCIE_PHY_SW_RESET 0x400 #define PCIE_PHY_POWER_DOWN_CONTROL 0x404 #define PCIE_PHY_START_CONTROL 0x408 #define PCIE_PHY_ENDPOINT_REFCLK_DRIVE 0x1454 #define PCIE_PHY_PWRUP_RESET_DLY_TIME_AUXCLK 0x14A0 #define PCIE_PORT_ENDPOINT_REFCLK_DRIVE 0x1454 #define PCIE_PORT_POWER_DOWN_CONTROL 0x1404 #define PCIE_PORT_SW_RESET 0x1400 #define PCIE_PORT_START_CONTROL 0x1408 #define PCIE_COM_PCS_READY_STATUS 0x448 #endif #endif