From: kettenis Date: Sun, 19 Mar 2023 11:17:16 +0000 (+0000) Subject: Add rkpciephy(4), ad friver for the PCIe 3.0 PHY dound on the RK356x. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a4de7ae7e622055c475f9d250662f21f45a7fb7c;p=openbsd Add rkpciephy(4), ad friver for the PCIe 3.0 PHY dound on the RK356x. The driver in principle supports bifurcation but this is (largely) untested. ok dlg@ --- diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index bb281966fee..0546228a185 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,4 +1,4 @@ -# $OpenBSD: files.fdt,v 1.181 2023/03/16 10:33:44 kettenis Exp $ +# $OpenBSD: files.fdt,v 1.182 2023/03/19 11:17:16 kettenis Exp $ # # Config file and device description for machine-independent FDT code. # Included by ports that need it. @@ -378,17 +378,21 @@ device rkiis attach rkiis at fdt file dev/fdt/rkiis.c rkiis -device rkpmic -attach rkpmic at i2c -file dev/fdt/rkpmic.c rkpmic +device rkpcie: pcibus +attach rkpcie at fdt +file dev/fdt/rkpcie.c rkpcie + +device rkpciephy +attach rkpciephy at fdt +file dev/fdt/rkpciephy.c rkpciephy device rkpinctrl: fdt attach rkpinctrl at fdt file dev/fdt/rkpinctrl.c rkpinctrl -device rkpcie: pcibus -attach rkpcie at fdt -file dev/fdt/rkpcie.c rkpcie +device rkpmic +attach rkpmic at i2c +file dev/fdt/rkpmic.c rkpmic device rkpwm attach rkpwm at fdt diff --git a/sys/dev/fdt/rkpciephy.c b/sys/dev/fdt/rkpciephy.c new file mode 100644 index 00000000000..75fac8ea7e4 --- /dev/null +++ b/sys/dev/fdt/rkpciephy.c @@ -0,0 +1,137 @@ +/* $OpenBSD: rkpciephy.c,v 1.1 2023/03/19 11:17:16 kettenis Exp $ */ +/* + * Copyright (c) 2023 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#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 +/* CON6 */ +#define GRF_PCIE30PHY_LANE1_LINK_NUM_MASK (0xf << 16) +#define GRF_PCIE30PHY_LANE1_LINK_NUM_SHIFT 0 +/* STATUS0 */ +#define GRF_PCIE30PHY_STATUS0 0x80 +#define GRF_PCIE30PHY_SRAM_INIT_DONE (1 << 14) + +struct rkpciephy_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + struct phy_device sc_pd; +}; + +int rkpciephy_match(struct device *, void *, void *); +void rkpciephy_attach(struct device *, struct device *, void *); + +const struct cfattach rkpciephy_ca = { + sizeof (struct rkpciephy_softc), rkpciephy_match, rkpciephy_attach +}; + +struct cfdriver rkpciephy_cd = { + NULL, "rkpciephy", DV_DULL +}; + +int rkpciephy_enable(void *, uint32_t *); + +int +rkpciephy_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "rockchip,rk3568-pcie3-phy"); +} + +void +rkpciephy_attach(struct device *parent, struct device *self, void *aux) +{ + struct rkpciephy_softc *sc = (struct rkpciephy_softc *)self; + struct fdt_attach_args *faa = aux; + + printf("\n"); + + sc->sc_pd.pd_node = faa->fa_node; + sc->sc_pd.pd_cookie = sc; + sc->sc_pd.pd_enable = rkpciephy_enable; + phy_register(&sc->sc_pd); +} + +int +rkpciephy_enable(void *cookie, uint32_t *cells) +{ + struct rkpciephy_softc *sc = cookie; + struct regmap *rm; + int node = sc->sc_pd.pd_node; + uint32_t data_lanes[2] = { 0, 0 }; + uint32_t grf, stat; + int timo; + + grf = OF_getpropint(node, "rockchip,phy-grf", 0); + rm = regmap_byphandle(grf); + if (rm == NULL) + return ENXIO; + + clock_enable_all(node); + reset_assert(node, "phy"); + delay(1); + + regmap_write_4(rm, GRF_PCIE30PHY_CON(9), GRF_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] > 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) + break; + delay(100); + } + if (timo == 0) { + printf("%s: timeout\n", sc->sc_dev.dv_xname); + return ETIMEDOUT; + } + + return 0; +}