Lines Matching +full:4 +full:- +full:bits

1 // SPDX-License-Identifier: GPL-2.0
21 #include "pci-bridge-emul.h"
28 * struct pci_bridge_reg_behavior - register bits behaviors
29 * @ro: Read-Only bits
30 * @rw: Read-Write bits
31 * @w1c: Write-1-to-Clear bits
33 * Reads and Writes will be filtered by specified behavior. All other bits not
36 * multi-bit fields) when read".
39 /* Read-only bits */
42 /* Read-write bits */
45 /* Write-1-to-clear bits */
50 struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = {
51 [PCI_VENDOR_ID / 4] = { .ro = ~0 },
52 [PCI_COMMAND / 4] = {
63 [PCI_CLASS_REVISION / 4] = { .ro = ~0 },
66 * Cache Line Size register: implement as read-only, we do not
70 * Latency Timer Register: implemented as read-only, as "A
75 * Header Type: always read-only
77 * BIST register: implemented as read-only, as "A bridge that
79 * read-only register that returns 0 when read"
81 [PCI_CACHE_LINE_SIZE / 4] = { .ro = ~0 },
85 * read-only registers that return 0 when read.
87 [PCI_BASE_ADDRESS_0 / 4] = { .ro = ~0 },
88 [PCI_BASE_ADDRESS_1 / 4] = { .ro = ~0 },
90 [PCI_PRIMARY_BUS / 4] = {
93 /* Secondary latency is read-only */
97 [PCI_IO_BASE / 4] = {
98 /* The high four bits of I/O base/limit are RW */
99 .rw = (GENMASK(15, 12) | GENMASK(7, 4)),
101 /* The low four bits of I/O base/limit are RO */
109 [PCI_MEMORY_BASE / 4] = {
110 /* The high 12-bits of mem base/limit are RW */
111 .rw = GENMASK(31, 20) | GENMASK(15, 4),
113 /* The low four bits of mem base/limit are RO */
117 [PCI_PREF_MEMORY_BASE / 4] = {
118 /* The high 12-bits of pref mem base/limit are RW */
119 .rw = GENMASK(31, 20) | GENMASK(15, 4),
121 /* The low four bits of pref mem base/limit are RO */
125 [PCI_PREF_BASE_UPPER32 / 4] = {
129 [PCI_PREF_LIMIT_UPPER32 / 4] = {
133 [PCI_IO_BASE_UPPER16 / 4] = {
137 [PCI_CAPABILITY_LIST / 4] = {
143 * be implemented as read-only register that return 0 when read, same
146 [PCI_ROM_ADDRESS1 / 4] = {
151 * Interrupt line (bits 7:0) are RW, interrupt pin (bits 15:8)
153 * reserved and W1C bits
155 [PCI_INTERRUPT_LINE / 4] = {
174 struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = {
175 [PCI_CAP_LIST_ID / 4] = {
178 * bits [14:0] of Capabilities register are all read-only.
184 [PCI_EXP_DEVCAP / 4] = {
186 * Bits [31:29] and [17:16] are reserved.
187 * Bits [27:18] are reserved for non-upstream ports.
188 * Bits 28 and [14:6] are reserved for non-endpoint devices.
189 * Other bits are read-only.
194 [PCI_EXP_DEVCTL / 4] = {
197 * reserved for non-endpoints or non-PCIe-to-PCI/X bridges.
202 * Device status register has bits 6 and [3:0] W1C, [5:4] RO,
203 * the rest is reserved. Also bit 6 is reserved for non-upstream
207 .ro = GENMASK(5, 4) << 16,
210 [PCI_EXP_LNKCAP / 4] = {
212 * All bits are RO, except bit 23 which is reserved and
213 * bit 18 which is reserved for non-upstream ports.
218 [PCI_EXP_LNKCTL / 4] = {
220 * Link control has bits [15:14], [11:3] and [1:0] RW, the
221 * rest is reserved. Bit 8 is reserved for non-upstream ports.
223 * Link status has bits [13:0] RO, and bits [15:14]
231 [PCI_EXP_SLTCAP / 4] = {
235 [PCI_EXP_SLTCTL / 4] = {
237 * Slot control has bits [14:0] RW, the rest is
240 * Slot status has bits 8 and [4:0] W1C, bits [7:5] RO, the
251 [PCI_EXP_RTCTL / 4] = {
253 * Root control has bits [4:0] RW, the rest is
264 [PCI_EXP_RTSTA / 4] = {
266 * Root status has bits 17 and [15:0] RO, bit 16 W1C, the rest
273 [PCI_EXP_DEVCAP2 / 4] = {
275 * Device capabilities 2 register has reserved bits [30:27].
276 * Also bits [26:24] are reserved for non-upstream ports.
281 [PCI_EXP_DEVCTL2 / 4] = {
284 * non-upstream ports.
291 [PCI_EXP_LNKCAP2 / 4] = {
292 /* Link capabilities 2 register has reserved bits [30:25] and 0. */
296 [PCI_EXP_LNKCTL2 / 4] = {
300 * Link status 2 register has bits 5, 15 W1C;
301 * bits 10, 11 reserved and others are RO.
305 .ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16,
308 [PCI_EXP_SLTCAP2 / 4] = {
312 [PCI_EXP_SLTCTL2 / 4] = {
323 ((bridge->pcie_start > bridge->ssid_start) ? (bridge->pcie_start << 8) : 0); in pci_bridge_emul_read_ssid()
327 *value = bridge->subsystem_vendor_id | in pci_bridge_emul_read_ssid()
328 (bridge->subsystem_id << 16); in pci_bridge_emul_read_ssid()
340 * (typically at least vendor, device, revision), the ->ops pointer,
341 * and optionally ->data and ->has_pcie.
346 BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END); in pci_bridge_emul_init()
349 * class_revision: Class is high 24 bits and revision is low 8 bit in pci_bridge_emul_init()
351 * 24-bit value: PCI_CLASS_BRIDGE_PCI_NORMAL in pci_bridge_emul_init()
353 bridge->conf.class_revision |= in pci_bridge_emul_init()
355 bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; in pci_bridge_emul_init()
356 bridge->conf.cache_line_size = 0x10; in pci_bridge_emul_init()
357 bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); in pci_bridge_emul_init()
358 bridge->pci_regs_behavior = kmemdup(pci_regs_behavior, in pci_bridge_emul_init()
361 if (!bridge->pci_regs_behavior) in pci_bridge_emul_init()
362 return -ENOMEM; in pci_bridge_emul_init()
365 if (!bridge->ssid_start && !bridge->pcie_start) { in pci_bridge_emul_init()
366 if (bridge->subsystem_vendor_id) in pci_bridge_emul_init()
367 bridge->ssid_start = PCI_BRIDGE_CONF_END; in pci_bridge_emul_init()
368 if (bridge->has_pcie) in pci_bridge_emul_init()
369 bridge->pcie_start = bridge->ssid_start + PCI_CAP_SSID_SIZEOF; in pci_bridge_emul_init()
370 } else if (!bridge->ssid_start && bridge->subsystem_vendor_id) { in pci_bridge_emul_init()
371 if (bridge->pcie_start - PCI_BRIDGE_CONF_END >= PCI_CAP_SSID_SIZEOF) in pci_bridge_emul_init()
372 bridge->ssid_start = PCI_BRIDGE_CONF_END; in pci_bridge_emul_init()
374 bridge->ssid_start = bridge->pcie_start + PCI_CAP_PCIE_SIZEOF; in pci_bridge_emul_init()
375 } else if (!bridge->pcie_start && bridge->has_pcie) { in pci_bridge_emul_init()
376 if (bridge->ssid_start - PCI_BRIDGE_CONF_END >= PCI_CAP_PCIE_SIZEOF) in pci_bridge_emul_init()
377 bridge->pcie_start = PCI_BRIDGE_CONF_END; in pci_bridge_emul_init()
379 bridge->pcie_start = bridge->ssid_start + PCI_CAP_SSID_SIZEOF; in pci_bridge_emul_init()
382 bridge->conf.capabilities_pointer = min(bridge->ssid_start, bridge->pcie_start); in pci_bridge_emul_init()
384 if (bridge->conf.capabilities_pointer) in pci_bridge_emul_init()
385 bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST); in pci_bridge_emul_init()
387 if (bridge->has_pcie) { in pci_bridge_emul_init()
388 bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP; in pci_bridge_emul_init()
389 bridge->pcie_conf.next = (bridge->ssid_start > bridge->pcie_start) ? in pci_bridge_emul_init()
390 bridge->ssid_start : 0; in pci_bridge_emul_init()
391 bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4); in pci_bridge_emul_init()
392 bridge->pcie_cap_regs_behavior = in pci_bridge_emul_init()
396 if (!bridge->pcie_cap_regs_behavior) { in pci_bridge_emul_init()
397 kfree(bridge->pci_regs_behavior); in pci_bridge_emul_init()
398 return -ENOMEM; in pci_bridge_emul_init()
400 /* These bits are applicable only for PCI and reserved on PCIe */ in pci_bridge_emul_init()
401 bridge->pci_regs_behavior[PCI_CACHE_LINE_SIZE / 4].ro &= in pci_bridge_emul_init()
403 bridge->pci_regs_behavior[PCI_COMMAND / 4].ro &= in pci_bridge_emul_init()
409 bridge->pci_regs_behavior[PCI_PRIMARY_BUS / 4].ro &= in pci_bridge_emul_init()
411 bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro &= in pci_bridge_emul_init()
414 bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].rw &= in pci_bridge_emul_init()
417 bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].ro &= in pci_bridge_emul_init()
419 bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].w1c &= in pci_bridge_emul_init()
424 bridge->pci_regs_behavior[PCI_PREF_MEMORY_BASE / 4].ro = ~0; in pci_bridge_emul_init()
425 bridge->pci_regs_behavior[PCI_PREF_MEMORY_BASE / 4].rw = 0; in pci_bridge_emul_init()
429 bridge->pci_regs_behavior[PCI_COMMAND / 4].ro |= PCI_COMMAND_IO; in pci_bridge_emul_init()
430 bridge->pci_regs_behavior[PCI_COMMAND / 4].rw &= ~PCI_COMMAND_IO; in pci_bridge_emul_init()
431 bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro |= GENMASK(15, 0); in pci_bridge_emul_init()
432 bridge->pci_regs_behavior[PCI_IO_BASE / 4].rw &= ~GENMASK(15, 0); in pci_bridge_emul_init()
433 bridge->pci_regs_behavior[PCI_IO_BASE_UPPER16 / 4].ro = ~0; in pci_bridge_emul_init()
434 bridge->pci_regs_behavior[PCI_IO_BASE_UPPER16 / 4].rw = 0; in pci_bridge_emul_init()
447 if (bridge->has_pcie) in pci_bridge_emul_cleanup()
448 kfree(bridge->pcie_cap_regs_behavior); in pci_bridge_emul_cleanup()
449 kfree(bridge->pci_regs_behavior); in pci_bridge_emul_cleanup()
456 * ->ops->read_base or ->ops->read_pcie operations.
470 read_op = bridge->ops->read_base; in pci_bridge_emul_conf_read()
471 cfgspace = (__le32 *) &bridge->conf; in pci_bridge_emul_conf_read()
472 behavior = bridge->pci_regs_behavior; in pci_bridge_emul_conf_read()
473 } else if (reg >= bridge->ssid_start && reg < bridge->ssid_start + PCI_CAP_SSID_SIZEOF && in pci_bridge_emul_conf_read()
474 bridge->subsystem_vendor_id) { in pci_bridge_emul_conf_read()
476 reg -= bridge->ssid_start; in pci_bridge_emul_conf_read()
480 } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF && in pci_bridge_emul_conf_read()
481 bridge->has_pcie) { in pci_bridge_emul_conf_read()
483 reg -= bridge->pcie_start; in pci_bridge_emul_conf_read()
484 read_op = bridge->ops->read_pcie; in pci_bridge_emul_conf_read()
485 cfgspace = (__le32 *) &bridge->pcie_conf; in pci_bridge_emul_conf_read()
486 behavior = bridge->pcie_cap_regs_behavior; in pci_bridge_emul_conf_read()
487 } else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) { in pci_bridge_emul_conf_read()
489 reg -= PCI_CFG_SPACE_SIZE; in pci_bridge_emul_conf_read()
490 read_op = bridge->ops->read_ext; in pci_bridge_emul_conf_read()
506 *value = le32_to_cpu(cfgspace[reg / 4]); in pci_bridge_emul_conf_read()
516 *value &= behavior[reg / 4].ro | behavior[reg / 4].rw | in pci_bridge_emul_conf_read()
517 behavior[reg / 4].w1c; in pci_bridge_emul_conf_read()
523 else if (size != 4) in pci_bridge_emul_conf_read()
533 * ->ops->write_base or ->ops->write_pcie operations.
545 ret = pci_bridge_emul_conf_read(bridge, reg, 4, &old); in pci_bridge_emul_conf_write()
551 write_op = bridge->ops->write_base; in pci_bridge_emul_conf_write()
552 cfgspace = (__le32 *) &bridge->conf; in pci_bridge_emul_conf_write()
553 behavior = bridge->pci_regs_behavior; in pci_bridge_emul_conf_write()
554 } else if (reg >= bridge->pcie_start && reg < bridge->pcie_start + PCI_CAP_PCIE_SIZEOF && in pci_bridge_emul_conf_write()
555 bridge->has_pcie) { in pci_bridge_emul_conf_write()
557 reg -= bridge->pcie_start; in pci_bridge_emul_conf_write()
558 write_op = bridge->ops->write_pcie; in pci_bridge_emul_conf_write()
559 cfgspace = (__le32 *) &bridge->pcie_conf; in pci_bridge_emul_conf_write()
560 behavior = bridge->pcie_cap_regs_behavior; in pci_bridge_emul_conf_write()
561 } else if (reg >= PCI_CFG_SPACE_SIZE && bridge->has_pcie) { in pci_bridge_emul_conf_write()
563 reg -= PCI_CFG_SPACE_SIZE; in pci_bridge_emul_conf_write()
564 write_op = bridge->ops->write_ext; in pci_bridge_emul_conf_write()
574 if (size == 4) in pci_bridge_emul_conf_write()
584 /* Keep all bits, except the RW bits */ in pci_bridge_emul_conf_write()
585 new = old & (~mask | ~behavior[reg / 4].rw); in pci_bridge_emul_conf_write()
587 /* Update the value of the RW bits */ in pci_bridge_emul_conf_write()
588 new |= (value << shift) & (behavior[reg / 4].rw & mask); in pci_bridge_emul_conf_write()
590 /* Clear the W1C bits */ in pci_bridge_emul_conf_write()
591 new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); in pci_bridge_emul_conf_write()
598 /* Save the new value with the cleared W1C bits into the cfgspace */ in pci_bridge_emul_conf_write()
599 cfgspace[reg / 4] = cpu_to_le32(new); in pci_bridge_emul_conf_write()
604 * Clear the W1C bits not specified by the write mask, so that the in pci_bridge_emul_conf_write()
607 new &= ~(behavior[reg / 4].w1c & ~mask); in pci_bridge_emul_conf_write()
610 * Set the W1C bits specified by the write mask, so that write_op() in pci_bridge_emul_conf_write()
613 new |= (value << shift) & (behavior[reg / 4].w1c & mask); in pci_bridge_emul_conf_write()