<p>Richard Spiegel has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/c/coreboot/+/30215">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Early eMMC phase 1 - programming bridge<br><br>Global objective: Early ready of eMMC by sending "reset all".<br><br>This phase objective: Create bridge driver to be used by phase 2.<br><br>BUG=b:118680303<br>TEST=WIP, will test<br><br>Change-Id: Iaec1fcc4f8db8c3b4cfd3786d3ff589dc9cb22f5<br>Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com><br>---<br>A src/drivers/generic/temp_pcie_bridge/Kconfig<br>A src/drivers/generic/temp_pcie_bridge/Makefile.inc<br>A src/drivers/generic/temp_pcie_bridge/README<br>A src/drivers/generic/temp_pcie_bridge/bridge_ram.c<br>A src/drivers/generic/temp_pcie_bridge/bridge_rom.c<br>A src/include/device/temp_bridge.h<br>6 files changed, 302 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/15/30215/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/drivers/generic/temp_pcie_bridge/Kconfig b/src/drivers/generic/temp_pcie_bridge/Kconfig</span><br><span>new file mode 100644</span><br><span>index 0000000..f2629e3</span><br><span>--- /dev/null</span><br><span>+++ b/src/drivers/generic/temp_pcie_bridge/Kconfig</span><br><span>@@ -0,0 +1,2 @@</span><br><span style="color: hsl(120, 100%, 40%);">+config DRIVERS_TEMP_BRIDGE</span><br><span style="color: hsl(120, 100%, 40%);">+       bool</span><br><span>diff --git a/src/drivers/generic/temp_pcie_bridge/Makefile.inc b/src/drivers/generic/temp_pcie_bridge/Makefile.inc</span><br><span>new file mode 100644</span><br><span>index 0000000..fcdbf6d</span><br><span>--- /dev/null</span><br><span>+++ b/src/drivers/generic/temp_pcie_bridge/Makefile.inc</span><br><span>@@ -0,0 +1,2 @@</span><br><span style="color: hsl(120, 100%, 40%);">+romstage-$(CONFIG_DRIVERS_TEMP_BRIDGE) += bridge_rom.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_DRIVERS_TEMP_BRIDGE) += bridge_ram.c</span><br><span>diff --git a/src/drivers/generic/temp_pcie_bridge/README b/src/drivers/generic/temp_pcie_bridge/README</span><br><span>new file mode 100644</span><br><span>index 0000000..a9bf362</span><br><span>--- /dev/null</span><br><span>+++ b/src/drivers/generic/temp_pcie_bridge/README</span><br><span>@@ -0,0 +1,36 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Documentation for accessing devices behinf a bridge.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018 Silverback Ltd.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Sometimes you need to send commands to a device behind a PCIe bridge still</span><br><span style="color: hsl(120, 100%, 40%);">+at romstage, but bridge is not yet programmed. You need to temporarily program</span><br><span style="color: hsl(120, 100%, 40%);">+the bridge and any base address. Then you send whatever command, and disable</span><br><span style="color: hsl(120, 100%, 40%);">+the bridge, so regular PCI enumeration can do the work without bothering with</span><br><span style="color: hsl(120, 100%, 40%);">+something previous. Finally, some time later, you have to send a second command,</span><br><span style="color: hsl(120, 100%, 40%);">+or maybe read a register, but now PCI was enumerated... so you need to check</span><br><span style="color: hsl(120, 100%, 40%);">+where the base address was placed.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This driver is intended to facilitate these operations by providing 3 functions:</span><br><span style="color: hsl(120, 100%, 40%);">+Program bridge and base address(es)</span><br><span style="color: hsl(120, 100%, 40%);">+Remove base addresses and reset the bridge.</span><br><span style="color: hsl(120, 100%, 40%);">+Find what base address(es) were programmed by PCI enumeration.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+For all these functions you need to provide the bridge device:</span><br><span style="color: hsl(120, 100%, 40%);">+<PCI_DEV(0, device, func)> at romstage.</span><br><span style="color: hsl(120, 100%, 40%);">+<dev_find_slot(0, PCI_DEVFN(device, func))> at ramstage.</span><br><span style="color: hsl(120, 100%, 40%);">+The only other parameter, for functions that return base address(es) is actually</span><br><span style="color: hsl(120, 100%, 40%);">+a pointer to a structure which tells what is expected, and place(es) to return</span><br><span style="color: hsl(120, 100%, 40%);">+the address(es).</span><br><span>diff --git a/src/drivers/generic/temp_pcie_bridge/bridge_ram.c b/src/drivers/generic/temp_pcie_bridge/bridge_ram.c</span><br><span>new file mode 100644</span><br><span>index 0000000..659e5af</span><br><span>--- /dev/null</span><br><span>+++ b/src/drivers/generic/temp_pcie_bridge/bridge_ram.c</span><br><span>@@ -0,0 +1,59 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Obtain base addresses of device behind bridge, for ramstage.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018 Silverback Ltd.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/temp_bridge.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/pci_ops.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PCIE_BASE CONFIG_MMCONF_BASE_ADDRESS</span><br><span style="color: hsl(120, 100%, 40%);">+#define PADDR(dev, reg) \</span><br><span style="color: hsl(120, 100%, 40%);">+      ((((uint32_t)dev << 12) | ((uint32_t)reg & 0x0fff)) + PCIE_BASE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t pci_read32(uint16_t dev, uint16_t reg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return *(uint32_t *)PADDR(dev, reg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int get_bases(DEVTREE_CONST struct device *bridge,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct device_addresses *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t value;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t dev;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t num;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t byte = pci_read_config8(bridge, PCI_HEADER_TYPE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (byte == 0xff)</span><br><span style="color: hsl(120, 100%, 40%);">+             return TP_BRIDGE_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((byte & 0x7f) != PCI_HEADER_TYPE_BRIDGE)</span><br><span style="color: hsl(120, 100%, 40%);">+              return TP_NOT_A_BRIDGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     byte = pci_read_config8(bridge, PCI_SECONDARY_BUS);</span><br><span style="color: hsl(120, 100%, 40%);">+   dev = (uint16_t)byte << 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      for (num = 0; num < 6; num++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            value = pci_read32(dev, TEMP_BASE(num));</span><br><span style="color: hsl(120, 100%, 40%);">+              switch (params->used[num]) {</span><br><span style="color: hsl(120, 100%, 40%);">+               case MEMORY_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                  params->bases[num] = value;</span><br><span style="color: hsl(120, 100%, 40%);">+                        break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case IO_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                      params->bases[num] = value & 0x0000fffe;</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return TP_BRIDGE_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/drivers/generic/temp_pcie_bridge/bridge_rom.c b/src/drivers/generic/temp_pcie_bridge/bridge_rom.c</span><br><span>new file mode 100644</span><br><span>index 0000000..5e63b1f</span><br><span>--- /dev/null</span><br><span>+++ b/src/drivers/generic/temp_pcie_bridge/bridge_rom.c</span><br><span>@@ -0,0 +1,150 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Temporary bridge/device programming for device access at romstage.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018 Silverback Ltd.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/temp_bridge.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int set_base(pci_devfn_t dev, uint8_t number, uint8_t use,</span><br><span style="color: hsl(120, 100%, 40%);">+                   uint32_t *size, uint32_t start, uint32_t *base)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int status = TP_BRIDGE_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t value;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t command;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    pci_write_config32(dev, TEMP_BASE(number), 0xffffffff);</span><br><span style="color: hsl(120, 100%, 40%);">+       value = pci_read_config32(dev, TEMP_BASE(number));</span><br><span style="color: hsl(120, 100%, 40%);">+    command = pci_read_config8(dev, PCI_COMMAND);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (use == MEMORY_ADDRESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (value & 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                    status = TP_DEVICE_INVALID_TYPE;</span><br><span style="color: hsl(120, 100%, 40%);">+              value &= 0xfffffc00; /* At least 1K between addresses */</span><br><span style="color: hsl(120, 100%, 40%);">+          *size = 1 + ~value;</span><br><span style="color: hsl(120, 100%, 40%);">+           value &= start;</span><br><span style="color: hsl(120, 100%, 40%);">+           command |= PCI_COMMAND_MEMORY;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if ((value & 1) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                     status = TP_DEVICE_INVALID_TYPE;</span><br><span style="color: hsl(120, 100%, 40%);">+              value &= 0x0000ffc0; /* At least 64 bytes between addresses */</span><br><span style="color: hsl(120, 100%, 40%);">+            *size = 1 + ~value;</span><br><span style="color: hsl(120, 100%, 40%);">+           value &= start;</span><br><span style="color: hsl(120, 100%, 40%);">+           value |= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           command |= PCI_COMMAND_IO;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     pci_write_config32(dev, TEMP_BASE(number), value);</span><br><span style="color: hsl(120, 100%, 40%);">+    command |= PCI_COMMAND_MASTER;</span><br><span style="color: hsl(120, 100%, 40%);">+        pci_write_config8(dev, PCI_COMMAND, command);</span><br><span style="color: hsl(120, 100%, 40%);">+ return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int set_bases(pci_devfn_t bridge, struct device_addresses *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int ret_stat, status = TP_BRIDGE_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t return_base, return_size;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t mem_start, next_mem, used_memory;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t io_start, next_io, used_io;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t num;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t byte = pci_read_config8(bridge, PCI_HEADER_TYPE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (byte == 0xff)</span><br><span style="color: hsl(120, 100%, 40%);">+             return TP_BRIDGE_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((byte & 0x7f) != PCI_HEADER_TYPE_BRIDGE)</span><br><span style="color: hsl(120, 100%, 40%);">+              return TP_NOT_A_BRIDGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     pci_write_config8(bridge, PCI_COMMAND, PCI_COMMAND_MASTER);</span><br><span style="color: hsl(120, 100%, 40%);">+   pci_write_config32(bridge, PCI_PRIMARY_BUS, BRIDGE_BUS_1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (params->memory_range)</span><br><span style="color: hsl(120, 100%, 40%);">+          next_mem = params->memory_range;</span><br><span style="color: hsl(120, 100%, 40%);">+   else</span><br><span style="color: hsl(120, 100%, 40%);">+          next_mem = TP_DEFAULT_MEM_START;</span><br><span style="color: hsl(120, 100%, 40%);">+      mem_start = next_mem;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (params->io_range)</span><br><span style="color: hsl(120, 100%, 40%);">+              next_io = params->io_range;</span><br><span style="color: hsl(120, 100%, 40%);">+        else</span><br><span style="color: hsl(120, 100%, 40%);">+          next_io = TP_DEFAULT_IO_START;</span><br><span style="color: hsl(120, 100%, 40%);">+        io_start = next_io;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (num = 0; num < 6; num++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return_base = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              return_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              switch (params->used[num]) {</span><br><span style="color: hsl(120, 100%, 40%);">+               case MEMORY_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                  ret_stat = set_base(DEVICE_BUS_1, num, MEMORY_ADDRESS,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        &return_base, next_mem, &return_size);</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (ret_stat)</span><br><span style="color: hsl(120, 100%, 40%);">+                         status = ret_stat;</span><br><span style="color: hsl(120, 100%, 40%);">+                    else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                next_mem += (return_base + return_size);</span><br><span style="color: hsl(120, 100%, 40%);">+                              params->bases[num] = return_base;</span><br><span style="color: hsl(120, 100%, 40%);">+                  }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case IO_ADDRESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                      ret_stat = set_base(DEVICE_BUS_1, num, IO_ADDRESS,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    &return_base, next_io, &return_size);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (ret_stat)</span><br><span style="color: hsl(120, 100%, 40%);">+                         status = ret_stat;</span><br><span style="color: hsl(120, 100%, 40%);">+                    else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                next_io += (uint16_t)(return_base +</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 return_size);</span><br><span style="color: hsl(120, 100%, 40%);">+                           params->bases[num] = return_base;</span><br><span style="color: hsl(120, 100%, 40%);">+                  }</span><br><span style="color: hsl(120, 100%, 40%);">+                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     used_memory = next_mem - mem_start;</span><br><span style="color: hsl(120, 100%, 40%);">+   used_io = next_io - io_start;</span><br><span style="color: hsl(120, 100%, 40%);">+ byte = pci_read_config8(bridge, PCI_COMMAND);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (used_memory) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* create base/limit dword */</span><br><span style="color: hsl(120, 100%, 40%);">+         next_mem--;</span><br><span style="color: hsl(120, 100%, 40%);">+           next_mem &= 0xfff00000;</span><br><span style="color: hsl(120, 100%, 40%);">+           next_mem |= 0x0000fff0 & (mem_start >> 16);</span><br><span style="color: hsl(120, 100%, 40%);">+         pci_write_config32(bridge, PCI_MEMORY_BASE, next_mem);</span><br><span style="color: hsl(120, 100%, 40%);">+                byte |= PCI_COMMAND_MEMORY;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (used_io) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* create base/limit word */</span><br><span style="color: hsl(120, 100%, 40%);">+          next_io--;</span><br><span style="color: hsl(120, 100%, 40%);">+            next_io &= 0xf000;</span><br><span style="color: hsl(120, 100%, 40%);">+                next_io |= 0x00f0 & (io_start >> 8);</span><br><span style="color: hsl(120, 100%, 40%);">+                pci_write_config16(bridge, PCI_IO_BASE, next_io);</span><br><span style="color: hsl(120, 100%, 40%);">+             byte |= PCI_COMMAND_IO;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     pci_write_config8(bridge, PCI_COMMAND, byte);</span><br><span style="color: hsl(120, 100%, 40%);">+ return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This code assumes the bridge was programmed to have the devi on bus 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+int release_bases(pci_devfn_t bridge)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int status = TP_BRIDGE_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t num;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t byte = pci_read_config8(bridge, PCI_HEADER_TYPE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (byte == 0xff)</span><br><span style="color: hsl(120, 100%, 40%);">+             return TP_BRIDGE_NOT_FOUND;</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((byte & 0x7f) != PCI_HEADER_TYPE_BRIDGE)</span><br><span style="color: hsl(120, 100%, 40%);">+              return TP_NOT_A_BRIDGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (num = 0; num < 6; num++)</span><br><span style="color: hsl(120, 100%, 40%);">+              pci_write_config32(DEVICE_BUS_1, TEMP_BASE(num), 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  pci_write_config32(DEVICE_BUS_1, PCI_COMMAND, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+     pci_write_config32(bridge, PCI_MEMORY_BASE, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       pci_write_config16(bridge, PCI_IO_BASE, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   pci_write_config8(bridge, PCI_COMMAND, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    return status;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/include/device/temp_bridge.h b/src/include/device/temp_bridge.h</span><br><span>new file mode 100644</span><br><span>index 0000000..52a19f5</span><br><span>--- /dev/null</span><br><span>+++ b/src/include/device/temp_bridge.h</span><br><span>@@ -0,0 +1,53 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Documentation for eMMC host drivers</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2018 Silverback Ltd.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __DRIVER_TEMP_BRIDGE_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __DRIVER_TEMP_BRIDGE_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/io.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/device.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/pci_def.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define NOT_USED                0</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEMORY_ADDRESS               1</span><br><span style="color: hsl(120, 100%, 40%);">+#define IO_ADDRESS           2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_BRIDGE_SUCCESS  0</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_BRIDGE_NOT_FOUND  -1</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_DEVICE_INVALID_TYPE      -2</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_NOT_A_BRIDGE             -3</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_BRIDGE__OTHER    -4</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BRIDGE_BUS_1              0x00010100</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEVICE_BUS_1                PCI_DEV(1, 0, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define TEMP_BASE(num)              ((num * 4) + PCI_BASE_ADDRESS_0)</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_DEFAULT_MEM_START  0xf4000000</span><br><span style="color: hsl(120, 100%, 40%);">+#define TP_DEFAULT_IO_START 0xa000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct device_addresses {</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t used[6];        /* If used, IO/memory for bases 0-5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t io_range;      /* start address of range to use */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t memory_range;  /* start address of range to use */</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t bases[6];      /* return values programmed */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int set_bases(pci_devfn_t bridge, struct device_addresses *params);</span><br><span style="color: hsl(120, 100%, 40%);">+int release_bases(pci_devfn_t bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+int get_bases(DEVTREE_CONST struct device *bridge,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct device_addresses *params);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/c/coreboot/+/30215">change 30215</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/c/coreboot/+/30215"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Iaec1fcc4f8db8c3b4cfd3786d3ff589dc9cb22f5 </div>
<div style="display:none"> Gerrit-Change-Number: 30215 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Spiegel <richard.spiegel@silverbackltd.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>