Merge remote branch 'origin' into secretlab/next-devicetree
Merging in current state of Linus' tree to deal with merge conflicts and build failures in vio.c after merge. Conflicts: drivers/i2c/busses/i2c-cpm.c drivers/i2c/busses/i2c-mpc.c drivers/net/gianfar.c Also fixed up one line in arch/powerpc/kernel/vio.c to use the correct node pointer. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
@@ -20,9 +20,6 @@
|
||||
* or rx, so this should be okay.
|
||||
*
|
||||
* TODO:
|
||||
* - Fix driver to work on more than just Virtex5. Right now the driver
|
||||
* assumes that the locallink DMA registers are accessed via DCR
|
||||
* instructions.
|
||||
* - Factor out locallink DMA code into separate driver
|
||||
* - Fix multicast assignment.
|
||||
* - Fix support for hardware checksumming.
|
||||
@@ -116,16 +113,85 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
|
||||
temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* temac_dma_in32 - Memory mapped DMA read, this function expects a
|
||||
* register input that is based on DCR word addresses which
|
||||
* are then converted to memory mapped byte addresses
|
||||
*/
|
||||
static u32 temac_dma_in32(struct temac_local *lp, int reg)
|
||||
{
|
||||
return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* temac_dma_out32 - Memory mapped DMA read, this function expects a
|
||||
* register input that is based on DCR word addresses which
|
||||
* are then converted to memory mapped byte addresses
|
||||
*/
|
||||
static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
|
||||
{
|
||||
out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
|
||||
}
|
||||
|
||||
/* DMA register access functions can be DCR based or memory mapped.
|
||||
* The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
|
||||
* memory mapped.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_DCR
|
||||
|
||||
/**
|
||||
* temac_dma_dcr_in32 - DCR based DMA read
|
||||
*/
|
||||
static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
|
||||
{
|
||||
return dcr_read(lp->sdma_dcrs, reg);
|
||||
}
|
||||
|
||||
static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
|
||||
/**
|
||||
* temac_dma_dcr_out32 - DCR based DMA write
|
||||
*/
|
||||
static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
|
||||
{
|
||||
dcr_write(lp->sdma_dcrs, reg, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* temac_dcr_setup - If the DMA is DCR based, then setup the address and
|
||||
* I/O functions
|
||||
*/
|
||||
static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
|
||||
struct device_node *np)
|
||||
{
|
||||
unsigned int dcrs;
|
||||
|
||||
/* setup the dcr address mapping if it's in the device tree */
|
||||
|
||||
dcrs = dcr_resource_start(np, 0);
|
||||
if (dcrs != 0) {
|
||||
lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
|
||||
lp->dma_in = temac_dma_dcr_in;
|
||||
lp->dma_out = temac_dma_dcr_out;
|
||||
dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
|
||||
return 0;
|
||||
}
|
||||
/* no DCR in the device tree, indicate a failure */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* temac_dcr_setup - This is a stub for when DCR is not supported,
|
||||
* such as with MicroBlaze
|
||||
*/
|
||||
static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
|
||||
struct device_node *np)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* temac_dma_bd_init - Setup buffer descriptor rings
|
||||
*/
|
||||
@@ -156,14 +222,14 @@ static int temac_dma_bd_init(struct net_device *ndev)
|
||||
lp->rx_bd_v[i].next = lp->rx_bd_p +
|
||||
sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
|
||||
|
||||
skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE
|
||||
+ XTE_ALIGN, GFP_ATOMIC);
|
||||
skb = netdev_alloc_skb_ip_align(ndev,
|
||||
XTE_MAX_JUMBO_FRAME_SIZE);
|
||||
|
||||
if (skb == 0) {
|
||||
dev_err(&ndev->dev, "alloc_skb error %d\n", i);
|
||||
return -1;
|
||||
}
|
||||
lp->rx_skb[i] = skb;
|
||||
skb_reserve(skb, BUFFER_ALIGN(skb->data));
|
||||
/* returns physical address of skb->data */
|
||||
lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
|
||||
skb->data,
|
||||
@@ -173,23 +239,23 @@ static int temac_dma_bd_init(struct net_device *ndev)
|
||||
lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
|
||||
}
|
||||
|
||||
temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 |
|
||||
lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
|
||||
CHNL_CTRL_IRQ_EN |
|
||||
CHNL_CTRL_IRQ_DLY_EN |
|
||||
CHNL_CTRL_IRQ_COAL_EN);
|
||||
/* 0x10220483 */
|
||||
/* 0x00100483 */
|
||||
temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 |
|
||||
lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
|
||||
CHNL_CTRL_IRQ_EN |
|
||||
CHNL_CTRL_IRQ_DLY_EN |
|
||||
CHNL_CTRL_IRQ_COAL_EN |
|
||||
CHNL_CTRL_IRQ_IOE);
|
||||
/* 0xff010283 */
|
||||
|
||||
temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p);
|
||||
temac_dma_out32(lp, RX_TAILDESC_PTR,
|
||||
lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p);
|
||||
lp->dma_out(lp, RX_TAILDESC_PTR,
|
||||
lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
|
||||
temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p);
|
||||
lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -251,20 +317,20 @@ static void temac_set_multicast_list(struct net_device *ndev)
|
||||
temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK);
|
||||
dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
|
||||
} else if (!netdev_mc_empty(ndev)) {
|
||||
struct dev_mc_list *mclist;
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
i = 0;
|
||||
netdev_for_each_mc_addr(mclist, ndev) {
|
||||
netdev_for_each_mc_addr(ha, ndev) {
|
||||
if (i >= MULTICAST_CAM_TABLE_NUM)
|
||||
break;
|
||||
multi_addr_msw = ((mclist->dmi_addr[3] << 24) |
|
||||
(mclist->dmi_addr[2] << 16) |
|
||||
(mclist->dmi_addr[1] << 8) |
|
||||
(mclist->dmi_addr[0]));
|
||||
multi_addr_msw = ((ha->addr[3] << 24) |
|
||||
(ha->addr[2] << 16) |
|
||||
(ha->addr[1] << 8) |
|
||||
(ha->addr[0]));
|
||||
temac_indirect_out32(lp, XTE_MAW0_OFFSET,
|
||||
multi_addr_msw);
|
||||
multi_addr_lsw = ((mclist->dmi_addr[5] << 8) |
|
||||
(mclist->dmi_addr[4]) | (i << 16));
|
||||
multi_addr_lsw = ((ha->addr[5] << 8) |
|
||||
(ha->addr[4]) | (i << 16));
|
||||
temac_indirect_out32(lp, XTE_MAW1_OFFSET,
|
||||
multi_addr_lsw);
|
||||
i++;
|
||||
@@ -427,9 +493,9 @@ static void temac_device_reset(struct net_device *ndev)
|
||||
temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
|
||||
|
||||
/* Reset Local Link (DMA) */
|
||||
temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
|
||||
lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
|
||||
timeout = 1000;
|
||||
while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
|
||||
while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
|
||||
udelay(1);
|
||||
if (--timeout == 0) {
|
||||
dev_err(&ndev->dev,
|
||||
@@ -437,7 +503,7 @@ static void temac_device_reset(struct net_device *ndev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
|
||||
lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
|
||||
|
||||
temac_dma_bd_init(ndev);
|
||||
|
||||
@@ -461,7 +527,7 @@ static void temac_device_reset(struct net_device *ndev)
|
||||
dev_err(&ndev->dev, "Error setting TEMAC options\n");
|
||||
|
||||
/* Init Driver variable */
|
||||
ndev->trans_start = 0;
|
||||
ndev->trans_start = jiffies; /* prevent tx timeout */
|
||||
}
|
||||
|
||||
void temac_adjust_link(struct net_device *ndev)
|
||||
@@ -598,7 +664,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
lp->tx_bd_tail = 0;
|
||||
|
||||
/* Kick off the transfer */
|
||||
temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
|
||||
lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
@@ -612,7 +678,6 @@ static void ll_temac_recv(struct net_device *ndev)
|
||||
struct cdmac_bd *cur_p;
|
||||
dma_addr_t tail_p;
|
||||
int length;
|
||||
unsigned long skb_vaddr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&lp->rx_lock, flags);
|
||||
@@ -626,8 +691,7 @@ static void ll_temac_recv(struct net_device *ndev)
|
||||
skb = lp->rx_skb[lp->rx_bd_ci];
|
||||
length = cur_p->app4 & 0x3FFF;
|
||||
|
||||
skb_vaddr = virt_to_bus(skb->data);
|
||||
dma_unmap_single(ndev->dev.parent, skb_vaddr, length,
|
||||
dma_unmap_single(ndev->dev.parent, cur_p->phys, length,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
skb_put(skb, length);
|
||||
@@ -640,16 +704,15 @@ static void ll_temac_recv(struct net_device *ndev)
|
||||
ndev->stats.rx_packets++;
|
||||
ndev->stats.rx_bytes += length;
|
||||
|
||||
new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN,
|
||||
GFP_ATOMIC);
|
||||
new_skb = netdev_alloc_skb_ip_align(ndev,
|
||||
XTE_MAX_JUMBO_FRAME_SIZE);
|
||||
|
||||
if (new_skb == 0) {
|
||||
dev_err(&ndev->dev, "no memory for new sk_buff\n");
|
||||
spin_unlock_irqrestore(&lp->rx_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data));
|
||||
|
||||
cur_p->app0 = STS_CTRL_APP0_IRQONEND;
|
||||
cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
|
||||
XTE_MAX_JUMBO_FRAME_SIZE,
|
||||
@@ -664,7 +727,7 @@ static void ll_temac_recv(struct net_device *ndev)
|
||||
cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
|
||||
bdstat = cur_p->app0;
|
||||
}
|
||||
temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p);
|
||||
lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
|
||||
|
||||
spin_unlock_irqrestore(&lp->rx_lock, flags);
|
||||
}
|
||||
@@ -675,8 +738,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
|
||||
struct temac_local *lp = netdev_priv(ndev);
|
||||
unsigned int status;
|
||||
|
||||
status = temac_dma_in32(lp, TX_IRQ_REG);
|
||||
temac_dma_out32(lp, TX_IRQ_REG, status);
|
||||
status = lp->dma_in(lp, TX_IRQ_REG);
|
||||
lp->dma_out(lp, TX_IRQ_REG, status);
|
||||
|
||||
if (status & (IRQ_COAL | IRQ_DLY))
|
||||
temac_start_xmit_done(lp->ndev);
|
||||
@@ -693,8 +756,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
|
||||
unsigned int status;
|
||||
|
||||
/* Read and clear the status registers */
|
||||
status = temac_dma_in32(lp, RX_IRQ_REG);
|
||||
temac_dma_out32(lp, RX_IRQ_REG, status);
|
||||
status = lp->dma_in(lp, RX_IRQ_REG);
|
||||
lp->dma_out(lp, RX_IRQ_REG, status);
|
||||
|
||||
if (status & (IRQ_COAL | IRQ_DLY))
|
||||
ll_temac_recv(lp->ndev);
|
||||
@@ -795,7 +858,7 @@ static ssize_t temac_show_llink_regs(struct device *dev,
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < 0x11; i++)
|
||||
len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i),
|
||||
len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
|
||||
(i % 8) == 7 ? "\n" : " ");
|
||||
len += sprintf(buf + len, "\n");
|
||||
|
||||
@@ -821,7 +884,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
||||
struct net_device *ndev;
|
||||
const void *addr;
|
||||
int size, rc = 0;
|
||||
unsigned int dcrs;
|
||||
|
||||
/* Init network device structure */
|
||||
ndev = alloc_etherdev(sizeof(*lp));
|
||||
@@ -871,13 +933,20 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
||||
goto nodev;
|
||||
}
|
||||
|
||||
dcrs = dcr_resource_start(np, 0);
|
||||
if (dcrs == 0) {
|
||||
dev_err(&op->dev, "could not get DMA register address\n");
|
||||
goto nodev;
|
||||
/* Setup the DMA register accesses, could be DCR or memory mapped */
|
||||
if (temac_dcr_setup(lp, op, np)) {
|
||||
|
||||
/* no DCR in the device tree, try non-DCR */
|
||||
lp->sdma_regs = of_iomap(np, 0);
|
||||
if (lp->sdma_regs) {
|
||||
lp->dma_in = temac_dma_in32;
|
||||
lp->dma_out = temac_dma_out32;
|
||||
dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
|
||||
} else {
|
||||
dev_err(&op->dev, "unable to map DMA registers\n");
|
||||
goto nodev;
|
||||
}
|
||||
}
|
||||
lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
|
||||
dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
|
||||
|
||||
lp->rx_irq = irq_of_parse_and_map(np, 0);
|
||||
lp->tx_irq = irq_of_parse_and_map(np, 1);
|
||||
|
Reference in New Issue
Block a user