1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <zircon/assert.h>
6
7#include <hw/reg.h>
8
9#include <ddk/debug.h>
10#include <ddk/protocol/platform-defs.h>
11
12#include <dev/pci/designware/atu-cfg.h>
13#include <soc/aml-a113/a113-gpio.h>
14#include <soc/aml-a113/a113-hw.h>
15#include <soc/aml-meson/axg-clk.h>
16
17#include "gauss.h"
18
19// Note: These are all constants for the PCIe A controller
20//       PCIe B is not currently supported.
21static const pbus_mmio_t dw_pcie_mmios[] = {
22    {   // elbi
23        .base = 0xf9800000,
24        .length = 0x400000,   // 4MiB
25    },
26    {   // cfg
27        .base = 0xff646000,
28        .length = 0x2000,     // 8KiB
29    },
30    {   // reset
31        .base = 0xffd01080,
32        .length = 0x10,       // 16B
33    },
34    {   // clock/plls
35        .base = 0xff63c000,
36        .length = PAGE_SIZE,
37    },
38};
39
40static const pbus_irq_t dw_pcie_irqs[] = {
41    {
42        .irq = DW_PCIE_IRQ0,
43        .mode = ZX_INTERRUPT_MODE_DEFAULT,
44    },
45    {
46        .irq = DW_PCIE_IRQ1,
47        .mode = ZX_INTERRUPT_MODE_DEFAULT,
48    },
49};
50
51static const pbus_gpio_t dw_pcie_gpios[] = {
52    {
53        .gpio = A113_GPIOX(19),     // Reset
54    },
55};
56
57static const pbus_clk_t pcie_clk_gates[] = {
58    {
59        .clk = CLK_AXG_CLK81,
60    },
61    {
62        .clk = CLK_AXG_PCIE_A,
63    },
64    {
65        .clk = CLK_CML0_EN,
66    },
67};
68
69#define CFG_CPU_ADDR_BASE  (0xf9c00000)
70#define CFG_CPU_ADDR_LEN   (0x10000)      // 64KiB of CFG Space
71#define IO_CPU_ADDR_BASE   (0xf9d00000)
72#define IO_CPU_ADDR_LEN    (0x10000)      // 64KiB of IO Space
73#define MEM_CPU_ADDR_BASE  (IO_CPU_ADDR_BASE + IO_CPU_ADDR_LEN)
74#define MEM_CPU_ADDR_LEN   (0x300000)     // 3MiB of memory space.
75
76static const iatu_translation_entry_t cfg_entry = {
77    .cpu_addr = CFG_CPU_ADDR_BASE,
78    .pci_addr = 0,
79    .length = CFG_CPU_ADDR_LEN,
80};
81
82static const iatu_translation_entry_t io_entry = {
83    .cpu_addr = IO_CPU_ADDR_BASE,
84    .pci_addr = 0,
85    .length = IO_CPU_ADDR_LEN,
86};
87
88static const iatu_translation_entry_t mem_entry = {
89    .cpu_addr = MEM_CPU_ADDR_BASE,
90    .pci_addr = MEM_CPU_ADDR_BASE,
91    .length = MEM_CPU_ADDR_LEN,
92};
93
94static const pbus_metadata_t iatu_metadata[] = {
95    // PCIe Configuration Space
96    {
97        .type = IATU_CFG_APERTURE_METADATA,  // Private Metadata
98        .data = &cfg_entry,
99        .len = sizeof(cfg_entry),
100    },
101
102    // PCIe IO Space
103    {
104        .type = IATU_IO_APERTURE_METADATA,  // Private Metadata
105        .data = &io_entry,
106        .len = sizeof(io_entry),
107    },
108
109    // PCIe Memory space
110    {
111        .type = IATU_MMIO_APERTURE_METADATA,  // Private Metadata
112        .data = &mem_entry,
113        .len = sizeof(mem_entry),
114    },
115};
116
117static const pbus_bti_t pci_btis[] = {
118    {
119        .iommu_index = 0,
120        .bti_id = 0,
121    },
122};
123
124static const pbus_dev_t pcie_dev_children[] = {
125    {
126        // Resources for child-1
127        .btis = pci_btis,
128        .bti_count = countof(pci_btis)
129    },
130};
131
132static const pbus_dev_t pcie_dev = {
133    .name = "aml-dw-pcie",
134    .vid = PDEV_VID_AMLOGIC,
135    .pid = PDEV_PID_GENERIC,
136    .did = PDEV_DID_DW_PCIE,
137    .mmios = dw_pcie_mmios,
138    .mmio_count = countof(dw_pcie_mmios),
139    .gpios = dw_pcie_gpios,
140    .gpio_count = countof(dw_pcie_gpios),
141    .clks = pcie_clk_gates,
142    .clk_count = countof(pcie_clk_gates),
143    .irqs = dw_pcie_irqs,
144    .irq_count = countof(dw_pcie_irqs),
145    .metadata = iatu_metadata,
146    .metadata_count = countof(iatu_metadata),
147
148    // Allow this device to publish the Kernel PCI device on the Platform Bus
149    .children = pcie_dev_children,
150    .child_count = countof(pcie_dev_children),
151};
152
153zx_status_t gauss_pcie_init(gauss_bus_t* bus) {
154    zx_status_t st = pbus_device_add(&bus->pbus, &pcie_dev);
155    if (st != ZX_OK) {
156        zxlogf(ERROR, "gauss_clk_init: pbus_device_add failed, st = %d\n", st);
157        return st;
158    }
159
160    return ZX_OK;
161}