diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-05 09:33:37 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-05 09:33:37 +1100 |
commit | 01ff8fea5c60c69aafa5d9a5e8877a3df67192de (patch) | |
tree | 82792b4a9be3a8608e0350ff3da071dee27cfd9c /platforms | |
parent | d09b52b8982db63525c67bf36506ce8a813f84d0 (diff) | |
download | skiboot-01ff8fea5c60c69aafa5d9a5e8877a3df67192de.zip skiboot-01ff8fea5c60c69aafa5d9a5e8877a3df67192de.tar.gz skiboot-01ff8fea5c60c69aafa5d9a5e8877a3df67192de.tar.bz2 |
plat/palmetto: Move most code to a common file & reorder inits a bit
This moves most of the palmetto platform code to a "common" file
to share with other platforms using AST BMC.
We also initialize IPMI later.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'platforms')
-rw-r--r-- | platforms/bmc/Makefile.inc | 2 | ||||
-rw-r--r-- | platforms/bmc/astbmc.h (renamed from platforms/bmc/bmc.h) | 12 | ||||
-rw-r--r-- | platforms/bmc/common.c | 234 | ||||
-rw-r--r-- | platforms/bmc/palmetto.c | 217 | ||||
-rw-r--r-- | platforms/bmc/pnor.c | 4 |
5 files changed, 252 insertions, 217 deletions
diff --git a/platforms/bmc/Makefile.inc b/platforms/bmc/Makefile.inc index 348e594..0b5c2c8 100644 --- a/platforms/bmc/Makefile.inc +++ b/platforms/bmc/Makefile.inc @@ -1,6 +1,6 @@ SUBDIRS += $(PLATDIR)/bmc -BMC_OBJS = palmetto.o pnor.o +BMC_OBJS = palmetto.o pnor.o common.o BMC = $(PLATDIR)/bmc/built-in.o $(BMC): $(BMC_OBJS:%=$(PLATDIR)/bmc/%) diff --git a/platforms/bmc/bmc.h b/platforms/bmc/astbmc.h index 59d20bb..cee475a 100644 --- a/platforms/bmc/bmc.h +++ b/platforms/bmc/astbmc.h @@ -15,10 +15,14 @@ */ -#ifndef __BMC_H -#define __BMC_H +#ifndef __ASTBMC_H +#define __ASTBMC_H -extern void bmc_ext_irq(uint32_t chip_id); +extern void astbmc_early_init(void); +extern int64_t astbmc_ipmi_reboot(void); +extern int64_t astbmc_ipmi_power_down(uint64_t request); +extern void astbmc_init(void); +extern void astbmc_ext_irq(unsigned int chip_id); extern int pnor_init(void); -#endif /* __BMC_H */ +#endif /* __ASTBMC_H */ diff --git a/platforms/bmc/common.c b/platforms/bmc/common.c new file mode 100644 index 0000000..684fe5d --- /dev/null +++ b/platforms/bmc/common.c @@ -0,0 +1,234 @@ +/* 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 <skiboot.h> +#include <device.h> +#include <console.h> +#include <psi.h> +#include <chip.h> +#include <xscom.h> +#include <ast.h> +#include <ipmi.h> +#include <bt.h> + +#include "astbmc.h" + +/* UART1 config */ +#define UART_IO_BASE 0x3f8 +#define UART_IO_COUNT 8 +#define UART_LPC_IRQ 4 + +/* BT config */ +#define BT_IO_BASE 0xe4 +#define BT_IO_COUNT 3 +#define BT_LPC_IRQ 10 + +void astbmc_ext_irq(unsigned int chip_id __unused) +{ + uart_irq(); + bt_irq(); +} + +void astbmc_init(void) +{ + /* Setup dummy console nodes */ + if (dummy_console_enabled()) + dummy_console_add_nodes(); + + /* Initialize PNOR/NVRAM */ + pnor_init(); + + /* Register the BT interface with the IPMI layer */ + bt_init(); + ipmi_rtc_init(); + + /* As soon as IPMI is up, inform BMC we are in "S0" */ + ipmi_set_power_state(IPMI_PWR_SYS_S0_WORKING, IPMI_PWR_NOCHANGE); +} + +int64_t astbmc_ipmi_power_down(uint64_t request) +{ + if (request != IPMI_CHASSIS_PWR_DOWN) { + prlog(PR_WARNING, "PLAT: unexpected shutdown request %llx\n", + request); + } + + return ipmi_chassis_control(request); +} + +int64_t astbmc_ipmi_reboot(void) +{ + return ipmi_chassis_control(IPMI_CHASSIS_HARD_RESET); +} + +static void astbmc_fixup_dt_bt(struct dt_node *lpc) +{ + struct dt_node *bt; + char namebuf[32]; + + /* First check if the BT interface is already there */ + dt_for_each_child(lpc, bt) { + if (dt_node_is_compatible(bt, "bt")) + return; + } + + sprintf(namebuf, "ipmi-bt@i%x", BT_IO_BASE); + bt = dt_new(lpc, namebuf); + + dt_add_property_cells(bt, "reg", + 1, /* IO space */ + BT_IO_BASE, BT_IO_COUNT); + dt_add_property_strings(bt, "compatible", "ipmi-bt"); + + /* Mark it as reserved to avoid Linux trying to claim it */ + dt_add_property_strings(bt, "status", "reserved"); +} + +static void astbmc_fixup_dt_uart(struct dt_node *lpc) +{ + /* + * The official OF ISA/LPC binding is a bit odd, it prefixes + * the unit address for IO with "i". It uses 2 cells, the first + * one indicating IO vs. Memory space (along with bits to + * represent aliasing). + * + * We pickup that binding and add to it "2" as a indication + * of FW space. + */ + struct dt_node *uart; + char namebuf[32]; + + /* First check if the UART is already there */ + dt_for_each_child(lpc, uart) { + if (dt_node_is_compatible(uart, "ns16550")) + return; + } + + /* Otherwise, add a node for it */ + sprintf(namebuf, "serial@i%x", UART_IO_BASE); + uart = dt_new(lpc, namebuf); + + dt_add_property_cells(uart, "reg", + 1, /* IO space */ + UART_IO_BASE, UART_IO_COUNT); + dt_add_property_strings(uart, "compatible", + "ns16550", + "pnpPNP,501"); + dt_add_property_cells(uart, "clock-frequency", 1843200); + dt_add_property_cells(uart, "current-speed", 115200); + + /* + * This is needed by Linux for some obscure reasons, + * we'll eventually need to sanitize it but in the meantime + * let's make sure it's there + */ + dt_add_property_strings(uart, "device_type", "serial"); + + /* + * Add interrupt. This simulates coming from HostBoot which + * does not know our interrupt numbering scheme. Instead, it + * just tells us which chip the interrupt is wired to, it will + * be the PSI "host error" interrupt of that chip. For now we + * assume the same chip as the LPC bus is on. + */ + dt_add_property_cells(uart, "ibm,irq-chip-id", dt_get_chip_id(lpc)); +} + +static void astbmc_fixup_dt(void) +{ + struct dt_node *n, *primary_lpc = NULL; + + /* Find the primary LPC bus */ + dt_for_each_compatible(dt_root, n, "ibm,power8-lpc") { + if (!primary_lpc || dt_has_node_property(n, "primary", NULL)) + primary_lpc = n; + if (dt_has_node_property(n, "#address-cells", NULL)) + break; + } + + if (!primary_lpc) + return; + + /* Fixup the UART, that might be missing from HB */ + astbmc_fixup_dt_uart(primary_lpc); + + astbmc_fixup_dt_bt(primary_lpc); + + /* Force the dummy console for now */ + force_dummy_console(); +} + +static void astbmc_fixup_psi_bar(void) +{ + struct proc_chip *chip = next_chip(NULL); + uint64_t psibar; + + /* Read PSI BAR */ + if (xscom_read(chip->id, 0x201090A, &psibar)) { + prerror("PLAT: Error reading PSI BAR\n"); + return; + } + /* Already configured, bail out */ + if (psibar & 1) + return; + + /* Hard wire ... yuck */ + psibar = 0x3fffe80000001; + + printf("PLAT: Fixing up PSI BAR on chip %d BAR=%llx\n", + chip->id, psibar); + + /* Now write it */ + xscom_write(chip->id, 0x201090A, psibar); +} + +void astbmc_early_init(void) +{ + /* Hostboot's device-tree isn't quite right yet */ + astbmc_fixup_dt(); + + /* Hostboot forgets to populate the PSI BAR */ + astbmc_fixup_psi_bar(); + + /* Send external interrupts to me */ + psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT); + + /* Initialize AHB accesses via AST2400 */ + ast_io_init(); + + /* + * Depending on which image we are running, it may be configuring + * the virtual UART or not. Check if VUART is enabled and use + * SIO if not. We also correct the configuration of VUART as some + * BMC images don't setup the interrupt properly + */ + if (ast_is_vuart1_enabled()) { + printf("PLAT: Using virtual UART\n"); + ast_disable_sio_uart1(); + ast_setup_vuart1(UART_IO_BASE, UART_LPC_IRQ); + } else { + printf("PLAT: Using SuperIO UART\n"); + ast_setup_sio_uart1(UART_IO_BASE, UART_LPC_IRQ); + } + + /* Similarily, some BMCs don't configure the BT interrupt properly */ + ast_setup_ibt(BT_IO_BASE, BT_LPC_IRQ); + + /* Setup UART and use it as console with interrupts */ + uart_init(true); +} + diff --git a/platforms/bmc/palmetto.c b/platforms/bmc/palmetto.c index ac6c4d9..99eb962 100644 --- a/platforms/bmc/palmetto.c +++ b/platforms/bmc/palmetto.c @@ -18,164 +18,9 @@ #include <skiboot.h> #include <device.h> #include <console.h> -#include <psi.h> #include <chip.h> -#include <xscom.h> -#include <ast.h> -#include <ipmi.h> -#include <bt.h> -#include "bmc.h" - -/* UART1 config */ -#define UART_IO_BASE 0x3f8 -#define UART_IO_COUNT 8 -#define UART_LPC_IRQ 4 - -/* BT config */ -#define BT_IO_BASE 0xe4 -#define BT_IO_COUNT 3 -#define BT_LPC_IRQ 10 - -static void palmetto_ext_irq(unsigned int chip_id __unused) -{ - uart_irq(); - bt_irq(); -} - -static void palmetto_init(void) -{ - /* Setup dummy console nodes */ - if (dummy_console_enabled()) - dummy_console_add_nodes(); - - /* Initialize AHB accesses via AST2400 */ - ast_io_init(); - - /* Initialize PNOR/NVRAM */ - pnor_init(); -} - -static void palmetto_fixup_dt_bt(struct dt_node *lpc) -{ - struct dt_node *bt; - char namebuf[32]; - - /* First check if the BT interface is already there */ - dt_for_each_child(lpc, bt) { - if (dt_node_is_compatible(bt, "bt")) - return; - } - - sprintf(namebuf, "ipmi-bt@i%x", BT_IO_BASE); - bt = dt_new(lpc, namebuf); - - dt_add_property_cells(bt, "reg", - 1, /* IO space */ - BT_IO_BASE, BT_IO_COUNT); - dt_add_property_strings(bt, "compatible", "ipmi-bt"); - - /* Mark it as reserved to avoid Linux trying to claim it */ - dt_add_property_strings(bt, "status", "reserved"); -} - -static void palmetto_fixup_dt_uart(struct dt_node *lpc) -{ - /* - * The official OF ISA/LPC binding is a bit odd, it prefixes - * the unit address for IO with "i". It uses 2 cells, the first - * one indicating IO vs. Memory space (along with bits to - * represent aliasing). - * - * We pickup that binding and add to it "2" as a indication - * of FW space. - */ - struct dt_node *uart; - char namebuf[32]; - - /* First check if the UART is already there */ - dt_for_each_child(lpc, uart) { - if (dt_node_is_compatible(uart, "ns16550")) - return; - } - - /* Otherwise, add a node for it */ - sprintf(namebuf, "serial@i%x", UART_IO_BASE); - uart = dt_new(lpc, namebuf); - - dt_add_property_cells(uart, "reg", - 1, /* IO space */ - UART_IO_BASE, UART_IO_COUNT); - dt_add_property_strings(uart, "compatible", - "ns16550", - "pnpPNP,501"); - dt_add_property_cells(uart, "clock-frequency", 1843200); - dt_add_property_cells(uart, "current-speed", 115200); - - /* - * This is needed by Linux for some obscure reasons, - * we'll eventually need to sanitize it but in the meantime - * let's make sure it's there - */ - dt_add_property_strings(uart, "device_type", "serial"); - - /* - * Add interrupt. This simulates coming from HostBoot which - * does not know our interrupt numbering scheme. Instead, it - * just tells us which chip the interrupt is wired to, it will - * be the PSI "host error" interrupt of that chip. For now we - * assume the same chip as the LPC bus is on. - */ - dt_add_property_cells(uart, "ibm,irq-chip-id", dt_get_chip_id(lpc)); -} - -static void palmetto_fixup_dt(void) -{ - struct dt_node *n, *primary_lpc = NULL; - - /* Find the primary LPC bus */ - dt_for_each_compatible(dt_root, n, "ibm,power8-lpc") { - if (!primary_lpc || dt_has_node_property(n, "primary", NULL)) - primary_lpc = n; - if (dt_has_node_property(n, "#address-cells", NULL)) - break; - } - - if (!primary_lpc) - return; - - /* Fixup the UART, that might be missing from HB */ - palmetto_fixup_dt_uart(primary_lpc); - - palmetto_fixup_dt_bt(primary_lpc); - - /* Force the dummy console for now */ - force_dummy_console(); -} - -static void palmetto_fixup_psi_bar(void) -{ - struct proc_chip *chip = next_chip(NULL); - uint64_t psibar; - - /* Read PSI BAR */ - if (xscom_read(chip->id, 0x201090A, &psibar)) { - prerror("PLAT: Error reading PSI BAR\n"); - return; - } - /* Already configured, bail out */ - if (psibar & 1) - return; - - /* Hard wire ... yuck */ - psibar = 0x3fffe80000001; - - printf("PLAT: Fixing up PSI BAR on chip %d BAR=%llx\n", - chip->id, psibar); - - /* Now write it */ - xscom_write(chip->id, 0x201090A, psibar); -} +#include "astbmc.h" static bool palmetto_probe(void) { @@ -190,66 +35,18 @@ static bool palmetto_probe(void) (!dt_node_is_compatible(dt_root, "ibm,palmetto"))) return false; - /* Hostboot's device-tree isn't quite right yet */ - palmetto_fixup_dt(); - - /* Hostboot forgets to populate the PSI BAR */ - palmetto_fixup_psi_bar(); - - /* Send external interrupts to me */ - psi_set_external_irq_policy(EXTERNAL_IRQ_POLICY_SKIBOOT); - - /* - * Depending on which image we are running, it may be configuring - * the virtual UART or not. Check if VUART is enabled and use - * SIO if not. We also correct the configuration of VUART as some - * BMC images don't setup the interrupt properly - */ - if (ast_is_vuart1_enabled()) { - printf("PLAT: Using virtual UART\n"); - ast_disable_sio_uart1(); - ast_setup_vuart1(UART_IO_BASE, UART_LPC_IRQ); - } else { - printf("PLAT: Using SuperIO UART\n"); - ast_setup_sio_uart1(UART_IO_BASE, UART_LPC_IRQ); - } - - /* Similarily, some BMCs don't configure the BT interrupt properly */ - ast_setup_ibt(BT_IO_BASE, BT_LPC_IRQ); - - /* Setup UART and use it as console with interrupts */ - uart_init(true); - - /* Register the BT interface with the IPMI layer */ - bt_init(); - ipmi_rtc_init(); - - /* As soon as IPMI is up, inform BMC we are in "S0" */ - ipmi_set_power_state(IPMI_PWR_SYS_S0_WORKING, IPMI_PWR_NOCHANGE); + /* Lot of common early inits here */ + astbmc_early_init(); return true; } -static int64_t palmetto_ipmi_power_down(uint64_t request) -{ - if (request != IPMI_CHASSIS_PWR_DOWN) { - prlog(PR_WARNING, "PLAT: unexpected shutdown request %llx\n", - request); - } - - return ipmi_chassis_control(request); -} - -static int64_t palmetto_ipmi_reboot(void) -{ - return ipmi_chassis_control(IPMI_CHASSIS_HARD_RESET); -} DECLARE_PLATFORM(palmetto) = { .name = "Palmetto", .probe = palmetto_probe, - .init = palmetto_init, - .external_irq = palmetto_ext_irq, - .cec_power_down = palmetto_ipmi_power_down, - .cec_reboot = palmetto_ipmi_reboot, + .init = astbmc_init, + .external_irq = astbmc_ext_irq, + .cec_power_down = astbmc_ipmi_power_down, + .cec_reboot = astbmc_ipmi_reboot, }; diff --git a/platforms/bmc/pnor.c b/platforms/bmc/pnor.c index 878615d..f6e7a5d 100644 --- a/platforms/bmc/pnor.c +++ b/platforms/bmc/pnor.c @@ -21,9 +21,9 @@ #include <opal.h> #include <libflash/libflash.h> #include <libflash/libffs.h> +#include <ast.h> -#include "bmc.h" -#include "ast.h" +#include "astbmc.h" static struct spi_flash_ctrl *pnor_ctrl; static struct flash_chip *pnor_chip; |