All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9 v3] R-Car Gen2 PCIe host driver
@ 2014-03-13  9:49 ` Phil Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:49 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This is version 3 of a PCIe Host driver for the R-Car Gen2 devices,
i.e. R-Car H2 (r8a7790) and R-Car M2 (r8a7791). This version includes
DT support, and includes a patch to add MSI.

All feedback welcome!
Phil

root@koelsch:~# lspci -vv
00:00.0 PCI bridge: Renesas Technology Corp. Device 001f (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary\0, secondary\x01, subordinate\x05, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-305fffff
        Prefetchable memory behind bridge: 38000000-381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] Express (v2) Root Port (Slot-), MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag+ RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s, Latency L0 unlimited, L1 unlimited
                        ClockPM- Surprise- LLActRep+ BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt-
                RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
                RootCap: CRSVisible-
                RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported ARIFwd-
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v1] Virtual Channel
                Caps:   LPEVC=0 RefClk\x100ns PATEntryBits=1
                Arb:    Fixed- WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VCÿ
                        Status: NegoPending- InProgress-
        Capabilities: [1b0 v1] Device Serial Number 00-00-00-00-00-00-00-00

01:00.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Region 0: Memory at 30500000 (32-bit, non-prefetchable) [size\x128K]
        Bus: primary\x01, secondary\x02, subordinate\x05, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-304fffff
        Prefetchable memory behind bridge: 0000000038000000-00000000381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Upstream Port, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-SlotPowerLimit 0.000W
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
                LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <1us, L1 <2us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [138 v1] Power Budgeting <?>
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk\x100ns PATEntryBits=4
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset\x06 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32+ WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=WRR32 TC/VCÿ
                        Status: NegoPending- InProgress-
                        Port Arbitration Table <?>
                VC1:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC\0
                        Status: NegoPending+ InProgress-
        Capabilities: [448 v1] Vendor Specific Information: ID\000 Rev=0 Len\fc <?>
        Capabilities: [950 v1] Vendor Specific Information: ID\001 Rev=0 Len\x010 <?>

02:01.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary\x02, secondary\x03, subordinate\x03, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-301fffff
        Prefetchable memory behind bridge: 0000000038000000-00000000381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #1, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <2us, L1 <4us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt-
                SltCap: AttnBtn+ PwrCtrl+ MRL+ AttnInd+ PwrInd+ HotPlug+ Surprise-
                        Slot #1, PowerLimit 25.000W; Interlock+ NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd On, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
                        Changed: MRL- PresDet+ LinkState+
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk\x100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VCÿ
                        Status: NegoPending- InProgress-
                VC1:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC\0
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID\001 Rev=0 Len\x010 <?>

02:04.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary\x02, secondary\x04, subordinate\x04, sec-latency=0
        Memory behind bridge: 30200000-304fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <1us, L1 <2us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt+
                SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surprise-
                        Slot #4, PowerLimit 25.000W; Interlock- NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd Off, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
                        Changed: MRL- PresDet+ LinkState+
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd+
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk\x100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VCÿ
                        Status: NegoPending- InProgress-
                VC1:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC\0
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID\001 Rev=0 Len\x010 <?>

02:05.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Bus: primary\x02, secondary\x05, subordinate\x05, sec-latency=0
        Secondary status: 66MHz- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
                LnkCap: Port #5, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <2us, L1 <4us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x0, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
                SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surprise-
                        Slot #5, PowerLimit 25.000W; Interlock- NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd Off, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet- Interlock-
                        Changed: MRL- PresDet- LinkState-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk\x100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VCÿ
                        Status: NegoPending+ InProgress-
                VC1:    Caps:   PATOffset\0 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC\0
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID\001 Rev=0 Len\x010 <?>

03:00.0 Ethernet controller: Intel Corporation 82572EI Gigabit Ethernet Controller (Copper) (rev 06)
        Subsystem: Intel Corporation PRO/1000 PT Server Adapter
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 434
        Region 0: Memory at 30000000 (32-bit, non-prefetchable) [size\x128K]
        Region 1: Memory at 30020000 (32-bit, non-prefetchable) [size\x128K]
        Region 2: I/O ports at 1000 [disabled] [size2]
        [virtual] Expansion ROM at 38000000 [disabled] [size\x128K]
        Capabilities: [c8] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
                Address: 000000006eeae000  Data: 000a
        Capabilities: [e0] Express (v1) Endpoint, MSI 00
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #1, Speed 2.5GT/s, Width x1, ASPM L0s, Latency L0 <4us, L1 <64us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
        Capabilities: [100 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
        Capabilities: [140 v1] Device Serial Number 68-05-ca-ff-ff-16-f7-40
        Kernel driver in use: e1000e
        Kernel modules: e1000e

04:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
        Subsystem: Intel Corporation Ethernet Server Adapter I350-T2
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 148
        Region 0: Memory at 30200000 (32-bit, non-prefetchable) [size=1M]
        Region 3: Memory at 30400000 (32-bit, non-prefetchable) [size\x16K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] MSI-X: Enable+ Count\x10 Masked-
                Vector table: BAR=3 offset\0000000
                PBA: BAR=3 offset\0002000
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x4, ASPM L0s L1, Latency L0 <4us, L1 <32us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR+, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v2] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [140 v1] Device Serial Number a0-36-9f-ff-ff-23-18-c0
        Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
                ARICap: MFVC- ACS-, Next Function: 1
                ARICtl: MFVC- ACS-, Function Group: 0
        Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
                IOVCap: Migration-, Interrupt Message Number: 000
                IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy-
                IOVSta: Migration-
                Initial VFs: 8, Total VFs: 8, Number of VFs: 0, Function Dependency Link: 00
                VF offset: 384, stride: 4, Device ID: 1520
                Supported Page Size: 00000553, System Page Size: 00000001
                Region 0: Memory at 0000000000000000 (64-bit, prefetchable)
                Region 3: Memory at 0000000000000000 (64-bit, prefetchable)
                VF Migration: offset: 00000000, BIR: 0
        Capabilities: [1a0 v1] Transaction Processing Hints
                Device specific mode supported
                Steering table in TPH capability structure
        Capabilities: [1c0 v1] Latency Tolerance Reporting
                Max snoop latency: 0ns
                Max no snoop latency: 0ns
        Capabilities: [1d0 v1] Access Control Services
                ACSCap: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Kernel driver in use: igb
        Kernel modules: igb

04:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
        Subsystem: Intel Corporation Ethernet Server Adapter I350-T2
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin B routed to IRQ 148
        Region 0: Memory at 30300000 (32-bit, non-prefetchable) [size=1M]
        Region 3: Memory at 30404000 (32-bit, non-prefetchable) [size\x16K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] MSI-X: Enable+ Count\x10 Masked-
                Vector table: BAR=3 offset\0000000
                PBA: BAR=3 offset\0002000
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x4, ASPM L0s L1, Latency L0 <4us, L1 <32us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR+, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v2] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [140 v1] Device Serial Number a0-36-9f-ff-ff-23-18-c0
        Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
                ARICap: MFVC- ACS-, Next Function: 0
                ARICtl: MFVC- ACS-, Function Group: 0
        Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
                IOVCap: Migration-, Interrupt Message Number: 000
                IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy-
                IOVSta: Migration-
                Initial VFs: 8, Total VFs: 8, Number of VFs: 0, Function Dependency Link: 01
                VF offset: 384, stride: 4, Device ID: 1520
                Supported Page Size: 00000553, System Page Size: 00000001
                Region 0: Memory at 0000000000000000 (64-bit, prefetchable)
                Region 3: Memory at 0000000000000000 (64-bit, prefetchable)
                VF Migration: offset: 00000000, BIR: 0
        Capabilities: [1a0 v1] Transaction Processing Hints
                Device specific mode supported
                Steering table in TPH capability structure
        Capabilities: [1d0 v1] Access Control Services
                ACSCap: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Kernel driver in use: igb
        Kernel modules: igb

Phil Edworthy (9):
  PCI: host: rcar: Add Renesas R-Car PCIe driver
  PCI: host: rcar: Add MSI support
  ARM: shmobile: r8a7790: Add PCIe clock device tree nodes
  ARM: shmobile: r8a7791: Add PCIe clock device tree nodes
  dt-bindings: pci: rcar pcie device tree bindings
  ARM: shmobile: Add PCIe device tree nodes for R8A7790
  ARM: shmobile: Add PCIe device tree nodes for R8A7791 Koelsch board
  ARM: koelsch: Add PCIe to defconfig
  ARM: koelsch: Add HAVE_ARM_ARCH_TIMER to defconfig

 Documentation/devicetree/bindings/pci/rcar-pci.txt |   40 +
 arch/arm/boot/dts/r8a7790.dtsi                     |   26 +-
 arch/arm/boot/dts/r8a7791-koelsch.dts              |    4 +
 arch/arm/boot/dts/r8a7791.dtsi                     |   26 +-
 arch/arm/configs/koelsch_defconfig                 |    4 +
 drivers/pci/host/Kconfig                           |    6 +
 drivers/pci/host/Makefile                          |    1 +
 drivers/pci/host/pcie-rcar.c                       |  859 ++++++++++++++++++++
 drivers/pci/host/pcie-rcar.h                       |   87 ++
 include/dt-bindings/clock/r8a7790-clock.h          |    1 +
 include/dt-bindings/clock/r8a7791-clock.h          |    1 +
 11 files changed, 1050 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt
 create mode 100644 drivers/pci/host/pcie-rcar.c
 create mode 100644 drivers/pci/host/pcie-rcar.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 0/9 v3] R-Car Gen2 PCIe host driver
@ 2014-03-13  9:49 ` Phil Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:49 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This is version 3 of a PCIe Host driver for the R-Car Gen2 devices,
i.e. R-Car H2 (r8a7790) and R-Car M2 (r8a7791). This version includes
DT support, and includes a patch to add MSI.

All feedback welcome!
Phil

root@koelsch:~# lspci -vv
00:00.0 PCI bridge: Renesas Technology Corp. Device 001f (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary=00, secondary=01, subordinate=05, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-305fffff
        Prefetchable memory behind bridge: 38000000-381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] Express (v2) Root Port (Slot-), MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag+ RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s, Latency L0 unlimited, L1 unlimited
                        ClockPM- Surprise- LLActRep+ BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt-
                RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
                RootCap: CRSVisible-
                RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported ARIFwd-
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v1] Virtual Channel
                Caps:   LPEVC=0 RefClk=100ns PATEntryBits=1
                Arb:    Fixed- WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending- InProgress-
        Capabilities: [1b0 v1] Device Serial Number 00-00-00-00-00-00-00-00

01:00.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Region 0: Memory at 30500000 (32-bit, non-prefetchable) [size=128K]
        Bus: primary=01, secondary=02, subordinate=05, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-304fffff
        Prefetchable memory behind bridge: 0000000038000000-00000000381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Upstream Port, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-SlotPowerLimit 0.000W
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
                LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <1us, L1 <2us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [138 v1] Power Budgeting <?>
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk=100ns PATEntryBits=4
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=06 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed- WRR32+ WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=WRR32 TC/VC=ff
                        Status: NegoPending- InProgress-
                        Port Arbitration Table <?>
                VC1:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC=00
                        Status: NegoPending+ InProgress-
        Capabilities: [448 v1] Vendor Specific Information: ID=0000 Rev=0 Len=0cc <?>
        Capabilities: [950 v1] Vendor Specific Information: ID=0001 Rev=0 Len=010 <?>

02:01.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary=02, secondary=03, subordinate=03, sec-latency=0
        I/O behind bridge: 00001000-00001fff
        Memory behind bridge: 30000000-301fffff
        Prefetchable memory behind bridge: 0000000038000000-00000000381fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #1, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <2us, L1 <4us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt-
                SltCap: AttnBtn+ PwrCtrl+ MRL+ AttnInd+ PwrInd+ HotPlug+ Surprise-
                        Slot #1, PowerLimit 25.000W; Interlock+ NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd On, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
                        Changed: MRL- PresDet+ LinkState+
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk=100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending- InProgress-
                VC1:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC=00
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID=0001 Rev=0 Len=010 <?>

02:04.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Bus: primary=02, secondary=04, subordinate=04, sec-latency=0
        Memory behind bridge: 30200000-304fffff
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <1us, L1 <2us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt+
                SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surprise-
                        Slot #4, PowerLimit 25.000W; Interlock- NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd Off, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
                        Changed: MRL- PresDet+ LinkState+
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd+
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk=100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending- InProgress-
                VC1:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC=00
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID=0001 Rev=0 Len=010 <?>

02:05.0 PCI bridge: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch (rev ba) (prog-if 00 [Normal decode])
        Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Bus: primary=02, secondary=05, subordinate=05, sec-latency=0
        Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
        BridgeCtl: Parity+ SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
                PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [48] MSI: Enable- Count=1/4 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <64ns, L1 <1us
                        ExtTag- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
                        MaxPayload 128 bytes, MaxReadReq 128 bytes
                DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
                LnkCap: Port #5, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <2us, L1 <4us
                        ClockPM- Surprise+ LLActRep+ BwNot+
                LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x0, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
                SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surprise-
                        Slot #5, PowerLimit 25.000W; Interlock- NoCompl-
                SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
                        Control: AttnInd Off, PwrInd Off, Power- Interlock-
                SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet- Interlock-
                        Changed: MRL- PresDet- LinkState-
                DevCap2: Completion Timeout: Not Supported, TimeoutDis-, LTR-, OBFF Not Supported ARIFwd+
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd-
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-, Selectable De-emphasis: -6dB
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [a4] Subsystem: PLX Technology, Inc. PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch
        Capabilities: [100 v1] Device Serial Number ba-86-01-10-b5-df-0e-00
        Capabilities: [fb4 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 1f, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [148 v1] Virtual Channel
                Caps:   LPEVC=1 RefClk=100ns PATEntryBits=1
                Arb:    Fixed+ WRR32- WRR64- WRR128-
                Ctrl:   ArbSelect=Fixed
                Status: InProgress-
                VC0:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable+ ID=0 ArbSelect=Fixed TC/VC=ff
                        Status: NegoPending+ InProgress-
                VC1:    Caps:   PATOffset=00 MaxTimeSlots=1 RejSnoopTrans-
                        Arb:    Fixed+ WRR32- WRR64- WRR128- TWRR128- WRR256-
                        Ctrl:   Enable- ID=1 ArbSelect=Fixed TC/VC=00
                        Status: NegoPending+ InProgress-
        Capabilities: [520 v1] Access Control Services
                ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl+ DirectTrans+
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Capabilities: [950 v1] Vendor Specific Information: ID=0001 Rev=0 Len=010 <?>

03:00.0 Ethernet controller: Intel Corporation 82572EI Gigabit Ethernet Controller (Copper) (rev 06)
        Subsystem: Intel Corporation PRO/1000 PT Server Adapter
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 434
        Region 0: Memory at 30000000 (32-bit, non-prefetchable) [size=128K]
        Region 1: Memory at 30020000 (32-bit, non-prefetchable) [size=128K]
        Region 2: I/O ports at 1000 [disabled] [size=32]
        [virtual] Expansion ROM at 38000000 [disabled] [size=128K]
        Capabilities: [c8] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
                Address: 000000006eeae000  Data: 000a
        Capabilities: [e0] Express (v1) Endpoint, MSI 00
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #1, Speed 2.5GT/s, Width x1, ASPM L0s, Latency L0 <4us, L1 <64us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
        Capabilities: [100 v1] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
        Capabilities: [140 v1] Device Serial Number 68-05-ca-ff-ff-16-f7-40
        Kernel driver in use: e1000e
        Kernel modules: e1000e

04:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
        Subsystem: Intel Corporation Ethernet Server Adapter I350-T2
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 148
        Region 0: Memory at 30200000 (32-bit, non-prefetchable) [size=1M]
        Region 3: Memory at 30400000 (32-bit, non-prefetchable) [size=16K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] MSI-X: Enable+ Count=10 Masked-
                Vector table: BAR=3 offset=00000000
                PBA: BAR=3 offset=00002000
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x4, ASPM L0s L1, Latency L0 <4us, L1 <32us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR+, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                         Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                         Compliance De-emphasis: -6dB
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v2] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [140 v1] Device Serial Number a0-36-9f-ff-ff-23-18-c0
        Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
                ARICap: MFVC- ACS-, Next Function: 1
                ARICtl: MFVC- ACS-, Function Group: 0
        Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
                IOVCap: Migration-, Interrupt Message Number: 000
                IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy-
                IOVSta: Migration-
                Initial VFs: 8, Total VFs: 8, Number of VFs: 0, Function Dependency Link: 00
                VF offset: 384, stride: 4, Device ID: 1520
                Supported Page Size: 00000553, System Page Size: 00000001
                Region 0: Memory at 0000000000000000 (64-bit, prefetchable)
                Region 3: Memory at 0000000000000000 (64-bit, prefetchable)
                VF Migration: offset: 00000000, BIR: 0
        Capabilities: [1a0 v1] Transaction Processing Hints
                Device specific mode supported
                Steering table in TPH capability structure
        Capabilities: [1c0 v1] Latency Tolerance Reporting
                Max snoop latency: 0ns
                Max no snoop latency: 0ns
        Capabilities: [1d0 v1] Access Control Services
                ACSCap: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Kernel driver in use: igb
        Kernel modules: igb

04:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
        Subsystem: Intel Corporation Ethernet Server Adapter I350-T2
        Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin B routed to IRQ 148
        Region 0: Memory at 30300000 (32-bit, non-prefetchable) [size=1M]
        Region 3: Memory at 30404000 (32-bit, non-prefetchable) [size=16K]
        Capabilities: [40] Power Management version 3
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
                Address: 0000000000000000  Data: 0000
                Masking: 00000000  Pending: 00000000
        Capabilities: [70] MSI-X: Enable+ Count=10 Masked-
                Vector table: BAR=3 offset=00000000
                PBA: BAR=3 offset=00002000
        Capabilities: [a0] Express (v2) Endpoint, MSI 00
                DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
                LnkCap: Port #4, Speed 5GT/s, Width x4, ASPM L0s L1, Latency L0 <4us, L1 <32us
                        ClockPM- Surprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR+, OBFF Not Supported
                DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
                LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
                         EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
        Capabilities: [100 v2] Advanced Error Reporting
                UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
                UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
                CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
                CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
                AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
        Capabilities: [140 v1] Device Serial Number a0-36-9f-ff-ff-23-18-c0
        Capabilities: [150 v1] Alternative Routing-ID Interpretation (ARI)
                ARICap: MFVC- ACS-, Next Function: 0
                ARICtl: MFVC- ACS-, Function Group: 0
        Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
                IOVCap: Migration-, Interrupt Message Number: 000
                IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy-
                IOVSta: Migration-
                Initial VFs: 8, Total VFs: 8, Number of VFs: 0, Function Dependency Link: 01
                VF offset: 384, stride: 4, Device ID: 1520
                Supported Page Size: 00000553, System Page Size: 00000001
                Region 0: Memory at 0000000000000000 (64-bit, prefetchable)
                Region 3: Memory at 0000000000000000 (64-bit, prefetchable)
                VF Migration: offset: 00000000, BIR: 0
        Capabilities: [1a0 v1] Transaction Processing Hints
                Device specific mode supported
                Steering table in TPH capability structure
        Capabilities: [1d0 v1] Access Control Services
                ACSCap: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
                ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-
        Kernel driver in use: igb
        Kernel modules: igb

Phil Edworthy (9):
  PCI: host: rcar: Add Renesas R-Car PCIe driver
  PCI: host: rcar: Add MSI support
  ARM: shmobile: r8a7790: Add PCIe clock device tree nodes
  ARM: shmobile: r8a7791: Add PCIe clock device tree nodes
  dt-bindings: pci: rcar pcie device tree bindings
  ARM: shmobile: Add PCIe device tree nodes for R8A7790
  ARM: shmobile: Add PCIe device tree nodes for R8A7791 Koelsch board
  ARM: koelsch: Add PCIe to defconfig
  ARM: koelsch: Add HAVE_ARM_ARCH_TIMER to defconfig

 Documentation/devicetree/bindings/pci/rcar-pci.txt |   40 +
 arch/arm/boot/dts/r8a7790.dtsi                     |   26 +-
 arch/arm/boot/dts/r8a7791-koelsch.dts              |    4 +
 arch/arm/boot/dts/r8a7791.dtsi                     |   26 +-
 arch/arm/configs/koelsch_defconfig                 |    4 +
 drivers/pci/host/Kconfig                           |    6 +
 drivers/pci/host/Makefile                          |    1 +
 drivers/pci/host/pcie-rcar.c                       |  859 ++++++++++++++++++++
 drivers/pci/host/pcie-rcar.h                       |   87 ++
 include/dt-bindings/clock/r8a7790-clock.h          |    1 +
 include/dt-bindings/clock/r8a7791-clock.h          |    1 +
 11 files changed, 1050 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt
 create mode 100644 drivers/pci/host/pcie-rcar.c
 create mode 100644 drivers/pci/host/pcie-rcar.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
  2014-03-13  9:49 ` Phil Edworthy
@ 2014-03-13  9:50   ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This PCIe Host driver currently does not support MSI, so cards
fall back to INTx interrupts.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
 - Add DT support
 - Use 'of_irq_parse_and_map_pci' for '.map_irq'
 - Use pm ops to enable clocks
 - Fix checkpatch errors
 - Use subsys_initcall to overcome issues with port bus driver
 - Adjust Kconfig to match other R-Car drivers

v2:
 - Use msleep instead of udelay when waiting for the link
 - Use pm_runtime
 - Removed unused definition
 - Also replaced call to devm_request_and_ioremap with devm_ioremap_resource
   and fixed a bug with this when reporting errors.
---
 drivers/pci/host/Kconfig     |    6 +
 drivers/pci/host/Makefile    |    1 +
 drivers/pci/host/pcie-rcar.c |  629 ++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pcie-rcar.h |   82 ++++++
 4 files changed, 718 insertions(+)
 create mode 100644 drivers/pci/host/pcie-rcar.c
 create mode 100644 drivers/pci/host/pcie-rcar.h

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 47d46c6..dc627e5 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -33,4 +33,10 @@ config PCI_RCAR_GEN2
 	  There are 3 internal PCI controllers available with a single
 	  built-in EHCI/OHCI host controller present on each one.
 
+config PCI_RCAR_GEN2_PCIE
+	bool "Renesas R-Car PCIe controller"
+	depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+	help
+	  Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 13fb333..19946f9 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
+obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
new file mode 100644
index 0000000..7f094fa
--- /dev/null
+++ b/drivers/pci/host/pcie-rcar.c
@@ -0,0 +1,629 @@
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ *  Copyright (C) 2013 Renesas Electronics Europe Ltd
+ *
+ * Based on:
+ *  arch/sh/drivers/pci/pcie-sh7786.c
+ *  arch/sh/drivers/pci/ops-sh7786.c
+ *  Copyright (C) 2009 - 2011  Paul Mundt
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include "pcie-rcar.h"
+
+#define DRV_NAME "rcar-pcie"
+
+enum chip_id {
+	RCAR_GENERIC,
+	RCAR_H1,
+};
+
+#define RCONF(x)	(PCICONF(0)+(x))
+#define RPMCAP(x)	(PMCAP(0)+(x))
+#define REXPCAP(x)	(EXPCAP(0)+(x))
+#define RVCCAP(x)	(VCCAP(0)+(x))
+
+#define  PCIE_CONF_BUS(b)	(((b) & 0xff) << 24)
+#define  PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
+#define  PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
+
+#define PCI_MAX_RESOURCES 4
+
+static const struct of_device_id rcar_pcie_of_match[] = {
+	{ .compatible = "renesas,r8a7779-pcie", .data = (void *)RCAR_H1 },
+	{ .compatible = "renesas,r8a7790-pcie", .data = (void *)RCAR_GENERIC },
+	{ .compatible = "renesas,r8a7791-pcie", .data = (void *)RCAR_GENERIC },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
+
+/* Structure representing the PCIe interface */
+struct rcar_pcie {
+	struct device		*dev;
+	void __iomem		*base;
+	struct resource		res[PCI_MAX_RESOURCES];
+	int			haslink;
+	enum chip_id		chip;
+	u8			root_bus_nr;
+	struct clk		*clk;
+};
+
+static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
+{
+	return sys->private_data;
+}
+
+static void
+pci_write_reg(struct rcar_pcie *pcie, unsigned long val, unsigned long reg)
+{
+	writel(val, pcie->base + reg);
+}
+
+static unsigned long
+pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
+{
+	return readl(pcie->base + reg);
+}
+
+enum {
+	PCI_ACCESS_READ,
+	PCI_ACCESS_WRITE,
+};
+
+static void rcar_rmw32(struct rcar_pcie *pcie,
+			    int where, u32 mask, u32 data)
+{
+	int shift = 8 * (where & 3);
+	u32 val = pci_read_reg(pcie, where & ~3);
+	val &= ~(mask << shift);
+	val |= data << shift;
+	pci_write_reg(pcie, val, where & ~3);
+}
+
+static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
+{
+	int shift = 8 * (where & 3);
+	u32 val = pci_read_reg(pcie, where & ~3);
+	return val >> shift;
+}
+
+static int rcar_pcie_config_access(struct rcar_pcie *pcie,
+		unsigned char access_type, struct pci_bus *bus,
+		unsigned int devfn, int where, u32 *data)
+{
+	int dev, func, reg, index;
+
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+	reg = where & ~3;
+	index = reg / 4;
+
+	if (bus->number > 255 || dev > 31 || func > 7)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	/*
+	 * While each channel has its own memory-mapped extended config
+	 * space, it's generally only accessible when in endpoint mode.
+	 * When in root complex mode, the controller is unable to target
+	 * itself with either type 0 or type 1 accesses, and indeed, any
+	 * controller initiated target transfer to its own config space
+	 * result in a completer abort.
+	 *
+	 * Each channel effectively only supports a single device, but as
+	 * the same channel <-> device access works for any PCI_SLOT()
+	 * value, we cheat a bit here and bind the controller's config
+	 * space to devfn 0 in order to enable self-enumeration. In this
+	 * case the regular ECAR/ECDR path is sidelined and the mangled
+	 * config access itself is initiated as an internal bus  transaction.
+	 */
+	if (pci_is_root_bus(bus)) {
+		if (dev != 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		if (access_type = PCI_ACCESS_READ)
+			*data = pci_read_reg(pcie, PCICONF(index));
+		else
+			pci_write_reg(pcie, *data, PCICONF(index));
+
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/* Clear errors */
+	pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+
+	/* Set the PIO address */
+	pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) |
+				PCIE_CONF_FUNC(func) | reg, PCIECAR);
+
+	/* Enable the configuration access */
+	if (bus->parent->number = pcie->root_bus_nr)
+		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+	else
+		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+
+	/* Check for errors */
+	if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Check for master and target aborts */
+	if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) &
+		(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (access_type = PCI_ACCESS_READ)
+		*data = pci_read_reg(pcie, PCIECDR);
+	else
+		pci_write_reg(pcie, *data, PCIECDR);
+
+	/* Disable the configuration access */
+	pci_write_reg(pcie, 0, PCIECCTLR);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+	int ret;
+
+	if ((size = 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size = 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+				      bus, devfn, where, val);
+	if (ret != PCIBIOS_SUCCESSFUL) {
+		*val = 0xffffffff;
+		return ret;
+	}
+
+	if (size = 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size = 2)
+		*val = (*val >> (8 * (where & 2))) & 0xffff;
+
+	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)*val);
+
+	return ret;
+}
+
+static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+	int shift, ret;
+	u32 data;
+
+	if ((size = 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size = 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+				      bus, devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+
+	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)val);
+
+	if (size = 1) {
+		shift = 8 * (where & 3);
+		data &= ~(0xff << shift);
+		data |= ((val & 0xff) << shift);
+	} else if (size = 2) {
+		shift = 8 * (where & 2);
+		data &= ~(0xffff << shift);
+		data |= ((val & 0xffff) << shift);
+	} else
+		data = val;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
+				      bus, devfn, where, &data);
+
+	return ret;
+}
+
+static struct pci_ops rcar_pcie_ops = {
+	.read	= rcar_pcie_read_conf,
+	.write	= rcar_pcie_write_conf,
+};
+
+static int rcar_pcie_setup_window(int win, struct resource *res,
+					struct rcar_pcie *pcie)
+{
+	/* Setup PCIe address space mappings for each resource */
+	resource_size_t size;
+	u32 mask;
+
+	pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
+
+	/*
+	 * The PAMR mask is calculated in units of 128Bytes, which
+	 * keeps things pretty simple.
+	 */
+	size = resource_size(res);
+	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+	pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
+
+	pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
+	pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+
+	/* First resource is for IO */
+	mask = PAR_ENABLE;
+	if (res->flags & IORESOURCE_IO)
+		mask |= IO_SPACE;
+
+	pci_write_reg(pcie, mask, PCIEPTCTLR(win));
+
+	return 0;
+}
+
+static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(sys);
+	struct resource *res;
+	int i, ret;
+
+	pcie->root_bus_nr = sys->busnr;
+
+	/* Setup PCI resources */
+	for (i = 0; i < PCI_MAX_RESOURCES; i++) {
+
+		res = &pcie->res[i];
+		if (!res->flags)
+			continue;
+
+		if (res->flags & IORESOURCE_IO) {
+			/* Setup IO mapped memory accesses */
+			ret = pci_ioremap_io(0, res->start);
+			if (ret)
+				return 1;
+
+			/* Correct addresses for remapped IO */
+			res->end = res->end - res->start;
+			res->start = 0;
+		}
+
+		rcar_pcie_setup_window(i, res, pcie);
+		pci_add_resource(&sys->resources, res);
+	}
+
+	return 1;
+}
+
+static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
+{
+	struct platform_device *pdev = to_platform_device(pcie->dev);
+	struct hw_pci hw;
+
+	memset(&hw, 0, sizeof(hw));
+
+	hw.nr_controllers = 1;
+	hw.private_data   = (void **)&pcie;
+	hw.setup          = rcar_pcie_setup,
+	hw.map_irq        = of_irq_parse_and_map_pci,
+	hw.ops		  = &rcar_pcie_ops,
+
+	pci_common_init_dev(&pdev->dev, &hw);
+}
+
+static int __init phy_wait_for_ack(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+			return 0;
+
+		udelay(100);
+	}
+
+	dev_err(pcie->dev, "Access to PCIe phy timed out\n");
+
+	return -ETIMEDOUT;
+}
+
+static void __init phy_write_reg(struct rcar_pcie *pcie,
+				 unsigned int rate, unsigned int addr,
+				 unsigned int lane, unsigned int data)
+{
+	unsigned long phyaddr;
+
+	phyaddr = WRITE_CMD |
+		((rate & 1) << RATE_POS) |
+		((lane & 0xf) << LANE_POS) |
+		((addr & 0xff) << ADR_POS);
+
+	/* Set write data */
+	pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
+	pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+
+	/* Ignore errors as they will be dealt with if the data link is down */
+	phy_wait_for_ack(pcie);
+
+	/* Clear command */
+	pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
+	pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+
+	/* Ignore errors as they will be dealt with if the data link is down */
+	phy_wait_for_ack(pcie);
+}
+
+static int __init rcar_pcie_phy_init_rcar_h1(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10;
+
+	/* Initialize the phy */
+	phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
+	phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
+	phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188);
+	phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188);
+	phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014);
+	phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014);
+	phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0);
+	phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB);
+	phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062);
+	phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000);
+	phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000);
+	phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806);
+
+	phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5);
+	phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
+	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
+
+	while (timeout--) {
+		if (pci_read_reg(pcie, H1_PCIEPHYSR))
+			return 0;
+
+		msleep(5);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int __init rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10;
+
+	while (timeout--) {
+		if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+			return 0;
+
+		msleep(5);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void __init rcar_pcie_hw_init(struct rcar_pcie *pcie)
+{
+	/* Initialise R-Car H1 PHY & wait for it to be ready */
+	if (pcie->chip = RCAR_H1)
+		if (rcar_pcie_phy_init_rcar_h1(pcie))
+			return;
+
+	/* Begin initialization */
+	pci_write_reg(pcie, 0, PCIETCTLR);
+
+	/* Set mode */
+	pci_write_reg(pcie, 1, PCIEMSR);
+
+	/*
+	 * For target transfers, setup a single 64-bit 4GB mapping at address
+	 * 0. The hardware can only map memory that starts on a power of two
+	 * boundary, and size is power of 2, so best to ignore it.
+	 */
+	pci_write_reg(pcie, 0, PCIEPRAR(0));
+	pci_write_reg(pcie, 0, PCIELAR(0));
+	pci_write_reg(pcie, 0xfffffff0UL | LAM_PREFETCH |
+		LAM_64BIT | LAR_ENABLE, PCIELAMR(0));
+	pci_write_reg(pcie, 0, PCIELAR(1));
+	pci_write_reg(pcie, 0, PCIEPRAR(1));
+	pci_write_reg(pcie, 0, PCIELAMR(1));
+
+	/*
+	 * Initial header for port config space is type 1, set the device
+	 * class to match. Hardware takes care of propagating the IDSETR
+	 * settings, so there is no need to bother with a quirk.
+	 */
+	pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+
+	/*
+	 * Setup Secondary Bus Number & Subordinate Bus Number, even though
+	 * they aren't used, to avoid bridge being detected as broken.
+	 */
+	rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
+	rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
+
+	/* Initialize default capabilities. */
+	rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
+		PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+	rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
+		PCI_HEADER_TYPE_BRIDGE);
+
+	/* Enable data link layer active state reporting */
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC);
+
+	/* Write out the physical slot number = 0 */
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
+
+	/* Set the completion timer timeout to the maximum 50ms. */
+	rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
+
+	/* Terminate list of capabilities (Next Capability Offset=0) */
+	rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
+
+	/* Enable MAC data scrambling. */
+	rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
+
+	/* Finish initialization - establish a PCI Express link */
+	pci_write_reg(pcie, CFINIT, PCIETCTLR);
+
+	/* This will timeout if we don't have a link. */
+	pcie->haslink = !rcar_pcie_wait_for_dl(pcie);
+
+	/* Enable INTx interrupts */
+	rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
+
+	/* Enable slave Bus Mastering */
+	rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
+		PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
+
+	wmb();
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int rcar_pcie_runtime_suspend(struct device *dev)
+{
+	struct rcar_pcie *pcie = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(pcie->clk);
+	return 0;
+}
+
+static int rcar_pcie_runtime_resume(struct device *dev)
+{
+	struct rcar_pcie *pcie = dev_get_drvdata(dev);
+
+	clk_prepare_enable(pcie->clk);
+	return 0;
+}
+#endif
+
+static int __init rcar_pcie_get_resources(struct platform_device *pdev,
+	struct rcar_pcie *pcie)
+{
+	struct device *dev = &pdev->dev;
+	struct resource res;
+	int err;
+
+	err = of_address_to_resource(pdev->dev.of_node, 0, &res);
+	if (err)
+		return err;
+
+	pcie->clk = devm_clk_get(&pdev->dev, "pcie");
+	if (IS_ERR(pcie->clk)) {
+		dev_err(pcie->dev, "cannot get platfom clock\n");
+		return PTR_ERR(pcie->clk);
+	}
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	pcie->base = devm_ioremap_resource(&pdev->dev, &res);
+	if (IS_ERR(pcie->base)) {
+		err = PTR_ERR(pcie->base);
+		goto err_map_reg;
+	}
+
+	return 0;
+
+err_map_reg:
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+
+	return err;
+}
+
+static int __init rcar_pcie_probe(struct platform_device *pdev)
+{
+	struct rcar_pcie *pcie;
+	unsigned int data;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	const struct of_device_id *of_id;
+	int err, win = 0;
+
+	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	pcie->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pcie);
+
+	of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
+	if (of_id)
+		pcie->chip = (enum chip_id)of_id->data;
+
+	if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
+		dev_err(&pdev->dev, "missing ranges property\n");
+		return -EINVAL;
+	}
+
+	err = rcar_pcie_get_resources(pdev, pcie);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to request resources: %d\n", err);
+		return err;
+	}
+
+	for_each_of_pci_range(&parser, &range) {
+		of_pci_range_to_resource(&range, pdev->dev.of_node,
+						&pcie->res[win++]);
+
+		if (win > PCI_MAX_RESOURCES)
+			break;
+	}
+
+	rcar_pcie_hw_init(pcie);
+
+	if (!pcie->haslink) {
+		dev_info(&pdev->dev, "PCI: PCIe link down\n");
+		return 0;
+	}
+
+	data = pci_read_reg(pcie, MACSR);
+	dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
+
+	rcar_pcie_enable(pcie);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rcar_pcie_pm_ops = {
+	SET_RUNTIME_PM_OPS(rcar_pcie_runtime_suspend,
+				rcar_pcie_runtime_resume, NULL)
+};
+
+static struct platform_driver rcar_pcie_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = rcar_pcie_of_match,
+		.pm = &rcar_pcie_pm_ops,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init pcie_init(void)
+{
+	return platform_driver_probe(&rcar_pcie_driver, rcar_pcie_probe);
+}
+subsys_initcall(pcie_init);
+
+MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
+MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/pci/host/pcie-rcar.h b/drivers/pci/host/pcie-rcar.h
new file mode 100644
index 0000000..3dc026b
--- /dev/null
+++ b/drivers/pci/host/pcie-rcar.h
@@ -0,0 +1,82 @@
+/*
+ * PCI Express definitions for Renesas R-Car SoCs
+ */
+#ifndef __PCI_RCAR_H
+#define __PCI_RCAR_H
+
+#define PCIECAR			0x000010
+#define PCIECCTLR		0x000018
+#define  CONFIG_SEND_ENABLE	(1 << 31)
+#define  TYPE0			(0 << 8)
+#define  TYPE1			(1 << 8)
+#define PCIECDR			0x000020
+#define PCIEMSR			0x000028
+#define PCIEINTXR		0x000400
+#define PCIEPHYSR		0x0007f0
+
+/* Transfer control */
+#define PCIETCTLR		0x02000
+#define  CFINIT			1
+#define PCIETSTR		0x02004
+#define  DATA_LINK_ACTIVE	1
+#define PCIEINTR		0x02008
+#define PCIEINTER		0x0200c
+#define PCIEERRFR		0x02020
+#define  UNSUPPORTED_REQUEST	(1 << 4)
+#define PCIEERRFER		0x02024
+#define PCIEERRFR2		0x02028
+#define PCIEPMSR		0x02034
+#define PCIEPMSCIER		0x02038
+#define PCIEMSIFR		0x02044
+
+/* root port address */
+#define PCIEPRAR(x)		(0x02080 + ((x) * 0x4))
+
+/* local address reg & mask */
+#define PCIELAR(x)		(0x02200 + ((x) * 0x20))
+#define PCIELAMR(x)		(0x02208 + ((x) * 0x20))
+#define  LAM_PMIOLAMnB3		(1 << 3)
+#define  LAM_PMIOLAMnB2		(1 << 2)
+#define  LAM_PREFETCH		(1 << 3)
+#define  LAM_64BIT		(1 << 2)
+#define  LAR_ENABLE		(1 << 1)
+
+/* PCIe address reg & mask */
+#define PCIEPARL(x)		(0x03400 + ((x) * 0x20))
+#define PCIEPARH(x)		(0x03404 + ((x) * 0x20))
+#define PCIEPAMR(x)		(0x03408 + ((x) * 0x20))
+#define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20))
+#define  PAR_ENABLE		(1 << 31)
+#define  IO_SPACE		(1 << 8)
+
+/* Configuration */
+#define PCICONF(x)		(0x010000 + ((x) * 0x4))
+#define PMCAP(x)		(0x010040 + ((x) * 0x4))
+#define MSICAP(x)		(0x010050 + ((x) * 0x4))
+#define EXPCAP(x)		(0x010070 + ((x) * 0x4))
+#define VCCAP(x)		(0x010100 + ((x) * 0x4))
+#define SERNUMCAP(x)		(0x0101b0 + ((x) * 0x4))
+
+/* link layer */
+#define IDSETR0			0x011000
+#define IDSETR1			0x011004
+#define SUBIDSETR		0x011024
+#define DSERSETR0		0x01102c
+#define DSERSETR1		0x011030
+#define TLCTLR			0x011048
+#define MACSR			0x011054
+#define MACCTLR			0x011058
+#define  SCRAMBLE_DISABLE	(1 << 27)
+
+/* R-Car H1 PHY */
+#define H1_PCIEPHYCTLR		0x040008
+#define H1_PCIEPHYADRR		0x04000c
+#define  WRITE_CMD		(1 << 16)
+#define  PHY_ACK		(1 << 24)
+#define  RATE_POS		12
+#define  LANE_POS		8
+#define  ADR_POS		0
+#define H1_PCIEPHYDOUTR		0x040014
+#define H1_PCIEPHYSR		0x040018
+
+#endif /* __PCI_RCAR_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
@ 2014-03-13  9:50   ` Phil Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This PCIe Host driver currently does not support MSI, so cards
fall back to INTx interrupts.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
 - Add DT support
 - Use 'of_irq_parse_and_map_pci' for '.map_irq'
 - Use pm ops to enable clocks
 - Fix checkpatch errors
 - Use subsys_initcall to overcome issues with port bus driver
 - Adjust Kconfig to match other R-Car drivers

v2:
 - Use msleep instead of udelay when waiting for the link
 - Use pm_runtime
 - Removed unused definition
 - Also replaced call to devm_request_and_ioremap with devm_ioremap_resource
   and fixed a bug with this when reporting errors.
---
 drivers/pci/host/Kconfig     |    6 +
 drivers/pci/host/Makefile    |    1 +
 drivers/pci/host/pcie-rcar.c |  629 ++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pcie-rcar.h |   82 ++++++
 4 files changed, 718 insertions(+)
 create mode 100644 drivers/pci/host/pcie-rcar.c
 create mode 100644 drivers/pci/host/pcie-rcar.h

diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 47d46c6..dc627e5 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -33,4 +33,10 @@ config PCI_RCAR_GEN2
 	  There are 3 internal PCI controllers available with a single
 	  built-in EHCI/OHCI host controller present on each one.
 
+config PCI_RCAR_GEN2_PCIE
+	bool "Renesas R-Car PCIe controller"
+	depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+	help
+	  Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 13fb333..19946f9 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
+obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
new file mode 100644
index 0000000..7f094fa
--- /dev/null
+++ b/drivers/pci/host/pcie-rcar.c
@@ -0,0 +1,629 @@
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ *  Copyright (C) 2013 Renesas Electronics Europe Ltd
+ *
+ * Based on:
+ *  arch/sh/drivers/pci/pcie-sh7786.c
+ *  arch/sh/drivers/pci/ops-sh7786.c
+ *  Copyright (C) 2009 - 2011  Paul Mundt
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include "pcie-rcar.h"
+
+#define DRV_NAME "rcar-pcie"
+
+enum chip_id {
+	RCAR_GENERIC,
+	RCAR_H1,
+};
+
+#define RCONF(x)	(PCICONF(0)+(x))
+#define RPMCAP(x)	(PMCAP(0)+(x))
+#define REXPCAP(x)	(EXPCAP(0)+(x))
+#define RVCCAP(x)	(VCCAP(0)+(x))
+
+#define  PCIE_CONF_BUS(b)	(((b) & 0xff) << 24)
+#define  PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
+#define  PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
+
+#define PCI_MAX_RESOURCES 4
+
+static const struct of_device_id rcar_pcie_of_match[] = {
+	{ .compatible = "renesas,r8a7779-pcie", .data = (void *)RCAR_H1 },
+	{ .compatible = "renesas,r8a7790-pcie", .data = (void *)RCAR_GENERIC },
+	{ .compatible = "renesas,r8a7791-pcie", .data = (void *)RCAR_GENERIC },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
+
+/* Structure representing the PCIe interface */
+struct rcar_pcie {
+	struct device		*dev;
+	void __iomem		*base;
+	struct resource		res[PCI_MAX_RESOURCES];
+	int			haslink;
+	enum chip_id		chip;
+	u8			root_bus_nr;
+	struct clk		*clk;
+};
+
+static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
+{
+	return sys->private_data;
+}
+
+static void
+pci_write_reg(struct rcar_pcie *pcie, unsigned long val, unsigned long reg)
+{
+	writel(val, pcie->base + reg);
+}
+
+static unsigned long
+pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
+{
+	return readl(pcie->base + reg);
+}
+
+enum {
+	PCI_ACCESS_READ,
+	PCI_ACCESS_WRITE,
+};
+
+static void rcar_rmw32(struct rcar_pcie *pcie,
+			    int where, u32 mask, u32 data)
+{
+	int shift = 8 * (where & 3);
+	u32 val = pci_read_reg(pcie, where & ~3);
+	val &= ~(mask << shift);
+	val |= data << shift;
+	pci_write_reg(pcie, val, where & ~3);
+}
+
+static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
+{
+	int shift = 8 * (where & 3);
+	u32 val = pci_read_reg(pcie, where & ~3);
+	return val >> shift;
+}
+
+static int rcar_pcie_config_access(struct rcar_pcie *pcie,
+		unsigned char access_type, struct pci_bus *bus,
+		unsigned int devfn, int where, u32 *data)
+{
+	int dev, func, reg, index;
+
+	dev = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+	reg = where & ~3;
+	index = reg / 4;
+
+	if (bus->number > 255 || dev > 31 || func > 7)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	/*
+	 * While each channel has its own memory-mapped extended config
+	 * space, it's generally only accessible when in endpoint mode.
+	 * When in root complex mode, the controller is unable to target
+	 * itself with either type 0 or type 1 accesses, and indeed, any
+	 * controller initiated target transfer to its own config space
+	 * result in a completer abort.
+	 *
+	 * Each channel effectively only supports a single device, but as
+	 * the same channel <-> device access works for any PCI_SLOT()
+	 * value, we cheat a bit here and bind the controller's config
+	 * space to devfn 0 in order to enable self-enumeration. In this
+	 * case the regular ECAR/ECDR path is sidelined and the mangled
+	 * config access itself is initiated as an internal bus  transaction.
+	 */
+	if (pci_is_root_bus(bus)) {
+		if (dev != 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		if (access_type == PCI_ACCESS_READ)
+			*data = pci_read_reg(pcie, PCICONF(index));
+		else
+			pci_write_reg(pcie, *data, PCICONF(index));
+
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/* Clear errors */
+	pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+
+	/* Set the PIO address */
+	pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) |
+				PCIE_CONF_FUNC(func) | reg, PCIECAR);
+
+	/* Enable the configuration access */
+	if (bus->parent->number == pcie->root_bus_nr)
+		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+	else
+		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+
+	/* Check for errors */
+	if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Check for master and target aborts */
+	if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) &
+		(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (access_type == PCI_ACCESS_READ)
+		*data = pci_read_reg(pcie, PCIECDR);
+	else
+		pci_write_reg(pcie, *data, PCIECDR);
+
+	/* Disable the configuration access */
+	pci_write_reg(pcie, 0, PCIECCTLR);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+	int ret;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+				      bus, devfn, where, val);
+	if (ret != PCIBIOS_SUCCESSFUL) {
+		*val = 0xffffffff;
+		return ret;
+	}
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 2))) & 0xffff;
+
+	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)*val);
+
+	return ret;
+}
+
+static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+	int shift, ret;
+	u32 data;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+				      bus, devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+
+	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
+		"where=0x%04x size=%d val=0x%08lx\n", bus->number,
+		devfn, where, size, (unsigned long)val);
+
+	if (size == 1) {
+		shift = 8 * (where & 3);
+		data &= ~(0xff << shift);
+		data |= ((val & 0xff) << shift);
+	} else if (size == 2) {
+		shift = 8 * (where & 2);
+		data &= ~(0xffff << shift);
+		data |= ((val & 0xffff) << shift);
+	} else
+		data = val;
+
+	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
+				      bus, devfn, where, &data);
+
+	return ret;
+}
+
+static struct pci_ops rcar_pcie_ops = {
+	.read	= rcar_pcie_read_conf,
+	.write	= rcar_pcie_write_conf,
+};
+
+static int rcar_pcie_setup_window(int win, struct resource *res,
+					struct rcar_pcie *pcie)
+{
+	/* Setup PCIe address space mappings for each resource */
+	resource_size_t size;
+	u32 mask;
+
+	pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
+
+	/*
+	 * The PAMR mask is calculated in units of 128Bytes, which
+	 * keeps things pretty simple.
+	 */
+	size = resource_size(res);
+	mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+	pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
+
+	pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
+	pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+
+	/* First resource is for IO */
+	mask = PAR_ENABLE;
+	if (res->flags & IORESOURCE_IO)
+		mask |= IO_SPACE;
+
+	pci_write_reg(pcie, mask, PCIEPTCTLR(win));
+
+	return 0;
+}
+
+static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct rcar_pcie *pcie = sys_to_pcie(sys);
+	struct resource *res;
+	int i, ret;
+
+	pcie->root_bus_nr = sys->busnr;
+
+	/* Setup PCI resources */
+	for (i = 0; i < PCI_MAX_RESOURCES; i++) {
+
+		res = &pcie->res[i];
+		if (!res->flags)
+			continue;
+
+		if (res->flags & IORESOURCE_IO) {
+			/* Setup IO mapped memory accesses */
+			ret = pci_ioremap_io(0, res->start);
+			if (ret)
+				return 1;
+
+			/* Correct addresses for remapped IO */
+			res->end = res->end - res->start;
+			res->start = 0;
+		}
+
+		rcar_pcie_setup_window(i, res, pcie);
+		pci_add_resource(&sys->resources, res);
+	}
+
+	return 1;
+}
+
+static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
+{
+	struct platform_device *pdev = to_platform_device(pcie->dev);
+	struct hw_pci hw;
+
+	memset(&hw, 0, sizeof(hw));
+
+	hw.nr_controllers = 1;
+	hw.private_data   = (void **)&pcie;
+	hw.setup          = rcar_pcie_setup,
+	hw.map_irq        = of_irq_parse_and_map_pci,
+	hw.ops		  = &rcar_pcie_ops,
+
+	pci_common_init_dev(&pdev->dev, &hw);
+}
+
+static int __init phy_wait_for_ack(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 100;
+
+	while (timeout--) {
+		if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+			return 0;
+
+		udelay(100);
+	}
+
+	dev_err(pcie->dev, "Access to PCIe phy timed out\n");
+
+	return -ETIMEDOUT;
+}
+
+static void __init phy_write_reg(struct rcar_pcie *pcie,
+				 unsigned int rate, unsigned int addr,
+				 unsigned int lane, unsigned int data)
+{
+	unsigned long phyaddr;
+
+	phyaddr = WRITE_CMD |
+		((rate & 1) << RATE_POS) |
+		((lane & 0xf) << LANE_POS) |
+		((addr & 0xff) << ADR_POS);
+
+	/* Set write data */
+	pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
+	pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+
+	/* Ignore errors as they will be dealt with if the data link is down */
+	phy_wait_for_ack(pcie);
+
+	/* Clear command */
+	pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
+	pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+
+	/* Ignore errors as they will be dealt with if the data link is down */
+	phy_wait_for_ack(pcie);
+}
+
+static int __init rcar_pcie_phy_init_rcar_h1(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10;
+
+	/* Initialize the phy */
+	phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
+	phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
+	phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188);
+	phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188);
+	phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014);
+	phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014);
+	phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0);
+	phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB);
+	phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062);
+	phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000);
+	phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000);
+	phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806);
+
+	phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5);
+	phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
+	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
+
+	while (timeout--) {
+		if (pci_read_reg(pcie, H1_PCIEPHYSR))
+			return 0;
+
+		msleep(5);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int __init rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10;
+
+	while (timeout--) {
+		if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+			return 0;
+
+		msleep(5);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void __init rcar_pcie_hw_init(struct rcar_pcie *pcie)
+{
+	/* Initialise R-Car H1 PHY & wait for it to be ready */
+	if (pcie->chip == RCAR_H1)
+		if (rcar_pcie_phy_init_rcar_h1(pcie))
+			return;
+
+	/* Begin initialization */
+	pci_write_reg(pcie, 0, PCIETCTLR);
+
+	/* Set mode */
+	pci_write_reg(pcie, 1, PCIEMSR);
+
+	/*
+	 * For target transfers, setup a single 64-bit 4GB mapping at address
+	 * 0. The hardware can only map memory that starts on a power of two
+	 * boundary, and size is power of 2, so best to ignore it.
+	 */
+	pci_write_reg(pcie, 0, PCIEPRAR(0));
+	pci_write_reg(pcie, 0, PCIELAR(0));
+	pci_write_reg(pcie, 0xfffffff0UL | LAM_PREFETCH |
+		LAM_64BIT | LAR_ENABLE, PCIELAMR(0));
+	pci_write_reg(pcie, 0, PCIELAR(1));
+	pci_write_reg(pcie, 0, PCIEPRAR(1));
+	pci_write_reg(pcie, 0, PCIELAMR(1));
+
+	/*
+	 * Initial header for port config space is type 1, set the device
+	 * class to match. Hardware takes care of propagating the IDSETR
+	 * settings, so there is no need to bother with a quirk.
+	 */
+	pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+
+	/*
+	 * Setup Secondary Bus Number & Subordinate Bus Number, even though
+	 * they aren't used, to avoid bridge being detected as broken.
+	 */
+	rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
+	rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
+
+	/* Initialize default capabilities. */
+	rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
+		PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+	rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
+		PCI_HEADER_TYPE_BRIDGE);
+
+	/* Enable data link layer active state reporting */
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC);
+
+	/* Write out the physical slot number = 0 */
+	rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
+
+	/* Set the completion timer timeout to the maximum 50ms. */
+	rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
+
+	/* Terminate list of capabilities (Next Capability Offset=0) */
+	rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
+
+	/* Enable MAC data scrambling. */
+	rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
+
+	/* Finish initialization - establish a PCI Express link */
+	pci_write_reg(pcie, CFINIT, PCIETCTLR);
+
+	/* This will timeout if we don't have a link. */
+	pcie->haslink = !rcar_pcie_wait_for_dl(pcie);
+
+	/* Enable INTx interrupts */
+	rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
+
+	/* Enable slave Bus Mastering */
+	rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
+		PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
+
+	wmb();
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int rcar_pcie_runtime_suspend(struct device *dev)
+{
+	struct rcar_pcie *pcie = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(pcie->clk);
+	return 0;
+}
+
+static int rcar_pcie_runtime_resume(struct device *dev)
+{
+	struct rcar_pcie *pcie = dev_get_drvdata(dev);
+
+	clk_prepare_enable(pcie->clk);
+	return 0;
+}
+#endif
+
+static int __init rcar_pcie_get_resources(struct platform_device *pdev,
+	struct rcar_pcie *pcie)
+{
+	struct device *dev = &pdev->dev;
+	struct resource res;
+	int err;
+
+	err = of_address_to_resource(pdev->dev.of_node, 0, &res);
+	if (err)
+		return err;
+
+	pcie->clk = devm_clk_get(&pdev->dev, "pcie");
+	if (IS_ERR(pcie->clk)) {
+		dev_err(pcie->dev, "cannot get platfom clock\n");
+		return PTR_ERR(pcie->clk);
+	}
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	pcie->base = devm_ioremap_resource(&pdev->dev, &res);
+	if (IS_ERR(pcie->base)) {
+		err = PTR_ERR(pcie->base);
+		goto err_map_reg;
+	}
+
+	return 0;
+
+err_map_reg:
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+
+	return err;
+}
+
+static int __init rcar_pcie_probe(struct platform_device *pdev)
+{
+	struct rcar_pcie *pcie;
+	unsigned int data;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	const struct of_device_id *of_id;
+	int err, win = 0;
+
+	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	pcie->dev = &pdev->dev;
+	platform_set_drvdata(pdev, pcie);
+
+	of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
+	if (of_id)
+		pcie->chip = (enum chip_id)of_id->data;
+
+	if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
+		dev_err(&pdev->dev, "missing ranges property\n");
+		return -EINVAL;
+	}
+
+	err = rcar_pcie_get_resources(pdev, pcie);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to request resources: %d\n", err);
+		return err;
+	}
+
+	for_each_of_pci_range(&parser, &range) {
+		of_pci_range_to_resource(&range, pdev->dev.of_node,
+						&pcie->res[win++]);
+
+		if (win > PCI_MAX_RESOURCES)
+			break;
+	}
+
+	rcar_pcie_hw_init(pcie);
+
+	if (!pcie->haslink) {
+		dev_info(&pdev->dev, "PCI: PCIe link down\n");
+		return 0;
+	}
+
+	data = pci_read_reg(pcie, MACSR);
+	dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
+
+	rcar_pcie_enable(pcie);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rcar_pcie_pm_ops = {
+	SET_RUNTIME_PM_OPS(rcar_pcie_runtime_suspend,
+				rcar_pcie_runtime_resume, NULL)
+};
+
+static struct platform_driver rcar_pcie_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = rcar_pcie_of_match,
+		.pm = &rcar_pcie_pm_ops,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init pcie_init(void)
+{
+	return platform_driver_probe(&rcar_pcie_driver, rcar_pcie_probe);
+}
+subsys_initcall(pcie_init);
+
+MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
+MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/pci/host/pcie-rcar.h b/drivers/pci/host/pcie-rcar.h
new file mode 100644
index 0000000..3dc026b
--- /dev/null
+++ b/drivers/pci/host/pcie-rcar.h
@@ -0,0 +1,82 @@
+/*
+ * PCI Express definitions for Renesas R-Car SoCs
+ */
+#ifndef __PCI_RCAR_H
+#define __PCI_RCAR_H
+
+#define PCIECAR			0x000010
+#define PCIECCTLR		0x000018
+#define  CONFIG_SEND_ENABLE	(1 << 31)
+#define  TYPE0			(0 << 8)
+#define  TYPE1			(1 << 8)
+#define PCIECDR			0x000020
+#define PCIEMSR			0x000028
+#define PCIEINTXR		0x000400
+#define PCIEPHYSR		0x0007f0
+
+/* Transfer control */
+#define PCIETCTLR		0x02000
+#define  CFINIT			1
+#define PCIETSTR		0x02004
+#define  DATA_LINK_ACTIVE	1
+#define PCIEINTR		0x02008
+#define PCIEINTER		0x0200c
+#define PCIEERRFR		0x02020
+#define  UNSUPPORTED_REQUEST	(1 << 4)
+#define PCIEERRFER		0x02024
+#define PCIEERRFR2		0x02028
+#define PCIEPMSR		0x02034
+#define PCIEPMSCIER		0x02038
+#define PCIEMSIFR		0x02044
+
+/* root port address */
+#define PCIEPRAR(x)		(0x02080 + ((x) * 0x4))
+
+/* local address reg & mask */
+#define PCIELAR(x)		(0x02200 + ((x) * 0x20))
+#define PCIELAMR(x)		(0x02208 + ((x) * 0x20))
+#define  LAM_PMIOLAMnB3		(1 << 3)
+#define  LAM_PMIOLAMnB2		(1 << 2)
+#define  LAM_PREFETCH		(1 << 3)
+#define  LAM_64BIT		(1 << 2)
+#define  LAR_ENABLE		(1 << 1)
+
+/* PCIe address reg & mask */
+#define PCIEPARL(x)		(0x03400 + ((x) * 0x20))
+#define PCIEPARH(x)		(0x03404 + ((x) * 0x20))
+#define PCIEPAMR(x)		(0x03408 + ((x) * 0x20))
+#define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20))
+#define  PAR_ENABLE		(1 << 31)
+#define  IO_SPACE		(1 << 8)
+
+/* Configuration */
+#define PCICONF(x)		(0x010000 + ((x) * 0x4))
+#define PMCAP(x)		(0x010040 + ((x) * 0x4))
+#define MSICAP(x)		(0x010050 + ((x) * 0x4))
+#define EXPCAP(x)		(0x010070 + ((x) * 0x4))
+#define VCCAP(x)		(0x010100 + ((x) * 0x4))
+#define SERNUMCAP(x)		(0x0101b0 + ((x) * 0x4))
+
+/* link layer */
+#define IDSETR0			0x011000
+#define IDSETR1			0x011004
+#define SUBIDSETR		0x011024
+#define DSERSETR0		0x01102c
+#define DSERSETR1		0x011030
+#define TLCTLR			0x011048
+#define MACSR			0x011054
+#define MACCTLR			0x011058
+#define  SCRAMBLE_DISABLE	(1 << 27)
+
+/* R-Car H1 PHY */
+#define H1_PCIEPHYCTLR		0x040008
+#define H1_PCIEPHYADRR		0x04000c
+#define  WRITE_CMD		(1 << 16)
+#define  PHY_ACK		(1 << 24)
+#define  RATE_POS		12
+#define  LANE_POS		8
+#define  ADR_POS		0
+#define H1_PCIEPHYDOUTR		0x040014
+#define H1_PCIEPHYSR		0x040018
+
+#endif /* __PCI_RCAR_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/9] PCI: host: rcar: Add MSI support
  2014-03-13  9:49 ` Phil Edworthy
  (?)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 drivers/pci/host/pcie-rcar.c |  232 +++++++++++++++++++++++++++++++++++++++++-
 drivers/pci/host/pcie-rcar.h |    5 +
 2 files changed, 236 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 7f094fa..a6f4049 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -14,8 +14,11 @@
 
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/msi.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_pci.h>
@@ -34,6 +37,8 @@ enum chip_id {
 	RCAR_H1,
 };
 
+#define INT_PCI_MSI_NR	32
+
 #define RCONF(x)	(PCICONF(0)+(x))
 #define RPMCAP(x)	(PMCAP(0)+(x))
 #define REXPCAP(x)	(EXPCAP(0)+(x))
@@ -53,6 +58,20 @@ static const struct of_device_id rcar_pcie_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
 
+struct rcar_msi {
+	DECLARE_BITMAP(used, INT_PCI_MSI_NR);
+	struct irq_domain *domain;
+	struct msi_chip chip;
+	unsigned long pages;
+	struct mutex lock;
+	int irq;
+};
+
+static inline struct rcar_msi *to_rcar_msi(struct msi_chip *chip)
+{
+	return container_of(chip, struct rcar_msi, chip);
+}
+
 /* Structure representing the PCIe interface */
 struct rcar_pcie {
 	struct device		*dev;
@@ -62,6 +81,7 @@ struct rcar_pcie {
 	enum chip_id		chip;
 	u8			root_bus_nr;
 	struct clk		*clk;
+	struct			rcar_msi msi;
 };
 
 static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
@@ -313,6 +333,15 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
 	return 1;
 }
 
+static void rcar_pcie_add_bus(struct pci_bus *bus)
+{
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
+
+		bus->msi = &pcie->msi.chip;
+	}
+}
+
 static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
 {
 	struct platform_device *pdev = to_platform_device(pcie->dev);
@@ -325,6 +354,7 @@ static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
 	hw.setup          = rcar_pcie_setup,
 	hw.map_irq        = of_irq_parse_and_map_pci,
 	hw.ops		  = &rcar_pcie_ops,
+	hw.add_bus	  = rcar_pcie_add_bus;
 
 	pci_common_init_dev(&pdev->dev, &hw);
 }
@@ -479,6 +509,10 @@ static void __init rcar_pcie_hw_init(struct rcar_pcie *pcie)
 	/* Enable MAC data scrambling. */
 	rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
 
+	/* Enable MSI */
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
+
 	/* Finish initialization - establish a PCI Express link */
 	pci_write_reg(pcie, CFINIT, PCIETCTLR);
 
@@ -514,12 +548,191 @@ static int rcar_pcie_runtime_resume(struct device *dev)
 }
 #endif
 
+static int rcar_msi_alloc(struct rcar_msi *chip)
+{
+	int msi;
+
+	mutex_lock(&chip->lock);
+
+	msi = find_first_zero_bit(chip->used, INT_PCI_MSI_NR);
+	if (msi < INT_PCI_MSI_NR)
+		set_bit(msi, chip->used);
+	else
+		msi = -ENOSPC;
+
+	mutex_unlock(&chip->lock);
+
+	return msi;
+}
+
+static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq)
+{
+	struct device *dev = chip->chip.dev;
+
+	mutex_lock(&chip->lock);
+
+	if (!test_bit(irq, chip->used))
+		dev_err(dev, "trying to free unused MSI#%lu\n", irq);
+	else
+		clear_bit(irq, chip->used);
+
+	mutex_unlock(&chip->lock);
+}
+
+static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
+{
+	struct rcar_pcie *pcie = data;
+	struct rcar_msi *msi = &pcie->msi;
+	unsigned long reg;
+
+	reg = pci_read_reg(pcie, PCIEMSIFR);
+
+	while (reg) {
+		unsigned int index = find_first_bit(&reg, 32);
+		unsigned int irq;
+
+		/* clear the interrupt */
+		pci_write_reg(pcie, 1 << index, PCIEMSIFR);
+
+		irq = irq_find_mapping(msi->domain, index);
+		if (irq) {
+			if (test_bit(index, msi->used))
+				generic_handle_irq(irq);
+			else
+				dev_info(pcie->dev, "unhandled MSI\n");
+		} else {
+			/*
+			 * that's weird who triggered this?
+			 * just clear it
+			 */
+			dev_info(pcie->dev, "unexpected MSI\n");
+		}
+
+		/* see if there's any more pending in this vector */
+		reg = pci_read_reg(pcie, PCIEMSIFR);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
+			       struct msi_desc *desc)
+{
+	struct rcar_msi *msi = to_rcar_msi(chip);
+	struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip);
+	struct msi_msg msg;
+	unsigned int irq;
+	int hwirq;
+
+	hwirq = rcar_msi_alloc(msi);
+	if (hwirq < 0)
+		return hwirq;
+
+	irq = irq_create_mapping(msi->domain, hwirq);
+	if (!irq) {
+		rcar_msi_free(msi, hwirq);
+		return -EINVAL;
+	}
+
+	irq_set_msi_desc(irq, desc);
+
+	msg.address_lo = pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
+	msg.address_hi = pci_read_reg(pcie, PCIEMSIAUR);
+	msg.data = hwirq;
+
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+static void rcar_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
+{
+	struct rcar_msi *msi = to_rcar_msi(chip);
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	rcar_msi_free(msi, d->hwirq);
+}
+
+static struct irq_chip rcar_msi_irq_chip = {
+	.name = "R-Car PCIe MSI",
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+static int rcar_msi_map(struct irq_domain *domain, unsigned int irq,
+			 irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &rcar_msi_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+	.map = rcar_msi_map,
+};
+
+static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
+{
+	struct platform_device *pdev = to_platform_device(pcie->dev);
+	struct rcar_msi *msi = &pcie->msi;
+	unsigned long base;
+	int err;
+
+	mutex_init(&msi->lock);
+
+	msi->chip.dev = pcie->dev;
+	msi->chip.setup_irq = rcar_msi_setup_irq;
+	msi->chip.teardown_irq = rcar_msi_teardown_irq;
+
+	msi->domain = irq_domain_add_linear(pcie->dev->of_node, INT_PCI_MSI_NR,
+					    &msi_domain_ops, &msi->chip);
+	if (!msi->domain) {
+		dev_err(&pdev->dev, "failed to create IRQ domain\n");
+		return -ENOMEM;
+	}
+
+	/* Two irqs are for MSI, but they are also used for non-MSI irqs */
+	err = devm_request_irq(&pdev->dev, msi->irq, rcar_pcie_msi_irq,
+			       IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+		goto err;
+	}
+
+	err = devm_request_irq(&pdev->dev, msi->irq+1, rcar_pcie_msi_irq,
+			       IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+		goto err;
+	}
+
+	/* setup MSI data target */
+	msi->pages = __get_free_pages(GFP_KERNEL, 0);
+	base = virt_to_phys((void *)msi->pages);
+
+	pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
+	pci_write_reg(pcie, 0, PCIEMSIAUR);
+
+	/* enable all MSI interrupts */
+	pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+
+	return 0;
+
+err:
+	irq_domain_remove(msi->domain);
+	return err;
+}
+
 static int __init rcar_pcie_get_resources(struct platform_device *pdev,
 	struct rcar_pcie *pcie)
 {
 	struct device *dev = &pdev->dev;
 	struct resource res;
-	int err;
+	int err, i;
 
 	err = of_address_to_resource(pdev->dev.of_node, 0, &res);
 	if (err)
@@ -531,6 +744,13 @@ static int __init rcar_pcie_get_resources(struct platform_device *pdev,
 		return PTR_ERR(pcie->clk);
 	}
 
+	i = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (i < 0) {
+		dev_err(pcie->dev, "cannot get platform resources for msi interrupt\n");
+		return -ENOENT;
+	}
+	pcie->msi.irq = i;
+
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
@@ -588,6 +808,16 @@ static int __init rcar_pcie_probe(struct platform_device *pdev)
 			break;
 	}
 
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		err = rcar_pcie_enable_msi(pcie);
+		if (err < 0) {
+			dev_err(&pdev->dev,
+				"failed to enable MSI support: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	rcar_pcie_hw_init(pcie);
 
 	if (!pcie->haslink) {
diff --git a/drivers/pci/host/pcie-rcar.h b/drivers/pci/host/pcie-rcar.h
index 3dc026b..4f0c678 100644
--- a/drivers/pci/host/pcie-rcar.h
+++ b/drivers/pci/host/pcie-rcar.h
@@ -13,6 +13,7 @@
 #define PCIEMSR			0x000028
 #define PCIEINTXR		0x000400
 #define PCIEPHYSR		0x0007f0
+#define PCIEMSITXR		0x000840
 
 /* Transfer control */
 #define PCIETCTLR		0x02000
@@ -28,6 +29,10 @@
 #define PCIEPMSR		0x02034
 #define PCIEPMSCIER		0x02038
 #define PCIEMSIFR		0x02044
+#define PCIEMSIALR		0x02048
+#define  MSIFE			1
+#define PCIEMSIAUR		0x0204c
+#define PCIEMSIIER		0x02050
 
 /* root port address */
 #define PCIEPRAR(x)		(0x02080 + ((x) * 0x4))
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/9] ARM: shmobile: r8a7790: Add PCIe clock device tree nodes
  2014-03-13  9:49 ` Phil Edworthy
@ 2014-03-13  9:50   ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree clock nodes for PCIe

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7790.dtsi            |    7 ++++---
 include/dt-bindings/clock/r8a7790-clock.h |    1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index da69afc..df9ec61 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -704,16 +704,17 @@
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>,
 				 <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>,
-				 <&mmc0_clk>, <&rclk_clk>;
+				 <&mmc0_clk>, <&rclk_clk>, <&mp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
 				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0
-				R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1
+				R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1 R8A7790_CLK_PCIE
 			>;
 			clock-output-names  				"tpu0", "mmcif1", "sdhi3", "sdhi2",
-				"sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"sdhi1", "sdhi0", "mmcif0", "cmt1",
+				"pcie";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h
index 6548a5f..840dbc8 100644
--- a/include/dt-bindings/clock/r8a7790-clock.h
+++ b/include/dt-bindings/clock/r8a7790-clock.h
@@ -57,6 +57,7 @@
 #define R8A7790_CLK_SDHI1		13
 #define R8A7790_CLK_SDHI0		14
 #define R8A7790_CLK_MMCIF0		15
+#define R8A7790_CLK_PCIE		19
 #define R8A7790_CLK_SSUSB		28
 #define R8A7790_CLK_CMT1		29
 #define R8A7790_CLK_USBDMAC0		30
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/9] ARM: shmobile: r8a7790: Add PCIe clock device tree nodes
@ 2014-03-13  9:50   ` Phil Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree clock nodes for PCIe

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7790.dtsi            |    7 ++++---
 include/dt-bindings/clock/r8a7790-clock.h |    1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index da69afc..df9ec61 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -704,16 +704,17 @@
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>,
 				 <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>,
-				 <&mmc0_clk>, <&rclk_clk>;
+				 <&mmc0_clk>, <&rclk_clk>, <&mp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
 				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0
-				R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1
+				R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1 R8A7790_CLK_PCIE
 			>;
 			clock-output-names =
 				"tpu0", "mmcif1", "sdhi3", "sdhi2",
-				"sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"sdhi1", "sdhi0", "mmcif0", "cmt1",
+				"pcie";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h
index 6548a5f..840dbc8 100644
--- a/include/dt-bindings/clock/r8a7790-clock.h
+++ b/include/dt-bindings/clock/r8a7790-clock.h
@@ -57,6 +57,7 @@
 #define R8A7790_CLK_SDHI1		13
 #define R8A7790_CLK_SDHI0		14
 #define R8A7790_CLK_MMCIF0		15
+#define R8A7790_CLK_PCIE		19
 #define R8A7790_CLK_SSUSB		28
 #define R8A7790_CLK_CMT1		29
 #define R8A7790_CLK_USBDMAC0		30
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/9] ARM: shmobile: r8a7791: Add PCIe clock device tree nodes
  2014-03-13  9:49 ` Phil Edworthy
@ 2014-03-13  9:50   ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree clock nodes for PCIe

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7791.dtsi            |    7 +++++--
 include/dt-bindings/clock/r8a7791-clock.h |    1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 71bac2c..ccfba57 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -717,14 +717,17 @@
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>,
-				<&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>;
+				<&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>,
+				<&mp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1
 				R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_CMT1
+				R8A7791_CLK_PCIE
 			>;
 			clock-output-names -				"tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1",
+				"pcie";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h
index 30f82f2..d3e2cf5 100644
--- a/include/dt-bindings/clock/r8a7791-clock.h
+++ b/include/dt-bindings/clock/r8a7791-clock.h
@@ -51,6 +51,7 @@
 #define R8A7791_CLK_SDHI1		12
 #define R8A7791_CLK_SDHI0		14
 #define R8A7791_CLK_MMCIF0		15
+#define R8A7791_CLK_PCIE		19
 #define R8A7791_CLK_SSUSB		28
 #define R8A7791_CLK_CMT1		29
 #define R8A7791_CLK_USBDMAC0		30
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/9] ARM: shmobile: r8a7791: Add PCIe clock device tree nodes
@ 2014-03-13  9:50   ` Phil Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree clock nodes for PCIe

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7791.dtsi            |    7 +++++--
 include/dt-bindings/clock/r8a7791-clock.h |    1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 71bac2c..ccfba57 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -717,14 +717,17 @@
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>,
-				<&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>;
+				<&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>,
+				<&mp_clk>;
 			#clock-cells = <1>;
 			renesas,clock-indices = <
 				R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1
 				R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_CMT1
+				R8A7791_CLK_PCIE
 			>;
 			clock-output-names =
-				"tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1";
+				"tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1",
+				"pcie";
 		};
 		mstp5_clks: mstp5_clks@e6150144 {
 			compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h
index 30f82f2..d3e2cf5 100644
--- a/include/dt-bindings/clock/r8a7791-clock.h
+++ b/include/dt-bindings/clock/r8a7791-clock.h
@@ -51,6 +51,7 @@
 #define R8A7791_CLK_SDHI1		12
 #define R8A7791_CLK_SDHI0		14
 #define R8A7791_CLK_MMCIF0		15
+#define R8A7791_CLK_PCIE		19
 #define R8A7791_CLK_SSUSB		28
 #define R8A7791_CLK_CMT1		29
 #define R8A7791_CLK_USBDMAC0		30
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
  2014-03-13  9:49 ` Phil Edworthy
                   ` (4 preceding siblings ...)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  2014-03-13 10:00     ` Arnd Bergmann
  -1 siblings, 1 reply; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy, devicetree

This patch adds the bindings for the rcar PCIE driver. The driver
resides under drivers/pci/host/pcie-rcar.c

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 Documentation/devicetree/bindings/pci/rcar-pci.txt | 40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt

diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/Documentation/devicetree/bindings/pci/rcar-pci.txt
new file mode 100644
index 0000000..0e219b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt
@@ -0,0 +1,40 @@
+* Renesas RCar PCIe interface
+
+Required properties:
+- compatible: should contain one of the following
+	"renesas,r8a7779-pcie", "renesas,r8a7790-pcie", "renesas,r8a7791-pcie"
+- reg: base addresses and lengths of the pcie controller.
+- #address-cells: set to <3>
+- #size-cells: set to <2>
+- device_type: set to "pci"
+- ranges: ranges for the PCI memory and I/O regions
+- interrupts: interrupt values for MSI interrupt
+- #interrupt-cells: set to <1>
+- interrupt-map-mask and interrupt-map: standard PCI properties
+	to define the mapping of the PCIe interface to interrupt
+	numbers.
+- clocks: from common clock binding: handle to pci clock.
+- clock-names: from common clock binding: should be "pcie"
+
+Example:
+
+SoC specific DT Entry:
+
+	pcie: pcie@0x01000000 {
+		compatible = "renesas,r8a7790-pcie";
+		reg = <0 0xfe000000 0 0x80000>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+		interrupts = <0 116 4>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 116 4>;
+		clocks = <&mstp3_clks R8A7790_CLK_PCIE>;
+		clock-names = "pcie";
+		status = "disabled";
+	};
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/9] ARM: shmobile: Add PCIe device tree nodes for R8A7790
  2014-03-13  9:49 ` Phil Edworthy
                   ` (5 preceding siblings ...)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree nodes for R8A7790

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7790.dtsi |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index df9ec61..e7d498a 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -821,4 +821,23 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	pcie: pcie@fe000000 {
+		compatible = "renesas,r8a7790-pcie";
+		reg = <0 0xfe000000 0 0x80000>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+		interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_PCIE>;
+		clock-names = "pcie";
+		status = "disabled";
+	};
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/9] ARM: shmobile: Add PCIe device tree nodes for R8A7791 Koelsch board
  2014-03-13  9:49 ` Phil Edworthy
                   ` (6 preceding siblings ...)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This patch adds the device tree nodes for the R8A7791 Koelsch board

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/boot/dts/r8a7791-koelsch.dts |    4 ++++
 arch/arm/boot/dts/r8a7791.dtsi        |   19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index e24fed9..17c953f 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -352,3 +352,7 @@
 		spi-cpha;
 	};
 };
+
+&pcie {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index ccfba57..915a5a6 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -836,4 +836,23 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	pcie: pcie@fe000000 {
+		compatible = "renesas,r8a7791-pcie";
+		reg = <0 0xfe000000 0 0x80000>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+		interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_PCIE>;
+		clock-names = "pcie";
+		status = "disabled";
+	};
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 8/9] ARM: koelsch: Add PCIe to defconfig
  2014-03-13  9:49 ` Phil Edworthy
                   ` (7 preceding siblings ...)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/configs/koelsch_defconfig |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
index 86faab5..ec14547 100644
--- a/arch/arm/configs/koelsch_defconfig
+++ b/arch/arm/configs/koelsch_defconfig
@@ -15,6 +15,9 @@ CONFIG_MACH_KOELSCH=y
 CONFIG_CPU_BPREDICT_DISABLE=y
 CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_754322=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_RCAR_GEN2_PCIE=y
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 9/9] ARM: koelsch: Add HAVE_ARM_ARCH_TIMER to defconfig
  2014-03-13  9:49 ` Phil Edworthy
                   ` (8 preceding siblings ...)
  (?)
@ 2014-03-13  9:50 ` Phil Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil Edworthy @ 2014-03-13  9:50 UTC (permalink / raw)
  To: linux-pci
  Cc: linux-sh, Bjorn Helgaas, Valentine Barshak, Simon Horman,
	Magnus Damm, Ben Dooks, Phil Edworthy

This is fixes a boot problem when the R-Car PCIe driver is enabled.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
 arch/arm/configs/koelsch_defconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
index ec14547..67666b6 100644
--- a/arch/arm/configs/koelsch_defconfig
+++ b/arch/arm/configs/koelsch_defconfig
@@ -15,6 +15,7 @@ CONFIG_MACH_KOELSCH=y
 CONFIG_CPU_BPREDICT_DISABLE=y
 CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_754322=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_RCAR_GEN2_PCIE=y
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
  2014-03-13  9:50 ` [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings Phil Edworthy
@ 2014-03-13 10:00     ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2014-03-13 10:00 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: linux-pci, linux-sh, Bjorn Helgaas, Valentine Barshak,
	Simon Horman, Magnus Damm, Ben Dooks, devicetree

On Thursday 13 March 2014 09:50:04 Phil Edworthy wrote:
> This patch adds the bindings for the rcar PCIE driver. The driver
> resides under drivers/pci/host/pcie-rcar.c
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
>  Documentation/devicetree/bindings/pci/rcar-pci.txt | 40 ++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt
> 
> diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/Documentation/devicetree/bindings/pci/rcar-pci.txt
> new file mode 100644
> index 0000000..0e219b0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt
> @@ -0,0 +1,40 @@
> +* Renesas RCar PCIe interface
> +
> +Required properties:
> +- compatible: should contain one of the following
> +	"renesas,r8a7779-pcie", "renesas,r8a7790-pcie", "renesas,r8a7791-pcie"
> +- reg: base addresses and lengths of the pcie controller.
> +- #address-cells: set to <3>
> +- #size-cells: set to <2>
> +- device_type: set to "pci"
> +- ranges: ranges for the PCI memory and I/O regions

I see your description and example includes I/O regions, but the driver
claims in a comment that these don't work. Do you also have a patch to
make them work?

In case that patch is part of the 9-patch series, do you mind adding the
arm kernel mailing list (and maybe me personally) to Cc the next time?

> +- interrupts: interrupt values for MSI interrupt
> +- #interrupt-cells: set to <1>
> +- interrupt-map-mask and interrupt-map: standard PCI properties
> +	to define the mapping of the PCIe interface to interrupt
> +	numbers.
> +- clocks: from common clock binding: handle to pci clock.
> +- clock-names: from common clock binding: should be "pcie"
> +
> +Example:
> +
> +SoC specific DT Entry:
> +
> +	pcie: pcie@0x01000000 {
> +		compatible = "renesas,r8a7790-pcie";
> +		reg = <0 0xfe000000 0 0x80000>;
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		device_type = "pci";
> +		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
> +			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
> +			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
> +			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;

I'm curious about why there are two non-prefetchable regions. What is
the significance of this?

> +		interrupts = <0 116 4>;
> +		#interrupt-cells = <1>;
> +		interrupt-map-mask = <0 0 0 0>;
> +		interrupt-map = <0 0 0 0 &gic 0 116 4>;
> +		clocks = <&mstp3_clks R8A7790_CLK_PCIE>;
> +		clock-names = "pcie";
> +		status = "disabled";
> +	};

Are you sure that there is only one legacy interrupt?  Most host
controllers wire up IntA through IntD to different output pins.

Otherwise looks good.

	Arnd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
@ 2014-03-13 10:00     ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2014-03-13 10:00 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: linux-pci, linux-sh, Bjorn Helgaas, Valentine Barshak,
	Simon Horman, Magnus Damm, Ben Dooks, devicetree

On Thursday 13 March 2014 09:50:04 Phil Edworthy wrote:
> This patch adds the bindings for the rcar PCIE driver. The driver
> resides under drivers/pci/host/pcie-rcar.c
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
>  Documentation/devicetree/bindings/pci/rcar-pci.txt | 40 ++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt
> 
> diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/Documentation/devicetree/bindings/pci/rcar-pci.txt
> new file mode 100644
> index 0000000..0e219b0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt
> @@ -0,0 +1,40 @@
> +* Renesas RCar PCIe interface
> +
> +Required properties:
> +- compatible: should contain one of the following
> +	"renesas,r8a7779-pcie", "renesas,r8a7790-pcie", "renesas,r8a7791-pcie"
> +- reg: base addresses and lengths of the pcie controller.
> +- #address-cells: set to <3>
> +- #size-cells: set to <2>
> +- device_type: set to "pci"
> +- ranges: ranges for the PCI memory and I/O regions

I see your description and example includes I/O regions, but the driver
claims in a comment that these don't work. Do you also have a patch to
make them work?

In case that patch is part of the 9-patch series, do you mind adding the
arm kernel mailing list (and maybe me personally) to Cc the next time?

> +- interrupts: interrupt values for MSI interrupt
> +- #interrupt-cells: set to <1>
> +- interrupt-map-mask and interrupt-map: standard PCI properties
> +	to define the mapping of the PCIe interface to interrupt
> +	numbers.
> +- clocks: from common clock binding: handle to pci clock.
> +- clock-names: from common clock binding: should be "pcie"
> +
> +Example:
> +
> +SoC specific DT Entry:
> +
> +	pcie: pcie@0x01000000 {
> +		compatible = "renesas,r8a7790-pcie";
> +		reg = <0 0xfe000000 0 0x80000>;
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		device_type = "pci";
> +		ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
> +			  0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
> +			  0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
> +			  0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;

I'm curious about why there are two non-prefetchable regions. What is
the significance of this?

> +		interrupts = <0 116 4>;
> +		#interrupt-cells = <1>;
> +		interrupt-map-mask = <0 0 0 0>;
> +		interrupt-map = <0 0 0 0 &gic 0 116 4>;
> +		clocks = <&mstp3_clks R8A7790_CLK_PCIE>;
> +		clock-names = "pcie";
> +		status = "disabled";
> +	};

Are you sure that there is only one legacy interrupt?  Most host
controllers wire up IntA through IntD to different output pins.

Otherwise looks good.

	Arnd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
  2014-03-13 10:00     ` Arnd Bergmann
  (?)
@ 2014-03-13 10:28     ` Phil.Edworthy
  2014-03-13 11:30         ` Arnd Bergmann
  -1 siblings, 1 reply; 23+ messages in thread
From: Phil.Edworthy @ 2014-03-13 10:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Ben Dooks, Bjorn Helgaas, devicetree, Simon Horman, linux-pci,
	linux-sh, Magnus Damm, Valentine Barshak

Hi Arnd,

Thanks for your review.

On 13/03/2014 10:00, Arnd wrote:
> On Thursday 13 March 2014 09:50:04 Phil Edworthy wrote:
> > This patch adds the bindings for the rcar PCIE driver. The driver
> > resides under drivers/pci/host/pcie-rcar.c
> > 
> > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > ---
> >  Documentation/devicetree/bindings/pci/rcar-pci.txt | 40 
++++++++++++++++++++++
> >  1 file changed, 40 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/
> Documentation/devicetree/bindings/pci/rcar-pci.txt
> > new file mode 100644
> > index 0000000..0e219b0
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt
> > @@ -0,0 +1,40 @@
> > +* Renesas RCar PCIe interface
> > +
> > +Required properties:
> > +- compatible: should contain one of the following
> > +   "renesas,r8a7779-pcie", "renesas,r8a7790-pcie", 
"renesas,r8a7791-pcie"
> > +- reg: base addresses and lengths of the pcie controller.
> > +- #address-cells: set to <3>
> > +- #size-cells: set to <2>
> > +- device_type: set to "pci"
> > +- ranges: ranges for the PCI memory and I/O regions
> 
> I see your description and example includes I/O regions, but the driver
> claims in a comment that these don't work. Do you also have a patch to
> make them work?
Are you referring to the comment "The controller does not support/use port 
I/O" in the driver for the internal PCI controller (pci-rcar-gen2.c)?
This is a separate block of hardware, it's a PCIe controller with external 
pins, for which we do support I/O regions.

> In case that patch is part of the 9-patch series, do you mind adding the
> arm kernel mailing list (and maybe me personally) to Cc the next time?
Sure, the rest of the patch set adds this new PCIe driver and adds it to 
the R-Car devices & boards.

> > +- interrupts: interrupt values for MSI interrupt
> > +- #interrupt-cells: set to <1>
> > +- interrupt-map-mask and interrupt-map: standard PCI properties
> > +   to define the mapping of the PCIe interface to interrupt
> > +   numbers.
> > +- clocks: from common clock binding: handle to pci clock.
> > +- clock-names: from common clock binding: should be "pcie"
> > +
> > +Example:
> > +
> > +SoC specific DT Entry:
> > +
> > +   pcie: pcie@0x01000000 {
> > +      compatible = "renesas,r8a7790-pcie";
> > +      reg = <0 0xfe000000 0 0x80000>;
> > +      #address-cells = <3>;
> > +      #size-cells = <2>;
> > +      device_type = "pci";
> > +      ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
> > +           0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
> > +           0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
> > +           0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
> 
> I'm curious about why there are two non-prefetchable regions. What is
> the significance of this?
The devices that have this PCIe controller both have a number of fixed, 
non-contiguous memory regions that can be used as PCIe windows. The ranges 
here map onto those fixed windows, i.e. if the CPU addresses of the ranges 
change it won't work. The first couple of windows are small, we use the 
first one for I/O, we decided that we may as well use the next small 
window for memory - otherwise we need to figure out a way to tell the 
driver to skip a window.

> > +      interrupts = <0 116 4>;
> > +      #interrupt-cells = <1>;
> > +      interrupt-map-mask = <0 0 0 0>;
> > +      interrupt-map = <0 0 0 0 &gic 0 116 4>;
> > +      clocks = <&mstp3_clks R8A7790_CLK_PCIE>;
> > +      clock-names = "pcie";
> > +      status = "disabled";
> > +   };
> 
> Are you sure that there is only one legacy interrupt?  Most host
> controllers wire up IntA through IntD to different output pins.
Yes, and we've tested that as well.

> Otherwise looks good.
> 
>    Arnd

Thanks
Phil

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
  2014-03-13 10:28     ` Phil.Edworthy
@ 2014-03-13 11:30         ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2014-03-13 11:30 UTC (permalink / raw)
  To: Phil.Edworthy
  Cc: Ben Dooks, Bjorn Helgaas, devicetree, Simon Horman, linux-pci,
	linux-sh, Magnus Damm, Valentine Barshak

On Thursday 13 March 2014 10:28:03 Phil.Edworthy@renesas.com wrote:
> On 13/03/2014 10:00, Arnd wrote:
> > On Thursday 13 March 2014 09:50:04 Phil Edworthy wrote:
> > 
> > I see your description and example includes I/O regions, but the driver
> > claims in a comment that these don't work. Do you also have a patch to
> > make them work?
> Are you referring to the comment "The controller does not support/use port 
> I/O" in the driver for the internal PCI controller (pci-rcar-gen2.c)?
> This is a separate block of hardware, it's a PCIe controller with external 
> pins, for which we do support I/O regions.

Ok, thanks for the clarification.

> > > +- interrupts: interrupt values for MSI interrupt
> > > +- #interrupt-cells: set to <1>
> > > +- interrupt-map-mask and interrupt-map: standard PCI properties
> > > +   to define the mapping of the PCIe interface to interrupt
> > > +   numbers.
> > > +- clocks: from common clock binding: handle to pci clock.
> > > +- clock-names: from common clock binding: should be "pcie"
> > > +
> > > +Example:
> > > +
> > > +SoC specific DT Entry:
> > > +
> > > +   pcie: pcie@0x01000000 {
> > > +      compatible = "renesas,r8a7790-pcie";
> > > +      reg = <0 0xfe000000 0 0x80000>;
> > > +      #address-cells = <3>;
> > > +      #size-cells = <2>;
> > > +      device_type = "pci";
> > > +      ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
> > > +           0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
> > > +           0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
> > > +           0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
> > 
> > I'm curious about why there are two non-prefetchable regions. What is
> > the significance of this?
>
> The devices that have this PCIe controller both have a number of fixed, 
> non-contiguous memory regions that can be used as PCIe windows. The ranges 
> here map onto those fixed windows, i.e. if the CPU addresses of the ranges 
> change it won't work. The first couple of windows are small, we use the 
> first one for I/O, we decided that we may as well use the next small 
> window for memory - otherwise we need to figure out a way to tell the 
> driver to skip a window.

Ok, makes sense. Good to know that this actually works. An idea that
may be helpful in some corner cases: if you can set up the small window as

           0x02000000 0 0 0 0xfe200000 0 0x00200000

or even

           0x02000000 0 0 0 0xfe200000 0 0x00100000
           0x02000000 0 0x00f00000 0 0xfe200000 0 0x00100000

then you will be able to map devices with legacy nonrelocatable ISA
memory BARs such as VGA cards that have PCI resources in the first MB
of bus space, and in the end of the first 16MB.

	Arnd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings
@ 2014-03-13 11:30         ` Arnd Bergmann
  0 siblings, 0 replies; 23+ messages in thread
From: Arnd Bergmann @ 2014-03-13 11:30 UTC (permalink / raw)
  To: Phil.Edworthy
  Cc: Ben Dooks, Bjorn Helgaas, devicetree, Simon Horman, linux-pci,
	linux-sh, Magnus Damm, Valentine Barshak

On Thursday 13 March 2014 10:28:03 Phil.Edworthy@renesas.com wrote:
> On 13/03/2014 10:00, Arnd wrote:
> > On Thursday 13 March 2014 09:50:04 Phil Edworthy wrote:
> > 
> > I see your description and example includes I/O regions, but the driver
> > claims in a comment that these don't work. Do you also have a patch to
> > make them work?
> Are you referring to the comment "The controller does not support/use port 
> I/O" in the driver for the internal PCI controller (pci-rcar-gen2.c)?
> This is a separate block of hardware, it's a PCIe controller with external 
> pins, for which we do support I/O regions.

Ok, thanks for the clarification.

> > > +- interrupts: interrupt values for MSI interrupt
> > > +- #interrupt-cells: set to <1>
> > > +- interrupt-map-mask and interrupt-map: standard PCI properties
> > > +   to define the mapping of the PCIe interface to interrupt
> > > +   numbers.
> > > +- clocks: from common clock binding: handle to pci clock.
> > > +- clock-names: from common clock binding: should be "pcie"
> > > +
> > > +Example:
> > > +
> > > +SoC specific DT Entry:
> > > +
> > > +   pcie: pcie@0x01000000 {
> > > +      compatible = "renesas,r8a7790-pcie";
> > > +      reg = <0 0xfe000000 0 0x80000>;
> > > +      #address-cells = <3>;
> > > +      #size-cells = <2>;
> > > +      device_type = "pci";
> > > +      ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
> > > +           0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
> > > +           0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
> > > +           0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
> > 
> > I'm curious about why there are two non-prefetchable regions. What is
> > the significance of this?
>
> The devices that have this PCIe controller both have a number of fixed, 
> non-contiguous memory regions that can be used as PCIe windows. The ranges 
> here map onto those fixed windows, i.e. if the CPU addresses of the ranges 
> change it won't work. The first couple of windows are small, we use the 
> first one for I/O, we decided that we may as well use the next small 
> window for memory - otherwise we need to figure out a way to tell the 
> driver to skip a window.

Ok, makes sense. Good to know that this actually works. An idea that
may be helpful in some corner cases: if you can set up the small window as

           0x02000000 0 0 0 0xfe200000 0 0x00200000

or even

           0x02000000 0 0 0 0xfe200000 0 0x00100000
           0x02000000 0 0x00f00000 0 0xfe200000 0 0x00100000

then you will be able to map devices with legacy nonrelocatable ISA
memory BARs such as VGA cards that have PCI resources in the first MB
of bus space, and in the end of the first 16MB.

	Arnd

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
  2014-03-13  9:50   ` Phil Edworthy
@ 2014-03-20 16:41     ` Phil.Edworthy
  -1 siblings, 0 replies; 23+ messages in thread
From: Phil.Edworthy @ 2014-03-20 16:41 UTC (permalink / raw)
  To: linux-pci
  Cc: Ben Dooks, Bjorn Helgaas, Simon Horman, linux-sh, Magnus Damm,
	Valentine Barshak

Hi,

Whilst looking at something else, I've realised that I completely messed 
up my use of runtime PM in this driver... I'll fix that up & resend.

On 13/03/2014 09:50, Phil Edworthy wrote:
> Subject: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
> 
> This PCIe Host driver currently does not support MSI, so cards
> fall back to INTx interrupts.
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
> v3:
>  - Add DT support
>  - Use 'of_irq_parse_and_map_pci' for '.map_irq'
>  - Use pm ops to enable clocks
>  - Fix checkpatch errors
>  - Use subsys_initcall to overcome issues with port bus driver
>  - Adjust Kconfig to match other R-Car drivers
> 
> v2:
>  - Use msleep instead of udelay when waiting for the link
>  - Use pm_runtime
>  - Removed unused definition
>  - Also replaced call to devm_request_and_ioremap with 
devm_ioremap_resource
>    and fixed a bug with this when reporting errors.
> ---
>  drivers/pci/host/Kconfig     |    6 +
>  drivers/pci/host/Makefile    |    1 +
>  drivers/pci/host/pcie-rcar.c |  629 
++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pcie-rcar.h |   82 ++++++
>  4 files changed, 718 insertions(+)
>  create mode 100644 drivers/pci/host/pcie-rcar.c
>  create mode 100644 drivers/pci/host/pcie-rcar.h
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 47d46c6..dc627e5 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -33,4 +33,10 @@ config PCI_RCAR_GEN2
>       There are 3 internal PCI controllers available with a single
>       built-in EHCI/OHCI host controller present on each one.
> 
> +config PCI_RCAR_GEN2_PCIE
> +   bool "Renesas R-Car PCIe controller"
> +   depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
> +   help
> +     Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
> +
>  endmenu
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 13fb333..19946f9 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
>  obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
>  obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
>  obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> +obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> new file mode 100644
> index 0000000..7f094fa
> --- /dev/null
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -0,0 +1,629 @@
> +/*
> + * PCIe driver for Renesas R-Car SoCs
> + *  Copyright (C) 2013 Renesas Electronics Europe Ltd
> + *
> + * Based on:
> + *  arch/sh/drivers/pci/pcie-sh7786.c
> + *  arch/sh/drivers/pci/ops-sh7786.c
> + *  Copyright (C) 2009 - 2011  Paul Mundt
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +#include "pcie-rcar.h"
> +
> +#define DRV_NAME "rcar-pcie"
> +
> +enum chip_id {
> +   RCAR_GENERIC,
> +   RCAR_H1,
> +};
> +
> +#define RCONF(x)   (PCICONF(0)+(x))
> +#define RPMCAP(x)   (PMCAP(0)+(x))
> +#define REXPCAP(x)   (EXPCAP(0)+(x))
> +#define RVCCAP(x)   (VCCAP(0)+(x))
> +
> +#define  PCIE_CONF_BUS(b)   (((b) & 0xff) << 24)
> +#define  PCIE_CONF_DEV(d)   (((d) & 0x1f) << 19)
> +#define  PCIE_CONF_FUNC(f)   (((f) & 0x7) << 16)
> +
> +#define PCI_MAX_RESOURCES 4
> +
> +static const struct of_device_id rcar_pcie_of_match[] = {
> +   { .compatible = "renesas,r8a7779-pcie", .data = (void *)RCAR_H1 },
> +   { .compatible = "renesas,r8a7790-pcie", .data = (void *)RCAR_GENERIC 
},
> +   { .compatible = "renesas,r8a7791-pcie", .data = (void *)RCAR_GENERIC 
},
> +   {},
> +};
> +MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
> +
> +/* Structure representing the PCIe interface */
> +struct rcar_pcie {
> +   struct device      *dev;
> +   void __iomem      *base;
> +   struct resource      res[PCI_MAX_RESOURCES];
> +   int         haslink;
> +   enum chip_id      chip;
> +   u8         root_bus_nr;
> +   struct clk      *clk;
> +};
> +
> +static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
> +{
> +   return sys->private_data;
> +}
> +
> +static void
> +pci_write_reg(struct rcar_pcie *pcie, unsigned long val, unsigned long 
reg)
> +{
> +   writel(val, pcie->base + reg);
> +}
> +
> +static unsigned long
> +pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
> +{
> +   return readl(pcie->base + reg);
> +}
> +
> +enum {
> +   PCI_ACCESS_READ,
> +   PCI_ACCESS_WRITE,
> +};
> +
> +static void rcar_rmw32(struct rcar_pcie *pcie,
> +             int where, u32 mask, u32 data)
> +{
> +   int shift = 8 * (where & 3);
> +   u32 val = pci_read_reg(pcie, where & ~3);
> +   val &= ~(mask << shift);
> +   val |= data << shift;
> +   pci_write_reg(pcie, val, where & ~3);
> +}
> +
> +static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
> +{
> +   int shift = 8 * (where & 3);
> +   u32 val = pci_read_reg(pcie, where & ~3);
> +   return val >> shift;
> +}
> +
> +static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> +      unsigned char access_type, struct pci_bus *bus,
> +      unsigned int devfn, int where, u32 *data)
> +{
> +   int dev, func, reg, index;
> +
> +   dev = PCI_SLOT(devfn);
> +   func = PCI_FUNC(devfn);
> +   reg = where & ~3;
> +   index = reg / 4;
> +
> +   if (bus->number > 255 || dev > 31 || func > 7)
> +      return PCIBIOS_FUNC_NOT_SUPPORTED;
> +
> +   /*
> +    * While each channel has its own memory-mapped extended config
> +    * space, it's generally only accessible when in endpoint mode.
> +    * When in root complex mode, the controller is unable to target
> +    * itself with either type 0 or type 1 accesses, and indeed, any
> +    * controller initiated target transfer to its own config space
> +    * result in a completer abort.
> +    *
> +    * Each channel effectively only supports a single device, but as
> +    * the same channel <-> device access works for any PCI_SLOT()
> +    * value, we cheat a bit here and bind the controller's config
> +    * space to devfn 0 in order to enable self-enumeration. In this
> +    * case the regular ECAR/ECDR path is sidelined and the mangled
> +    * config access itself is initiated as an internal bus transaction.
> +    */
> +   if (pci_is_root_bus(bus)) {
> +      if (dev != 0)
> +         return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +      if (access_type = PCI_ACCESS_READ)
> +         *data = pci_read_reg(pcie, PCICONF(index));
> +      else
> +         pci_write_reg(pcie, *data, PCICONF(index));
> +
> +      return PCIBIOS_SUCCESSFUL;
> +   }
> +
> +   /* Clear errors */
> +   pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
> +
> +   /* Set the PIO address */
> +   pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) 
|
> +            PCIE_CONF_FUNC(func) | reg, PCIECAR);
> +
> +   /* Enable the configuration access */
> +   if (bus->parent->number = pcie->root_bus_nr)
> +      pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
> +   else
> +      pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
> +
> +   /* Check for errors */
> +   if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
> +      return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +   /* Check for master and target aborts */
> +   if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) &
> +      (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
> +      return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +   if (access_type = PCI_ACCESS_READ)
> +      *data = pci_read_reg(pcie, PCIECDR);
> +   else
> +      pci_write_reg(pcie, *data, PCIECDR);
> +
> +   /* Disable the configuration access */
> +   pci_write_reg(pcie, 0, PCIECCTLR);
> +
> +   return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
> +            int where, int size, u32 *val)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
> +   int ret;
> +
> +   if ((size = 2) && (where & 1))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +   else if ((size = 4) && (where & 3))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
> +                  bus, devfn, where, val);
> +   if (ret != PCIBIOS_SUCCESSFUL) {
> +      *val = 0xffffffff;
> +      return ret;
> +   }
> +
> +   if (size = 1)
> +      *val = (*val >> (8 * (where & 3))) & 0xff;
> +   else if (size = 2)
> +      *val = (*val >> (8 * (where & 2))) & 0xffff;
> +
> +   dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
> +      "where=0x%04x size=%d val=0x%08lx\n", bus->number,
> +      devfn, where, size, (unsigned long)*val);
> +
> +   return ret;
> +}
> +
> +static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int 
devfn,
> +             int where, int size, u32 val)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
> +   int shift, ret;
> +   u32 data;
> +
> +   if ((size = 2) && (where & 1))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +   else if ((size = 4) && (where & 3))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
> +                  bus, devfn, where, &data);
> +   if (ret != PCIBIOS_SUCCESSFUL)
> +      return ret;
> +
> +   dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
> +      "where=0x%04x size=%d val=0x%08lx\n", bus->number,
> +      devfn, where, size, (unsigned long)val);
> +
> +   if (size = 1) {
> +      shift = 8 * (where & 3);
> +      data &= ~(0xff << shift);
> +      data |= ((val & 0xff) << shift);
> +   } else if (size = 2) {
> +      shift = 8 * (where & 2);
> +      data &= ~(0xffff << shift);
> +      data |= ((val & 0xffff) << shift);
> +   } else
> +      data = val;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
> +                  bus, devfn, where, &data);
> +
> +   return ret;
> +}
> +
> +static struct pci_ops rcar_pcie_ops = {
> +   .read   = rcar_pcie_read_conf,
> +   .write   = rcar_pcie_write_conf,
> +};
> +
> +static int rcar_pcie_setup_window(int win, struct resource *res,
> +               struct rcar_pcie *pcie)
> +{
> +   /* Setup PCIe address space mappings for each resource */
> +   resource_size_t size;
> +   u32 mask;
> +
> +   pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> +
> +   /*
> +    * The PAMR mask is calculated in units of 128Bytes, which
> +    * keeps things pretty simple.
> +    */
> +   size = resource_size(res);
> +   mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> +   pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> +
> +   pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> +   pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> +
> +   /* First resource is for IO */
> +   mask = PAR_ENABLE;
> +   if (res->flags & IORESOURCE_IO)
> +      mask |= IO_SPACE;
> +
> +   pci_write_reg(pcie, mask, PCIEPTCTLR(win));
> +
> +   return 0;
> +}
> +
> +static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(sys);
> +   struct resource *res;
> +   int i, ret;
> +
> +   pcie->root_bus_nr = sys->busnr;
> +
> +   /* Setup PCI resources */
> +   for (i = 0; i < PCI_MAX_RESOURCES; i++) {
> +
> +      res = &pcie->res[i];
> +      if (!res->flags)
> +         continue;
> +
> +      if (res->flags & IORESOURCE_IO) {
> +         /* Setup IO mapped memory accesses */
> +         ret = pci_ioremap_io(0, res->start);
> +         if (ret)
> +            return 1;
> +
> +         /* Correct addresses for remapped IO */
> +         res->end = res->end - res->start;
> +         res->start = 0;
> +      }
> +
> +      rcar_pcie_setup_window(i, res, pcie);
> +      pci_add_resource(&sys->resources, res);
> +   }
> +
> +   return 1;
> +}
> +
> +static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
> +{
> +   struct platform_device *pdev = to_platform_device(pcie->dev);
> +   struct hw_pci hw;
> +
> +   memset(&hw, 0, sizeof(hw));
> +
> +   hw.nr_controllers = 1;
> +   hw.private_data   = (void **)&pcie;
> +   hw.setup          = rcar_pcie_setup,
> +   hw.map_irq        = of_irq_parse_and_map_pci,
> +   hw.ops        = &rcar_pcie_ops,
> +
> +   pci_common_init_dev(&pdev->dev, &hw);
> +}
> +
> +static int __init phy_wait_for_ack(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 100;
> +
> +   while (timeout--) {
> +      if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
> +         return 0;
> +
> +      udelay(100);
> +   }
> +
> +   dev_err(pcie->dev, "Access to PCIe phy timed out\n");
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static void __init phy_write_reg(struct rcar_pcie *pcie,
> +             unsigned int rate, unsigned int addr,
> +             unsigned int lane, unsigned int data)
> +{
> +   unsigned long phyaddr;
> +
> +   phyaddr = WRITE_CMD |
> +      ((rate & 1) << RATE_POS) |
> +      ((lane & 0xf) << LANE_POS) |
> +      ((addr & 0xff) << ADR_POS);
> +
> +   /* Set write data */
> +   pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
> +   pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
> +
> +   /* Ignore errors as they will be dealt with if the data link is down 
*/
> +   phy_wait_for_ack(pcie);
> +
> +   /* Clear command */
> +   pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
> +   pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
> +
> +   /* Ignore errors as they will be dealt with if the data link is down 
*/
> +   phy_wait_for_ack(pcie);
> +}
> +
> +static int __init rcar_pcie_phy_init_rcar_h1(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 10;
> +
> +   /* Initialize the phy */
> +   phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
> +   phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
> +   phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188);
> +   phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188);
> +   phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014);
> +   phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014);
> +   phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0);
> +   phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB);
> +   phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062);
> +   phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000);
> +   phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000);
> +   phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806);
> +
> +   phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5);
> +   phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
> +   phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
> +
> +   while (timeout--) {
> +      if (pci_read_reg(pcie, H1_PCIEPHYSR))
> +         return 0;
> +
> +      msleep(5);
> +   }
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static int __init rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 10;
> +
> +   while (timeout--) {
> +      if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
> +         return 0;
> +
> +      msleep(5);
> +   }
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static void __init rcar_pcie_hw_init(struct rcar_pcie *pcie)
> +{
> +   /* Initialise R-Car H1 PHY & wait for it to be ready */
> +   if (pcie->chip = RCAR_H1)
> +      if (rcar_pcie_phy_init_rcar_h1(pcie))
> +         return;
> +
> +   /* Begin initialization */
> +   pci_write_reg(pcie, 0, PCIETCTLR);
> +
> +   /* Set mode */
> +   pci_write_reg(pcie, 1, PCIEMSR);
> +
> +   /*
> +    * For target transfers, setup a single 64-bit 4GB mapping at 
address
> +    * 0. The hardware can only map memory that starts on a power of two
> +    * boundary, and size is power of 2, so best to ignore it.
> +    */
> +   pci_write_reg(pcie, 0, PCIEPRAR(0));
> +   pci_write_reg(pcie, 0, PCIELAR(0));
> +   pci_write_reg(pcie, 0xfffffff0UL | LAM_PREFETCH |
> +      LAM_64BIT | LAR_ENABLE, PCIELAMR(0));
> +   pci_write_reg(pcie, 0, PCIELAR(1));
> +   pci_write_reg(pcie, 0, PCIEPRAR(1));
> +   pci_write_reg(pcie, 0, PCIELAMR(1));
> +
> +   /*
> +    * Initial header for port config space is type 1, set the device
> +    * class to match. Hardware takes care of propagating the IDSETR
> +    * settings, so there is no need to bother with a quirk.
> +    */
> +   pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
> +
> +   /*
> +    * Setup Secondary Bus Number & Subordinate Bus Number, even though
> +    * they aren't used, to avoid bridge being detected as broken.
> +    */
> +   rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> +   rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
> +
> +   /* Initialize default capabilities. */
> +   rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
> +      PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> +   rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
> +      PCI_HEADER_TYPE_BRIDGE);
> +
> +   /* Enable data link layer active state reporting */
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, 
PCI_EXP_LNKCAP_DLLLARC);
> +
> +   /* Write out the physical slot number = 0 */
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
> +
> +   /* Set the completion timer timeout to the maximum 50ms. */
> +   rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
> +
> +   /* Terminate list of capabilities (Next Capability Offset=0) */
> +   rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
> +
> +   /* Enable MAC data scrambling. */
> +   rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
> +
> +   /* Finish initialization - establish a PCI Express link */
> +   pci_write_reg(pcie, CFINIT, PCIETCTLR);
> +
> +   /* This will timeout if we don't have a link. */
> +   pcie->haslink = !rcar_pcie_wait_for_dl(pcie);
> +
> +   /* Enable INTx interrupts */
> +   rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
> +
> +   /* Enable slave Bus Mastering */
> +   rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
> +      PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
> +      PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
> +
> +   wmb();
> +}
> +
> +#ifdef CONFIG_PM_RUNTIME
> +static int rcar_pcie_runtime_suspend(struct device *dev)
> +{
> +   struct rcar_pcie *pcie = dev_get_drvdata(dev);
> +
> +   clk_disable_unprepare(pcie->clk);
> +   return 0;
> +}
> +
> +static int rcar_pcie_runtime_resume(struct device *dev)
> +{
> +   struct rcar_pcie *pcie = dev_get_drvdata(dev);
> +
> +   clk_prepare_enable(pcie->clk);
> +   return 0;
> +}
> +#endif
> +
> +static int __init rcar_pcie_get_resources(struct platform_device *pdev,
> +   struct rcar_pcie *pcie)
> +{
> +   struct device *dev = &pdev->dev;
> +   struct resource res;
> +   int err;
> +
> +   err = of_address_to_resource(pdev->dev.of_node, 0, &res);
> +   if (err)
> +      return err;
> +
> +   pcie->clk = devm_clk_get(&pdev->dev, "pcie");
> +   if (IS_ERR(pcie->clk)) {
> +      dev_err(pcie->dev, "cannot get platfom clock\n");
> +      return PTR_ERR(pcie->clk);
> +   }
> +
> +   pm_runtime_enable(dev);
> +   pm_runtime_get_sync(dev);
> +
> +   pcie->base = devm_ioremap_resource(&pdev->dev, &res);
> +   if (IS_ERR(pcie->base)) {
> +      err = PTR_ERR(pcie->base);
> +      goto err_map_reg;
> +   }
> +
> +   return 0;
> +
> +err_map_reg:
> +   pm_runtime_put_sync(dev);
> +   pm_runtime_disable(dev);
> +
> +   return err;
> +}
> +
> +static int __init rcar_pcie_probe(struct platform_device *pdev)
> +{
> +   struct rcar_pcie *pcie;
> +   unsigned int data;
> +   struct of_pci_range range;
> +   struct of_pci_range_parser parser;
> +   const struct of_device_id *of_id;
> +   int err, win = 0;
> +
> +   pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> +   if (!pcie)
> +      return -ENOMEM;
> +
> +   pcie->dev = &pdev->dev;
> +   platform_set_drvdata(pdev, pcie);
> +
> +   of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
> +   if (of_id)
> +      pcie->chip = (enum chip_id)of_id->data;
> +
> +   if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
> +      dev_err(&pdev->dev, "missing ranges property\n");
> +      return -EINVAL;
> +   }
> +
> +   err = rcar_pcie_get_resources(pdev, pcie);
> +   if (err < 0) {
> +      dev_err(&pdev->dev, "failed to request resources: %d\n", err);
> +      return err;
> +   }
> +
> +   for_each_of_pci_range(&parser, &range) {
> +      of_pci_range_to_resource(&range, pdev->dev.of_node,
> +                  &pcie->res[win++]);
> +
> +      if (win > PCI_MAX_RESOURCES)
> +         break;
> +   }
> +
> +   rcar_pcie_hw_init(pcie);
> +
> +   if (!pcie->haslink) {
> +      dev_info(&pdev->dev, "PCI: PCIe link down\n");
> +      return 0;
> +   }
> +
> +   data = pci_read_reg(pcie, MACSR);
> +   dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
> +
> +   rcar_pcie_enable(pcie);
> +
> +   return 0;
> +}
> +
> +static const struct dev_pm_ops rcar_pcie_pm_ops = {
> +   SET_RUNTIME_PM_OPS(rcar_pcie_runtime_suspend,
> +            rcar_pcie_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rcar_pcie_driver = {
> +   .driver = {
> +      .name = DRV_NAME,
> +      .owner = THIS_MODULE,
> +      .of_match_table = rcar_pcie_of_match,
> +      .pm = &rcar_pcie_pm_ops,
> +      .suppress_bind_attrs = true,
> +   },
> +};
> +
> +static int __init pcie_init(void)
> +{
> +   return platform_driver_probe(&rcar_pcie_driver, rcar_pcie_probe);
> +}
> +subsys_initcall(pcie_init);
> +
> +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
> +MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
> +MODULE_LICENSE("GPLv2");
> diff --git a/drivers/pci/host/pcie-rcar.h b/drivers/pci/host/pcie-rcar.h
> new file mode 100644
> index 0000000..3dc026b
> --- /dev/null
> +++ b/drivers/pci/host/pcie-rcar.h
> @@ -0,0 +1,82 @@
> +/*
> + * PCI Express definitions for Renesas R-Car SoCs
> + */
> +#ifndef __PCI_RCAR_H
> +#define __PCI_RCAR_H
> +
> +#define PCIECAR         0x000010
> +#define PCIECCTLR      0x000018
> +#define  CONFIG_SEND_ENABLE   (1 << 31)
> +#define  TYPE0         (0 << 8)
> +#define  TYPE1         (1 << 8)
> +#define PCIECDR         0x000020
> +#define PCIEMSR         0x000028
> +#define PCIEINTXR      0x000400
> +#define PCIEPHYSR      0x0007f0
> +
> +/* Transfer control */
> +#define PCIETCTLR      0x02000
> +#define  CFINIT         1
> +#define PCIETSTR      0x02004
> +#define  DATA_LINK_ACTIVE   1
> +#define PCIEINTR      0x02008
> +#define PCIEINTER      0x0200c
> +#define PCIEERRFR      0x02020
> +#define  UNSUPPORTED_REQUEST   (1 << 4)
> +#define PCIEERRFER      0x02024
> +#define PCIEERRFR2      0x02028
> +#define PCIEPMSR      0x02034
> +#define PCIEPMSCIER      0x02038
> +#define PCIEMSIFR      0x02044
> +
> +/* root port address */
> +#define PCIEPRAR(x)      (0x02080 + ((x) * 0x4))
> +
> +/* local address reg & mask */
> +#define PCIELAR(x)      (0x02200 + ((x) * 0x20))
> +#define PCIELAMR(x)      (0x02208 + ((x) * 0x20))
> +#define  LAM_PMIOLAMnB3      (1 << 3)
> +#define  LAM_PMIOLAMnB2      (1 << 2)
> +#define  LAM_PREFETCH      (1 << 3)
> +#define  LAM_64BIT      (1 << 2)
> +#define  LAR_ENABLE      (1 << 1)
> +
> +/* PCIe address reg & mask */
> +#define PCIEPARL(x)      (0x03400 + ((x) * 0x20))
> +#define PCIEPARH(x)      (0x03404 + ((x) * 0x20))
> +#define PCIEPAMR(x)      (0x03408 + ((x) * 0x20))
> +#define PCIEPTCTLR(x)      (0x0340c + ((x) * 0x20))
> +#define  PAR_ENABLE      (1 << 31)
> +#define  IO_SPACE      (1 << 8)
> +
> +/* Configuration */
> +#define PCICONF(x)      (0x010000 + ((x) * 0x4))
> +#define PMCAP(x)      (0x010040 + ((x) * 0x4))
> +#define MSICAP(x)      (0x010050 + ((x) * 0x4))
> +#define EXPCAP(x)      (0x010070 + ((x) * 0x4))
> +#define VCCAP(x)      (0x010100 + ((x) * 0x4))
> +#define SERNUMCAP(x)      (0x0101b0 + ((x) * 0x4))
> +
> +/* link layer */
> +#define IDSETR0         0x011000
> +#define IDSETR1         0x011004
> +#define SUBIDSETR      0x011024
> +#define DSERSETR0      0x01102c
> +#define DSERSETR1      0x011030
> +#define TLCTLR         0x011048
> +#define MACSR         0x011054
> +#define MACCTLR         0x011058
> +#define  SCRAMBLE_DISABLE   (1 << 27)
> +
> +/* R-Car H1 PHY */
> +#define H1_PCIEPHYCTLR      0x040008
> +#define H1_PCIEPHYADRR      0x04000c
> +#define  WRITE_CMD      (1 << 16)
> +#define  PHY_ACK      (1 << 24)
> +#define  RATE_POS      12
> +#define  LANE_POS      8
> +#define  ADR_POS      0
> +#define H1_PCIEPHYDOUTR      0x040014
> +#define H1_PCIEPHYSR      0x040018
> +
> +#endif /* __PCI_RCAR_H */
> -- 
> 1.7.9.5
> 

Thanks
Phil

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
@ 2014-03-20 16:41     ` Phil.Edworthy
  0 siblings, 0 replies; 23+ messages in thread
From: Phil.Edworthy @ 2014-03-20 16:41 UTC (permalink / raw)
  To: linux-pci
  Cc: Ben Dooks, Bjorn Helgaas, Simon Horman, linux-sh, Magnus Damm,
	Valentine Barshak

Hi,

Whilst looking at something else, I've realised that I completely messed 
up my use of runtime PM in this driver... I'll fix that up & resend.

On 13/03/2014 09:50, Phil Edworthy wrote:
> Subject: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
> 
> This PCIe Host driver currently does not support MSI, so cards
> fall back to INTx interrupts.
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
> v3:
>  - Add DT support
>  - Use 'of_irq_parse_and_map_pci' for '.map_irq'
>  - Use pm ops to enable clocks
>  - Fix checkpatch errors
>  - Use subsys_initcall to overcome issues with port bus driver
>  - Adjust Kconfig to match other R-Car drivers
> 
> v2:
>  - Use msleep instead of udelay when waiting for the link
>  - Use pm_runtime
>  - Removed unused definition
>  - Also replaced call to devm_request_and_ioremap with 
devm_ioremap_resource
>    and fixed a bug with this when reporting errors.
> ---
>  drivers/pci/host/Kconfig     |    6 +
>  drivers/pci/host/Makefile    |    1 +
>  drivers/pci/host/pcie-rcar.c |  629 
++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/host/pcie-rcar.h |   82 ++++++
>  4 files changed, 718 insertions(+)
>  create mode 100644 drivers/pci/host/pcie-rcar.c
>  create mode 100644 drivers/pci/host/pcie-rcar.h
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index 47d46c6..dc627e5 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -33,4 +33,10 @@ config PCI_RCAR_GEN2
>       There are 3 internal PCI controllers available with a single
>       built-in EHCI/OHCI host controller present on each one.
> 
> +config PCI_RCAR_GEN2_PCIE
> +   bool "Renesas R-Car PCIe controller"
> +   depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
> +   help
> +     Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
> +
>  endmenu
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 13fb333..19946f9 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
>  obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
>  obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
>  obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> +obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> new file mode 100644
> index 0000000..7f094fa
> --- /dev/null
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -0,0 +1,629 @@
> +/*
> + * PCIe driver for Renesas R-Car SoCs
> + *  Copyright (C) 2013 Renesas Electronics Europe Ltd
> + *
> + * Based on:
> + *  arch/sh/drivers/pci/pcie-sh7786.c
> + *  arch/sh/drivers/pci/ops-sh7786.c
> + *  Copyright (C) 2009 - 2011  Paul Mundt
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +#include "pcie-rcar.h"
> +
> +#define DRV_NAME "rcar-pcie"
> +
> +enum chip_id {
> +   RCAR_GENERIC,
> +   RCAR_H1,
> +};
> +
> +#define RCONF(x)   (PCICONF(0)+(x))
> +#define RPMCAP(x)   (PMCAP(0)+(x))
> +#define REXPCAP(x)   (EXPCAP(0)+(x))
> +#define RVCCAP(x)   (VCCAP(0)+(x))
> +
> +#define  PCIE_CONF_BUS(b)   (((b) & 0xff) << 24)
> +#define  PCIE_CONF_DEV(d)   (((d) & 0x1f) << 19)
> +#define  PCIE_CONF_FUNC(f)   (((f) & 0x7) << 16)
> +
> +#define PCI_MAX_RESOURCES 4
> +
> +static const struct of_device_id rcar_pcie_of_match[] = {
> +   { .compatible = "renesas,r8a7779-pcie", .data = (void *)RCAR_H1 },
> +   { .compatible = "renesas,r8a7790-pcie", .data = (void *)RCAR_GENERIC 
},
> +   { .compatible = "renesas,r8a7791-pcie", .data = (void *)RCAR_GENERIC 
},
> +   {},
> +};
> +MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
> +
> +/* Structure representing the PCIe interface */
> +struct rcar_pcie {
> +   struct device      *dev;
> +   void __iomem      *base;
> +   struct resource      res[PCI_MAX_RESOURCES];
> +   int         haslink;
> +   enum chip_id      chip;
> +   u8         root_bus_nr;
> +   struct clk      *clk;
> +};
> +
> +static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
> +{
> +   return sys->private_data;
> +}
> +
> +static void
> +pci_write_reg(struct rcar_pcie *pcie, unsigned long val, unsigned long 
reg)
> +{
> +   writel(val, pcie->base + reg);
> +}
> +
> +static unsigned long
> +pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
> +{
> +   return readl(pcie->base + reg);
> +}
> +
> +enum {
> +   PCI_ACCESS_READ,
> +   PCI_ACCESS_WRITE,
> +};
> +
> +static void rcar_rmw32(struct rcar_pcie *pcie,
> +             int where, u32 mask, u32 data)
> +{
> +   int shift = 8 * (where & 3);
> +   u32 val = pci_read_reg(pcie, where & ~3);
> +   val &= ~(mask << shift);
> +   val |= data << shift;
> +   pci_write_reg(pcie, val, where & ~3);
> +}
> +
> +static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
> +{
> +   int shift = 8 * (where & 3);
> +   u32 val = pci_read_reg(pcie, where & ~3);
> +   return val >> shift;
> +}
> +
> +static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> +      unsigned char access_type, struct pci_bus *bus,
> +      unsigned int devfn, int where, u32 *data)
> +{
> +   int dev, func, reg, index;
> +
> +   dev = PCI_SLOT(devfn);
> +   func = PCI_FUNC(devfn);
> +   reg = where & ~3;
> +   index = reg / 4;
> +
> +   if (bus->number > 255 || dev > 31 || func > 7)
> +      return PCIBIOS_FUNC_NOT_SUPPORTED;
> +
> +   /*
> +    * While each channel has its own memory-mapped extended config
> +    * space, it's generally only accessible when in endpoint mode.
> +    * When in root complex mode, the controller is unable to target
> +    * itself with either type 0 or type 1 accesses, and indeed, any
> +    * controller initiated target transfer to its own config space
> +    * result in a completer abort.
> +    *
> +    * Each channel effectively only supports a single device, but as
> +    * the same channel <-> device access works for any PCI_SLOT()
> +    * value, we cheat a bit here and bind the controller's config
> +    * space to devfn 0 in order to enable self-enumeration. In this
> +    * case the regular ECAR/ECDR path is sidelined and the mangled
> +    * config access itself is initiated as an internal bus transaction.
> +    */
> +   if (pci_is_root_bus(bus)) {
> +      if (dev != 0)
> +         return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +      if (access_type == PCI_ACCESS_READ)
> +         *data = pci_read_reg(pcie, PCICONF(index));
> +      else
> +         pci_write_reg(pcie, *data, PCICONF(index));
> +
> +      return PCIBIOS_SUCCESSFUL;
> +   }
> +
> +   /* Clear errors */
> +   pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
> +
> +   /* Set the PIO address */
> +   pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) 
|
> +            PCIE_CONF_FUNC(func) | reg, PCIECAR);
> +
> +   /* Enable the configuration access */
> +   if (bus->parent->number == pcie->root_bus_nr)
> +      pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
> +   else
> +      pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
> +
> +   /* Check for errors */
> +   if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
> +      return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +   /* Check for master and target aborts */
> +   if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) &
> +      (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
> +      return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +   if (access_type == PCI_ACCESS_READ)
> +      *data = pci_read_reg(pcie, PCIECDR);
> +   else
> +      pci_write_reg(pcie, *data, PCIECDR);
> +
> +   /* Disable the configuration access */
> +   pci_write_reg(pcie, 0, PCIECCTLR);
> +
> +   return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
> +            int where, int size, u32 *val)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
> +   int ret;
> +
> +   if ((size == 2) && (where & 1))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +   else if ((size == 4) && (where & 3))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
> +                  bus, devfn, where, val);
> +   if (ret != PCIBIOS_SUCCESSFUL) {
> +      *val = 0xffffffff;
> +      return ret;
> +   }
> +
> +   if (size == 1)
> +      *val = (*val >> (8 * (where & 3))) & 0xff;
> +   else if (size == 2)
> +      *val = (*val >> (8 * (where & 2))) & 0xffff;
> +
> +   dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x "
> +      "where=0x%04x size=%d val=0x%08lx\n", bus->number,
> +      devfn, where, size, (unsigned long)*val);
> +
> +   return ret;
> +}
> +
> +static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int 
devfn,
> +             int where, int size, u32 val)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
> +   int shift, ret;
> +   u32 data;
> +
> +   if ((size == 2) && (where & 1))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +   else if ((size == 4) && (where & 3))
> +      return PCIBIOS_BAD_REGISTER_NUMBER;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
> +                  bus, devfn, where, &data);
> +   if (ret != PCIBIOS_SUCCESSFUL)
> +      return ret;
> +
> +   dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x "
> +      "where=0x%04x size=%d val=0x%08lx\n", bus->number,
> +      devfn, where, size, (unsigned long)val);
> +
> +   if (size == 1) {
> +      shift = 8 * (where & 3);
> +      data &= ~(0xff << shift);
> +      data |= ((val & 0xff) << shift);
> +   } else if (size == 2) {
> +      shift = 8 * (where & 2);
> +      data &= ~(0xffff << shift);
> +      data |= ((val & 0xffff) << shift);
> +   } else
> +      data = val;
> +
> +   ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
> +                  bus, devfn, where, &data);
> +
> +   return ret;
> +}
> +
> +static struct pci_ops rcar_pcie_ops = {
> +   .read   = rcar_pcie_read_conf,
> +   .write   = rcar_pcie_write_conf,
> +};
> +
> +static int rcar_pcie_setup_window(int win, struct resource *res,
> +               struct rcar_pcie *pcie)
> +{
> +   /* Setup PCIe address space mappings for each resource */
> +   resource_size_t size;
> +   u32 mask;
> +
> +   pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> +
> +   /*
> +    * The PAMR mask is calculated in units of 128Bytes, which
> +    * keeps things pretty simple.
> +    */
> +   size = resource_size(res);
> +   mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> +   pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> +
> +   pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
> +   pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
> +
> +   /* First resource is for IO */
> +   mask = PAR_ENABLE;
> +   if (res->flags & IORESOURCE_IO)
> +      mask |= IO_SPACE;
> +
> +   pci_write_reg(pcie, mask, PCIEPTCTLR(win));
> +
> +   return 0;
> +}
> +
> +static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> +   struct rcar_pcie *pcie = sys_to_pcie(sys);
> +   struct resource *res;
> +   int i, ret;
> +
> +   pcie->root_bus_nr = sys->busnr;
> +
> +   /* Setup PCI resources */
> +   for (i = 0; i < PCI_MAX_RESOURCES; i++) {
> +
> +      res = &pcie->res[i];
> +      if (!res->flags)
> +         continue;
> +
> +      if (res->flags & IORESOURCE_IO) {
> +         /* Setup IO mapped memory accesses */
> +         ret = pci_ioremap_io(0, res->start);
> +         if (ret)
> +            return 1;
> +
> +         /* Correct addresses for remapped IO */
> +         res->end = res->end - res->start;
> +         res->start = 0;
> +      }
> +
> +      rcar_pcie_setup_window(i, res, pcie);
> +      pci_add_resource(&sys->resources, res);
> +   }
> +
> +   return 1;
> +}
> +
> +static void __init rcar_pcie_enable(struct rcar_pcie *pcie)
> +{
> +   struct platform_device *pdev = to_platform_device(pcie->dev);
> +   struct hw_pci hw;
> +
> +   memset(&hw, 0, sizeof(hw));
> +
> +   hw.nr_controllers = 1;
> +   hw.private_data   = (void **)&pcie;
> +   hw.setup          = rcar_pcie_setup,
> +   hw.map_irq        = of_irq_parse_and_map_pci,
> +   hw.ops        = &rcar_pcie_ops,
> +
> +   pci_common_init_dev(&pdev->dev, &hw);
> +}
> +
> +static int __init phy_wait_for_ack(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 100;
> +
> +   while (timeout--) {
> +      if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
> +         return 0;
> +
> +      udelay(100);
> +   }
> +
> +   dev_err(pcie->dev, "Access to PCIe phy timed out\n");
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static void __init phy_write_reg(struct rcar_pcie *pcie,
> +             unsigned int rate, unsigned int addr,
> +             unsigned int lane, unsigned int data)
> +{
> +   unsigned long phyaddr;
> +
> +   phyaddr = WRITE_CMD |
> +      ((rate & 1) << RATE_POS) |
> +      ((lane & 0xf) << LANE_POS) |
> +      ((addr & 0xff) << ADR_POS);
> +
> +   /* Set write data */
> +   pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
> +   pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
> +
> +   /* Ignore errors as they will be dealt with if the data link is down 
*/
> +   phy_wait_for_ack(pcie);
> +
> +   /* Clear command */
> +   pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
> +   pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
> +
> +   /* Ignore errors as they will be dealt with if the data link is down 
*/
> +   phy_wait_for_ack(pcie);
> +}
> +
> +static int __init rcar_pcie_phy_init_rcar_h1(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 10;
> +
> +   /* Initialize the phy */
> +   phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
> +   phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
> +   phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188);
> +   phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188);
> +   phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014);
> +   phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014);
> +   phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0);
> +   phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB);
> +   phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062);
> +   phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000);
> +   phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000);
> +   phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806);
> +
> +   phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5);
> +   phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
> +   phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
> +
> +   while (timeout--) {
> +      if (pci_read_reg(pcie, H1_PCIEPHYSR))
> +         return 0;
> +
> +      msleep(5);
> +   }
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static int __init rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> +{
> +   unsigned int timeout = 10;
> +
> +   while (timeout--) {
> +      if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
> +         return 0;
> +
> +      msleep(5);
> +   }
> +
> +   return -ETIMEDOUT;
> +}
> +
> +static void __init rcar_pcie_hw_init(struct rcar_pcie *pcie)
> +{
> +   /* Initialise R-Car H1 PHY & wait for it to be ready */
> +   if (pcie->chip == RCAR_H1)
> +      if (rcar_pcie_phy_init_rcar_h1(pcie))
> +         return;
> +
> +   /* Begin initialization */
> +   pci_write_reg(pcie, 0, PCIETCTLR);
> +
> +   /* Set mode */
> +   pci_write_reg(pcie, 1, PCIEMSR);
> +
> +   /*
> +    * For target transfers, setup a single 64-bit 4GB mapping at 
address
> +    * 0. The hardware can only map memory that starts on a power of two
> +    * boundary, and size is power of 2, so best to ignore it.
> +    */
> +   pci_write_reg(pcie, 0, PCIEPRAR(0));
> +   pci_write_reg(pcie, 0, PCIELAR(0));
> +   pci_write_reg(pcie, 0xfffffff0UL | LAM_PREFETCH |
> +      LAM_64BIT | LAR_ENABLE, PCIELAMR(0));
> +   pci_write_reg(pcie, 0, PCIELAR(1));
> +   pci_write_reg(pcie, 0, PCIEPRAR(1));
> +   pci_write_reg(pcie, 0, PCIELAMR(1));
> +
> +   /*
> +    * Initial header for port config space is type 1, set the device
> +    * class to match. Hardware takes care of propagating the IDSETR
> +    * settings, so there is no need to bother with a quirk.
> +    */
> +   pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
> +
> +   /*
> +    * Setup Secondary Bus Number & Subordinate Bus Number, even though
> +    * they aren't used, to avoid bridge being detected as broken.
> +    */
> +   rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> +   rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
> +
> +   /* Initialize default capabilities. */
> +   rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
> +      PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> +   rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
> +      PCI_HEADER_TYPE_BRIDGE);
> +
> +   /* Enable data link layer active state reporting */
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, 
PCI_EXP_LNKCAP_DLLLARC);
> +
> +   /* Write out the physical slot number = 0 */
> +   rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
> +
> +   /* Set the completion timer timeout to the maximum 50ms. */
> +   rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
> +
> +   /* Terminate list of capabilities (Next Capability Offset=0) */
> +   rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
> +
> +   /* Enable MAC data scrambling. */
> +   rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
> +
> +   /* Finish initialization - establish a PCI Express link */
> +   pci_write_reg(pcie, CFINIT, PCIETCTLR);
> +
> +   /* This will timeout if we don't have a link. */
> +   pcie->haslink = !rcar_pcie_wait_for_dl(pcie);
> +
> +   /* Enable INTx interrupts */
> +   rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
> +
> +   /* Enable slave Bus Mastering */
> +   rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
> +      PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
> +      PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
> +
> +   wmb();
> +}
> +
> +#ifdef CONFIG_PM_RUNTIME
> +static int rcar_pcie_runtime_suspend(struct device *dev)
> +{
> +   struct rcar_pcie *pcie = dev_get_drvdata(dev);
> +
> +   clk_disable_unprepare(pcie->clk);
> +   return 0;
> +}
> +
> +static int rcar_pcie_runtime_resume(struct device *dev)
> +{
> +   struct rcar_pcie *pcie = dev_get_drvdata(dev);
> +
> +   clk_prepare_enable(pcie->clk);
> +   return 0;
> +}
> +#endif
> +
> +static int __init rcar_pcie_get_resources(struct platform_device *pdev,
> +   struct rcar_pcie *pcie)
> +{
> +   struct device *dev = &pdev->dev;
> +   struct resource res;
> +   int err;
> +
> +   err = of_address_to_resource(pdev->dev.of_node, 0, &res);
> +   if (err)
> +      return err;
> +
> +   pcie->clk = devm_clk_get(&pdev->dev, "pcie");
> +   if (IS_ERR(pcie->clk)) {
> +      dev_err(pcie->dev, "cannot get platfom clock\n");
> +      return PTR_ERR(pcie->clk);
> +   }
> +
> +   pm_runtime_enable(dev);
> +   pm_runtime_get_sync(dev);
> +
> +   pcie->base = devm_ioremap_resource(&pdev->dev, &res);
> +   if (IS_ERR(pcie->base)) {
> +      err = PTR_ERR(pcie->base);
> +      goto err_map_reg;
> +   }
> +
> +   return 0;
> +
> +err_map_reg:
> +   pm_runtime_put_sync(dev);
> +   pm_runtime_disable(dev);
> +
> +   return err;
> +}
> +
> +static int __init rcar_pcie_probe(struct platform_device *pdev)
> +{
> +   struct rcar_pcie *pcie;
> +   unsigned int data;
> +   struct of_pci_range range;
> +   struct of_pci_range_parser parser;
> +   const struct of_device_id *of_id;
> +   int err, win = 0;
> +
> +   pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> +   if (!pcie)
> +      return -ENOMEM;
> +
> +   pcie->dev = &pdev->dev;
> +   platform_set_drvdata(pdev, pcie);
> +
> +   of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
> +   if (of_id)
> +      pcie->chip = (enum chip_id)of_id->data;
> +
> +   if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
> +      dev_err(&pdev->dev, "missing ranges property\n");
> +      return -EINVAL;
> +   }
> +
> +   err = rcar_pcie_get_resources(pdev, pcie);
> +   if (err < 0) {
> +      dev_err(&pdev->dev, "failed to request resources: %d\n", err);
> +      return err;
> +   }
> +
> +   for_each_of_pci_range(&parser, &range) {
> +      of_pci_range_to_resource(&range, pdev->dev.of_node,
> +                  &pcie->res[win++]);
> +
> +      if (win > PCI_MAX_RESOURCES)
> +         break;
> +   }
> +
> +   rcar_pcie_hw_init(pcie);
> +
> +   if (!pcie->haslink) {
> +      dev_info(&pdev->dev, "PCI: PCIe link down\n");
> +      return 0;
> +   }
> +
> +   data = pci_read_reg(pcie, MACSR);
> +   dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
> +
> +   rcar_pcie_enable(pcie);
> +
> +   return 0;
> +}
> +
> +static const struct dev_pm_ops rcar_pcie_pm_ops = {
> +   SET_RUNTIME_PM_OPS(rcar_pcie_runtime_suspend,
> +            rcar_pcie_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rcar_pcie_driver = {
> +   .driver = {
> +      .name = DRV_NAME,
> +      .owner = THIS_MODULE,
> +      .of_match_table = rcar_pcie_of_match,
> +      .pm = &rcar_pcie_pm_ops,
> +      .suppress_bind_attrs = true,
> +   },
> +};
> +
> +static int __init pcie_init(void)
> +{
> +   return platform_driver_probe(&rcar_pcie_driver, rcar_pcie_probe);
> +}
> +subsys_initcall(pcie_init);
> +
> +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
> +MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
> +MODULE_LICENSE("GPLv2");
> diff --git a/drivers/pci/host/pcie-rcar.h b/drivers/pci/host/pcie-rcar.h
> new file mode 100644
> index 0000000..3dc026b
> --- /dev/null
> +++ b/drivers/pci/host/pcie-rcar.h
> @@ -0,0 +1,82 @@
> +/*
> + * PCI Express definitions for Renesas R-Car SoCs
> + */
> +#ifndef __PCI_RCAR_H
> +#define __PCI_RCAR_H
> +
> +#define PCIECAR         0x000010
> +#define PCIECCTLR      0x000018
> +#define  CONFIG_SEND_ENABLE   (1 << 31)
> +#define  TYPE0         (0 << 8)
> +#define  TYPE1         (1 << 8)
> +#define PCIECDR         0x000020
> +#define PCIEMSR         0x000028
> +#define PCIEINTXR      0x000400
> +#define PCIEPHYSR      0x0007f0
> +
> +/* Transfer control */
> +#define PCIETCTLR      0x02000
> +#define  CFINIT         1
> +#define PCIETSTR      0x02004
> +#define  DATA_LINK_ACTIVE   1
> +#define PCIEINTR      0x02008
> +#define PCIEINTER      0x0200c
> +#define PCIEERRFR      0x02020
> +#define  UNSUPPORTED_REQUEST   (1 << 4)
> +#define PCIEERRFER      0x02024
> +#define PCIEERRFR2      0x02028
> +#define PCIEPMSR      0x02034
> +#define PCIEPMSCIER      0x02038
> +#define PCIEMSIFR      0x02044
> +
> +/* root port address */
> +#define PCIEPRAR(x)      (0x02080 + ((x) * 0x4))
> +
> +/* local address reg & mask */
> +#define PCIELAR(x)      (0x02200 + ((x) * 0x20))
> +#define PCIELAMR(x)      (0x02208 + ((x) * 0x20))
> +#define  LAM_PMIOLAMnB3      (1 << 3)
> +#define  LAM_PMIOLAMnB2      (1 << 2)
> +#define  LAM_PREFETCH      (1 << 3)
> +#define  LAM_64BIT      (1 << 2)
> +#define  LAR_ENABLE      (1 << 1)
> +
> +/* PCIe address reg & mask */
> +#define PCIEPARL(x)      (0x03400 + ((x) * 0x20))
> +#define PCIEPARH(x)      (0x03404 + ((x) * 0x20))
> +#define PCIEPAMR(x)      (0x03408 + ((x) * 0x20))
> +#define PCIEPTCTLR(x)      (0x0340c + ((x) * 0x20))
> +#define  PAR_ENABLE      (1 << 31)
> +#define  IO_SPACE      (1 << 8)
> +
> +/* Configuration */
> +#define PCICONF(x)      (0x010000 + ((x) * 0x4))
> +#define PMCAP(x)      (0x010040 + ((x) * 0x4))
> +#define MSICAP(x)      (0x010050 + ((x) * 0x4))
> +#define EXPCAP(x)      (0x010070 + ((x) * 0x4))
> +#define VCCAP(x)      (0x010100 + ((x) * 0x4))
> +#define SERNUMCAP(x)      (0x0101b0 + ((x) * 0x4))
> +
> +/* link layer */
> +#define IDSETR0         0x011000
> +#define IDSETR1         0x011004
> +#define SUBIDSETR      0x011024
> +#define DSERSETR0      0x01102c
> +#define DSERSETR1      0x011030
> +#define TLCTLR         0x011048
> +#define MACSR         0x011054
> +#define MACCTLR         0x011058
> +#define  SCRAMBLE_DISABLE   (1 << 27)
> +
> +/* R-Car H1 PHY */
> +#define H1_PCIEPHYCTLR      0x040008
> +#define H1_PCIEPHYADRR      0x04000c
> +#define  WRITE_CMD      (1 << 16)
> +#define  PHY_ACK      (1 << 24)
> +#define  RATE_POS      12
> +#define  LANE_POS      8
> +#define  ADR_POS      0
> +#define H1_PCIEPHYDOUTR      0x040014
> +#define H1_PCIEPHYSR      0x040018
> +
> +#endif /* __PCI_RCAR_H */
> -- 
> 1.7.9.5
> 

Thanks
Phil

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
  2014-03-20 16:41     ` Phil.Edworthy
@ 2014-03-20 16:49       ` Ben Dooks
  -1 siblings, 0 replies; 23+ messages in thread
From: Ben Dooks @ 2014-03-20 16:49 UTC (permalink / raw)
  To: Phil.Edworthy
  Cc: linux-pci, Bjorn Helgaas, Simon Horman, linux-sh, Magnus Damm,
	Valentine Barshak

On 20/03/14 17:41, Phil.Edworthy@renesas.com wrote:
> Hi,
>
> Whilst looking at something else, I've realised that I completely messed
> up my use of runtime PM in this driver... I'll fix that up & resend.

Yes, you don't need the suspend/resume hooks at-all by the looks
of it. Hopefully the pm_runtime driver for shmobile will be sorted
upstream soon.

And it looks as if your hooks would never have been called anyway
as your probe does a pm_runtime_get_sync() to keep the pm_runtime
for the device open (which probably for this bus bridge is what
you wanted)

-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver
@ 2014-03-20 16:49       ` Ben Dooks
  0 siblings, 0 replies; 23+ messages in thread
From: Ben Dooks @ 2014-03-20 16:49 UTC (permalink / raw)
  To: Phil.Edworthy
  Cc: linux-pci, Bjorn Helgaas, Simon Horman, linux-sh, Magnus Damm,
	Valentine Barshak

On 20/03/14 17:41, Phil.Edworthy@renesas.com wrote:
> Hi,
>
> Whilst looking at something else, I've realised that I completely messed
> up my use of runtime PM in this driver... I'll fix that up & resend.

Yes, you don't need the suspend/resume hooks at-all by the looks
of it. Hopefully the pm_runtime driver for shmobile will be sorted
upstream soon.

And it looks as if your hooks would never have been called anyway
as your probe does a pm_runtime_get_sync() to keep the pm_runtime
for the device open (which probably for this bus bridge is what
you wanted)

-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2014-03-20 16:49 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-13  9:49 [PATCH 0/9 v3] R-Car Gen2 PCIe host driver Phil Edworthy
2014-03-13  9:49 ` Phil Edworthy
2014-03-13  9:50 ` [PATCH 1/9 v3] PCI: host: rcar: Add Renesas R-Car PCIe driver Phil Edworthy
2014-03-13  9:50   ` Phil Edworthy
2014-03-20 16:41   ` Phil.Edworthy
2014-03-20 16:41     ` Phil.Edworthy
2014-03-20 16:49     ` Ben Dooks
2014-03-20 16:49       ` Ben Dooks
2014-03-13  9:50 ` [PATCH 2/9] PCI: host: rcar: Add MSI support Phil Edworthy
2014-03-13  9:50 ` [PATCH 3/9] ARM: shmobile: r8a7790: Add PCIe clock device tree nodes Phil Edworthy
2014-03-13  9:50   ` Phil Edworthy
2014-03-13  9:50 ` [PATCH 4/9] ARM: shmobile: r8a7791: " Phil Edworthy
2014-03-13  9:50   ` Phil Edworthy
2014-03-13  9:50 ` [PATCH 5/9] dt-bindings: pci: rcar pcie device tree bindings Phil Edworthy
2014-03-13 10:00   ` Arnd Bergmann
2014-03-13 10:00     ` Arnd Bergmann
2014-03-13 10:28     ` Phil.Edworthy
2014-03-13 11:30       ` Arnd Bergmann
2014-03-13 11:30         ` Arnd Bergmann
2014-03-13  9:50 ` [PATCH 6/9] ARM: shmobile: Add PCIe device tree nodes for R8A7790 Phil Edworthy
2014-03-13  9:50 ` [PATCH 7/9] ARM: shmobile: Add PCIe device tree nodes for R8A7791 Koelsch board Phil Edworthy
2014-03-13  9:50 ` [PATCH 8/9] ARM: koelsch: Add PCIe to defconfig Phil Edworthy
2014-03-13  9:50 ` [PATCH 9/9] ARM: koelsch: Add HAVE_ARM_ARCH_TIMER " Phil Edworthy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.