summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-03-05 03:32:48 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-03-05 03:32:48 -0500
commit30be2b690449a31bd51f2302b262204198da06fb (patch)
treeb804936498d79c744cd23630565444050c26e32c
parent56ca294877ce9a02e176c76a742e16cb2c78288b (diff)
parent955bd9bb8e6e4ac3d042434424aed42efdd5c636 (diff)
Merge pobox.com:/garz/repo/netdev-2.6/smc91x
into pobox.com:/garz/repo/net-drivers-2.6
-rw-r--r--arch/arm/mach-pxa/lubbock.c2
-rw-r--r--arch/arm/mach-sa1100/neponset.c2
-rw-r--r--drivers/net/smc91x.c275
-rw-r--r--drivers/net/smc91x.h79
4 files changed, 258 insertions, 100 deletions
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index d4516a8ad351..dd012d6e2f5c 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = 0x0c000000,
.end = 0x0c0fffff,
.flags = IORESOURCE_MEM,
@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = 0x0e000000,
.end = 0x0e0fffff,
.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index e3dc13832d76..6ffa50151a8c 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index fb9935b670ac..6766bacbb199 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -210,10 +210,15 @@ struct smc_local {
spinlock_t lock;
+#ifdef SMC_CAN_USE_DATACS
+ u32 __iomem *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
#endif
+ void __iomem *base;
};
#if SMC_DEBUG > 0
@@ -307,8 +312,8 @@ static void PRINT_PKT(u_char *buf, int length)
*/
static void smc_reset(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int ctl, cfg;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -399,8 +404,8 @@ static void smc_reset(struct net_device *dev)
*/
static void smc_enable(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
int mask;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -433,8 +438,8 @@ static void smc_enable(struct net_device *dev)
*/
static void smc_shutdown(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
@@ -462,7 +467,7 @@ static void smc_shutdown(struct net_device *dev)
static inline void smc_rcv(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int packet_number, status, packet_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -483,7 +488,19 @@ static inline void smc_rcv(struct net_device *dev)
dev->name, packet_number, status,
packet_len, packet_len);
- if (unlikely(status & RS_ERRORS)) {
+ back:
+ if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
+ if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
+ /* accept VLAN packets */
+ status &= ~RS_TOOLONG;
+ goto back;
+ }
+ if (packet_len < 6) {
+ /* bloody hardware */
+ printk(KERN_ERR "%s: fubar (rxlen %u status %x\n",
+ dev->name, packet_len, status);
+ status |= RS_TOOSHORT;
+ }
SMC_WAIT_MMU_BUSY();
SMC_SET_MMU_CMD(MC_RELEASE);
lp->stats.rx_errors++;
@@ -508,7 +525,7 @@ static inline void smc_rcv(struct net_device *dev)
* (2 bytes, possibly containing the payload odd byte).
* Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses.
- * Ence packet_len - 6 + 2 + 2 + 2.
+ * Hence packet_len - 6 + 2 + 2 + 2.
*/
skb = dev_alloc_skb(packet_len);
if (unlikely(skb == NULL)) {
@@ -596,7 +613,7 @@ static void smc_hardware_send_pkt(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
struct sk_buff *skb;
unsigned int packet_no, len;
unsigned char *buf;
@@ -680,7 +697,7 @@ done: if (!THROTTLE_TX_PKTS)
static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int numPages, poll_count, status;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -752,8 +769,8 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static void smc_tx(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int saved_packet, packet_no, tx_status, pkt_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -809,7 +826,8 @@ static void smc_tx(struct net_device *dev)
static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int mii_reg, mask;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -830,7 +848,8 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
static unsigned int smc_mii_in(struct net_device *dev, int bits)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int mii_reg, mask, val;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -854,7 +873,8 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits)
*/
static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int phydata;
SMC_SELECT_BANK(3);
@@ -884,7 +904,8 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
int phydata)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
SMC_SELECT_BANK(3);
@@ -946,7 +967,7 @@ static void smc_phy_detect(struct net_device *dev)
static int smc_phy_fixed(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int phyaddr = lp->mii.phy_id;
int bmcr, cfg1;
@@ -1017,13 +1038,29 @@ static int smc_phy_reset(struct net_device *dev, int phy)
/*
* smc_phy_powerdown - powerdown phy
* @dev: net device
- * @phy: phy address
*
* Power down the specified PHY
*/
-static void smc_phy_powerdown(struct net_device *dev, int phy)
+static void smc_phy_powerdown(struct net_device *dev)
{
+ struct smc_local *lp = netdev_priv(dev);
unsigned int bmcr;
+ int phy = lp->mii.phy_id;
+
+ if (lp->phy_type == 0)
+ return;
+
+ /* We need to ensure that no calls to smc_phy_configure are
+ pending.
+
+ flush_scheduled_work() cannot be called because we are
+ running with the netlink semaphore held (from
+ devinet_ioctl()) and the pending work queue contains
+ linkwatch_event() (scheduled by netif_carrier_off()
+ above). linkwatch_event() also wants the netlink semaphore.
+ */
+ while(lp->work_pending)
+ schedule();
bmcr = smc_phy_read(dev, phy, MII_BMCR);
smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
@@ -1040,7 +1077,7 @@ static void smc_phy_powerdown(struct net_device *dev, int phy)
static void smc_phy_check_media(struct net_device *dev, int init)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
/* duplex state has changed */
@@ -1068,7 +1105,7 @@ static void smc_phy_configure(void *data)
{
struct net_device *dev = data;
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int phyaddr = lp->mii.phy_id;
int my_phy_caps; /* My PHY capabilities */
int my_ad_caps; /* My Advertised capabilities */
@@ -1193,7 +1230,7 @@ static void smc_phy_interrupt(struct net_device *dev)
static void smc_10bt_check_media(struct net_device *dev, int init)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int old_carrier, new_carrier;
old_carrier = netif_carrier_ok(dev) ? 1 : 0;
@@ -1216,7 +1253,8 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
static void smc_eph_interrupt(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int ctl;
smc_10bt_check_media(dev, 0);
@@ -1235,8 +1273,8 @@ static void smc_eph_interrupt(struct net_device *dev)
static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
int status, mask, timeout, card_stats;
int saved_pointer;
@@ -1350,7 +1388,7 @@ static void smc_poll_controller(struct net_device *dev)
static void smc_timeout(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int status, mask, meminfo, fifo;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -1394,7 +1432,7 @@ static void smc_timeout(struct net_device *dev)
static void smc_set_multicast_list(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned char multicast_table[8];
int update_multicast = 0;
@@ -1561,21 +1599,7 @@ static int smc_close(struct net_device *dev)
/* clear everything */
smc_shutdown(dev);
- if (lp->phy_type != 0) {
- /* We need to ensure that no calls to
- smc_phy_configure are pending.
-
- flush_scheduled_work() cannot be called because we
- are running with the netlink semaphore held (from
- devinet_ioctl()) and the pending work queue
- contains linkwatch_event() (scheduled by
- netif_carrier_off() above). linkwatch_event() also
- wants the netlink semaphore.
- */
- while(lp->work_pending)
- schedule();
- smc_phy_powerdown(dev, lp->mii.phy_id);
- }
+ smc_phy_powerdown(dev);
if (lp->pending_tx_skb) {
dev_kfree_skb(lp->pending_tx_skb);
@@ -1723,7 +1747,7 @@ static struct ethtool_ops smc_ethtool_ops = {
* I just deleted auto_irq.c, since it was never built...
* --jgarzik
*/
-static int __init smc_findirq(unsigned long ioaddr)
+static int __init smc_findirq(void __iomem *ioaddr)
{
int timeout = 20;
unsigned long cookie;
@@ -1796,7 +1820,7 @@ static int __init smc_findirq(unsigned long ioaddr)
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
+static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
{
struct smc_local *lp = netdev_priv(dev);
static int version_printed = 0;
@@ -1813,7 +1837,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
if ((val & 0xFF) == 0x33) {
printk(KERN_WARNING
"%s: Detected possible byte-swapped interface"
- " at IOADDR 0x%lx\n", CARDNAME, ioaddr);
+ " at IOADDR %p\n", CARDNAME, ioaddr);
}
retval = -ENODEV;
goto err_out;
@@ -1839,8 +1863,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
SMC_SELECT_BANK(1);
val = SMC_GET_BASE();
val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
- if ((ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) {
- printk("%s: IOADDR %lx doesn't match configuration (%x).\n",
+ if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
+ printk("%s: IOADDR %p doesn't match configuration (%x).\n",
CARDNAME, ioaddr, val);
}
@@ -1855,7 +1879,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
version_string = chip_ids[ (revision_register >> 4) & 0xF];
if (!version_string || (revision_register & 0xff00) != 0x3300) {
/* I don't recognize this chip, so... */
- printk("%s: IO 0x%lx: Unrecognized revision register 0x%04x"
+ printk("%s: IO %p: Unrecognized revision register 0x%04x"
", Contact author.\n", CARDNAME,
ioaddr, revision_register);
@@ -1868,7 +1892,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
printk("%s", version);
/* fill in some of the fields */
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long)ioaddr;
+ lp->base = ioaddr;
lp->version = revision_register & 0xff;
spin_lock_init(&lp->lock);
@@ -1974,9 +1999,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
retval = register_netdev(dev);
if (retval == 0) {
/* now, print out the card info, in a short format.. */
- printk("%s: %s (rev %d) at %#lx IRQ %d",
+ printk("%s: %s (rev %d) at %p IRQ %d",
dev->name, version_string, revision_register & 0x0f,
- dev->base_addr, dev->irq);
+ lp->base, dev->irq);
if (dev->dma != (unsigned char)-1)
printk(" DMA %d", dev->dma);
@@ -2012,16 +2037,21 @@ err_out:
return retval;
}
-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
- void *addr;
+ void __iomem *addr;
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ if (!res)
+ return 0;
/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;
@@ -2069,6 +2099,62 @@ static int smc_enable_device(unsigned long attrib_phys)
return 0;
}
+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (!res)
+ return 0;
+
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return;
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+ return;
+ }
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+
+ if (lp->datacs)
+ iounmap(lp->datacs);
+
+ lp->datacs = NULL;
+
+ if (res)
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2084,20 +2170,20 @@ static int smc_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
- unsigned int *addr;
+ struct resource *res;
+ unsigned int __iomem *addr;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
}
- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2106,7 +2192,7 @@ static int smc_drv_probe(struct device *dev)
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2114,42 +2200,26 @@ static int smc_drv_probe(struct device *dev)
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);
- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;
addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}
dev_set_drvdata(dev, ndev);
- ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ ret = smc_probe(ndev, addr);
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2157,6 +2227,22 @@ static int smc_drv_probe(struct device *dev)
}
#endif
+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}
@@ -2164,6 +2250,7 @@ static int smc_drv_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct smc_local *lp = netdev_priv(ndev);
struct resource *res;
dev_set_drvdata(dev, NULL);
@@ -2176,11 +2263,14 @@ static int smc_drv_remove(struct device *dev)
if (ndev->dma != (unsigned char)-1)
pxa_free_dma(ndev->dma);
#endif
- iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(lp->base);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, SMC_IO_EXTENT);
free_netdev(ndev);
@@ -2196,6 +2286,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level)
if (netif_running(ndev)) {
netif_device_detach(ndev);
smc_shutdown(ndev);
+ smc_phy_powerdown(ndev);
}
}
return 0;
@@ -2208,9 +2299,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index fad8c0437334..e347b71af038 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -162,6 +162,26 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
}
}
+#elif defined(CONFIG_ARCH_OMAP)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+
#elif defined(CONFIG_ISA)
#define SMC_CAN_USE_8BIT 1
@@ -362,7 +382,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)
/*
. Bank Select Register:
@@ -883,7 +903,7 @@ static const char * chip_ids[ 16 ] = {
#endif
#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -898,7 +918,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -918,11 +938,11 @@ static const char * chip_ids[ 16 ] = {
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif
#if ! SMC_CAN_USE_16BIT
@@ -941,6 +961,51 @@ static const char * chip_ids[ 16 ] = {
})
#endif
+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif