diff options
Diffstat (limited to 'kernel/include/linux/can')
-rw-r--r-- | kernel/include/linux/can/core.h | 61 | ||||
-rw-r--r-- | kernel/include/linux/can/dev.h | 146 | ||||
-rw-r--r-- | kernel/include/linux/can/led.h | 53 | ||||
-rw-r--r-- | kernel/include/linux/can/platform/cc770.h | 33 | ||||
-rw-r--r-- | kernel/include/linux/can/platform/mcp251x.h | 21 | ||||
-rw-r--r-- | kernel/include/linux/can/platform/rcar_can.h | 17 | ||||
-rw-r--r-- | kernel/include/linux/can/platform/sja1000.h | 35 | ||||
-rw-r--r-- | kernel/include/linux/can/platform/ti_hecc.h | 44 | ||||
-rw-r--r-- | kernel/include/linux/can/skb.h | 78 |
9 files changed, 488 insertions, 0 deletions
diff --git a/kernel/include/linux/can/core.h b/kernel/include/linux/can/core.h new file mode 100644 index 000000000..a0875001b --- /dev/null +++ b/kernel/include/linux/can/core.h @@ -0,0 +1,61 @@ +/* + * linux/can/core.h + * + * Protoypes and definitions for CAN protocol modules using the PF_CAN core + * + * Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de> + * Urs Thuermann <urs.thuermann@volkswagen.de> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research + * All rights reserved. + * + */ + +#ifndef _CAN_CORE_H +#define _CAN_CORE_H + +#include <linux/can.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> + +#define CAN_VERSION "20120528" + +/* increment this number each time you change some user-space interface */ +#define CAN_ABI_VERSION "9" + +#define CAN_VERSION_STRING "rev " CAN_VERSION " abi " CAN_ABI_VERSION + +#define DNAME(dev) ((dev) ? (dev)->name : "any") + +/** + * struct can_proto - CAN protocol structure + * @type: type argument in socket() syscall, e.g. SOCK_DGRAM. + * @protocol: protocol number in socket() syscall. + * @ops: pointer to struct proto_ops for sock->ops. + * @prot: pointer to struct proto structure. + */ +struct can_proto { + int type; + int protocol; + const struct proto_ops *ops; + struct proto *prot; +}; + +/* function prototypes for the CAN networklayer core (af_can.c) */ + +extern int can_proto_register(const struct can_proto *cp); +extern void can_proto_unregister(const struct can_proto *cp); + +extern int can_rx_register(struct net_device *dev, canid_t can_id, + canid_t mask, + void (*func)(struct sk_buff *, void *), + void *data, char *ident); + +extern void can_rx_unregister(struct net_device *dev, canid_t can_id, + canid_t mask, + void (*func)(struct sk_buff *, void *), + void *data); + +extern int can_send(struct sk_buff *skb, int loop); +extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); + +#endif /* !_CAN_CORE_H */ diff --git a/kernel/include/linux/can/dev.h b/kernel/include/linux/can/dev.h new file mode 100644 index 000000000..c3a9c8fc6 --- /dev/null +++ b/kernel/include/linux/can/dev.h @@ -0,0 +1,146 @@ +/* + * linux/can/dev.h + * + * Definitions for the CAN network device driver interface + * + * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com> + * Varma Electronics Oy + * + * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com> + * + */ + +#ifndef _CAN_DEV_H +#define _CAN_DEV_H + +#include <linux/can.h> +#include <linux/can/netlink.h> +#include <linux/can/error.h> +#include <linux/can/led.h> + +/* + * CAN mode + */ +enum can_mode { + CAN_MODE_STOP = 0, + CAN_MODE_START, + CAN_MODE_SLEEP +}; + +/* + * CAN common private data + */ +struct can_priv { + struct can_device_stats can_stats; + + struct can_bittiming bittiming, data_bittiming; + const struct can_bittiming_const *bittiming_const, + *data_bittiming_const; + struct can_clock clock; + + enum can_state state; + u32 ctrlmode; + u32 ctrlmode_supported; + + int restart_ms; + struct timer_list restart_timer; + + int (*do_set_bittiming)(struct net_device *dev); + int (*do_set_data_bittiming)(struct net_device *dev); + int (*do_set_mode)(struct net_device *dev, enum can_mode mode); + int (*do_get_state)(const struct net_device *dev, + enum can_state *state); + int (*do_get_berr_counter)(const struct net_device *dev, + struct can_berr_counter *bec); + + unsigned int echo_skb_max; + struct sk_buff **echo_skb; + +#ifdef CONFIG_CAN_LEDS + struct led_trigger *tx_led_trig; + char tx_led_trig_name[CAN_LED_NAME_SZ]; + struct led_trigger *rx_led_trig; + char rx_led_trig_name[CAN_LED_NAME_SZ]; + struct led_trigger *rxtx_led_trig; + char rxtx_led_trig_name[CAN_LED_NAME_SZ]; +#endif +}; + +/* + * get_can_dlc(value) - helper macro to cast a given data length code (dlc) + * to __u8 and ensure the dlc value to be max. 8 bytes. + * + * To be used in the CAN netdriver receive path to ensure conformance with + * ISO 11898-1 Chapter 8.4.2.3 (DLC field) + */ +#define get_can_dlc(i) (min_t(__u8, (i), CAN_MAX_DLC)) +#define get_canfd_dlc(i) (min_t(__u8, (i), CANFD_MAX_DLC)) + +/* Drop a given socketbuffer if it does not contain a valid CAN frame. */ +static inline int can_dropped_invalid_skb(struct net_device *dev, + struct sk_buff *skb) +{ + const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; + + if (skb->protocol == htons(ETH_P_CAN)) { + if (unlikely(skb->len != CAN_MTU || + cfd->len > CAN_MAX_DLEN)) + goto inval_skb; + } else if (skb->protocol == htons(ETH_P_CANFD)) { + if (unlikely(skb->len != CANFD_MTU || + cfd->len > CANFD_MAX_DLEN)) + goto inval_skb; + } else + goto inval_skb; + + return 0; + +inval_skb: + kfree_skb(skb); + dev->stats.tx_dropped++; + return 1; +} + +static inline bool can_is_canfd_skb(const struct sk_buff *skb) +{ + /* the CAN specific type of skb is identified by its data length */ + return skb->len == CANFD_MTU; +} + +/* get data length from can_dlc with sanitized can_dlc */ +u8 can_dlc2len(u8 can_dlc); + +/* map the sanitized data length to an appropriate data length code */ +u8 can_len2dlc(u8 len); + +struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max); +void free_candev(struct net_device *dev); + +/* a candev safe wrapper around netdev_priv */ +struct can_priv *safe_candev_priv(struct net_device *dev); + +int open_candev(struct net_device *dev); +void close_candev(struct net_device *dev); +int can_change_mtu(struct net_device *dev, int new_mtu); + +int register_candev(struct net_device *dev); +void unregister_candev(struct net_device *dev); + +int can_restart_now(struct net_device *dev); +void can_bus_off(struct net_device *dev); + +void can_change_state(struct net_device *dev, struct can_frame *cf, + enum can_state tx_state, enum can_state rx_state); + +void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, + unsigned int idx); +unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx); +void can_free_echo_skb(struct net_device *dev, unsigned int idx); + +struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); +struct sk_buff *alloc_canfd_skb(struct net_device *dev, + struct canfd_frame **cfd); +struct sk_buff *alloc_can_err_skb(struct net_device *dev, + struct can_frame **cf); + +#endif /* !_CAN_DEV_H */ diff --git a/kernel/include/linux/can/led.h b/kernel/include/linux/can/led.h new file mode 100644 index 000000000..146de4506 --- /dev/null +++ b/kernel/include/linux/can/led.h @@ -0,0 +1,53 @@ +/* + * 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"/"-rxtx" + * suffix and null terminator + */ +#define CAN_LED_NAME_SZ (IFNAMSIZ + 6) + +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 /* !_CAN_LED_H */ diff --git a/kernel/include/linux/can/platform/cc770.h b/kernel/include/linux/can/platform/cc770.h new file mode 100644 index 000000000..78b2d44f0 --- /dev/null +++ b/kernel/include/linux/can/platform/cc770.h @@ -0,0 +1,33 @@ +#ifndef _CAN_PLATFORM_CC770_H +#define _CAN_PLATFORM_CC770_H + +/* CPU Interface Register (0x02) */ +#define CPUIF_CEN 0x01 /* Clock Out Enable */ +#define CPUIF_MUX 0x04 /* Multiplex */ +#define CPUIF_SLP 0x08 /* Sleep */ +#define CPUIF_PWD 0x10 /* Power Down Mode */ +#define CPUIF_DMC 0x20 /* Divide Memory Clock */ +#define CPUIF_DSC 0x40 /* Divide System Clock */ +#define CPUIF_RST 0x80 /* Hardware Reset Status */ + +/* Clock Out Register (0x1f) */ +#define CLKOUT_CD_MASK 0x0f /* Clock Divider mask */ +#define CLKOUT_SL_MASK 0x30 /* Slew Rate mask */ +#define CLKOUT_SL_SHIFT 4 + +/* Bus Configuration Register (0x2f) */ +#define BUSCFG_DR0 0x01 /* Disconnect RX0 Input / Select RX input */ +#define BUSCFG_DR1 0x02 /* Disconnect RX1 Input / Silent mode */ +#define BUSCFG_DT1 0x08 /* Disconnect TX1 Output */ +#define BUSCFG_POL 0x20 /* Polarity dominant or recessive */ +#define BUSCFG_CBY 0x40 /* Input Comparator Bypass */ + +struct cc770_platform_data { + u32 osc_freq; /* CAN bus oscillator frequency in Hz */ + + u8 cir; /* CPU Interface Register */ + u8 cor; /* Clock Out Register */ + u8 bcr; /* Bus Configuration Register */ +}; + +#endif /* !_CAN_PLATFORM_CC770_H */ diff --git a/kernel/include/linux/can/platform/mcp251x.h b/kernel/include/linux/can/platform/mcp251x.h new file mode 100644 index 000000000..d44fcae27 --- /dev/null +++ b/kernel/include/linux/can/platform/mcp251x.h @@ -0,0 +1,21 @@ +#ifndef _CAN_PLATFORM_MCP251X_H +#define _CAN_PLATFORM_MCP251X_H + +/* + * + * CAN bus driver for Microchip 251x CAN Controller with SPI Interface + * + */ + +#include <linux/spi/spi.h> + +/* + * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data + * @oscillator_frequency: - oscillator frequency in Hz + */ + +struct mcp251x_platform_data { + unsigned long oscillator_frequency; +}; + +#endif /* !_CAN_PLATFORM_MCP251X_H */ diff --git a/kernel/include/linux/can/platform/rcar_can.h b/kernel/include/linux/can/platform/rcar_can.h new file mode 100644 index 000000000..0f4a2f3df --- /dev/null +++ b/kernel/include/linux/can/platform/rcar_can.h @@ -0,0 +1,17 @@ +#ifndef _CAN_PLATFORM_RCAR_CAN_H_ +#define _CAN_PLATFORM_RCAR_CAN_H_ + +#include <linux/types.h> + +/* Clock Select Register settings */ +enum CLKR { + CLKR_CLKP1 = 0, /* Peripheral clock (clkp1) */ + CLKR_CLKP2 = 1, /* Peripheral clock (clkp2) */ + CLKR_CLKEXT = 3 /* Externally input clock */ +}; + +struct rcar_can_platform_data { + enum CLKR clock_select; /* Clock source select */ +}; + +#endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */ diff --git a/kernel/include/linux/can/platform/sja1000.h b/kernel/include/linux/can/platform/sja1000.h new file mode 100644 index 000000000..93570b61e --- /dev/null +++ b/kernel/include/linux/can/platform/sja1000.h @@ -0,0 +1,35 @@ +#ifndef _CAN_PLATFORM_SJA1000_H +#define _CAN_PLATFORM_SJA1000_H + +/* clock divider register */ +#define CDR_CLKOUT_MASK 0x07 +#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */ +#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */ +#define CDR_CBP 0x40 /* CAN input comparator bypass */ +#define CDR_PELICAN 0x80 /* PeliCAN mode */ + +/* output control register */ +#define OCR_MODE_BIPHASE 0x00 +#define OCR_MODE_TEST 0x01 +#define OCR_MODE_NORMAL 0x02 +#define OCR_MODE_CLOCK 0x03 +#define OCR_MODE_MASK 0x07 +#define OCR_TX0_INVERT 0x04 +#define OCR_TX0_PULLDOWN 0x08 +#define OCR_TX0_PULLUP 0x10 +#define OCR_TX0_PUSHPULL 0x18 +#define OCR_TX1_INVERT 0x20 +#define OCR_TX1_PULLDOWN 0x40 +#define OCR_TX1_PULLUP 0x80 +#define OCR_TX1_PUSHPULL 0xc0 +#define OCR_TX_MASK 0xfc +#define OCR_TX_SHIFT 2 + +struct sja1000_platform_data { + u32 osc_freq; /* CAN bus oscillator frequency in Hz */ + + u8 ocr; /* output control register */ + u8 cdr; /* clock divider register */ +}; + +#endif /* !_CAN_PLATFORM_SJA1000_H */ diff --git a/kernel/include/linux/can/platform/ti_hecc.h b/kernel/include/linux/can/platform/ti_hecc.h new file mode 100644 index 000000000..a52f47ca6 --- /dev/null +++ b/kernel/include/linux/can/platform/ti_hecc.h @@ -0,0 +1,44 @@ +#ifndef _CAN_PLATFORM_TI_HECC_H +#define _CAN_PLATFORM_TI_HECC_H + +/* + * TI HECC (High End CAN Controller) driver platform header + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed as is WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/** + * struct hecc_platform_data - HECC Platform Data + * + * @scc_hecc_offset: mostly 0 - should really never change + * @scc_ram_offset: SCC RAM offset + * @hecc_ram_offset: HECC RAM offset + * @mbx_offset: Mailbox RAM offset + * @int_line: Interrupt line to use - 0 or 1 + * @version: version for future use + * @transceiver_switch: platform specific callback fn for transceiver control + * + * Platform data structure to get all platform specific settings. + * this structure also accounts the fact that the IP may have different + * RAM and mailbox offsets for different SOC's + */ +struct ti_hecc_platform_data { + u32 scc_hecc_offset; + u32 scc_ram_offset; + u32 hecc_ram_offset; + u32 mbx_offset; + u32 int_line; + u32 version; + void (*transceiver_switch) (int); +}; +#endif /* !_CAN_PLATFORM_TI_HECC_H */ diff --git a/kernel/include/linux/can/skb.h b/kernel/include/linux/can/skb.h new file mode 100644 index 000000000..b6a52a4b4 --- /dev/null +++ b/kernel/include/linux/can/skb.h @@ -0,0 +1,78 @@ +/* + * linux/can/skb.h + * + * Definitions for the CAN network socket buffer + * + * Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net> + * + */ + +#ifndef _CAN_SKB_H +#define _CAN_SKB_H + +#include <linux/types.h> +#include <linux/skbuff.h> +#include <linux/can.h> +#include <net/sock.h> + +/* + * The struct can_skb_priv is used to transport additional information along + * with the stored struct can(fd)_frame that can not be contained in existing + * struct sk_buff elements. + * N.B. that this information must not be modified in cloned CAN sk_buffs. + * To modify the CAN frame content or the struct can_skb_priv content + * skb_copy() needs to be used instead of skb_clone(). + */ + +/** + * struct can_skb_priv - private additional data inside CAN sk_buffs + * @ifindex: ifindex of the first interface the CAN frame appeared on + * @cf: align to the following CAN frame at skb->data + */ +struct can_skb_priv { + int ifindex; + struct can_frame cf[0]; +}; + +static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb) +{ + return (struct can_skb_priv *)(skb->head); +} + +static inline void can_skb_reserve(struct sk_buff *skb) +{ + skb_reserve(skb, sizeof(struct can_skb_priv)); +} + +static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) +{ + if (sk) { + sock_hold(sk); + skb->destructor = sock_efree; + skb->sk = sk; + } +} + +/* + * returns an unshared skb owned by the original sock to be echo'ed back + */ +static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) +{ + if (skb_shared(skb)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + + if (likely(nskb)) { + can_skb_set_owner(nskb, skb->sk); + consume_skb(skb); + return nskb; + } else { + kfree_skb(skb); + return NULL; + } + } + + /* we can assume to have an unshared skb with proper owner */ + return skb; +} + +#endif /* !_CAN_SKB_H */ |