From e446630c960946b5c1762e4eadb618becef599e7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 29 Mar 2010 08:57:56 +0000 Subject: Add hotplug support to mcp251x driver Chip model can now be selected directly by matching the modalias name (instead of filling the .model field in platform_data), and allows the module to be auto-loaded. Previous behaviour is of course still supported. Convert the two in-tree users to this feature (icontrol & zeus). Tested on an Zeus platform (mcp2515). Signed-off-by: Marc Zyngier Acked-by: Christian Pellegrin Cc: Edwin Peer Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- arch/arm/mach-pxa/icontrol.c | 9 ++++----- arch/arm/mach-pxa/zeus.c | 4 +--- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index 771137fc1a82..5ccb0ceff6c4 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -73,7 +73,6 @@ static struct pxa2xx_spi_chip mcp251x_chip_info4 = { static struct mcp251x_platform_data mcp251x_info = { .oscillator_frequency = 16E6, - .model = CAN_MCP251X_MCP2515, .board_specific_setup = NULL, .power_enable = NULL, .transceiver_enable = NULL @@ -81,7 +80,7 @@ static struct mcp251x_platform_data mcp251x_info = { static struct spi_board_info mcp251x_board_info[] = { { - .modalias = "mcp251x", + .modalias = "mcp2515", .max_speed_hz = 6500000, .bus_num = 3, .chip_select = 0, @@ -90,7 +89,7 @@ static struct spi_board_info mcp251x_board_info[] = { .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ1) }, { - .modalias = "mcp251x", + .modalias = "mcp2515", .max_speed_hz = 6500000, .bus_num = 3, .chip_select = 1, @@ -99,7 +98,7 @@ static struct spi_board_info mcp251x_board_info[] = { .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ2) }, { - .modalias = "mcp251x", + .modalias = "mcp2515", .max_speed_hz = 6500000, .bus_num = 4, .chip_select = 0, @@ -108,7 +107,7 @@ static struct spi_board_info mcp251x_board_info[] = { .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ3) }, { - .modalias = "mcp251x", + .modalias = "mcp2515", .max_speed_hz = 6500000, .bus_num = 4, .chip_select = 1, diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 39896d883584..dbd256966379 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -414,15 +414,13 @@ static int zeus_mcp2515_transceiver_enable(int enable) static struct mcp251x_platform_data zeus_mcp2515_pdata = { .oscillator_frequency = 16*1000*1000, - .model = CAN_MCP251X_MCP2515, .board_specific_setup = zeus_mcp2515_setup, - .transceiver_enable = zeus_mcp2515_transceiver_enable, .power_enable = zeus_mcp2515_transceiver_enable, }; static struct spi_board_info zeus_spi_board_info[] = { [0] = { - .modalias = "mcp251x", + .modalias = "mcp2515", .platform_data = &zeus_mcp2515_pdata, .irq = gpio_to_irq(ZEUS_CAN_GPIO), .max_speed_hz = 1*1000*1000, -- cgit v1.2.3-58-ga151 From 459569145516f7967b916c57445feb02c600668c Mon Sep 17 00:00:00 2001 From: John Linn Date: Tue, 6 Apr 2010 11:43:28 +0000 Subject: Add non-Virtex5 support for LL TEMAC driver This patch adds support for using the LL TEMAC Ethernet driver on non-Virtex 5 platforms by adding support for accessing the Soft DMA registers as if they were memory mapped instead of solely through the DCR's (available on the Virtex 5). The patch also updates the driver so that it runs on the MicroBlaze. The changes were tested on the PowerPC 440, PowerPC 405, and the MicroBlaze platforms. Signed-off-by: John Tyner Signed-off-by: John Linn Signed-off-by: David S. Miller --- arch/microblaze/include/asm/system.h | 11 +++ drivers/net/Kconfig | 2 +- drivers/net/ll_temac.h | 14 +++- drivers/net/ll_temac_main.c | 137 ++++++++++++++++++++++++++--------- 4 files changed, 126 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index 157970688b2a..88fc92cdd8ce 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -93,4 +94,14 @@ extern struct dentry *of_debugfs_root; #define arch_align_stack(x) (x) +/* + * MicroBlaze doesn't handle unaligned accesses in hardware. + * + * Based on this we force the IP header alignment in network drivers. + * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining + * cacheline alignment of buffers. + */ +#define NET_IP_ALIGN 2 +#define NET_SKB_PAD L1_CACHE_BYTES + #endif /* _ASM_MICROBLAZE_SYSTEM_H */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a55bff26a264..20e2dec1d534 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2435,8 +2435,8 @@ config MV643XX_ETH config XILINX_LL_TEMAC tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" + depends on PPC || MICROBLAZE select PHYLIB - depends on PPC_DCR_NATIVE help This driver supports the Xilinx 10/100/1000 LocalLink TEMAC core used in Xilinx Spartan and Virtex FPGAs diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h index 1af66a1e6911..c03358434acb 100644 --- a/drivers/net/ll_temac.h +++ b/drivers/net/ll_temac.h @@ -5,8 +5,11 @@ #include #include #include + +#ifdef CONFIG_PPC_DCR #include #include +#endif /* packet size info */ #define XTE_HDR_SIZE 14 /* size of Ethernet header */ @@ -290,9 +293,6 @@ This option defaults to enabled (set) */ #define TX_CONTROL_CALC_CSUM_MASK 1 -#define XTE_ALIGN 32 -#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN) - #define MULTICAST_CAM_TABLE_NUM 4 /* TX/RX CURDESC_PTR points to first descriptor */ @@ -335,9 +335,15 @@ struct temac_local { struct mii_bus *mii_bus; /* MII bus reference */ int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ - /* IO registers and IRQs */ + /* IO registers, dma functions and IRQs */ void __iomem *regs; + void __iomem *sdma_regs; +#ifdef CONFIG_PPC_DCR dcr_host_t sdma_dcrs; +#endif + u32 (*dma_in)(struct temac_local *, int); + void (*dma_out)(struct temac_local *, int, u32); + int tx_irq; int rx_irq; int emac_num; diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 30474d6b15c3..b6edb2fd0a8a 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -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. @@ -115,16 +112,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 dcr_read(lp->sdma_dcrs, 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); +} + +/** + * 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 */ @@ -155,14 +221,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, @@ -172,23 +238,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; } @@ -426,9 +492,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, @@ -436,7 +502,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); @@ -597,7 +663,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; } @@ -639,16 +705,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, @@ -663,7 +728,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); } @@ -674,8 +739,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); @@ -692,8 +757,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); @@ -794,7 +859,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"); @@ -820,7 +885,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)); @@ -870,13 +934,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); -- cgit v1.2.3-58-ga151 From 4d8dc679084d8dd7b81b2ae245844246deb0759c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 7 Apr 2010 23:28:28 -0700 Subject: Revert "Add non-Virtex5 support for LL TEMAC driver" This reverts commit 459569145516f7967b916c57445feb02c600668c. Uses virt_to_bus() and breaks the build. Signed-off-by: David S. Miller --- arch/microblaze/include/asm/system.h | 11 --- drivers/net/Kconfig | 2 +- drivers/net/ll_temac.h | 14 +--- drivers/net/ll_temac_main.c | 137 +++++++++-------------------------- 4 files changed, 38 insertions(+), 126 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index 48c4f0335e3f..59efb3fef957 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -97,14 +96,4 @@ extern struct dentry *of_debugfs_root; #define arch_align_stack(x) (x) -/* - * MicroBlaze doesn't handle unaligned accesses in hardware. - * - * Based on this we force the IP header alignment in network drivers. - * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining - * cacheline alignment of buffers. - */ -#define NET_IP_ALIGN 2 -#define NET_SKB_PAD L1_CACHE_BYTES - #endif /* _ASM_MICROBLAZE_SYSTEM_H */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dbd26f992158..49c372a5e0b7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2435,8 +2435,8 @@ config MV643XX_ETH config XILINX_LL_TEMAC tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" - depends on PPC || MICROBLAZE select PHYLIB + depends on PPC_DCR_NATIVE help This driver supports the Xilinx 10/100/1000 LocalLink TEMAC core used in Xilinx Spartan and Virtex FPGAs diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h index c03358434acb..1af66a1e6911 100644 --- a/drivers/net/ll_temac.h +++ b/drivers/net/ll_temac.h @@ -5,11 +5,8 @@ #include #include #include - -#ifdef CONFIG_PPC_DCR #include #include -#endif /* packet size info */ #define XTE_HDR_SIZE 14 /* size of Ethernet header */ @@ -293,6 +290,9 @@ This option defaults to enabled (set) */ #define TX_CONTROL_CALC_CSUM_MASK 1 +#define XTE_ALIGN 32 +#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN) + #define MULTICAST_CAM_TABLE_NUM 4 /* TX/RX CURDESC_PTR points to first descriptor */ @@ -335,15 +335,9 @@ struct temac_local { struct mii_bus *mii_bus; /* MII bus reference */ int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ - /* IO registers, dma functions and IRQs */ + /* IO registers and IRQs */ void __iomem *regs; - void __iomem *sdma_regs; -#ifdef CONFIG_PPC_DCR dcr_host_t sdma_dcrs; -#endif - u32 (*dma_in)(struct temac_local *, int); - void (*dma_out)(struct temac_local *, int, u32); - int tx_irq; int rx_irq; int emac_num; diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index b6edb2fd0a8a..30474d6b15c3 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -20,6 +20,9 @@ * 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. @@ -112,85 +115,16 @@ 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); } -/** - * temac_dma_dcr_out32 - DCR based DMA write - */ -static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) +static void temac_dma_out32(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 */ @@ -221,14 +155,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 = netdev_alloc_skb_ip_align(ndev, - XTE_MAX_JUMBO_FRAME_SIZE); - + skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + + XTE_ALIGN, GFP_ATOMIC); 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, @@ -238,23 +172,23 @@ static int temac_dma_bd_init(struct net_device *ndev) lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND; } - lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 | + temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 | CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN); /* 0x10220483 */ /* 0x00100483 */ - lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 | + temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 | CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN | CHNL_CTRL_IRQ_IOE); /* 0xff010283 */ - lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p); - lp->dma_out(lp, RX_TAILDESC_PTR, + temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p); + temac_dma_out32(lp, RX_TAILDESC_PTR, lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); - lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); + temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p); return 0; } @@ -492,9 +426,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) */ - lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST); timeout = 1000; - while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { + while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) { udelay(1); if (--timeout == 0) { dev_err(&ndev->dev, @@ -502,7 +436,7 @@ static void temac_device_reset(struct net_device *ndev) break; } } - lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); + temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); temac_dma_bd_init(ndev); @@ -663,7 +597,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) lp->tx_bd_tail = 0; /* Kick off the transfer */ - lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ + temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ return NETDEV_TX_OK; } @@ -705,15 +639,16 @@ static void ll_temac_recv(struct net_device *ndev) ndev->stats.rx_packets++; ndev->stats.rx_bytes += length; - new_skb = netdev_alloc_skb_ip_align(ndev, - XTE_MAX_JUMBO_FRAME_SIZE); - + new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN, + GFP_ATOMIC); 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, @@ -728,7 +663,7 @@ static void ll_temac_recv(struct net_device *ndev) cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; bdstat = cur_p->app0; } - lp->dma_out(lp, RX_TAILDESC_PTR, tail_p); + temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p); spin_unlock_irqrestore(&lp->rx_lock, flags); } @@ -739,8 +674,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) struct temac_local *lp = netdev_priv(ndev); unsigned int status; - status = lp->dma_in(lp, TX_IRQ_REG); - lp->dma_out(lp, TX_IRQ_REG, status); + status = temac_dma_in32(lp, TX_IRQ_REG); + temac_dma_out32(lp, TX_IRQ_REG, status); if (status & (IRQ_COAL | IRQ_DLY)) temac_start_xmit_done(lp->ndev); @@ -757,8 +692,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev) unsigned int status; /* Read and clear the status registers */ - status = lp->dma_in(lp, RX_IRQ_REG); - lp->dma_out(lp, RX_IRQ_REG, status); + status = temac_dma_in32(lp, RX_IRQ_REG); + temac_dma_out32(lp, RX_IRQ_REG, status); if (status & (IRQ_COAL | IRQ_DLY)) ll_temac_recv(lp->ndev); @@ -859,7 +794,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", lp->dma_in(lp, i), + len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i), (i % 8) == 7 ? "\n" : " "); len += sprintf(buf + len, "\n"); @@ -885,6 +820,7 @@ 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)); @@ -934,20 +870,13 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) 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; - } + dcrs = dcr_resource_start(np, 0); + if (dcrs == 0) { + dev_err(&op->dev, "could not get DMA register address\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); -- cgit v1.2.3-58-ga151 From e44171f115de3dedf34064646206deb91549865f Mon Sep 17 00:00:00 2001 From: John Linn Date: Thu, 8 Apr 2010 07:08:02 +0000 Subject: Add non-Virtex5 support for LL TEMAC driver This patch adds support for using the LL TEMAC Ethernet driver on non-Virtex 5 platforms by adding support for accessing the Soft DMA registers as if they were memory mapped instead of solely through the DCR's (available on the Virtex 5). The patch also updates the driver so that it runs on the MicroBlaze. The changes were tested on the PowerPC 440, PowerPC 405, and the MicroBlaze platforms. Signed-off-by: John Tyner Signed-off-by: John Linn Acked-by: Grant Likely Signed-off-by: David S. Miller --- arch/microblaze/include/asm/system.h | 11 +++ drivers/net/Kconfig | 2 +- drivers/net/ll_temac.h | 14 +++- drivers/net/ll_temac_main.c | 137 ++++++++++++++++++++++++++--------- 4 files changed, 126 insertions(+), 38 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index 59efb3fef957..48c4f0335e3f 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -96,4 +97,14 @@ extern struct dentry *of_debugfs_root; #define arch_align_stack(x) (x) +/* + * MicroBlaze doesn't handle unaligned accesses in hardware. + * + * Based on this we force the IP header alignment in network drivers. + * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining + * cacheline alignment of buffers. + */ +#define NET_IP_ALIGN 2 +#define NET_SKB_PAD L1_CACHE_BYTES + #endif /* _ASM_MICROBLAZE_SYSTEM_H */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 49c372a5e0b7..dbd26f992158 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2435,8 +2435,8 @@ config MV643XX_ETH config XILINX_LL_TEMAC tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" + depends on PPC || MICROBLAZE select PHYLIB - depends on PPC_DCR_NATIVE help This driver supports the Xilinx 10/100/1000 LocalLink TEMAC core used in Xilinx Spartan and Virtex FPGAs diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h index 1af66a1e6911..c03358434acb 100644 --- a/drivers/net/ll_temac.h +++ b/drivers/net/ll_temac.h @@ -5,8 +5,11 @@ #include #include #include + +#ifdef CONFIG_PPC_DCR #include #include +#endif /* packet size info */ #define XTE_HDR_SIZE 14 /* size of Ethernet header */ @@ -290,9 +293,6 @@ This option defaults to enabled (set) */ #define TX_CONTROL_CALC_CSUM_MASK 1 -#define XTE_ALIGN 32 -#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN) - #define MULTICAST_CAM_TABLE_NUM 4 /* TX/RX CURDESC_PTR points to first descriptor */ @@ -335,9 +335,15 @@ struct temac_local { struct mii_bus *mii_bus; /* MII bus reference */ int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ - /* IO registers and IRQs */ + /* IO registers, dma functions and IRQs */ void __iomem *regs; + void __iomem *sdma_regs; +#ifdef CONFIG_PPC_DCR dcr_host_t sdma_dcrs; +#endif + u32 (*dma_in)(struct temac_local *, int); + void (*dma_out)(struct temac_local *, int, u32); + int tx_irq; int rx_irq; int emac_num; diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 67765756577d..78c9a2e6e51e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -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 dcr_read(lp->sdma_dcrs, 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); +} + +/** + * 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; } @@ -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); @@ -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; } @@ -638,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, @@ -662,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); } @@ -673,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); @@ -691,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); @@ -793,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"); @@ -819,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)); @@ -869,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); -- cgit v1.2.3-58-ga151 From 8cd9b13207f9a38e4da2d69bba51eb8dcbe1ead9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 27 Apr 2010 15:54:50 -0700 Subject: net/sb1250: setup the pdevice within the soc code doing it within the driver does not look good. And surely isn't how platform devices were meat to be used. Acked-by: Ralf Baechle Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: David S. Miller --- arch/mips/sibyte/swarm/platform.c | 54 +++++++++++++++++ drivers/net/sb1250-mac.c | 120 +------------------------------------- 2 files changed, 55 insertions(+), 119 deletions(-) (limited to 'arch') diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c index 54847fe1e564..097335262fb3 100644 --- a/arch/mips/sibyte/swarm/platform.c +++ b/arch/mips/sibyte/swarm/platform.c @@ -83,3 +83,57 @@ static int __init swarm_pata_init(void) device_initcall(swarm_pata_init); #endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */ + +#define sb1250_dev_struct(num) \ + static struct resource sb1250_res##num = { \ + .name = "SB1250 MAC " __stringify(num), \ + .flags = IORESOURCE_MEM, \ + .start = A_MAC_CHANNEL_BASE(num), \ + .end = A_MAC_CHANNEL_BASE(num + 1) -1, \ + };\ + static struct platform_device sb1250_dev##num = { \ + .name = "sb1250-mac", \ + .id = num, \ + .resource = &sb1250_res##num, \ + .num_resources = 1, \ + } + +sb1250_dev_struct(0); +sb1250_dev_struct(1); +sb1250_dev_struct(2); +sb1250_dev_struct(3); + +static struct platform_device *sb1250_devs[] __initdata = { + &sb1250_dev0, + &sb1250_dev1, + &sb1250_dev2, + &sb1250_dev3, +}; + +static int __init sb1250_device_init(void) +{ + int ret; + + /* Set the number of available units based on the SOC type. */ + switch (soc_type) { + case K_SYS_SOC_TYPE_BCM1250: + case K_SYS_SOC_TYPE_BCM1250_ALT: + ret = platform_add_devices(sb1250_devs, 3); + break; + case K_SYS_SOC_TYPE_BCM1120: + case K_SYS_SOC_TYPE_BCM1125: + case K_SYS_SOC_TYPE_BCM1125H: + case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */ + ret = platform_add_devices(sb1250_devs, 2); + break; + case K_SYS_SOC_TYPE_BCM1x55: + case K_SYS_SOC_TYPE_BCM1x80: + ret = platform_add_devices(sb1250_devs, 4); + break; + default: + ret = -ENODEV; + break; + } + return ret; +} +device_initcall(sb1250_device_init); diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 6ed92d62af22..ba4770a6c2e4 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -332,7 +332,6 @@ static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, ********************************************************************* */ static char sbmac_string[] = "sb1250-mac"; -static char sbmac_pretty[] = "SB1250 MAC"; static char sbmac_mdio_string[] = "sb1250-mac-mdio"; @@ -2670,114 +2669,6 @@ static int __exit sbmac_remove(struct platform_device *pldev) return 0; } - -static struct platform_device **sbmac_pldev; -static int sbmac_max_units; - -static int __init sbmac_platform_probe_one(int idx) -{ - struct platform_device *pldev; - struct { - struct resource r; - char name[strlen(sbmac_pretty) + 4]; - } *res; - int err; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) { - printk(KERN_ERR "%s.%d: unable to allocate memory\n", - sbmac_string, idx); - err = -ENOMEM; - goto out_err; - } - - /* - * This is the base address of the MAC. - */ - snprintf(res->name, sizeof(res->name), "%s %d", sbmac_pretty, idx); - res->r.name = res->name; - res->r.flags = IORESOURCE_MEM; - res->r.start = A_MAC_CHANNEL_BASE(idx); - res->r.end = A_MAC_CHANNEL_BASE(idx + 1) - 1; - - pldev = platform_device_register_simple(sbmac_string, idx, &res->r, 1); - if (IS_ERR(pldev)) { - printk(KERN_ERR "%s.%d: unable to register platform device\n", - sbmac_string, idx); - err = PTR_ERR(pldev); - goto out_kfree; - } - - if (!pldev->dev.driver) { - err = 0; /* No hardware at this address. */ - goto out_unregister; - } - - sbmac_pldev[idx] = pldev; - return 0; - -out_unregister: - platform_device_unregister(pldev); - -out_kfree: - kfree(res); - -out_err: - return err; -} - -static void __init sbmac_platform_probe(void) -{ - int i; - - /* Set the number of available units based on the SOC type. */ - switch (soc_type) { - case K_SYS_SOC_TYPE_BCM1250: - case K_SYS_SOC_TYPE_BCM1250_ALT: - sbmac_max_units = 3; - break; - case K_SYS_SOC_TYPE_BCM1120: - case K_SYS_SOC_TYPE_BCM1125: - case K_SYS_SOC_TYPE_BCM1125H: - case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */ - sbmac_max_units = 2; - break; - case K_SYS_SOC_TYPE_BCM1x55: - case K_SYS_SOC_TYPE_BCM1x80: - sbmac_max_units = 4; - break; - default: - return; /* none */ - } - - sbmac_pldev = kcalloc(sbmac_max_units, sizeof(*sbmac_pldev), - GFP_KERNEL); - if (!sbmac_pldev) { - printk(KERN_ERR "%s: unable to allocate memory\n", - sbmac_string); - return; - } - - /* - * Walk through the Ethernet controllers and find - * those who have their MAC addresses set. - */ - for (i = 0; i < sbmac_max_units; i++) - if (sbmac_platform_probe_one(i)) - break; -} - - -static void __exit sbmac_platform_cleanup(void) -{ - int i; - - for (i = 0; i < sbmac_max_units; i++) - platform_device_unregister(sbmac_pldev[i]); - kfree(sbmac_pldev); -} - - static struct platform_driver sbmac_driver = { .probe = sbmac_probe, .remove = __exit_p(sbmac_remove), @@ -2788,20 +2679,11 @@ static struct platform_driver sbmac_driver = { static int __init sbmac_init_module(void) { - int err; - - err = platform_driver_register(&sbmac_driver); - if (err) - return err; - - sbmac_platform_probe(); - - return err; + return platform_driver_register(&sbmac_driver); } static void __exit sbmac_cleanup_module(void) { - sbmac_platform_cleanup(); platform_driver_unregister(&sbmac_driver); } -- cgit v1.2.3-58-ga151 From 39e0786d3cf39c6d2f47b4818ae2da8b8ebc9ce2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 6 May 2010 22:01:53 -0700 Subject: microblaze: Kill NET_SKB_PAD and NET_IP_ALIGN overrides. NET_IP_ALIGN defaults to 2, no need to override. NET_SKB_PAD is now 64, which is much larger than microblaze's L1_CACHE_SIZE so no need to override that either. Signed-off-by: David S. Miller --- arch/microblaze/include/asm/system.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index 48c4f0335e3f..b1e2f0710098 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -97,14 +97,4 @@ extern struct dentry *of_debugfs_root; #define arch_align_stack(x) (x) -/* - * MicroBlaze doesn't handle unaligned accesses in hardware. - * - * Based on this we force the IP header alignment in network drivers. - * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining - * cacheline alignment of buffers. - */ -#define NET_IP_ALIGN 2 -#define NET_SKB_PAD L1_CACHE_BYTES - #endif /* _ASM_MICROBLAZE_SYSTEM_H */ -- cgit v1.2.3-58-ga151 From e0e33280fedcfa9dd70a54085c4d44d9d53b788f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 7 May 2010 02:55:33 -0700 Subject: Revert "microblaze: Kill NET_SKB_PAD and NET_IP_ALIGN overrides." This reverts commit 39e0786d3cf39c6d2f47b4818ae2da8b8ebc9ce2. On request from microblaze developers, they are going to handle this differently. Signed-off-by: David S. Miller --- arch/microblaze/include/asm/system.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index b1e2f0710098..48c4f0335e3f 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h @@ -97,4 +97,14 @@ extern struct dentry *of_debugfs_root; #define arch_align_stack(x) (x) +/* + * MicroBlaze doesn't handle unaligned accesses in hardware. + * + * Based on this we force the IP header alignment in network drivers. + * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining + * cacheline alignment of buffers. + */ +#define NET_IP_ALIGN 2 +#define NET_SKB_PAD L1_CACHE_BYTES + #endif /* _ASM_MICROBLAZE_SYSTEM_H */ -- cgit v1.2.3-58-ga151 From 56e6943b902562e09d3e74126d8d8256b5ea17fb Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Mon, 17 May 2010 22:39:48 -0700 Subject: can: sja1000 platform data fixes The member "clock" of struct "sja1000_platform_data" is documented as "CAN bus oscillator frequency in Hz" but it's actually used as the CAN clock frequency, which is half of it. To avoid further confusion, this patch fixes it by renaming the member to "osc_freq". That way, also non mainline users will notice the change. The platform code for the relevant boards is updated accordingly. Furthermore, pre-defined values are now used for the members "ocr" and "cdr". Signed-off-by: Wolfgang Grandegger Acked-by: Marc Kleine-Budde Signed-off-by: David S. Miller --- arch/arm/mach-mx2/pcm970-baseboard.c | 6 +++--- arch/arm/mach-mx3/mach-pcm037.c | 6 +++--- drivers/net/can/sja1000/sja1000_platform.c | 3 ++- include/linux/can/platform/sja1000.h | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c index 4aafd5b8b85b..f490a406d57e 100644 --- a/arch/arm/mach-mx2/pcm970-baseboard.c +++ b/arch/arm/mach-mx2/pcm970-baseboard.c @@ -201,9 +201,9 @@ static struct resource pcm970_sja1000_resources[] = { }; struct sja1000_platform_data pcm970_sja1000_platform_data = { - .clock = 16000000 / 2, - .ocr = 0x40 | 0x18, - .cdr = 0x40, + .osc_freq = 16000000, + .ocr = OCR_TX1_PULLDOWN | OCR_TX0_PUSHPULL, + .cdr = CDR_CBP, }; static struct platform_device pcm970_sja1000 = { diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c index 2df1ec55a97e..78ecd751549b 100644 --- a/arch/arm/mach-mx3/mach-pcm037.c +++ b/arch/arm/mach-mx3/mach-pcm037.c @@ -530,9 +530,9 @@ static struct resource pcm970_sja1000_resources[] = { }; struct sja1000_platform_data pcm970_sja1000_platform_data = { - .clock = 16000000 / 2, - .ocr = 0x40 | 0x18, - .cdr = 0x40, + .osc_freq = 16000000, + .ocr = OCR_TX1_PULLDOWN | OCR_TX0_PUSHPULL, + .cdr = CDR_CBP, }; static struct platform_device pcm970_sja1000 = { diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index b65cabb361ab..d9fadc489b32 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -111,7 +111,8 @@ static int sp_probe(struct platform_device *pdev) dev->irq = res_irq->start; priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED); priv->reg_base = addr; - priv->can.clock.freq = pdata->clock; + /* The CAN clock frequency is half the oscillator clock frequency */ + priv->can.clock.freq = pdata->osc_freq / 2; priv->ocr = pdata->ocr; priv->cdr = pdata->cdr; diff --git a/include/linux/can/platform/sja1000.h b/include/linux/can/platform/sja1000.h index 01ee2aeb048d..96f8fcc78d78 100644 --- a/include/linux/can/platform/sja1000.h +++ b/include/linux/can/platform/sja1000.h @@ -26,7 +26,7 @@ #define OCR_TX_SHIFT 2 struct sja1000_platform_data { - u32 clock; /* CAN bus oscillator frequency in Hz */ + u32 osc_freq; /* CAN bus oscillator frequency in Hz */ u8 ocr; /* output control register */ u8 cdr; /* clock divider register */ -- cgit v1.2.3-58-ga151