2217 lines
58 KiB
C
2217 lines
58 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/of_pci.h>
|
|
#include <linux/phy/phy.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/reset.h>
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/amlogic/cpu_version.h>
|
|
#include <linux/ktime.h>
|
|
|
|
#include "amlogic-pcie-v3.h"
|
|
|
|
static u8 __aml_pcie_find_next_cap(struct amlogic_pcie *pci, u8 cap_ptr,
|
|
u8 cap)
|
|
{
|
|
u8 cap_id, next_cap_ptr;
|
|
u16 reg;
|
|
|
|
if (!cap_ptr)
|
|
return 0;
|
|
|
|
reg = amlogic_pcieinter_readw(pci, cap_ptr);
|
|
cap_id = (reg & 0x00ff);
|
|
|
|
if (cap_id > PCI_CAP_ID_MAX)
|
|
return 0;
|
|
|
|
if (cap_id == cap)
|
|
return cap_ptr;
|
|
|
|
next_cap_ptr = (reg & 0xff00) >> 8;
|
|
return __aml_pcie_find_next_cap(pci, next_cap_ptr, cap);
|
|
}
|
|
|
|
u8 aml_pcie_find_capability(struct amlogic_pcie *pci, u8 cap)
|
|
{
|
|
u8 next_cap_ptr;
|
|
u16 reg;
|
|
|
|
reg = amlogic_pcieinter_readw(pci, PCI_CAPABILITY_LIST);
|
|
next_cap_ptr = (reg & 0x00ff);
|
|
|
|
return __aml_pcie_find_next_cap(pci, next_cap_ptr, cap);
|
|
}
|
|
EXPORT_SYMBOL_GPL(aml_pcie_find_capability);
|
|
|
|
static int amlogic_pcie_get_reset_for_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct device_node *node = dev->of_node;
|
|
struct resource *rst_regs;
|
|
int ret = 0;
|
|
|
|
/*m31phy_pcie_wrapper_rst*/
|
|
amlogic->m31phy_rst = devm_reset_control_get_exclusive(dev,
|
|
"m31phy_rst");
|
|
if (IS_ERR(amlogic->m31phy_rst)) {
|
|
if (PTR_ERR(amlogic->m31phy_rst) != -EPROBE_DEFER)
|
|
goto get_rst_reg;
|
|
}
|
|
|
|
/*pcie_gen3_l0_rst*/
|
|
amlogic->gen3_l0_rst = devm_reset_control_get_exclusive(dev,
|
|
"gen3_l0_rst");
|
|
if (IS_ERR(amlogic->gen3_l0_rst)) {
|
|
if (PTR_ERR(amlogic->gen3_l0_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "gen3_l0_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->gen3_l0_rst);
|
|
}
|
|
|
|
amlogic->pcie_apb_rst = devm_reset_control_get_exclusive(dev,
|
|
"apb_rst");
|
|
if (IS_ERR(amlogic->pcie_apb_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_apb_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_apb_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_apb_rst);
|
|
}
|
|
|
|
amlogic->pcie_phy_rst = devm_reset_control_get_exclusive(dev,
|
|
"phy_rst");
|
|
if (IS_ERR(amlogic->pcie_phy_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_phy_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_phy_rst property in node\n");
|
|
return PTR_ERR(amlogic->pcie_phy_rst);
|
|
}
|
|
|
|
amlogic->pcie_a_rst = devm_reset_control_get_exclusive(dev,
|
|
"pcie_a_rst");
|
|
if (IS_ERR(amlogic->pcie_a_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_a_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_a_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_a_rst);
|
|
}
|
|
|
|
amlogic->pcie_rst0 = devm_reset_control_get_exclusive(dev, "pcie_rst0");
|
|
if (IS_ERR(amlogic->pcie_rst0)) {
|
|
if (PTR_ERR(amlogic->pcie_rst0) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst0 property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst0);
|
|
}
|
|
|
|
amlogic->pcie_rst1 = devm_reset_control_get_exclusive(dev, "pcie_rst1");
|
|
if (IS_ERR(amlogic->pcie_rst1)) {
|
|
if (PTR_ERR(amlogic->pcie_rst1) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst1 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst1);
|
|
}
|
|
|
|
amlogic->pcie_rst2 = devm_reset_control_get_exclusive(dev, "pcie_rst2");
|
|
if (IS_ERR(amlogic->pcie_rst2)) {
|
|
if (PTR_ERR(amlogic->pcie_rst2) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst2 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst2);
|
|
}
|
|
|
|
amlogic->pcie_rst3 = devm_reset_control_get_exclusive(dev, "pcie_rst3");
|
|
if (IS_ERR(amlogic->pcie_rst3)) {
|
|
if (PTR_ERR(amlogic->pcie_rst3) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst3 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst3);
|
|
}
|
|
|
|
amlogic->pcie_rst4 = devm_reset_control_get_exclusive(dev, "pcie_rst4");
|
|
if (IS_ERR(amlogic->pcie_rst4)) {
|
|
if (PTR_ERR(amlogic->pcie_rst4) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst4 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst4);
|
|
}
|
|
|
|
amlogic->pcie_rst5 = devm_reset_control_get_exclusive(dev, "pcie_rst5");
|
|
if (IS_ERR(amlogic->pcie_rst5)) {
|
|
if (PTR_ERR(amlogic->pcie_rst5) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst5 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst5);
|
|
}
|
|
|
|
amlogic->pcie_rst6 = devm_reset_control_get_exclusive(dev, "pcie_rst6");
|
|
if (IS_ERR(amlogic->pcie_rst6)) {
|
|
if (PTR_ERR(amlogic->pcie_rst6) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst6 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst6);
|
|
}
|
|
|
|
amlogic->pcie_rst7 = devm_reset_control_get_exclusive(dev, "pcie_rst7");
|
|
if (IS_ERR(amlogic->pcie_rst7)) {
|
|
if (PTR_ERR(amlogic->pcie_rst7) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst7 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst7);
|
|
}
|
|
|
|
return 0;
|
|
|
|
get_rst_reg:
|
|
rst_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"reset-base");
|
|
amlogic->rst_base = devm_ioremap(dev, rst_regs->start,
|
|
resource_size(rst_regs));
|
|
if (IS_ERR(amlogic->rst_base)) {
|
|
dev_err(dev, "failed to request rst_base\n");
|
|
return PTR_ERR(amlogic->rst_base);
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-m31phy-rst-bit",
|
|
&amlogic->m31phy_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request m31phy_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-gen3-l0-rst-bit",
|
|
&amlogic->gen3_l0_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request gen3_l0_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-apb-rst-bit",
|
|
&amlogic->apb_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request apb_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-phy-rst-bit",
|
|
&amlogic->phy_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request phy_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-a-rst-bit",
|
|
&amlogic->pcie_a_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_a_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-bit",
|
|
&amlogic->pcie_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-mask",
|
|
&amlogic->pcie_rst_mask);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_size\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_reset_for_m31_comphy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct device_node *node = dev->of_node;
|
|
struct resource *rst_regs;
|
|
int ret = 0;
|
|
|
|
amlogic->gen2_l0_rst = devm_reset_control_get_exclusive(dev,
|
|
"gen2_l0_rst");
|
|
if (IS_ERR(amlogic->gen2_l0_rst)) {
|
|
if (PTR_ERR(amlogic->gen2_l0_rst) != -EPROBE_DEFER)
|
|
goto get_rst_reg;
|
|
}
|
|
|
|
amlogic->pcie_apb_rst = devm_reset_control_get_exclusive(dev,
|
|
"apb_rst");
|
|
if (IS_ERR(amlogic->pcie_apb_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_apb_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_apb_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_apb_rst);
|
|
}
|
|
|
|
amlogic->pcie_phy_rst = devm_reset_control_get_exclusive(dev,
|
|
"phy_rst");
|
|
if (IS_ERR(amlogic->pcie_phy_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_phy_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_phy_rst property in node\n");
|
|
return PTR_ERR(amlogic->pcie_phy_rst);
|
|
}
|
|
|
|
amlogic->pcie_a_rst = devm_reset_control_get_exclusive(dev,
|
|
"pcie_a_rst");
|
|
if (IS_ERR(amlogic->pcie_a_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_a_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_a_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_a_rst);
|
|
}
|
|
|
|
amlogic->pcie_rst0 = devm_reset_control_get_exclusive(dev, "pcie_rst0");
|
|
if (IS_ERR(amlogic->pcie_rst0)) {
|
|
if (PTR_ERR(amlogic->pcie_rst0) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst0 property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst0);
|
|
}
|
|
|
|
amlogic->pcie_rst1 = devm_reset_control_get_exclusive(dev, "pcie_rst1");
|
|
if (IS_ERR(amlogic->pcie_rst1)) {
|
|
if (PTR_ERR(amlogic->pcie_rst1) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst1 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst1);
|
|
}
|
|
|
|
amlogic->pcie_rst2 = devm_reset_control_get_exclusive(dev, "pcie_rst2");
|
|
if (IS_ERR(amlogic->pcie_rst2)) {
|
|
if (PTR_ERR(amlogic->pcie_rst2) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst2 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst2);
|
|
}
|
|
|
|
amlogic->pcie_rst3 = devm_reset_control_get_exclusive(dev, "pcie_rst3");
|
|
if (IS_ERR(amlogic->pcie_rst3)) {
|
|
if (PTR_ERR(amlogic->pcie_rst3) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst3 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst3);
|
|
}
|
|
|
|
amlogic->pcie_rst4 = devm_reset_control_get_exclusive(dev, "pcie_rst4");
|
|
if (IS_ERR(amlogic->pcie_rst4)) {
|
|
if (PTR_ERR(amlogic->pcie_rst4) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst4 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst4);
|
|
}
|
|
|
|
amlogic->pcie_rst5 = devm_reset_control_get_exclusive(dev, "pcie_rst5");
|
|
if (IS_ERR(amlogic->pcie_rst5)) {
|
|
if (PTR_ERR(amlogic->pcie_rst5) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst5 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst5);
|
|
}
|
|
|
|
amlogic->pcie_rst6 = devm_reset_control_get_exclusive(dev, "pcie_rst6");
|
|
if (IS_ERR(amlogic->pcie_rst6)) {
|
|
if (PTR_ERR(amlogic->pcie_rst6) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst6 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst6);
|
|
}
|
|
|
|
amlogic->pcie_rst7 = devm_reset_control_get_exclusive(dev, "pcie_rst7");
|
|
if (IS_ERR(amlogic->pcie_rst7)) {
|
|
if (PTR_ERR(amlogic->pcie_rst7) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst7 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst7);
|
|
}
|
|
|
|
return 0;
|
|
|
|
get_rst_reg:
|
|
rst_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"reset-base");
|
|
amlogic->rst_base = devm_ioremap(dev, rst_regs->start,
|
|
resource_size(rst_regs));
|
|
if (IS_ERR(amlogic->rst_base)) {
|
|
dev_err(dev, "failed to request rst_base\n");
|
|
return PTR_ERR(amlogic->rst_base);
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-gen2-l0-rst-bit",
|
|
&amlogic->gen2_l0_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request gen2_l0_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-apb-rst-bit",
|
|
&amlogic->apb_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request apb_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-phy-rst-bit",
|
|
&amlogic->phy_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request phy_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-a-rst-bit",
|
|
&amlogic->pcie_a_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_a_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-bit",
|
|
&amlogic->pcie_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-mask",
|
|
&amlogic->pcie_rst_mask);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_size\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_reset_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct device_node *node = dev->of_node;
|
|
struct resource *rst_regs;
|
|
int ret = 0;
|
|
|
|
amlogic->amlphy_rst = devm_reset_control_get_exclusive(dev,
|
|
"amlphy_rst");
|
|
if (IS_ERR(amlogic->amlphy_rst)) {
|
|
if (PTR_ERR(amlogic->amlphy_rst) != -EPROBE_DEFER)
|
|
goto get_rst_reg;
|
|
}
|
|
|
|
amlogic->pcie_apb_rst = devm_reset_control_get_exclusive(dev,
|
|
"apb_rst");
|
|
if (IS_ERR(amlogic->pcie_apb_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_apb_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_apb_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_apb_rst);
|
|
}
|
|
|
|
amlogic->u3p2_phy_apb_rst = devm_reset_control_get_exclusive(dev,
|
|
"u3p2_phy_apb_rst");
|
|
if (IS_ERR(amlogic->u3p2_phy_apb_rst)) {
|
|
if (PTR_ERR(amlogic->u3p2_phy_apb_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "u3p2_phy_apb_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->u3p2_phy_apb_rst);
|
|
}
|
|
|
|
amlogic->pcie_pipe_rst = devm_reset_control_get_exclusive(dev,
|
|
"pcie_pipe_rst");
|
|
if (IS_ERR(amlogic->pcie_pipe_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_pipe_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_pipe_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_pipe_rst);
|
|
}
|
|
|
|
amlogic->pcie_a_rst = devm_reset_control_get_exclusive(dev,
|
|
"pcie_a_rst");
|
|
if (IS_ERR(amlogic->pcie_a_rst)) {
|
|
if (PTR_ERR(amlogic->pcie_a_rst) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_a_rst reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_a_rst);
|
|
}
|
|
|
|
amlogic->pcie_rst0 = devm_reset_control_get_exclusive(dev, "pcie_rst0");
|
|
if (IS_ERR(amlogic->pcie_rst0)) {
|
|
if (PTR_ERR(amlogic->pcie_rst0) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst0 property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst0);
|
|
}
|
|
|
|
amlogic->pcie_rst1 = devm_reset_control_get_exclusive(dev, "pcie_rst1");
|
|
if (IS_ERR(amlogic->pcie_rst1)) {
|
|
if (PTR_ERR(amlogic->pcie_rst1) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst1 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst1);
|
|
}
|
|
|
|
amlogic->pcie_rst2 = devm_reset_control_get_exclusive(dev, "pcie_rst2");
|
|
if (IS_ERR(amlogic->pcie_rst2)) {
|
|
if (PTR_ERR(amlogic->pcie_rst2) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst2 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst2);
|
|
}
|
|
|
|
amlogic->pcie_rst3 = devm_reset_control_get_exclusive(dev, "pcie_rst3");
|
|
if (IS_ERR(amlogic->pcie_rst3)) {
|
|
if (PTR_ERR(amlogic->pcie_rst3) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst3 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst3);
|
|
}
|
|
|
|
amlogic->pcie_rst4 = devm_reset_control_get_exclusive(dev, "pcie_rst4");
|
|
if (IS_ERR(amlogic->pcie_rst4)) {
|
|
if (PTR_ERR(amlogic->pcie_rst4) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst4 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst4);
|
|
}
|
|
|
|
amlogic->pcie_rst5 = devm_reset_control_get_exclusive(dev, "pcie_rst5");
|
|
if (IS_ERR(amlogic->pcie_rst5)) {
|
|
if (PTR_ERR(amlogic->pcie_rst5) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst5 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst5);
|
|
}
|
|
|
|
amlogic->pcie_rst6 = devm_reset_control_get_exclusive(dev, "pcie_rst6");
|
|
if (IS_ERR(amlogic->pcie_rst6)) {
|
|
if (PTR_ERR(amlogic->pcie_rst6) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst6 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst6);
|
|
}
|
|
|
|
amlogic->pcie_rst7 = devm_reset_control_get_exclusive(dev, "pcie_rst7");
|
|
if (IS_ERR(amlogic->pcie_rst7)) {
|
|
if (PTR_ERR(amlogic->pcie_rst7) != -EPROBE_DEFER)
|
|
dev_err(dev, "pcie_rst7 reset property in node\n");
|
|
return PTR_ERR(amlogic->pcie_rst7);
|
|
}
|
|
|
|
return 0;
|
|
|
|
get_rst_reg:
|
|
rst_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"reset-base");
|
|
amlogic->rst_base = devm_ioremap(dev, rst_regs->start,
|
|
resource_size(rst_regs));
|
|
if (IS_ERR(amlogic->rst_base)) {
|
|
dev_err(dev, "failed to request rst_base\n");
|
|
return PTR_ERR(amlogic->rst_base);
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-amlphy-rst-bit",
|
|
&amlogic->amlphy_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request amlphy_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-apb-rst-bit",
|
|
&amlogic->apb_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request apb_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-pipe-rst-bit",
|
|
&amlogic->pcie_pipe_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_pipe_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "u3p2-phy-apb",
|
|
&amlogic->u3p2_phy_apb_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request u3p2_phy_apb_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-a-rst-bit",
|
|
&amlogic->pcie_a_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_a_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-bit",
|
|
&amlogic->pcie_rst_bit);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_bit\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(node, "pcie-rst-mask",
|
|
&amlogic->pcie_rst_mask);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request pcie_rst_size\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int amlogic_pcie_get_resets(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie use AMLOGIC_PHY\n");
|
|
ret = amlogic_pcie_get_reset_for_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie use M31_COMBPHY\n");
|
|
ret = amlogic_pcie_get_reset_for_m31_comphy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie use M31_PHY\n");
|
|
ret = amlogic_pcie_get_reset_for_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int amlogic_pcie_set_reset_for_m31_phy(struct amlogic_pcie *amlogic, bool set)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int err = 0, val = 0;
|
|
int regs = 0;
|
|
|
|
if (amlogic->rst_base)
|
|
goto set_rst_reg;
|
|
|
|
err = reset_control_deassert(amlogic->m31phy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert m31phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->m31phy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert m31phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->gen3_l0_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert gen3_l0_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->gen3_l0_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert gen3_l0_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_phy_rst);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_phy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_a_rst);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_a_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst0);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst0);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst1);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst1);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst2);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst2);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst3);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst3);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst4);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst4);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst5);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst5);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst6);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst6);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst7);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst7);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
|
|
set_rst_reg:
|
|
if (!set) {
|
|
val = readl(amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
val &= ~(amlogic->pcie_rst_mask << amlogic->pcie_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~((1 << amlogic->pcie_a_rst_bit) |
|
|
(1 << amlogic->phy_rst_bit) |
|
|
(1 << amlogic->apb_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
} else {
|
|
val = readl(amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
val |= (amlogic->pcie_rst_mask << amlogic->pcie_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
|
|
/*PHY_Register_XCFGA_COM value from vendor recommend*/
|
|
regs = readl(amlogic->phy_base + 0x828);
|
|
regs &= ~GENMASK(31, 28);
|
|
regs |= (2 << 28);
|
|
writel(regs, amlogic->phy_base + 0x828);
|
|
|
|
/*PHY_Register_XCFGD value from vendor recommend*/
|
|
regs = readl(amlogic->phy_base + 0x460);
|
|
regs &= ~GENMASK(23, 20);
|
|
regs |= (4 << 20);
|
|
writel(regs, amlogic->phy_base + 0x460);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val |= ((1 << amlogic->pcie_a_rst_bit) |
|
|
(1 << amlogic->phy_rst_bit) |
|
|
(1 << amlogic->apb_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_set_reset_for_m31_combphy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int err = 0, val = 0;
|
|
|
|
if (amlogic->rst_base)
|
|
goto set_rst_reg;
|
|
|
|
err = reset_control_deassert(amlogic->gen2_l0_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert gen2_l0_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->gen2_l0_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert gen2_l0_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_phy_rst);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_phy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_phy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_a_rst);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_a_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst0);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst0);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst1);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst1);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst2);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst2);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst3);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst3);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst4);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst4);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst5);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst5);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst6);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst6);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst7);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst7);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
|
|
set_rst_reg:
|
|
val = readl(amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
val &= ~(1 << amlogic->phy_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~((1 << amlogic->pcie_a_rst_bit) |
|
|
(1 << amlogic->gen2_l0_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
val &= ~(amlogic->pcie_rst_mask << amlogic->pcie_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
|
|
usleep_range(10, 20);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
val |= 1 << amlogic->phy_rst_bit;
|
|
writel(val, amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val |= ((1 << amlogic->pcie_a_rst_bit) |
|
|
(1 << amlogic->gen2_l0_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
val |= (amlogic->pcie_rst_mask << amlogic->pcie_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL3_OFFSET);
|
|
|
|
usleep_range(10, 30);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int amlogic_pcie_set_reset_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int err = 0, val = 0;
|
|
static int flag;
|
|
|
|
if (amlogic->rst_base)
|
|
goto set_rst_reg;
|
|
|
|
err = reset_control_deassert(amlogic->amlphy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert amlphy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->amlphy_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert amlphy_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
err = reset_control_deassert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "deassert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_apb_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_apb_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_a_rst);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_a_rst);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_a_rst err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst0);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst0);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst0 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst1);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst1);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst1 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst2);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst2);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst2 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst3);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst3);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst3 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst4);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst4);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst4 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst5);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst5);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst5 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst6);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst6);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst6 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(amlogic->pcie_rst7);
|
|
if (err) {
|
|
dev_err(dev, "deassert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_assert(amlogic->pcie_rst7);
|
|
if (err < 0) {
|
|
dev_err(dev, "assert pcie_rst7 err %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
|
|
set_rst_reg:
|
|
if (!flag) {
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~(BIT(amlogic->amlphy_rst_bit) |
|
|
BIT(amlogic->pcie_a_rst_bit) |
|
|
BIT(amlogic->apb_rst_bit) |
|
|
BIT(amlogic->u3p2_phy_apb_rst_bit) |
|
|
BIT(amlogic->pcie_pipe_bit) |
|
|
(amlogic->pcie_rst_mask << amlogic->pcie_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
usleep_range(20, 30);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val |= (BIT(amlogic->amlphy_rst_bit) |
|
|
BIT(amlogic->pcie_a_rst_bit) |
|
|
BIT(amlogic->apb_rst_bit) |
|
|
BIT(amlogic->u3p2_phy_apb_rst_bit) |
|
|
BIT(amlogic->pcie_pipe_bit) |
|
|
(amlogic->pcie_rst_mask << amlogic->pcie_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
usleep_range(10, 20);
|
|
flag++;
|
|
} else {
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~BIT(amlogic->pcie_pipe_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
usleep_range(10, 20);
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val |= BIT(amlogic->pcie_pipe_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
usleep_range(10, 20);
|
|
flag = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_reset_gpio(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct device_node *node = dev->of_node;
|
|
int ret;
|
|
|
|
ret = of_property_read_u32(node, "gpio-type",
|
|
&amlogic->gpio_type);
|
|
if (ret) {
|
|
dev_err(dev, "failed to request gpio-type\n");
|
|
return ret;
|
|
}
|
|
|
|
amlogic->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
|
|
if (gpio_is_valid(amlogic->reset_gpio)) {
|
|
if (!amlogic->is_rc)
|
|
return 0;
|
|
|
|
if (amlogic->gpio_type == 1) {
|
|
ret = devm_gpio_request_one(dev, amlogic->reset_gpio,
|
|
GPIOF_IN,
|
|
"pcie_perst");
|
|
if (ret) {
|
|
dev_err(dev, "unable to get reset gpio\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = gpio_direction_output(amlogic->reset_gpio, 0);
|
|
if (ret)
|
|
return ret;
|
|
} else {
|
|
ret = devm_gpio_request_one(dev, amlogic->reset_gpio,
|
|
GPIOF_OUT_INIT_LOW,
|
|
"pcie_perst");
|
|
if (ret) {
|
|
dev_err(dev, "unable to get reset gpio\n");
|
|
return ret;
|
|
}
|
|
gpio_set_value_cansleep(amlogic->reset_gpio, 0);
|
|
}
|
|
} else {
|
|
dev_err(dev, "failed to get reset-gpio\n");
|
|
return -ENODEV;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_set_reset_gpio(struct amlogic_pcie *amlogic, int flag)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
|
|
if (!amlogic->do_reset_gpio) {
|
|
dev_info(dev, "GPIO no need reset for W2 when resume\n");
|
|
usleep_range(500, 900);
|
|
return 0;
|
|
}
|
|
|
|
/*reset-gpio-type 0:Shared pad(no reset)1:OD pad2:Normal pad*/
|
|
if (amlogic->gpio_type == 0) {
|
|
dev_info(dev, "gpio multiplex, don't reset!\n");
|
|
} else if (amlogic->gpio_type == 1) {
|
|
dev_info(dev, "pad gpio\n");
|
|
if (gpio_is_valid(amlogic->reset_gpio)) {
|
|
dev_info(dev, "GPIO pad: assert reset\n");
|
|
ret = gpio_direction_output(amlogic->reset_gpio, 0);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (flag) {
|
|
usleep_range(90000, 110000);
|
|
ret = gpio_direction_input(amlogic->reset_gpio);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
}
|
|
} else {
|
|
dev_info(dev, "normal gpio\n");
|
|
if (gpio_is_valid(amlogic->reset_gpio)) {
|
|
dev_info(dev, "GPIO normal: assert reset\n");
|
|
gpio_set_value_cansleep(amlogic->reset_gpio, 0);
|
|
|
|
if (flag) {
|
|
usleep_range(90000, 110000);
|
|
gpio_set_value_cansleep(amlogic->reset_gpio, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_clks_for_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
|
|
amlogic->pcie_400m_clk = devm_clk_get(dev, "pcie_400m_clk");
|
|
if (IS_ERR(amlogic->pcie_400m_clk)) {
|
|
dev_err(dev, "pcie_400m_clk not found\n");
|
|
return PTR_ERR(amlogic->pcie_400m_clk);
|
|
}
|
|
|
|
amlogic->pcie_tl_clk = devm_clk_get(dev, "pcie_tl_clk");
|
|
if (IS_ERR(amlogic->pcie_tl_clk)) {
|
|
dev_err(dev, "pcie_tl_clk not found\n");
|
|
return PTR_ERR(amlogic->pcie_tl_clk);
|
|
}
|
|
|
|
amlogic->cts_pcie_clk = devm_clk_get(dev, "cts_pcie_clk");
|
|
if (IS_ERR(amlogic->cts_pcie_clk)) {
|
|
dev_err(dev, "cts_pcie_clk not found\n");
|
|
return PTR_ERR(amlogic->cts_pcie_clk);
|
|
}
|
|
|
|
amlogic->pcie_clk = devm_clk_get(dev, "pcie");
|
|
if (IS_ERR(amlogic->pcie_clk)) {
|
|
dev_err(dev, "pcie_clk not found\n");
|
|
return PTR_ERR(amlogic->pcie_clk);
|
|
}
|
|
|
|
amlogic->phy_clk = devm_clk_get(dev, "pcie_phy");
|
|
if (IS_ERR(amlogic->phy_clk)) {
|
|
dev_err(dev, "phy_clk not found\n");
|
|
return PTR_ERR(amlogic->phy_clk);
|
|
}
|
|
|
|
amlogic->refpll_clk = devm_clk_get(dev, "pcie_refpll");
|
|
if (IS_ERR(amlogic->refpll_clk)) {
|
|
dev_err(dev, "refpll_clk not found\n");
|
|
return PTR_ERR(amlogic->refpll_clk);
|
|
}
|
|
|
|
amlogic->dev_clk = devm_clk_get(dev, "pcie_hcsl");
|
|
if (IS_ERR(amlogic->dev_clk)) {
|
|
dev_err(dev, "dev_clk not found\n");
|
|
return PTR_ERR(amlogic->dev_clk);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_clks_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
|
|
amlogic->pcie_tl_clk = devm_clk_get(dev, "pcie_tl_clk");
|
|
if (IS_ERR(amlogic->pcie_tl_clk)) {
|
|
dev_err(dev, "pcie_tl_clk not found\n");
|
|
return PTR_ERR(amlogic->pcie_tl_clk);
|
|
}
|
|
|
|
amlogic->pcie_clk = devm_clk_get(dev, "pcie");
|
|
if (IS_ERR(amlogic->pcie_clk)) {
|
|
dev_err(dev, "pcie_clk not found\n");
|
|
return PTR_ERR(amlogic->pcie_clk);
|
|
}
|
|
|
|
amlogic->phy_clk = devm_clk_get(dev, "pcie_phy");
|
|
if (IS_ERR(amlogic->phy_clk)) {
|
|
dev_err(dev, "phy_clk not found\n");
|
|
return PTR_ERR(amlogic->phy_clk);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_clks(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie use AMLOGIC_PHY get clks\n");
|
|
ret = amlogic_pcie_get_clks_for_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie use M31_COMBPHY get clks\n");
|
|
ret = amlogic_pcie_get_clks_for_m31_phy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie use M31_PHY get clks\n");
|
|
ret = amlogic_pcie_get_clks_for_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int amlogic_pcie_parse_dt(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct device_node *node = dev->of_node;
|
|
struct resource *res;
|
|
int err;
|
|
|
|
err = of_property_read_u32(node, "phy-type",
|
|
&amlogic->phy_type);
|
|
if (err)
|
|
amlogic->phy_type = M31_PHY;
|
|
dev_dbg(amlogic->dev, "PCIE phy type is %d\n", amlogic->phy_type);
|
|
|
|
err = amlogic_pcie_get_reset_gpio(amlogic);
|
|
if (err)
|
|
return err;
|
|
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"apb-base");
|
|
amlogic->apb_base = devm_ioremap_resource(dev, res);
|
|
if (IS_ERR(amlogic->apb_base)) {
|
|
dev_err(dev, "failed to request apb_base\n");
|
|
return PTR_ERR(amlogic->apb_base);
|
|
}
|
|
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"pcictrl-base");
|
|
amlogic->pcictrl_base = devm_ioremap_resource(dev, res);
|
|
if (IS_ERR(amlogic->pcictrl_base)) {
|
|
dev_err(dev, "failed to request pcictrl_base\n");
|
|
return PTR_ERR(amlogic->pcictrl_base);
|
|
}
|
|
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"ecam-base");
|
|
if (res) {
|
|
amlogic->ecam_size = resource_size(res);
|
|
amlogic->ecam_bus_base = res->start;
|
|
} else {
|
|
dev_err(dev, "Missing *ecam-base* reg space\n");
|
|
return -ENODEV;
|
|
}
|
|
amlogic->ecam_base = devm_pci_remap_cfg_resource(dev, res);
|
|
if (IS_ERR(amlogic->ecam_base)) {
|
|
dev_err(dev, "failed to request ecam_base\n");
|
|
return PTR_ERR(amlogic->ecam_base);
|
|
}
|
|
|
|
err = amlogic_pcie_get_phys(amlogic);
|
|
if (err)
|
|
return err;
|
|
|
|
amlogic->lanes = 1;
|
|
err = of_property_read_u32(node, "num-lanes", &amlogic->lanes);
|
|
if (!err && amlogic->lanes == 0) {
|
|
dev_err(dev, "invalid num-lanes, default to use one lane\n");
|
|
amlogic->lanes = 1;
|
|
}
|
|
|
|
err = of_property_read_u32(node, "port-num", &amlogic->port_num);
|
|
if (err)
|
|
amlogic->port_num = 0;
|
|
dev_dbg(dev, "pcie port_num = %d\n", amlogic->port_num);
|
|
|
|
err = amlogic_pcie_get_resets(amlogic);
|
|
if (err)
|
|
return err;
|
|
|
|
err = amlogic_pcie_get_clks(amlogic);
|
|
if (err)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_parse_dt);
|
|
|
|
bool amlogic_pcie_link_up(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
bool ltssm_linkup = false;
|
|
u32 neg_link_speed = 0;
|
|
int cnt = 0;
|
|
u32 val = 0;
|
|
ktime_t start, end;
|
|
|
|
start = ktime_get();
|
|
|
|
do {
|
|
val = amlogic_pciectrl_read(amlogic, PCIE_A_CTRL5);
|
|
ltssm_linkup = PCIE_LINK_STATE_CHECK(val, LTSSM_L0);
|
|
|
|
if (unlikely(cnt >= WAIT_LINKUP_TIMEOUT)) {
|
|
dev_err(dev, "Error: Wait linkup timeout. Pls check pcie device\n");
|
|
return false;
|
|
} else if (unlikely(cnt >= amlogic->link_times)) {
|
|
dev_info(dev, "%s:%d, ltssm_state=0x%x\n", __func__, __LINE__,
|
|
((val >> 18) & 0x1f));
|
|
}
|
|
|
|
if (PCIE_LINK_STATE_CHECK(val, LTSSM_L1_IDLE)) {
|
|
dev_info(dev, "ltssm state into L1_IDLE\n");
|
|
break;
|
|
}
|
|
|
|
if (PCIE_LINK_STATE_CHECK(val, LTSSM_L2_IDLE)) {
|
|
dev_info(dev, "ltssm state into L2_IDLE\n");
|
|
break;
|
|
}
|
|
|
|
val = amlogic_pcieinter_read(amlogic, PCIE_BASIC_STATUS);
|
|
neg_link_speed = (val >> 8) & 0xf;
|
|
if (!neg_link_speed)
|
|
dev_dbg(dev, "speed no okay\n");
|
|
|
|
cnt++;
|
|
usleep_range(1, 3);
|
|
} while (!ltssm_linkup);
|
|
|
|
end = ktime_get();
|
|
dev_info_once(dev, "LTSSM consumes time:%llu us\n", ktime_to_us(ktime_sub(end, start)));
|
|
|
|
return true;
|
|
}
|
|
|
|
void amlogic_set_max_rd_req_size(struct amlogic_pcie *amlogic, int size)
|
|
{
|
|
int max_rd_req_size = 1;
|
|
u32 val = 0;
|
|
|
|
switch (size) {
|
|
case 128:
|
|
max_rd_req_size = 0;
|
|
break;
|
|
case 256:
|
|
max_rd_req_size = 1;
|
|
break;
|
|
case 512:
|
|
max_rd_req_size = 2;
|
|
break;
|
|
case 1024:
|
|
max_rd_req_size = 3;
|
|
break;
|
|
case 2048:
|
|
max_rd_req_size = 4;
|
|
break;
|
|
case 4096:
|
|
max_rd_req_size = 5;
|
|
break;
|
|
default:
|
|
max_rd_req_size = 1;
|
|
break;
|
|
}
|
|
|
|
val = amlogic_pcieinter_read(amlogic,
|
|
PCIE_CAP_OFFSET + PCI_EXP_DEVCTL);
|
|
val &= (~PCI_EXP_DEVCTL_READRQ);
|
|
val |= (max_rd_req_size << 12);
|
|
amlogic_pcieinter_write(amlogic, val,
|
|
PCIE_CAP_OFFSET + PCI_EXP_DEVCTL);
|
|
}
|
|
|
|
void amlogic_set_max_payload(struct amlogic_pcie *amlogic, int size)
|
|
{
|
|
int max_payload_size = 1;
|
|
u32 val = 0;
|
|
|
|
switch (size) {
|
|
case 128:
|
|
max_payload_size = 0;
|
|
break;
|
|
case 256:
|
|
max_payload_size = 1;
|
|
break;
|
|
case 512:
|
|
max_payload_size = 2;
|
|
break;
|
|
case 1024:
|
|
max_payload_size = 3;
|
|
break;
|
|
case 2048:
|
|
max_payload_size = 4;
|
|
break;
|
|
case 4096:
|
|
max_payload_size = 5;
|
|
break;
|
|
default:
|
|
max_payload_size = 1;
|
|
break;
|
|
}
|
|
|
|
val = amlogic_pcieinter_read(amlogic,
|
|
PCIE_CAP_OFFSET + PCI_EXP_DEVCTL);
|
|
val &= (~PCI_EXP_DEVCTL_PAYLOAD);
|
|
val |= (max_payload_size << 5);
|
|
amlogic_pcieinter_write(amlogic, val,
|
|
PCIE_CAP_OFFSET + PCI_EXP_DEVCTL);
|
|
}
|
|
|
|
static int amlogic_pcie_init_port_for_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
int err;
|
|
u32 regs;
|
|
u32 val;
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~(1 << amlogic->m31phy_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val |= (1 << amlogic->m31phy_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
err = amlogic_pcie_set_reset_for_m31_phy(amlogic, false);
|
|
if (err)
|
|
return err;
|
|
|
|
/* XCFGI[706] value from vendor recommend for temperature compensation */
|
|
val = readl(amlogic->phy_base + 0x858);
|
|
val |= BIT(2);
|
|
writel(val, amlogic->phy_base + 0x858);
|
|
|
|
/* XCFGI[322:320] value from vendor recommend for temperature compensation */
|
|
val = readl(amlogic->phy_base + 0x828);
|
|
val |= 0x6;
|
|
writel(val, amlogic->phy_base + 0x828);
|
|
|
|
/*PHY_Register_XCFGD value from vendor recommend*/
|
|
regs = readl(amlogic->phy_base + 0x470);
|
|
regs |= (1 << 6);
|
|
writel(regs, amlogic->phy_base + 0x470);
|
|
|
|
/*set phy for gen3 device*/
|
|
regs = readl(amlogic->phy_base);
|
|
regs |= BIT(19);
|
|
writel(regs, amlogic->phy_base);
|
|
usleep_range(20, 30);
|
|
|
|
err = amlogic_pcie_set_reset_for_m31_phy(amlogic, true);
|
|
if (err)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_init_port_for_m31_combphy(struct amlogic_pcie *amlogic)
|
|
{
|
|
int ret = 0;
|
|
u32 val;
|
|
|
|
/* phy init */
|
|
val = readl(amlogic->phy_base);
|
|
val &= ~(BIT(0) | BIT(10) | BIT(22));
|
|
val |= BIT(2) | BIT(12) | BIT(17) | BIT(23) | BIT(25);
|
|
writel(val, amlogic->phy_base);
|
|
val = readl(amlogic->phy_base + 0x4);
|
|
|
|
val |= BIT(11);
|
|
writel(val, amlogic->phy_base + 0x4);
|
|
|
|
/* XCFGI[706] value from vendor recommend for temperature compensation */
|
|
val = readl(amlogic->phy_base + 0x858);
|
|
val |= BIT(2);
|
|
writel(val, amlogic->phy_base + 0x858);
|
|
|
|
/* XCFGI[322:320] value from vendor recommend for temperature compensation */
|
|
val = readl(amlogic->phy_base + 0x828);
|
|
val |= 0x6;
|
|
writel(val, amlogic->phy_base + 0x828);
|
|
|
|
ret = amlogic_pcie_set_reset_for_m31_combphy(amlogic);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/*
|
|
* workaround pcie1 ctrl just for S5, S5 pcie0 no need
|
|
* value recommend by VLSI
|
|
*/
|
|
if (amlogic->port_num == 1 && is_meson_s5_cpu()) {
|
|
val = 0x73f << 2;
|
|
amlogic_pciectrl_write(amlogic, val, 0xb4);
|
|
val = amlogic_pciectrl_read(amlogic, 0xb8);
|
|
val = 0x390073;
|
|
amlogic_pciectrl_write(amlogic, val, 0xb8);
|
|
|
|
val = amlogic_pciectrl_read(amlogic, 0xbc);
|
|
val = 0xe0000;
|
|
amlogic_pciectrl_write(amlogic, val, 0xbc);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_do_pll_v1_set(struct amlogic_pcie *amlogic, int cnt)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
u32 reg[2];
|
|
int ret;
|
|
|
|
ret = of_property_read_u32_array(dev_of_node(dev),
|
|
kasprintf(GFP_KERNEL, "phy_pll_setting_%d", cnt),
|
|
reg, ARRAY_SIZE(reg));
|
|
if (ret) {
|
|
dev_err(dev, "amlogic phy pll V1 setting read failed\n");
|
|
return ret;
|
|
}
|
|
|
|
if (cnt != amlogic->pll_setting_number) {
|
|
if (is_meson_s6_cpu() && is_meson_rev_b() && reg[0] == 0x10)
|
|
reg[1] |= BIT(5);
|
|
|
|
writel(reg[1], amlogic->phy_base + reg[0]);
|
|
usleep_range(100, 200);
|
|
} else {
|
|
if (!(readl(amlogic->phy_base + reg[0]) & reg[1]))
|
|
dev_err(dev, "aml pcie phy pll lock failed\n");
|
|
else
|
|
dev_dbg(dev, "aml pcie phy pll locked\n");
|
|
}
|
|
dev_dbg(dev, "aml pcie phy pll cnt=%d, reg[0]=0x%x, reg[1]=0x%x\n", cnt, reg[0], reg[1]);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int amlogic_pcie_set_phy_pll(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct device_node *node = dev->of_node;
|
|
u32 aml_phy_pll_version;
|
|
int ret, i;
|
|
|
|
ret = of_property_read_u32(node, "aml_phy_pll_version", &aml_phy_pll_version);
|
|
if (ret)
|
|
return ret;
|
|
|
|
switch (aml_phy_pll_version) {
|
|
case AMLOGIC_PHY_PLL_V1:
|
|
default:
|
|
dev_dbg(dev, "amlogic pcie phy pll V1\n");
|
|
ret = of_property_read_u32(node, "pll_setting_number",
|
|
&amlogic->pll_setting_number);
|
|
if (ret)
|
|
return ret;
|
|
|
|
for (i = 1; i <= 6; i++)
|
|
ret = amlogic_pcie_do_pll_v1_set(amlogic, i);
|
|
|
|
for (i = 8; i <= amlogic->pll_setting_number; i++)
|
|
ret = amlogic_pcie_do_pll_v1_set(amlogic, i);
|
|
|
|
ret = amlogic_pcie_set_reset_for_aml_phy(amlogic);
|
|
if (ret)
|
|
return ret;
|
|
break;
|
|
case AMLOGIC_PHY_PLL_V2:
|
|
dev_dbg(dev, "amlogic pcie phy pll V2\n");
|
|
ret = of_property_read_u32(node, "pll_setting_number",
|
|
&amlogic->pll_setting_number);
|
|
if (ret)
|
|
return ret;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int amlogic_pcie_init_port_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct resource *efuse_res;
|
|
void __iomem *efuse_base = NULL;
|
|
u32 val, tmp;
|
|
int ret = 0, i;
|
|
|
|
ret = amlogic_pcie_set_reset_for_aml_phy(amlogic);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/*
|
|
* bit13 : always use pll1 ref clk for debug
|
|
* writel(readl(amlogic->phy_base + UPCRX_DR_REG1) | BIT(13),
|
|
* amlogic->phy_base + UPCRX_DR_REG1);
|
|
*/
|
|
|
|
/* fom bypass */
|
|
writel(0x42389800, amlogic->phy_base + EQVAL_CTRL_REG);
|
|
|
|
/* CTLE reset */
|
|
writel(0x2c032100, amlogic->phy_base + SW_CTRL_PMA_REG0);
|
|
|
|
/* LEQ timer */
|
|
writel(0x222e0, amlogic->phy_base + DELAY_TIME24);
|
|
|
|
/* tx rtem odt */
|
|
writel(0x3a98, amlogic->phy_base + SAMPLE_3RD_TIME);
|
|
|
|
/* tx detect RX decrease delay to 8us */
|
|
writel(0x1900190, amlogic->phy_base + SAMPLE_1ST_2ND_TIME);
|
|
|
|
/* Improved TX signal quality */
|
|
for (i = 0; i < 3; i++)
|
|
writel(0x54da54da, amlogic->phy_base + UPCTX_CONT1_REG2 + i * 4);
|
|
|
|
/* modify CDR PH_DIV and FR_DIV */
|
|
for (i = 0; i < 3; i++) {
|
|
val = readl(amlogic->phy_base + REG_DCHD_CDR_GEN1_REG + i * 4);
|
|
val &= ~GENMASK(7, 0);
|
|
val |= 0xa4;
|
|
writel(val, amlogic->phy_base + REG_DCHD_CDR_GEN1_REG + i * 4);
|
|
}
|
|
|
|
/* RX and TX trim */
|
|
efuse_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pci-efuse");
|
|
efuse_base = devm_ioremap(dev, efuse_res->start, resource_size(efuse_res));
|
|
if (IS_ERR(efuse_base)) {
|
|
dev_err(dev, "failed to request efuse_base\n");
|
|
return PTR_ERR(efuse_base);
|
|
}
|
|
|
|
if (efuse_base) {
|
|
tmp = readl(efuse_base);
|
|
dev_dbg(dev, "tx trim = 0x%x\n", (unsigned int)(tmp & GENMASK(5, 0)));
|
|
dev_dbg(dev, "rx trim = 0x%x\n", (unsigned int)((tmp & GENMASK(10, 6)) >> 6));
|
|
/* TX trim */
|
|
if (tmp & BIT(5)) {
|
|
val = readl(amlogic->phy_base + UPCTX_CTRL_REG);
|
|
val &= ~GENMASK(7, 0);
|
|
val |= (tmp & GENMASK(4, 0));
|
|
writel(val, amlogic->phy_base + UPCTX_CTRL_REG);
|
|
} else {
|
|
val = readl(amlogic->phy_base + UPCTX_CTRL_REG);
|
|
val &= ~GENMASK(7, 0);
|
|
val |= 0x10;
|
|
writel(val, amlogic->phy_base + UPCTX_CTRL_REG);
|
|
}
|
|
|
|
/* RX trim */
|
|
if (tmp & BIT(10)) {
|
|
for (i = 0; i < 5; i++) {
|
|
val = readl(amlogic->phy_base + REG_DCHA_AFE_LPBK_REG + i * 4);
|
|
val &= ~GENMASK(7, 4);
|
|
val |= (((tmp & GENMASK(9, 6)) >> 6) << 4);
|
|
writel(val, amlogic->phy_base + REG_DCHA_AFE_LPBK_REG + i * 4);
|
|
}
|
|
} else {
|
|
for (i = 0; i < 5; i++) {
|
|
val = readl(amlogic->phy_base + REG_DCHA_AFE_LPBK_REG + i * 4);
|
|
val &= ~GENMASK(7, 4);
|
|
val |= (0x7 << 4);
|
|
writel(val, amlogic->phy_base + REG_DCHA_AFE_LPBK_REG + i * 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* GEN3 EQ */
|
|
for (i = 0; i < 4; i++) {
|
|
val = readl(amlogic->phy_base + REG_DCHD_EQ_LPBK_REG + i * 4);
|
|
val &= ~(2 << 6);
|
|
val |= (1 << 6);
|
|
writel(val, amlogic->phy_base + REG_DCHD_EQ_LPBK_REG + i * 4);
|
|
}
|
|
|
|
/* close RC EQ */
|
|
amlogic_pcieinter_write(amlogic, 0, PHYMAC_CFG);
|
|
|
|
/* set phy pll */
|
|
if (of_property_read_bool(dev_of_node(dev), "phy_pll_setting_1")) {
|
|
ret = amlogic_pcie_set_phy_pll(amlogic);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int amlogic_pcie_init_port(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
u32 reg;
|
|
u32 val;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie init port and AMLOGIC_PHY\n");
|
|
ret = amlogic_pcie_init_port_for_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie init port and M31_COMBPHY\n");
|
|
ret = amlogic_pcie_init_port_for_m31_combphy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie init port and M31_PHY\n");
|
|
ret = amlogic_pcie_init_port_for_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
|
|
val = amlogic_pciectrl_read(amlogic, PCIE_A_CTRL0);
|
|
if (amlogic->is_rc)
|
|
val |= PORT_TYPE;
|
|
else
|
|
val &= ~PORT_TYPE;
|
|
amlogic_pciectrl_write(amlogic, val, PCIE_A_CTRL0);
|
|
|
|
if (amlogic->link_gen == 1) {
|
|
u32 exp_cap_off = aml_pcie_find_capability(amlogic, PCI_CAP_ID_EXP);
|
|
|
|
reg = amlogic_pcieinter_read(amlogic,
|
|
PCI_CFG_SPACE + exp_cap_off + PCI_EXP_LNKCAP);
|
|
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
|
|
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
|
|
reg |= PCI_EXP_LNKCAP_SLS_2_5GB;
|
|
amlogic_pcieinter_write(amlogic, reg,
|
|
PCI_CFG_SPACE + exp_cap_off + PCI_EXP_LNKCAP);
|
|
}
|
|
|
|
reg = amlogic_pcieinter_readw(amlogic, exp_cap_off + PCI_EXP_LNKCTL2);
|
|
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
|
|
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
|
|
reg |= PCI_EXP_LNKCAP_SLS_2_5GB;
|
|
amlogic_pcieinter_writew(amlogic, reg, exp_cap_off + PCI_EXP_LNKCTL2);
|
|
}
|
|
} else if (amlogic->link_gen == 2) {
|
|
u32 exp_cap_off = aml_pcie_find_capability(amlogic, PCI_CAP_ID_EXP);
|
|
|
|
reg = amlogic_pcieinter_read(amlogic,
|
|
PCI_CFG_SPACE + exp_cap_off + PCI_EXP_LNKCAP);
|
|
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_5_0GB) {
|
|
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
|
|
reg |= PCI_EXP_LNKCAP_SLS_5_0GB;
|
|
amlogic_pcieinter_write(amlogic, reg,
|
|
PCI_CFG_SPACE + exp_cap_off + PCI_EXP_LNKCAP);
|
|
}
|
|
|
|
reg = amlogic_pcieinter_readw(amlogic, exp_cap_off + PCI_EXP_LNKCTL2);
|
|
if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_5_0GB) {
|
|
reg &= ~((u32)PCI_EXP_LNKCAP_SLS);
|
|
reg |= PCI_EXP_LNKCAP_SLS_5_0GB;
|
|
amlogic_pcieinter_writew(amlogic, reg, exp_cap_off + PCI_EXP_LNKCTL2);
|
|
}
|
|
} else {
|
|
if (amlogic->link_gen > 3)
|
|
dev_err(dev, "Set pcie parameter link_speed is ERR\n");
|
|
}
|
|
|
|
if (amlogic_pcie_set_reset_gpio(amlogic, 1))
|
|
dev_err(dev, "Set pcie reset gpio faile\n");
|
|
|
|
if (!amlogic_pcie_link_up(amlogic))
|
|
return -ETIMEDOUT;
|
|
|
|
usleep_range(100, 200);
|
|
reg = amlogic_pcieinter_read(amlogic, PCIE_BASIC_STATUS);
|
|
|
|
dev_info(dev, "current link speed is GEN%d,link width is x%d\n",
|
|
((reg >> 8) & 0x3f), (reg & 0xff));
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_init_port);
|
|
|
|
static int amlogic_pcie_get_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct resource *res;
|
|
|
|
amlogic->pcie_phy = devm_of_phy_get(dev, dev->of_node, "pcie-phy");
|
|
if (IS_ERR(amlogic->pcie_phy)) {
|
|
if (PTR_ERR(amlogic->pcie_phy) != -EPROBE_DEFER)
|
|
goto get_phy_reg;
|
|
}
|
|
|
|
get_phy_reg:
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
|
"phy-base");
|
|
amlogic->phy_base = devm_ioremap_resource(dev, res);
|
|
if (IS_ERR(amlogic->phy_base)) {
|
|
dev_err(dev, "failed to request phy_base\n");
|
|
return PTR_ERR(amlogic->phy_base);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int amlogic_pcie_get_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct resource *res;
|
|
|
|
amlogic->pcie_phy = devm_of_phy_get(dev, dev->of_node, "pcie-phy");
|
|
if (IS_ERR(amlogic->pcie_phy)) {
|
|
if (PTR_ERR(amlogic->pcie_phy) != -EPROBE_DEFER)
|
|
goto get_phy_reg;
|
|
}
|
|
|
|
get_phy_reg:
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aml-phy-base");
|
|
amlogic->phy_base = devm_ioremap_resource(dev, res);
|
|
if (IS_ERR(amlogic->phy_base)) {
|
|
dev_err(dev, "failed to request amlogic phy_base\n");
|
|
return PTR_ERR(amlogic->phy_base);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int amlogic_pcie_get_phys(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie use AMLOGIC_PHY get phy\n");
|
|
ret = amlogic_pcie_get_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie use M31_COMBPHY get phy\n");
|
|
ret = amlogic_pcie_get_m31_phy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie use M31_PHY get phy\n");
|
|
ret = amlogic_pcie_get_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_get_phys);
|
|
|
|
void amlogic_pcie_deinit_phys(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
u32 val;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie deinit AMLOGIC_PHY\n");
|
|
if (amlogic_pcie_set_reset_gpio(amlogic, 0))
|
|
dev_err(dev, "suspend set pcie reset gpio faile\n");
|
|
|
|
val = readl(amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
val &= ~(BIT(amlogic->amlphy_rst_bit) |
|
|
BIT(amlogic->pcie_a_rst_bit) |
|
|
BIT(amlogic->apb_rst_bit) |
|
|
BIT(amlogic->pcie_pipe_bit) |
|
|
(amlogic->pcie_rst_mask << amlogic->pcie_rst_bit));
|
|
writel(val, amlogic->rst_base + RESETCTRL1_OFFSET);
|
|
|
|
writel(0x0, amlogic->phy_base + UPCTX_CONT0_REG2);
|
|
writel(0x0, amlogic->phy_base + UPCTX_CONT1_REG2);
|
|
writel(0x0, amlogic->phy_base + UPCTX_DR_REG0);
|
|
writel(0x0, amlogic->phy_base + UPCRX_DR_REG0);
|
|
writel(0x0, amlogic->phy_base + UPCRX_DR_REG1);
|
|
writel(0x0, amlogic->phy_base + REG_MISC_GEN1_REG);
|
|
writel(0x0, amlogic->phy_base + REG_DCHA_AFE_GEN1_REG);
|
|
writel(0x0, amlogic->phy_base + REG_DCHA_DFE_GEN1_REG);
|
|
writel(0x0, amlogic->phy_base + REG_DCHD_CDR_GEN1_REG);
|
|
writel(0x0, amlogic->phy_base + REG_DCHD_EQ_GEN1_REG);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie deinit M31_COMBPHY\n");
|
|
val = readl(amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
val &= ~(1 << amlogic->phy_rst_bit);
|
|
writel(val, amlogic->rst_base + RESETCTRL0_OFFSET);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie deinit M31_PHY\n");
|
|
break;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_deinit_phys);
|
|
|
|
void amlogic_pcie_init_phys(struct amlogic_pcie *amlogic)
|
|
{
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_init_phys);
|
|
|
|
static int amlogic_pcie_enable_clks_for_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int err = 0, ret = 0;
|
|
|
|
ret = clk_set_rate(amlogic->pcie_400m_clk, 400000000);
|
|
err = clk_prepare_enable(amlogic->pcie_400m_clk);
|
|
if (err || ret) {
|
|
dev_err(dev, "unable to enable pcie_400m_clk clock\n");
|
|
return err;
|
|
}
|
|
|
|
ret = clk_set_rate(amlogic->pcie_tl_clk, 125000000);
|
|
err = clk_prepare_enable(amlogic->pcie_tl_clk);
|
|
if (err || ret) {
|
|
dev_err(dev, "unable to enable pcie_tl_clk clock\n");
|
|
goto err_400m_clk;
|
|
}
|
|
|
|
ret = clk_set_rate(amlogic->cts_pcie_clk, 200000000);
|
|
err = clk_prepare_enable(amlogic->cts_pcie_clk);
|
|
if (err || ret) {
|
|
dev_err(dev, "unable to enable cts_pcie_clk clock\n");
|
|
goto err_tl_clk;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->dev_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable dev_clk clock\n");
|
|
goto err_cts_pcie_clk;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->phy_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable phy_clk clock\n");
|
|
goto err_dev_clk;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->refpll_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable refpll_clk clock\n");
|
|
goto err_phy_clk;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->pcie_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable pcie_clk clock\n");
|
|
goto err_refpll_clk;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_refpll_clk:
|
|
clk_disable_unprepare(amlogic->refpll_clk);
|
|
err_phy_clk:
|
|
clk_disable_unprepare(amlogic->phy_clk);
|
|
err_dev_clk:
|
|
clk_disable_unprepare(amlogic->dev_clk);
|
|
err_cts_pcie_clk:
|
|
clk_disable_unprepare(amlogic->cts_pcie_clk);
|
|
err_tl_clk:
|
|
clk_disable_unprepare(amlogic->pcie_tl_clk);
|
|
err_400m_clk:
|
|
clk_disable_unprepare(amlogic->pcie_400m_clk);
|
|
return err;
|
|
}
|
|
|
|
static int amlogic_pcie_enable_clks_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int err = 0, ret = 0;
|
|
|
|
ret = clk_set_rate(amlogic->pcie_tl_clk, 125000000);
|
|
err = clk_prepare_enable(amlogic->pcie_tl_clk);
|
|
if (err || ret) {
|
|
dev_err(dev, "unable to enable pcie_tl_clk clock\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->phy_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable phy_clk clock\n");
|
|
goto err_tl_clk;
|
|
}
|
|
|
|
err = clk_prepare_enable(amlogic->pcie_clk);
|
|
if (err) {
|
|
dev_err(dev, "unable to enable pcie_clk clock\n");
|
|
goto err_phy_clk;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_phy_clk:
|
|
clk_disable_unprepare(amlogic->phy_clk);
|
|
err_tl_clk:
|
|
clk_disable_unprepare(amlogic->pcie_tl_clk);
|
|
return err;
|
|
}
|
|
|
|
int amlogic_pcie_enable_clocks(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
int ret = 0;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie use AMLOGIC_PHY enable clks\n");
|
|
ret = amlogic_pcie_enable_clks_for_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie use M31_COMBPHY enable clks\n");
|
|
ret = amlogic_pcie_enable_clks_for_m31_phy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie use M31_PHY enable clks\n");
|
|
ret = amlogic_pcie_enable_clks_for_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_enable_clocks);
|
|
|
|
static void amlogic_pcie_disable_clks_for_m31_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
clk_disable_unprepare(amlogic->pcie_clk);
|
|
clk_disable_unprepare(amlogic->refpll_clk);
|
|
clk_disable_unprepare(amlogic->phy_clk);
|
|
clk_disable_unprepare(amlogic->dev_clk);
|
|
clk_disable_unprepare(amlogic->cts_pcie_clk);
|
|
clk_disable_unprepare(amlogic->pcie_tl_clk);
|
|
clk_disable_unprepare(amlogic->pcie_400m_clk);
|
|
}
|
|
|
|
static void amlogic_pcie_disable_clks_for_aml_phy(struct amlogic_pcie *amlogic)
|
|
{
|
|
clk_disable_unprepare(amlogic->pcie_clk);
|
|
clk_disable_unprepare(amlogic->phy_clk);
|
|
clk_disable_unprepare(amlogic->pcie_tl_clk);
|
|
clk_disable_unprepare(amlogic->pcie_400m_clk);
|
|
}
|
|
|
|
void amlogic_pcie_disable_clocks(struct amlogic_pcie *amlogic)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
|
|
switch (amlogic->phy_type) {
|
|
case AMLOGIC_PHY:
|
|
dev_dbg(dev, " pcie use AMLOGIC_PHY disable clks\n");
|
|
amlogic_pcie_disable_clks_for_aml_phy(amlogic);
|
|
break;
|
|
case M31_COMBPHY:
|
|
dev_dbg(dev, " pcie use M31_COMBPHY disable clks\n");
|
|
amlogic_pcie_disable_clks_for_m31_phy(amlogic);
|
|
break;
|
|
case M31_PHY:
|
|
default:
|
|
dev_dbg(dev, " pcie use M31_PHY disable clks\n");
|
|
amlogic_pcie_disable_clks_for_m31_phy(amlogic);
|
|
break;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_disable_clocks);
|
|
|
|
void amlogic_pcie_cfg_addr_map(struct amlogic_pcie *amlogic,
|
|
unsigned int atr_base,
|
|
u64 src_addr,
|
|
u64 trsl_addr,
|
|
int size,
|
|
int trsl_param)
|
|
{
|
|
struct device *dev = amlogic->dev;
|
|
u32 val;
|
|
|
|
/* ATR_SRC_ADDR_LOW:
|
|
* - bit 0: enable entry,
|
|
* - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1)
|
|
* - bits 7-11: reserved
|
|
* - bits 12-31: start of source address
|
|
*/
|
|
val = (src_addr & 0xfffff000) | ((size & 0x3f) << 1) | (1 << 0);
|
|
amlogic_pcieinter_write(amlogic, val, atr_base + ATR_SRC_ADDR_LOW);
|
|
|
|
amlogic_pcieinter_write(amlogic,
|
|
(src_addr >> 32),
|
|
atr_base + ATR_SRC_ADDR_HIGH);
|
|
amlogic_pcieinter_write(amlogic,
|
|
(trsl_addr & 0xfffff000),
|
|
atr_base + ATR_TRSL_ADDR_LOW);
|
|
amlogic_pcieinter_write(amlogic,
|
|
(trsl_addr >> 32),
|
|
atr_base + ATR_TRSL_ADDR_HIGH);
|
|
amlogic_pcieinter_write(amlogic, trsl_param,
|
|
atr_base + ATR_TRSL_PARAM);
|
|
|
|
dev_dbg(dev,
|
|
"ATR Map:0x%010llx %s 0x%010llx [0x%010llx] (param: 0x%06x)\n",
|
|
src_addr, (trsl_param & 0x400000) ? "<-" : "->", trsl_addr,
|
|
((u64)1) << (size + 1), trsl_param);
|
|
}
|
|
EXPORT_SYMBOL_GPL(amlogic_pcie_cfg_addr_map);
|