diff options
Diffstat (limited to 'include/p5ioc2.h')
-rw-r--r-- | include/p5ioc2.h | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/include/p5ioc2.h b/include/p5ioc2.h new file mode 100644 index 0000000..fb9ed1b --- /dev/null +++ b/include/p5ioc2.h @@ -0,0 +1,184 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __P5IOC2_H +#define __P5IOC2_H + +#include <stdint.h> +#include <cec.h> +#include <io.h> +#include <cec.h> +#include <pci.h> +#include <lock.h> +#include <device.h> + +#include <ccan/container_of/container_of.h> + +/* + * Various definitions which are the result of various + * things we have hard wired (routing etc...) + */ + +/* It looks like our registers are at an offset from GX BAR 0 ... */ +#define P5IOC2_REGS_OFFSET 0x01F00000 + +#define P5IOC2_CA0_REG_OFFSET 0 /* From BAR6, R0 */ +#define P5IOC2_CA1_REG_OFFSET 0x01000000 /* From BAR6, R1 */ +#define P5IOC2_CA0_MM_OFFSET 0 /* From BAR0, R0 and 1 */ +#define P5IOC2_CA1_MM_OFFSET 0x400000000ul /* From BAR0, R1 and 2 */ +#define P5IOC2_CA_PHB_COUNT 4 +#define P5IOC2_CA0_RIO_ID 2 +#define P5IOC2_CA1_RIO_ID 3 +#define P5IOC2_CA0_BUID 0x10 +#define P5IOC2_CA1_BUID 0x20 + +/* + * Our memory space is slightly different than pHyp + * (or even BML). We do as follow: + * + * - IO space is in the Calgary MMIO, at (phb_index +1) * 1M + * (pHyp seems to mangle the IO space location) and is always + * 1M in size mapping to PCI 0 + * + * - Memory space is in the BAR0 mapped region. Each PHB gets + * allocated a 4G window at base + (phb_index * 4G). It uses + * a portion of that space based on the chosen size of the + * MMIO space, typically 2G. + */ +#define MM_WINDOW_SIZE 0x100000000ul +#define MM_PCI_START 0x80000000 +#define MM_PCI_SIZE 0x80000000 +#define IO_PCI_START 0x00000000 +#define IO_PCI_SIZE 0x00100000 + +/* + * CAn interrupts + * + * Within Calgary BUID space + */ +#define P5IOC2_CA_HOST_IRQ 0 +#define P5IOC2_CA_SPCN_IRQ 1 +#define P5IOC2_CA_PERF_IRQ 2 + +/* + * The PHB states are similar to P7IOC, see the explanation + * in p7ioc.h + */ +enum p5ioc2_phb_state { + /* First init state */ + P5IOC2_PHB_STATE_UNINITIALIZED, + + /* During PHB HW inits */ + P5IOC2_PHB_STATE_INITIALIZING, + + /* Set if the PHB is for some reason unusable */ + P5IOC2_PHB_STATE_BROKEN, + + /* Normal PHB functional state */ + P5IOC2_PHB_STATE_FUNCTIONAL, +}; + +/* + * Structure for a PHB + */ + +struct p5ioc2; + +struct p5ioc2_phb { + bool active; /* Is this PHB functional ? */ + bool is_pcie; + uint8_t ca; /* CA0 or CA1 */ + uint8_t index; /* 0..3 index inside CA */ + void *ca_regs; /* Calgary regs */ + void *regs; /* PHB regs */ + struct lock lock; + uint32_t buid; + uint64_t mm_base; + uint64_t io_base; + int64_t ecap; /* cached PCI-E cap offset */ + int64_t aercap; /* cached AER ecap offset */ + enum p5ioc2_phb_state state; + uint64_t delay_tgt_tb; + uint64_t retries; + uint64_t xive_cache[16]; + struct p5ioc2 *ioc; + struct phb phb; +}; + +static inline struct p5ioc2_phb *phb_to_p5ioc2_phb(struct phb *phb) +{ + return container_of(phb, struct p5ioc2_phb, phb); +} + +extern void p5ioc2_phb_setup(struct p5ioc2 *ioc, struct p5ioc2_phb *p, + uint8_t ca, uint8_t index, bool active, + uint32_t buid); + +/* + * State structure for P5IOC2 IO HUB + */ +struct p5ioc2 { + /* Device node */ + struct dt_node *dt_node; + + /* MMIO regs for the chip */ + void *regs; + + /* BAR6 (matches GX BAR 1) is used for internal Calgary MMIO and + * for PCI IO space. + */ + uint64_t bar6; + + /* BAR0 (matches GX BAR 2) is used for PCI memory space */ + uint64_t bar0; + + /* Calgary 0 and 1 registers. We assume their BBAR values as such + * that CA0 is at bar6 and CA1 at bar6 + 16M + */ + void* ca0_regs; + void* ca1_regs; + + /* The large MM regions assigned off bar0 to CA0 and CA1 for use + * by their PHBs (16G each) + */ + uint64_t ca0_mm_region; + uint64_t ca1_mm_region; + + /* BUID base for the PHB. This does include the top bits + * (chip, GX bus ID, etc...). This is initialized from the + * SPIRA. + */ + uint32_t buid_base; + + /* TCE region set by the user */ + uint64_t tce_base; + uint64_t tce_size; + + /* Calgary 0 and 1 PHBs */ + struct p5ioc2_phb ca0_phbs[P5IOC2_CA_PHB_COUNT]; + struct p5ioc2_phb ca1_phbs[P5IOC2_CA_PHB_COUNT]; + + uint32_t host_chip; + uint32_t gx_bus; + struct io_hub hub; +}; + +static inline struct p5ioc2 *iohub_to_p5ioc2(struct io_hub *hub) +{ + return container_of(hub, struct p5ioc2, hub); +} + +#endif /* __P5IOC2_H */ |