Index: rkpciephy.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/rkpciephy.c,v retrieving revision 1.1 diff -u -p -r1.1 rkpciephy.c --- rkpciephy.c 19 Mar 2023 11:17:16 -0000 1.1 +++ rkpciephy.c 23 Mar 2023 00:31:45 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: rkpciephy.c,v 1.1 2023/03/19 11:17:16 kettenis Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2023 Mark Kettenis * @@ -15,6 +15,20 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* + * Rockchip PCIe 3.0 PHY driver + * + * The RK3568 PCIe PHY provides 2 lanes of PCIe connectivity between + * controllers and devices. The 2x PCIe lanes can be configured to + * connect to a single controller, or split (bifurcated) into a pair + * of 1x PCIe lanes connected to 2 controllers. + * + * The configuration of bifurcation depends on the "data-lanes" int + * array property from the device tree. If the lanes are enabled + * (not 0), and different (ie, mapped to different controllers), then + * bifurcation should be configured. + */ + #include #include #include @@ -29,18 +43,21 @@ #include /* GRF registers */ -#define GRF_PCIE30PHY_CON(idx) ((idx) * 4) -/* CON1 */ -#define GRF_PCIE30PHY_DA_OCM 0x80008000 -/* CON5 */ -#define GRF_PCIE30PHY_LANE0_LINK_NUM_MASK (0xf << 16) -#define GRF_PCIE30PHY_LANE0_LINK_NUM_SHIFT 0 + +#define RK3568_PCIE30PHY_CON1 0x04 +#define RK3568_PCIE30PHY_CON6 0x18 +#define RK3568_PCIE30PHY_CON9 0x24 +#define RK3568_PCIE30PHY_STATUS0 0x80 + +/* CON1 and CON9 */ +#define RK3568_PCIE30PHY_DA_OCM 0x80008000 + /* CON6 */ -#define GRF_PCIE30PHY_LANE1_LINK_NUM_MASK (0xf << 16) -#define GRF_PCIE30PHY_LANE1_LINK_NUM_SHIFT 0 +#define RK3568_PCIE30PHY_WR_EN (0xf << 16) +#define RK3568_PCIE30PHY_BIFURCATION (0x1 << 0) + /* STATUS0 */ -#define GRF_PCIE30PHY_STATUS0 0x80 -#define GRF_PCIE30PHY_SRAM_INIT_DONE (1 << 14) +#define RK3568_PCIE30PHY_SRAM_INIT_DONE (1 << 14) struct rkpciephy_softc { struct device sc_dev; @@ -104,27 +121,26 @@ rkpciephy_enable(void *cookie, uint32_t reset_assert(node, "phy"); delay(1); - regmap_write_4(rm, GRF_PCIE30PHY_CON(9), GRF_PCIE30PHY_DA_OCM); + regmap_write_4(rm, RK3568_PCIE30PHY_CON9, RK3568_PCIE30PHY_DA_OCM); OF_getpropintarray(node, "data-lanes", data_lanes, sizeof(data_lanes)); - if (data_lanes[0] > 0) { - regmap_write_4(rm, GRF_PCIE30PHY_CON(5), - GRF_PCIE30PHY_LANE0_LINK_NUM_MASK | - (data_lanes[0] - 1) << GRF_PCIE30PHY_LANE0_LINK_NUM_SHIFT); - } - if (data_lanes[1] > 0) { - regmap_write_4(rm, GRF_PCIE30PHY_CON(6), - GRF_PCIE30PHY_LANE1_LINK_NUM_MASK | - (data_lanes[1] - 1) << GRF_PCIE30PHY_LANE1_LINK_NUM_SHIFT); + if ((data_lanes[0] > 0 && data_lanes[1] > 0) && + (data_lanes[0] != data_lanes[1])) { + /* bifurcation enabled */ + regmap_write_4(rm, RK3568_PCIE30PHY_CON6, + RK3568_PCIE30PHY_WR_EN | RK3568_PCIE30PHY_BIFURCATION); + regmap_write_4(rm, RK3568_PCIE30PHY_CON1, + RK3568_PCIE30PHY_DA_OCM); + } else { + regmap_write_4(rm, RK3568_PCIE30PHY_CON6, + RK3568_PCIE30PHY_WR_EN); } - if (data_lanes[0] > 1 || data_lanes[1] > 1) - regmap_write_4(rm, GRF_PCIE30PHY_CON(1), GRF_PCIE30PHY_DA_OCM); reset_deassert(node, "phy"); for (timo = 500; timo > 0; timo--) { - stat = regmap_read_4(rm, GRF_PCIE30PHY_STATUS0); - if (stat & GRF_PCIE30PHY_SRAM_INIT_DONE) + stat = regmap_read_4(rm, RK3568_PCIE30PHY_STATUS0); + if (stat & RK3568_PCIE30PHY_SRAM_INIT_DONE) break; delay(100); }