Commit 5884f98b authored by François Romieu's avatar François Romieu Committed by Linus Torvalds

[PATCH] 2.4.8 - dscc4 update 2/13

- dscc4_patch_register() turns into scc_patchl() and should now avoid an
  hardware bug quoted in errata sheet;
- dscc4_init_registers() interface changes as any caller doesn't really need
  to poke into dscc4_dev_priv internal;
- scc_{writel/readl}() are added to access some buggy behaving registers;
- {read/write}l conversion to the previous functions
- dscc4_do_tx() sneaks, sorry. Belongs to HOLD -> LxDA changes.
parent 279b570d
...@@ -356,14 +356,50 @@ static inline struct dscc4_dev_priv *dscc4_priv(struct net_device *dev) ...@@ -356,14 +356,50 @@ static inline struct dscc4_dev_priv *dscc4_priv(struct net_device *dev)
return list_entry(dev, struct dscc4_dev_priv, hdlc.netdev); return list_entry(dev, struct dscc4_dev_priv, hdlc.netdev);
} }
static inline void dscc4_patch_register(u32 ioaddr, u32 mask, u32 value) static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv,
struct net_device *dev, int offset)
{ {
u32 state; u32 state;
state = readl(ioaddr); /* Cf scc_writel for concern regarding thread-safety */
state = dpriv->scc_regs[offset];
state &= ~mask; state &= ~mask;
state |= value; state |= value;
writel(state, ioaddr); dpriv->scc_regs[offset] = state;
writel(state, dev->base_addr + SCC_REG_START(dpriv) + offset);
}
static void scc_writel(u32 bits, struct dscc4_dev_priv *dpriv,
struct net_device *dev, int offset)
{
/*
* Thread-UNsafe.
* As of 2002/02/16, there are no thread racing for access.
*/
dpriv->scc_regs[offset] = bits;
writel(bits, dev->base_addr + SCC_REG_START(dpriv) + offset);
}
static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset)
{
return dpriv->scc_regs[offset];
}
static u32 scc_readl_star(struct dscc4_dev_priv *dpriv, struct net_device *dev)
{
/* Cf errata DS5 p.4 */
readl(dev->base_addr + SCC_REG_START(dpriv) + STAR);
return readl(dev->base_addr + SCC_REG_START(dpriv) + STAR);
}
static inline void dscc4_do_tx(struct dscc4_dev_priv *dpriv,
struct net_device *dev)
{
dpriv->ltda = dpriv->tx_fd_dma +
(dpriv->tx_current%TX_RING_SIZE)*sizeof(struct TxFD);
writel(dpriv->ltda, dev->base_addr + CH0LTDA + dpriv->dev_id*4);
/* Flush posted writes *NOW* */
readl(dev->base_addr + CH0LTDA + dpriv->dev_id*4);
} }
int state_check(u32 state, struct dscc4_dev_priv *dpriv, int state_check(u32 state, struct dscc4_dev_priv *dpriv,
...@@ -686,28 +722,28 @@ static int __init dscc4_init_one (struct pci_dev *pdev, ...@@ -686,28 +722,28 @@ static int __init dscc4_init_one (struct pci_dev *pdev,
* Let's hope the default values are decent enough to protect my * Let's hope the default values are decent enough to protect my
* feet from the user's gun - Ueimor * feet from the user's gun - Ueimor
*/ */
static void dscc4_init_registers(u32 base_addr, int dev_id) static void dscc4_init_registers(struct dscc4_dev_priv *dpriv,
struct net_device *dev)
{ {
u32 ioaddr = base_addr + SCC_REG_START(dpriv); scc_writel(0x80001000, dpriv, dev, CCR0);
writel(0x80001000, ioaddr + CCR0); scc_writel(LengthCheck | (HDLC_MAX_MRU >> 5), dpriv, dev, RLCR);
writel(LengthCheck | (HDLC_MAX_MRU >> 5), ioaddr + RLCR); /* Shared flags transmission disabled - cf errata DS5 p.11 */
/* Carrier detect disabled - cf errata p.14 */
scc_writel(0x021c8000, dpriv, dev, CCR1);
/* no address recognition/crc-CCITT/cts enabled */ /* crc not forwarded - Cf errata DS5 p.11 */
writel(0x021c8000, ioaddr + CCR1); scc_writel(0x00050008 & ~RxActivate, dpriv, dev, CCR2);
/* crc not forwarded */
writel(0x00050008 & ~RxActivate, ioaddr + CCR2);
// crc forwarded // crc forwarded
//writel(0x00250008 & ~RxActivate, ioaddr + CCR2); //scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
/* Don't mask RDO. Ever. */ /* Don't mask RDO. Ever. */
#ifdef DSCC4_POLLING #ifdef DSCC4_POLLING
writel(0xfffeef7f, ioaddr + IMR); /* Interrupt mask */ scc_writel(0xfffeef7f, dpriv, dev, IMR); /* Interrupt mask */
#else #else
//writel(0xfffaef7f, ioaddr + IMR); /* Interrupt mask */ //scc_writel(0xfffaef7f, dpriv, dev, IMR); /* Interrupt mask */
writel(0xfffaef7e, ioaddr + IMR); /* Interrupt mask */ scc_writel(0xfffaef7e, dpriv, dev, IMR); /* Interrupt mask */
#endif #endif
} }
...@@ -760,7 +796,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) ...@@ -760,7 +796,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
} }
hdlc->proto = IF_PROTO_HDLC; hdlc->proto = IF_PROTO_HDLC;
SET_MODULE_OWNER(d); SET_MODULE_OWNER(d);
dscc4_init_registers(ioaddr, dpriv); dscc4_init_registers(dpriv, d);
dpriv->parity = PARITY_CRC16_PR0_CCITT; dpriv->parity = PARITY_CRC16_PR0_CCITT;
dpriv->encoding = ENCODING_NRZ; dpriv->encoding = ENCODING_NRZ;
} }
...@@ -890,7 +926,7 @@ static int dscc4_open(struct net_device *dev) ...@@ -890,7 +926,7 @@ static int dscc4_open(struct net_device *dev)
} }
/* Posted write is flushed in the busy-waiting loop */ /* Posted write is flushed in the busy-waiting loop */
writel(TxSccRes | RxSccRes, ioaddr + CMDR); scc_writel(TxSccRes | RxSccRes, dpriv, dev, CMDR);
if (dscc4_wait_ack_cec(ioaddr, dev, "Cec")) if (dscc4_wait_ack_cec(ioaddr, dev, "Cec"))
goto err_free_ring; goto err_free_ring;
...@@ -1063,7 +1099,7 @@ static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state) ...@@ -1063,7 +1099,7 @@ static int dscc4_set_clock(struct net_device *dev, u32 *bps, u32 *state)
*/ */
brr = 0; brr = 0;
} }
writel(brr, dev->base_addr + BRR + SCC_REG_START(dpriv)); scc_writel(brr, dpriv, dev, BRR);
return 0; return 0;
} }
...@@ -1136,11 +1172,9 @@ static int dscc4_clock_setting(struct net_device *dev) ...@@ -1136,11 +1172,9 @@ static int dscc4_clock_setting(struct net_device *dev)
struct dscc4_dev_priv *dpriv = dscc4_priv(dev); struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
sync_serial_settings *settings = &dpriv->settings; sync_serial_settings *settings = &dpriv->settings;
u32 bps, state; u32 bps, state;
u32 ioaddr;
bps = settings->clock_rate; bps = settings->clock_rate;
ioaddr = dev->base_addr + CCR0 + SCC_REG_START(dpriv); state = scc_readl(dpriv, CCR0);
state = readl(ioaddr);
if(dscc4_set_clock(dev, &bps, &state) < 0) if(dscc4_set_clock(dev, &bps, &state) < 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (bps) { /* DCE */ if (bps) { /* DCE */
...@@ -1154,7 +1188,7 @@ static int dscc4_clock_setting(struct net_device *dev) ...@@ -1154,7 +1188,7 @@ static int dscc4_clock_setting(struct net_device *dev)
state = 0x80001000; state = 0x80001000;
printk(KERN_DEBUG "%s: external RxClk (DTE)\n", dev->name); printk(KERN_DEBUG "%s: external RxClk (DTE)\n", dev->name);
} }
writel(state, ioaddr); scc_writel(state, dpriv, dev, CCR0);
return 0; return 0;
} }
...@@ -1172,12 +1206,9 @@ static int dscc4_encoding_setting(struct net_device *dev) ...@@ -1172,12 +1206,9 @@ static int dscc4_encoding_setting(struct net_device *dev)
int i, ret = 0; int i, ret = 0;
i = dscc4_match(encoding, dpriv->encoding); i = dscc4_match(encoding, dpriv->encoding);
if (i >= 0) { if (i >= 0)
u32 ioaddr; scc_patchl(EncodingMask, encoding[i].bits, dpriv, dev, CCR0);
else
ioaddr = dev->base_addr + CCR0 + SCC_REG_START(dpriv);
dscc4_patch_register(ioaddr, EncodingMask, encoding[i].bits);
} else
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
return ret; return ret;
} }
...@@ -1186,10 +1217,9 @@ static int dscc4_loopback_setting(struct net_device *dev) ...@@ -1186,10 +1217,9 @@ static int dscc4_loopback_setting(struct net_device *dev)
{ {
struct dscc4_dev_priv *dpriv = dscc4_priv(dev); struct dscc4_dev_priv *dpriv = dscc4_priv(dev);
sync_serial_settings *settings = &dpriv->settings; sync_serial_settings *settings = &dpriv->settings;
u32 ioaddr, state; u32 state;
ioaddr = dev->base_addr + CCR1 + SCC_REG_START(dpriv); state = scc_readl(dpriv, CCR1);
state = readl(ioaddr);
if (settings->loopback) { if (settings->loopback) {
printk(KERN_DEBUG "%s: loopback\n", dev->name); printk(KERN_DEBUG "%s: loopback\n", dev->name);
state |= 0x00000100; state |= 0x00000100;
...@@ -1197,7 +1227,7 @@ static int dscc4_loopback_setting(struct net_device *dev) ...@@ -1197,7 +1227,7 @@ static int dscc4_loopback_setting(struct net_device *dev)
printk(KERN_DEBUG "%s: normal\n", dev->name); printk(KERN_DEBUG "%s: normal\n", dev->name);
state &= ~0x00000100; state &= ~0x00000100;
} }
writel(state, ioaddr); scc_writel(state, dpriv, dev, CCR1);
return 0; return 0;
} }
...@@ -1213,12 +1243,9 @@ static int dscc4_crc_setting(struct net_device *dev) ...@@ -1213,12 +1243,9 @@ static int dscc4_crc_setting(struct net_device *dev)
int i, ret = 0; int i, ret = 0;
i = dscc4_match(crc, dpriv->parity); i = dscc4_match(crc, dpriv->parity);
if (i >= 0) { if (i >= 0)
u32 ioaddr; scc_patchl(CrcMask, crc[i].bits, dpriv, dev, CCR1);
else
ioaddr = dev->base_addr + CCR1 + SCC_REG_START(dpriv);
dscc4_patch_register(ioaddr, CrcMask, crc[i].bits);
} else
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
return ret; return ret;
} }
...@@ -1424,7 +1451,7 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, struct dscc4_dev_p ...@@ -1424,7 +1451,7 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, struct dscc4_dev_p
dpriv->flags &= ~NeedIDR; dpriv->flags &= ~NeedIDR;
mb(); mb();
/* Activate receiver and misc */ /* Activate receiver and misc */
writel(0x08050008, scc_offset + CCR2); scc_writel(0x08050008, dpriv, dev, CCR2);
} }
err_xpr: err_xpr:
if (!(state &= ~Xpr)) if (!(state &= ~Xpr))
...@@ -1561,7 +1588,7 @@ static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv, ...@@ -1561,7 +1588,7 @@ static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
* ORed with TxSccRes, one sees the CFG ack (for * ORed with TxSccRes, one sees the CFG ack (for
* the TX part only). * the TX part only).
*/ */
writel(RxSccRes, scc_offset + CMDR); scc_writel(RxSccRes, dpriv, dev, CMDR);
dpriv->flags |= RdoSet; dpriv->flags |= RdoSet;
/* /*
......
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