Commit 30be2b69 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/netdev-2.6/smc91x

into pobox.com:/garz/repo/net-drivers-2.6
parents 56ca2948 955bd9bb
...@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = { ...@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = { static struct resource smc91x_resources[] = {
[0] = { [0] = {
.name = "smc91x-regs",
.start = 0x0c000000, .start = 0x0c000000,
.end = 0x0c0fffff, .end = 0x0c0fffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
...@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = { ...@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { [2] = {
.name = "smc91x-attrib",
.start = 0x0e000000, .start = 0x0e000000,
.end = 0x0e0fffff, .end = 0x0e0fffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
......
...@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = { ...@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = { static struct resource smc91x_resources[] = {
[0] = { [0] = {
.name = "smc91x-regs",
.start = SA1100_CS3_PHYS, .start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff, .end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
...@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = { ...@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
[2] = { [2] = {
.name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000, .start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff, .end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
......
...@@ -210,10 +210,15 @@ struct smc_local { ...@@ -210,10 +210,15 @@ struct smc_local {
spinlock_t lock; spinlock_t lock;
#ifdef SMC_CAN_USE_DATACS
u32 __iomem *datacs;
#endif
#ifdef SMC_USE_PXA_DMA #ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */ /* DMA needs the physical address of the chip */
u_long physaddr; u_long physaddr;
#endif #endif
void __iomem *base;
}; };
#if SMC_DEBUG > 0 #if SMC_DEBUG > 0
...@@ -307,8 +312,8 @@ static void PRINT_PKT(u_char *buf, int length) ...@@ -307,8 +312,8 @@ static void PRINT_PKT(u_char *buf, int length)
*/ */
static void smc_reset(struct net_device *dev) static void smc_reset(struct net_device *dev)
{ {
unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
unsigned int ctl, cfg; unsigned int ctl, cfg;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__); DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
...@@ -399,8 +404,8 @@ static void smc_reset(struct net_device *dev) ...@@ -399,8 +404,8 @@ static void smc_reset(struct net_device *dev)
*/ */
static void smc_enable(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); struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int mask; int mask;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__); DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
...@@ -433,8 +438,8 @@ static void smc_enable(struct net_device *dev) ...@@ -433,8 +438,8 @@ static void smc_enable(struct net_device *dev)
*/ */
static void smc_shutdown(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); struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
...@@ -462,7 +467,7 @@ static void smc_shutdown(struct net_device *dev) ...@@ -462,7 +467,7 @@ static void smc_shutdown(struct net_device *dev)
static inline void smc_rcv(struct net_device *dev) static inline void smc_rcv(struct net_device *dev)
{ {
struct smc_local *lp = netdev_priv(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; unsigned int packet_number, status, packet_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__); DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
...@@ -483,7 +488,19 @@ static inline void smc_rcv(struct net_device *dev) ...@@ -483,7 +488,19 @@ static inline void smc_rcv(struct net_device *dev)
dev->name, packet_number, status, dev->name, packet_number, status,
packet_len, packet_len); 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_WAIT_MMU_BUSY();
SMC_SET_MMU_CMD(MC_RELEASE); SMC_SET_MMU_CMD(MC_RELEASE);
lp->stats.rx_errors++; lp->stats.rx_errors++;
...@@ -508,7 +525,7 @@ static inline void smc_rcv(struct net_device *dev) ...@@ -508,7 +525,7 @@ static inline void smc_rcv(struct net_device *dev)
* (2 bytes, possibly containing the payload odd byte). * (2 bytes, possibly containing the payload odd byte).
* Furthermore, we add 2 bytes to allow rounding up to * Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses. * 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); skb = dev_alloc_skb(packet_len);
if (unlikely(skb == NULL)) { if (unlikely(skb == NULL)) {
...@@ -596,7 +613,7 @@ static void smc_hardware_send_pkt(unsigned long data) ...@@ -596,7 +613,7 @@ static void smc_hardware_send_pkt(unsigned long data)
{ {
struct net_device *dev = (struct net_device *)data; struct net_device *dev = (struct net_device *)data;
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr; void __iomem *ioaddr = lp->base;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int packet_no, len; unsigned int packet_no, len;
unsigned char *buf; unsigned char *buf;
...@@ -680,7 +697,7 @@ done: if (!THROTTLE_TX_PKTS) ...@@ -680,7 +697,7 @@ done: if (!THROTTLE_TX_PKTS)
static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct smc_local *lp = netdev_priv(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; unsigned int numPages, poll_count, status;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__); 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) ...@@ -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) static void smc_tx(struct net_device *dev)
{ {
unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
unsigned int saved_packet, packet_no, tx_status, pkt_len; unsigned int saved_packet, packet_no, tx_status, pkt_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__); DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
...@@ -809,7 +826,8 @@ static void smc_tx(struct net_device *dev) ...@@ -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) 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; unsigned int mii_reg, mask;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); 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) ...@@ -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) 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; unsigned int mii_reg, mask, val;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); 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) ...@@ -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) 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; unsigned int phydata;
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
...@@ -884,7 +904,8 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) ...@@ -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, static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
int phydata) int phydata)
{ {
unsigned long ioaddr = dev->base_addr; struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
...@@ -946,7 +967,7 @@ static void smc_phy_detect(struct net_device *dev) ...@@ -946,7 +967,7 @@ static void smc_phy_detect(struct net_device *dev)
static int smc_phy_fixed(struct net_device *dev) static int smc_phy_fixed(struct net_device *dev)
{ {
struct smc_local *lp = netdev_priv(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 phyaddr = lp->mii.phy_id;
int bmcr, cfg1; int bmcr, cfg1;
...@@ -1017,13 +1038,29 @@ static int smc_phy_reset(struct net_device *dev, int phy) ...@@ -1017,13 +1038,29 @@ static int smc_phy_reset(struct net_device *dev, int phy)
/* /*
* smc_phy_powerdown - powerdown phy * smc_phy_powerdown - powerdown phy
* @dev: net device * @dev: net device
* @phy: phy address
* *
* Power down the specified PHY * 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; 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); bmcr = smc_phy_read(dev, phy, MII_BMCR);
smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); 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) ...@@ -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) static void smc_phy_check_media(struct net_device *dev, int init)
{ {
struct smc_local *lp = netdev_priv(dev); 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)) { if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
/* duplex state has changed */ /* duplex state has changed */
...@@ -1068,7 +1105,7 @@ static void smc_phy_configure(void *data) ...@@ -1068,7 +1105,7 @@ static void smc_phy_configure(void *data)
{ {
struct net_device *dev = data; struct net_device *dev = data;
struct smc_local *lp = netdev_priv(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 phyaddr = lp->mii.phy_id;
int my_phy_caps; /* My PHY capabilities */ int my_phy_caps; /* My PHY capabilities */
int my_ad_caps; /* My Advertised capabilities */ int my_ad_caps; /* My Advertised capabilities */
...@@ -1193,7 +1230,7 @@ static void smc_phy_interrupt(struct net_device *dev) ...@@ -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) static void smc_10bt_check_media(struct net_device *dev, int init)
{ {
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr; void __iomem *ioaddr = lp->base;
unsigned int old_carrier, new_carrier; unsigned int old_carrier, new_carrier;
old_carrier = netif_carrier_ok(dev) ? 1 : 0; old_carrier = netif_carrier_ok(dev) ? 1 : 0;
...@@ -1216,7 +1253,8 @@ static void smc_10bt_check_media(struct net_device *dev, int init) ...@@ -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) 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; unsigned int ctl;
smc_10bt_check_media(dev, 0); smc_10bt_check_media(dev, 0);
...@@ -1235,8 +1273,8 @@ static void smc_eph_interrupt(struct net_device *dev) ...@@ -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) static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int status, mask, timeout, card_stats; int status, mask, timeout, card_stats;
int saved_pointer; int saved_pointer;
...@@ -1350,7 +1388,7 @@ static void smc_poll_controller(struct net_device *dev) ...@@ -1350,7 +1388,7 @@ static void smc_poll_controller(struct net_device *dev)
static void smc_timeout(struct net_device *dev) static void smc_timeout(struct net_device *dev)
{ {
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr; void __iomem *ioaddr = lp->base;
int status, mask, meminfo, fifo; int status, mask, meminfo, fifo;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__); DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
...@@ -1394,7 +1432,7 @@ static void smc_timeout(struct net_device *dev) ...@@ -1394,7 +1432,7 @@ static void smc_timeout(struct net_device *dev)
static void smc_set_multicast_list(struct net_device *dev) static void smc_set_multicast_list(struct net_device *dev)
{ {
struct smc_local *lp = netdev_priv(dev); struct smc_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr; void __iomem *ioaddr = lp->base;
unsigned char multicast_table[8]; unsigned char multicast_table[8];
int update_multicast = 0; int update_multicast = 0;
...@@ -1561,21 +1599,7 @@ static int smc_close(struct net_device *dev) ...@@ -1561,21 +1599,7 @@ static int smc_close(struct net_device *dev)
/* clear everything */ /* clear everything */
smc_shutdown(dev); smc_shutdown(dev);
if (lp->phy_type != 0) { smc_phy_powerdown(dev);
/* 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);
}
if (lp->pending_tx_skb) { if (lp->pending_tx_skb) {
dev_kfree_skb(lp->pending_tx_skb); dev_kfree_skb(lp->pending_tx_skb);
...@@ -1723,7 +1747,7 @@ static struct ethtool_ops smc_ethtool_ops = { ...@@ -1723,7 +1747,7 @@ static struct ethtool_ops smc_ethtool_ops = {
* I just deleted auto_irq.c, since it was never built... * I just deleted auto_irq.c, since it was never built...
* --jgarzik * --jgarzik
*/ */
static int __init smc_findirq(unsigned long ioaddr) static int __init smc_findirq(void __iomem *ioaddr)
{ {
int timeout = 20; int timeout = 20;
unsigned long cookie; unsigned long cookie;
...@@ -1796,7 +1820,7 @@ static int __init smc_findirq(unsigned long ioaddr) ...@@ -1796,7 +1820,7 @@ static int __init smc_findirq(unsigned long ioaddr)
* o actually GRAB the irq. * o actually GRAB the irq.
* o GRAB the region * 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); struct smc_local *lp = netdev_priv(dev);
static int version_printed = 0; static int version_printed = 0;
...@@ -1813,7 +1837,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -1813,7 +1837,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
if ((val & 0xFF) == 0x33) { if ((val & 0xFF) == 0x33) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Detected possible byte-swapped interface" "%s: Detected possible byte-swapped interface"
" at IOADDR 0x%lx\n", CARDNAME, ioaddr); " at IOADDR %p\n", CARDNAME, ioaddr);
} }
retval = -ENODEV; retval = -ENODEV;
goto err_out; goto err_out;
...@@ -1839,8 +1863,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -1839,8 +1863,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
val = SMC_GET_BASE(); val = SMC_GET_BASE();
val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT; val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
if ((ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
printk("%s: IOADDR %lx doesn't match configuration (%x).\n", printk("%s: IOADDR %p doesn't match configuration (%x).\n",
CARDNAME, ioaddr, val); CARDNAME, ioaddr, val);
} }
...@@ -1855,7 +1879,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -1855,7 +1879,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
version_string = chip_ids[ (revision_register >> 4) & 0xF]; version_string = chip_ids[ (revision_register >> 4) & 0xF];
if (!version_string || (revision_register & 0xff00) != 0x3300) { if (!version_string || (revision_register & 0xff00) != 0x3300) {
/* I don't recognize this chip, so... */ /* 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, ", Contact author.\n", CARDNAME,
ioaddr, revision_register); ioaddr, revision_register);
...@@ -1868,7 +1892,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -1868,7 +1892,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
printk("%s", version); printk("%s", version);
/* fill in some of the fields */ /* fill in some of the fields */
dev->base_addr = ioaddr; dev->base_addr = (unsigned long)ioaddr;
lp->base = ioaddr;
lp->version = revision_register & 0xff; lp->version = revision_register & 0xff;
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
...@@ -1974,9 +1999,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -1974,9 +1999,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
retval = register_netdev(dev); retval = register_netdev(dev);
if (retval == 0) { if (retval == 0) {
/* now, print out the card info, in a short format.. */ /* 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->name, version_string, revision_register & 0x0f,
dev->base_addr, dev->irq); lp->base, dev->irq);
if (dev->dma != (unsigned char)-1) if (dev->dma != (unsigned char)-1)
printk(" DMA %d", dev->dma); printk(" DMA %d", dev->dma);
...@@ -2012,16 +2037,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) ...@@ -2012,16 +2037,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
return retval; return retval;
} }
static int smc_enable_device(unsigned long attrib_phys) static int smc_enable_device(struct platform_device *pdev)
{ {
unsigned long flags; unsigned long flags;
unsigned char ecor, ecsr; 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. * Map the attribute space. This is overkill, but clean.
*/ */
addr = ioremap(attrib_phys, ATTRIB_SIZE); addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr) if (!addr)
return -ENOMEM; return -ENOMEM;
...@@ -2069,6 +2099,62 @@ static int smc_enable_device(unsigned long attrib_phys) ...@@ -2069,6 +2099,62 @@ static int smc_enable_device(unsigned long attrib_phys)
return 0; 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) * smc_init(void)
* Input parameters: * Input parameters:
...@@ -2084,20 +2170,20 @@ static int smc_drv_probe(struct device *dev) ...@@ -2084,20 +2170,20 @@ static int smc_drv_probe(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev; struct net_device *ndev;
struct resource *res, *ext = NULL; struct resource *res;
unsigned int *addr; unsigned int __iomem *addr;
int ret; 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) { if (!res) {
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
/*
* Request the regions. if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
*/
if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
...@@ -2106,7 +2192,7 @@ static int smc_drv_probe(struct device *dev) ...@@ -2106,7 +2192,7 @@ static int smc_drv_probe(struct device *dev)
if (!ndev) { if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME); printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM; ret = -ENOMEM;
goto release_1; goto out_release_io;
} }
SET_MODULE_OWNER(ndev); SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev); SET_NETDEV_DEV(ndev, dev);
...@@ -2114,42 +2200,26 @@ static int smc_drv_probe(struct device *dev) ...@@ -2114,42 +2200,26 @@ static int smc_drv_probe(struct device *dev)
ndev->dma = (unsigned char)-1; ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0); ndev->irq = platform_get_irq(pdev, 0);
ext = platform_get_resource(pdev, IORESOURCE_MEM, 1); ret = smc_request_attrib(pdev);
if (ext) { if (ret)
if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) { goto out_free_netdev;
ret = -EBUSY;
goto release_1;
}
#if defined(CONFIG_SA1100_ASSABET) #if defined(CONFIG_SA1100_ASSABET)
NCR_0 |= NCR_ENET_OSC_EN; NCR_0 |= NCR_ENET_OSC_EN;
#endif #endif
ret = smc_enable_device(pdev);
ret = smc_enable_device(ext->start); if (ret)
if (ret) goto out_release_attrib;
goto release_both;
}
addr = ioremap(res->start, SMC_IO_EXTENT); addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) { if (!addr) {
ret = -ENOMEM; ret = -ENOMEM;
goto release_both; goto out_release_attrib;
} }
dev_set_drvdata(dev, ndev); dev_set_drvdata(dev, ndev);
ret = smc_probe(ndev, (unsigned long)addr); ret = smc_probe(ndev, addr);
if (ret != 0) { if (ret != 0)
dev_set_drvdata(dev, NULL); goto out_iounmap;
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);
}
#ifdef SMC_USE_PXA_DMA #ifdef SMC_USE_PXA_DMA
else { else {
struct smc_local *lp = netdev_priv(ndev); struct smc_local *lp = netdev_priv(ndev);
...@@ -2157,6 +2227,22 @@ static int smc_drv_probe(struct device *dev) ...@@ -2157,6 +2227,22 @@ static int smc_drv_probe(struct device *dev)
} }
#endif #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; return ret;
} }
...@@ -2164,6 +2250,7 @@ static int smc_drv_remove(struct device *dev) ...@@ -2164,6 +2250,7 @@ static int smc_drv_remove(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct smc_local *lp = netdev_priv(ndev);
struct resource *res; struct resource *res;
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
...@@ -2176,11 +2263,14 @@ static int smc_drv_remove(struct device *dev) ...@@ -2176,11 +2263,14 @@ static int smc_drv_remove(struct device *dev)
if (ndev->dma != (unsigned char)-1) if (ndev->dma != (unsigned char)-1)
pxa_free_dma(ndev->dma); pxa_free_dma(ndev->dma);
#endif #endif
iounmap((void *)ndev->base_addr); iounmap(lp->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) smc_release_datacs(pdev,ndev);
release_mem_region(res->start, ATTRIB_SIZE); smc_release_attrib(pdev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
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); release_mem_region(res->start, SMC_IO_EXTENT);
free_netdev(ndev); free_netdev(ndev);
...@@ -2196,6 +2286,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level) ...@@ -2196,6 +2286,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level)
if (netif_running(ndev)) { if (netif_running(ndev)) {
netif_device_detach(ndev); netif_device_detach(ndev);
smc_shutdown(ndev); smc_shutdown(ndev);
smc_phy_powerdown(ndev);
} }
} }
return 0; return 0;
...@@ -2208,9 +2299,7 @@ static int smc_drv_resume(struct device *dev, u32 level) ...@@ -2208,9 +2299,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
if (ndev && level == RESUME_ENABLE) { if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev); struct smc_local *lp = netdev_priv(ndev);
smc_enable_device(pdev);
if (pdev->num_resources == 3)
smc_enable_device(pdev->resource[2].start);
if (netif_running(ndev)) { if (netif_running(ndev)) {
smc_reset(ndev); smc_reset(ndev);
smc_enable(ndev); smc_enable(ndev);
......
...@@ -162,6 +162,26 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg) ...@@ -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) #elif defined(CONFIG_ISA)
#define SMC_CAN_USE_8BIT 1 #define SMC_CAN_USE_8BIT 1
...@@ -362,7 +382,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) ...@@ -362,7 +382,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
#define SMC_IO_SHIFT 0 #define SMC_IO_SHIFT 0
#endif #endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) #define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
#define SMC_DATA_EXTENT (4)
/* /*
. Bank Select Register: . Bank Select Register:
...@@ -883,7 +903,7 @@ static const char * chip_ids[ 16 ] = { ...@@ -883,7 +903,7 @@ static const char * chip_ids[ 16 ] = {
#endif #endif
#if SMC_CAN_USE_32BIT #if SMC_CAN_USE_32BIT
#define SMC_PUSH_DATA(p, l) \ #define _SMC_PUSH_DATA(p, l) \
do { \ do { \
char *__ptr = (p); \ char *__ptr = (p); \
int __len = (l); \ int __len = (l); \
...@@ -898,7 +918,7 @@ static const char * chip_ids[ 16 ] = { ...@@ -898,7 +918,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \ } \
} while (0) } while (0)
#define SMC_PULL_DATA(p, l) \ #define _SMC_PULL_DATA(p, l) \
do { \ do { \
char *__ptr = (p); \ char *__ptr = (p); \
int __len = (l); \ int __len = (l); \
...@@ -918,11 +938,11 @@ static const char * chip_ids[ 16 ] = { ...@@ -918,11 +938,11 @@ static const char * chip_ids[ 16 ] = {
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0) } while (0)
#elif SMC_CAN_USE_16BIT #elif SMC_CAN_USE_16BIT
#define SMC_PUSH_DATA(p, l) SMC_outsw( 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 ) #define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT #elif SMC_CAN_USE_8BIT
#define SMC_PUSH_DATA(p, l) SMC_outsb( 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 ) #define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif #endif
#if ! SMC_CAN_USE_16BIT #if ! SMC_CAN_USE_16BIT
...@@ -941,6 +961,51 @@ static const char * chip_ids[ 16 ] = { ...@@ -941,6 +961,51 @@ static const char * chip_ids[ 16 ] = {
}) })
#endif #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) #if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE # define SMC_INTERRUPT_PREAMBLE
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment