Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -Naur a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
- --- a/drivers/net/can/mcp251x.c 2012-11-22 12:06:42.000000000 +0100
- +++ b/drivers/net/can/mcp251x.c 2014-01-02 14:50:05.984543370 +0100
- @@ -60,6 +60,7 @@
- #include <linux/can/core.h>
- #include <linux/can/dev.h>
- +#include <linux/can/led.h>
- #include <linux/can/platform/mcp251x.h>
- #include <linux/completion.h>
- #include <linux/delay.h>
- @@ -83,6 +84,11 @@
- #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
- #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94)
- #define INSTRUCTION_RESET 0xC0
- +#define RTS_TXB0 0x01
- +#define RTS_TXB1 0x02
- +#define RTS_TXB2 0x04
- +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07))
- +
- /* MPC251x registers */
- #define CANSTAT 0x0e
- @@ -214,7 +220,7 @@
- module_param(mcp251x_enable_dma, int, S_IRUGO);
- MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)");
- -static struct can_bittiming_const mcp251x_bittiming_const = {
- +static const struct can_bittiming_const mcp251x_bittiming_const = {
- .name = DEVICE_NAME,
- .tseg1_min = 3,
- .tseg1_max = 16,
- @@ -263,7 +269,7 @@
- #define MCP251X_IS(_model) \
- static inline int mcp251x_is_##_model(struct spi_device *spi) \
- { \
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \
- + struct mcp251x_priv *priv = spi_get_drvdata(spi); \
- return priv->model == CAN_MCP251X_MCP##_model; \
- }
- @@ -299,7 +305,7 @@
- */
- static int mcp251x_spi_trans(struct spi_device *spi, int len)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- struct spi_transfer t = {
- .tx_buf = priv->spi_tx_buf,
- .rx_buf = priv->spi_rx_buf,
- @@ -327,7 +333,7 @@
- static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- u8 val = 0;
- priv->spi_tx_buf[0] = INSTRUCTION_READ;
- @@ -342,7 +348,7 @@
- static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg,
- uint8_t *v1, uint8_t *v2)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- priv->spi_tx_buf[0] = INSTRUCTION_READ;
- priv->spi_tx_buf[1] = reg;
- @@ -355,7 +361,7 @@
- static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- priv->spi_tx_buf[0] = INSTRUCTION_WRITE;
- priv->spi_tx_buf[1] = reg;
- @@ -367,7 +373,7 @@
- static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
- u8 mask, uint8_t val)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY;
- priv->spi_tx_buf[1] = reg;
- @@ -380,7 +386,7 @@
- static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
- int len, int tx_buf_idx)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- if (mcp251x_is_2510(spi)) {
- int i;
- @@ -397,6 +403,7 @@
- static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
- int tx_buf_idx)
- {
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- u32 sid, eid, exide, rtr;
- u8 buf[SPI_TRANSFER_BUF_LEN];
- @@ -418,13 +425,16 @@
- buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
- memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
- mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
- - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
- +
- + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */
- + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
- + mcp251x_spi_trans(priv->spi, 1);
- }
- static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
- int buf_idx)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- if (mcp251x_is_2510(spi)) {
- int i, len;
- @@ -444,7 +454,7 @@
- static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- struct sk_buff *skb;
- struct can_frame *frame;
- u8 buf[SPI_TRANSFER_BUF_LEN];
- @@ -485,6 +495,9 @@
- priv->net->stats.rx_packets++;
- priv->net->stats.rx_bytes += frame->can_dlc;
- +
- + can_led_event(priv->net, CAN_LED_EVENT_RX);
- +
- netif_rx_ni(skb);
- }
- @@ -537,7 +550,7 @@
- static int mcp251x_set_normal_mode(struct spi_device *spi)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- unsigned long timeout;
- /* Enable interrupts */
- @@ -607,7 +620,7 @@
- static int mcp251x_hw_reset(struct spi_device *spi)
- {
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- int ret;
- unsigned long timeout;
- @@ -698,6 +711,8 @@
- mutex_unlock(&priv->mcp_lock);
- + can_led_event(net, CAN_LED_EVENT_STOP);
- +
- return 0;
- }
- @@ -712,8 +727,7 @@
- frame->data[1] = data1;
- netif_rx_ni(skb);
- } else {
- - dev_err(&net->dev,
- - "cannot allocate error skb\n");
- + netdev_err(net, "cannot allocate error skb\n");
- }
- }
- @@ -897,6 +911,7 @@
- if (intf & CANINTF_TX) {
- net->stats.tx_packets++;
- net->stats.tx_bytes += priv->tx_len - 1;
- + can_led_event(net, CAN_LED_EVENT_TX);
- if (priv->tx_len) {
- can_get_echo_skb(net, 0);
- priv->tx_len = 0;
- @@ -914,6 +929,7 @@
- struct mcp251x_priv *priv = netdev_priv(net);
- struct spi_device *spi = priv->spi;
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- + unsigned long flags;
- int ret;
- ret = open_candev(net);
- @@ -930,9 +946,14 @@
- priv->tx_skb = NULL;
- priv->tx_len = 0;
- + flags = IRQF_ONESHOT;
- + if (pdata->irq_flags)
- + flags |= pdata->irq_flags;
- + else
- + flags |= IRQF_TRIGGER_FALLING;
- +
- ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
- - pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
- - DEVICE_NAME, priv);
- + flags, DEVICE_NAME, priv);
- if (ret) {
- dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
- if (pdata->transceiver_enable)
- @@ -960,6 +981,9 @@
- mcp251x_open_clean(net);
- goto open_unlock;
- }
- +
- + can_led_event(net, CAN_LED_EVENT_OPEN);
- +
- netif_wake_queue(net);
- open_unlock:
- @@ -973,11 +997,11 @@
- .ndo_start_xmit = mcp251x_hard_start_xmit,
- };
- -static int __devinit mcp251x_can_probe(struct spi_device *spi)
- +static int mcp251x_can_probe(struct spi_device *spi)
- {
- struct net_device *net;
- struct mcp251x_priv *priv;
- - struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- + struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);
- int ret = -ENODEV;
- if (!pdata)
- @@ -1002,7 +1026,7 @@
- CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
- priv->model = spi_get_device_id(spi)->driver_data;
- priv->net = net;
- - dev_set_drvdata(&spi->dev, priv);
- + spi_set_drvdata(spi, priv);
- priv->spi = spi;
- mutex_init(&priv->mcp_lock);
- @@ -1021,8 +1045,7 @@
- GFP_DMA);
- if (priv->spi_tx_buf) {
- - priv->spi_rx_buf = (u8 *)(priv->spi_tx_buf +
- - (PAGE_SIZE / 2));
- + priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
- priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
- (PAGE_SIZE / 2));
- } else {
- @@ -1033,15 +1056,15 @@
- /* Allocate non-DMA buffers */
- if (!mcp251x_enable_dma) {
- - priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
- + priv->spi_tx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
- if (!priv->spi_tx_buf) {
- ret = -ENOMEM;
- - goto error_tx_buf;
- + goto error_probe;
- }
- - priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
- + priv->spi_rx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
- if (!priv->spi_rx_buf) {
- ret = -ENOMEM;
- - goto error_rx_buf;
- + goto error_probe;
- }
- }
- @@ -1055,13 +1078,18 @@
- SET_NETDEV_DEV(net, &spi->dev);
- /* Configure the SPI bus */
- - spi->mode = SPI_MODE_0;
- + spi->mode = spi->mode ? : SPI_MODE_0;
- + if (mcp251x_is_2510(spi))
- + spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000;
- + else
- + spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000;
- +
- spi->bits_per_word = 8;
- spi_setup(spi);
- /* Here is OK to not lock the MCP, no one knows about it yet */
- if (!mcp251x_hw_probe(spi)) {
- -//### dev_info(&spi->dev, "Probe failed\n");
- + dev_info(&spi->dev, "Probe failed\n");
- goto error_probe;
- }
- mcp251x_hw_sleep(spi);
- @@ -1070,17 +1098,16 @@
- pdata->transceiver_enable(0);
- ret = register_candev(net);
- - if (!ret) {
- - dev_info(&spi->dev, "probed\n");
- - return ret;
- - }
- + if (ret)
- + goto error_probe;
- +
- + devm_can_led_init(net);
- +
- + dev_info(&spi->dev, "probed\n");
- +
- + return ret;
- +
- error_probe:
- - if (!mcp251x_enable_dma)
- - kfree(priv->spi_rx_buf);
- -error_rx_buf:
- - if (!mcp251x_enable_dma)
- - kfree(priv->spi_tx_buf);
- -error_tx_buf:
- free_candev(net);
- if (mcp251x_enable_dma)
- dma_free_coherent(&spi->dev, PAGE_SIZE,
- @@ -1093,10 +1120,10 @@
- return ret;
- }
- -static int __devexit mcp251x_can_remove(struct spi_device *spi)
- +static int mcp251x_can_remove(struct spi_device *spi)
- {
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- struct net_device *net = priv->net;
- unregister_candev(net);
- @@ -1105,9 +1132,6 @@
- if (mcp251x_enable_dma) {
- dma_free_coherent(&spi->dev, PAGE_SIZE,
- priv->spi_tx_buf, priv->spi_tx_dma);
- - } else {
- - kfree(priv->spi_tx_buf);
- - kfree(priv->spi_rx_buf);
- }
- if (pdata->power_enable)
- @@ -1116,11 +1140,13 @@
- return 0;
- }
- -#ifdef CONFIG_PM
- -static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
- +#ifdef CONFIG_PM_SLEEP
- +
- +static int mcp251x_can_suspend(struct device *dev)
- {
- + struct spi_device *spi = to_spi_device(dev);
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- struct net_device *net = priv->net;
- priv->force_quit = 1;
- @@ -1148,10 +1174,11 @@
- return 0;
- }
- -static int mcp251x_can_resume(struct spi_device *spi)
- +static int mcp251x_can_resume(struct device *dev)
- {
- + struct spi_device *spi = to_spi_device(dev);
- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
- - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
- + struct mcp251x_priv *priv = spi_get_drvdata(spi);
- if (priv->after_suspend & AFTER_SUSPEND_POWER) {
- pdata->power_enable(1);
- @@ -1169,11 +1196,11 @@
- enable_irq(spi->irq);
- return 0;
- }
- -#else
- -#define mcp251x_can_suspend NULL
- -#define mcp251x_can_resume NULL
- #endif
- +static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend,
- + mcp251x_can_resume);
- +
- static const struct spi_device_id mcp251x_id_table[] = {
- { "mcp2510", CAN_MCP251X_MCP2510 },
- { "mcp2515", CAN_MCP251X_MCP2515 },
- @@ -1185,31 +1212,18 @@
- static struct spi_driver mcp251x_can_driver = {
- .driver = {
- .name = DEVICE_NAME,
- - .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- + .pm = &mcp251x_can_pm_ops,
- },
- .id_table = mcp251x_id_table,
- .probe = mcp251x_can_probe,
- - .remove = __devexit_p(mcp251x_can_remove),
- - .suspend = mcp251x_can_suspend,
- - .resume = mcp251x_can_resume,
- + .remove = mcp251x_can_remove,
- };
- -
- -static int __init mcp251x_can_init(void)
- -{
- - return spi_register_driver(&mcp251x_can_driver);
- -}
- -
- -static void __exit mcp251x_can_exit(void)
- -{
- - spi_unregister_driver(&mcp251x_can_driver);
- -}
- -
- -module_init(mcp251x_can_init);
- -module_exit(mcp251x_can_exit);
- +module_spi_driver(mcp251x_can_driver);
- MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
- "Christian Pellegrin <chripell@evolware.org>");
- MODULE_DESCRIPTION("Microchip 251x CAN driver");
- MODULE_LICENSE("GPL v2");
- +
- diff -Naur a/include/linux/can/led.h b/include/linux/can/led.h
- --- a/include/linux/can/led.h 1970-01-01 01:00:00.000000000 +0100
- +++ b/include/linux/can/led.h 2014-01-02 14:42:04.108435089 +0100
- @@ -0,0 +1,51 @@
- +/*
- + * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + */
- +
- +#ifndef CAN_LED_H
- +#define CAN_LED_H
- +
- +#include <linux/if.h>
- +#include <linux/leds.h>
- +
- +enum can_led_event {
- + CAN_LED_EVENT_OPEN,
- + CAN_LED_EVENT_STOP,
- + CAN_LED_EVENT_TX,
- + CAN_LED_EVENT_RX,
- +};
- +
- +#ifdef CONFIG_CAN_LEDS
- +
- +/* keep space for interface name + "-tx"/"-rx" suffix and null terminator */
- +#define CAN_LED_NAME_SZ (IFNAMSIZ + 4)
- +
- +void can_led_event(struct net_device *netdev, enum can_led_event event);
- +void devm_can_led_init(struct net_device *netdev);
- +int __init can_led_notifier_init(void);
- +void __exit can_led_notifier_exit(void);
- +
- +#else
- +
- +static inline void can_led_event(struct net_device *netdev,
- + enum can_led_event event)
- +{
- +}
- +static inline void devm_can_led_init(struct net_device *netdev)
- +{
- +}
- +static inline int can_led_notifier_init(void)
- +{
- + return 0;
- +}
- +static inline void can_led_notifier_exit(void)
- +{
- +}
- +
- +#endif
- +
- +#endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement