summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2015-09-03 05:37:23 -0700
committerSimon Glass <sjg@chromium.org>2015-09-09 07:48:03 -0600
commit5750e5e29a4d4e90cb0ce3ec71233f8efbf5ebaa (patch)
treee51131daf89888e445763705d744369a3d460c76
parent983c6ba227e192c79b1df82853d8bacd40e1e989 (diff)
downloadu-boot-imx-5750e5e29a4d4e90cb0ce3ec71233f8efbf5ebaa.zip
u-boot-imx-5750e5e29a4d4e90cb0ce3ec71233f8efbf5ebaa.tar.gz
u-boot-imx-5750e5e29a4d4e90cb0ce3ec71233f8efbf5ebaa.tar.bz2
x86: quark: Optimize MRC execution time
Intel Quark SoC has a low end x86 processor with only 400MHz frequency. Currently it takes about 15 seconds for U-Boot to boot to shell and the most time consuming part is with MRC, which is about 12 seconds. MRC programs lots of registers on the SoC internal message bus indirectly accessed via pci bus. To speed up the boot, create an optimized version of pci config read/write dword routines which directly operate on PCI I/O ports. These two routines are inlined to provide better performance too. Now it only takes about 3 seconds to finish MRC, which is really fast (4 times faster than before). Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org>
-rw-r--r--arch/x86/cpu/quark/msg_port.c44
-rw-r--r--arch/x86/include/asm/arch-quark/quark.h35
2 files changed, 57 insertions, 22 deletions
diff --git a/arch/x86/cpu/quark/msg_port.c b/arch/x86/cpu/quark/msg_port.c
index 31713e3..cf828f2 100644
--- a/arch/x86/cpu/quark/msg_port.c
+++ b/arch/x86/cpu/quark/msg_port.c
@@ -5,34 +5,34 @@
*/
#include <common.h>
-#include <pci.h>
#include <asm/arch/device.h>
#include <asm/arch/msg_port.h>
+#include <asm/arch/quark.h>
void msg_port_setup(int op, int port, int reg)
{
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
- (((op) << 24) | ((port) << 16) |
- (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_REG,
+ (((op) << 24) | ((port) << 16) |
+ (((reg) << 8) & 0xff00) | MSG_BYTE_ENABLE));
}
u32 msg_port_read(u8 port, u32 reg)
{
u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_READ, port, reg);
- pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_write(u8 port, u32 reg, u32 value)
{
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_WRITE, port, reg);
}
@@ -40,19 +40,19 @@ u32 msg_port_alt_read(u8 port, u32 reg)
{
u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_ALT_READ, port, reg);
- pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_alt_write(u8 port, u32 reg, u32 value)
{
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_ALT_WRITE, port, reg);
}
@@ -60,18 +60,18 @@ u32 msg_port_io_read(u8 port, u32 reg)
{
u32 value;
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_READ, port, reg);
- pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
+ qrk_pci_read_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, &value);
return value;
}
void msg_port_io_write(u8 port, u32 reg, u32 value)
{
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
- pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
- reg & 0xffffff00);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, value);
+ qrk_pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG,
+ reg & 0xffffff00);
msg_port_setup(MSG_OP_IO_WRITE, port, reg);
}
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h
index c997928..1ce5693 100644
--- a/arch/x86/include/asm/arch-quark/quark.h
+++ b/arch/x86/include/asm/arch-quark/quark.h
@@ -89,6 +89,41 @@ struct quark_rcba {
u16 d20d21_ir;
};
+#include <asm/io.h>
+#include <asm/pci.h>
+
+/**
+ * qrk_pci_read_config_dword() - Read a configuration value
+ *
+ * @dev: PCI device address: bus, device and function
+ * @offset: Dword offset within the device's configuration space
+ * @valuep: Place to put the returned value
+ *
+ * Note: This routine is inlined to provide better performance on Quark
+ */
+static inline void qrk_pci_read_config_dword(pci_dev_t dev, int offset,
+ u32 *valuep)
+{
+ outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR);
+ *valuep = inl(PCI_REG_DATA);
+}
+
+/**
+ * qrk_pci_write_config_dword() - Write a PCI configuration value
+ *
+ * @dev: PCI device address: bus, device and function
+ * @offset: Dword offset within the device's configuration space
+ * @value: Value to write
+ *
+ * Note: This routine is inlined to provide better performance on Quark
+ */
+static inline void qrk_pci_write_config_dword(pci_dev_t dev, int offset,
+ u32 value)
+{
+ outl(dev | offset | PCI_CFG_EN, PCI_REG_ADDR);
+ outl(value, PCI_REG_DATA);
+}
+
#endif /* __ASSEMBLY__ */
#endif /* _QUARK_H_ */