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