Tom Rini | 53633a8 | 2024-02-29 12:33:36 -0500 | [diff] [blame] | 1 | |
| 2 | * Marvell MBus |
| 3 | |
| 4 | Required properties: |
| 5 | |
| 6 | - compatible: Should be set to one of the following: |
| 7 | marvell,armada370-mbus |
| 8 | marvell,armadaxp-mbus |
| 9 | marvell,armada375-mbus |
| 10 | marvell,armada380-mbus |
| 11 | marvell,kirkwood-mbus |
| 12 | marvell,dove-mbus |
| 13 | marvell,orion5x-88f5281-mbus |
| 14 | marvell,orion5x-88f5182-mbus |
| 15 | marvell,orion5x-88f5181-mbus |
| 16 | marvell,orion5x-88f6183-mbus |
| 17 | marvell,mv78xx0-mbus |
| 18 | |
| 19 | - address-cells: Must be '2'. The first cell for the MBus ID encoding, |
| 20 | the second cell for the address offset within the window. |
| 21 | |
| 22 | - size-cells: Must be '1'. |
| 23 | |
| 24 | - ranges: Must be set up to provide a proper translation for each child. |
| 25 | See the examples below. |
| 26 | |
| 27 | - controller: Contains a single phandle referring to the MBus controller |
| 28 | node. This allows to specify the node that contains the |
| 29 | registers that control the MBus, which is typically contained |
| 30 | within the internal register window (see below). |
| 31 | |
| 32 | Optional properties: |
| 33 | |
| 34 | - pcie-mem-aperture: This optional property contains the aperture for |
| 35 | the memory region of the PCIe driver. |
| 36 | If it's defined, it must encode the base address and |
| 37 | size for the address decoding windows allocated for |
| 38 | the PCIe memory region. |
| 39 | |
| 40 | - pcie-io-aperture: Just as explained for the above property, this |
| 41 | optional property contains the aperture for the |
| 42 | I/O region of the PCIe driver. |
| 43 | |
| 44 | * Marvell MBus controller |
| 45 | |
| 46 | Required properties: |
| 47 | |
| 48 | - compatible: Should be set to "marvell,mbus-controller". |
| 49 | |
| 50 | - reg: Device's register space. |
| 51 | Two or three entries are expected (see the examples below): |
| 52 | the first one controls the devices decoding window, |
| 53 | the second one controls the SDRAM decoding window and |
| 54 | the third controls the MBus bridge (only with the |
| 55 | marvell,armada370-mbus and marvell,armadaxp-mbus |
| 56 | compatible strings) |
| 57 | |
| 58 | Example: |
| 59 | |
| 60 | soc { |
| 61 | compatible = "marvell,armada370-mbus", "simple-bus"; |
| 62 | #address-cells = <2>; |
| 63 | #size-cells = <1>; |
| 64 | controller = <&mbusc>; |
| 65 | pcie-mem-aperture = <0xe0000000 0x8000000>; |
| 66 | pcie-io-aperture = <0xe8000000 0x100000>; |
| 67 | |
| 68 | internal-regs { |
| 69 | compatible = "simple-bus"; |
| 70 | |
| 71 | mbusc: mbus-controller@20000 { |
| 72 | compatible = "marvell,mbus-controller"; |
| 73 | reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>; |
| 74 | }; |
| 75 | |
| 76 | /* more children ...*/ |
| 77 | }; |
| 78 | }; |
| 79 | |
| 80 | ** MBus address decoding window specification |
| 81 | |
| 82 | The MBus children address space is comprised of two cells: the first one for |
| 83 | the window ID and the second one for the offset within the window. |
| 84 | In order to allow to describe valid and non-valid window entries, the |
| 85 | following encoding is used: |
| 86 | |
| 87 | 0xSIAA0000 0x00oooooo |
| 88 | |
| 89 | Where: |
| 90 | |
| 91 | S = 0x0 for a MBus valid window |
| 92 | S = 0xf for a non-valid window (see below) |
| 93 | |
| 94 | If S = 0x0, then: |
| 95 | |
| 96 | I = 4-bit window target ID |
| 97 | AA = windpw attribute |
| 98 | |
| 99 | If S = 0xf, then: |
| 100 | |
| 101 | I = don't care |
| 102 | AA = 1 for internal register |
| 103 | |
| 104 | Following the above encoding, for each ranges entry for a MBus valid window |
| 105 | (S = 0x0), an address decoding window is allocated. On the other side, |
| 106 | entries for translation that do not correspond to valid windows (S = 0xf) |
| 107 | are skipped. |
| 108 | |
| 109 | soc { |
| 110 | compatible = "marvell,armada370-mbus", "simple-bus"; |
| 111 | #address-cells = <2>; |
| 112 | #size-cells = <1>; |
| 113 | controller = <&mbusc>; |
| 114 | |
| 115 | ranges = <0xf0010000 0 0 0xd0000000 0x100000 |
| 116 | 0x01e00000 0 0 0xfff00000 0x100000>; |
| 117 | |
| 118 | bootrom { |
| 119 | compatible = "marvell,bootrom"; |
| 120 | reg = <0x01e00000 0 0x100000>; |
| 121 | }; |
| 122 | |
| 123 | /* other children */ |
| 124 | ... |
| 125 | |
| 126 | internal-regs { |
| 127 | compatible = "simple-bus"; |
| 128 | ranges = <0 0xf0010000 0 0x100000>; |
| 129 | |
| 130 | mbusc: mbus-controller@20000 { |
| 131 | compatible = "marvell,mbus-controller"; |
| 132 | reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>; |
| 133 | }; |
| 134 | |
| 135 | /* more children ...*/ |
| 136 | }; |
| 137 | }; |
| 138 | |
| 139 | In the shown example, the translation entry in the 'ranges' property is what |
| 140 | makes the MBus driver create a static decoding window for the corresponding |
| 141 | given child device. Note that the binding does not require child nodes to be |
| 142 | present. Of course, child nodes are needed to probe the devices. |
| 143 | |
| 144 | Since each window is identified by its target ID and attribute ID there's |
| 145 | a special macro that can be use to simplify the translation entries: |
| 146 | |
| 147 | #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) |
| 148 | |
| 149 | Using this macro, the above example would be: |
| 150 | |
| 151 | soc { |
| 152 | compatible = "marvell,armada370-mbus", "simple-bus"; |
| 153 | #address-cells = <2>; |
| 154 | #size-cells = <1>; |
| 155 | controller = <&mbusc>; |
| 156 | |
| 157 | ranges = < MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000 |
| 158 | MBUS_ID(0x01, 0xe0) 0 0 0xfff00000 0x100000>; |
| 159 | |
| 160 | bootrom { |
| 161 | compatible = "marvell,bootrom"; |
| 162 | reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>; |
| 163 | }; |
| 164 | |
| 165 | /* other children */ |
| 166 | ... |
| 167 | |
| 168 | internal-regs { |
| 169 | compatible = "simple-bus"; |
| 170 | #address-cells = <1>; |
| 171 | #size-cells = <1>; |
| 172 | ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; |
| 173 | |
| 174 | mbusc: mbus-controller@20000 { |
| 175 | compatible = "marvell,mbus-controller"; |
| 176 | reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>; |
| 177 | }; |
| 178 | |
| 179 | /* other children */ |
| 180 | ... |
| 181 | }; |
| 182 | }; |
| 183 | |
| 184 | |
| 185 | ** About the window base address |
| 186 | |
| 187 | Remember the MBus controller allows a great deal of flexibility for choosing |
| 188 | the decoding window base address. When planning the device tree layout it's |
| 189 | possible to choose any address as the base address, provided of course there's |
| 190 | a region large enough available, and with the required alignment. |
| 191 | |
| 192 | Yet in other words: there's nothing preventing us from setting a base address |
| 193 | of 0xf0000000, or 0xd0000000 for the NOR device shown above, if such region is |
| 194 | unused. |
| 195 | |
| 196 | ** Window allocation policy |
| 197 | |
| 198 | The mbus-node ranges property defines a set of mbus windows that are expected |
| 199 | to be set by the operating system and that are guaranteed to be free of overlaps |
| 200 | with one another or with the system memory ranges. |
| 201 | |
| 202 | Each entry in the property refers to exactly one window. If the operating system |
| 203 | chooses to use a different set of mbus windows, it must ensure that any address |
| 204 | translations performed from downstream devices are adapted accordingly. |
| 205 | |
| 206 | The operating system may insert additional mbus windows that do not conflict |
| 207 | with the ones listed in the ranges, e.g. for mapping PCIe devices. |
| 208 | As a special case, the internal register window must be set up by the boot |
| 209 | loader at the address listed in the ranges property, since access to that region |
| 210 | is needed to set up the other windows. |
| 211 | |
| 212 | ** Example |
| 213 | |
| 214 | See the example below, where a more complete device tree is shown: |
| 215 | |
| 216 | soc { |
| 217 | compatible = "marvell,armadaxp-mbus", "simple-bus"; |
| 218 | controller = <&mbusc>; |
| 219 | |
| 220 | ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000 /* internal-regs */ |
| 221 | MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 |
| 222 | MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>; |
| 223 | |
| 224 | bootrom { |
| 225 | compatible = "marvell,bootrom"; |
| 226 | reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>; |
| 227 | }; |
| 228 | |
| 229 | devbus-bootcs { |
| 230 | ranges = <0 MBUS_ID(0x01, 0x2f) 0 0x8000000>; |
| 231 | |
| 232 | /* NOR */ |
| 233 | nor { |
| 234 | compatible = "cfi-flash"; |
| 235 | reg = <0 0x8000000>; |
| 236 | bank-width = <2>; |
| 237 | }; |
| 238 | }; |
| 239 | |
| 240 | pcie-controller { |
| 241 | compatible = "marvell,armada-xp-pcie"; |
| 242 | device_type = "pci"; |
| 243 | |
| 244 | #address-cells = <3>; |
| 245 | #size-cells = <2>; |
| 246 | |
| 247 | ranges = |
| 248 | <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */ |
| 249 | 0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */ |
| 250 | 0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */ |
| 251 | 0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */ |
| 252 | 0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */ |
| 253 | 0x82000800 0 0xe0000000 MBUS_ID(0x04, 0xe8) 0xe0000000 0 0x08000000 /* Port 0.0 MEM */ |
| 254 | 0x81000800 0 0 MBUS_ID(0x04, 0xe0) 0xe8000000 0 0x00100000 /* Port 0.0 IO */>; |
| 255 | |
| 256 | |
| 257 | pcie@1,0 { |
| 258 | /* Port 0, Lane 0 */ |
| 259 | }; |
| 260 | }; |
| 261 | |
| 262 | internal-regs { |
| 263 | compatible = "simple-bus"; |
| 264 | #address-cells = <1>; |
| 265 | #size-cells = <1>; |
| 266 | ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; |
| 267 | |
| 268 | mbusc: mbus-controller@20000 { |
| 269 | reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>; |
| 270 | }; |
| 271 | |
| 272 | interrupt-controller@20000 { |
| 273 | reg = <0x20a00 0x2d0>, <0x21070 0x58>; |
| 274 | }; |
| 275 | }; |
| 276 | }; |