/* * Copyright 2017 Scalys B.V. * opensource@scalys.com * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include "dragonfruit.h" uint32_t *gpio2_gpdir = (uint32_t *) 0xffe131000; uint32_t *gpio2_gpdat = (uint32_t *) 0xffe131008; uint32_t regval; /* * SERDER MUX Configuration pins: * IFC_A25 : GPIO2_25 : SERDES_CLK_ MUX_SER0_1_SEL * IFC_A26 : GPIO2_26 : SERDES_CLK_ MUX_SER2_3_SEL * IFC_A27 : GPIO2_27 : SERDES_CLK_ MUX_SER5_6_SEL */ #define MUX_SER0_1_SEL (0x80000000 >> 25) #define MUX_SER2_3_SEL (0x80000000 >> 26) #define MUX_SER5_6_SEL (0x80000000 >> 27) #define SERDES_CLK_OE (0x80000000 >> 29) /* * MUX_SER0_1_SEL * 0: SERDES A => Slot1, lane 0 * SERDES B => Slot1, lane 1 * 1: SERDES A => CS4315 retimer => SFP+ 0 * SERDES B => CS4315 retimer => SFP+ 1 */ #define SER_0_1_SLOT1 0 #define SER_0_1_SFP01 1 /* * MUX_SER2_3_SEL * 0: SERDES C => Slot1, lane 2 * SERDES D => Slot1, lane 3 * 1: SERDES C => QSFP+ 2 * SERDES D => QSFP+ 3 */ #define SER_2_3_SLOT1 0 #define SER_2_3_SFP23 2 /* * SERDES E => Slot 4, lane 0 */ /* MUX_SER5_6_SEL * 0: SERDES F => SLOT4, lane 1 * SERDES G => SLOT4, lane 2 * 1: SERDES F => SLOT2 * SERDES G => SLOT3 */ #define SER_5_6_SLOT4 0 #define SER_5_6_SLOT23 4 /* * SERDES H => Slot 4, lane 3 */ int scalys_carrier_setup_muxing(int serdes_config) { int ret = 0; int mux_config = 0; ret = gpio_request(MUX_SER0_1_SEL, "mux_ser0_1_sel"); if (ret != 0) { printf("gpio request failed(%i)\n", ret); } gpio_request(MUX_SER2_3_SEL, "mux_ser2_3_sel"); gpio_request(MUX_SER5_6_SEL, "mux_ser5_6_sel"); gpio_request(SERDES_CLK_OE, "serdes_clk_oe"); /* * SERDES options for each target as supported by the dragonfruit * carrier board. Refer to the QorIQ reference manual for the SERDES options table * and all relevant information. * * Note: The SERDES lanes A&B, C&D, and F&G can only be switched * as pairs using the multiplexers. Which means some SERDES options are only partly usable. * * * T2081 has 8 SERDES lanes at up to 10GHz (ie. SERDES 2 configurations are DNC) * */ switch(serdes_config){ #if defined(CONFIG_PPC_T2081) /* TODO: test all major cases */ case 0x6E: case 0xC8: case 0xD6: case 0x6C: mux_config = SER_5_6_SLOT4 | SER_2_3_SFP23 | SER_0_1_SFP01; break; case 0xAA: /* Note 2 */ mux_config = SER_5_6_SLOT4 | SER_2_3_SLOT1 | SER_0_1_SLOT1; break; case 0xBC: /* Note 2 */ mux_config = SER_5_6_SLOT4 | SER_2_3_SFP23 | SER_0_1_SLOT1; break; case 0xCA: case 0xF2: /* Note 2 */ case 0xF8: case 0xFA: case 0x70: mux_config = SER_5_6_SLOT23 | SER_2_3_SFP23 | SER_0_1_SFP01; break; case 0xDE: /* Note 2 */ case 0xE0: /* Note 2 */ mux_config = SER_5_6_SLOT23 | SER_2_3_SLOT1 | SER_0_1_SLOT1; break; #else #error "Invalid or unspecified target cpu for dragonfruit carrier board!" #endif default: printf("Unsupported SERDES configuration (%02x) detected for dragonfruit carrier board (Warning: Using default multiplexer settings)!\n", serdes_config); } printf("-----------------------------------------------------\n"); printf("Serdes lane configuration:\n"); if ((mux_config & 1) > 0) { regval = in_be32(gpio2_gpdat); regval |= MUX_SER0_1_SEL; out_be32(gpio2_gpdat, regval); printf("A: SFP slot 0 (T2081 only)\n"); printf("B: SFP slot 1\n"); } else { regval = in_be32(gpio2_gpdat); regval &= ~MUX_SER0_1_SEL; out_be32(gpio2_gpdat, regval); printf("A: PCIe slot 1 on lane 0\n"); printf("B: PCIe slot 1 on lane 1\n"); } if ((mux_config & 2) > 0) { regval = in_be32(gpio2_gpdat); regval |= MUX_SER2_3_SEL; out_be32(gpio2_gpdat, regval); printf("C: SFP slot 2\n"); printf("D: SFP slot 3\n"); } else { regval = in_be32(gpio2_gpdat); regval &= ~MUX_SER2_3_SEL; out_be32(gpio2_gpdat, regval); printf("C: PCIe slot 1 on lane 2\n"); printf("D: PCIe slot 1 on lane 3\n"); } printf("E: PCIe slot 4 on lane 0\n"); if ((mux_config & 4) > 0) { regval = in_be32(gpio2_gpdat); regval |= MUX_SER5_6_SEL; out_be32(gpio2_gpdat, regval); printf("F: PCIe slot 2 on lane 0\n"); printf("G: PCIe slot 3 on lane 0\n"); } else { regval = in_be32(gpio2_gpdat); regval &= ~MUX_SER5_6_SEL; out_be32(gpio2_gpdat, regval); printf("F: PCIe slot 4 on lane 1\n"); printf("G: PCIe slot 4 on lane 2\n"); } printf("H: PCIe slot 4 on lane 3\n"); printf("-----------------------------------------------------\n"); /* Enable serdes clock */ regval = in_be32(gpio2_gpdat); regval |= SERDES_CLK_OE; out_be32(gpio2_gpdat, regval); /* Set outputs to output mode */ regval = in_be32(gpio2_gpdir); regval |= (MUX_SER0_1_SEL | MUX_SER2_3_SEL | MUX_SER5_6_SEL | SERDES_CLK_OE); out_be32(gpio2_gpdir, regval); return ret; }