Add support for imx6qp-pcie.
+ Add vpcie-supply support + Add ext_osc support Tested on SABRESD i.MX 6QP.
This commit is contained in:
parent
d284e45ce6
commit
1914e34e1b
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imx6_pcie.c,v 1.3 2019/08/19 03:45:51 hkenken Exp $ */
|
||||
/* $NetBSD: imx6_pcie.c,v 1.4 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
|
||||
* Written by Hashimoto Kenichi for Genetec Corporation.
|
||||
|
@ -25,7 +25,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: imx6_pcie.c,v 1.3 2019/08/19 03:45:51 hkenken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: imx6_pcie.c,v 1.4 2019/09/02 01:28:41 hkenken Exp $");
|
||||
|
||||
#include "opt_pci.h"
|
||||
#include "opt_fdt.h"
|
||||
|
@ -69,6 +69,7 @@ struct imxpcie_fdt_softc {
|
|||
struct imxpcie_softc sc_imxpcie;
|
||||
|
||||
struct fdtbus_gpio_pin *sc_pin_reset;
|
||||
struct fdtbus_regulator *sc_reg_vpcie;
|
||||
};
|
||||
|
||||
static int imx6_pcie_match(device_t, cfdata_t, void *);
|
||||
|
@ -89,9 +90,10 @@ static void imx6_pcie_reset(void *);
|
|||
CFATTACH_DECL_NEW(imxpcie_fdt, sizeof(struct imxpcie_fdt_softc),
|
||||
imx6_pcie_match, imx6_pcie_attach, NULL, NULL);
|
||||
|
||||
static const char * const compatible[] = {
|
||||
"fsl,imx6q-pcie",
|
||||
NULL
|
||||
static const struct of_compat_data compat_data[] = {
|
||||
{ "fsl,imx6q-pcie", false },
|
||||
{ "fsl,imx6qp-pcie", true },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -99,7 +101,7 @@ imx6_pcie_match(device_t parent, cfdata_t cf, void *aux)
|
|||
{
|
||||
struct fdt_attach_args * const faa = aux;
|
||||
|
||||
return of_match_compatible(faa->faa_phandle, compatible);
|
||||
return of_match_compat_data(faa->faa_phandle, compat_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -125,6 +127,7 @@ imx6_pcie_attach(device_t parent, device_t self, void *aux)
|
|||
sc->sc_gpr_read = imx6_pcie_gpr_read;
|
||||
sc->sc_gpr_write = imx6_pcie_gpr_write;
|
||||
sc->sc_reset = imx6_pcie_reset;
|
||||
sc->sc_have_sw_reset = of_search_compatible(phandle, compat_data)->data;
|
||||
|
||||
if (fdtbus_get_reg_byname(phandle, "dbi", &addr, &size) != 0) {
|
||||
aprint_error(": couldn't get registers\n");
|
||||
|
@ -171,6 +174,49 @@ imx6_pcie_attach(device_t parent, device_t self, void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
if (of_hasprop(phandle, "vpcie-supply")) {
|
||||
ifsc->sc_reg_vpcie = fdtbus_regulator_acquire(phandle, "vpcie-supply");
|
||||
if (ifsc->sc_reg_vpcie == NULL) {
|
||||
aprint_error(": couldn't acquire regulator\n");
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "regulator On\n");
|
||||
fdtbus_regulator_enable(ifsc->sc_reg_vpcie);
|
||||
}
|
||||
|
||||
if (of_hasprop(phandle, "ext_osc")) {
|
||||
aprint_normal_dev(self, "Use external OSC\n");
|
||||
sc->sc_ext_osc = true;
|
||||
|
||||
sc->sc_clk_pcie_ext = fdtbus_clock_get(phandle, "pcie_ext");
|
||||
if (sc->sc_clk_pcie_ext == NULL) {
|
||||
aprint_error(": couldn't get clock pcie_ext\n");
|
||||
return;
|
||||
}
|
||||
sc->sc_clk_pcie_ext_src = fdtbus_clock_get(phandle, "pcie_ext_src");
|
||||
if (sc->sc_clk_pcie_ext_src == NULL) {
|
||||
aprint_error(": couldn't get clock pcie_ext_src\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct clk *clk_lvds1_in = imx6_get_clock("lvds1_in");
|
||||
if (clk_lvds1_in == NULL) {
|
||||
aprint_error(": couldn't get clock lvds1_in\n");
|
||||
return;
|
||||
}
|
||||
int error = clk_set_parent(sc->sc_clk_pcie_ext_src, clk_lvds1_in);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"couldn't set '%s' parent to '%s': %d\n",
|
||||
sc->sc_clk_pcie_ext_src->name, clk_lvds1_in->name, error);
|
||||
}
|
||||
} else {
|
||||
sc->sc_ext_osc = false;
|
||||
sc->sc_clk_pcie_ext = NULL;
|
||||
sc->sc_clk_pcie_ext_src = NULL;
|
||||
}
|
||||
|
||||
|
||||
TAILQ_INIT(&sc->sc_intrs);
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imx6_ccm.c,v 1.13 2019/07/30 11:11:15 hkenken Exp $ */
|
||||
/* $NetBSD: imx6_ccm.c,v 1.14 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010-2012, 2014 Genetec Corporation. All rights reserved.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: imx6_ccm.c,v 1.13 2019/07/30 11:11:15 hkenken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: imx6_ccm.c,v 1.14 2019/09/02 01:28:41 hkenken Exp $");
|
||||
|
||||
#include "opt_cputypes.h"
|
||||
|
||||
|
@ -886,6 +886,8 @@ static struct imx6_clk imx6_clks[] = {
|
|||
|
||||
CLK_GATE_EXCLUSIVE("lvds1_gate", "lvds1_sel", CCM_ANALOG, MISC1, LVDS_CLK1_OBEN, LVDS_CLK1_IBEN),
|
||||
CLK_GATE_EXCLUSIVE("lvds2_gate", "lvds2_sel", CCM_ANALOG, MISC1, LVDS_CLK2_OBEN, LVDS_CLK2_IBEN),
|
||||
CLK_GATE_EXCLUSIVE("lvds1_in", "anaclk1", CCM_ANALOG, MISC1, LVDS_CLK1_IBEN, LVDS_CLK1_OBEN),
|
||||
CLK_GATE_EXCLUSIVE("lvds2_in", "anaclk2", CCM_ANALOG, MISC1, LVDS_CLK2_IBEN, LVDS_CLK2_OBEN),
|
||||
};
|
||||
|
||||
static struct imx6_clk *imx6_clk_find(const char *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imx6_iomuxreg.h,v 1.5 2019/07/22 11:44:01 hkenken Exp $ */
|
||||
/* $NetBSD: imx6_iomuxreg.h,v 1.6 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Ryo Shimizu <ryo@nerv.org>
|
||||
|
@ -33,6 +33,7 @@
|
|||
#define IOMUX_GPR1 0x00000004
|
||||
#define IOMUX_GPR1_CFG_L1_CLK_REMOVAL_EN __BIT(31)
|
||||
#define IOMUX_GPR1_APP_CLK_REQ_N __BIT(30)
|
||||
#define IOMUX_GPR1_PCIE_SW_RST __BIT(29)
|
||||
#define IOMUX_GPR1_APP_REQ_EXIT_L1 __BIT(28)
|
||||
#define IOMUX_GPR1_APP_READY_ENTR_L23 __BIT(27)
|
||||
#define IOMUX_GPR1_APP_REQ_ENTR_L1 __BIT(26)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imxpcie.c,v 1.1 2019/07/24 12:33:18 hkenken Exp $ */
|
||||
/* $NetBSD: imxpcie.c,v 1.2 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: imxpcie.c,v 1.1 2019/07/24 12:33:18 hkenken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: imxpcie.c,v 1.2 2019/09/02 01:28:41 hkenken Exp $");
|
||||
|
||||
#include "opt_pci.h"
|
||||
#include "opt_fdt.h"
|
||||
|
@ -244,34 +244,32 @@ imxpcie_phy_read(struct imxpcie_softc *sc, uint32_t addr)
|
|||
static int
|
||||
imxpcie_assert_core_reset(struct imxpcie_softc *sc)
|
||||
{
|
||||
uint32_t gpr1;
|
||||
uint32_t gpr12;
|
||||
if (sc->sc_have_sw_reset) {
|
||||
uint32_t gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
|
||||
gpr1 |= IOMUX_GPR1_PCIE_SW_RST;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
} else {
|
||||
uint32_t gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
|
||||
uint32_t gpr12 = sc->sc_gpr_read(sc, IOMUX_GPR12);
|
||||
|
||||
gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
|
||||
gpr12 = sc->sc_gpr_read(sc, IOMUX_GPR12);
|
||||
/* already enabled by bootloader */
|
||||
if ((gpr1 & IOMUX_GPR1_REF_SSP_EN) &&
|
||||
(gpr12 & IOMUX_GPR12_APP_LTSSM_ENABLE)) {
|
||||
uint32_t v = PCIE_READ(sc, PCIE_PL_PFLR);
|
||||
v &= ~PCIE_PL_PFLR_LINK_STATE;
|
||||
v |= PCIE_PL_PFLR_FORCE_LINK;
|
||||
PCIE_WRITE(sc, PCIE_PL_PFLR, v);
|
||||
|
||||
/* already enabled by bootloader */
|
||||
if ((gpr1 & IOMUX_GPR1_REF_SSP_EN) &&
|
||||
(gpr12 & IOMUX_GPR12_APP_LTSSM_ENABLE)) {
|
||||
uint32_t v = PCIE_READ(sc, PCIE_PL_PFLR);
|
||||
v &= ~PCIE_PL_PFLR_LINK_STATE;
|
||||
v |= PCIE_PL_PFLR_FORCE_LINK;
|
||||
PCIE_WRITE(sc, PCIE_PL_PFLR, v);
|
||||
gpr12 &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR12, gpr12);
|
||||
}
|
||||
|
||||
gpr12 &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR12, gpr12);
|
||||
gpr1 |= IOMUX_GPR1_TEST_POWERDOWN;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
gpr1 &= ~IOMUX_GPR1_REF_SSP_EN;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
}
|
||||
|
||||
#if defined(IMX6DQP)
|
||||
gpr1 |= IOMUX_GPR1_PCIE_SW_RST;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
#endif
|
||||
|
||||
gpr1 |= IOMUX_GPR1_TEST_POWERDOWN;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
gpr1 &= ~IOMUX_GPR1_REF_SSP_EN;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -285,11 +283,23 @@ imxpcie_deassert_core_reset(struct imxpcie_softc *sc)
|
|||
aprint_error_dev(sc->sc_dev, "couldn't enable pcie_axi: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
error = clk_enable(sc->sc_clk_lvds1_gate);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "couldn't enable lvds1_gate: %d\n", error);
|
||||
return error;
|
||||
|
||||
if (sc->sc_ext_osc) {
|
||||
clk_set_parent(sc->sc_clk_pcie_ext, sc->sc_clk_pcie_ext_src);
|
||||
error = clk_enable(sc->sc_clk_pcie_ext);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "couldn't enable ext: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
error = clk_enable(sc->sc_clk_lvds1_gate);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "couldn't enable lvds1_gate: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = clk_enable(sc->sc_clk_pcie_ref);
|
||||
if (error) {
|
||||
aprint_error_dev(sc->sc_dev, "couldn't enable pcie_ref: %d\n", error);
|
||||
|
@ -298,11 +308,6 @@ imxpcie_deassert_core_reset(struct imxpcie_softc *sc)
|
|||
|
||||
uint32_t gpr1 = sc->sc_gpr_read(sc, IOMUX_GPR1);
|
||||
|
||||
#if defined(IMX6DQP)
|
||||
gpr1 &= ~IOMUX_GPR1_PCIE_SW_RST;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
#endif
|
||||
|
||||
delay(50 * 1000);
|
||||
|
||||
gpr1 &= ~IOMUX_GPR1_TEST_POWERDOWN;
|
||||
|
@ -317,6 +322,31 @@ imxpcie_deassert_core_reset(struct imxpcie_softc *sc)
|
|||
if (sc->sc_reset != NULL)
|
||||
sc->sc_reset(sc);
|
||||
|
||||
if (sc->sc_have_sw_reset) {
|
||||
gpr1 &= ~IOMUX_GPR1_PCIE_SW_RST;
|
||||
sc->sc_gpr_write(sc, IOMUX_GPR1, gpr1);
|
||||
delay(200);
|
||||
}
|
||||
|
||||
if (sc->sc_ext_osc) {
|
||||
delay(5 * 1000);
|
||||
|
||||
uint32_t val;
|
||||
val = imxpcie_phy_read(sc, PCIE_PHY_MPLL_OVRD_IN_LO);
|
||||
val &= ~MPLL_MULTIPLIER;
|
||||
val |= __SHIFTIN(0x19, MPLL_MULTIPLIER);
|
||||
val |= MPLL_MULTIPLIER_OVRD;
|
||||
imxpcie_phy_write(sc, PCIE_PHY_MPLL_OVRD_IN_LO, val);
|
||||
|
||||
delay(5 * 1000);
|
||||
|
||||
val = imxpcie_phy_read(sc, PCIE_PHY_ATEOVRD);
|
||||
val |= REF_USB2_EN;
|
||||
imxpcie_phy_write(sc, PCIE_PHY_ATEOVRD, val);
|
||||
|
||||
delay(5 * 1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imxpciereg.h,v 1.1 2019/07/24 12:33:18 hkenken Exp $ */
|
||||
/* $NetBSD: imxpciereg.h,v 1.2 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Ryo Shimizu <ryo@nerv.org>
|
||||
|
@ -220,8 +220,21 @@
|
|||
#define PCIE_PHY_SS_PHASE 0x0005
|
||||
#define PCIE_PHY_SS_FREQ 0x0006
|
||||
#define PCIE_PHY_ATEOVRD 0x0010
|
||||
#define ATEOVRD_EN __BIT(3)
|
||||
#define REF_USB2_EN __BIT(2)
|
||||
#define REF_CLKDIV2 __BIT(1)
|
||||
#define PCIE_PHY_MPLL_OVRD_IN_LO 0x0011
|
||||
#define PCIE_PHY_MPLL_OVRD_IN_HI 0x0011
|
||||
#define RES_ACK_IN_OVRD __BIT(15)
|
||||
#define RES_ACK_IN __BIT(14)
|
||||
#define RES_REQ_IN_OVRD __BIT(13)
|
||||
#define RES_REQ_IN __BIT(12)
|
||||
#define RTUNE_REQ_OVRD __BIT(11)
|
||||
#define RTUNE_REQ __BIT(10)
|
||||
#define MPLL_MULTIPLIER_OVRD __BIT(9)
|
||||
#define MPLL_MULTIPLIER __BITS(8, 2)
|
||||
#define MPLL_EN_OVRD __BIT(1)
|
||||
#define MPLL_EN __BIT(0)
|
||||
#define PCIE_PHY_SSC_OVRD_IN 0x0013
|
||||
#define PCIE_PHY_BS_OVRD_IN 0x0014
|
||||
#define PCIE_PHY_LEVEL_OVRD_IN 0x0015
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: imxpcievar.h,v 1.1 2019/07/24 12:33:18 hkenken Exp $ */
|
||||
/* $NetBSD: imxpcievar.h,v 1.2 2019/09/02 01:28:41 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
|
||||
|
@ -54,12 +54,17 @@ struct imxpcie_softc {
|
|||
struct clk *sc_clk_pcie_axi;
|
||||
struct clk *sc_clk_lvds1_gate;
|
||||
struct clk *sc_clk_pcie_ref;
|
||||
struct clk *sc_clk_pcie_ext;
|
||||
struct clk *sc_clk_pcie_ext_src;
|
||||
bool sc_ext_osc;
|
||||
|
||||
void *sc_cookie;
|
||||
void (* sc_pci_netbsd_configure)(void *);
|
||||
uint32_t (* sc_gpr_read)(void *, uint32_t);
|
||||
void (* sc_gpr_write)(void *, uint32_t, uint32_t);
|
||||
void (* sc_reset)(void *);
|
||||
|
||||
bool sc_have_sw_reset;
|
||||
};
|
||||
|
||||
struct imxpcie_ih {
|
||||
|
|
Loading…
Reference in New Issue