diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-02-20 17:54:28 +0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-20 17:54:28 +0400 |
commit | d4263348f796f29546f90802177865dd4379dd0a (patch) | |
tree | adcbdaebae584eee2f32fab95e826e8e49eef385 /drivers/net/can | |
parent | be873ac782f5ff5ee6675f83929f4fe6737eead2 (diff) | |
parent | 6d0abeca3242a88cab8232e4acd7e2bf088f3bc2 (diff) | |
download | linux-d4263348f796f29546f90802177865dd4379dd0a.tar.xz |
Merge branch 'master' into for-next
Diffstat (limited to 'drivers/net/can')
29 files changed, 311 insertions, 250 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 3c069472eb8b..9e7d95dae2c7 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -71,7 +71,7 @@ config CAN_AT91 and AT91SAM9X5 processors. config CAN_TI_HECC - depends on ARCH_OMAP3 + depends on ARM tristate "TI High End CAN Controller" ---help--- Driver for TI HECC (High End CAN Controller) module found on many diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index cf0f63e14e53..6efe27458116 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -22,7 +22,6 @@ #include <linux/clk.h> #include <linux/errno.h> #include <linux/if_arp.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 8a0b515b33ea..8d2b89a12e09 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -9,7 +9,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/bitops.h> #include <linux/interrupt.h> diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 77061eebb034..951bfede8f3d 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -808,17 +808,19 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) u32 num_rx_pkts = 0; unsigned int msg_obj, msg_ctrl_save; struct c_can_priv *priv = netdev_priv(dev); - u32 val = c_can_read_reg32(priv, C_CAN_INTPND1_REG); + u16 val; + + /* + * It is faster to read only one 16bit register. This is only possible + * for a maximum number of 16 objects. + */ + BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, + "Implementation does not support more message objects than 16"); + + while (quota > 0 && (val = priv->read_reg(priv, C_CAN_INTPND1_REG))) { + while ((msg_obj = ffs(val)) && quota > 0) { + val &= ~BIT(msg_obj - 1); - for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST; - msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0; - val = c_can_read_reg32(priv, C_CAN_INTPND1_REG), - msg_obj++) { - /* - * as interrupt pending register's bit n-1 corresponds to - * message object n, we need to handle the same properly. - */ - if (val & (1 << (msg_obj - 1))) { c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL & ~IF_COMM_TXRQST); msg_ctrl_save = priv->read_reg(priv, diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index bda1888cae9a..fc59bc6f040b 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -13,8 +13,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/module.h> @@ -324,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, } if (!priv->echo_skb[idx]) { - struct sock *srcsk = skb->sk; - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else - skb_orphan(skb); - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* make settings for echo to reduce code in irq context */ skb->protocol = htons(ETH_P_CAN); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index aaed97bee471..320bef2dba42 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -235,9 +235,12 @@ static const struct can_bittiming_const flexcan_bittiming_const = { }; /* - * Abstract off the read/write for arm versus ppc. + * Abstract off the read/write for arm versus ppc. This + * assumes that PPC uses big-endian registers and everything + * else uses little-endian registers, independent of CPU + * endianess. */ -#if defined(__BIG_ENDIAN) +#if defined(CONFIG_PPC) static inline u32 flexcan_read(void __iomem *addr) { return in_be32(addr); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index ab5909a7bae9..71594e5676fd 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/platform_device.h> @@ -19,6 +18,7 @@ #include <linux/netdevice.h> #include <linux/can.h> #include <linux/can/dev.h> +#include <linux/can/skb.h> #include <linux/can/error.h> #include <linux/mfd/janz.h> @@ -1134,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) */ static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) { - struct sock *srcsk = skb->sk; - - if (atomic_read(&skb->users) != 1) { - struct sk_buff *old_skb = skb; - - skb = skb_clone(old_skb, GFP_ATOMIC); - kfree_skb(old_skb); - if (!skb) - return; - } else { - skb_orphan(skb); - } - - skb->sk = srcsk; + skb = can_create_echo_skb(skb); + if (!skb) + return; /* save this skb for tx interrupt echo handling */ skb_queue_tail(&mod->echoq, skb); @@ -1323,7 +1312,7 @@ static int ican3_napi(struct napi_struct *napi, int budget) /* process all communication messages */ while (true) { - struct ican3_msg msg; + struct ican3_msg uninitialized_var(msg); ret = ican3_recv_msg(mod, &msg); if (ret) break; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 08ac401e0214..cdb9808d12db 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -28,8 +28,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/>. * * * @@ -59,6 +58,7 @@ #include <linux/can/dev.h> #include <linux/can/led.h> #include <linux/can/platform/mcp251x.h> +#include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/device.h> @@ -69,6 +69,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spi/spi.h> @@ -264,6 +266,7 @@ struct mcp251x_priv { int restart_tx; struct regulator *power; struct regulator *transceiver; + struct clk *clk; }; #define MCP251X_IS(_model) \ @@ -995,22 +998,65 @@ static const struct net_device_ops mcp251x_netdev_ops = { .ndo_start_xmit = mcp251x_hard_start_xmit, }; +static const struct of_device_id mcp251x_of_match[] = { + { + .compatible = "microchip,mcp2510", + .data = (void *)CAN_MCP251X_MCP2510, + }, + { + .compatible = "microchip,mcp2515", + .data = (void *)CAN_MCP251X_MCP2515, + }, + { } +}; +MODULE_DEVICE_TABLE(of, mcp251x_of_match); + +static const struct spi_device_id mcp251x_id_table[] = { + { + .name = "mcp2510", + .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2510, + }, + { + .name = "mcp2515", + .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, + }, + { } +}; +MODULE_DEVICE_TABLE(spi, mcp251x_id_table); + static int mcp251x_can_probe(struct spi_device *spi) { + const struct of_device_id *of_id = of_match_device(mcp251x_of_match, + &spi->dev); + struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); struct net_device *net; struct mcp251x_priv *priv; - struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); - int ret = -ENODEV; + int freq, ret = -ENODEV; + struct clk *clk; + + clk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) { + if (pdata) + freq = pdata->oscillator_frequency; + else + return PTR_ERR(clk); + } else { + freq = clk_get_rate(clk); + } - if (!pdata) - /* Platform data is required for osc freq */ - goto error_out; + /* Sanity check */ + if (freq < 1000000 || freq > 25000000) + return -ERANGE; /* Allocate can/net device */ net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); - if (!net) { - ret = -ENOMEM; - goto error_alloc; + if (!net) + return -ENOMEM; + + if (!IS_ERR(clk)) { + ret = clk_prepare_enable(clk); + if (ret) + goto out_free; } net->netdev_ops = &mcp251x_netdev_ops; @@ -1019,23 +1065,27 @@ static int mcp251x_can_probe(struct spi_device *spi) priv = netdev_priv(net); priv->can.bittiming_const = &mcp251x_bittiming_const; priv->can.do_set_mode = mcp251x_do_set_mode; - priv->can.clock.freq = pdata->oscillator_frequency / 2; + priv->can.clock.freq = freq / 2; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; - priv->model = spi_get_device_id(spi)->driver_data; + if (of_id) + priv->model = (enum mcp251x_model)of_id->data; + else + priv->model = spi_get_device_id(spi)->driver_data; priv->net = net; + priv->clk = clk; priv->power = devm_regulator_get(&spi->dev, "vdd"); priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { ret = -EPROBE_DEFER; - goto error_power; + goto out_clk; } ret = mcp251x_power_enable(priv->power, 1); if (ret) - goto error_power; + goto out_clk; spi_set_drvdata(spi, priv); @@ -1067,15 +1117,17 @@ static int mcp251x_can_probe(struct spi_device *spi) /* 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; } } @@ -1108,21 +1160,18 @@ static int mcp251x_can_probe(struct spi_device *spi) 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: if (mcp251x_enable_dma) dma_free_coherent(&spi->dev, PAGE_SIZE, priv->spi_tx_buf, priv->spi_tx_dma); mcp251x_power_enable(priv->power, 0); -error_power: + +out_clk: + if (!IS_ERR(clk)) + clk_disable_unprepare(clk); + +out_free: free_candev(net); -error_alloc: - dev_err(&spi->dev, "probe failed\n"); -error_out: + return ret; } @@ -1136,13 +1185,13 @@ static int mcp251x_can_remove(struct spi_device *spi) 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); } mcp251x_power_enable(priv->power, 0); + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); + free_candev(net); return 0; @@ -1205,21 +1254,13 @@ static int mcp251x_can_resume(struct device *dev) 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 }, - { }, -}; - -MODULE_DEVICE_TABLE(spi, mcp251x_id_table); - static struct spi_driver mcp251x_can_driver = { .driver = { .name = DEVICE_NAME, .owner = THIS_MODULE, + .of_match_table = mcp251x_of_match, .pm = &mcp251x_can_pm_ops, }, - .id_table = mcp251x_id_table, .probe = mcp251x_can_probe, .remove = mcp251x_can_remove, diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index e59b3a392af6..44725296f72a 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.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> @@ -109,135 +108,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, #endif /* CONFIG_PPC_MPC52xx */ #ifdef CONFIG_PPC_MPC512x -struct mpc512x_clockctl { - u32 spmr; /* System PLL Mode Reg */ - u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ - u32 scfr1; /* System Clk Freq Reg 1 */ - u32 scfr2; /* System Clk Freq Reg 2 */ - u32 reserved; - u32 bcr; /* Bread Crumb Reg */ - u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */ - u32 spccr; /* SPDIF Clk Ctrl Reg */ - u32 cccr; /* CFM Clk Ctrl Reg */ - u32 dccr; /* DIU Clk Cnfg Reg */ - u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */ -}; - -static struct of_device_id mpc512x_clock_ids[] = { - { .compatible = "fsl,mpc5121-clock", }, - {} -}; - static u32 mpc512x_can_get_clock(struct platform_device *ofdev, - const char *clock_name, int *mscan_clksrc) + const char *clock_source, int *mscan_clksrc) { - struct mpc512x_clockctl __iomem *clockctl; - struct device_node *np_clock; - struct clk *sys_clk, *ref_clk; - int plen, clockidx, clocksrc = -1; - u32 sys_freq, val, clockdiv = 1, freq = 0; - const u32 *pval; - - np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); - if (!np_clock) { - dev_err(&ofdev->dev, "couldn't find clock node\n"); - return 0; - } - clockctl = of_iomap(np_clock, 0); - if (!clockctl) { - dev_err(&ofdev->dev, "couldn't map clock registers\n"); - goto exit_put; - } + struct device_node *np; + u32 clockdiv; + enum { + CLK_FROM_AUTO, + CLK_FROM_IPS, + CLK_FROM_SYS, + CLK_FROM_REF, + } clk_from; + struct clk *clk_in, *clk_can; + unsigned long freq_calc; + struct mscan_priv *priv; + struct clk *clk_ipg; - /* Determine the MSCAN device index from the peripheral's - * physical address. Register address offsets against the - * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380 + /* the caller passed in the clock source spec that was read from + * the device tree, get the optional clock divider as well */ - pval = of_get_property(ofdev->dev.of_node, "reg", &plen); - BUG_ON(!pval || plen < sizeof(*pval)); - clockidx = (*pval & 0x80) ? 1 : 0; - if (*pval & 0x2000) - clockidx += 2; + np = ofdev->dev.of_node; + clockdiv = 1; + of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv); + dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n", + clock_source ? clock_source : "<NULL>", clockdiv); + + /* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to + * get set, and the 'ips' clock is the input to the MSCAN + * component + * + * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC] + * bit needs to get cleared, an optional clock-divider may have + * been specified (the default value is 1), the appropriate + * MSCAN related MCLK is the input to the MSCAN component + * + * in the absence of a clock-source spec, first an optimal clock + * gets determined based on the 'sys' clock, if that fails the + * 'ref' clock is used + */ + clk_from = CLK_FROM_AUTO; + if (clock_source) { + /* interpret the device tree's spec for the clock source */ + if (!strcmp(clock_source, "ip")) + clk_from = CLK_FROM_IPS; + else if (!strcmp(clock_source, "sys")) + clk_from = CLK_FROM_SYS; + else if (!strcmp(clock_source, "ref")) + clk_from = CLK_FROM_REF; + else + goto err_invalid; + dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from); + } + if (clk_from == CLK_FROM_AUTO) { + /* no spec so far, try the 'sys' clock; round to the + * next MHz and see if we can get a multiple of 16MHz + */ + dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n"); + clk_in = devm_clk_get(&ofdev->dev, "sys"); + if (IS_ERR(clk_in)) + goto err_notavail; + freq_calc = clk_get_rate(clk_in); + freq_calc += 499999; + freq_calc /= 1000000; + freq_calc *= 1000000; + if ((freq_calc % 16000000) == 0) { + clk_from = CLK_FROM_SYS; + clockdiv = freq_calc / 16000000; + dev_dbg(&ofdev->dev, + "clk fit, sys[%lu] div[%d] freq[%lu]\n", + freq_calc, clockdiv, freq_calc / clockdiv); + } + } + if (clk_from == CLK_FROM_AUTO) { + /* no spec so far, use the 'ref' clock */ + dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n"); + clk_in = devm_clk_get(&ofdev->dev, "ref"); + if (IS_ERR(clk_in)) + goto err_notavail; + clk_from = CLK_FROM_REF; + freq_calc = clk_get_rate(clk_in); + dev_dbg(&ofdev->dev, + "clk fit, ref[%lu] (no div) freq[%lu]\n", + freq_calc, freq_calc); + } - /* - * Clock source and divider selection: 3 different clock sources - * can be selected: "ip", "ref" or "sys". For the latter two, a - * clock divider can be defined as well. If the clock source is - * not specified by the device tree, we first try to find an - * optimal CAN source clock based on the system clock. If that - * is not posslible, the reference clock will be used. + /* select IPS or MCLK as the MSCAN input (returned to the caller), + * setup the MCLK mux source and rate if applicable, apply the + * optionally specified or derived above divider, and determine + * the actual resulting clock rate to return to the caller */ - if (clock_name && !strcmp(clock_name, "ip")) { + switch (clk_from) { + case CLK_FROM_IPS: + clk_can = devm_clk_get(&ofdev->dev, "ips"); + if (IS_ERR(clk_can)) + goto err_notavail; + priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); + priv->clk_can = clk_can; + freq_calc = clk_get_rate(clk_can); *mscan_clksrc = MSCAN_CLKSRC_IPS; - freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node); - } else { + dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n", + *mscan_clksrc, freq_calc); + break; + case CLK_FROM_SYS: + case CLK_FROM_REF: + clk_can = devm_clk_get(&ofdev->dev, "mclk"); + if (IS_ERR(clk_can)) + goto err_notavail; + priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); + priv->clk_can = clk_can; + if (clk_from == CLK_FROM_SYS) + clk_in = devm_clk_get(&ofdev->dev, "sys"); + if (clk_from == CLK_FROM_REF) + clk_in = devm_clk_get(&ofdev->dev, "ref"); + if (IS_ERR(clk_in)) + goto err_notavail; + clk_set_parent(clk_can, clk_in); + freq_calc = clk_get_rate(clk_in); + freq_calc /= clockdiv; + clk_set_rate(clk_can, freq_calc); + freq_calc = clk_get_rate(clk_can); *mscan_clksrc = MSCAN_CLKSRC_BUS; - - pval = of_get_property(ofdev->dev.of_node, - "fsl,mscan-clock-divider", &plen); - if (pval && plen == sizeof(*pval)) - clockdiv = *pval; - if (!clockdiv) - clockdiv = 1; - - if (!clock_name || !strcmp(clock_name, "sys")) { - sys_clk = devm_clk_get(&ofdev->dev, "sys_clk"); - if (IS_ERR(sys_clk)) { - dev_err(&ofdev->dev, "couldn't get sys_clk\n"); - goto exit_unmap; - } - /* Get and round up/down sys clock rate */ - sys_freq = 1000000 * - ((clk_get_rate(sys_clk) + 499999) / 1000000); - - if (!clock_name) { - /* A multiple of 16 MHz would be optimal */ - if ((sys_freq % 16000000) == 0) { - clocksrc = 0; - clockdiv = sys_freq / 16000000; - freq = sys_freq / clockdiv; - } - } else { - clocksrc = 0; - freq = sys_freq / clockdiv; - } - } - - if (clocksrc < 0) { - ref_clk = devm_clk_get(&ofdev->dev, "ref_clk"); - if (IS_ERR(ref_clk)) { - dev_err(&ofdev->dev, "couldn't get ref_clk\n"); - goto exit_unmap; - } - clocksrc = 1; - freq = clk_get_rate(ref_clk) / clockdiv; - } + dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n", + *mscan_clksrc, freq_calc); + break; + default: + goto err_invalid; } - /* Disable clock */ - out_be32(&clockctl->mccr[clockidx], 0x0); - if (clocksrc >= 0) { - /* Set source and divider */ - val = (clocksrc << 14) | ((clockdiv - 1) << 17); - out_be32(&clockctl->mccr[clockidx], val); - /* Enable clock */ - out_be32(&clockctl->mccr[clockidx], val | 0x10000); - } + /* the above clk_can item is used for the bitrate, access to + * the peripheral's register set needs the clk_ipg item + */ + clk_ipg = devm_clk_get(&ofdev->dev, "ipg"); + if (IS_ERR(clk_ipg)) + goto err_notavail_ipg; + if (clk_prepare_enable(clk_ipg)) + goto err_notavail_ipg; + priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); + priv->clk_ipg = clk_ipg; + + /* return the determined clock source rate */ + return freq_calc; + +err_invalid: + dev_err(&ofdev->dev, "invalid clock source specification\n"); + /* clock source rate could not get determined */ + return 0; - /* Enable MSCAN clock domain */ - val = in_be32(&clockctl->sccr[1]); - if (!(val & (1 << 25))) - out_be32(&clockctl->sccr[1], val | (1 << 25)); +err_notavail: + dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n"); + /* clock source rate could not get determined */ + return 0; - dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", - *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : - clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); +err_notavail_ipg: + dev_err(&ofdev->dev, "cannot acquire or setup register clock\n"); + /* clock source rate could not get determined */ + return 0; +} -exit_unmap: - iounmap(clockctl); -exit_put: - of_node_put(np_clock); - return freq; +static void mpc512x_can_put_clock(struct platform_device *ofdev) +{ + struct mscan_priv *priv; + + priv = netdev_priv(dev_get_drvdata(&ofdev->dev)); + if (priv->clk_ipg) + clk_disable_unprepare(priv->clk_ipg); } #else /* !CONFIG_PPC_MPC512x */ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, @@ -245,6 +279,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, { return 0; } +#define mpc512x_can_put_clock NULL #endif /* CONFIG_PPC_MPC512x */ static const struct of_device_id mpc5xxx_can_table[]; @@ -386,11 +421,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev) static const struct mpc5xxx_can_data mpc5200_can_data = { .type = MSCAN_TYPE_MPC5200, .get_clock = mpc52xx_can_get_clock, + /* .put_clock not applicable */ }; static const struct mpc5xxx_can_data mpc5121_can_data = { .type = MSCAN_TYPE_MPC5121, .get_clock = mpc512x_can_get_clock, + .put_clock = mpc512x_can_put_clock, }; static const struct of_device_id mpc5xxx_can_table[] = { diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index a955ec8c4b97..b9f3faabb0f3 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> diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index e98abb97a050..ad8e08f9c496 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h @@ -14,8 +14,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/>. */ #ifndef __MSCAN_H__ diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 5f0e9b3bfa7b..6c077eb87b5e 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -12,8 +12,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/interrupt.h> @@ -22,7 +21,6 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/pci.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 835921388e7b..d790b874ca79 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -13,8 +13,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> diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 087b13bd300e..c96eb14699d5 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -26,8 +26,7 @@ * 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> diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index f9b4f81cd86a..fbb61a0d901f 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.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> @@ -45,7 +44,8 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " "esd CAN-PCI/PMC/266, " "esd CAN-PCIe/2000, " "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), " - "IXXAT PC-I 04/PCI") + "IXXAT PC-I 04/PCI, " + "ELCUS CAN-200-PCI") MODULE_LICENSE("GPL v2"); #define PLX_PCI_MAX_CHAN 2 @@ -123,6 +123,11 @@ struct plx_pci_card { #define ESD_PCI_SUB_SYS_ID_PCIE2000 0x0200 #define ESD_PCI_SUB_SYS_ID_PCI104200 0x0501 +#define CAN200PCI_DEVICE_ID 0x9030 +#define CAN200PCI_VENDOR_ID 0x10b5 +#define CAN200PCI_SUB_DEVICE_ID 0x0301 +#define CAN200PCI_SUB_VENDOR_ID 0xe1c5 + #define IXXAT_PCI_VENDOR_ID 0x10b5 #define IXXAT_PCI_DEVICE_ID 0x9050 #define IXXAT_PCI_SUB_SYS_ID 0x2540 @@ -234,6 +239,14 @@ static struct plx_pci_card_info plx_pci_card_info_cti = { /* based on PLX9030 */ }; +static struct plx_pci_card_info plx_pci_card_info_elcus = { + "Eclus CAN-200-PCI", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {1, 0x00, 0x00}, { {2, 0x00, 0x80}, {3, 0x00, 0x80} }, + &plx_pci_reset_common + /* based on PLX9030 */ +}; + static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = { { /* Adlink PCI-7841/cPCI-7841 */ @@ -319,6 +332,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = { 0, 0, (kernel_ulong_t)&plx_pci_card_info_cti }, + { + /* Elcus CAN-200-PCI */ + CAN200PCI_VENDOR_ID, CAN200PCI_DEVICE_ID, + CAN200PCI_SUB_VENDOR_ID, CAN200PCI_SUB_DEVICE_ID, + 0, 0, + (kernel_ulong_t)&plx_pci_card_info_elcus + }, { 0,} }; MODULE_DEVICE_TABLE(pci, plx_pci_tbl); diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 06a282397fff..df136a2516c4 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -11,8 +11,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> diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 047accd4ede5..2f6e24534231 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -13,8 +13,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/>. */ /* This is a generic driver for SJA1000 chips on the OpenFirmware platform diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 29f9b6321187..943df645b459 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -12,8 +12,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> diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 25377e547f9b..3fcdae266377 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -18,9 +18,7 @@ * 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. You can also get it - * at http://www.gnu.org/licenses/gpl.html + * with this program; if not, see http://www.gnu.org/licenses/gpl.html * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c index 498605f833dd..cdc0c7433a4b 100644 --- a/drivers/net/can/softing/softing_cs.c +++ b/drivers/net/can/softing/softing_cs.c @@ -13,8 +13,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/module.h> diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c index b595d3422b9f..52fe50725d74 100644 --- a/drivers/net/can/softing/softing_fw.c +++ b/drivers/net/can/softing/softing_fw.c @@ -13,8 +13,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/firmware.h> diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 6cd5c01b624d..9ea0dcde94ce 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -13,12 +13,10 @@ * 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/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <asm/io.h> diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 60d95b44d0f7..2c62fe6c8fa9 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -37,7 +37,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/interrupt.h> @@ -518,10 +517,10 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) data = (cf->can_id & CAN_SFF_MASK) << 18; hecc_write_mbx(priv, mbxno, HECC_CANMID, data); hecc_write_mbx(priv, mbxno, HECC_CANMDL, - be32_to_cpu(*(u32 *)(cf->data))); + be32_to_cpu(*(__be32 *)(cf->data))); if (cf->can_dlc > 4) hecc_write_mbx(priv, mbxno, HECC_CANMDH, - be32_to_cpu(*(u32 *)(cf->data + 4))); + be32_to_cpu(*(__be32 *)(cf->data + 4))); else *(u32 *)(cf->data + 4) = 0; can_put_echo_skb(skb, ndev, mbxno); @@ -569,12 +568,10 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno) cf->can_id |= CAN_RTR_FLAG; cf->can_dlc = get_can_dlc(data & 0xF); data = hecc_read_mbx(priv, mbxno, HECC_CANMDL); - *(u32 *)(cf->data) = cpu_to_be32(data); + *(__be32 *)(cf->data) = cpu_to_be32(data); if (cf->can_dlc > 4) { data = hecc_read_mbx(priv, mbxno, HECC_CANMDH); - *(u32 *)(cf->data + 4) = cpu_to_be32(data); - } else { - *(u32 *)(cf->data + 4) = 0; + *(__be32 *)(cf->data + 4) = cpu_to_be32(data); } spin_lock_irqsave(&priv->mbx_lock, flags); hecc_clear_bit(priv, HECC_CANME, mbx_mask); diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 5f9a7ad9b964..52c42fd49510 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -16,7 +16,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <linux/init.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> @@ -625,6 +624,7 @@ static int ems_usb_start(struct ems_usb *dev) usb_unanchor_urb(urb); usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, urb->transfer_dma); + usb_free_urb(urb); break; } @@ -798,8 +798,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne * allowed (MAX_TX_URBS). */ if (!context) { - usb_unanchor_urb(urb); usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); + usb_free_urb(urb); netdev_warn(netdev, "couldn't find free context\n"); diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index ac6177d3befc..7fbe85935f1d 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -16,7 +16,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <linux/init.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 4b2d5ed62b11..6c859bba8b65 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -12,7 +12,6 @@ * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be> */ -#include <linux/init.h> #include <linux/completion.h> #include <linux/module.h> #include <linux/netdevice.h> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 8ee9d1556e6e..263dd921edc4 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) /* set LED in default state (end of init phase) */ pcan_usb_pro_set_led(dev, 0, 1); + kfree(bi); + kfree(fi); + return 0; err_out: diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index 8becd3d838b5..a0fa1fd5092b 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -23,7 +23,6 @@ * who were very cooperative and answered my questions. */ -#include <linux/init.h> #include <linux/signal.h> #include <linux/slab.h> #include <linux/module.h> diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0a2a5ee79a17..4e94057ef5cf 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -46,6 +46,7 @@ #include <linux/if_ether.h> #include <linux/can.h> #include <linux/can/dev.h> +#include <linux/can/skb.h> #include <linux/slab.h> #include <net/rtnetlink.h> @@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) stats->rx_packets++; stats->rx_bytes += cfd->len; } - kfree_skb(skb); + consume_skb(skb); return NETDEV_TX_OK; } /* perform standard echo handling for CAN network interfaces */ if (loop) { - struct sock *srcsk = skb->sk; - skb = skb_share_check(skb, GFP_ATOMIC); + skb = can_create_echo_skb(skb); if (!skb) return NETDEV_TX_OK; /* receive with packet counting */ - skb->sk = srcsk; vcan_rx(skb, dev); } else { /* no looped packets => no counting */ - kfree_skb(skb); + consume_skb(skb); } return NETDEV_TX_OK; } |