summaryrefslogtreecommitdiff
path: root/board/aspeed/ast2300/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/aspeed/ast2300/pci.c')
-rwxr-xr-xboard/aspeed/ast2300/pci.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/board/aspeed/ast2300/pci.c b/board/aspeed/ast2300/pci.c
new file mode 100755
index 0000000000..5b17466132
--- /dev/null
+++ b/board/aspeed/ast2300/pci.c
@@ -0,0 +1,243 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+#include <common.h>
+#include <pci.h>
+
+#ifdef CONFIG_PCI
+
+#define PCI_CSR_BASE 0x60000000
+#define ASPEED_PCI_IO_BASE 0x00000000
+#define ASPEED_PCI_IO_SIZE 0x00010000
+#define ASPEED_PCI_MEM_BASE 0x68000000
+#define ASPEED_PCI_MEM_SIZE 0x18000000
+
+#define CSR_CRP_CMD_OFFSET 0x00
+#define CSR_CRP_WRITE_OFFSET 0x04
+#define CSR_CRP_READ_OFFSET 0x08
+#define CSR_PCI_ADDR_OFFSET 0x0C
+#define CSR_PCI_CMD_OFFSET 0x10
+#define CSR_PCI_WRITE_OFFSET 0x14
+#define CSR_PCI_READ_OFFSET 0x18
+#define CSR_PCI_STATUS_OFFSET 0x1C
+
+#define CRP_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_CMD_OFFSET)
+#define CRP_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_WRITE_OFFSET)
+#define CRP_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_CRP_READ_OFFSET)
+#define PCI_ADDR_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_ADDR_OFFSET)
+#define PCI_CMD_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_CMD_OFFSET)
+#define PCI_WRITE_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_WRITE_OFFSET)
+#define PCI_READ_REG (volatile ulong*) (PCI_CSR_BASE + CSR_PCI_READ_OFFSET)
+
+#define PCI_CMD_READ 0x0A
+#define PCI_CMD_WRITE 0x0B
+
+#define RESET_PCI_STATUS *(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) = 0x01
+#define CHK_PCI_STATUS (*(volatile ulong*) (PCI_CSR_BASE + CSR_PCI_STATUS_OFFSET) & 0x03)
+
+static int pci_config_access (u8 access_type, u32 dev, u32 reg, u32 * data)
+{
+ u32 bus;
+ u32 device;
+ u32 function;
+
+ bus = ((dev & 0xff0000) >> 16);
+ device = ((dev & 0xf800) >> 11);
+ function = (dev & 0x0700);
+
+ if (bus == 0) {
+ // Type 0 Configuration
+ *PCI_ADDR_REG = (u32) (1UL << device | function | (reg & 0xfc));
+ } else {
+ // Type 1 Configuration
+ *PCI_ADDR_REG = (u32) (dev | ((reg / 4) << 2) | 1);
+ }
+
+ RESET_PCI_STATUS;
+
+ if (access_type == PCI_CMD_WRITE) {
+ *PCI_CMD_REG = (ulong) PCI_CMD_WRITE;
+ *PCI_WRITE_REG = *data;
+ } else {
+ *PCI_CMD_REG = (ulong) PCI_CMD_READ;
+ *data = *PCI_READ_REG;
+ }
+
+ return (CHK_PCI_STATUS);
+}
+
+static int aspeed_pci_read_config_byte (u32 hose, u32 dev, u32 reg, u8 * val)
+{
+ u32 data;
+
+ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
+ *val = 0;
+ return -1;
+ }
+
+ *val = (data >> ((reg & 3) << 3)) & 0xff;
+
+ return 0;
+}
+
+
+static int aspeed_pci_read_config_word (u32 hose, u32 dev, u32 reg, u16 * val)
+{
+ u32 data;
+
+ if (reg & 1)
+ return -1;
+
+ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
+ *val = 0;
+ return -1;
+ }
+
+ *val = (data >> ((reg & 3) << 3)) & 0xffff;
+
+ return 0;
+}
+
+
+static int aspeed_pci_read_config_dword (u32 hose, u32 dev, u32 reg,
+ u32 * val)
+{
+ u32 data = 0;
+
+ if (reg & 3)
+ return -1;
+
+ if (pci_config_access (PCI_CMD_READ, dev, reg, &data)) {
+ *val = 0;
+ return -1;
+ }
+
+ *val = data;
+
+ return (0);
+}
+
+static int aspeed_pci_write_config_byte (u32 hose, u32 dev, u32 reg, u8 val)
+{
+ u32 data = 0;
+
+ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
+ return -1;
+
+ data = (data & ~(0xff << ((reg & 3) << 3))) | (val <<
+ ((reg & 3) << 3));
+
+ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
+ return -1;
+
+ return 0;
+}
+
+
+static int aspeed_pci_write_config_word (u32 hose, u32 dev, u32 reg, u16 val)
+{
+ u32 data = 0;
+
+ if (reg & 1)
+ return -1;
+
+ if (pci_config_access (PCI_CMD_READ, dev, reg, &data))
+ return -1;
+
+ data = (data & ~(0xffff << ((reg & 3) << 3))) | (val <<
+ ((reg & 3) << 3));
+
+ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
+ return -1;
+
+ return 0;
+}
+
+static int aspeed_pci_write_config_dword (u32 hose, u32 dev, u32 reg, u32 val)
+{
+ u32 data;
+
+ if (reg & 3) {
+ return -1;
+ }
+
+ data = val;
+
+ if (pci_config_access (PCI_CMD_WRITE, dev, reg, &data))
+ return -1;
+
+ return (0);
+}
+
+/*
+ * Initialize PCIU
+ */
+aspeed_pciu_init ()
+{
+
+ unsigned long reg;
+
+ /* Reset PCI Host */
+ reg = *((volatile ulong*) 0x1e6e2004);
+ *((volatile ulong*) 0x1e6e2004) = reg | 0x00280000;
+
+ reg = *((volatile ulong*) 0x1e6e2074); /* REQ2 */
+ *((volatile ulong*) 0x1e6e2074) = reg | 0x00000010;
+
+ *((volatile ulong*) 0x1e6e2008) |= 0x00080000;
+ reg = *((volatile ulong*) 0x1e6e200c);
+ *((volatile ulong*) 0x1e6e200c) = reg & 0xfff7ffff;
+ udelay(1);
+ *((volatile ulong*) 0x1e6e2004) &= 0xfff7ffff;
+
+ /* Initial PCI Host */
+ RESET_PCI_STATUS;
+
+ *CRP_ADDR_REG = ((ulong)(PCI_CMD_READ) << 16) | 0x04;
+ reg = *CRP_READ_REG;
+
+ *CRP_ADDR_REG = ((ulong)(PCI_CMD_WRITE) << 16) | 0x04;
+ *CRP_WRITE_REG = reg | 0x07;
+
+}
+
+/*
+ * Initialize Module
+ */
+
+void aspeed_init_pci (struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ aspeed_pciu_init (); /* Initialize PCIU */
+
+ /* PCI memory space #1 */
+ pci_set_region (hose->regions + 0,
+ ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_BASE, ASPEED_PCI_MEM_SIZE, PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region (hose->regions + 1,
+ ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_BASE, ASPEED_PCI_IO_SIZE, PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ hose->read_byte = aspeed_pci_read_config_byte;
+ hose->read_word = aspeed_pci_read_config_word;
+ hose->read_dword = aspeed_pci_read_config_dword;
+ hose->write_byte = aspeed_pci_write_config_byte;
+ hose->write_word = aspeed_pci_write_config_word;
+ hose->write_dword = aspeed_pci_write_config_dword;
+
+ pci_register_hose (hose);
+
+ hose->last_busno = pci_hose_scan (hose);
+
+ return;
+}
+#endif /* CONFIG_PCI */
+