Modified: trunk/drivers/net/can/bfin_can.c (7971 => 7972)
--- trunk/drivers/net/can/bfin_can.c 2009-12-11 02:44:28 UTC (rev 7971)
+++ trunk/drivers/net/can/bfin_can.c 2009-12-11 04:15:27 UTC (rev 7972)
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
@@ -31,11 +30,11 @@
/*
* transmit and receive channels
*/
-#define TRANSMIT_CHL 24
-#define RECEIVE_STD_CHL 0
-#define RECEIVE_EXT_CHL 4
-#define RECEIVE_RTR_CHL 8
-#define RECEIVE_EXT_RTR_CHL 12
+#define TRANSMIT_CHL 24
+#define RECEIVE_STD_CHL 0
+#define RECEIVE_EXT_CHL 4
+#define RECEIVE_RTR_CHL 8
+#define RECEIVE_EXT_RTR_CHL 12
#define MAX_CHL_NUMBER 32
/*
@@ -74,41 +73,41 @@
u16 dummy3;
u16 mbim1; /* offset 0x28 */
u16 rsv2[11];
- u16 mc2; /* offset 0x40 */
+ u16 mc2; /* offset 0x40 */
u16 dummy4;
- u16 md2; /* offset 0x44 */
+ u16 md2; /* offset 0x44 */
u16 dummy5;
- u16 trs2; /* offset 0x48 */
+ u16 trs2; /* offset 0x48 */
u16 rsv3[11];
- u16 mbtif2; /* offset 0x60 */
+ u16 mbtif2; /* offset 0x60 */
u16 dummy6;
- u16 mbrif2; /* offset 0x64 */
+ u16 mbrif2; /* offset 0x64 */
u16 dummy7;
- u16 mbim2; /* offset 0x68 */
+ u16 mbim2; /* offset 0x68 */
u16 rsv4[11];
- u16 clk; /* offset 0x80 */
+ u16 clk; /* offset 0x80 */
u16 dummy8;
- u16 timing; /* offset 0x84 */
+ u16 timing; /* offset 0x84 */
u16 rsv5[3];
- u16 status; /* offset 0x8c */
+ u16 status; /* offset 0x8c */
u16 dummy9;
- u16 cec; /* offset 0x90 */
+ u16 cec; /* offset 0x90 */
u16 dummy10;
- u16 gis; /* offset 0x94 */
+ u16 gis; /* offset 0x94 */
u16 dummy11;
- u16 gim; /* offset 0x98 */
+ u16 gim; /* offset 0x98 */
u16 rsv6[3];
- u16 ctrl; /* offset 0xa0 */
+ u16 ctrl; /* offset 0xa0 */
u16 dummy12;
- u16 intr; /* offset 0xa4 */
+ u16 intr; /* offset 0xa4 */
u16 rsv7[7];
- u16 esr; /* offset 0xb4 */
+ u16 esr; /* offset 0xb4 */
u16 rsv8[37];
/*
* channel(mailbox) mask and message registers
*/
- struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */
+ struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */
struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
};
@@ -135,7 +134,8 @@
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
- /* Although the BRP field can be set to any value, it is recommended
+ /*
+ * Although the BRP field can be set to any value, it is recommended
* that the value be greater than or equal to 4, as restrictions
* apply to the bit timing configuration when BRP is less than 4.
*/
@@ -144,97 +144,10 @@
.brp_inc = 1,
};
-/*
- * inline functions to read/write ID, data length and payload of CAN frame
- */
-static inline void bfin_can_write_oid(struct bfin_can_priv *priv, int channel, canid_t id)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- writew((id << 2) + AME, ®->chl[channel].id1);
-}
-
-static inline void bfin_can_write_oid_rtr(struct bfin_can_priv *priv, int channel, canid_t id)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- writew((id << 2) + AME + RTR, ®->chl[channel].id1);
-}
-
-static inline canid_t bfin_can_read_oid(struct bfin_can_priv *priv, int channel)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- return (readw(®->chl[channel].id1) & 0x1ffc) >> 2;
-}
-
-static inline void bfin_can_write_xoid(struct bfin_can_priv *priv, int channel, canid_t id)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- writew(id, ®->chl[channel].id0);
- writew(((id & 0x1FFF0000) >> 16) + IDE + AME, ®->chl[channel].id1);
-}
-
-static inline void bfin_can_write_xoid_rtr(struct bfin_can_priv *priv, int channel, canid_t id)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- writew(id, ®->chl[channel].id0);
- writew(((id & 0x1FFF0000) >> 16) + IDE + AME + RTR, ®->chl[channel].id1);
-}
-
-static inline canid_t bfin_can_read_xoid(struct bfin_can_priv *priv, int channel)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- return ((readw(®->chl[channel].id1) & 0x1FFF) << 16) + readw(®->chl[channel].id0);
-}
-
-static inline void bfin_can_write_dlc(struct bfin_can_priv *priv, int channel, u8 dlc)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- writew(dlc, ®->chl[channel].dlc);
-}
-
-static inline u8 bfin_can_read_dlc(struct bfin_can_priv *priv, int channel)
-{
- struct bfin_can_regs *reg = priv->membase;
-
- return readw(®->chl[channel].dlc);
-}
-
-static inline void bfin_can_write_data(struct bfin_can_priv *priv, int channel, u8 *data, u8 dlc)
-{
- struct bfin_can_regs *reg = priv->membase;
- int i;
- u16 val;
-
- for (i = 0; i < 8; i += 2) {
- val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
- ((6 - i) < dlc ? (data[6 - i] << 8) : 0);
- writew(val, ®->chl[channel].data[i]);
- }
-}
-
-static inline void bfin_can_read_data(struct bfin_can_priv *priv, int channel, u8 *data, u8 dlc)
-{
- struct bfin_can_regs *reg = priv->membase;
- int i;
- u16 val;
-
- for (i = 0; i < 8; i += 2) {
- val = readw(®->chl[channel].data[i]);
- data[7 - i] = (7 - i) < dlc ? val : 0;
- data[6 - i] = (6 - i) < dlc ? (val >> 8) : 0;
- }
-}
-
static int bfin_can_set_bittiming(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
struct can_bittiming *bt = &priv->can.bittiming;
u16 clk, timing;
@@ -243,7 +156,8 @@
((bt->phase_seg2 - 1) << 4);
/*
- * If the SAM bit is set, the input signal is oversampled three times at the SCLK rate.
+ * If the SAM bit is set, the input signal is oversampled three times
+ * at the SCLK rate.
*/
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
@@ -251,14 +165,16 @@
writew(clk, ®->clk);
writew(timing, ®->timing);
- dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing);
+ dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
+ clk, timing);
+
return 0;
}
static void bfin_can_set_reset_mode(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
int i;
@@ -275,7 +191,8 @@
while (!(readw(®->ctrl) & CCA)) {
udelay(10);
if (--timeout == 0) {
- dev_err(dev->dev.parent, "fail to enter configuration mode\n");
+ dev_err(dev->dev.parent,
+ "fail to enter configuration mode\n");
BUG();
}
}
@@ -320,7 +237,7 @@
static void bfin_can_set_normal_mode(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
/*
@@ -331,7 +248,8 @@
while (readw(®->status) & CCA) {
udelay(10);
if (--timeout == 0) {
- dev_err(dev->dev.parent, "fail to leave configuration mode\n");
+ dev_err(dev->dev.parent,
+ "fail to leave configuration mode\n");
BUG();
}
}
@@ -365,7 +283,7 @@
{
struct bfin_can_priv *priv = netdev_priv(dev);
- /* leave reset mode */
+ /* enter reset mode */
if (priv->can.state != CAN_STATE_STOPPED)
bfin_can_set_reset_mode(dev);
@@ -392,32 +310,43 @@
static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
struct can_frame *cf = (struct can_frame *)skb->data;
- u8 dlc;
- canid_t id;
+ u8 dlc = cf->can_dlc;
+ canid_t id = cf->can_id;
+ u8 *data = ""
+ u16 val;
+ int i;
netif_stop_queue(dev);
- dlc = cf->can_dlc;
- id = cf->can_id;
-
- /* fill id and data length code */
+ /* fill id */
if (id & CAN_EFF_FLAG) {
+ writew(id, ®->chl[TRANSMIT_CHL].id0);
if (id & CAN_RTR_FLAG)
- bfin_can_write_xoid_rtr(priv, TRANSMIT_CHL, id);
+ writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
+ ®->chl[TRANSMIT_CHL].id1);
else
- bfin_can_write_xoid(priv, TRANSMIT_CHL, id);
+ writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
+ ®->chl[TRANSMIT_CHL].id1);
+
} else {
if (id & CAN_RTR_FLAG)
- bfin_can_write_oid_rtr(priv, TRANSMIT_CHL, id);
+ writew((id << 2) | AME | RTR,
+ ®->chl[TRANSMIT_CHL].id1);
else
- bfin_can_write_oid(priv, TRANSMIT_CHL, id);
+ writew((id << 2) | AME, ®->chl[TRANSMIT_CHL].id1);
}
- bfin_can_write_data(priv, TRANSMIT_CHL, cf->data, dlc);
+ /* fill payload */
+ for (i = 0; i < 8; i += 2) {
+ val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
+ ((6 - i) < dlc ? (data[6 - i] << 8) : 0);
+ writew(val, ®->chl[TRANSMIT_CHL].data[i]);
+ }
- bfin_can_write_dlc(priv, TRANSMIT_CHL, dlc);
+ /* fill data length code */
+ writew(dlc, ®->chl[TRANSMIT_CHL].dlc);
dev->trans_start = jiffies;
@@ -425,6 +354,7 @@
/* set transmit request */
writew(BIT(TRANSMIT_CHL - 16), ®->trs2);
+
return 0;
}
@@ -432,47 +362,53 @@
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
struct can_frame *cf;
struct sk_buff *skb;
- canid_t id;
- u8 dlc;
int obj;
+ int i;
+ u16 val;
skb = alloc_can_skb(dev, &cf);
if (skb == NULL)
return;
- /* get id and data length code */
+ /* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
- id = bfin_can_read_xoid(priv, RECEIVE_EXT_CHL);
- id |= CAN_EFF_FLAG;
+ cf->can_id = ((readw(®->chl[RECEIVE_EXT_CHL].id1) & 0x1FFF)
+ << 16) + readw(®->chl[RECEIVE_EXT_CHL].id0);
+ cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
- id = bfin_can_read_oid(priv, RECEIVE_STD_CHL);
+ cf->can_id = (readw(®->chl[RECEIVE_STD_CHL].id1) & 0x1ffc)
+ >> 2;
obj = RECEIVE_STD_CHL;
}
if (readw(®->chl[obj].id1) & RTR)
- id |= CAN_RTR_FLAG;
- dlc = bfin_can_read_dlc(priv, obj);
+ cf->can_id |= CAN_RTR_FLAG;
- cf->can_id = id;
- cf->can_dlc = dlc;
+ /* get data length code */
+ cf->can_dlc = readw(®->chl[obj].dlc);
- bfin_can_read_data(priv, obj, cf->data, dlc);
+ /* get payload */
+ for (i = 0; i < 8; i += 2) {
+ val = readw(®->chl[obj].data[i]);
+ cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
+ cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
+ }
netif_rx(skb);
stats->rx_packets++;
- stats->rx_bytes += dlc;
+ stats->rx_bytes += cf->can_dlc;
}
static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
{
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
@@ -493,7 +429,6 @@
if (isrc & BOIS) {
dev_dbg(dev->dev.parent, "bus-off mode interrupt\n");
-
state = CAN_STATE_BUS_OFF;
cf->can_id |= CAN_ERR_BUSOFF;
can_bus_off(dev);
@@ -506,7 +441,8 @@
}
if ((isrc & EWTIS) || (isrc & EWRIS)) {
- dev_dbg(dev->dev.parent, "Error Warning Transmit/Receive Interrupt\n");
+ dev_dbg(dev->dev.parent,
+ "Error Warning Transmit/Receive Interrupt\n");
state = CAN_STATE_ERROR_WARNING;
}
@@ -515,6 +451,7 @@
u16 cec = readw(®->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
+
cf->can_id |= CAN_ERR_CRTL;
if (state == CAN_STATE_ERROR_WARNING) {
priv->can.can_stats.error_warning++;
@@ -558,7 +495,7 @@
{
struct net_device *dev = dev_id;
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
@@ -566,7 +503,7 @@
/* transmission complete interrupt */
writew(0xFFFF, ®->mbtif2);
stats->tx_packets++;
- stats->tx_bytes += bfin_can_read_dlc(priv, TRANSMIT_CHL);
+ stats->tx_bytes += readw(®->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
} else if ((irq == priv->rx_irq) && readw(®->mbrif1)) {
@@ -580,14 +517,16 @@
status = readw(®->esr);
writew(0x7FF, ®->gis);
bfin_can_err(dev, isrc, status);
- } else
+ } else {
return IRQ_NONE;
+ }
return IRQ_HANDLED;
}
static int bfin_can_open(struct net_device *dev)
{
+ struct bfin_can_priv *priv = netdev_priv(dev);
int err;
/* set chip into reset mode */
@@ -596,23 +535,51 @@
/* common open */
err = open_candev(dev);
if (err)
- return err;
+ goto exit_open;
- /* init and start chi */
+ /* register interrupt handler */
+ err = request_irq(priv->rx_irq, &bfin_can_interrupt, 0,
+ "bfin-can-rx", dev);
+ if (err)
+ goto exit_rx_irq;
+ err = request_irq(priv->tx_irq, &bfin_can_interrupt, 0,
+ "bfin-can-tx", dev);
+ if (err)
+ goto exit_tx_irq;
+ err = request_irq(priv->err_irq, &bfin_can_interrupt, 0,
+ "bfin-can-err", dev);
+ if (err)
+ goto exit_err_irq;
+
bfin_can_start(dev);
netif_start_queue(dev);
return 0;
+
+exit_err_irq:
+ free_irq(priv->tx_irq, dev);
+exit_tx_irq:
+ free_irq(priv->rx_irq, dev);
+exit_rx_irq:
+ close_candev(dev);
+exit_open:
+ return err;
}
static int bfin_can_close(struct net_device *dev)
{
+ struct bfin_can_priv *priv = netdev_priv(dev);
+
netif_stop_queue(dev);
bfin_can_set_reset_mode(dev);
close_candev(dev);
+ free_irq(priv->rx_irq, dev);
+ free_irq(priv->tx_irq, dev);
+ free_irq(priv->err_irq, dev);
+
return 0;
}
@@ -682,20 +649,6 @@
goto exit_peri_pin_free;
}
- /* register interrupt handler */
- err = request_irq(rx_irq->start, &bfin_can_interrupt, 0,
- "bfin-can-rx", (void *)dev);
- if (err)
- goto exit_candev_free;
- err = request_irq(tx_irq->start, &bfin_can_interrupt, 0,
- "bfin-can-tx", (void *)dev);
- if (err)
- goto exit_rx_irq_free;
- err = request_irq(err_irq->start, &bfin_can_interrupt, 0,
- "bfin-can-err", (void *)dev);
- if (err)
- goto exit_tx_irq_free;
-
priv = netdev_priv(dev);
priv->membase = (void __iomem *)res_mem->start;
priv->rx_irq = rx_irq->start;
@@ -715,20 +668,16 @@
err = register_candev(dev);
if (err) {
dev_err(&pdev->dev, "registering failed (err=%d)\n", err);
- goto exit_err_irq_free;
+ goto exit_candev_free;
}
- dev_info(&pdev->dev, "%s device registered (reg_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n",
- DRV_NAME, (void *)priv->membase, priv->rx_irq, priv->tx_irq, priv->err_irq,
- priv->can.clock.freq);
+ dev_info(&pdev->dev,
+ "%s device registered"
+ "(®_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n",
+ DRV_NAME, (void *)priv->membase, priv->rx_irq,
+ priv->tx_irq, priv->err_irq, priv->can.clock.freq);
return 0;
-exit_err_irq_free:
- free_irq(err_irq->start, dev);
-exit_tx_irq_free:
- free_irq(tx_irq->start, dev);
-exit_rx_irq_free:
- free_irq(rx_irq->start, dev);
exit_candev_free:
free_candev(dev);
exit_peri_pin_free:
@@ -754,9 +703,6 @@
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
- free_irq(priv->rx_irq, dev);
- free_irq(priv->tx_irq, dev);
- free_irq(priv->err_irq, dev);
peripheral_free_list(priv->pin_list);
free_candev(dev);
@@ -768,7 +714,7 @@
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
if (netif_running(dev)) {
@@ -778,7 +724,8 @@
while (!(readw(®->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
- dev_err(dev->dev.parent, "fail to enter sleep mode\n");
+ dev_err(dev->dev.parent,
+ "fail to enter sleep mode\n");
BUG();
}
}
@@ -791,7 +738,7 @@
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
- struct bfin_can_regs *reg = priv->membase;
+ struct bfin_can_regs __iomem *reg = priv->membase;
if (netif_running(dev)) {
/* leave sleep mode */
@@ -821,14 +768,12 @@
{
return platform_driver_register(&bfin_can_driver);
}
-
module_init(bfin_can_init);
static void __exit bfin_can_exit(void)
{
platform_driver_unregister(&bfin_can_driver);
}
-
module_exit(bfin_can_exit);
MODULE_AUTHOR("Barry Song <[email protected]>");