From 1d880992fd8c8457a2d990ac6622cfd58fb1b261 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 2 Jul 2014 15:36:20 +1000 Subject: Initial commit of Open Source release Signed-off-by: Benjamin Herrenschmidt --- hw/homer.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 hw/homer.c (limited to 'hw/homer.c') diff --git a/hw/homer.c b/hw/homer.c new file mode 100644 index 0000000..14cfa1e --- /dev/null +++ b/hw/homer.c @@ -0,0 +1,143 @@ +/* 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PBA_BAR0 0x2013f00 +#define PBA_BARMASK0 0x2013f04 + +static bool read_pba_bar(struct proc_chip *chip, unsigned int bar_no, + uint64_t *base, uint64_t *size) +{ + uint64_t bar, mask; + int rc; + + rc = xscom_read(chip->id, PBA_BAR0 + bar_no, &bar); + if (rc) { + prerror("SLW: Error %d reading PBA BAR%d on chip %d\n", + rc, bar_no, chip->id); + return false; + } + rc = xscom_read(chip->id, PBA_BARMASK0 + bar_no, &mask); + if (rc) { + prerror("SLW: Error %d reading PBA BAR MASK%d on chip %d\n", + rc, bar_no, chip->id); + return false; + } + printf(" PBA BAR%d : 0x%016llx\n", bar_no, bar); + printf(" PBA MASK%d: 0x%016llx\n", bar_no, mask); + + *base = bar & 0x0ffffffffffffffful; + *size = (mask | 0xfffff) + 1; + + return (*base) != 0; +} + +static void homer_init_chip(struct proc_chip *chip) +{ + uint64_t hbase = 0, hsize = 0; + uint64_t sbase, ssize, obase, osize; + + /* + * PBA BARs assigned by HB: + * + * 0 : Entire HOMER + * 1 : OCC to Centaur path (we don't care) + * 2 : SLW image + * 3 : OCC Common area + * + * We need to reserve the memory covered by BAR 0 and BAR 3, however + * on earlier HBs, BAR0 isn't set so we need BAR 2 instead in that + * case to cover SLW (OCC not running). + */ + if (read_pba_bar(chip, 0, &hbase, &hsize)) { + printf(" HOMER Image at 0x%llx size %lldMB\n", + hbase, hsize / 0x100000); + mem_reserve("ibm,homer-image", hbase, hsize); + + chip->homer_base = hbase; + chip->homer_size = hsize; + } + + /* + * We always read the SLW BAR since we need to grab info about the + * SLW image in the struct proc_chip for use by the slw.c code + */ + if (read_pba_bar(chip, 2, &sbase, &ssize)) { + printf(" SLW Image at 0x%llx size %lldMB\n", + sbase, ssize / 0x100000); + + /* + * Only reserve it if we have no homer image or if it + * doesn't fit in it (only check the base). + */ + if (sbase < hbase || sbase > (hbase + hsize) || + (hbase == 0 && sbase > 0)) + mem_reserve("ibm,slw-image", sbase, ssize); + + chip->slw_base = sbase; + chip->slw_bar_size = ssize; + chip->slw_image_size = ssize; /* will be adjusted later */ + } + + if (read_pba_bar(chip, 3, &obase, &osize)) { + printf(" OCC Common Area at 0x%llx size %lldMB\n", + obase, osize / 0x100000); + chip->occ_common_base = obase; + chip->occ_common_size = osize; + } +} + +void homer_init(void) +{ + struct proc_chip *chip; + + if (proc_gen != proc_gen_p8) + return; + + /* + * XXX This is temporary, on P8 we look for any configured + * SLW/OCC BAR and reserve the memory. Eventually, this will be + * done via HostBoot using the device-tree "reserved-ranges" + * or we'll load the SLW & OCC images ourselves using Host Services. + */ + for_each_chip(chip) { + printf("HOMER: Init chip %d\n", chip->id); + homer_init_chip(chip); + } + + /* + * Check is PBA BARs are already loaded with HOMER and + * skip host services. + */ + + chip = next_chip(NULL); + if (chip->homer_base && chip->occ_common_base) { + /* Reserve OCC comman area from BAR */ + mem_reserve("ibm,occ-common-area", chip->occ_common_base, + chip->occ_common_size); + } else { + /* Allocate memory for HOMER and OCC common area */ + host_services_occ_base_setup(); + } +} + -- cgit v1.1