Commit e175587f authored by Nicolas Ferre's avatar Nicolas Ferre Committed by David S. Miller
Browse files

net/macb: configure for FIFO mode and non-gigabit



This addition will also allow to configure DMA burst length.

Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: default avatarCyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ef492001
Loading
Loading
Loading
Loading
+57 −18
Original line number Diff line number Diff line
@@ -264,7 +264,8 @@ static void macb_handle_link_change(struct net_device *dev)
				reg |= MACB_BIT(FD);
			if (phydev->speed == SPEED_100)
				reg |= MACB_BIT(SPD);
			if (phydev->speed == SPEED_1000)
			if (phydev->speed == SPEED_1000 &&
			    bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
				reg |= GEM_BIT(GBE);

			macb_or_gem_writel(bp, NCFGR, reg);
@@ -337,7 +338,7 @@ static int macb_mii_probe(struct net_device *dev)
	}

	/* mask with MAC supported features */
	if (macb_is_gem(bp))
	if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
		phydev->supported &= PHY_GBIT_FEATURES;
	else
		phydev->supported &= PHY_BASIC_FEATURES;
@@ -1342,7 +1343,7 @@ static u32 macb_dbw(struct macb *bp)
/*
 * Configure the receive DMA engine
 * - use the correct receive buffer size
 * - set the possibility to use INCR16 bursts
 * - set best burst length for DMA operations
 *   (if not supported by FIFO, it will fallback to default)
 * - set both rx/tx packet buffers to full memory size
 * These are configurable parameters for GEM.
@@ -1354,24 +1355,16 @@ static void macb_configure_dma(struct macb *bp)
	if (macb_is_gem(bp)) {
		dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
		dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
		dmacfg |= GEM_BF(FBLDO, 16);
		if (bp->dma_burst_length)
			dmacfg = GEM_BFINS(FBLDO, bp->dma_burst_length, dmacfg);
		dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
		dmacfg &= ~GEM_BIT(ENDIA);
		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
			   dmacfg);
		gem_writel(bp, DMACFG, dmacfg);
	}
}

/*
 * Configure peripheral capacities according to integration options used
 */
static void macb_configure_caps(struct macb *bp)
{
	if (macb_is_gem(bp)) {
		if (GEM_BFEXT(IRQCOR, gem_readl(bp, DCFG1)) == 0)
			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
	}
}

static void macb_init_hw(struct macb *bp)
{
	u32 config;
@@ -1394,7 +1387,6 @@ static void macb_init_hw(struct macb *bp)
	bp->duplex = DUPLEX_HALF;

	macb_configure_dma(bp);
	macb_configure_caps(bp);

	/* Initialize TX and RX buffers */
	macb_writel(bp, RBQP, bp->rx_ring_dma);
@@ -1783,17 +1775,61 @@ static const struct net_device_ops macb_netdev_ops = {
};

#if defined(CONFIG_OF)
static struct macb_config pc302gem_config = {
	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE,
	.dma_burst_length = 16,
};

static const struct of_device_id macb_dt_ids[] = {
	{ .compatible = "cdns,at32ap7000-macb" },
	{ .compatible = "cdns,at91sam9260-macb" },
	{ .compatible = "cdns,macb" },
	{ .compatible = "cdns,pc302-gem" },
	{ .compatible = "cdns,gem" },
	{ .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
	{ .compatible = "cdns,gem", .data = &pc302gem_config },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
#endif

/*
 * Configure peripheral capacities according to device tree
 * and integration options used
 */
static void macb_configure_caps(struct macb *bp)
{
	u32 dcfg;
	const struct of_device_id *match;
	const struct macb_config *config;

	if (bp->pdev->dev.of_node) {
		match = of_match_node(macb_dt_ids, bp->pdev->dev.of_node);
		if (match && match->data) {
			config = (const struct macb_config *)match->data;

			bp->caps = config->caps;
			/*
			 * As we have access to the matching node, configure
			 * DMA burst length as well
			 */
			bp->dma_burst_length = config->dma_burst_length;
		}
	}

	if (MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2)
		bp->caps |= MACB_CAPS_MACB_IS_GEM;

	if (macb_is_gem(bp)) {
		dcfg = gem_readl(bp, DCFG1);
		if (GEM_BFEXT(IRQCOR, dcfg) == 0)
			bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
		dcfg = gem_readl(bp, DCFG2);
		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
			bp->caps |= MACB_CAPS_FIFO_MODE;
	}

	netdev_dbg(bp->dev, "Cadence caps 0x%08x\n", bp->caps);
}

static int __init macb_probe(struct platform_device *pdev)
{
	struct macb_platform_data *pdata;
@@ -1897,6 +1933,9 @@ static int __init macb_probe(struct platform_device *pdev)

	dev->base_addr = regs->start;

	/* setup capacities */
	macb_configure_caps(bp);

	/* setup appropriated routines according to adapter type */
	if (macb_is_gem(bp)) {
		bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
+17 −2
Original line number Diff line number Diff line
@@ -305,6 +305,12 @@
#define GEM_DBWDEF_OFFSET			25
#define GEM_DBWDEF_SIZE				3

/* Bitfields in DCFG2. */
#define GEM_RX_PKT_BUFF_OFFSET			20
#define GEM_RX_PKT_BUFF_SIZE			1
#define GEM_TX_PKT_BUFF_OFFSET			21
#define GEM_TX_PKT_BUFF_SIZE			1

/* Constants for CLK */
#define MACB_CLK_DIV8				0
#define MACB_CLK_DIV16				1
@@ -326,7 +332,10 @@
#define MACB_MAN_CODE				2

/* Capability mask bits */
#define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x1
#define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x00000001
#define MACB_CAPS_FIFO_MODE			0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
#define MACB_CAPS_MACB_IS_GEM			0x80000000

/* Bit manipulation macros */
#define MACB_BIT(name)					\
@@ -554,6 +563,11 @@ struct macb_or_gem_ops {
	int	(*mog_rx)(struct macb *bp, int budget);
};

struct macb_config {
	u32			caps;
	unsigned int		dma_burst_length;
};

struct macb {
	void __iomem		*regs;

@@ -595,6 +609,7 @@ struct macb {
	unsigned int 		duplex;

	u32			caps;
	unsigned int		dma_burst_length;

	phy_interface_t		phy_interface;

@@ -615,7 +630,7 @@ void macb_get_hwaddr(struct macb *bp);

static inline bool macb_is_gem(struct macb *bp)
{
	return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
}

#endif /* _MACB_H */