aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/can/mscan/mscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/mscan/mscan.c')
-rw-r--r--drivers/net/can/mscan/mscan.c125
1 files changed, 81 insertions, 44 deletions
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 74cd880c7e0..e0c9be5e2ab 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -16,8 +16,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
@@ -34,7 +33,7 @@
#include "mscan.h"
-static struct can_bittiming_const mscan_bittiming_const = {
+static const struct can_bittiming_const mscan_bittiming_const = {
.name = "mscan",
.tseg1_min = 4,
.tseg1_max = 16,
@@ -62,7 +61,7 @@ static enum can_state state_map[] = {
static int mscan_set_mode(struct net_device *dev, u8 mode)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int ret = 0;
int i;
u8 canctl1;
@@ -95,9 +94,9 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
* any, at once.
*/
if (i >= MSCAN_SET_MODE_RETRIES)
- dev_dbg(dev->dev.parent,
- "device failed to enter sleep mode. "
- "We proceed anyhow.\n");
+ netdev_dbg(dev,
+ "device failed to enter sleep mode. "
+ "We proceed anyhow.\n");
else
priv->can.state = CAN_STATE_SLEEPING;
}
@@ -138,7 +137,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
static int mscan_start(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 canrflg;
int err;
@@ -178,7 +177,7 @@ static int mscan_restart(struct net_device *dev)
struct mscan_priv *priv = netdev_priv(dev);
if (priv->type == MSCAN_TYPE_MPC5121) {
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
@@ -199,7 +198,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct can_frame *frame = (struct can_frame *)skb->data;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
int i, rtr, buf_id;
u32 can_id;
@@ -213,7 +212,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
switch (hweight8(i)) {
case 0:
netif_stop_queue(dev);
- dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n");
+ netdev_err(dev, "Tx Ring full when queue awake!\n");
return NETDEV_TX_BUSY;
case 1:
/*
@@ -246,7 +245,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
out_be16(&regs->tx.idr3_2, can_id);
can_id >>= 16;
- /* EFF_FLAGS are inbetween the IDs :( */
+ /* EFF_FLAGS are between the IDs :( */
can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0)
| MSCAN_EFF_FLAGS;
} else {
@@ -261,11 +260,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
void __iomem *data = &regs->tx.dsr1_0;
u16 *payload = (u16 *)frame->data;
- /* It is safe to write into dsr[dlc+1] */
- for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
+ for (i = 0; i < frame->can_dlc / 2; i++) {
out_be16(data, *payload++);
data += 2 + _MSCAN_RESERVED_DSR_SIZE;
}
+ /* write remaining byte if necessary */
+ if (frame->can_dlc & 1)
+ out_8(data, frame->data[frame->can_dlc - 1]);
}
out_8(&regs->tx.dlr, frame->can_dlc);
@@ -305,7 +306,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg)
static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u32 can_id;
int i;
@@ -330,10 +331,13 @@ static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame)
void __iomem *data = &regs->rx.dsr1_0;
u16 *payload = (u16 *)frame->data;
- for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
+ for (i = 0; i < frame->can_dlc / 2; i++) {
*payload++ = in_be16(data);
data += 2 + _MSCAN_RESERVED_DSR_SIZE;
}
+ /* read remaining byte if necessary */
+ if (frame->can_dlc & 1)
+ frame->data[frame->can_dlc - 1] = in_8(data);
}
out_8(&regs->canrflg, MSCAN_RXF);
@@ -343,11 +347,11 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
u8 canrflg)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
enum can_state old_state;
- dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg);
+ netdev_dbg(dev, "error interrupt (canrflg=%#x)\n", canrflg);
frame->can_id = CAN_ERR_FLAG;
if (canrflg & MSCAN_OVRIF) {
@@ -406,7 +410,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
{
struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
struct net_device *dev = napi->dev;
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
int npackets = 0;
int ret = 1;
@@ -422,7 +426,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
skb = alloc_can_skb(dev, &frame);
if (!skb) {
if (printk_ratelimit())
- dev_notice(dev->dev.parent, "packet dropped\n");
+ netdev_notice(dev, "packet dropped\n");
stats->rx_dropped++;
out_8(&regs->canrflg, canrflg);
continue;
@@ -453,7 +457,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct net_device_stats *stats = &dev->stats;
u8 cantier, cantflg, canrflg;
irqreturn_t ret = IRQ_NONE;
@@ -512,12 +516,8 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
{
- struct mscan_priv *priv = netdev_priv(dev);
int ret = 0;
- if (!priv->open_time)
- return -EINVAL;
-
switch (mode) {
case CAN_MODE_START:
ret = mscan_restart(dev);
@@ -537,7 +537,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
static int mscan_do_set_bittiming(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
struct can_bittiming *bt = &priv->can.bittiming;
u8 btr0, btr1;
@@ -546,8 +546,7 @@ static int mscan_do_set_bittiming(struct net_device *dev)
BTR1_SET_TSEG2(bt->phase_seg2) |
BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES));
- dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
- btr0, btr1);
+ netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
out_8(&regs->canbtr0, btr0);
out_8(&regs->canbtr1, btr1);
@@ -555,28 +554,52 @@ static int mscan_do_set_bittiming(struct net_device *dev)
return 0;
}
+static int mscan_get_berr_counter(const struct net_device *dev,
+ struct can_berr_counter *bec)
+{
+ struct mscan_priv *priv = netdev_priv(dev);
+ struct mscan_regs __iomem *regs = priv->reg_base;
+
+ bec->txerr = in_8(&regs->cantxerr);
+ bec->rxerr = in_8(&regs->canrxerr);
+
+ return 0;
+}
+
static int mscan_open(struct net_device *dev)
{
int ret;
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
+
+ if (priv->clk_ipg) {
+ ret = clk_prepare_enable(priv->clk_ipg);
+ if (ret)
+ goto exit_retcode;
+ }
+ if (priv->clk_can) {
+ ret = clk_prepare_enable(priv->clk_can);
+ if (ret)
+ goto exit_dis_ipg_clock;
+ }
/* common open */
ret = open_candev(dev);
if (ret)
- return ret;
+ goto exit_dis_can_clock;
napi_enable(&priv->napi);
ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);
if (ret < 0) {
- dev_err(dev->dev.parent, "failed to attach interrupt\n");
+ netdev_err(dev, "failed to attach interrupt\n");
goto exit_napi_disable;
}
- priv->open_time = jiffies;
-
- clrbits8(&regs->canctl1, MSCAN_LISTEN);
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ setbits8(&regs->canctl1, MSCAN_LISTEN);
+ else
+ clrbits8(&regs->canctl1, MSCAN_LISTEN);
ret = mscan_start(dev);
if (ret)
@@ -587,18 +610,24 @@ static int mscan_open(struct net_device *dev)
return 0;
exit_free_irq:
- priv->open_time = 0;
free_irq(dev->irq, dev);
exit_napi_disable:
napi_disable(&priv->napi);
close_candev(dev);
+exit_dis_can_clock:
+ if (priv->clk_can)
+ clk_disable_unprepare(priv->clk_can);
+exit_dis_ipg_clock:
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+exit_retcode:
return ret;
}
static int mscan_close(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
netif_stop_queue(dev);
napi_disable(&priv->napi);
@@ -608,21 +637,26 @@ static int mscan_close(struct net_device *dev)
mscan_set_mode(dev, MSCAN_INIT_MODE);
close_candev(dev);
free_irq(dev->irq, dev);
- priv->open_time = 0;
+
+ if (priv->clk_can)
+ clk_disable_unprepare(priv->clk_can);
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
return 0;
}
static const struct net_device_ops mscan_netdev_ops = {
- .ndo_open = mscan_open,
- .ndo_stop = mscan_close,
- .ndo_start_xmit = mscan_start_xmit,
+ .ndo_open = mscan_open,
+ .ndo_stop = mscan_close,
+ .ndo_start_xmit = mscan_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
};
int register_mscandev(struct net_device *dev, int mscan_clksrc)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
u8 ctl1;
ctl1 = in_8(&regs->canctl1);
@@ -631,8 +665,10 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)
else
ctl1 &= ~MSCAN_CLKSRC;
- if (priv->type == MSCAN_TYPE_MPC5121)
+ if (priv->type == MSCAN_TYPE_MPC5121) {
+ priv->can.do_get_berr_counter = mscan_get_berr_counter;
ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
+ }
ctl1 |= MSCAN_CANE;
out_8(&regs->canctl1, ctl1);
@@ -659,7 +695,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc)
void unregister_mscandev(struct net_device *dev)
{
struct mscan_priv *priv = netdev_priv(dev);
- struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
+ struct mscan_regs __iomem *regs = priv->reg_base;
mscan_set_mode(dev, MSCAN_INIT_MODE);
clrbits8(&regs->canctl1, MSCAN_CANE);
unregister_candev(dev);
@@ -685,7 +721,8 @@ struct net_device *alloc_mscandev(void)
priv->can.bittiming_const = &mscan_bittiming_const;
priv->can.do_set_bittiming = mscan_do_set_bittiming;
priv->can.do_set_mode = mscan_do_set_mode;
- priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+ CAN_CTRLMODE_LISTENONLY;
for (i = 0; i < TX_QUEUE_SIZE; i++) {
priv->tx_queue[i].id = i;