Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Minghuan Lian | a4d6b61 | 2014-10-31 13:43:44 +0800 | [diff] [blame] | 2 | /* |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 3 | * Copyright 2017-2020 NXP |
Minghuan Lian | fdab545 | 2015-01-21 17:29:20 +0800 | [diff] [blame] | 4 | * Copyright 2014-2015 Freescale Semiconductor, Inc. |
Minghuan Lian | a4d6b61 | 2014-10-31 13:43:44 +0800 | [diff] [blame] | 5 | * Layerscape PCIe driver |
Minghuan Lian | a4d6b61 | 2014-10-31 13:43:44 +0800 | [diff] [blame] | 6 | */ |
| 7 | |
Simon Glass | 0f2af88 | 2020-05-10 11:40:05 -0600 | [diff] [blame] | 8 | #include <log.h> |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 9 | #include <asm/global_data.h> |
Minghuan Lian | a4d6b61 | 2014-10-31 13:43:44 +0800 | [diff] [blame] | 10 | #include <asm/io.h> |
Minghuan Lian | fdab545 | 2015-01-21 17:29:20 +0800 | [diff] [blame] | 11 | #include <errno.h> |
| 12 | #include <malloc.h> |
Simon Glass | 243182c | 2017-05-17 08:23:06 -0600 | [diff] [blame] | 13 | #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ |
| 14 | defined(CONFIG_ARM) |
| 15 | #include <asm/arch/clock.h> |
| 16 | #endif |
Hou Zhiqiang | 09716a7b | 2016-12-13 14:54:16 +0800 | [diff] [blame] | 17 | #include "pcie_layerscape.h" |
Minghuan Lian | fdab545 | 2015-01-21 17:29:20 +0800 | [diff] [blame] | 18 | |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 19 | DECLARE_GLOBAL_DATA_PTR; |
| 20 | |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 21 | LIST_HEAD(ls_pcie_list); |
| 22 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 23 | unsigned int dbi_readl(struct ls_pcie *pcie, unsigned int offset) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 24 | { |
| 25 | return in_le32(pcie->dbi + offset); |
| 26 | } |
| 27 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 28 | void dbi_writel(struct ls_pcie *pcie, unsigned int value, unsigned int offset) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 29 | { |
| 30 | out_le32(pcie->dbi + offset, value); |
| 31 | } |
| 32 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 33 | unsigned int ctrl_readl(struct ls_pcie *pcie, unsigned int offset) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 34 | { |
| 35 | if (pcie->big_endian) |
| 36 | return in_be32(pcie->ctrl + offset); |
| 37 | else |
| 38 | return in_le32(pcie->ctrl + offset); |
| 39 | } |
| 40 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 41 | void ctrl_writel(struct ls_pcie *pcie, unsigned int value, |
| 42 | unsigned int offset) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 43 | { |
| 44 | if (pcie->big_endian) |
| 45 | out_be32(pcie->ctrl + offset, value); |
| 46 | else |
| 47 | out_le32(pcie->ctrl + offset, value); |
| 48 | } |
| 49 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 50 | void ls_pcie_dbi_ro_wr_en(struct ls_pcie *pcie) |
| 51 | { |
| 52 | u32 reg, val; |
| 53 | |
| 54 | reg = PCIE_MISC_CONTROL_1_OFF; |
| 55 | val = dbi_readl(pcie, reg); |
| 56 | val |= PCIE_DBI_RO_WR_EN; |
| 57 | dbi_writel(pcie, val, reg); |
| 58 | } |
| 59 | |
| 60 | void ls_pcie_dbi_ro_wr_dis(struct ls_pcie *pcie) |
| 61 | { |
| 62 | u32 reg, val; |
| 63 | |
| 64 | reg = PCIE_MISC_CONTROL_1_OFF; |
| 65 | val = dbi_readl(pcie, reg); |
| 66 | val &= ~PCIE_DBI_RO_WR_EN; |
| 67 | dbi_writel(pcie, val, reg); |
| 68 | } |
| 69 | |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 70 | static int ls_pcie_ltssm(struct ls_pcie *pcie) |
| 71 | { |
| 72 | u32 state; |
| 73 | uint svr; |
| 74 | |
| 75 | svr = get_svr(); |
| 76 | if (((svr >> SVR_VAR_PER_SHIFT) & SVR_LS102XA_MASK) == SVR_LS102XA) { |
| 77 | state = ctrl_readl(pcie, LS1021_PEXMSCPORTSR(pcie->idx)); |
| 78 | state = (state >> LS1021_LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; |
| 79 | } else { |
| 80 | state = ctrl_readl(pcie, PCIE_PF_DBG) & LTSSM_STATE_MASK; |
| 81 | } |
| 82 | |
| 83 | return state; |
| 84 | } |
| 85 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 86 | int ls_pcie_link_up(struct ls_pcie *pcie) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 87 | { |
| 88 | int ltssm; |
| 89 | |
| 90 | ltssm = ls_pcie_ltssm(pcie); |
| 91 | if (ltssm < LTSSM_PCIE_L0) |
| 92 | return 0; |
| 93 | |
| 94 | return 1; |
| 95 | } |
| 96 | |
Xiaowei Bao | 13b277f | 2020-07-09 23:31:33 +0800 | [diff] [blame] | 97 | void ls_pcie_atu_outbound_set(struct ls_pcie *pcie, int idx, int type, |
Xiaowei Bao | ecb85db | 2020-07-09 23:31:39 +0800 | [diff] [blame] | 98 | u64 phys, u64 bus_addr, u64 size) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 99 | { |
| 100 | dbi_writel(pcie, PCIE_ATU_REGION_OUTBOUND | idx, PCIE_ATU_VIEWPORT); |
| 101 | dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_BASE); |
| 102 | dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_BASE); |
| 103 | dbi_writel(pcie, (u32)phys + size - 1, PCIE_ATU_LIMIT); |
| 104 | dbi_writel(pcie, (u32)bus_addr, PCIE_ATU_LOWER_TARGET); |
| 105 | dbi_writel(pcie, bus_addr >> 32, PCIE_ATU_UPPER_TARGET); |
| 106 | dbi_writel(pcie, type, PCIE_ATU_CR1); |
| 107 | dbi_writel(pcie, PCIE_ATU_ENABLE, PCIE_ATU_CR2); |
| 108 | } |
| 109 | |
| 110 | /* Use bar match mode and MEM type as default */ |
Xiaowei Bao | ecb85db | 2020-07-09 23:31:39 +0800 | [diff] [blame] | 111 | void ls_pcie_atu_inbound_set(struct ls_pcie *pcie, u32 pf, u32 vf_flag, |
| 112 | int type, int idx, int bar, u64 phys) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 113 | { |
| 114 | dbi_writel(pcie, PCIE_ATU_REGION_INBOUND | idx, PCIE_ATU_VIEWPORT); |
| 115 | dbi_writel(pcie, (u32)phys, PCIE_ATU_LOWER_TARGET); |
| 116 | dbi_writel(pcie, phys >> 32, PCIE_ATU_UPPER_TARGET); |
Xiaowei Bao | b4d63b0 | 2020-07-09 23:31:36 +0800 | [diff] [blame] | 117 | dbi_writel(pcie, type | PCIE_ATU_FUNC_NUM(pf), PCIE_ATU_CR1); |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 118 | dbi_writel(pcie, PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE | |
Xiaowei Bao | ecb85db | 2020-07-09 23:31:39 +0800 | [diff] [blame] | 119 | (vf_flag ? PCIE_ATU_FUNC_NUM_MATCH_EN : 0) | |
| 120 | (vf_flag ? PCIE_ATU_VFBAR_MATCH_MODE_EN : 0) | |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 121 | PCIE_ATU_BAR_NUM(bar), PCIE_ATU_CR2); |
| 122 | } |
| 123 | |
Xiaowei Bao | bb3f713 | 2020-07-09 23:31:40 +0800 | [diff] [blame] | 124 | void ls_pcie_dump_atu(struct ls_pcie *pcie, u32 win_num, u32 type) |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 125 | { |
Xiaowei Bao | bb3f713 | 2020-07-09 23:31:40 +0800 | [diff] [blame] | 126 | int win_idx; |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 127 | |
Xiaowei Bao | bb3f713 | 2020-07-09 23:31:40 +0800 | [diff] [blame] | 128 | for (win_idx = 0; win_idx < win_num; win_idx++) { |
| 129 | dbi_writel(pcie, type | win_idx, PCIE_ATU_VIEWPORT); |
| 130 | debug("iATU%d:\n", win_idx); |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 131 | debug("\tLOWER PHYS 0x%08x\n", |
| 132 | dbi_readl(pcie, PCIE_ATU_LOWER_BASE)); |
| 133 | debug("\tUPPER PHYS 0x%08x\n", |
| 134 | dbi_readl(pcie, PCIE_ATU_UPPER_BASE)); |
Xiaowei Bao | bb3f713 | 2020-07-09 23:31:40 +0800 | [diff] [blame] | 135 | if (type == PCIE_ATU_REGION_OUTBOUND) { |
| 136 | debug("\tLOWER BUS 0x%08x\n", |
| 137 | dbi_readl(pcie, PCIE_ATU_LOWER_TARGET)); |
| 138 | debug("\tUPPER BUS 0x%08x\n", |
| 139 | dbi_readl(pcie, PCIE_ATU_UPPER_TARGET)); |
| 140 | debug("\tLIMIT 0x%08x\n", |
| 141 | dbi_readl(pcie, PCIE_ATU_LIMIT)); |
| 142 | } |
Minghuan Lian | c106784 | 2016-12-13 14:54:17 +0800 | [diff] [blame] | 143 | debug("\tCR1 0x%08x\n", |
| 144 | dbi_readl(pcie, PCIE_ATU_CR1)); |
| 145 | debug("\tCR2 0x%08x\n", |
| 146 | dbi_readl(pcie, PCIE_ATU_CR2)); |
| 147 | } |
| 148 | } |