From c0ef33fc06bf954dadc429def13ec3a01252ff3d Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Mon, 7 Aug 2023 23:27:37 -0400 Subject: mb/x11-lga1151-series: Add x11ssw-f MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This board is similar to x11ssm-f but has a proprietary form factor with NVMe and a single x16 slot (potentially bifurcated to 2x x8) and a x4 slot. Change-Id: I53a0b6012ae64cf1ba4b625f11aaf771637307f3 Signed-off-by: Kieran Kunhya Reviewed-on: https://review.coreboot.org/c/coreboot/+/77610 Tested-by: build bot (Jenkins) Reviewed-by: Michael Niewöhner --- .../supermicro/x11-lga1151-series/Kconfig | 3 + .../supermicro/x11-lga1151-series/Kconfig.name | 4 + .../variants/x11ssw-f/board_info.txt | 7 + .../x11-lga1151-series/variants/x11ssw-f/gpio.c | 230 +++++++++++++++++++++ .../variants/x11ssw-f/gpio_early.c | 22 ++ .../variants/x11ssw-f/overridetree.cb | 127 ++++++++++++ 6 files changed, 393 insertions(+) create mode 100644 src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/board_info.txt create mode 100644 src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio.c create mode 100644 src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio_early.c create mode 100644 src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/overridetree.cb (limited to 'src/mainboard/supermicro') diff --git a/src/mainboard/supermicro/x11-lga1151-series/Kconfig b/src/mainboard/supermicro/x11-lga1151-series/Kconfig index d6183421a8..862c0b4b20 100644 --- a/src/mainboard/supermicro/x11-lga1151-series/Kconfig +++ b/src/mainboard/supermicro/x11-lga1151-series/Kconfig @@ -29,6 +29,7 @@ config MAINBOARD_PART_NUMBER default "X11SSH-TF" if BOARD_SUPERMICRO_X11SSH_TF default "X11SSM-F" if BOARD_SUPERMICRO_X11SSM_F default "X11SSH-F/LN4F" if BOARD_SUPERMICRO_X11SSH_F + default "X11SSW-F" if BOARD_SUPERMICRO_X11SSW_F config MAINBOARD_DIR default "supermicro/x11-lga1151-series" @@ -37,6 +38,7 @@ config VARIANT_DIR default "x11ssh-tf" if BOARD_SUPERMICRO_X11SSH_TF default "x11ssm-f" if BOARD_SUPERMICRO_X11SSM_F default "x11ssh-f" if BOARD_SUPERMICRO_X11SSH_F + default "x11ssw-f" if BOARD_SUPERMICRO_X11SSW_F config OVERRIDE_DEVICETREE default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" @@ -85,5 +87,6 @@ config SUPERMICRO_BOARDID default "0896" if BOARD_SUPERMICRO_X11SSM_F default "089C" if BOARD_SUPERMICRO_X11SSH_TF default "0884" if BOARD_SUPERMICRO_X11SSH_F + default "089B" if BOARD_SUPERMICRO_X11SSW_F endif # BOARD_SUPERMICRO_BASEBOARD_X11_LGA1151_SERIES diff --git a/src/mainboard/supermicro/x11-lga1151-series/Kconfig.name b/src/mainboard/supermicro/x11-lga1151-series/Kconfig.name index 0f488a9683..cdefa73f12 100644 --- a/src/mainboard/supermicro/x11-lga1151-series/Kconfig.name +++ b/src/mainboard/supermicro/x11-lga1151-series/Kconfig.name @@ -9,3 +9,7 @@ config BOARD_SUPERMICRO_X11SSM_F config BOARD_SUPERMICRO_X11SSH_F bool "X11SSH-F/LN4F" select BOARD_SUPERMICRO_BASEBOARD_X11_LGA1151_SERIES + +config BOARD_SUPERMICRO_X11SSW_F + bool "X11SSW-F" + select BOARD_SUPERMICRO_BASEBOARD_X11_LGA1151_SERIES diff --git a/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/board_info.txt b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/board_info.txt new file mode 100644 index 0000000000..006c2ec8b1 --- /dev/null +++ b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/board_info.txt @@ -0,0 +1,7 @@ +Category: server +Vendor name: Supermicro +Board name: X11SSW-F +Board URL: https://www.supermicro.com/en/products/motherboard/X11SSW-F +ROM protocol: SPI +ROM socketed: n +Flashrom support: y diff --git a/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio.c b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio.c new file mode 100644 index 0000000000..e37e008285 --- /dev/null +++ b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +static const struct pad_config gpio_table[] = { + /* GPIO Group GPP_A */ + PAD_CFG_NF(GPP_A0, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A1, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A2, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A3, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A4, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A5, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A7, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A8, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A9, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A10, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A11, NONE, DEEP, NF1), + PAD_NC(GPP_A12, NONE), + PAD_CFG_NF(GPP_A13, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A14, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A15, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A16, NONE, DEEP, NF1), + PAD_NC(GPP_A17, NONE), + PAD_NC(GPP_A18, NONE), + /* GPP_A19 - RESERVED */ + PAD_NC(GPP_A20, NONE), + PAD_NC(GPP_A21, NONE), + PAD_NC(GPP_A22, NONE), + PAD_NC(GPP_A23, NONE), + PAD_CFG_GPO(GPP_B0, 1, DEEP), + PAD_CFG_GPO(GPP_B1, 1, DEEP), + PAD_NC(GPP_B2, NONE), + PAD_NC(GPP_B3, NONE), + PAD_NC(GPP_B4, NONE), + PAD_NC(GPP_B5, NONE), + PAD_NC(GPP_B6, NONE), + PAD_NC(GPP_B7, NONE), + PAD_NC(GPP_B8, NONE), + PAD_NC(GPP_B9, NONE), + PAD_NC(GPP_B10, NONE), + PAD_CFG_GPO(GPP_B11, 0, DEEP), + PAD_CFG_NF(GPP_B12, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_B13, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_B14, NONE, PLTRST, NF1), + PAD_NC(GPP_B15, NONE), + PAD_NC(GPP_B16, NONE), + PAD_NC(GPP_B17, NONE), + PAD_NC(GPP_B18, NONE), + PAD_NC(GPP_B19, NONE), + PAD_CFG_GPO(GPP_B20, 1, PLTRST), + PAD_NC(GPP_B21, NONE), + PAD_NC(GPP_B22, NONE), + PAD_CFG_NF(GPP_B23, NONE, DEEP, NF2), + + /* GPIO Group GPP_C */ + /* GPP_C0 - RESERVED */ + /* GPP_C1 - RESERVED */ + PAD_NC(GPP_C2, NONE), + /* GPP_C3 - RESERVED */ + /* GPP_C4 - RESERVED */ + PAD_CFG_GPO(GPP_C5, 1, DEEP), + /* GPP_C6 - RESERVED */ + /* GPP_C7 - RESERVED */ + PAD_NC(GPP_C8, NONE), + PAD_NC(GPP_C9, NONE), + PAD_NC(GPP_C10, NONE), + PAD_NC(GPP_C11, NONE), + PAD_NC(GPP_C12, NONE), + PAD_NC(GPP_C13, NONE), + PAD_NC(GPP_C14, NONE), + PAD_NC(GPP_C15, NONE), + PAD_NC(GPP_C16, NONE), + PAD_NC(GPP_C17, NONE), + PAD_NC(GPP_C18, NONE), + PAD_NC(GPP_C19, NONE), + PAD_NC(GPP_C20, NONE), + PAD_NC(GPP_C21, NONE), + PAD_CFG_GPI_SMI(GPP_C22, UP_20K, DEEP, EDGE_SINGLE, NONE), + PAD_NC(GPP_C23, NONE), + + /* GPIO Group GPP_D */ + PAD_NC(GPP_D0, NONE), + PAD_CFG_GPO(GPP_D1, 1, DEEP), + PAD_CFG_GPI_NMI(GPP_D2, UP_20K, DEEP, EDGE_SINGLE, NONE), + PAD_NC(GPP_D3, NONE), + PAD_CFG_GPO(GPP_D4, 0, PLTRST), + PAD_NC(GPP_D5, NONE), + PAD_NC(GPP_D6, NONE), + PAD_NC(GPP_D7, NONE), + PAD_NC(GPP_D8, NONE), + PAD_NC(GPP_D9, NONE), + PAD_NC(GPP_D10, NONE), + PAD_NC(GPP_D11, NONE), + PAD_NC(GPP_D12, NONE), + PAD_NC(GPP_D13, NONE), + PAD_NC(GPP_D14, NONE), + PAD_NC(GPP_D15, NONE), + PAD_NC(GPP_D16, NONE), + PAD_NC(GPP_D17, NONE), + PAD_CFG_GPO(GPP_D18, 1, PLTRST), + PAD_CFG_GPO(GPP_D19, 1, PLTRST), + PAD_NC(GPP_D20, NONE), + PAD_CFG_GPO(GPP_D21, 0, DEEP), + PAD_NC(GPP_D22, NONE), + PAD_NC(GPP_D23, NONE), + + /* GPIO Group GPP_E */ + PAD_NC(GPP_E0, NONE), + PAD_NC(GPP_E1, NONE), + PAD_NC(GPP_E2, NONE), + PAD_NC(GPP_E3, NONE), + PAD_NC(GPP_E4, NONE), + PAD_NC(GPP_E5, NONE), + PAD_CFG_GPI_NMI(GPP_E6, UP_20K, PLTRST, EDGE_SINGLE, NONE), + PAD_NC(GPP_E7, NONE), + PAD_CFG_NF(GPP_E8, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_E9, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_E10, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_E11, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_E12, NONE, DEEP, NF1), + + /* GPIO Group GPP_F */ + PAD_NC(GPP_F0, NONE), + PAD_NC(GPP_F1, NONE), + PAD_NC(GPP_F2, NONE), + PAD_NC(GPP_F3, NONE), + PAD_NC(GPP_F4, NONE), + PAD_CFG_GPI_APIC_HIGH(GPP_F5, NONE, PLTRST), + PAD_CFG_GPO(GPP_F6, 1, PLTRST), + PAD_CFG_GPO(GPP_F7, 1, PLTRST), + PAD_CFG_GPO(GPP_F8, 1, PLTRST), + PAD_NC(GPP_F9, NONE), + PAD_CFG_NF(GPP_F10, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_F11, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_F12, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_F13, NONE, DEEP, NF1), + PAD_NC(GPP_F14, NONE), + PAD_CFG_NF(GPP_F15, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_F16, NONE, DEEP, NF1), + PAD_NC(GPP_F17, NONE), + PAD_NC(GPP_F18, NONE), + PAD_NC(GPP_F19, NONE), + PAD_NC(GPP_F20, NONE), + PAD_NC(GPP_F21, NONE), + PAD_NC(GPP_F22, NONE), + PAD_CFG_GPO(GPP_F23, 0, RSMRST), + PAD_NC(GPP_G0, NONE), + PAD_NC(GPP_G1, NONE), + PAD_NC(GPP_G2, NONE), + PAD_NC(GPP_G3, NONE), + PAD_NC(GPP_G4, NONE), + PAD_NC(GPP_G5, NONE), + PAD_NC(GPP_G6, NONE), + PAD_NC(GPP_G7, NONE), + PAD_NC(GPP_G8, NONE), + PAD_NC(GPP_G9, NONE), + PAD_NC(GPP_G10, NONE), + PAD_NC(GPP_G11, NONE), + PAD_NC(GPP_G12, NONE), + PAD_NC(GPP_G13, NONE), + PAD_NC(GPP_G14, NONE), + PAD_NC(GPP_G15, NONE), + PAD_NC(GPP_G16, NONE), + PAD_NC(GPP_G17, NONE), + PAD_CFG_NF(GPP_G18, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_G19, NONE, DEEP, NF1), + PAD_NC(GPP_G20, NONE), + PAD_NC(GPP_G21, NONE), + PAD_NC(GPP_G22, NONE), + PAD_NC(GPP_G23, NONE), + PAD_CFG_GPO(GPP_H0, 1, DEEP), + PAD_NC(GPP_H1, NONE), + PAD_CFG_GPO(GPP_H2, 1, DEEP), + PAD_CFG_NF(GPP_H3, NONE, DEEP, NF1), + PAD_NC(GPP_H4, NONE), + PAD_CFG_GPO(GPP_H5, 1, PLTRST), + PAD_CFG_GPO(GPP_H6, 1, PLTRST), + PAD_CFG_GPO(GPP_H7, 1, PLTRST), + PAD_CFG_GPO(GPP_H8, 1, PLTRST), + PAD_CFG_GPO(GPP_H9, 1, PLTRST), + PAD_CFG_NF(GPP_H10, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_H11, NONE, DEEP, NF1), + PAD_NC(GPP_H12, NONE), + PAD_CFG_NF(GPP_H13, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_H14, NONE, DEEP, NF1), + PAD_NC(GPP_H15, NONE), + PAD_CFG_NF(GPP_H16, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_H17, NONE, DEEP, NF1), + PAD_NC(GPP_H18, NONE), + PAD_CFG_GPO(GPP_H19, 1, PLTRST), + PAD_CFG_GPO(GPP_H20, 1, PLTRST), + PAD_CFG_GPO(GPP_H21, 1, PLTRST), + PAD_CFG_GPO(GPP_H22, 1, PLTRST), + PAD_CFG_GPO(GPP_H23, 1, PLTRST), + + /* GPIO Group GPD */ + PAD_NC(GPD0, NONE), + PAD_NC(GPD1, NONE), + PAD_CFG_NF(GPD2, NONE, PWROK, NF1), + PAD_CFG_NF(GPD3, NONE, PWROK, NF1), + PAD_CFG_NF(GPD4, NONE, PWROK, NF1), + PAD_CFG_NF(GPD5, NONE, PWROK, NF1), + PAD_CFG_NF(GPD6, NONE, PWROK, NF1), + PAD_NC(GPD7, NONE), + PAD_CFG_NF(GPD8, NONE, PWROK, NF1), + PAD_NC(GPD9, NONE), + PAD_NC(GPD10, NONE), + PAD_NC(GPD11, NONE), + + /* GPIO Group GPP_I */ + PAD_CFG_NF(GPP_I0, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I1, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I2, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I3, NONE, PLTRST, NF1), + PAD_NC(GPP_I4, NONE), + PAD_CFG_NF(GPP_I5, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I6, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I7, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I8, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I9, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_I10, NONE, DEEP, NF1), +}; + +void mainboard_configure_gpios(void) +{ + gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); +} diff --git a/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio_early.c b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio_early.c new file mode 100644 index 0000000000..3ea21e0321 --- /dev/null +++ b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/gpio_early.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +static const struct pad_config early_gpio_table[] = { + /* Early LPC configuration in romstage */ + PAD_CFG_NF(GPP_A1, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A2, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A3, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A4, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A5, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A8, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A9, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_A10, NONE, DEEP, NF1), +}; + +void mainboard_configure_early_gpios(void) +{ + gpio_configure_pads(early_gpio_table, ARRAY_SIZE(early_gpio_table)); +} diff --git a/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/overridetree.cb b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/overridetree.cb new file mode 100644 index 0000000000..6984b834ed --- /dev/null +++ b/src/mainboard/supermicro/x11-lga1151-series/variants/x11ssw-f/overridetree.cb @@ -0,0 +1,127 @@ +chip soc/intel/skylake + + # GPE configuration + # Note that GPE events called out in ASL code rely on this + # route. i.e. If this route changes then the affected GPE + # offset bits also need to be changed. + register "gpe0_dw0" = "GPP_B" + register "gpe0_dw1" = "GPP_D" + register "gpe0_dw2" = "GPP_E" + + register "gen1_dec" = "0x007c0a01" # Super IO SWC + register "gen2_dec" = "0x000c0ca1" # IPMI KCS + + # Additional FSP Configuration + # This board has an IGD with no output. + register "PrimaryDisplay" = "Display_Auto" + + # USB configuration + # NB: Overcurrent OCx values untested + # USB2/3 + register "usb2_ports[8]" = "USB2_PORT_MID(OC0)" + register "usb2_ports[9]" = "USB2_PORT_MID(OC0)" + + # ? + register "usb2_ports[14]" = "USB2_PORT_MID(OC0)" + register "usb2_ports[15]" = "USB2_PORT_MID(OC0)" + + # USB4/5 + register "usb2_ports[4]" = "USB2_PORT_MID(OC1)" + register "usb2_ports[5]" = "USB2_PORT_MID(OC1)" + + # USB0/1 + register "usb2_ports[2]" = "USB2_PORT_MID(OC2)" + register "usb2_ports[3]" = "USB2_PORT_MID(OC2)" + + # USB6/7 (USB3.0) + register "usb2_ports[0]" = "USB2_PORT_MID(OC3)" + register "usb2_ports[1]" = "USB2_PORT_MID(OC3)" + register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC3)" + register "usb3_ports[1]" = "USB3_PORT_DEFAULT(OC3)" + + # USB8 (USB3.0) + register "usb2_ports[12]" = "USB2_PORT_MID(OC4)" + register "usb3_ports[2]" = "USB3_PORT_DEFAULT(OC4)" + + # USB9/10 (USB3.0) + register "usb2_ports[10]" = "USB2_PORT_MID(OC5)" + register "usb2_ports[11]" = "USB2_PORT_MID(OC5)" + register "usb3_ports[3]" = "USB3_PORT_DEFAULT(OC5)" + register "usb3_ports[4]" = "USB3_PORT_DEFAULT(OC5)" + + + # IPMI USB HUB + register "usb2_ports[13]" = "USB2_PORT_MID(OC_SKIP)" + + device domain 0 on + device pci 01.0 on + smbios_slot_desc "SlotTypePciExpressGen3X16" "SlotLengthLong" "CPU SLOT1 PCI-E 3.0 X16" "SlotDataBusWidth16X" + end # CPU PCIE Slot JSXB1B + device pci 1c.0 on # PCI Express Port 1 + register "PcieRpEnable[0]" = "1" + device pci 00.0 on end # GbE + end + device pci 1c.1 on # PCI Express Port 2 + register "PcieRpEnable[1]" = "1" + device pci 00.0 on end # GbE + end + device pci 1c.4 on # PCI Express Port 5 + register "PcieRpEnable[4]" = "1" + smbios_slot_desc "SlotTypeM2Socket3" "SlotLengthOther" "M.2 2280" "SlotDataBusWidth4X" + end + device pci 1d.0 on # PCI Express Port 9 (Slot JSXB2) + register "PcieRpEnable[8]" = "1" + smbios_slot_desc "SlotTypePciExpressGen3X4" "SlotLengthShort" "PCH SLOT2 PCI-E 3.0 X4(IN X8)" "SlotDataBusWidth4X" + end + device pci 1d.4 on # PCI Express Port 13 + register "PcieRpEnable[12]" = "1" + device pci 00.0 on # Aspeed PCI Bridge + device pci 00.0 on end # Aspeed 2400 VGA + end + end + device pci 1f.0 on # LPC Interface + chip drivers/ipmi + # On cold boot it takes a while for the BMC to start the IPMI service + register "wait_for_bmc" = "1" + register "bmc_boot_timeout" = "60" + device pnp ca2.0 on end # IPMI KCS + end + chip superio/common + device pnp 2e.0 on + chip superio/aspeed/ast2400 + device pnp 2e.2 on # SUART1 + io 0x60 = 0x3f8 + irq 0x70 = 4 + drq 0xf0 = 0x00 + end + device pnp 2e.3 on # SUART2 + io 0x60 = 0x2f8 + irq 0x70 = 3 + drq 0xf0 = 0x00 + end + device pnp 2e.4 on # SWC + io 0x60 = 0xa00 + io 0x62 = 0xa10 + io 0x64 = 0xa20 + io 0x66 = 0xa30 + irq 0x70 = 0x00 + end + device pnp 2e.5 off end # KBC + device pnp 2e.7 on # GPIO + irq 0x70 = 0x00 + end + device pnp 2e.b off end # SUART3 + device pnp 2e.c off end # SUART4 + device pnp 2e.d on # iLPC2AHB + irq 0x70 = 0x00 + end + device pnp 2e.e on # Mailbox + io 0x60 = 0xa40 + irq 0x70 = 0x00 + end + end + end + end + end + end +end -- cgit v1.2.3