/* * Copyright 2020 Scalys B.V. * opensource@scalys.com * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include "dragonfruit.h" /* * 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 MPC85XX_GPIO_NR(2, 25) #define MUX_SER2_3_SEL MPC85XX_GPIO_NR(2, 26) #define MUX_SER5_6_SEL MPC85XX_GPIO_NR(2, 27) #define SERDES_CLK_OE MPC85XX_GPIO_NR(2, 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. * * Note/TODO: SERDES PLL2 must be powered down using SRDS_PLL_PD_S1 when * SRDS_PRTCL_S1 is any of the following values: 0x00, 0x40, 0x60, 0x67, * 0x85, 0x87, 0x8D, 0x45. * */ switch(serdes_config){ #if defined(CONFIG_PPC_T1040) || defined(CONFIG_PPC_T1020) /* With Ethernet Switch (T1040/T1020 only) */ //case 0x69: //case 0x67: /* See note 2 */ case 0x60: /* See note 2 */ mux_config = SER_5_6_SLOT4 | SER_2_3_SFP23 | SER_0_1_SFP01; break; //case 0x8D: /* See note 2 */ //case 0x8E: //case 0x66: case 0x89: /* A: unused; B: sg.s3; C: sg.s1; D: sg.s2; * E: PCIe2 (5/2.5G); F: PCIe3 (5/2.5G); G: unused; H: SATA1(3/1.5G) */ mux_config = SER_5_6_SLOT23 | SER_2_3_SFP23 | SER_0_1_SFP01; break; case 0x81: /* A: Unused; B: sg.m3/sg.s3; C: sg.m1/sg.s1; D: sg.m2/sg.s2; * E: PCIe2 (5/2.5G); F: unused; G: unused; H: SATA1(3/1.5G) */ //case 0x88: /* Option has been verified to work, but is not officially supported */ /* A: Unused; B: sg.m3; C: sg.m1; D: sg.m2; * E: PCIe2 (5/2.5G); F: unused; G: SATA.2(3/1.5G); H: SATA1(3/1.5G) */ mux_config = SER_5_6_SLOT4 | SER_2_3_SFP23 | SER_0_1_SFP01; break; #elif defined(CONFIG_PPC_T1042) || defined(CONFIG_PPC_T1022) case 0x86: /* A: Unused; B: sg.m3; C: sg.m1; D: sg.m2; * E: PCIe2 (5/2.5G); F: PCIe3 (5/2.5G); G: PCIe4 (5/2.5G); H: SATA1(3/1.5G) */ mux_config = SER_5_6_SLOT23 | SER_2_3_SFP23 | SER_0_1_SFP01; break; case 0x81: /* A: Unused; B: sg.m3/sg.s3; C: sg.m1/sg.s1; D: sg.m2/sg.s2; * E: PCIe2 (5/2.5G); F: unused; G: unused; H: SATA1(3/1.5G) */ case 0x88: /* A: Unused; B: sg.m3; C: sg.m1; D: sg.m2; * E: PCIe2 (5/2.5G); F: unused; G: SATA.2(3/1.5G); H: SATA1(3/1.5G) */ mux_config = SER_5_6_SLOT4 | SER_2_3_SFP23 | SER_0_1_SFP01; break; case 0x06: /* A-D: PCIe1 (5/2.5G); * E: PCIe2 (5/2.5G); F: PCIe3 (5/2.5G); G: PCIe4 (5/2.5G); H: SATA.1 (3/1.5G) */ mux_config = SER_5_6_SLOT23 | SER_2_3_SLOT1 | SER_0_1_SLOT1; break; //case 0x08: //case 0x87: /* See note 2 */ //case 0xA7: //case 0xAA: //case 0xA2: //case 0x45: //case 0x40: /* See note 2 */ //case 0x8E: //case 0x85: /* See note 2 */ //case 0xA5: //case 0x00: /* See note 2 */ #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) { gpio_direction_output(MUX_SER0_1_SEL, 1); printf("A: SFP+ slot 0 (T2081 only)\n"); printf("B: SFP+ slot 1 (T2081 only)\n"); } else { gpio_direction_output(MUX_SER0_1_SEL, 0); printf("A: PCIe slot 1 on lane 0\n"); printf("B: PCIe slot 1 on lane 1\n"); } if ((mux_config & 2) != 0) { gpio_direction_output(MUX_SER2_3_SEL, 1); printf("C: SFP slot 2\n"); printf("D: SFP slot 3\n"); } else { gpio_direction_output(MUX_SER2_3_SEL, 0); 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) { gpio_direction_output(MUX_SER5_6_SEL, 1); printf("F: PCIe slot 2 on lane 0\n"); printf("G: PCIe slot 3 on lane 0\n"); } else { gpio_direction_output(MUX_SER5_6_SEL, 0); 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 */ gpio_direction_output(SERDES_CLK_OE, 1); return ret; }