diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/can/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/can/flexcan/dev.c | 112 | ||||
-rw-r--r-- | drivers/net/can/flexcan/flexcan.h | 31 | ||||
-rw-r--r-- | drivers/net/can/flexcan/mbm.c | 74 | ||||
-rw-r--r-- | drivers/net/enc28j60.c | 18 | ||||
-rw-r--r-- | drivers/net/fec.c | 62 | ||||
-rw-r--r-- | drivers/net/fec_1588.c | 155 | ||||
-rw-r--r-- | drivers/net/fec_1588.h | 51 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 72 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 4 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 31 | ||||
-rw-r--r-- | drivers/net/smsc911x.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath6kl/os/linux/ar6000_android.c | 2 |
15 files changed, 482 insertions, 147 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bd5d0e026b02..28318f4236b1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1885,6 +1885,13 @@ config FEC_1588 bool "Enable FEC 1588 timestamping" depends on FEC +config FEC_L2SWITCH + bool "L2 Switch Ethernet Controller (of ColdFire CPUs)" + depends on ARCH_MX28 && !FEC + help + Say Y here if you want to use the built-in 10/100 Ethernet Switch + Controller on some Motorola ColdFire processors. + config FEC2 bool "Second FEC ethernet controller (on some ColdFire CPUs)" depends on FEC diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f3c89fb1b799..11bb1b5623bf 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -115,6 +115,7 @@ obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o obj-$(CONFIG_FEC_1588) += fec_1588.o +obj-$(CONFIG_FEC_L2SWITCH) += fec_switch.o obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index a6bf9a7fddd9..481990fd3f2b 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -86,8 +86,8 @@ config CAN_DEBUG_DEVICES config CAN_FLEXCAN tristate "Freescale FlexCAN" - depends on CAN && (ARCH_MX25 || ARCH_MX35 || ARCH_MX28) - default m + depends on CAN && (ARCH_MX25 || ARCH_MX35 || ARCH_MX28 || ARCH_MX53) + default y ---help--- This select the support of Freescale CAN(FlexCAN). This driver can also be built as a module. diff --git a/drivers/net/can/flexcan/dev.c b/drivers/net/can/flexcan/dev.c index 389f85d75709..404877c33eab 100644 --- a/drivers/net/can/flexcan/dev.c +++ b/drivers/net/can/flexcan/dev.c @@ -35,6 +35,74 @@ #endif #include "flexcan.h" +#define DEFAULT_BITRATE 500000 +#define TIME_SEGMENT_MIN 8 +#define TIME_SEGMENT_MAX 25 +#define TIME_SEGMENT_MID ((TIME_SEGMENT_MIN + TIME_SEGMENT_MAX)/2) + +struct time_segment { + char propseg; + char pseg1; + char pseg2; +}; + +struct time_segment time_segments[] = { + { /* total 8 timequanta */ + 1, 2, 1 + }, + { /* total 9 timequanta */ + 1, 2, 2 + }, + { /* total 10 timequanta */ + 2, 2, 2 + }, + { /* total 11 timequanta */ + 2, 2, 3 + }, + { /* total 12 timequanta */ + 2, 3, 3 + }, + { /* total 13 timequanta */ + 3, 3, 3 + }, + { /* total 14 timequanta */ + 3, 3, 4 + }, + { /* total 15 timequanta */ + 3, 4, 4 + }, + { /* total 16 timequanta */ + 4, 4, 4 + }, + { /* total 17 timequanta */ + 4, 4, 5 + }, + { /* total 18 timequanta */ + 4, 5, 5 + }, + { /* total 19 timequanta */ + 5, 5, 5 + }, + { /* total 20 timequanta */ + 5, 5, 6 + }, + { /* total 21 timequanta */ + 5, 6, 6 + }, + { /* total 22 timequanta */ + 6, 6, 6 + }, + { /* total 23 timequanta */ + 6, 6, 7 + }, + { /* total 24 timequanta */ + 6, 7, 7 + }, + { /* total 25 timequanta */ + 7, 7, 7 + }, +}; + enum { FLEXCAN_ATTR_STATE = 0, FLEXCAN_ATTR_BITRATE, @@ -138,6 +206,45 @@ static void flexcan_set_bitrate(struct flexcan_device *flexcan, int bitrate) * based on the bitrate to get the timing of * presdiv, pseg1, pseg2, propseg */ + int i, rate, div; + bool found = false; + struct time_segment *segment; + rate = clk_get_rate(flexcan->clk); + + if (!bitrate) + bitrate = DEFAULT_BITRATE; + + if (rate % bitrate == 0) { + div = rate / bitrate; + for (i = TIME_SEGMENT_MID; i <= TIME_SEGMENT_MAX; i++) { + if (div % i == 0) { + found = true; + break; + } + } + if (!found) { + for (i = TIME_SEGMENT_MID - 1; + i >= TIME_SEGMENT_MIN; i--) { + if (div % i == 0) { + found = true; + break; + } + } + + } + } + + if (found) { + segment = &time_segments[i - TIME_SEGMENT_MIN]; + flexcan->br_presdiv = div/i - 1; + flexcan->br_propseg = segment->propseg; + flexcan->br_pseg1 = segment->pseg1; + flexcan->br_pseg2 = segment->pseg2; + flexcan->bitrate = bitrate; + } else { + pr_info("The bitrate %d can't supported with clock \ + rate of %d \n", bitrate, rate); + } } static void flexcan_update_bitrate(struct flexcan_device *flexcan) @@ -201,7 +308,7 @@ static int flexcan_dump_xmit_mb(struct flexcan_device *flexcan, char *buf) ret += sprintf(buf + ret, "mb[%d]::CS:0x%x ID:0x%x DATA[1~2]:0x%02x,0x%02x\n", - i, flexcan->hwmb[i].mb_cs.data, + i, flexcan->hwmb[i].mb_cs, flexcan->hwmb[i].mb_id, flexcan->hwmb[i].mb_data[1], flexcan->hwmb[i].mb_data[2]); return ret; @@ -214,7 +321,7 @@ static int flexcan_dump_rx_mb(struct flexcan_device *flexcan, char *buf) ret += sprintf(buf + ret, "mb[%d]::CS:0x%x ID:0x%x DATA[1~2]:0x%02x,0x%02x\n", - i, flexcan->hwmb[i].mb_cs.data, + i, flexcan->hwmb[i].mb_cs, flexcan->hwmb[i].mb_id, flexcan->hwmb[i].mb_data[1], flexcan->hwmb[i].mb_data[2]); return ret; @@ -575,6 +682,7 @@ struct net_device *flexcan_device_alloc(struct platform_device *pdev, return NULL; } flexcan_device_default(flexcan); + flexcan_set_bitrate(flexcan, flexcan->bitrate); flexcan_update_bitrate(flexcan); num = ARRAY_SIZE(flexcan_dev_attr); diff --git a/drivers/net/can/flexcan/flexcan.h b/drivers/net/can/flexcan/flexcan.h index d19cc1ee0620..51a800bd8e55 100644 --- a/drivers/net/can/flexcan/flexcan.h +++ b/drivers/net/can/flexcan/flexcan.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -32,17 +32,6 @@ #define FLEXCAN_DEVICE_NAME "FlexCAN" -struct can_mb_cs { - unsigned int time_stamp:16; - unsigned int length:4; - unsigned int rtr:1; - unsigned int ide:1; - unsigned int srr:1; - unsigned int nouse1:1; - unsigned int code:4; - unsigned int nouse2:4; -}; - #define CAN_MB_RX_INACTIVE 0x0 #define CAN_MB_RX_EMPTY 0x4 #define CAN_MB_RX_FULL 0x2 @@ -55,14 +44,24 @@ struct can_mb_cs { #define CAN_MB_TX_REMOTE 0xA struct can_hw_mb { - union { - struct can_mb_cs cs; - unsigned int data; - } mb_cs; + unsigned int mb_cs; unsigned int mb_id; unsigned char mb_data[8]; }; +#define MB_CS_CODE_OFFSET 24 +#define MB_CS_CODE_MASK (0xF << MB_CS_CODE_OFFSET) +#define MB_CS_SRR_OFFSET 22 +#define MB_CS_SRR_MASK (0x1 << MB_CS_SRR_OFFSET) +#define MB_CS_IDE_OFFSET 21 +#define MB_CS_IDE_MASK (0x1 << MB_CS_IDE_OFFSET) +#define MB_CS_RTR_OFFSET 20 +#define MB_CS_RTR_MASK (0x1 << MB_CS_RTR_OFFSET) +#define MB_CS_LENGTH_OFFSET 16 +#define MB_CS_LENGTH_MASK (0xF << MB_CS_LENGTH_OFFSET) +#define MB_CS_TIMESTAMP_OFFSET 0 +#define MB_CS_TIMESTAMP_MASK (0xFF << MB_CS_TIMESTAMP_OFFSET) + #define CAN_HW_REG_MCR 0x00 #define CAN_HW_REG_CTRL 0x04 #define CAN_HW_REG_TIMER 0x08 diff --git a/drivers/net/can/flexcan/mbm.c b/drivers/net/can/flexcan/mbm.c index b0341ba9128e..c846d97daadb 100644 --- a/drivers/net/can/flexcan/mbm.c +++ b/drivers/net/can/flexcan/mbm.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -55,10 +55,13 @@ static void flexcan_mb_bottom(struct net_device *dev, int index) hwmb = flexcan->hwmb + index; if (flexcan->fifo || (index >= (flexcan->maxmb - flexcan->xmit_maxmb))) { - if (hwmb->mb_cs.cs.code == CAN_MB_TX_ABORT) - hwmb->mb_cs.cs.code = CAN_MB_TX_INACTIVE; + if ((hwmb->mb_cs & MB_CS_CODE_MASK) >> MB_CS_CODE_OFFSET == + CAN_MB_TX_ABORT) { + hwmb->mb_cs &= ~MB_CS_CODE_MASK; + hwmb->mb_cs |= CAN_MB_TX_INACTIVE << MB_CS_CODE_OFFSET; + } - if (hwmb->mb_cs.cs.code & CAN_MB_TX_INACTIVE) { + if (hwmb->mb_cs & (CAN_MB_TX_INACTIVE << MB_CS_CODE_OFFSET)) { if (netif_queue_stopped(dev)) netif_start_queue(dev); return; @@ -68,16 +71,17 @@ static void flexcan_mb_bottom(struct net_device *dev, int index) if (skb) { frame = (struct can_frame *)skb_put(skb, sizeof(*frame)); memset(frame, 0, sizeof(*frame)); - if (hwmb->mb_cs.cs.ide) + if (hwmb->mb_cs & MB_CS_IDE_MASK) frame->can_id = (hwmb->mb_id & CAN_EFF_MASK) | CAN_EFF_FLAG; else frame->can_id = (hwmb->mb_id >> 18) & CAN_SFF_MASK; - if (hwmb->mb_cs.cs.rtr) + if (hwmb->mb_cs & MB_CS_RTR_MASK) frame->can_id |= CAN_RTR_FLAG; - frame->can_dlc = hwmb->mb_cs.cs.length; + frame->can_dlc = + (hwmb->mb_cs & MB_CS_LENGTH_MASK) >> MB_CS_LENGTH_OFFSET; if (frame->can_dlc && frame->can_dlc) flexcan_memcpy(frame->data, hwmb->mb_data, @@ -85,7 +89,8 @@ static void flexcan_mb_bottom(struct net_device *dev, int index) if (flexcan->fifo || (index >= (flexcan->maxmb - flexcan->xmit_maxmb))) { - hwmb->mb_cs.cs.code = CAN_MB_TX_INACTIVE; + hwmb->mb_cs &= ~MB_CS_CODE_MASK; + hwmb->mb_cs |= CAN_MB_TX_INACTIVE << MB_CS_CODE_OFFSET; if (netif_queue_stopped(dev)) netif_start_queue(dev); } @@ -101,13 +106,13 @@ static void flexcan_mb_bottom(struct net_device *dev, int index) skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); } else { - tmp = hwmb->mb_cs.data; + tmp = hwmb->mb_cs; tmp = hwmb->mb_id; tmp = hwmb->mb_data[0]; if (flexcan->fifo || (index >= (flexcan->maxmb - flexcan->xmit_maxmb))) { - - hwmb->mb_cs.cs.code = CAN_MB_TX_INACTIVE; + hwmb->mb_cs &= ~MB_CS_CODE_MASK; + hwmb->mb_cs |= CAN_MB_TX_INACTIVE << MB_CS_CODE_OFFSET; if (netif_queue_stopped(dev)) netif_start_queue(dev); } @@ -131,17 +136,19 @@ static void flexcan_fifo_isr(struct net_device *dev, unsigned int iflag1) frame = (struct can_frame *)skb_put(skb, sizeof(*frame)); memset(frame, 0, sizeof(*frame)); - if (hwmb->mb_cs.cs.ide) + if (hwmb->mb_cs & MB_CS_IDE_MASK) frame->can_id = (hwmb->mb_id & CAN_EFF_MASK) | CAN_EFF_FLAG; else frame->can_id = (hwmb->mb_id >> 18) & CAN_SFF_MASK; - if (hwmb->mb_cs.cs.rtr) + if (hwmb->mb_cs & MB_CS_RTR_MASK) frame->can_id |= CAN_RTR_FLAG; - frame->can_dlc = hwmb->mb_cs.cs.length; + frame->can_dlc = + (hwmb->mb_cs & MB_CS_LENGTH_MASK) >> + MB_CS_LENGTH_OFFSET; if (frame->can_dlc && (frame->can_dlc <= 8)) flexcan_memcpy(frame->data, hwmb->mb_data, @@ -158,7 +165,7 @@ static void flexcan_fifo_isr(struct net_device *dev, unsigned int iflag1) skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); } else { - tmp = hwmb->mb_cs.data; + tmp = hwmb->mb_cs; tmp = hwmb->mb_id; tmp = hwmb->mb_data[0]; tmp = __raw_readl(flexcan->io_base + CAN_HW_REG_TIMER); @@ -252,7 +259,8 @@ int flexcan_mbm_xmit(struct flexcan_device *flexcan, struct can_frame *frame) struct can_hw_mb *hwmb = flexcan->hwmb; do { - if (hwmb[i].mb_cs.cs.code == CAN_MB_TX_INACTIVE) + if ((hwmb[i].mb_cs & MB_CS_CODE_MASK) >> MB_CS_CODE_OFFSET == + CAN_MB_TX_INACTIVE) break; if ((++i) > flexcan->maxmb) { if (flexcan->fifo) @@ -273,22 +281,24 @@ int flexcan_mbm_xmit(struct flexcan_device *flexcan, struct can_frame *frame) } if (frame->can_id & CAN_RTR_FLAG) - hwmb[i].mb_cs.cs.rtr = 1; + hwmb[i].mb_cs |= 1 << MB_CS_RTR_OFFSET; else - hwmb[i].mb_cs.cs.rtr = 0; + hwmb[i].mb_cs &= ~MB_CS_RTR_MASK; if (frame->can_id & CAN_EFF_FLAG) { - hwmb[i].mb_cs.cs.ide = 1; - hwmb[i].mb_cs.cs.srr = 1; + hwmb[i].mb_cs |= 1 << MB_CS_IDE_OFFSET; + hwmb[i].mb_cs |= 1 << MB_CS_SRR_OFFSET; hwmb[i].mb_id = frame->can_id & CAN_EFF_MASK; } else { - hwmb[i].mb_cs.cs.ide = 0; + hwmb[i].mb_cs &= ~MB_CS_IDE_MASK; hwmb[i].mb_id = (frame->can_id & CAN_SFF_MASK) << 18; } - hwmb[i].mb_cs.cs.length = frame->can_dlc; + hwmb[i].mb_cs &= ~MB_CS_LENGTH_MASK; + hwmb[i].mb_cs |= frame->can_dlc << MB_CS_LENGTH_OFFSET; flexcan_memcpy(hwmb[i].mb_data, frame->data, frame->can_dlc); - hwmb[i].mb_cs.cs.code = CAN_MB_TX_ONCE; + hwmb[i].mb_cs &= ~MB_CS_CODE_MASK; + hwmb[i].mb_cs |= CAN_MB_TX_ONCE << MB_CS_CODE_OFFSET; return 0; } @@ -325,23 +335,27 @@ void flexcan_mbm_init(struct flexcan_device *flexcan) id_table[i] = 0; } else { for (i = 0; i < rx_mb; i++) { - hwmb[i].mb_cs.cs.code = CAN_MB_RX_EMPTY; + hwmb[i].mb_cs &= ~MB_CS_CODE_MASK; + hwmb[i].mb_cs |= CAN_MB_RX_EMPTY << MB_CS_CODE_OFFSET; /* * IDE bit can not control by mask registers * So set message buffer to receive extend * or standard message. */ - if (flexcan->ext_msg && flexcan->std_msg) - hwmb[i].mb_cs.cs.ide = i & 1; - else { + if (flexcan->ext_msg && flexcan->std_msg) { + hwmb[i].mb_cs &= ~MB_CS_IDE_MASK; + hwmb[i].mb_cs |= (i & 1) << MB_CS_IDE_OFFSET; + } else { if (flexcan->ext_msg) - hwmb[i].mb_cs.cs.ide = 1; + hwmb[i].mb_cs |= 1 << MB_CS_IDE_OFFSET; } } } - for (; i <= flexcan->maxmb; i++) - hwmb[i].mb_cs.cs.code = CAN_MB_TX_INACTIVE; + for (; i <= flexcan->maxmb; i++) { + hwmb[i].mb_cs &= ~MB_CS_CODE_MASK; + hwmb[i].mb_cs |= CAN_MB_TX_INACTIVE << MB_CS_CODE_OFFSET; + } flexcan->xmit_mb = rx_mb; } diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 582eb37390ed..8a34f4679fa5 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -30,8 +30,6 @@ #include <linux/delay.h> #include <linux/spi/spi.h> -#include <mach/platform.h> - #include "enc28j60_hw.h" #define DRV_NAME "enc28j60" @@ -53,9 +51,17 @@ #define MAX_TX_RETRYCOUNT 16 #ifdef CONFIG_ARCH_STMP3XXX +#include <mach/platform.h> #include <mach/stmp3xxx.h> #include <mach/regs-ocotp.h> #endif +#ifdef CONFIG_ARCH_MXS +#include <mach/system.h> +#include <mach/hardware.h> +#include <mach/regs-ocotp.h> +#define REGS_OCOTP_BASE IO_ADDRESS(OCOTP_PHYS_ADDR) +#endif + enum { RXFILTER_NORMAL, RXFILTER_MULTI, @@ -104,12 +110,14 @@ static int enc28j60_get_mac(unsigned char *dev_addr, int idx) return false; if (!mac[idx]) { -#ifdef CONFIG_ARCH_STMP3XXX +#if defined(CONFIG_ARCH_STMP3XXX) || defined(CONFIG_ARCH_MXS) if (get_evk_board_version() >= 1) { int mac1 , mac2 , retry = 0; - stmp3xxx_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, REGS_OCOTP_BASE + HW_OCOTP_CTRL); - while (__raw_readl(REGS_OCOTP_BASE + HW_OCOTP_CTRL) & BM_OCOTP_CTRL_BUSY) { + __raw_writel(BM_OCOTP_CTRL_RD_BANK_OPEN, + REGS_OCOTP_BASE + HW_OCOTP_CTRL_SET); + while (__raw_readl(REGS_OCOTP_BASE + HW_OCOTP_CTRL) & + BM_OCOTP_CTRL_BUSY) { msleep(10); retry++; if (retry > 10) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 46799e092bc1..206be36f0d19 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -296,6 +296,17 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bufaddr = fep->tx_bounce[index]; } + if (fep->ptimer_present) { + if (fec_ptp_do_txstamp(skb)) + estatus = BD_ENET_TX_TS; + else + estatus = 0; +#ifdef CONFIG_FEC_1588 + bdp->cbd_esc = (estatus | BD_ENET_TX_INT); + bdp->cbd_bdu = 0; +#endif + } + #ifdef CONFIG_ARCH_MXS swap_buffer(bufaddr, skb->len); #endif @@ -318,16 +329,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; - if (fep->ptimer_present) { - if (fec_ptp_do_txstamp(skb)) - estatus = BD_ENET_TX_TS; - else - estatus = 0; -#ifdef CONFIG_FEC_1588 - bdp->cbd_esc = (estatus | BD_ENET_TX_INT); - bdp->cbd_bdu = 0; -#endif - } dev->trans_start = jiffies; /* Trigger transmission start */ @@ -807,7 +808,7 @@ static struct mii_bus *fec_enet_mii_init(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(dev); - struct fec_enet_platform_data *pdata; + struct fec_platform_data *pdata; int err = -ENXIO, i; fep->mii_timeout = 0; @@ -836,6 +837,7 @@ static struct mii_bus *fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; pdata = pdev->dev.platform_data; + fep->mii_bus->phy_mask = pdata->phy_mask; fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!fep->mii_bus->irq) { @@ -1131,17 +1133,18 @@ fec_set_mac_address(struct net_device *dev, void *p) { struct fec_enet_private *fep = netdev_priv(dev); struct sockaddr *addr = p; + u32 temp_mac[2]; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) | - (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), - fep->hwp + FEC_ADDR_LOW); - writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), - fep + FEC_ADDR_HIGH); + memcpy(&temp_mac, dev->dev_addr, ETH_ALEN); + + writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); + writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); + return 0; } @@ -1277,6 +1280,7 @@ fec_restart(struct net_device *dev, int duplex) /* Clear any outstanding interrupt. */ writel(0xffc00000, fep->hwp + FEC_IEVENT); +#if !defined(CONFIG_MACH_CCMX51JS) && !defined(CONFIG_MACH_CCWMX51JS) /* Reset all multicast. */ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); @@ -1284,6 +1288,7 @@ fec_restart(struct net_device *dev, int duplex) writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_HASH_TABLE_LOW); #endif +#endif /* !defined(CONFIG_MACH_CCMX51JS) && !defined(CONFIG_MACH_CCWMX51JS) */ #ifndef CONFIG_ARCH_MXS if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { @@ -1407,6 +1412,15 @@ fec_stop(struct net_device *dev) writel(1, fep->hwp + FEC_ECNTRL); udelay(10); +#ifdef CONFIG_ARCH_MXS + /* Check MII or RMII */ + if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) + writel(readl(fep->hwp + FEC_R_CNTRL) | 0x100, + fep->hwp + FEC_R_CNTRL); + else + writel(readl(fep->hwp + FEC_R_CNTRL) & ~0x100, + fep->hwp + FEC_R_CNTRL); +#endif /* Clear outstanding MII command interrupts. */ writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); @@ -1482,6 +1496,18 @@ fec_probe(struct platform_device *pdev) fep->phy_interface = pdata->phy; if (pdata->init && pdata->init()) goto failed_platform_init; + + /* + * The priority for getting MAC address is: + * (1) kernel command line fec_mac = xx:xx:xx... + * (2) platform data mac field got from fuse etc + * (3) bootloader set the FEC mac register + */ + + if (!is_valid_ether_addr(fec_mac_default) && + pdata->mac && is_valid_ether_addr(pdata->mac)) + memcpy(fec_mac_default, pdata->mac, + sizeof(fec_mac_default)); } else fep->phy_interface = PHY_INTERFACE_MODE_MII; @@ -1499,10 +1525,10 @@ fec_probe(struct platform_device *pdev) fep->mii_bus = fec_mii_bus; } - fep->ptp_priv = kmalloc(sizeof(struct fec_ptp_private), GFP_KERNEL); + fep->ptp_priv = kzalloc(sizeof(struct fec_ptp_private), GFP_KERNEL); if (fep->ptp_priv) { fep->ptp_priv->hwp = fep->hwp; - ret = fec_ptp_init(fep->ptp_priv); + ret = fec_ptp_init(fep->ptp_priv, pdev->id); if (ret) printk(KERN_WARNING "IEEE1588: ptp-timer is unavailable\n"); diff --git a/drivers/net/fec_1588.c b/drivers/net/fec_1588.c index 5babcc29de78..c4bf278c7f19 100644 --- a/drivers/net/fec_1588.c +++ b/drivers/net/fec_1588.c @@ -35,7 +35,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ptp_rx_ts_wait); #define PTP_GET_RX_TIMEOUT (HZ/10) -static struct fec_ptp_private *ptp_private; +static struct fec_ptp_private *ptp_private[2]; /* Alloc the ring resource */ static int fec_ptp_init_circ(struct circ_buf *ptp_buf) @@ -88,14 +88,15 @@ static int fec_ptp_is_full(struct circ_buf *buf) } static int fec_ptp_insert(struct circ_buf *ptp_buf, - struct fec_ptp_data_t *data) + struct fec_ptp_data_t *data, + struct fec_ptp_private *priv) { struct fec_ptp_data_t *tmp; if (fec_ptp_is_full(ptp_buf)) return 1; - spin_lock(&ptp_private->ptp_lock); + spin_lock(&priv->ptp_lock); tmp = (struct fec_ptp_data_t *)(ptp_buf->buf) + ptp_buf->tail; tmp->key = data->key; @@ -104,13 +105,15 @@ static int fec_ptp_insert(struct circ_buf *ptp_buf, ptp_buf->tail = fec_ptp_calc_index(DEFAULT_PTP_RX_BUF_SZ, ptp_buf->tail, 1); - spin_unlock(&ptp_private->ptp_lock); + spin_unlock(&priv->ptp_lock); return 0; } static int fec_ptp_find_and_remove(struct circ_buf *ptp_buf, - int key, struct fec_ptp_data_t *data) + int key, + struct fec_ptp_data_t *data, + struct fec_ptp_private *priv) { int i; int size = DEFAULT_PTP_RX_BUF_SZ; @@ -129,10 +132,10 @@ static int fec_ptp_find_and_remove(struct circ_buf *ptp_buf, i = fec_ptp_calc_index(size, i, 1); } - spin_lock_irqsave(&ptp_private->ptp_lock, flags); + spin_lock_irqsave(&priv->ptp_lock, flags); if (i == end) { ptp_buf->head = end; - spin_unlock_irqrestore(&ptp_private->ptp_lock, flags); + spin_unlock_irqrestore(&priv->ptp_lock, flags); return 1; } @@ -140,7 +143,7 @@ static int fec_ptp_find_and_remove(struct circ_buf *ptp_buf, data->ts_time.nsec = tmp->ts_time.nsec; ptp_buf->head = fec_ptp_calc_index(size, i, 1); - spin_unlock_irqrestore(&ptp_private->ptp_lock, flags); + spin_unlock_irqrestore(&priv->ptp_lock, flags); return 0; } @@ -154,9 +157,9 @@ int fec_ptp_start(struct fec_ptp_private *priv) writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL); writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, fpp->hwp + FEC_ATIME_INC); writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD); - writel(FEC_T_CTRL_PERIOD_RST, fpp->hwp + FEC_ATIME_CTRL); /* start counter */ - writel(FEC_T_CTRL_ENABLE, fpp->hwp + FEC_ATIME_CTRL); + writel(FEC_T_CTRL_PERIOD_RST | FEC_T_CTRL_ENABLE, + fpp->hwp + FEC_ATIME_CTRL); return 0; } @@ -175,12 +178,19 @@ void fec_ptp_stop(struct fec_ptp_private *priv) static void fec_get_curr_cnt(struct fec_ptp_private *priv, struct ptp_rtc_time *curr_time) { + u32 tempval; + + writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); curr_time->rtc_time.nsec = readl(priv->hwp + FEC_ATIME); curr_time->rtc_time.sec = priv->prtc; + writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); - if (readl(priv->hwp + FEC_ATIME) < curr_time->rtc_time.nsec) - curr_time->rtc_time.sec++; + tempval = readl(priv->hwp + FEC_ATIME); + if (tempval < curr_time->rtc_time.nsec) { + curr_time->rtc_time.nsec = tempval; + curr_time->rtc_time.sec = priv->prtc; + } } /* Set the 1588 timer counter registers */ @@ -190,12 +200,12 @@ static void fec_set_1588cnt(struct fec_ptp_private *priv, u32 tempval; unsigned long flags; - spin_lock_irqsave(&ptp_private->cnt_lock, flags); + spin_lock_irqsave(&priv->cnt_lock, flags); priv->prtc = fec_time->rtc_time.sec; tempval = fec_time->rtc_time.nsec; writel(tempval, priv->hwp + FEC_ATIME); - spin_unlock_irqrestore(&ptp_private->cnt_lock, flags); + spin_unlock_irqrestore(&priv->cnt_lock, flags); } /* Set the BD to ptp */ @@ -207,11 +217,11 @@ int fec_ptp_do_txstamp(struct sk_buff *skb) if (skb->len > 44) { /* Check if port is 319 for PTP Event, and check for UDP */ iph = ip_hdr(skb); - if (iph->protocol != FEC_PACKET_TYPE_UDP) + if (iph == NULL || iph->protocol != FEC_PACKET_TYPE_UDP) return 0; udph = udp_hdr(skb); - if (udph->source == 319) + if (udph != NULL && ntohs(udph->source) == 319) return 1; } @@ -244,24 +254,24 @@ void fec_ptp_store_rxstamp(struct fec_ptp_private *priv, return; udph = (struct udphdr *)(skb->data + FEC_PTP_UDP_OFFS); - if (udph->source != 319) + if (ntohs(udph->source) != 319) return; seq_id = *((u16 *)(skb->data + FEC_PTP_SEQ_ID_OFFS)); control = *((u8 *)(skb->data + FEC_PTP_CTRL_OFFS)); - tmp_rx_time.key = seq_id; + tmp_rx_time.key = ntohs(seq_id); tmp_rx_time.ts_time.sec = fpp->prtc; tmp_rx_time.ts_time.nsec = bdp->ts; switch (control) { case PTP_MSG_SYNC: - fec_ptp_insert(&(priv->rx_time_sync), &tmp_rx_time); + fec_ptp_insert(&(priv->rx_time_sync), &tmp_rx_time, priv); break; case PTP_MSG_DEL_REQ: - fec_ptp_insert(&(priv->rx_time_del_req), &tmp_rx_time); + fec_ptp_insert(&(priv->rx_time_del_req), &tmp_rx_time, priv); break; /* clear transportSpecific field*/ @@ -271,11 +281,11 @@ void fec_ptp_store_rxstamp(struct fec_ptp_private *priv, switch (msg_type) { case PTP_MSG_P_DEL_REQ: fec_ptp_insert(&(priv->rx_time_pdel_req), - &tmp_rx_time); + &tmp_rx_time, priv); break; case PTP_MSG_P_DEL_RESP: fec_ptp_insert(&(priv->rx_time_pdel_resp), - &tmp_rx_time); + &tmp_rx_time, priv); break; default: break; @@ -308,20 +318,20 @@ static uint8_t fec_get_rx_time(struct fec_ptp_private *priv, switch (mode) { case PTP_MSG_SYNC: flag = fec_ptp_find_and_remove(&(priv->rx_time_sync), - key, &tmp); + key, &tmp, priv); break; case PTP_MSG_DEL_REQ: flag = fec_ptp_find_and_remove(&(priv->rx_time_del_req), - key, &tmp); + key, &tmp, priv); break; case PTP_MSG_P_DEL_REQ: flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_req), - key, &tmp); + key, &tmp, priv); break; case PTP_MSG_P_DEL_RESP: flag = fec_ptp_find_and_remove(&(priv->rx_time_pdel_resp), - key, &tmp); + key, &tmp, priv); break; default: @@ -341,19 +351,19 @@ static uint8_t fec_get_rx_time(struct fec_ptp_private *priv, switch (mode) { case PTP_MSG_SYNC: flag = fec_ptp_find_and_remove(&(priv->rx_time_sync), - key, &tmp); + key, &tmp, priv); break; case PTP_MSG_DEL_REQ: flag = fec_ptp_find_and_remove( - &(priv->rx_time_del_req), key, &tmp); + &(priv->rx_time_del_req), key, &tmp, priv); break; case PTP_MSG_P_DEL_REQ: flag = fec_ptp_find_and_remove( - &(priv->rx_time_pdel_req), key, &tmp); + &(priv->rx_time_pdel_req), key, &tmp, priv); break; case PTP_MSG_P_DEL_RESP: flag = fec_ptp_find_and_remove( - &(priv->rx_time_pdel_resp), key, &tmp); + &(priv->rx_time_pdel_resp), key, &tmp, priv); break; } @@ -367,6 +377,75 @@ static uint8_t fec_get_rx_time(struct fec_ptp_private *priv, } } +static void fec_handle_ptpdrift(struct ptp_set_comp *comp, + struct ptp_time_correct *ptc) +{ + u32 ndrift; + u32 i; + u32 tmp, tmp_ns, tmp_prid; + u32 min_ns, min_prid, miss_ns; + + ndrift = comp->drift; + if (ndrift == 0) { + ptc->corr_inc = 0; + ptc->corr_period = 0; + return; + } + + if (ndrift >= FEC_ATIME_40MHZ) { + ptc->corr_inc = (u32)(ndrift / FEC_ATIME_40MHZ); + ptc->corr_period = 1; + return; + } + + min_ns = 1; + tmp = FEC_ATIME_40MHZ % ndrift; + tmp_prid = (u32)(FEC_ATIME_40MHZ / ndrift); + min_prid = tmp_prid; + miss_ns = tmp / tmp_prid; + for (i = 2; i <= FEC_T_INC_40MHZ; i++) { + tmp = (FEC_ATIME_40MHZ * i) % ndrift; + tmp_prid = (FEC_ATIME_40MHZ * i) / ndrift; + tmp_ns = tmp / tmp_prid; + if (tmp_ns <= 10) { + min_ns = i; + min_prid = tmp_prid; + break; + } + if (tmp_ns < miss_ns) { + min_ns = i; + min_prid = tmp_prid; + miss_ns = tmp_ns; + } + } + + ptc->corr_inc = min_ns; + ptc->corr_period = min_prid; +} + +static void fec_set_drift(struct fec_ptp_private *priv, + struct ptp_set_comp *comp) +{ + struct ptp_time_correct tc; + struct fec_ptp_private *fpp = priv; + u32 tmp, corr_ns; + + fec_handle_ptpdrift(comp, &tc); + if (tc.corr_inc == 0) + return; + + if (comp->o_ops == TRUE) + corr_ns = FEC_T_INC_40MHZ + tc.corr_inc; + else + corr_ns = FEC_T_INC_40MHZ - tc.corr_inc; + + tmp = readl(fpp->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK; + tmp |= corr_ns << FEC_T_INC_CORR_OFFSET; + writel(tmp, fpp->hwp + FEC_ATIME_INC); + + writel(tc.corr_period, fpp->hwp + FEC_ATIME_CORR); +} + static int ptp_open(struct inode *inode, struct file *file) { return 0; @@ -387,10 +466,12 @@ static int ptp_ioctl( struct ptp_rtc_time curr_time; struct ptp_time rx_time, tx_time; struct ptp_ts_data *p_ts; + struct ptp_set_comp *p_comp; struct fec_ptp_private *priv; + unsigned int minor = MINOR(inode->i_rdev); int retval = 0; - priv = (struct fec_ptp_private *) ptp_private; + priv = (struct fec_ptp_private *) ptp_private[minor]; switch (cmd) { case PTP_GET_RX_TIMESTAMP: p_ts = (struct ptp_ts_data *)arg; @@ -428,10 +509,11 @@ static int ptp_ioctl( priv->rx_time_pdel_resp.tail = 0; break; case PTP_SET_COMPENSATION: - /* TBD */ + p_comp = (struct ptp_set_comp *)arg; + fec_set_drift(priv, p_comp); break; case PTP_GET_ORIG_COMP: - /* TBD */ + ((struct ptp_get_comp *)arg)->dw_origcomp = FEC_PTP_ORIG_COMP; break; default: return -EINVAL; @@ -466,7 +548,7 @@ static void ptp_free(void) /* * Resource required for accessing 1588 Timer Registers. */ -int fec_ptp_init(struct fec_ptp_private *priv) +int fec_ptp_init(struct fec_ptp_private *priv, int id) { fec_ptp_init_circ(&(priv->rx_time_sync)); fec_ptp_init_circ(&(priv->rx_time_del_req)); @@ -475,8 +557,9 @@ int fec_ptp_init(struct fec_ptp_private *priv) spin_lock_init(&priv->ptp_lock); spin_lock_init(&priv->cnt_lock); - ptp_private = priv; - init_ptp(); + ptp_private[id] = priv; + if (id == 0) + init_ptp(); return 0; } EXPORT_SYMBOL(fec_ptp_init); diff --git a/drivers/net/fec_1588.h b/drivers/net/fec_1588.h index 55b1a8c995bd..800ff310668f 100644 --- a/drivers/net/fec_1588.h +++ b/drivers/net/fec_1588.h @@ -24,6 +24,9 @@ #include <linux/circ_buf.h> +#define FALSE 0 +#define TRUE 1 + /* FEC 1588 register bits */ #define FEC_T_CTRL_CAPTURE 0x00000800 #define FEC_T_CTRL_RESTART 0x00000200 @@ -32,8 +35,11 @@ #define FEC_T_INC_MASK 0x0000007f #define FEC_T_INC_OFFSET 0 +#define FEC_T_INC_CORR_MASK 0x00007f00 +#define FEC_T_INC_CORR_OFFSET 8 -#define FEC_T_INC_40MHZ 20 +#define FEC_T_INC_40MHZ 25 +#define FEC_ATIME_40MHZ 40000000 #define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00 @@ -52,7 +58,7 @@ #define PTP_MSG_ALL_OTHER 0x5 #define PTP_GET_TX_TIMESTAMP 0x1 -#define PTP_GET_RX_TIMESTAMP 0x2 +#define PTP_GET_RX_TIMESTAMP 0x9 #define PTP_SET_RTC_TIME 0x3 #define PTP_SET_COMPENSATION 0x4 #define PTP_GET_CURRENT_TIME 0x5 @@ -64,13 +70,15 @@ #define PTP_GET_RX_TIMESTAMP_PDELAY_RESP 0xD #define FEC_PTP_DOMAIN_DLFT 0xe0000181 -#define FEC_PTP_IP_OFFS 0xE -#define FEC_PTP_UDP_OFFS 0x22 -#define FEC_PTP_MSG_TYPE_OFFS 0x2A -#define FEC_PTP_SEQ_ID_OFFS 0x48 -#define FEC_PTP_CTRL_OFFS 0x4A +#define FEC_PTP_IP_OFFS 0x0 +#define FEC_PTP_UDP_OFFS 0x14 +#define FEC_PTP_MSG_TYPE_OFFS 0x1C +#define FEC_PTP_SEQ_ID_OFFS 0x3A +#define FEC_PTP_CTRL_OFFS 0x3C #define FEC_PACKET_TYPE_UDP 0x11 +#define FEC_PTP_ORIG_COMP 0x15555555 + /* PTP standard time representation structure */ struct ptp_time{ u64 sec; /* seconds */ @@ -102,6 +110,31 @@ struct ptp_rtc_time { struct ptp_time rtc_time; }; +/* interface for PTP driver command SET_COMPENSATION */ +struct ptp_set_comp { + u32 drift; + bool o_ops; +}; + +/* interface for PTP driver command GET_ORIG_COMP */ +struct ptp_get_comp { + /* the initial compensation value */ + u32 dw_origcomp; + /* the minimum compensation value */ + u32 dw_mincomp; + /*the max compensation value*/ + u32 dw_maxcomp; + /*the min drift applying min compensation value in ppm*/ + u32 dw_mindrift; + /*the max drift applying max compensation value in ppm*/ + u32 dw_maxdrift; +}; + +struct ptp_time_correct { + u32 corr_period; + u32 corr_inc; +}; + /* PTP message version */ #define PTP_1588_MSG_VER_1 1 #define PTP_1588_MSG_VER_2 2 @@ -124,7 +157,7 @@ struct fec_ptp_private { }; #ifdef CONFIG_FEC_1588 -extern int fec_ptp_init(struct fec_ptp_private *priv); +extern int fec_ptp_init(struct fec_ptp_private *priv, int id); extern void fec_ptp_cleanup(struct fec_ptp_private *priv); extern int fec_ptp_start(struct fec_ptp_private *priv); extern void fec_ptp_stop(struct fec_ptp_private *priv); @@ -134,7 +167,7 @@ extern void fec_ptp_store_rxstamp(struct fec_ptp_private *priv, struct sk_buff *skb, struct bufdesc *bdp); #else -static inline int fec_ptp_init(struct fec_ptp_private *priv) +static inline int fec_ptp_init(struct fec_ptp_private *priv, int id) { return 1; } diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index bd4e8d72dc08..e17b70291bbc 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -264,6 +264,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) (phydev->phy_id & phydrv->phy_id_mask)); } +#ifdef CONFIG_PM + static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) { struct device_driver *drv = phydev->dev.driver; @@ -295,34 +297,88 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) return true; } -/* Suspend and resume. Copied from platform_suspend and - * platform_resume - */ -static int mdio_bus_suspend(struct device * dev, pm_message_t state) +static int mdio_bus_suspend(struct device *dev) { struct phy_driver *phydrv = to_phy_driver(dev->driver); struct phy_device *phydev = to_phy_device(dev); + /* + * We must stop the state machine manually, otherwise it stops out of + * control, possibly with the phydev->lock held. Upon resume, netdev + * may call phy routines that try to grab the same lock, and that may + * lead to a deadlock. + */ + if (phydev->attached_dev) + phy_stop_machine(phydev); + if (!mdio_bus_phy_may_suspend(phydev)) return 0; + return phydrv->suspend(phydev); } -static int mdio_bus_resume(struct device * dev) +static int mdio_bus_resume(struct device *dev) { struct phy_driver *phydrv = to_phy_driver(dev->driver); struct phy_device *phydev = to_phy_device(dev); + int ret; if (!mdio_bus_phy_may_suspend(phydev)) + goto no_resume; + + ret = phydrv->resume(phydev); + if (ret < 0) + return ret; + +no_resume: + if (phydev->attached_dev) + phy_start_machine(phydev, NULL); + + return 0; +} + +static int mdio_bus_restore(struct device *dev) +{ + struct phy_device *phydev = to_phy_device(dev); + struct net_device *netdev = phydev->attached_dev; + int ret; + + if (!netdev) return 0; - return phydrv->resume(phydev); + + ret = phy_init_hw(phydev); + if (ret < 0) + return ret; + + /* The PHY needs to renegotiate. */ + phydev->link = 0; + phydev->state = PHY_UP; + + phy_start_machine(phydev, NULL); + + return 0; } +static struct dev_pm_ops mdio_bus_pm_ops = { + .suspend = mdio_bus_suspend, + .resume = mdio_bus_resume, + .freeze = mdio_bus_suspend, + .thaw = mdio_bus_resume, + .restore = mdio_bus_restore, +}; + +#define MDIO_BUS_PM_OPS (&mdio_bus_pm_ops) + +#else + +#define MDIO_BUS_PM_OPS NULL + +#endif /* CONFIG_PM */ + struct bus_type mdio_bus_type = { .name = "mdio_bus", .match = mdio_bus_match, - .suspend = mdio_bus_suspend, - .resume = mdio_bus_resume, + .pm = MDIO_BUS_PM_OPS, }; EXPORT_SYMBOL(mdio_bus_type); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index eda94fcd4065..d2df6382e123 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -413,7 +413,6 @@ EXPORT_SYMBOL(phy_start_aneg); static void phy_change(struct work_struct *work); -static void phy_state_machine(struct work_struct *work); /** * phy_start_machine - start PHY state machine tracking @@ -433,7 +432,6 @@ void phy_start_machine(struct phy_device *phydev, { phydev->adjust_state = handler; - INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine); schedule_delayed_work(&phydev->state_queue, HZ); } @@ -764,7 +762,7 @@ EXPORT_SYMBOL(phy_start); * phy_state_machine - Handle the state machine * @work: work_struct that describes the work to be done */ -static void phy_state_machine(struct work_struct *work) +void phy_state_machine(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct phy_device *phydev = diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index b10fedd82143..adbc0fded130 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -177,6 +177,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->state = PHY_DOWN; mutex_init(&dev->lock); + INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); return dev; } @@ -378,6 +379,20 @@ void phy_disconnect(struct phy_device *phydev) } EXPORT_SYMBOL(phy_disconnect); +int phy_init_hw(struct phy_device *phydev) +{ + int ret; + + if (!phydev->drv || !phydev->drv->config_init) + return 0; + + ret = phy_scan_fixups(phydev); + if (ret < 0) + return ret; + + return phydev->drv->config_init(phydev); +} + /** * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach @@ -425,21 +440,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) */ - if (phydev->drv->config_init) { - int err; - - err = phy_scan_fixups(phydev); - - if (err < 0) - return err; - - err = phydev->drv->config_init(phydev); - - if (err < 0) - return err; - } - - return 0; + return phy_init_hw(phydev); } EXPORT_SYMBOL(phy_attach_direct); diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index d4c82f5fa555..a13d107a412b 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -789,6 +789,7 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) } pdata->last_carrier = carrier; } + udelay(10); } static int smsc911x_mii_probe(struct net_device *dev) @@ -1011,7 +1012,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) struct net_device *dev = pdata->dev; int npackets = 0; - while (likely(netif_running(dev)) && (npackets < budget)) { + while (npackets < budget) { unsigned int pktlength; unsigned int pktwords; struct sk_buff *skb; @@ -1584,7 +1585,7 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) if (unlikely(intsts & inten & INT_STS_PHY_INT_)) { smsc911x_reg_write( pdata, INT_STS , INT_STS_PHY_INT_); temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr, MII_INTSTS); - SMSC_TRACE("PHY interrupt, sts 0x%04X", (u16)temp); + SMSC_TRACE(DRV,"PHY interrupt, sts 0x%04X", (u16)temp); smsc911x_phy_adjust_link(dev); serviced = IRQ_HANDLED; } diff --git a/drivers/net/wireless/ath6kl/os/linux/ar6000_android.c b/drivers/net/wireless/ath6kl/os/linux/ar6000_android.c index 1ca77e513493..9d0c3773d4d7 100644 --- a/drivers/net/wireless/ath6kl/os/linux/ar6000_android.c +++ b/drivers/net/wireless/ath6kl/os/linux/ar6000_android.c @@ -56,7 +56,7 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(android, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -char fwpath[256] = "/system/wifi"; +char fwpath[256] = "/lib/firmware/ath6k/AR6102"; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ int buspm = WLAN_PWR_CTRL_CUT_PWR; int wow2mode = WLAN_PWR_CTRL_CUT_PWR; |