01 · QUESTION
무엇을 증명할 것인가
Linux가 장치를 찾지 못했을 때, 정말 PCI core 문제인지 아니면 그 전에 link 자체가 L0에 들어오지 못한 것인지 어떤 증거로 구분하는가?
Synopsys DesignWare PCIe Controller와 별도 PHY hard macro가 PIPE로 연결된 구성을 기준으로 전원, REFCLK, PERST#, SerDes/PCS, LTSSM, DBI, iATU와 Configuration Read까지 확인합니다. 이 글은 Linux 로그를 출발점으로 삼지 않습니다. 같은 사건이 보드, controller, firmware, kernel에서 어떤 이름과 번호로 바뀌는지 아래에서 위로 연결합니다.
02 · CONTRACT
입력과 완료 조건
| 구분 | 확인할 내용 |
|---|---|
| 입력 | 안정된 전원 rail, 100MHz REFCLK, 해제 가능한 PERST#, 연결된 lane와 endpoint |
| 출력 | L0 상태의 link와 Bus/Device/Function 0번 configuration header 응답 |
| 소유권 | PHY와 LTSSM은 controller hardware, bus number와 resource window는 firmware 및 Linux host bridge가 소유 |
| 완료 조건 | Link Status의 negotiated speed/width가 유효하고 Vendor ID read가 0xffff가 아님 |
03 · BOTTOM-UP
완전히 아래에서 시작하는 8단계
Endpoint 전원 rail과 analog rail이 규격 범위에 들어온 뒤 REFCLK가 안정되고 PERST#가 최소 요구 시간 뒤 해제되어야 한다. common-clock 설계인지 SRNS/SRIS인지에 따라 양쪽 clock tolerance와 SSC 조건이 달라진다. CLKREQ#와 WAKE#는 link training의 필수 신호는 아니지만 ASPM, clock power management와 wake 동작을 검증할 때 반드시 분리해 본다.
증거: 전원 시퀀스 파형, REFCLK 주파수/SSC, PERST# 해제 시점, endpoint reset pin level
Root Complex transmitter가 receiver termination을 검출하면서 Detect에서 Polling으로 이동한다. lane polarity inversion은 허용될 수 있지만 lane reversal 지원은 controller 구성에 달려 있다. insertion loss, AC coupling capacitor 위치, differential impedance와 lane mapping이 틀리면 Polling.Active 또는 Recovery에서 반복한다.
증거: 고속 scope/BER 장비, controller receiver-detect bitmap, lane별 training 상태
Ordered Set 교환으로 lane number, link number, speed와 training control을 맞춘다. Gen1에서 먼저 link를 만든 뒤 directed speed change로 상위 generation에 올라가는 controller도 많다. Recovery가 반복되면 equalization, clock, signal integrity 또는 상대편 capability를 구분해야 한다.
증거: LTSSM state history, Link Training bit, negotiated width/speed, equalization status
Data Link Layer는 TLP에 sequence number와 LCRC를 붙이고 replay buffer로 손실을 복구한다. Posted, Non-Posted, Completion은 header/data credit가 따로 관리된다. credit가 0이면 물리 link가 L0여도 transaction이 진행하지 않는 것처럼 보일 수 있다.
증거: Bad DLLP/LCRC, Replay Number Rollover, replay timer, flow-control credit counter
Configuration Read는 requester ID, tag, first byte enable을 담아 전송되고 endpoint는 같은 tag를 가진 Completion with Data로 응답한다. Unsupported Request, Completer Abort, Completion Timeout은 서로 다른 failure다. Memory Write는 posted이므로 protocol completion이 없고 device register readback이나 별도 status로 완료를 확인해야 한다.
증거: protocol analyzer TLP, AER Uncorrectable Status, Completion Timeout, requester/completer ID
첫 64 bytes에는 Vendor/Device ID, Command/Status, Class Code, Header Type와 BAR가 있다. PCIe Capability에는 Device/Link/Slot control과 status가 있고 0x100 이후 Extended Capability에는 AER, ACS, ATS, SR-IOV 등이 연결된다. ECAM은 bus/device/function/register를 physical address bit field로 바꾼다.
증거: ECAM base와 bus-range, `lspci -xxxx`, capability pointer loop, BAR size probe 결과
Device Tree의 `reg`, `ranges`, `bus-range`, `num-lanes`, `max-link-speed`, reset/clock/PHY와 interrupt-map이 host controller를 설명한다. ACPI 시스템은 MCFG로 ECAM segment와 bus range를 제공하고 _CRS로 I/O와 MMIO aperture를 제공한다. firmware range와 실제 outbound ATU window가 일치해야 한다.
증거: live DT, ACPI MCFG/_CRS dump, controller DBI/ATU register와 host bridge resource log
host controller driver가 clock/reset/PHY를 켜고 root bus resource와 config-space accessor를 등록한다. PCI core가 device 0 function 0부터 Vendor ID를 읽어 function 존재 여부를 판단한다. 이때 실패하면 Linux log만 보지 말고 같은 시점의 LTSSM, AER, ATU와 ECAM physical address를 묶어서 본다.
증거: `dmesg`, dynamic debug, `lspci -vv`, `/sys/bus/pci/devices`, host controller trace
0. Board · 전원, reset, reference clock
Endpoint 전원 rail과 analog rail이 규격 범위에 들어온 뒤 REFCLK가 안정되고 PERST#가 최소 요구 시간 뒤 해제되어야 한다. common-clock 설계인지 SRNS/SRIS인지에 따라 양쪽 clock tolerance와 SSC 조건이 달라진다. CLKREQ#와 WAKE#는 link training의 필수 신호는 아니지만 ASPM, clock power management와 wake 동작을 검증할 때 반드시 분리해 본다.
남길 증거: 전원 시퀀스 파형, REFCLK 주파수/SSC, PERST# 해제 시점, endpoint reset pin level
이 단계가 실패하면 configuration read나 LTSSM register를 해석할 이유가 없다.
1. Electrical · Receiver detect와 lane electrical
Root Complex transmitter가 receiver termination을 검출하면서 Detect에서 Polling으로 이동한다. lane polarity inversion은 허용될 수 있지만 lane reversal 지원은 controller 구성에 달려 있다. insertion loss, AC coupling capacitor 위치, differential impedance와 lane mapping이 틀리면 Polling.Active 또는 Recovery에서 반복한다.
남길 증거: 고속 scope/BER 장비, controller receiver-detect bitmap, lane별 training 상태
모든 예상 lane이 detect되지 않으면 x4 설계가 x1로 축소되거나 link가 성립하지 않는다.
2. LTSSM · TS1/TS2와 Detect → Polling → Configuration → L0
Ordered Set 교환으로 lane number, link number, speed와 training control을 맞춘다. Gen1에서 먼저 link를 만든 뒤 directed speed change로 상위 generation에 올라가는 controller도 많다. Recovery가 반복되면 equalization, clock, signal integrity 또는 상대편 capability를 구분해야 한다.
남길 증거: LTSSM state history, Link Training bit, negotiated width/speed, equalization status
L0에 들어오기 전에는 정상 Memory/Configuration TLP 교환을 기대하지 않는다.
3. Data Link · Sequence number, LCRC, ACK/NAK와 flow-control credit
Data Link Layer는 TLP에 sequence number와 LCRC를 붙이고 replay buffer로 손실을 복구한다. Posted, Non-Posted, Completion은 header/data credit가 따로 관리된다. credit가 0이면 물리 link가 L0여도 transaction이 진행하지 않는 것처럼 보일 수 있다.
남길 증거: Bad DLLP/LCRC, Replay Number Rollover, replay timer, flow-control credit counter
link up와 transaction forward progress를 같은 의미로 보지 않는다.
4. Transaction · Memory, Configuration, Completion TLP
Configuration Read는 requester ID, tag, first byte enable을 담아 전송되고 endpoint는 같은 tag를 가진 Completion with Data로 응답한다. Unsupported Request, Completer Abort, Completion Timeout은 서로 다른 failure다. Memory Write는 posted이므로 protocol completion이 없고 device register readback이나 별도 status로 완료를 확인해야 한다.
남길 증거: protocol analyzer TLP, AER Uncorrectable Status, Completion Timeout, requester/completer ID
0xffff read가 no-device인지 poisoned/completion timeout인지 AER와 root-port status로 나눈다.
5. Config · 4KiB Configuration Space와 capability list
첫 64 bytes에는 Vendor/Device ID, Command/Status, Class Code, Header Type와 BAR가 있다. PCIe Capability에는 Device/Link/Slot control과 status가 있고 0x100 이후 Extended Capability에는 AER, ACS, ATS, SR-IOV 등이 연결된다. ECAM은 bus/device/function/register를 physical address bit field로 바꾼다.
남길 증거: ECAM base와 bus-range, `lspci -xxxx`, capability pointer loop, BAR size probe 결과
ECAM window와 bus-range가 틀리면 link가 정상이어도 Linux는 0xffff만 읽는다.
6. Firmware · DT/ACPI host bridge description
Device Tree의 `reg`, `ranges`, `bus-range`, `num-lanes`, `max-link-speed`, reset/clock/PHY와 interrupt-map이 host controller를 설명한다. ACPI 시스템은 MCFG로 ECAM segment와 bus range를 제공하고 _CRS로 I/O와 MMIO aperture를 제공한다. firmware range와 실제 outbound ATU window가 일치해야 한다.
남길 증거: live DT, ACPI MCFG/_CRS dump, controller DBI/ATU register와 host bridge resource log
주소 변환 창이 겹치거나 크기가 다르면 enumeration 뒤 BAR access에서 abort가 난다.
7. Linux · host probe와 첫 configuration read
host controller driver가 clock/reset/PHY를 켜고 root bus resource와 config-space accessor를 등록한다. PCI core가 device 0 function 0부터 Vendor ID를 읽어 function 존재 여부를 판단한다. 이때 실패하면 Linux log만 보지 말고 같은 시점의 LTSSM, AER, ATU와 ECAM physical address를 묶어서 본다.
남길 증거: `dmesg`, dynamic debug, `lspci -vv`, `/sys/bus/pci/devices`, host controller trace
Vendor ID와 class code가 안정적으로 읽혀야 resource sizing 단계로 넘어간다.
04 · DIAGRAMS
주소와 상태가 이동하는 모습
안정된 전원 rail, 100MHz REFCLK, 해제 가능한 PERST#, 연결된 lane와 endpoint
PHY와 LTSSM은 controller hardware, bus number와 resource window는 firmware 및 Linux host bridge가 소유
L0 상태의 link와 Bus/Device/Function 0번 configuration header 응답
Link Status의 negotiated speed/width가 유효하고 Vendor ID read가 0xffff가 아님
05 · SYNOPSYS DESIGNWARE IP
Synopsys DesignWare PCIe Controller와 PHY 경계
여기서는 SoC에 가장 널리 통합되는 Synopsys DesignWare PCIe digital controller를 Root Complex로 사용하고, 별도의 PCIe PHY hard macro가 PIPE로 연결된 구성을 기준으로 읽습니다. 실제 PHY register와 SoC application register는 공정·SoC 업체마다 달라지지만, DWC DBI/Port Logic/iATU와 Linux dw_pcie 공통 계층의 경계는 반복해서 나타납니다.
SoC application logic
전원 domain, APB/AXI clock, core/PHY reset, PERST#, device type(RC/EP), LTSSM enable을 제어합니다.
- 관찰
- vendor glue driver와 application register
- 대표 실패
- PERST#와 LTSSM enable 순서가 바뀌면 Detect 이전 또는 Polling에서 정지
DBI configuration
Root Port의 Type-1 Configuration Space와 PCIe Capability를 CPU가 programming하는 내부 register 창입니다.
- 관찰
- dbi_base, DBI read/write, PCI_COMMAND/LINK_CAP
- 대표 실패
- DBI clock/reset이 없으면 값이 0 또는 bus fault이며 link 문제와 구분해야 함
Port Logic / LTSSM
lane mode, N_FTS, speed change, equalization과 Detect→Polling→Configuration→L0 상태를 관리합니다.
- 관찰
- 0x710, 0x728, 0x72c, 0x80c, 0x890 계열
- 대표 실패
- controller 상태는 Polling인데 PHY PLL만 lock된 것을 link-up으로 오판
Transaction / Data Link
TLP 생성·routing, ACK/NAK, replay, flow-control credit, Root Port bridge 동작을 수행합니다.
- 관찰
- AER, replay/credit counter, protocol analyzer
- 대표 실패
- L0인데 Completion Timeout이면 electrical보다 routing/iATU/config path를 먼저 확인
AXI bridge
CPU의 AXI transaction을 PCIe TLP로, inbound PCIe request를 SoC AXI transaction으로 바꿉니다.
- 관찰
- AXI decode, outstanding ID, ordering, slave/master error
- 대표 실패
- AXI DECERR/SLVERR를 endpoint completion 오류와 구분
iATU
CPU address와 PCIe address/BDF를 outbound·inbound region으로 변환합니다. 구형 viewport 방식과 v4.80a 이후 unrolled register 방식이 있습니다.
- 관찰
- region type, base, limit, target, enable
- 대표 실패
- L0인데 config read가 0xffff이면 CFG0/CFG1 region과 BDF target을 우선 검사
MSI / eDMA option
DWC 내부 MSI controller와 선택적 eDMA가 포함될 수 있지만 SoC가 외부 MSI domain이나 별도 DMA를 사용할 수도 있습니다.
- 관찰
- MSI address/mask/status, eDMA channel/LLP
- 대표 실패
- IP configuration과 Linux driver가 기대하는 interrupt/DMA 구현 불일치
PIPE / PCIe PHY
Controller와 PHY 사이에서 power state, rate, electrical idle, receiver detect, Tx/Rx data와 status를 교환합니다.
- 관찰
- PIPE state와 vendor PHY status를 같은 timestamp로 수집
- 대표 실패
- PHY ready와 controller LTSSM 진행 사이에서 처음 끊긴 handshake를 찾음
PHY와 Controller가 만나는 PIPE 경계
한쪽 register만 보고 link 상태를 판정하지 않습니다. 동일 사건에 대해 PHY evidence와 controller evidence를 같은 행에 놓고 처음 불일치하는 구간을 찾습니다.
| 단계 | PHY 쪽에서 확인 | DWC Controller 쪽에서 확인 | 경계 판정 |
|---|---|---|---|
| Power/reset | analog/digital rail, PLL/SerDes reset, calibration 완료 | DBI/APB/AXI clock과 core reset, LTSSM disable 유지 | PHY calibration 전에 LTSSM을 시작하지 않음 |
| Reference clock | REFCLK 수신, PLL lock, SRNS/SRIS/common-clock mode | Link Capability와 SRIS deskew/N_FTS 정책 | PLL lock은 receiver detect나 link-up을 의미하지 않음 |
| Receiver Detect | termination detect 결과와 lane별 Rx readiness | Detect state에서 PIPE 요청을 발행하고 결과를 소비 | 예상 lane별 detect bitmap과 LTSSM state를 함께 기록 |
| Polling / TS1·TS2 | 직렬화·복구 clock·CDR, Tx/Rx electrical path | ordered set 생성/해석, lane/link number와 polarity·lane reversal 정책 | PIPE RxStatus만 보지 말고 controller training state와 lane map을 대조 |
| Gen3+ Equalization | CTLE/DFE, Tx preset/coeff 적용, eye/BER와 PVT margin | Recovery.Equalization phase, preset request·평가와 directed speed change | PHY FOM/eye가 좋아도 controller phase가 timeout이면 PIPE control 교환 검사 |
| L0 / power state | electrical idle exit, L0s/L1/L1SS 진입·복귀, clock/power gating | DLL active, credit/replay와 ASPM 정책 | ASPM off 비교로 PHY wake 지연과 protocol 오류를 분리 |
DWC 공개 register와 읽는 목적
| Register/영역 | 역할 | 검증 시 주의점 |
|---|---|---|
| DBI base | Root Port Type-1 config와 capability | DBI read-only write enable은 제한된 초기화 구간에서만 사용 |
| PCIE_PORT_LINK_CONTROL 0x710 | DLL enable과 x1/x2/x4/x8/x16 link mode | synthesis lane 수, DT num-lanes, PHY lane 수가 모두 일치해야 함 |
| PCIE_PORT_DEBUG0 0x728 | 하위 6bit LTSSM state | 0x11은 L0이며 단발 read보다 histogram이 유용 |
| PCIE_PORT_DEBUG1 0x72c | link-up과 link-in-training bit | 두 bit와 표준 PCI_EXP_LNKSTA를 함께 비교 |
| PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c | negotiated width가 아니라 target width와 speed-change 요청 | PORT_LOGIC_SPEED_CHANGE가 장시간 남으면 Recovery/equalization 확인 |
| GEN3_RELATED_OFF 0x890 | Gen3 equalization·rate shadow 관련 DWC port logic | IP version과 PHY PIPE 세대에 맞는 programming만 적용 |
| PCIE_VERSION_NUMBER/TYPE 0x8f8/0x8fc | DWC component version과 type | quirk를 SoC 이름만으로 선택하지 말고 IP version도 기록 |
| iATU viewport/unroll | CFG0/CFG1/MEM/IO outbound와 inbound region | v4.80a 전후 접근 방식을 혼동하면 잘못된 register에 기록 |
PHY를 controller register로 판단하지 않는다
DWC Port Debug의 LTSSM state는 controller가 보는 protocol state다. PLL lock, CDR lock, receiver detect, lane calibration, equalizer adaptation은 PHY 또는 SoC application register에서 따로 읽어야 한다. 두 register bank의 timestamp를 맞춰야 PIPE 경계의 deadlock을 찾을 수 있다.
PIPE 세대에 따라 책임이 이동한다
전통적인 PIPE에서는 PHY PCS가 encoding/decoding과 elastic buffer의 더 많은 부분을 담당할 수 있다. PIPE 5 SerDes architecture는 8b/10b·128b/130b encoding과 일부 protocol-specific 동작을 controller 쪽으로 옮긴다. 따라서 같은 ‘PHY 문제’라는 말도 사용한 PIPE architecture를 먼저 확정해야 한다.
Synopsys common core와 SoC glue를 분리한다
Linux의 pcie-designware*.c는 DBI, iATU, Root Port와 공통 link 설정을 제공한다. Exynos, i.MX, Tegra 같은 glue driver는 clock/reset/PHY/application register와 LTSSM start_link를 구현한다. probe call graph에서 두 계층을 섞으면 누가 PHY를 켜야 하는지 놓치기 쉽다.
공개 register와 vendor PHY register의 범위
DWC Port Logic과 iATU offset은 Linux 소스에서 확인할 수 있지만, 실제 Synopsys PHY hard macro의 세부 tuning register는 라이선스 databook 및 SoC vendor TRM에 의존한다. 홈페이지에서는 공개적으로 검증 가능한 상태 이름과 경계를 사용하고 임의의 PHY offset을 만들어 쓰지 않습니다.
06 · DETAILED MANUAL
DWC Controller와 PHY를 실제로 구분해서 읽는 상세 매뉴얼
Synopsys 전체 databook은 IP 설정과 라이선스 옵션에 따라 내용이 달라집니다. 아래 내용은 공개된 Synopsys 제품 정보, PIPE 구조 설명, Linux v6.18.37 DWC 공통 드라이버와 공개 register 정의에서 다시 확인할 수 있는 범위만 사용합니다. PHY tuning 값이나 SoC application register offset처럼 공개 자료만으로 확정할 수 없는 값은 임의로 채우지 않고, 어느 문서와 어느 측정값에서 확인해야 하는지를 적습니다.
공개적으로 다시 확인할 수 있는 자료
공개되지 않은 vendor register나 integration별 offset을 추측해서 채우지 않았습니다. 아래 제조사 자료, architecture 문서와 Linux v6.18.37 원본에서 다시 확인할 수 있는 범위만 사용했습니다.
Synopsys PCIe 5.0 complete solution
Controller, PHY, verification IP가 별도 구성요소이며 PIPE 5.x와 SerDes architecture를 지원한다는 공개 제품 범위
Synopsys PCIe 5.0 PHY
PHY가 담당하는 SerDes, equalization, lane margining과 진단 기능의 공개 범위
Synopsys PIPE 5.1 SerDes architecture
기존 PIPE와 SerDes architecture에서 PCS 책임이 이동하는 이유
Linux v6.18.37 DWC header
DWC Port Logic, link debug, iATU와 eDMA 공개 register offset
Linux DWC Devicetree binding
clock, reset, PHY, lane, speed와 DWC resource description
07 · REGISTERS
읽어야 할 상태와 해석
값 하나만 떼어 보지 말고 동일 사건의 enable, status, ownership, completion register를 한 줄에 기록합니다. read-to-clear나 write-one-to-clear 속성은 반드시 datasheet에서 먼저 확인합니다.
| 레지스터/상태 | 소유 블록 | 검증할 의미 |
|---|---|---|
| PERST# / REFCLK | board signal | reset deassert 전에 clock과 power가 안정됐는지 확인 |
| LTSSM state | controller-specific | Detect/Polling/Recovery/L0 중 어디서 반복하는지 기록 |
| PCI_EXP_LNKSTA | PCIe Capability + 0x12 | 현재 speed, negotiated width, training 상태 |
| PCI_COMMAND | Config 0x04 | Memory/IO/Bus Master enable은 enumeration 이후 별도 단계 |
| PCI_BAR0..5 | Config 0x10..0x24 | size probe와 assigned address를 구분 |
| AER UE/CE Status | Extended Capability | Completion timeout, malformed TLP, bad DLLP/LCRC 분리 |
08 · LINUX SOURCE
Linux v6.18.37 원본 코드와 줄별 해설
라인 번호를 고정해 외우는 대신 함수 선언을 기준으로 Linux v6.18.37 tree에서 다시 찾았습니다. 로컬 tree에 있는 파일은 실제 코드를 직접 싣고, 나머지는 원본 파일과 읽을 함수 좌표를 연결했습니다.
Linux v6.18.37 · 실제 원본 코드
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의
drivers/pci/controller/dwc/pcie-designware.h:70-200
70#define LINK_WAIT_IATU 9
71
72/* Synopsys-specific PCIe configuration registers */
73#define PCIE_PORT_FORCE 0x708
74#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23)
75
76#define PCIE_PORT_AFR 0x70C
77#define PORT_AFR_N_FTS_MASK GENMASK(15, 8)
78#define PORT_AFR_N_FTS(n) FIELD_PREP(PORT_AFR_N_FTS_MASK, n)
79#define PORT_AFR_CC_N_FTS_MASK GENMASK(23, 16)
80#define PORT_AFR_CC_N_FTS(n) FIELD_PREP(PORT_AFR_CC_N_FTS_MASK, n)
81#define PORT_AFR_ENTER_ASPM BIT(30)
82#define PORT_AFR_L0S_ENTRANCE_LAT_SHIFT 24
83#define PORT_AFR_L0S_ENTRANCE_LAT_MASK GENMASK(26, 24)
84#define PORT_AFR_L1_ENTRANCE_LAT_SHIFT 27
85#define PORT_AFR_L1_ENTRANCE_LAT_MASK GENMASK(29, 27)
86
87#define PCIE_PORT_LINK_CONTROL 0x710
88#define PORT_LINK_DLL_LINK_EN BIT(5)
89#define PORT_LINK_FAST_LINK_MODE BIT(7)
90#define PORT_LINK_MODE_MASK GENMASK(21, 16)
91#define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n)
92#define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1)
93#define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3)
94#define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7)
95#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
96#define PORT_LINK_MODE_16_LANES PORT_LINK_MODE(0x1f)
97
98#define PCIE_PORT_LANE_SKEW 0x714
99#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)
100
101#define PCIE_PORT_DEBUG0 0x728
102#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
103#define PORT_LOGIC_LTSSM_STATE_L0 0x11
104#define PCIE_PORT_DEBUG1 0x72C
105#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
106#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29)
107
108#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
109#define PORT_LOGIC_N_FTS_MASK GENMASK(7, 0)
110#define PORT_LOGIC_SPEED_CHANGE BIT(17)
111#define PORT_LOGIC_LINK_WIDTH_MASK GENMASK(12, 8)
112#define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n)
113#define PORT_LOGIC_LINK_WIDTH_1_LANES PORT_LOGIC_LINK_WIDTH(0x1)
114#define PORT_LOGIC_LINK_WIDTH_2_LANES PORT_LOGIC_LINK_WIDTH(0x2)
115#define PORT_LOGIC_LINK_WIDTH_4_LANES PORT_LOGIC_LINK_WIDTH(0x4)
116#define PORT_LOGIC_LINK_WIDTH_8_LANES PORT_LOGIC_LINK_WIDTH(0x8)
117
118#define PCIE_MSI_ADDR_LO 0x820
119#define PCIE_MSI_ADDR_HI 0x824
120#define PCIE_MSI_INTR0_ENABLE 0x828
121#define PCIE_MSI_INTR0_MASK 0x82C
122#define PCIE_MSI_INTR0_STATUS 0x830
123
124#define GEN3_RELATED_OFF 0x890
125#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0)
126#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13)
127#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16)
128#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24
129#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24)
130
131#define GEN3_EQ_CONTROL_OFF 0x8A8
132#define GEN3_EQ_CONTROL_OFF_FB_MODE GENMASK(3, 0)
133#define GEN3_EQ_CONTROL_OFF_PHASE23_EXIT_MODE BIT(4)
134#define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC GENMASK(23, 8)
135#define GEN3_EQ_CONTROL_OFF_FOM_INC_INITIAL_EVAL BIT(24)
136
137#define GEN3_EQ_FB_MODE_DIR_CHANGE_OFF 0x8AC
138#define GEN3_EQ_FMDC_T_MIN_PHASE23 GENMASK(4, 0)
139#define GEN3_EQ_FMDC_N_EVALS GENMASK(9, 5)
140#define GEN3_EQ_FMDC_MAX_PRE_CURSOR_DELTA GENMASK(13, 10)
141#define GEN3_EQ_FMDC_MAX_POST_CURSOR_DELTA GENMASK(17, 14)
142
143#define PCIE_PORT_MULTI_LANE_CTRL 0x8C0
144#define PORT_MLTI_UPCFG_SUPPORT BIT(7)
145
146#define PCIE_VERSION_NUMBER 0x8F8
147#define PCIE_VERSION_TYPE 0x8FC
148
149/*
150 * iATU inbound and outbound windows CSRs. Before the IP-core v4.80a each
151 * iATU region CSRs had been indirectly accessible by means of the dedicated
152 * viewport selector. The iATU/eDMA CSRs space was re-designed in DWC PCIe
153 * v4.80a in a way so the viewport was unrolled into the directly accessible
154 * iATU/eDMA CSRs space.
155 */
156#define PCIE_ATU_VIEWPORT 0x900
157#define PCIE_ATU_REGION_DIR_IB BIT(31)
158#define PCIE_ATU_REGION_DIR_OB 0
159#define PCIE_ATU_VIEWPORT_BASE 0x904
160#define PCIE_ATU_UNROLL_BASE(dir, index) \
161 (((index) << 9) | ((dir == PCIE_ATU_REGION_DIR_IB) ? BIT(8) : 0))
162#define PCIE_ATU_VIEWPORT_SIZE 0x2C
163#define PCIE_ATU_REGION_CTRL1 0x000
164#define PCIE_ATU_INCREASE_REGION_SIZE BIT(13)
165#define PCIE_ATU_TYPE_MEM 0x0
166#define PCIE_ATU_TYPE_IO 0x2
167#define PCIE_ATU_TYPE_CFG0 0x4
168#define PCIE_ATU_TYPE_CFG1 0x5
169#define PCIE_ATU_TYPE_MSG 0x10
170#define PCIE_ATU_TD BIT(8)
171#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20)
172#define PCIE_ATU_REGION_CTRL2 0x004
173#define PCIE_ATU_ENABLE BIT(31)
174#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
175#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28)
176#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22)
177#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
178#define PCIE_ATU_LOWER_BASE 0x008
179#define PCIE_ATU_UPPER_BASE 0x00C
180#define PCIE_ATU_LIMIT 0x010
181#define PCIE_ATU_LOWER_TARGET 0x014
182#define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x)
183#define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x)
184#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x)
185#define PCIE_ATU_UPPER_TARGET 0x018
186#define PCIE_ATU_UPPER_LIMIT 0x020
187
188#define PCIE_MISC_CONTROL_1_OFF 0x8BC
189#define PCIE_DBI_RO_WR_EN BIT(0)
190
191#define PCIE_MSIX_DOORBELL 0x948
192#define PCIE_MSIX_DOORBELL_PF_SHIFT 24
193
194/*
195 * eDMA CSRs. DW PCIe IP-core v4.70a and older had the eDMA registers accessible
196 * over the Port Logic registers space. Afterwards the unrolled mapping was
197 * introduced so eDMA and iATU could be accessed via a dedicated registers
198 * space.
199 */
200#define PCIE_DMA_VIEWPORT_BASE 0x970#define LINK_WAIT_IATU 9
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* Synopsys-specific PCIe configuration registers */
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
#define PCIE_PORT_FORCE 0x708
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_PORT_AFR 0x70C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_N_FTS_MASK GENMASK(15, 8)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_N_FTS(n) FIELD_PREP(PORT_AFR_N_FTS_MASK, n)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_CC_N_FTS_MASK GENMASK(23, 16)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_CC_N_FTS(n) FIELD_PREP(PORT_AFR_CC_N_FTS_MASK, n)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_ENTER_ASPM BIT(30)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_L0S_ENTRANCE_LAT_SHIFT 24
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_L0S_ENTRANCE_LAT_MASK GENMASK(26, 24)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_L1_ENTRANCE_LAT_SHIFT 27
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_AFR_L1_ENTRANCE_LAT_MASK GENMASK(29, 27)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_PORT_LINK_CONTROL 0x710
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_DLL_LINK_EN BIT(5)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_FAST_LINK_MODE BIT(7)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_MASK GENMASK(21, 16)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LINK_MODE_16_LANES PORT_LINK_MODE(0x1f)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_PORT_LANE_SKEW 0x714
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_PORT_DEBUG0 0x728
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LTSSM_STATE_L0 0x11
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_PORT_DEBUG1 0x72C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_N_FTS_MASK GENMASK(7, 0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_SPEED_CHANGE BIT(17)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH_MASK GENMASK(12, 8)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH_1_LANES PORT_LOGIC_LINK_WIDTH(0x1)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH_2_LANES PORT_LOGIC_LINK_WIDTH(0x2)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH_4_LANES PORT_LOGIC_LINK_WIDTH(0x4)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_LOGIC_LINK_WIDTH_8_LANES PORT_LOGIC_LINK_WIDTH(0x8)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_MSI_ADDR_LO 0x820
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_MSI_ADDR_HI 0x824
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_MSI_INTR0_ENABLE 0x828
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_MSI_INTR0_MASK 0x82C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_MSI_INTR0_STATUS 0x830
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define GEN3_RELATED_OFF 0x890
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define GEN3_EQ_CONTROL_OFF 0x8A8
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_CONTROL_OFF_FB_MODE GENMASK(3, 0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_CONTROL_OFF_PHASE23_EXIT_MODE BIT(4)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC GENMASK(23, 8)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_CONTROL_OFF_FOM_INC_INITIAL_EVAL BIT(24)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define GEN3_EQ_FB_MODE_DIR_CHANGE_OFF 0x8AC
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_FMDC_T_MIN_PHASE23 GENMASK(4, 0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_FMDC_N_EVALS GENMASK(9, 5)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_FMDC_MAX_PRE_CURSOR_DELTA GENMASK(13, 10)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define GEN3_EQ_FMDC_MAX_POST_CURSOR_DELTA GENMASK(17, 14)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_PORT_MULTI_LANE_CTRL 0x8C0
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PORT_MLTI_UPCFG_SUPPORT BIT(7)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_VERSION_NUMBER 0x8F8
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_VERSION_TYPE 0x8FC
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/*
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* iATU inbound and outbound windows CSRs. Before the IP-core v4.80a each
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* iATU region CSRs had been indirectly accessible by means of the dedicated
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* viewport selector. The iATU/eDMA CSRs space was re-designed in DWC PCIe
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* v4.80a in a way so the viewport was unrolled into the directly accessible
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* iATU/eDMA CSRs space.
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
#define PCIE_ATU_VIEWPORT 0x900
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_REGION_DIR_IB BIT(31)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_REGION_DIR_OB 0
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_VIEWPORT_BASE 0x904
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_UNROLL_BASE(dir, index) \
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(((index) << 9) | ((dir == PCIE_ATU_REGION_DIR_IB) ? BIT(8) : 0))
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_VIEWPORT_SIZE 0x2C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_REGION_CTRL1 0x000
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_INCREASE_REGION_SIZE BIT(13)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TYPE_MEM 0x0
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TYPE_IO 0x2
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TYPE_CFG0 0x4
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TYPE_CFG1 0x5
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TYPE_MSG 0x10
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_TD BIT(8)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_REGION_CTRL2 0x004
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_ENABLE BIT(31)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_LOWER_BASE 0x008
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_UPPER_BASE 0x00C
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_LIMIT 0x010
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_LOWER_TARGET 0x014
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_UPPER_TARGET 0x018
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_ATU_UPPER_LIMIT 0x020
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_MISC_CONTROL_1_OFF 0x8BC
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_DBI_RO_WR_EN BIT(0)
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
#define PCIE_MSIX_DOORBELL 0x948
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
#define PCIE_MSIX_DOORBELL_PF_SHIFT 24
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/*
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* eDMA CSRs. DW PCIe IP-core v4.70a and older had the eDMA registers accessible
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* over the Port Logic registers space. Afterwards the unrolled mapping was
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* introduced so eDMA and iATU could be accessed via a dedicated registers
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* space.
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
#define PCIE_DMA_VIEWPORT_BASE 0x970
Synopsys DWC Port Logic, link debug와 iATU 공개 register 정의의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
Linux v6.18.37 · 실제 원본 코드
DWC component version과 type을 실제 register에서 판별하는 과정
drivers/pci/controller/dwc/pcie-designware.c:194-260
194 of_property_read_u32(np, "num-lanes", &pci->num_lanes);
195
196 if (of_property_read_bool(np, "snps,enable-cdm-check"))
197 dw_pcie_cap_set(pci, CDM_CHECK);
198
199 return 0;
200}
201
202void dw_pcie_version_detect(struct dw_pcie *pci)
203{
204 u32 ver;
205
206 /* The content of the CSR is zero on DWC PCIe older than v4.70a */
207 ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_NUMBER);
208 if (!ver)
209 return;
210
211 if (pci->version && pci->version != ver)
212 dev_warn(pci->dev, "Versions don't match (%08x != %08x)\n",
213 pci->version, ver);
214 else
215 pci->version = ver;
216
217 ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_TYPE);
218
219 if (pci->type && pci->type != ver)
220 dev_warn(pci->dev, "Types don't match (%08x != %08x)\n",
221 pci->type, ver);
222 else
223 pci->type = ver;
224}
225
226u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap)
227{
228 return PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
229 NULL, pci);
230}
231EXPORT_SYMBOL_GPL(dw_pcie_find_capability);
232
233u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
234{
235 return PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, 0, cap, NULL, pci);
236}
237EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
238
239void dw_pcie_remove_capability(struct dw_pcie *pci, u8 cap)
240{
241 u8 cap_pos, pre_pos, next_pos;
242 u16 reg;
243
244 cap_pos = PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
245 &pre_pos, pci);
246 if (!cap_pos)
247 return;
248
249 reg = dw_pcie_readw_dbi(pci, cap_pos);
250 next_pos = (reg & 0xff00) >> 8;
251
252 dw_pcie_dbi_ro_wr_en(pci);
253 if (pre_pos == PCI_CAPABILITY_LIST)
254 dw_pcie_writeb_dbi(pci, PCI_CAPABILITY_LIST, next_pos);
255 else
256 dw_pcie_writeb_dbi(pci, pre_pos + 1, next_pos);
257 dw_pcie_dbi_ro_wr_dis(pci);
258}
259EXPORT_SYMBOL_GPL(dw_pcie_remove_capability);
260 of_property_read_u32(np, "num-lanes", &pci->num_lanes);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (of_property_read_bool(np, "snps,enable-cdm-check"))
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_cap_set(pci, CDM_CHECK);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
return 0;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
void dw_pcie_version_detect(struct dw_pcie *pci)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 DWC component version과 type을 실제 register에서 판별하는 과정의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
u32 ver;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* The content of the CSR is zero on DWC PCIe older than v4.70a */
원본 주석입니다. DWC component version과 type을 실제 register에서 판별하는 과정에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_NUMBER);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
if (!ver)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
return;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pci->version && pci->version != ver)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dev_warn(pci->dev, "Versions don't match (%08x != %08x)\n",
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
pci->version, ver);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
else
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
pci->version = ver;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_TYPE);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pci->type && pci->type != ver)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dev_warn(pci->dev, "Types don't match (%08x != %08x)\n",
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
pci->type, ver);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
else
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
pci->type = ver;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap)
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
return PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
NULL, pci);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
EXPORT_SYMBOL_GPL(dw_pcie_find_capability);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
return PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, 0, cap, NULL, pci);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
void dw_pcie_remove_capability(struct dw_pcie *pci, u8 cap)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 DWC component version과 type을 실제 register에서 판별하는 과정의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
u8 cap_pos, pre_pos, next_pos;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
u16 reg;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
cap_pos = PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
&pre_pos, pci);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (!cap_pos)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
return;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
reg = dw_pcie_readw_dbi(pci, cap_pos);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
next_pos = (reg & 0xff00) >> 8;
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_dbi_ro_wr_en(pci);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (pre_pos == PCI_CAPABILITY_LIST)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_writeb_dbi(pci, PCI_CAPABILITY_LIST, next_pos);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
else
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writeb_dbi(pci, pre_pos + 1, next_pos);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
dw_pcie_dbi_ro_wr_dis(pci);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
EXPORT_SYMBOL_GPL(dw_pcie_remove_capability);
DWC component version과 type을 실제 register에서 판별하는 과정의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
Linux v6.18.37 · 실제 원본 코드
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup
drivers/pci/controller/dwc/pcie-designware.c:1155-1215
1155 */
1156 l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
1157 l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
1158 PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
1159 PCI_L1SS_CAP_L1_PM_SS);
1160 dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
1161}
1162
1163void dw_pcie_setup(struct dw_pcie *pci)
1164{
1165 u32 val;
1166
1167 dw_pcie_link_set_max_speed(pci);
1168
1169 /* Configure Gen1 N_FTS */
1170 if (pci->n_fts[0]) {
1171 val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
1172 val &= ~(PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK);
1173 val |= PORT_AFR_N_FTS(pci->n_fts[0]);
1174 val |= PORT_AFR_CC_N_FTS(pci->n_fts[0]);
1175 dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val);
1176 }
1177
1178 /* Configure Gen2+ N_FTS */
1179 if (pci->n_fts[1]) {
1180 val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
1181 val &= ~PORT_LOGIC_N_FTS_MASK;
1182 val |= pci->n_fts[1];
1183 dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
1184 }
1185
1186 if (dw_pcie_cap_is(pci, CDM_CHECK)) {
1187 val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
1188 val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS |
1189 PCIE_PL_CHK_REG_CHK_REG_START;
1190 dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
1191 }
1192
1193 val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
1194 val &= ~PORT_LINK_FAST_LINK_MODE;
1195 val |= PORT_LINK_DLL_LINK_EN;
1196 dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
1197
1198 dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
1199}
1200
1201resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
1202 const char *reg_name,
1203 resource_size_t cpu_phys_addr)
1204{
1205 struct device *dev = pci->dev;
1206 struct device_node *np = dev->of_node;
1207 int index;
1208 u64 reg_addr, fixup_addr;
1209 u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
1210
1211 /* Look up reg_name address on parent bus */
1212 index = of_property_match_string(np, "reg-names", reg_name);
1213
1214 if (index < 0) {
1215 dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);*/
원본 주석입니다. Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
l1ss_cap = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
l1ss_cap &= ~(PCI_L1SS_CAP_PCIPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_1 |
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2 |
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
PCI_L1SS_CAP_L1_PM_SS);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, l1ss_cap);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
void dw_pcie_setup(struct dw_pcie *pci)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
u32 val;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_link_set_max_speed(pci);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* Configure Gen1 N_FTS */
원본 주석입니다. Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
if (pci->n_fts[0]) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
val &= ~(PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
val |= PORT_AFR_N_FTS(pci->n_fts[0]);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
val |= PORT_AFR_CC_N_FTS(pci->n_fts[0]);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* Configure Gen2+ N_FTS */
원본 주석입니다. Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
if (pci->n_fts[1]) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
val &= ~PORT_LOGIC_N_FTS_MASK;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
val |= pci->n_fts[1];
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (dw_pcie_cap_is(pci, CDM_CHECK)) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS |
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
PCIE_PL_CHK_REG_CHK_REG_START;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
공유 상태나 MMIO를 읽습니다. 이 값은 단순 변수라기보다 hardware가 갱신한 시점과 read ordering을 포함해 해석해야 합니다.
val &= ~PORT_LINK_FAST_LINK_MODE;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
val |= PORT_LINK_DLL_LINK_EN;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_link_set_max_link_width(pci, pci->num_lanes);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
const char *reg_name,
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
resource_size_t cpu_phys_addr)
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
struct device *dev = pci->dev;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
struct device_node *np = dev->of_node;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
int index;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
u64 reg_addr, fixup_addr;
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
u64 (*fixup)(struct dw_pcie *pcie, u64 cpu_addr);
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 입력 계약을 만족하는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* Look up reg_name address on parent bus */
원본 주석입니다. Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
index = of_property_match_string(np, "reg-names", reg_name);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (index < 0) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dev_err(dev, "No %s in devicetree \"reg\" property\n", reg_name);
Link speed, lane width와 N_FTS를 programming하는 DWC 공통 setup의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
Linux v6.18.37 · 실제 원본 코드
Gen3 이상 각 data rate와 lane의 equalization preset programming
drivers/pci/controller/dwc/pcie-designware-host.c:1014-1064
1014 /*
1015 * Write preset values to the registers byte-by-byte for the given
1016 * number of lanes and register size.
1017 */
1018 for (i = 0; i < pci->num_lanes * lane_reg_size; i++)
1019 dw_pcie_writeb_dbi(pci, cap + lane_eq_offset + i, presets[i]);
1020}
1021
1022static void dw_pcie_config_presets(struct dw_pcie_rp *pp)
1023{
1024 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
1025 enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed];
1026
1027 /*
1028 * Lane equalization settings need to be applied for all data rates the
1029 * controller supports and for all supported lanes.
1030 */
1031
1032 if (speed >= PCIE_SPEED_8_0GT)
1033 dw_pcie_program_presets(pp, PCIE_SPEED_8_0GT);
1034
1035 if (speed >= PCIE_SPEED_16_0GT)
1036 dw_pcie_program_presets(pp, PCIE_SPEED_16_0GT);
1037
1038 if (speed >= PCIE_SPEED_32_0GT)
1039 dw_pcie_program_presets(pp, PCIE_SPEED_32_0GT);
1040
1041 if (speed >= PCIE_SPEED_64_0GT)
1042 dw_pcie_program_presets(pp, PCIE_SPEED_64_0GT);
1043}
1044
1045int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
1046{
1047 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
1048 u32 val;
1049 int ret;
1050
1051 /*
1052 * Enable DBI read-only registers for writing/updating configuration.
1053 * Write permission gets disabled towards the end of this function.
1054 */
1055 dw_pcie_dbi_ro_wr_en(pci);
1056
1057 dw_pcie_setup(pci);
1058
1059 dw_pcie_msi_init(pp);
1060
1061 /* Setup RC BARs */
1062 dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
1063 dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
1064 /*
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Write preset values to the registers byte-by-byte for the given
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* number of lanes and register size.
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
for (i = 0; i < pci->num_lanes * lane_reg_size; i++)
여러 pending source 또는 resource를 순회하는 구간입니다. 한 번의 진입에서 처리 가능한 양과 종료 조건이 interrupt latency에 영향을 줍니다.
dw_pcie_writeb_dbi(pci, cap + lane_eq_offset + i, presets[i]);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
static void dw_pcie_config_presets(struct dw_pcie_rp *pp)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 Gen3 이상 각 data rate와 lane의 equalization preset programming의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed];
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/*
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Lane equalization settings need to be applied for all data rates the
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* controller supports and for all supported lanes.
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (speed >= PCIE_SPEED_8_0GT)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_program_presets(pp, PCIE_SPEED_8_0GT);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (speed >= PCIE_SPEED_16_0GT)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_program_presets(pp, PCIE_SPEED_16_0GT);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (speed >= PCIE_SPEED_32_0GT)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_program_presets(pp, PCIE_SPEED_32_0GT);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (speed >= PCIE_SPEED_64_0GT)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dw_pcie_program_presets(pp, PCIE_SPEED_64_0GT);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 Gen3 이상 각 data rate와 lane의 equalization preset programming의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
u32 val;
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
int ret;
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/*
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Enable DBI read-only registers for writing/updating configuration.
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Write permission gets disabled towards the end of this function.
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
dw_pcie_dbi_ro_wr_en(pci);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_setup(pci);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_msi_init(pp);
Gen3 이상 각 data rate와 lane의 equalization preset programming의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/* Setup RC BARs */
원본 주석입니다. Gen3 이상 각 data rate와 lane의 equalization preset programming에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
hardware 또는 공유 메모리에 상태를 게시합니다. write가 완료되는 지점과 다음 read/doorbell 사이의 ordering 조건을 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
Linux v6.18.37 · 실제 원본 코드
DesignWare Root Port 초기화
drivers/pci/controller/dwc/pcie-designware-host.c:560-638
560 * visconti_pcie_cpu_addr_fixup() uses pp->io_base, so we have to
561 * call dw_pcie_parent_bus_offset() after setting pp->io_base.
562 */
563 pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "config",
564 pp->cfg0_base);
565 return 0;
566}
567
568int dw_pcie_host_init(struct dw_pcie_rp *pp)
569{
570 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
571 struct device *dev = pci->dev;
572 struct device_node *np = dev->of_node;
573 struct pci_host_bridge *bridge;
574 int ret;
575
576 raw_spin_lock_init(&pp->lock);
577
578 bridge = devm_pci_alloc_host_bridge(dev, 0);
579 if (!bridge)
580 return -ENOMEM;
581
582 pp->bridge = bridge;
583
584 ret = dw_pcie_host_get_resources(pp);
585 if (ret)
586 return ret;
587
588 if (pp->ops->init) {
589 ret = pp->ops->init(pp);
590 if (ret)
591 goto err_free_ecam;
592 }
593
594 if (pci_msi_enabled()) {
595 pp->has_msi_ctrl = !(pp->ops->msi_init ||
596 of_property_present(np, "msi-parent") ||
597 of_property_present(np, "msi-map"));
598
599 /*
600 * For the has_msi_ctrl case the default assignment is handled
601 * in the dw_pcie_msi_host_init().
602 */
603 if (!pp->has_msi_ctrl && !pp->num_vectors) {
604 pp->num_vectors = MSI_DEF_NUM_VECTORS;
605 } else if (pp->num_vectors > MAX_MSI_IRQS) {
606 dev_err(dev, "Invalid number of vectors\n");
607 ret = -EINVAL;
608 goto err_deinit_host;
609 }
610
611 if (pp->ops->msi_init) {
612 ret = pp->ops->msi_init(pp);
613 if (ret < 0)
614 goto err_deinit_host;
615 } else if (pp->has_msi_ctrl) {
616 ret = dw_pcie_msi_host_init(pp);
617 if (ret < 0)
618 goto err_deinit_host;
619 }
620 }
621
622 dw_pcie_version_detect(pci);
623
624 dw_pcie_iatu_detect(pci);
625
626 if (pci->num_lanes < 1)
627 pci->num_lanes = dw_pcie_link_get_max_link_width(pci);
628
629 ret = of_pci_get_equalization_presets(dev, &pp->presets, pci->num_lanes);
630 if (ret)
631 goto err_free_msi;
632
633 if (pp->ecam_enabled) {
634 ret = dw_pcie_config_ecam_iatu(pp);
635 if (ret) {
636 dev_err(dev, "Failed to configure iATU in ECAM mode\n");
637 goto err_free_msi;
638 }* visconti_pcie_cpu_addr_fixup() uses pp->io_base, so we have to
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* call dw_pcie_parent_bus_offset() after setting pp->io_base.
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
pci->parent_bus_offset = dw_pcie_parent_bus_offset(pci, "config",
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
pp->cfg0_base);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
return 0;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
int dw_pcie_host_init(struct dw_pcie_rp *pp)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 DesignWare Root Port 초기화의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
struct device *dev = pci->dev;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
struct device_node *np = dev->of_node;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
struct pci_host_bridge *bridge;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
int ret;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
raw_spin_lock_init(&pp->lock);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
bridge = devm_pci_alloc_host_bridge(dev, 0);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (!bridge)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
return -ENOMEM;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
pp->bridge = bridge;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
ret = dw_pcie_host_get_resources(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
return ret;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pp->ops->init) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
ret = pp->ops->init(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
goto err_free_ecam;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pci_msi_enabled()) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
pp->has_msi_ctrl = !(pp->ops->msi_init ||
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
of_property_present(np, "msi-parent") ||
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
of_property_present(np, "msi-map"));
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/*
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* For the has_msi_ctrl case the default assignment is handled
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* in the dw_pcie_msi_host_init().
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. DesignWare Root Port 초기화에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
if (!pp->has_msi_ctrl && !pp->num_vectors) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
pp->num_vectors = MSI_DEF_NUM_VECTORS;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
} else if (pp->num_vectors > MAX_MSI_IRQS) {
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
dev_err(dev, "Invalid number of vectors\n");
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
ret = -EINVAL;
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
goto err_deinit_host;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pp->ops->msi_init) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
ret = pp->ops->msi_init(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret < 0)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
goto err_deinit_host;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
} else if (pp->has_msi_ctrl) {
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
ret = dw_pcie_msi_host_init(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret < 0)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
goto err_deinit_host;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_version_detect(pci);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
dw_pcie_iatu_detect(pci);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pci->num_lanes < 1)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
pci->num_lanes = dw_pcie_link_get_max_link_width(pci);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
ret = of_pci_get_equalization_presets(dev, &pp->presets, pci->num_lanes);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret)
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
goto err_free_msi;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
if (pp->ecam_enabled) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
ret = dw_pcie_config_ecam_iatu(pp);
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
if (ret) {
상태나 ID를 분류하는 분기입니다. 이 조건의 참·거짓은 장치 register, firmware 기술 또는 CPU mode 중 하나에서 결정됩니다.
dev_err(dev, "Failed to configure iATU in ECAM mode\n");
DesignWare Root Port 초기화의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
goto err_free_msi;
공통 정리 또는 오류 경로로 이동합니다. 이미 얻은 clock, mapping, IRQ, DMA 자원의 역순 해제가 맞는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
Linux v6.18.37 · 실제 원본 코드
PCI bus scan 진입
3221 *
3222 * Return how far we've got finding sub-buses.
3223 */
3224 dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
3225 return max;
3226}
3227
3228/**
3229 * pci_scan_child_bus() - Scan devices below a bus
3230 * @bus: Bus to scan for devices
3231 *
3232 * Scans devices below @bus including subordinate buses. Returns new
3233 * subordinate number including all the found devices.
3234 */
3235unsigned int pci_scan_child_bus(struct pci_bus *bus)
3236{
3237 return pci_scan_child_bus_extend(bus, 0);
3238}
3239EXPORT_SYMBOL_GPL(pci_scan_child_bus);
3240
3241/**
3242 * pcibios_root_bridge_prepare - Platform-specific host bridge setup
3243 * @bridge: Host bridge to set up
3244 *
3245 * Default empty implementation. Replace with an architecture-specific setup
3246 * routine, if necessary.
3247 */
3248int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
3249{
3250 return 0;
3251}
3252
3253void __weak pcibios_add_bus(struct pci_bus *bus)
3254{
3255}
3256
3257void __weak pcibios_remove_bus(struct pci_bus *bus)
3258{
3259}
3260
3261struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
3262 struct pci_ops *ops, void *sysdata, struct list_head *resources)
3263{*
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Return how far we've got finding sub-buses.
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
PCI bus scan 진입의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
return max;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/**
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* pci_scan_child_bus() - Scan devices below a bus
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* @bus: Bus to scan for devices
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Scans devices below @bus including subordinate buses. Returns new
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* subordinate number including all the found devices.
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
unsigned int pci_scan_child_bus(struct pci_bus *bus)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 PCI bus scan 진입의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
return pci_scan_child_bus_extend(bus, 0);
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
PCI bus scan 진입의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
/**
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* pcibios_root_bridge_prepare - Platform-specific host bridge setup
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* @bridge: Host bridge to set up
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* Default empty implementation. Replace with an architecture-specific setup
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
* routine, if necessary.
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
*/
원본 주석입니다. PCI bus scan 진입에서 뒤따르는 코드가 전제하는 하드웨어 조건이나 예외를 먼저 확인합니다.
int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 PCI bus scan 진입의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
return 0;
호출자에게 상태를 반환합니다. 반환값만 보지 말고 그 전에 controller ownership이나 active 상태가 정리되었는지 확인합니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
void __weak pcibios_add_bus(struct pci_bus *bus)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 PCI bus scan 진입의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
void __weak pcibios_remove_bus(struct pci_bus *bus)
함수 경계입니다. 호출자가 넘긴 번호 공간과 현재 CPU/controller context가 PCI bus scan 진입의 입력 계약을 만족하는지 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
}
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
(blank)
논리 구간을 나누는 빈 줄입니다. 바로 위에서 준비한 상태와 다음 제어 흐름을 분리해 읽습니다.
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
PCI bus scan 진입의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
struct pci_ops *ops, void *sysdata, struct list_head *resources)
PCI bus scan 진입의 한 단계입니다. 이 줄이 바꾸는 software 상태를 대응하는 controller register나 trace checkpoint와 연결해 확인합니다.
{
제어 블록의 범위를 표시합니다. 이 괄호 안에서만 유효한 lock, CPU context, resource lifetime을 함께 표시해 둡니다.
09 · VERIFICATION
실제 장비에서 확인하는 순서
- Board
실행 scope로 power-good, REFCLK와 PERST#를 같은 trigger에 잡는다.
통과 기준 reset이 clock보다 먼저 풀리거나 rail ramp 중 toggling이 없어야 한다.
- LTSSM
실행 controller debug register를 1ms 간격으로 수집한다.
통과 기준 L0 고정인지 Recovery 반복인지 state histogram으로 확인한다.
- Config
실행 `lspci -s <BDF> -vvxxxx`와 root-port AER를 저장한다.
통과 기준 Vendor/Device ID, Link Status, AER status가 같은 BDF를 가리켜야 한다.
- Address
실행 ECAM 식으로 BDF register physical address를 계산한다.
통과 기준 firmware MCFG/DT window와 controller outbound range 안에 있어야 한다.
- Stress
실행 link retrain과 warm reset을 반복하며 width/speed를 기록한다.
통과 기준 항상 같은 width/speed로 올라오고 correctable error 증가율이 안정적이어야 한다.
10 · FAILURE MATRIX
처음 끊긴 경계로 원인을 좁히기
| 관측 결과 | 우선 의심할 경계 | 다음 증거 |
|---|---|---|
| Detect에 머묾 | receiver 미검출 | 전원, AC coupling, lane 연결, endpoint reset |
| Polling/Recovery 반복 | TS 교환 또는 equalization 실패 | REFCLK/SSC, SI, polarity/lane map, preset |
| L0인데 0xffff | ECAM/ATU/bus-range 또는 endpoint config 응답 문제 | LTSSM과 config TLP/AER 동시 확인 |
| x4가 x1로 협상 | 일부 lane training 실패 | lane별 receiver detect와 equalization status |
| 간헐 Completion Timeout | signal integrity, power management, credit/replay 문제 | AER, replay counter, ASPM off 비교 |
핵심은 마지막 오류 메시지가 아니라 처음 기대값과 달라진 checkpoint입니다. 그보다 아래의 통과 증거와 그 지점의 실패 증거를 한 묶음으로 남겨야 수정의 효과도 검증할 수 있습니다.