1 /* 2 * Copyright 2022, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #ifndef _PCICONTROLLERDW_H_ 8 #define _PCICONTROLLERDW_H_ 9 10 #include <bus/PCI.h> 11 #include <arch/generic/msi.h> 12 13 #include <AutoDeleterOS.h> 14 #include <lock.h> 15 #include <util/Vector.h> 16 17 18 #define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;} 19 20 #define DESIGNWARE_PCI_DRIVER_MODULE_NAME "busses/pci/designware/driver_v1" 21 22 23 enum { 24 fdtPciRangeConfig = 0x00000000, 25 fdtPciRangeIoPort = 0x01000000, 26 fdtPciRangeMmio32Bit = 0x02000000, 27 fdtPciRangeMmio64Bit = 0x03000000, 28 fdtPciRangeTypeMask = 0x03000000, 29 fdtPciRangeAliased = 0x20000000, 30 fdtPciRangePrefechable = 0x40000000, 31 fdtPciRangeRelocatable = 0x80000000, 32 }; 33 34 35 enum PciBarKind { 36 kRegIo, 37 kRegMmio32, 38 kRegMmio64, 39 kRegMmio1MB, 40 kRegUnknown, 41 }; 42 43 44 union PciAddress { 45 struct { 46 uint32 offset: 8; 47 uint32 function: 3; 48 uint32 device: 5; 49 uint32 bus: 8; 50 uint32 unused: 8; 51 }; 52 uint32 val; 53 }; 54 55 union PciAddressEcam { 56 struct { 57 uint32 offset: 12; 58 uint32 function: 3; 59 uint32 device: 5; 60 uint32 bus: 8; 61 uint32 unused: 4; 62 }; 63 uint32 val; 64 }; 65 66 struct RegisterRange { 67 phys_addr_t parentBase; 68 phys_addr_t childBase; 69 uint64 size; 70 }; 71 72 struct InterruptMapMask { 73 uint32_t childAdr; 74 uint32_t childIrq; 75 }; 76 77 struct InterruptMap { 78 uint32_t childAdr; 79 uint32_t childIrq; 80 uint32_t parentIrqCtrl; 81 uint32_t parentIrq; 82 }; 83 84 85 enum { 86 kPciAtuOffset = 0x300000, 87 }; 88 89 enum { 90 kPciAtuOutbound = 0, 91 kPciAtuInbound = 1, 92 }; 93 94 enum { 95 // ctrl1 96 kPciAtuTypeMem = 0, 97 kPciAtuTypeIo = 2, 98 kPciAtuTypeCfg0 = 4, 99 kPciAtuTypeCfg1 = 5, 100 // ctrl2 101 kPciAtuBarModeEnable = 1 << 30, 102 kPciAtuEnable = 1 << 31, 103 }; 104 105 struct PciAtuRegs { 106 uint32 ctrl1; 107 uint32 ctrl2; 108 uint32 baseLo; 109 uint32 baseHi; 110 uint32 limit; 111 uint32 targetLo; 112 uint32 targetHi; 113 uint32 unused[57]; 114 }; 115 116 struct PciDbiRegs { 117 uint8 unknown0[0x700]; 118 119 uint32 unknown1[3]; 120 uint32 portAfr; 121 uint32 linkControl; 122 uint32 unknown2[5]; 123 uint32 portDebug0; 124 uint32 portDebug1; 125 uint32 unknown3[55]; 126 uint32 linkWidthSpeedControl; 127 uint32 unknown4[4]; 128 uint32 msiAddrLo; 129 uint32 msiAddrHi; 130 struct { 131 uint32 enable; 132 uint32 mask; 133 uint32 status; 134 } msiIntr[8]; 135 uint32 unknown5[13]; 136 uint32 miscControl1Off; 137 uint32 miscPortMultiLaneCtrl; 138 uint32 unknown6[15]; 139 140 uint32 atuViewport; 141 uint32 atuCr1; 142 uint32 atuCr2; 143 uint32 atuBaseLo; 144 uint32 atuBaseHi; 145 uint32 atuLimit; 146 uint32 atuTargetLo; 147 uint32 atuTargetHi; 148 uint32 unknown7; 149 uint32 atuLimitHi; 150 uint32 unknown8[8]; 151 152 uint32 msixDoorbell; 153 uint32 unknown9[117]; 154 155 uint32 plChkRegControlStatus; 156 uint32 unknown10; 157 uint32 plChkRegErrAddr; 158 uint32 unknown11[309]; 159 }; 160 161 162 class MsiInterruptCtrlDW: public MSIInterface { 163 public: 164 virtual ~MsiInterruptCtrlDW() = default; 165 166 status_t Init(PciDbiRegs volatile* dbiRegs, int32 msiIrq); 167 168 status_t AllocateVectors(uint32 count, uint32& startVector, uint64& address, 169 uint32& data) final; 170 void FreeVectors(uint32 count, uint32 startVector) final; 171 172 173 private: 174 static int32 InterruptReceived(void* arg); 175 inline int32 InterruptReceivedInt(); 176 177 private: 178 PciDbiRegs volatile* fDbiRegs {}; 179 180 uint32 fAllocatedMsiIrqs[1]; 181 phys_addr_t fMsiPhysAddr {}; 182 int32 fMsiStartIrq {}; 183 uint64 fMsiData {}; 184 }; 185 186 187 class DWPCIController { 188 public: 189 static float SupportsDevice(device_node* parent); 190 static status_t RegisterDevice(device_node* parent); 191 static status_t InitDriver(device_node* node, DWPCIController*& outDriver); 192 void UninitDriver(); 193 194 status_t ReadConfig( 195 uint8 bus, uint8 device, uint8 function, 196 uint16 offset, uint8 size, uint32 &value); 197 198 status_t WriteConfig( 199 uint8 bus, uint8 device, uint8 function, 200 uint16 offset, uint8 size, uint32 value); 201 202 status_t GetMaxBusDevices(int32& count); 203 204 status_t ReadIrq( 205 uint8 bus, uint8 device, uint8 function, 206 uint8 pin, uint8& irq); 207 208 status_t WriteIrq( 209 uint8 bus, uint8 device, uint8 function, 210 uint8 pin, uint8 irq); 211 212 status_t GetRange(uint32 index, pci_resource_range* range); 213 214 private: 215 status_t ReadResourceInfo(); 216 inline status_t InitDriverInt(device_node* node); 217 218 inline addr_t ConfigAddress(uint8 bus, uint8 device, uint8 function, uint16 offset); 219 GetDbuRegs()220 PciDbiRegs volatile* GetDbuRegs() {return (PciDbiRegs volatile*)fDbiBase;} 221 status_t AtuMap(uint32 index, uint32 direction, uint32 type, 222 uint64 parentAdr, uint64 childAdr, uint32 size); 223 void AtuDump(); 224 225 private: 226 spinlock fLock = B_SPINLOCK_INITIALIZER; 227 228 device_node* fNode {}; 229 230 AreaDeleter fConfigArea; 231 addr_t fConfigPhysBase {}; 232 addr_t fConfigBase {}; 233 size_t fConfigSize {}; 234 235 Vector<pci_resource_range> fResourceRanges; 236 InterruptMapMask fInterruptMapMask {}; 237 uint32 fInterruptMapLen {}; 238 ArrayDeleter<InterruptMap> fInterruptMap; 239 240 AreaDeleter fDbiArea; 241 addr_t fDbiPhysBase {}; 242 addr_t fDbiBase {}; 243 size_t fDbiSize {}; 244 245 MsiInterruptCtrlDW fIrqCtrl; 246 }; 247 248 249 extern device_manager_info* gDeviceManager; 250 251 #endif // _PCICONTROLLERDW_H_ 252