Add support imx6 PCIe controller.
This commit is contained in:
parent
713e0a32de
commit
5dbe7c6e5b
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.imx6,v 1.7 2016/05/17 06:44:45 ryo Exp $
|
||||
# $NetBSD: files.imx6,v 1.8 2016/11/24 12:06:43 hkenken Exp $
|
||||
#
|
||||
# Configuration info for the Freescale i.MX6
|
||||
#
|
||||
|
@ -26,6 +26,11 @@ device axi { [addr=-1], [size=0], [irq=-1], [irqbase=-1]} : bus_space_generic
|
|||
attach axi at mainbus
|
||||
file arch/arm/imx/imx6_axi.c axi
|
||||
|
||||
# iMX6 PCIe
|
||||
device imxpcie: pcibus
|
||||
attach imxpcie at axi
|
||||
file arch/arm/imx/imx6_pcie.c imxpcie
|
||||
|
||||
# iMX6 Clock Control Module
|
||||
device imxccm
|
||||
attach imxccm at axi
|
||||
|
@ -101,4 +106,3 @@ device imxsnvs
|
|||
attach imxsnvs at axi
|
||||
file arch/arm/imx/imxsnvs.c imxsnvs
|
||||
file arch/arm/imx/imx6_snvs.c imxsnvs
|
||||
|
||||
|
|
|
@ -0,0 +1,942 @@
|
|||
/* $NetBSD: imx6_pcie.c,v 1.1 2016/11/24 12:06:43 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Genetec Corporation. All rights reserved.
|
||||
* Written by Hashimoto Kenichi for Genetec Corporation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i.MX6 On-Chip PCI Express Controller
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: imx6_pcie.c,v 1.1 2016/11/24 12:06:43 hkenken Exp $");
|
||||
|
||||
#include "opt_pci.h"
|
||||
#include "opt_imx6pcie.h"
|
||||
|
||||
#include "pci.h"
|
||||
#include "imxgpio.h"
|
||||
#include "locators.h"
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/intr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/extent.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/gpio.h>
|
||||
|
||||
#include <machine/frame.h>
|
||||
#include <arm/cpufunc.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pciconf.h>
|
||||
|
||||
#include <arm/imx/imxgpioreg.h>
|
||||
#include <arm/imx/imxgpiovar.h>
|
||||
#include <arm/imx/imx6var.h>
|
||||
#include <arm/imx/imx6_reg.h>
|
||||
#include <arm/imx/imx6_pciereg.h>
|
||||
#include <arm/imx/imx6_iomuxreg.h>
|
||||
#include <arm/imx/imx6_ccmreg.h>
|
||||
#include <arm/imx/imx6_ccmvar.h>
|
||||
|
||||
static int imx6pcie_match(device_t, cfdata_t, void *);
|
||||
static void imx6pcie_attach(device_t, device_t, void *);
|
||||
|
||||
#define IMX6_PCIE_MEM_BASE 0x01000000
|
||||
#define IMX6_PCIE_MEM_SIZE 0x00f00000 /* 15MB */
|
||||
#define IMX6_PCIE_ROOT_BASE 0x01f00000
|
||||
#define IMX6_PCIE_ROOT_SIZE 0x00080000 /* 512KB */
|
||||
#define IMX6_PCIE_IO_BASE 0x01f80000
|
||||
#define IMX6_PCIE_IO_SIZE 0x00010000 /* 64KB */
|
||||
|
||||
struct imx6pcie_ih {
|
||||
int (*ih_handler)(void *);
|
||||
void *ih_arg;
|
||||
int ih_ipl;
|
||||
TAILQ_ENTRY(imx6pcie_ih) ih_entry;
|
||||
};
|
||||
|
||||
struct imx6pcie_softc {
|
||||
device_t sc_dev;
|
||||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_space_handle_t sc_root_ioh;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
|
||||
struct arm32_pci_chipset sc_pc;
|
||||
|
||||
TAILQ_HEAD(, imx6pcie_ih) sc_intrs;
|
||||
|
||||
void *sc_ih;
|
||||
kmutex_t sc_lock;
|
||||
u_int sc_intrgen;
|
||||
|
||||
int32_t sc_gpio_reset;
|
||||
int32_t sc_gpio_reset_active;
|
||||
int32_t sc_gpio_pwren;
|
||||
int32_t sc_gpio_pwren_active;
|
||||
};
|
||||
|
||||
#define PCIE_CONF_LOCK(s) (s) = disable_interrupts(I32_bit)
|
||||
#define PCIE_CONF_UNLOCK(s) restore_interrupts((s))
|
||||
|
||||
#define PCIE_READ(sc, reg) \
|
||||
bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, reg)
|
||||
#define PCIE_WRITE(sc, reg, val) \
|
||||
bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, reg, val)
|
||||
|
||||
static int imx6pcie_intr(void *);
|
||||
static void imx6pcie_init(pci_chipset_tag_t, void *);
|
||||
static void imx6pcie_setup(struct imx6pcie_softc * const);
|
||||
|
||||
static void imx6pcie_attach_hook(device_t, device_t,
|
||||
struct pcibus_attach_args *);
|
||||
static int imx6pcie_bus_maxdevs(void *, int);
|
||||
static pcitag_t imx6pcie_make_tag(void *, int, int, int);
|
||||
static void imx6pcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
|
||||
static pcireg_t imx6pcie_conf_read(void *, pcitag_t, int);
|
||||
static void imx6pcie_conf_write(void *, pcitag_t, int, pcireg_t);
|
||||
#ifdef __HAVE_PCI_CONF_HOOK
|
||||
static int imx6pcie_conf_hook(void *, int, int, int, pcireg_t);
|
||||
#endif
|
||||
static void imx6pcie_conf_interrupt(void *, int, int, int, int, int *);
|
||||
|
||||
static int imx6pcie_intr_map(const struct pci_attach_args *,
|
||||
pci_intr_handle_t *);
|
||||
static const char *imx6pcie_intr_string(void *, pci_intr_handle_t,
|
||||
char *, size_t);
|
||||
const struct evcnt *imx6pcie_intr_evcnt(void *, pci_intr_handle_t);
|
||||
static void * imx6pcie_intr_establish(void *, pci_intr_handle_t,
|
||||
int, int (*)(void *), void *);
|
||||
static void imx6pcie_intr_disestablish(void *, void *);
|
||||
|
||||
CFATTACH_DECL_NEW(imxpcie, sizeof(struct imx6pcie_softc),
|
||||
imx6pcie_match, imx6pcie_attach, NULL, NULL);
|
||||
|
||||
static void
|
||||
imx6pcie_clock_enable(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = imx6_ccm_read(CCM_ANALOG_MISC1);
|
||||
v &= ~CCM_ANALOG_MISC1_LVDS_CLK1_IBEN;
|
||||
v &= ~CCM_ANALOG_MISC1_LVDS_CLK1_SRC;
|
||||
v |= CCM_ANALOG_MISC1_LVDS_CLK1_OBEN;
|
||||
v |= CCM_ANALOG_MISC1_LVDS_CLK1_SRC_SATA;
|
||||
imx6_ccm_write(CCM_ANALOG_MISC1, v);
|
||||
|
||||
/* select PCIe clock source from axi */
|
||||
v = imx6_ccm_read(CCM_CBCMR);
|
||||
v &= ~CCM_CBCMR_PCIE_AXI_CLK_SEL;
|
||||
imx6_ccm_write(CCM_CBCMR, v);
|
||||
|
||||
/* AHCISATA clock enable */
|
||||
v = imx6_ccm_read(CCM_CCGR5);
|
||||
v |= CCM_CCGR5_100M_CLK_ENABLE(3);
|
||||
imx6_ccm_write(CCM_CCGR5, v);
|
||||
|
||||
/* PCIe clock enable */
|
||||
v = imx6_ccm_read(CCM_CCGR4);
|
||||
v |= CCM_CCGR4_125M_ROOT_ENABLE(3);
|
||||
imx6_ccm_write(CCM_CCGR4, v);
|
||||
|
||||
/* PLL power up */
|
||||
if (imx6_pll_power(CCM_ANALOG_PLL_ENET, 1,
|
||||
CCM_ANALOG_PLL_ENET_ENABLE_125M |
|
||||
CCM_ANALOG_PLL_ENET_ENABLE_100M) != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"couldn't enable CCM_ANALOG_PLL_ENET\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_init_phy(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
/* initialize IOMUX */
|
||||
v = iomux_read(IOMUX_GPR12);
|
||||
v &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
|
||||
iomux_write(IOMUX_GPR12, v);
|
||||
|
||||
v &= ~IOMUX_GPR12_DEVICE_TYPE;
|
||||
v |= IOMUX_GPR12_DEVICE_TYPE_PCIE_RC;
|
||||
iomux_write(IOMUX_GPR12, v);
|
||||
|
||||
v &= ~IOMUX_GPR12_LOS_LEVEL;
|
||||
v |= __SHIFTIN(9, IOMUX_GPR12_LOS_LEVEL);
|
||||
iomux_write(IOMUX_GPR12, v);
|
||||
|
||||
v = 0;
|
||||
v |= __SHIFTIN(0x7f, IOMUX_GPR8_PCS_TX_SWING_LOW);
|
||||
v |= __SHIFTIN(0x7f, IOMUX_GPR8_PCS_TX_SWING_FULL);
|
||||
v |= __SHIFTIN(20, IOMUX_GPR8_PCS_TX_DEEMPH_GEN2_6DB);
|
||||
v |= __SHIFTIN(0, IOMUX_GPR8_PCS_TX_DEEMPH_GEN2_3P5DB);
|
||||
v |= __SHIFTIN(0, IOMUX_GPR8_PCS_TX_DEEMPH_GEN1);
|
||||
iomux_write(IOMUX_GPR8, v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_phy_wait_ack(struct imx6pcie_softc *sc, int ack)
|
||||
{
|
||||
uint32_t v;
|
||||
int timeout;
|
||||
|
||||
for (timeout = 10; timeout > 0; --timeout) {
|
||||
v = PCIE_READ(sc, PCIE_PL_PHY_STATUS);
|
||||
if (!!(v & PCIE_PL_PHY_STATUS_ACK) == !!ack)
|
||||
return 0;
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_phy_addr(struct imx6pcie_softc *sc, uint32_t addr)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = __SHIFTIN(addr, PCIE_PL_PHY_CTRL_DATA);
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
|
||||
|
||||
v |= PCIE_PL_PHY_CTRL_CAP_ADR;
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
|
||||
|
||||
if (imx6pcie_phy_wait_ack(sc, 1))
|
||||
return -1;
|
||||
|
||||
v = __SHIFTIN(addr, PCIE_PL_PHY_CTRL_DATA);
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, v);
|
||||
|
||||
if (imx6pcie_phy_wait_ack(sc, 0))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_phy_write(struct imx6pcie_softc *sc, uint32_t addr, uint16_t data)
|
||||
{
|
||||
/* write address */
|
||||
if (imx6pcie_phy_addr(sc, addr) != 0)
|
||||
return -1;
|
||||
|
||||
/* store data */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
|
||||
|
||||
/* assert CAP_DAT and wait ack */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA) | PCIE_PL_PHY_CTRL_CAP_DAT);
|
||||
if (imx6pcie_phy_wait_ack(sc, 1))
|
||||
return -1;
|
||||
|
||||
/* deassert CAP_DAT and wait ack */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
|
||||
if (imx6pcie_phy_wait_ack(sc, 0))
|
||||
return -1;
|
||||
|
||||
/* assert WR and wait ack */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, PCIE_PL_PHY_CTRL_WR);
|
||||
if (imx6pcie_phy_wait_ack(sc, 1))
|
||||
return -1;
|
||||
|
||||
/* deassert WR and wait ack */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, __SHIFTIN(data, PCIE_PL_PHY_CTRL_DATA));
|
||||
if (imx6pcie_phy_wait_ack(sc, 0))
|
||||
return -1;
|
||||
|
||||
/* done */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_phy_read(struct imx6pcie_softc *sc, uint32_t addr)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
/* write address */
|
||||
if (imx6pcie_phy_addr(sc, addr) != 0)
|
||||
return -1;
|
||||
|
||||
/* assert RD */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, PCIE_PL_PHY_CTRL_RD);
|
||||
if (imx6pcie_phy_wait_ack(sc, 1))
|
||||
return -1;
|
||||
|
||||
/* read data */
|
||||
v = __SHIFTOUT(PCIE_READ(sc, PCIE_PL_PHY_STATUS),
|
||||
PCIE_PL_PHY_STATUS_DATA);
|
||||
|
||||
/* deassert RD */
|
||||
PCIE_WRITE(sc, PCIE_PL_PHY_CTRL, 0);
|
||||
if (imx6pcie_phy_wait_ack(sc, 0))
|
||||
return -1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_assert_core_reset(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t gpr1;
|
||||
uint32_t gpr12;
|
||||
|
||||
gpr1 = iomux_read(IOMUX_GPR1);
|
||||
gpr12 = iomux_read(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);
|
||||
|
||||
gpr12 &= ~IOMUX_GPR12_APP_LTSSM_ENABLE;
|
||||
iomux_write(IOMUX_GPR12, gpr12);
|
||||
}
|
||||
|
||||
#if defined(IMX6DQP)
|
||||
gpr1 |= IOMUX_GPR1_PCIE_SW_RST;
|
||||
iomux_write(IOMUX_GPR1, gpr1);
|
||||
#endif
|
||||
|
||||
gpr1 |= IOMUX_GPR1_TEST_POWERDOWN;
|
||||
iomux_write(IOMUX_GPR1, gpr1);
|
||||
gpr1 &= ~IOMUX_GPR1_REF_SSP_EN;
|
||||
iomux_write(IOMUX_GPR1, gpr1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_deassert_core_reset(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
/* Power ON */
|
||||
#if NIMXGPIO > 0
|
||||
if (sc->sc_gpio_pwren >= 0) {
|
||||
gpio_data_write(sc->sc_gpio_pwren, sc->sc_gpio_pwren_active);
|
||||
delay(100 * 1000);
|
||||
gpio_data_write(sc->sc_gpio_pwren, !sc->sc_gpio_pwren_active);
|
||||
}
|
||||
#endif
|
||||
|
||||
imx6pcie_clock_enable(sc);
|
||||
|
||||
v = iomux_read(IOMUX_GPR1);
|
||||
|
||||
#if defined(IMX6DQP)
|
||||
v &= ~IOMUX_GPR1_PCIE_SW_RST;
|
||||
iomux_write(IOMUX_GPR1, v);
|
||||
#endif
|
||||
|
||||
delay(50 * 1000);
|
||||
|
||||
v &= ~IOMUX_GPR1_TEST_POWERDOWN;
|
||||
iomux_write(IOMUX_GPR1, v);
|
||||
delay(10);
|
||||
v |= IOMUX_GPR1_REF_SSP_EN;
|
||||
iomux_write(IOMUX_GPR1, v);
|
||||
|
||||
delay(50 * 1000);
|
||||
|
||||
/* Reset */
|
||||
#if NIMXGPIO > 0
|
||||
if (sc->sc_gpio_reset >= 0) {
|
||||
gpio_data_write(sc->sc_gpio_reset, sc->sc_gpio_reset_active);
|
||||
delay(100 * 1000);
|
||||
gpio_data_write(sc->sc_gpio_reset, !sc->sc_gpio_reset_active);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_wait_for_link(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t ltssm, valid, v;
|
||||
uint32_t linkup;
|
||||
int retry;
|
||||
|
||||
#define LINKUP_RETRY 200
|
||||
for (retry = LINKUP_RETRY; retry > 0; --retry) {
|
||||
linkup = PCIE_READ(sc, PCIE_PL_DEBUG1);
|
||||
if ((linkup & PCIE_PL_DEBUG1_XMLH_LINK_UP) &&
|
||||
!(linkup & PCIE_PL_DEBUG1_XMLH_LINK_IN_TRAINING)) {
|
||||
delay(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
valid = imx6pcie_phy_read(sc, PCIE_PHY_RX_ASIC_OUT) &
|
||||
PCIE_PHY_RX_ASIC_OUT_VALID;
|
||||
ltssm = __SHIFTOUT(PCIE_READ(sc, PCIE_PL_DEBUG0),
|
||||
PCIE_PL_DEBUG0_XMLH_LTSSM_STATE);
|
||||
|
||||
if ((ltssm == 0x0d) && !valid) {
|
||||
aprint_normal_dev(sc->sc_dev, "resetting PCIe phy\n");
|
||||
|
||||
v = imx6pcie_phy_read(sc, PCIE_PHY_RX_OVRD_IN_LO);
|
||||
v |= PCIE_PHY_RX_OVRD_IN_LO_RX_PLL_EN_OVRD;
|
||||
v |= PCIE_PHY_RX_OVRD_IN_LO_RX_DATA_EN_OVRD;
|
||||
imx6pcie_phy_write(sc, PCIE_PHY_RX_OVRD_IN_LO, v);
|
||||
|
||||
delay(3000);
|
||||
|
||||
v = imx6pcie_phy_read(sc, PCIE_PHY_RX_OVRD_IN_LO);
|
||||
v &= ~PCIE_PHY_RX_OVRD_IN_LO_RX_PLL_EN_OVRD;
|
||||
v &= ~PCIE_PHY_RX_OVRD_IN_LO_RX_DATA_EN_OVRD;
|
||||
imx6pcie_phy_write(sc, PCIE_PHY_RX_OVRD_IN_LO, v);
|
||||
}
|
||||
|
||||
if (linkup)
|
||||
return 0;
|
||||
}
|
||||
|
||||
aprint_error_dev(sc->sc_dev, "Link Up failed.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_wait_for_changespeed(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
int retry;
|
||||
|
||||
#define CHANGESPEED_RETRY 200
|
||||
for (retry = CHANGESPEED_RETRY; retry > 0; --retry) {
|
||||
v = PCIE_READ(sc, PCIE_PL_G2CR);
|
||||
if (!(v & PCIE_PL_G2CR_DIRECTED_SPEED_CHANGE))
|
||||
return 0;
|
||||
delay(100);
|
||||
}
|
||||
|
||||
aprint_error_dev(sc->sc_dev, "Speed change timeout.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_linkup(struct imx6pcie_softc *sc)
|
||||
{
|
||||
uint32_t v;
|
||||
int ret;
|
||||
|
||||
imx6pcie_assert_core_reset(sc);
|
||||
imx6pcie_init_phy(sc);
|
||||
imx6pcie_deassert_core_reset(sc);
|
||||
|
||||
imx6pcie_setup(sc);
|
||||
|
||||
/* GEN1 Operation */
|
||||
v = PCIE_READ(sc, PCIE_RC_LCR);
|
||||
v &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS;
|
||||
v |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
|
||||
PCIE_WRITE(sc, PCIE_RC_LCR, v);
|
||||
|
||||
/* Link Up */
|
||||
v = iomux_read(IOMUX_GPR12);
|
||||
v |= IOMUX_GPR12_APP_LTSSM_ENABLE;
|
||||
iomux_write(IOMUX_GPR12, v);
|
||||
|
||||
ret = imx6pcie_wait_for_link(sc);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Change speed */
|
||||
v = PCIE_READ(sc, PCIE_PL_G2CR);
|
||||
v |= PCIE_PL_G2CR_DIRECTED_SPEED_CHANGE;
|
||||
PCIE_WRITE(sc, PCIE_PL_G2CR, v);
|
||||
|
||||
ret = imx6pcie_wait_for_changespeed(sc);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Allow Gen2 mode */
|
||||
v = PCIE_READ(sc, PCIE_RC_LCR);
|
||||
v &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS;
|
||||
v |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
|
||||
PCIE_WRITE(sc, PCIE_RC_LCR, v);
|
||||
|
||||
ret = imx6pcie_wait_for_link(sc);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
v = PCIE_READ(sc, PCIE_RC_LCSR);
|
||||
aprint_normal_dev(sc->sc_dev, "LinkUp, Gen %d\n",
|
||||
(int)__SHIFTOUT(v, PCIE_RC_LCSR_LINK_SPEED));
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"PCIE_PL_DEBUG0,1 = %08x, %08x\n",
|
||||
PCIE_READ(sc, PCIE_PL_DEBUG0),
|
||||
PCIE_READ(sc, PCIE_PL_DEBUG1));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_match(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct axi_attach_args * const aa = aux;
|
||||
|
||||
/* i.MX6 SoloLite has no PCIe controller */
|
||||
switch (IMX6_CHIPID_MAJOR(imx6_chip_id())) {
|
||||
case CHIPID_MAJOR_IMX6SL:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aa->aa_addr) {
|
||||
case (IMX6_PCIE_BASE):
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct imx6pcie_softc * const sc = device_private(self);
|
||||
struct axi_attach_args * const aa = aux;
|
||||
struct pcibus_attach_args pba;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_iot = aa->aa_iot;
|
||||
sc->sc_dmat = aa->aa_dmat;
|
||||
|
||||
if (aa->aa_size == AXICF_SIZE_DEFAULT)
|
||||
aa->aa_size = IMX6_PCIE_SIZE;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": PCI Express Controller\n");
|
||||
|
||||
if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0,
|
||||
&sc->sc_ioh)) {
|
||||
aprint_error_dev(self, "Cannot map registers\n");
|
||||
return;
|
||||
}
|
||||
if (bus_space_map(sc->sc_iot, IMX6_PCIE_ROOT_BASE,
|
||||
IMX6_PCIE_ROOT_SIZE, 0, &sc->sc_root_ioh)) {
|
||||
aprint_error_dev(self, "Cannot map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
imx6_set_gpio(self, "imx6pcie-reset-gpio", &sc->sc_gpio_reset,
|
||||
&sc->sc_gpio_reset_active, GPIO_DIR_OUT);
|
||||
imx6_set_gpio(self, "imx6pcie-pwren-gpio", &sc->sc_gpio_pwren,
|
||||
&sc->sc_gpio_pwren_active, GPIO_DIR_OUT);
|
||||
|
||||
imx6pcie_linkup(sc);
|
||||
|
||||
TAILQ_INIT(&sc->sc_intrs);
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
|
||||
|
||||
sc->sc_ih = intr_establish(aa->aa_irq, IPL_VM, IST_LEVEL,
|
||||
imx6pcie_intr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
aprint_error_dev(self, "failed to establish interrupt on %d\n",
|
||||
aa->aa_irq);
|
||||
return;
|
||||
}
|
||||
aprint_normal_dev(self, "interrupting on %d\n", aa->aa_irq);
|
||||
|
||||
imx6pcie_init(&sc->sc_pc, sc);
|
||||
|
||||
#ifdef PCI_NETBSD_CONFIGURE
|
||||
struct extent *ioext, *memext;
|
||||
int error;
|
||||
|
||||
ioext = extent_create("pciio", IMX6_PCIE_IO_BASE,
|
||||
IMX6_PCIE_IO_BASE + IMX6_PCIE_IO_SIZE - 1,
|
||||
NULL, 0, EX_NOWAIT);
|
||||
memext = extent_create("pcimem", IMX6_PCIE_MEM_BASE,
|
||||
IMX6_PCIE_MEM_BASE + IMX6_PCIE_MEM_SIZE - 1,
|
||||
NULL, 0, EX_NOWAIT);
|
||||
|
||||
error = pci_configure_bus(&sc->sc_pc, ioext, memext, NULL, 0,
|
||||
arm_dcache_align);
|
||||
|
||||
extent_destroy(ioext);
|
||||
extent_destroy(memext);
|
||||
|
||||
if (error) {
|
||||
aprint_error_dev(self, "configuration failed (%d)\n",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&pba, 0, sizeof(pba));
|
||||
pba.pba_flags = PCI_FLAGS_MEM_OKAY |
|
||||
PCI_FLAGS_IO_OKAY;
|
||||
pba.pba_iot = sc->sc_iot;
|
||||
pba.pba_memt = sc->sc_iot;
|
||||
pba.pba_dmat = sc->sc_dmat;
|
||||
pba.pba_pc = &sc->sc_pc;
|
||||
pba.pba_bus = 0;
|
||||
|
||||
config_found_ia(self, "pcibus", &pba, pcibusprint);
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_intr(void *priv)
|
||||
{
|
||||
struct imx6pcie_softc *sc = priv;
|
||||
struct imx6pcie_ih *pcie_ih;
|
||||
int rv = 0;
|
||||
uint32_t v;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
v = PCIE_READ(sc, PCIE_PL_MSICIN_STATUS + i * 0xC);
|
||||
int bit;
|
||||
while ((bit = ffs(v) - 1) >= 0) {
|
||||
PCIE_WRITE(sc, PCIE_PL_MSICIN_STATUS + i * 0xC,
|
||||
__BIT(bit));
|
||||
v &= ~__BIT(bit);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
const u_int lastgen = sc->sc_intrgen;
|
||||
TAILQ_FOREACH(pcie_ih, &sc->sc_intrs, ih_entry) {
|
||||
int (*callback)(void *) = pcie_ih->ih_handler;
|
||||
void *arg = pcie_ih->ih_arg;
|
||||
mutex_exit(&sc->sc_lock);
|
||||
rv += callback(arg);
|
||||
mutex_enter(&sc->sc_lock);
|
||||
if (lastgen != sc->sc_intrgen)
|
||||
break;
|
||||
}
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_setup(struct imx6pcie_softc * const sc)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
/* Setup RC */
|
||||
|
||||
/* BARs */
|
||||
PCIE_WRITE(sc, PCI_BAR0, 0x00000004);
|
||||
PCIE_WRITE(sc, PCI_BAR1, 0x00000000);
|
||||
|
||||
/* Interurupt pins */
|
||||
v = PCIE_READ(sc, PCI_INTERRUPT_REG);
|
||||
v &= ~(PCI_INTERRUPT_PIN_MASK << PCI_INTERRUPT_PIN_SHIFT);
|
||||
v |= PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT;
|
||||
PCIE_WRITE(sc, PCI_INTERRUPT_REG, v);
|
||||
|
||||
/* Bus number */
|
||||
v = PCIE_READ(sc, PCI_BRIDGE_BUS_REG);
|
||||
v &= ~(PCI_BRIDGE_BUS_EACH_MASK << PCI_BRIDGE_BUS_SUBORDINATE_SHIFT |
|
||||
PCI_BRIDGE_BUS_EACH_MASK << PCI_BRIDGE_BUS_SECONDARY_SHIFT |
|
||||
PCI_BRIDGE_BUS_EACH_MASK << PCI_BRIDGE_BUS_PRIMARY_SHIFT);
|
||||
v |= PCI_BRIDGE_BUS_SUBORDINATE(1);
|
||||
v |= PCI_BRIDGE_BUS_SECONDARY(1);
|
||||
v |= PCI_BRIDGE_BUS_PRIMARY(0);
|
||||
PCIE_WRITE(sc, PCI_BRIDGE_BUS_REG, v);
|
||||
|
||||
/* Command register */
|
||||
v = PCIE_READ(sc, PCI_COMMAND_STATUS_REG);
|
||||
v |= PCI_COMMAND_IO_ENABLE |
|
||||
PCI_COMMAND_MEM_ENABLE |
|
||||
PCI_COMMAND_MASTER_ENABLE;
|
||||
PCIE_WRITE(sc, PCI_COMMAND_STATUS_REG, v);
|
||||
|
||||
PCIE_WRITE(sc, PCI_CLASS_REG,
|
||||
PCI_CLASS_CODE(PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI, PCI_INTERFACE_BRIDGE_PCI_PCI));
|
||||
|
||||
PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
|
||||
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURLBA, IMX6_PCIE_ROOT_BASE);
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURUBA, 0);
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURLA, IMX6_PCIE_ROOT_BASE + IMX6_PCIE_ROOT_SIZE);
|
||||
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURLTA, 0);
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURUTA, 0);
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC2, PCIE_PL_IATURC2_REGION_ENABLE);
|
||||
}
|
||||
|
||||
void
|
||||
imx6pcie_init(pci_chipset_tag_t pc, void *priv)
|
||||
{
|
||||
pc->pc_conf_v = priv;
|
||||
pc->pc_attach_hook = imx6pcie_attach_hook;
|
||||
pc->pc_bus_maxdevs = imx6pcie_bus_maxdevs;
|
||||
pc->pc_make_tag = imx6pcie_make_tag;
|
||||
pc->pc_decompose_tag = imx6pcie_decompose_tag;
|
||||
pc->pc_conf_read = imx6pcie_conf_read;
|
||||
pc->pc_conf_write = imx6pcie_conf_write;
|
||||
#ifdef __HAVE_PCI_CONF_HOOK
|
||||
pc->pc_conf_hook = imx6pcie_conf_hook;
|
||||
#endif
|
||||
pc->pc_conf_interrupt = imx6pcie_conf_interrupt;
|
||||
|
||||
pc->pc_intr_v = priv;
|
||||
pc->pc_intr_map = imx6pcie_intr_map;
|
||||
pc->pc_intr_string = imx6pcie_intr_string;
|
||||
pc->pc_intr_evcnt = imx6pcie_intr_evcnt;
|
||||
pc->pc_intr_establish = imx6pcie_intr_establish;
|
||||
pc->pc_intr_disestablish = imx6pcie_intr_disestablish;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_attach_hook(device_t parent, device_t self,
|
||||
struct pcibus_attach_args *pba)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_bus_maxdevs(void *v, int busno)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
static pcitag_t
|
||||
imx6pcie_make_tag(void *v, int b, int d, int f)
|
||||
{
|
||||
return (b << 16) | (d << 11) | (f << 8);
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
|
||||
{
|
||||
if (bp)
|
||||
*bp = (tag >> 16) & 0xff;
|
||||
if (dp)
|
||||
*dp = (tag >> 11) & 0x1f;
|
||||
if (fp)
|
||||
*fp = (tag >> 8) & 0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
* work around.
|
||||
* If there is no PCIe devices, DABT will be generated by read/write access to
|
||||
* config area, so replace original DABT handler with sinple jump-back one.
|
||||
*/
|
||||
extern u_int data_abort_handler_address;
|
||||
static bool data_abort_flag;
|
||||
static void
|
||||
imx6pcie_data_abort_handler(trapframe_t *tf)
|
||||
{
|
||||
data_abort_flag = true;
|
||||
tf->tf_pc += 0x4;
|
||||
return;
|
||||
}
|
||||
|
||||
static pcireg_t
|
||||
imx6pcie_conf_read(void *v, pcitag_t tag, int offset)
|
||||
{
|
||||
struct imx6pcie_softc *sc = v;
|
||||
bus_space_handle_t bsh;
|
||||
int b, d, f;
|
||||
pcireg_t ret = -1;
|
||||
int s;
|
||||
|
||||
imx6pcie_decompose_tag(v, tag, &b, &d, &f);
|
||||
|
||||
if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
|
||||
return ret;
|
||||
if (b <= 1 && d > 0)
|
||||
return ret;
|
||||
|
||||
PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
|
||||
if (b < 2)
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
|
||||
else
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG1);
|
||||
|
||||
if (b == 0) {
|
||||
bsh = sc->sc_ioh;
|
||||
} else {
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURLTA, tag << 8);
|
||||
bsh = sc->sc_root_ioh;
|
||||
}
|
||||
PCIE_READ(sc, PCIE_PL_IATURC2);
|
||||
|
||||
PCIE_CONF_LOCK(s);
|
||||
|
||||
u_int saved = data_abort_handler_address;
|
||||
data_abort_handler_address = (u_int)imx6pcie_data_abort_handler;
|
||||
data_abort_flag = false;
|
||||
|
||||
ret = bus_space_read_4(sc->sc_iot, bsh, offset & ~0x3);
|
||||
|
||||
data_abort_handler_address = saved;
|
||||
|
||||
PCIE_CONF_UNLOCK(s);
|
||||
|
||||
if (data_abort_flag)
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
|
||||
{
|
||||
struct imx6pcie_softc *sc = v;
|
||||
bus_space_handle_t bsh;
|
||||
int b, d, f;
|
||||
int s;
|
||||
|
||||
imx6pcie_decompose_tag(v, tag, &b, &d, &f);
|
||||
|
||||
if ((unsigned int)offset >= PCI_EXTCONF_SIZE)
|
||||
return;
|
||||
if (b <= 1 && d > 0)
|
||||
return;
|
||||
|
||||
PCIE_WRITE(sc, PCIE_PL_IATUVR, 0);
|
||||
if (b < 2)
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG0);
|
||||
else
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURC1, PCIE_PL_IATURC1_TYPE_CFG1);
|
||||
|
||||
if (b == 0) {
|
||||
bsh = sc->sc_ioh;
|
||||
} else {
|
||||
PCIE_WRITE(sc, PCIE_PL_IATURLTA, tag << 8);
|
||||
bsh = sc->sc_root_ioh;
|
||||
}
|
||||
PCIE_READ(sc, PCIE_PL_IATURC2);
|
||||
|
||||
PCIE_CONF_LOCK(s);
|
||||
|
||||
u_int saved = data_abort_handler_address;
|
||||
data_abort_handler_address = (u_int)imx6pcie_data_abort_handler;
|
||||
|
||||
bus_space_write_4(sc->sc_iot, bsh, offset & ~0x3, val);
|
||||
|
||||
data_abort_handler_address = saved;
|
||||
|
||||
PCIE_CONF_UNLOCK(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __HAVE_PCI_CONF_HOOK
|
||||
static int
|
||||
imx6pcie_conf_hook(void *v, int b, int d, int f, pcireg_t id)
|
||||
{
|
||||
return PCI_CONF_DEFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
imx6pcie_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz,
|
||||
int *ilinep)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int
|
||||
imx6pcie_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ih)
|
||||
{
|
||||
if (pa->pa_intrpin == 0)
|
||||
return EINVAL;
|
||||
*ih = pa->pa_intrpin;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
imx6pcie_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
|
||||
{
|
||||
if (ih == PCI_INTERRUPT_PIN_NONE)
|
||||
return NULL;
|
||||
|
||||
strlcpy(buf, "pci", len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
const struct evcnt *
|
||||
imx6pcie_intr_evcnt(void *v, pci_intr_handle_t ih)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
imx6pcie_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
|
||||
int (*callback)(void *), void *arg)
|
||||
{
|
||||
struct imx6pcie_softc *sc = v;
|
||||
struct imx6pcie_ih *pcie_ih;
|
||||
|
||||
if (ih == 0)
|
||||
return NULL;
|
||||
|
||||
pcie_ih = kmem_alloc(sizeof(*pcie_ih), KM_SLEEP);
|
||||
pcie_ih->ih_handler = callback;
|
||||
pcie_ih->ih_arg = arg;
|
||||
pcie_ih->ih_ipl = ipl;
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
TAILQ_INSERT_TAIL(&sc->sc_intrs, pcie_ih, ih_entry);
|
||||
sc->sc_intrgen++;
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return pcie_ih;
|
||||
}
|
||||
|
||||
static void
|
||||
imx6pcie_intr_disestablish(void *v, void *vih)
|
||||
{
|
||||
struct imx6pcie_softc *sc = v;
|
||||
struct imx6pcie_ih *pcie_ih = vih;
|
||||
|
||||
mutex_enter(&sc->sc_lock);
|
||||
TAILQ_REMOVE(&sc->sc_intrs, pcie_ih, ih_entry);
|
||||
sc->sc_intrgen++;
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
kmem_free(pcie_ih, sizeof(*pcie_ih));
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
/* $NetBSD: imx6_pciereg.h,v 1.1 2016/11/24 12:06:43 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Ryo Shimizu <ryo@nerv.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_IMX_IMX6_PCIEREG_H_
|
||||
#define _ARM_IMX_IMX6_PCIEREG_H_
|
||||
|
||||
/* PCIe EP Mode Registers */
|
||||
#define PCIE_EP_DEVICEID 0x00000000
|
||||
#define PCIE_EP_COMMAND 0x00000004
|
||||
#define PCIE_EP_BIST 0x0000000c
|
||||
#define PCIE_EP_BAR0 0x00000010
|
||||
#define PCIE_EP_MASK0 0x00000010
|
||||
#define PCIE_EP_MASK1 0x00000014
|
||||
#define PCIE_EP_MASK2 0x00000018
|
||||
#define PCIE_EP_MASK3 0x0000001c
|
||||
#define PCIE_EP_CISP 0x00000028
|
||||
#define PCIE_EP_SSID 0x0000002c
|
||||
#define PCIE_EP_EROMBAR 0x00000030
|
||||
#define PCIE_EP_EROMMASK 0x00000030
|
||||
#define PCIE_EP_CAPPR 0x00000034
|
||||
#define PCIE_EP_ILR 0x0000003c
|
||||
#define PCIE_EP_AER 0x00000100
|
||||
#define PCIE_EP_UESR 0x00000104
|
||||
#define PCIE_EP_UEMR 0x00000108
|
||||
#define PCIE_EP_UESEVR 0x0000010c
|
||||
#define PCIE_EP_CESR 0x00000110
|
||||
#define PCIE_EP_CEMR 0x00000114
|
||||
#define PCIE_EP_ACCR 0x00000118
|
||||
#define PCIE_EP_HLR 0x0000011c
|
||||
#define PCIE_EP_VCECHR 0x00000140
|
||||
#define PCIE_EP_PVCCR1 0x00000144
|
||||
#define PCIE_EP_PVCCR2 0x00000148
|
||||
#define PCIE_EP_PVCCSR 0x0000014c
|
||||
#define PCIE_EP_VCRCR 0x00000150
|
||||
#define PCIE_EP_VCRCONR 0x00000154
|
||||
#define PCIE_EP_VCRSR 0x00000158
|
||||
|
||||
/* PCIe RC Mode Registers */
|
||||
#define PCIE_RC_DEVICEID 0x00000000
|
||||
#define PCIE_RC_COMMAND 0x00000004
|
||||
#define PCIE_RC_REVID 0x00000008
|
||||
#define PCIE_RC_BIST 0x0000000c
|
||||
#define PCIE_RC_BAR0 0x00000010
|
||||
#define PCIE_RC_BAR1 0x00000014
|
||||
#define PCIE_RC_BNR 0x00000018
|
||||
#define PCIE_RC_IOBLSSR 0x0000001c
|
||||
#define PCIE_RC_MEM_BLR 0x00000020
|
||||
#define PCIE_RC_PREF_MEM_BLR 0x00000024
|
||||
#define PCIE_RC_PREF_BASE_U32 0x00000028
|
||||
#define PCIE_RC_PREF_LIM_U32 0x0000002c
|
||||
#define PCIE_RC_IO_BASE_LIM_U16 0x00000030
|
||||
#define PCIE_RC_CAPPR 0x00000034
|
||||
#define PCIE_RC_EROMBAR 0x00000038
|
||||
#define PCIE_RC_EROMMASK 0x00000038
|
||||
#define PCIE_RC_PMCR 0x00000040
|
||||
#define PCIE_RC_PMCSR 0x00000044
|
||||
#define PCIE_RC_CIDR 0x00000070
|
||||
#define PCIE_RC_DCR 0x00000074
|
||||
#define PCIE_RC_DCONR 0x00000078
|
||||
#define PCIE_RC_LCR 0x0000007c
|
||||
#define PCIE_RC_LCR_MAX_LINK_SPEEDS __BITS(3, 0)
|
||||
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 __SHIFTIN(0x1, PCIE_RC_LCR_MAX_LINK_SPEEDS)
|
||||
#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 __SHIFTIN(0x2, PCIE_RC_LCR_MAX_LINK_SPEEDS)
|
||||
#define PCIE_RC_LCSR 0x00000080
|
||||
#define PCIE_RC_LCSR_LINK_SPEED __BITS(19, 16)
|
||||
#define PCIE_RC_SCR 0x00000084
|
||||
#define PCIE_RC_SCSR 0x00000088
|
||||
#define PCIE_RC_RCCR 0x0000008c
|
||||
#define PCIE_RC_RSR 0x00000090
|
||||
#define PCIE_RC_DCR2 0x00000094
|
||||
#define PCIE_RC_DCSR2 0x00000098
|
||||
#define PCIE_RC_LCR2 0x0000009c
|
||||
#define PCIE_RC_LCSR2 0x000000a0
|
||||
#define PCIE_RC_AER 0x00000100
|
||||
#define PCIE_RC_UESR 0x00000104
|
||||
#define PCIE_RC_UEMR 0x00000108
|
||||
#define PCIE_RC_UESEVR 0x0000010c
|
||||
#define PCIE_RC_CESR 0x00000110
|
||||
#define PCIE_RC_CEMR 0x00000114
|
||||
#define PCIE_RC_ACCR 0x00000118
|
||||
#define PCIE_RC_HLR 0x0000011c
|
||||
#define PCIE_RC_RECR 0x0000012c
|
||||
#define PCIE_RC_RESR 0x00000130
|
||||
#define PCIE_RC_ESIR 0x00000134
|
||||
#define PCIE_RC_VCECHR 0x00000140
|
||||
#define PCIE_RC_PVCCR1 0x00000144
|
||||
#define PCIE_RC_PVCCR2 0x00000148
|
||||
#define PCIE_RC_PVCCSR 0x0000014c
|
||||
#define PCIE_RC_VCRCR 0x00000150
|
||||
#define PCIE_RC_VCRCONR 0x00000154
|
||||
#define PCIE_RC_VCRSR 0x00000158
|
||||
|
||||
/* PCIe Port Logic Registers */
|
||||
#define PCIE_PL_ALTRTR 0x00000700
|
||||
#define PCIE_PL_VSDR 0x00000704
|
||||
#define PCIE_PL_PFLR 0x00000708
|
||||
#define PCIE_PL_PFLR_LOW_POWER_ENTRANCE_COUNT __BITS(31, 24)
|
||||
#define PCIE_PL_PFLR_LINK_STATE __BITS(21, 16)
|
||||
#define PCIE_PL_PFLR_FORCE_LINK __BIT(15)
|
||||
#define PCIE_PL_PFLR_LINK_NUMBER __BITS(7, 0)
|
||||
#define PCIE_PL_AFLACR 0x0000070c
|
||||
#define PCIE_PL_PLCR 0x00000710
|
||||
#define PCIE_PL_LSR 0x00000714
|
||||
#define PCIE_PL_SNR 0x00000718
|
||||
#define PCIE_PL_STRFM1 0x0000071c
|
||||
#define PCIE_PL_STRFM2 0x00000720
|
||||
#define PCIE_PL_AMODNPSR 0x00000724
|
||||
#define PCIE_PL_DEBUG0 0x00000728
|
||||
#define PCIE_PL_DEBUG0_XMLH_LTSSM_STATE __BITS(0, 5)
|
||||
#define PCIE_PL_DEBUG1 0x0000072c
|
||||
#define PCIE_PL_DEBUG1_XMLH_LINK_UP __BIT(4)
|
||||
#define PCIE_PL_DEBUG1_XMLH_LINK_IN_TRAINING __BIT(29)
|
||||
#define PCIE_PL_TPFCSR 0x00000730
|
||||
#define PCIE_PL_TNFCSR 0x00000734
|
||||
#define PCIE_PL_TCFCSR 0x00000738
|
||||
#define PCIE_PL_QSR 0x0000073c
|
||||
#define PCIE_PL_VCTAR1 0x00000740
|
||||
#define PCIE_PL_VCTAR2 0x00000744
|
||||
#define PCIE_PL_VC0PRQC 0x00000748
|
||||
#define PCIE_PL_VC0NRQC 0x0000074c
|
||||
#define PCIE_PL_VC0CRQC 0x00000750
|
||||
#define PCIE_PL_VCNPRQC 0x00000754
|
||||
#define PCIE_PL_VCNNRQC 0x00000758
|
||||
#define PCIE_PL_VCNCRQC 0x0000075c
|
||||
#define PCIE_PL_VC0PBD 0x000007a8
|
||||
#define PCIE_PL_VC0NPBD 0x000007ac
|
||||
#define PCIE_PL_VC0CBD 0x000007b0
|
||||
#define PCIE_PL_VC1PBD 0x000007b4
|
||||
#define PCIE_PL_VC1NPBD 0x000007b8
|
||||
#define PCIE_PL_VC1CBD 0x000007bc
|
||||
#define PCIE_PL_G2CR 0x0000080c
|
||||
#define PCIE_PL_G2CR_DIRECTED_SPEED_CHANGE __BIT(17)
|
||||
#define PCIE_PL_PHY_STATUS 0x00000810
|
||||
#define PCIE_PL_PHY_STATUS_ACK __BIT(16)
|
||||
#define PCIE_PL_PHY_STATUS_DATA __BITS(0, 15)
|
||||
#define PCIE_PL_PHY_CTRL 0x00000814
|
||||
#define PCIE_PL_PHY_CTRL_RD __BIT(19)
|
||||
#define PCIE_PL_PHY_CTRL_WR __BIT(18)
|
||||
#define PCIE_PL_PHY_CTRL_CAP_DAT __BIT(17)
|
||||
#define PCIE_PL_PHY_CTRL_CAP_ADR __BIT(16)
|
||||
#define PCIE_PL_PHY_CTRL_DATA __BITS(0, 15)
|
||||
#define PCIE_PL_MRCCR0 0x00000818
|
||||
#define PCIE_PL_MRCCR1 0x0000081c
|
||||
#define PCIE_PL_MSICA 0x00000820
|
||||
#define PCIE_PL_MSICUA 0x00000824
|
||||
#define PCIE_PL_MSICIN_ENB 0x00000828
|
||||
#define PCIE_PL_MSICIN_MASK 0x0000082c
|
||||
#define PCIE_PL_MSICIN_STATUS 0x00000830
|
||||
#define PCIE_PL_MSICGPIO 0x00000888
|
||||
|
||||
// ATU_R_BaseAddress 0x900
|
||||
#define PCIE_PL_IATUVR 0x00000900
|
||||
// ATU_VIEWPORT_R (ATU_R_BaseAddress + 0x0)
|
||||
|
||||
#define PCIE_PL_IATURC1 0x00000904
|
||||
// ATU_REGION_CTRL1_R (ATU_R_BaseAddress + 0x4)
|
||||
#define PCIE_PL_IATURC1_FUNC __BITS(22, 20)
|
||||
#define PCIE_PL_IATURC1_AT __BITS(17, 16)
|
||||
#define PCIE_PL_IATURC1_ATTR __BITS(10, 9)
|
||||
#define PCIE_PL_IATURC1_TD __BIT(8)
|
||||
#define PCIE_PL_IATURC1_TC __BITS(7, 5)
|
||||
#define PCIE_PL_IATURC1_TYPE __BITS(4, 0)
|
||||
#define PCIE_PL_IATURC1_TYPE_IO __SHIFTIN(0, PCIE_PL_IATURC1_TYPE)
|
||||
#define PCIE_PL_IATURC1_TYPE_MEM __SHIFTIN(2, PCIE_PL_IATURC1_TYPE)
|
||||
#define PCIE_PL_IATURC1_TYPE_CFG0 __SHIFTIN(4, PCIE_PL_IATURC1_TYPE)
|
||||
#define PCIE_PL_IATURC1_TYPE_CFG1 __SHIFTIN(5, PCIE_PL_IATURC1_TYPE)
|
||||
|
||||
#define PCIE_PL_IATURC2 0x00000908
|
||||
// ATU_REGION_CTRL2_R (ATU_R_BaseAddress + 0x8)
|
||||
#define PCIE_PL_IATURC2_REGION_ENABLE __BIT(31)
|
||||
|
||||
#define PCIE_PL_IATURLBA 0x0000090c
|
||||
// ATU_REGION_LOWBASE_R (ATU_R_BaseAddress + 0xC)
|
||||
|
||||
#define PCIE_PL_IATURUBA 0x00000910
|
||||
// ATU_REGION_UPBASE_R (ATU_R_BaseAddress + 0x10)
|
||||
|
||||
#define PCIE_PL_IATURLA 0x00000914
|
||||
// ATU_REGION_LIMIT_ADDR_R (ATU_R_BaseAddress + 0x14)
|
||||
|
||||
#define PCIE_PL_IATURLTA 0x00000918
|
||||
// ATU_REGION_LOW_TRGT_ADDR_R (ATU_R_BaseAddress + 0x18)
|
||||
|
||||
#define PCIE_PL_IATURUTA 0x0000091c
|
||||
// ATU_REGION_UP_TRGT_ADDR_R (ATU_R_BaseAddress + 0x1C)
|
||||
|
||||
/* PCIe PHY registers */
|
||||
#define PCIE_PHY_IDCODE_LO 0x0000
|
||||
#define PCIE_PHY_IDCODE_HI 0x0001
|
||||
#define PCIE_PHY_DEBUG 0x0002
|
||||
#define PCIE_PHY_RTUNE_DEBUG 0x0003
|
||||
#define PCIE_PHY_RTUNE_STAT 0x0004
|
||||
#define PCIE_PHY_SS_PHASE 0x0005
|
||||
#define PCIE_PHY_SS_FREQ 0x0006
|
||||
#define PCIE_PHY_ATEOVRD 0x0010
|
||||
#define PCIE_PHY_MPLL_OVRD_IN_LO 0x0011
|
||||
#define PCIE_PHY_MPLL_OVRD_IN_HI 0x0011
|
||||
#define PCIE_PHY_SSC_OVRD_IN 0x0013
|
||||
#define PCIE_PHY_BS_OVRD_IN 0x0014
|
||||
#define PCIE_PHY_LEVEL_OVRD_IN 0x0015
|
||||
#define PCIE_PHY_SUP_OVRD_OUT 0x0016
|
||||
#define PCIE_PHY_MPLL_ASIC_IN 0x0017
|
||||
#define PCIE_PHY_BS_ASIC_IN 0x0018
|
||||
#define PCIE_PHY_LEVEL_ASIC_IN 0x0019
|
||||
#define PCIE_PHY_SSC_ASIC_IN 0x001a
|
||||
#define PCIE_PHY_SUP_ASIC_OUT 0x001b
|
||||
#define PCIE_PHY_ATEOVRD_STATUS 0x001c
|
||||
#define PCIE_PHY_SCOPE_ENABLES 0x0020
|
||||
#define PCIE_PHY_SCOPE_SAMPLES 0x0021
|
||||
#define PCIE_PHY_SCOPE_COUNT 0x0022
|
||||
#define PCIE_PHY_SCOPE_CTL 0x0023
|
||||
#define PCIE_PHY_SCOPE_MASK_000 0x0024
|
||||
#define PCIE_PHY_SCOPE_MASK_001 0x0025
|
||||
#define PCIE_PHY_SCOPE_MASK_010 0x0026
|
||||
#define PCIE_PHY_SCOPE_MASK_011 0x0027
|
||||
#define PCIE_PHY_SCOPE_MASK_100 0x0028
|
||||
#define PCIE_PHY_SCOPE_MASK_101 0x0029
|
||||
#define PCIE_PHY_SCOPE_MASK_110 0x002a
|
||||
#define PCIE_PHY_SCOPE_MASK_111 0x002b
|
||||
#define PCIE_PHY_MPLL_LOOP_CTL 0x0030
|
||||
#define PCIE_PHY_MPLL_ATB_MEAS2 0x0032
|
||||
#define PCIE_PHY_MPLL_OVR 0x0033
|
||||
#define PCIE_PHY_RTUNE_RTUNE_CTRL 0x0034
|
||||
#define PCIE_PHY_TX_OVRD_IN_LO 0x1000
|
||||
#define PCIE_PHY_TX_OVRD_IN_HI 0x1001
|
||||
#define PCIE_PHY_TX_OVRD_DRV_LO 0x1003
|
||||
#define PCIE_PHY_TX_OVRD_OUT 0x1004
|
||||
#define PCIE_PHY_RX_OVRD_IN_LO 0x1005
|
||||
#define PCIE_PHY_RX_OVRD_IN_LO_RX_PLL_EN_OVRD __BIT(3)
|
||||
#define PCIE_PHY_RX_OVRD_IN_LO_RX_DATA_EN_OVRD __BIT(5)
|
||||
#define PCIE_PHY_RX_OVRD_IN_HI 0x1006
|
||||
#define PCIE_PHY_RX_OVRD_OUT 0x1007
|
||||
#define PCIE_PHY_TX_ASIC_IN 0x1008
|
||||
#define PCIE_PHY_TX_ASIC_DRV_LO 0x1009
|
||||
#define PCIE_PHY_TX_ASIC_DRV_HI 0x100a
|
||||
#define PCIE_PHY_TX_ASIC_OUT 0x100b
|
||||
#define PCIE_PHY_RX_ASIC_IN 0x100c
|
||||
#define PCIE_PHY_RX_ASIC_OUT 0x100d
|
||||
#define PCIE_PHY_RX_ASIC_OUT_LOS __BIT(2)
|
||||
#define PCIE_PHY_RX_ASIC_OUT_PLL_STATE __BIT(1)
|
||||
#define PCIE_PHY_RX_ASIC_OUT_VALID __BIT(0)
|
||||
#define PCIE_PHY_TX_VMD_FSM_TX_VCM_0 0x1011
|
||||
#define PCIE_PHY_TX_VMD_FSM_TX_VCM_1 0x1012
|
||||
#define PCIE_PHY_TX_VMD_FSM_TX_VCM_DEBUG_IN 0x1013
|
||||
#define PCIE_PHY_TX_VMD_FSM_TX_VCM_DEBUG_OUT 0x1014
|
||||
#define PCIE_PHY_TX_LBERT_CTL 0x1015
|
||||
#define PCIE_PHY_RX_LBERT_CTL 0x1016
|
||||
#define PCIE_PHY_RX_LBERT_ERR 0x1017
|
||||
#define PCIE_PHY_RX_SCOPE_CTL 0x1018
|
||||
#define PCIE_PHY_RX_SCOPE_PHASE 0x1019
|
||||
#define PCIE_PHY_RX_DPLL_FREQ 0x101a
|
||||
#define PCIE_PHY_RX_CDR_CTL 0x101b
|
||||
#define PCIE_PHY_RX_CDR_CDR_FSM_DEBUG 0x101c
|
||||
#define PCIE_PHY_RX_CDR_LOCK_VEC_OVRD 0x101d
|
||||
#define PCIE_PHY_RX_CDR_LOCK_VEC 0x101e
|
||||
#define PCIE_PHY_RX_CDR_ADAP_FSM 0x101f
|
||||
#define PCIE_PHY_RX_ATB0 0x1020
|
||||
#define PCIE_PHY_RX_ATB1 0x1021
|
||||
#define PCIE_PHY_RX_ENPWR0 0x1022
|
||||
#define PCIE_PHY_RX_PMIX_PHASE 0x1023
|
||||
#define PCIE_PHY_RX_ENPWR1 0x1024
|
||||
#define PCIE_PHY_RX_ENPWR2 0x1025
|
||||
#define PCIE_PHY_RX_SCOPE 0x1026
|
||||
#define PCIE_PHY_TX_TXDRV_CNTRL 0x102b
|
||||
#define PCIE_PHY_TX_POWER_CTL 0x102c
|
||||
#define PCIE_PHY_TX_ALT_BLOCK 0x102d
|
||||
#define PCIE_PHY_TX_ALT_AND_LOOPBACK 0x102e
|
||||
#define PCIE_PHY_TX_TX_ATB_REG 0x102f
|
||||
|
||||
#endif /* _ARM_IMX_IMX6_PCIEREG_H_ */
|
|
@ -0,0 +1,158 @@
|
|||
#
|
||||
# $NetBSD: HUMMINGBOARD,v 1.1 2016/11/24 12:06:44 hkenken Exp $
|
||||
#
|
||||
# Hummingboard -- Freescale i.MX6 Eval Board Kernel
|
||||
#
|
||||
|
||||
include "arch/evbarm/conf/std.nitrogen6"
|
||||
include "arch/evbarm/conf/GENERIC.common"
|
||||
|
||||
# Board Type
|
||||
options EVBARM_BOARDTYPE=hummingboard
|
||||
#options EVBARM_BOARDTYPE=hummingboard_edge
|
||||
options HUMMINGBOARD
|
||||
|
||||
# CPU options
|
||||
options CPU_CORTEX
|
||||
options CPU_CORTEXA9
|
||||
options IMX6
|
||||
options MULTIPROCESSOR
|
||||
|
||||
# Console options. also need IMXUARTCONSOLE
|
||||
options CONSDEVNAME="\"imxuart\"",CONADDR=0x02020000
|
||||
options CONSPEED=115200 # Console speed
|
||||
|
||||
options DIAGNOSTIC # internal consistency checks
|
||||
options DEBUG
|
||||
#options KGDB
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
makeoptions COPY_SYMTAB=1
|
||||
|
||||
# Valid options for BOOT_ARGS:
|
||||
# single Boot to single user only
|
||||
# kdb Give control to kernel debugger
|
||||
# ask Ask for file name to reboot from
|
||||
# pmapdebug=<n> If PMAP_DEBUG, set pmap_debug_level to <n>
|
||||
# memorydisk=<n> Set memorydisk size to <n> KB
|
||||
# quiet Show aprint_naive output
|
||||
# verbose Show aprint_normal and aprint_verbose output
|
||||
options BOOT_ARGS="\"verbose\""
|
||||
|
||||
# Kernel root file system and dump configuration.
|
||||
#config netbsd root on ? type ?
|
||||
config netbsd-wd0 root on wd0 type ffs
|
||||
|
||||
#
|
||||
# Device configuration
|
||||
#
|
||||
|
||||
mainbus0 at root
|
||||
|
||||
cpu* at mainbus?
|
||||
|
||||
# The MPCore interrupt controller and global timer
|
||||
armperiph0 at mainbus? # A9 On-Chip Peripherals
|
||||
armgic0 at armperiph? # ARM Generic Interrupt Controller
|
||||
arml2cc0 at armperiph? flags 0 # ARM PL310 L2CC
|
||||
a9tmr0 at armperiph? # A9 Global Timer
|
||||
#a9wdt0 at armperiph? flags 0 # A9 Watchdog Timer
|
||||
|
||||
axi0 at mainbus?
|
||||
|
||||
# GPIO
|
||||
imxgpio0 at axi? addr 0x0209c000 irqbase 256 irq 98
|
||||
imxgpio1 at axi? addr 0x020a0000 irqbase 288 irq 100
|
||||
imxgpio2 at axi? addr 0x020a4000 irqbase 320 irq 102
|
||||
imxgpio3 at axi? addr 0x020a8000 irqbase 352 irq 104
|
||||
imxgpio4 at axi? addr 0x020ac000 irqbase 384 irq 106
|
||||
imxgpio5 at axi? addr 0x020b0000 irqbase 416 irq 108
|
||||
imxgpio6 at axi? addr 0x020b4000 irqbase 448 irq 110
|
||||
gpio* at imxgpio?
|
||||
options IMX_GPIO_INTR_SPLIT
|
||||
|
||||
# Clock Control
|
||||
imxccm0 at axi? addr 0x020c4000
|
||||
|
||||
# On-Chip OTP Controller
|
||||
imxocotp0 at axi? addr 0x021bc000
|
||||
|
||||
# IOMUX
|
||||
imxiomux0 at axi? addr 0x020e0000
|
||||
|
||||
# WatchDog
|
||||
imxwdog0 at axi? addr 0x020bc000 irq 112 flags 0
|
||||
#imxwdog1 at axi? addr 0x020c0000 irq 113 flags 0
|
||||
|
||||
# Serial
|
||||
imxuart0 at axi? addr 0x02020000 irq 58 # UART1
|
||||
#imxuart1 at axi? addr 0x021e8000 irq 59 # UART2
|
||||
#imxuart2 at axi? addr 0x021ec000 irq 60 # UART3
|
||||
#imxuart3 at axi? addr 0x021f0000 irq 61 # UART4
|
||||
#imxuart4 at axi? addr 0x021f4000 irq 62 # UART5
|
||||
options IMXUARTCONSOLE
|
||||
|
||||
# I2C
|
||||
imxi2c0 at axi? addr 0x021A0000 irq 68
|
||||
imxi2c1 at axi? addr 0x021A4000 irq 69
|
||||
imxi2c2 at axi? addr 0x021A8000 irq 70
|
||||
|
||||
# IIC
|
||||
iic* at imxi2c?
|
||||
|
||||
# SATA
|
||||
ahcisata* at axi? addr 0x02200000 irq 71
|
||||
atabus* at ahcisata? channel ?
|
||||
wd* at atabus? drive ? flags 0x0000
|
||||
|
||||
# ATAPI bus support
|
||||
atapibus* at atapi?
|
||||
|
||||
# ATAPI devices
|
||||
# flags have the same meaning as for IDE drives.
|
||||
cd* at atapibus? drive ? flags 0x0000 # ATAPI CD-ROM drives
|
||||
sd* at atapibus? drive ? flags 0x0000 # ATAPI disk drives
|
||||
st* at atapibus? drive ? flags 0x0000 # ATAPI tape drives
|
||||
uk* at atapibus? drive ? flags 0x0000 # ATAPI unknown
|
||||
|
||||
# Network Interfaces
|
||||
enet0 at axi? addr 0x02188000 irq 150 # iMX6 SoC Ethernet
|
||||
|
||||
# MII/PHY support
|
||||
atphy* at mii? phy ? # Attansic/Atheros PHYs
|
||||
ukphy* at mii? phy ? # generic unknown PHYs
|
||||
|
||||
# SD/MMC
|
||||
#sdhc0 at axi? addr 0x02190000 irq 54 # uSDHC1
|
||||
sdhc1 at axi? addr 0x02194000 irq 55 # uSDHC2
|
||||
#sdhc2 at axi? addr 0x02198000 irq 56 # uSDHC3
|
||||
#sdhc3 at axi? addr 0x0219c000 irq 57 # uSDHC4
|
||||
sdmmc* at sdhc?
|
||||
ld* at sdmmc? # MMC/SD card
|
||||
#options SDHC_DEBUG
|
||||
#options SDMMC_DEBUG
|
||||
|
||||
# USB
|
||||
imxusbc0 at axi? addr 0x02184000
|
||||
ehci0 at imxusbc0 unit 0 irq 75 # OTG
|
||||
ehci1 at imxusbc0 unit 1 irq 72 # Host1
|
||||
#ehci2 at imxusbc0 unit 2 irq 73 # Host2
|
||||
#ehci3 at imxusbc0 unit 3 irq 74 # Host3
|
||||
|
||||
usb* at ehci?
|
||||
|
||||
# USB device drivers
|
||||
include "dev/usb/usbdevices.config"
|
||||
|
||||
midi* at midibus?
|
||||
|
||||
# PCIe
|
||||
imxpcie0 at axi? addr 0x01ffc000 irq 155 # PCIe
|
||||
#options PCIVERBOSE
|
||||
#options PCI_CONFIG_DUMP
|
||||
|
||||
pci* at imxpcie0
|
||||
ppb* at pci? dev ? function ?
|
||||
pci* at ppb?
|
||||
|
||||
iwn* at pci? dev ? function ? # Intel PRO/Wireless 4965AGN
|
||||
iwm* at pci? dev ? function ? # Intel Centrino 7260
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: std.nitrogen6,v 1.3 2015/07/30 08:09:36 ryo Exp $
|
||||
# $NetBSD: std.nitrogen6,v 1.4 2016/11/24 12:06:44 hkenken Exp $
|
||||
#
|
||||
# standard NetBSD/evbarm options for Nitrogen6X
|
||||
|
||||
|
@ -14,6 +14,7 @@ options ARM_HAS_VBAR
|
|||
options __HAVE_CPU_COUNTER
|
||||
options __HAVE_FAST_SOFTINTS # should be in types.h
|
||||
options TPIDRPRW_IS_CURCPU
|
||||
options PCI_NETBSD_CONFIGURE
|
||||
|
||||
makeoptions CPUFLAGS="-mcpu=cortex-a9"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nitrogen6_iomux.c,v 1.2 2015/12/31 11:53:19 ryo Exp $ */
|
||||
/* $NetBSD: nitrogen6_iomux.c,v 1.3 2016/11/24 12:06:44 hkenken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Ryo Shimizu <ryo@nerv.org>
|
||||
|
@ -26,7 +26,7 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nitrogen6_iomux.c,v 1.2 2015/12/31 11:53:19 ryo Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nitrogen6_iomux.c,v 1.3 2016/11/24 12:06:44 hkenken Exp $");
|
||||
|
||||
#include "opt_evbarm_boardtype.h"
|
||||
#include <sys/bus.h>
|
||||
|
@ -52,10 +52,11 @@ static void nitrogen6_mux_config(const struct iomux_conf *);
|
|||
static void nitrogen6_gpio_config(const struct gpio_conf *);
|
||||
|
||||
|
||||
#define nitrogen6x 1
|
||||
#define nitrogen6max 2
|
||||
#define cubox_i 3
|
||||
#define hummingboard 4
|
||||
#define nitrogen6x 1
|
||||
#define nitrogen6max 2
|
||||
#define cubox_i 3
|
||||
#define hummingboard 4
|
||||
#define hummingboard_edge 5
|
||||
|
||||
#define PAD_UART \
|
||||
(PAD_CTL_HYS | PAD_CTL_PUS_100K_PU | PAD_CTL_PULL | \
|
||||
|
@ -111,6 +112,10 @@ static void nitrogen6_gpio_config(const struct gpio_conf *);
|
|||
PAD_CTL_SPEED_100MHZ | PAD_CTL_DSE_40OHM | PAD_CTL_SRE_SLOW)
|
||||
#define PAD_OUTPUT_40OHM (PAD_CTL_SPEED_100MHZ | PAD_CTL_DSE_40OHM)
|
||||
|
||||
#define PAD_PCIE_GPIO \
|
||||
(PAD_CTL_HYS | PAD_CTL_PUS_22K_PU | PAD_CTL_PULL | \
|
||||
PAD_CTL_SPEED_50MHZ | PAD_CTL_DSE_40OHM | PAD_CTL_SRE_FAST)
|
||||
|
||||
|
||||
/* iMX6 SoloLite */
|
||||
static const struct iomux_conf iomux_data_6sl[] = {
|
||||
|
@ -176,7 +181,8 @@ static const struct iomux_conf iomux_data_6sdl[] = {
|
|||
.pad = 0
|
||||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard)
|
||||
#if (EVBARM_BOARDTYPE == hummingboard) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
{
|
||||
.pin = MUX_PIN(IMX6SDL, GPIO05),
|
||||
.mux = IOMUX_CONFIG_ALT3, /* CCM_CLKO1 */
|
||||
|
@ -184,7 +190,8 @@ static const struct iomux_conf iomux_data_6sdl[] = {
|
|||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == cubox_i) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard)
|
||||
(EVBARM_BOARDTYPE == hummingboard) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
{
|
||||
.pin = MUX_PIN(IMX6SDL, EIM_DATA22),
|
||||
.mux = IOMUX_CONFIG_ALT5, /* GPIO3_IO22 */
|
||||
|
@ -407,15 +414,33 @@ static const struct iomux_conf iomux_data_6dq[] = {
|
|||
.pad = 0
|
||||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard)
|
||||
#if (EVBARM_BOARDTYPE == hummingboard) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
{
|
||||
.pin = MUX_PIN(IMX6DQ, GPIO05),
|
||||
.mux = IOMUX_CONFIG_ALT3, /* CCM_CLKO1 */
|
||||
.pad = PAD_USB
|
||||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard)
|
||||
/* PCIe */
|
||||
{
|
||||
.pin = MUX_PIN(IMX6DQ, EIM_AD04),
|
||||
.mux = IOMUX_CONFIG_ALT5,
|
||||
.pad = PAD_PCIE_GPIO
|
||||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
/* PCIe */
|
||||
{
|
||||
.pin = MUX_PIN(IMX6DQ, SD4_DATA3),
|
||||
.mux = IOMUX_CONFIG_ALT5,
|
||||
.pad = PAD_PCIE_GPIO
|
||||
},
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == cubox_i) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard)
|
||||
(EVBARM_BOARDTYPE == hummingboard) || \
|
||||
(EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
{
|
||||
.pin = MUX_PIN(IMX6DQ, EIM_DATA22),
|
||||
.mux = IOMUX_CONFIG_ALT5, /* GPIO3_IO22 */
|
||||
|
@ -456,6 +481,13 @@ static const struct gpio_conf gpio_data[] = {
|
|||
{ 3, 22, GPIO_DIR_OUT, 1 }, /* USB OTG */
|
||||
{ 1, 0, GPIO_DIR_OUT, 1 }, /* USB H1 */
|
||||
{ 1, 4, GPIO_DIR_IN, 0 }, /* USDHC2 */
|
||||
{ 3, 4, GPIO_DIR_OUT, 0 }, /* PCIe */
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
{ 3, 22, GPIO_DIR_OUT, 1 }, /* USB OTG */
|
||||
{ 1, 0, GPIO_DIR_OUT, 1 }, /* USB H1 */
|
||||
{ 1, 4, GPIO_DIR_IN, 0 }, /* USDHC2 */
|
||||
{ 2, 11, GPIO_DIR_OUT, 0 }, /* PCIe */
|
||||
#endif
|
||||
|
||||
/* end of table */
|
||||
|
@ -553,6 +585,18 @@ nitrogen6_device_register(device_t self, void *aux)
|
|||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard)
|
||||
prop_dictionary_set_cstring(dict, "usdhc2-cd-gpio", "!1,4");
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
prop_dictionary_set_cstring(dict, "usdhc2-cd-gpio", "!1,4");
|
||||
#endif
|
||||
}
|
||||
if (device_is_a(self, "imxpcie") &&
|
||||
device_is_a(device_parent(self), "axi")) {
|
||||
#if (EVBARM_BOARDTYPE == hummingboard)
|
||||
prop_dictionary_set_cstring(dict, "imx6pcie-reset-gpio", "!3,4");
|
||||
#endif
|
||||
#if (EVBARM_BOARDTYPE == hummingboard_edge)
|
||||
prop_dictionary_set_cstring(dict, "imx6pcie-reset-gpio", "!2,11");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue