diff --git a/Documentation/ABI/testing/sysfs-class-net-peak_usb b/Documentation/ABI/testing/sysfs-class-net-peak_usb new file mode 100644 index 000000000000..9e3d0bf4d4b2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-net-peak_usb @@ -0,0 +1,19 @@ + +What: /sys/class/net//peak_usb/can_channel_id +Date: November 2022 +KernelVersion: 6.2 +Contact: Stephane Grosjean +Description: + PEAK PCAN-USB devices support user-configurable CAN channel + identifiers. Contrary to a USB serial number, these identifiers + are writable and can be set per CAN interface. This means that + if a USB device exports multiple CAN interfaces, each of them + can be assigned a unique channel ID. + This attribute provides read-only access to the currently + configured value of the channel identifier. Depending on the + device type, the identifier has a length of 8 or 32 bit. The + value read from this attribute is always an 8 digit 32 bit + hexadecimal value in big endian format. If the device only + supports an 8 bit identifier, the upper 24 bit of the value are + set to zero. + diff --git a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml index 1eb98c9a1a26..d3f45d29fa0a 100644 --- a/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml +++ b/Documentation/devicetree/bindings/net/can/renesas,rcar-canfd.yaml @@ -28,6 +28,12 @@ properties: - renesas,r8a77995-canfd # R-Car D3 - const: renesas,rcar-gen3-canfd # R-Car Gen3 and RZ/G2 + - items: + - enum: + - renesas,r8a779a0-canfd # R-Car V3U + - renesas,r8a779g0-canfd # R-Car V4H + - const: renesas,rcar-gen4-canfd # R-Car Gen4 + - items: - enum: - renesas,r9a07g043-canfd # RZ/G2UL and RZ/Five @@ -35,8 +41,6 @@ properties: - renesas,r9a07g054-canfd # RZ/V2L - const: renesas,rzg2l-canfd # RZ/G2L family - - const: renesas,r8a779a0-canfd # R-Car V3U - reg: maxItems: 1 @@ -60,7 +64,7 @@ properties: $ref: /schemas/types.yaml#/definitions/flag description: The controller can operate in either CAN FD only mode (default) or - Classical CAN only mode. The mode is global to both the channels. + Classical CAN only mode. The mode is global to all channels. Specify this property to put the controller in Classical CAN only mode. assigned-clocks: @@ -80,6 +84,10 @@ patternProperties: The controller supports multiple channels and each is represented as a child node. Each channel can be enabled/disabled individually. + properties: + phys: + maxItems: 1 + additionalProperties: false required: @@ -159,7 +167,7 @@ allOf: properties: compatible: contains: - const: renesas,r8a779a0-canfd + const: renesas,rcar-gen4-canfd then: patternProperties: "^channel[2-7]$": false diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c index 7ae80763c960..0b93900b1dfa 100644 --- a/drivers/net/can/dev/bittiming.c +++ b/drivers/net/can/dev/bittiming.c @@ -6,25 +6,81 @@ #include +void can_sjw_set_default(struct can_bittiming *bt) +{ + if (bt->sjw) + return; + + /* If user space provides no sjw, use sane default of phase_seg2 / 2 */ + bt->sjw = max(1U, min(bt->phase_seg1, bt->phase_seg2 / 2)); +} + +int can_sjw_check(const struct net_device *dev, const struct can_bittiming *bt, + const struct can_bittiming_const *btc, struct netlink_ext_ack *extack) +{ + if (bt->sjw > btc->sjw_max) { + NL_SET_ERR_MSG_FMT(extack, "sjw: %u greater than max sjw: %u", + bt->sjw, btc->sjw_max); + return -EINVAL; + } + + if (bt->sjw > bt->phase_seg1) { + NL_SET_ERR_MSG_FMT(extack, + "sjw: %u greater than phase-seg1: %u", + bt->sjw, bt->phase_seg1); + return -EINVAL; + } + + if (bt->sjw > bt->phase_seg2) { + NL_SET_ERR_MSG_FMT(extack, + "sjw: %u greater than phase-seg2: %u", + bt->sjw, bt->phase_seg2); + return -EINVAL; + } + + return 0; +} + /* Checks the validity of the specified bit-timing parameters prop_seg, * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate * prescaler value brp. You can find more information in the header * file linux/can/netlink.h. */ static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) + const struct can_bittiming_const *btc, + struct netlink_ext_ack *extack) { + const unsigned int tseg1 = bt->prop_seg + bt->phase_seg1; const struct can_priv *priv = netdev_priv(dev); - unsigned int tseg1, alltseg; u64 brp64; + int err; - tseg1 = bt->prop_seg + bt->phase_seg1; - if (!bt->sjw) - bt->sjw = 1; - if (bt->sjw > btc->sjw_max || - tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max || - bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max) - return -ERANGE; + if (tseg1 < btc->tseg1_min) { + NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u less than tseg1-min: %u", + tseg1, btc->tseg1_min); + return -EINVAL; + } + if (tseg1 > btc->tseg1_max) { + NL_SET_ERR_MSG_FMT(extack, "prop-seg + phase-seg1: %u greater than tseg1-max: %u", + tseg1, btc->tseg1_max); + return -EINVAL; + } + if (bt->phase_seg2 < btc->tseg2_min) { + NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u less than tseg2-min: %u", + bt->phase_seg2, btc->tseg2_min); + return -EINVAL; + } + if (bt->phase_seg2 > btc->tseg2_max) { + NL_SET_ERR_MSG_FMT(extack, "phase-seg2: %u greater than tseg2-max: %u", + bt->phase_seg2, btc->tseg2_max); + return -EINVAL; + } + + can_sjw_set_default(bt); + + err = can_sjw_check(dev, bt, btc, extack); + if (err) + return err; brp64 = (u64)priv->clock.freq * (u64)bt->tq; if (btc->brp_inc > 1) @@ -35,12 +91,21 @@ static int can_fixup_bittiming(const struct net_device *dev, struct can_bittimin brp64 *= btc->brp_inc; bt->brp = (u32)brp64; - if (bt->brp < btc->brp_min || bt->brp > btc->brp_max) + if (bt->brp < btc->brp_min) { + NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u less than brp-min: %u", + bt->brp, btc->brp_min); return -EINVAL; + } + if (bt->brp > btc->brp_max) { + NL_SET_ERR_MSG_FMT(extack, "resulting brp: %u greater than brp-max: %u", + bt->brp, btc->brp_max); + return -EINVAL; + } - alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1; - bt->bitrate = priv->clock.freq / (bt->brp * alltseg); - bt->sample_point = ((tseg1 + 1) * 1000) / alltseg; + bt->bitrate = priv->clock.freq / (bt->brp * can_bit_time(bt)); + bt->sample_point = ((CAN_SYNC_SEG + tseg1) * 1000) / can_bit_time(bt); + bt->tq = DIV_U64_ROUND_CLOSEST(mul_u32_u32(bt->brp, NSEC_PER_SEC), + priv->clock.freq); return 0; } @@ -49,7 +114,8 @@ static int can_fixup_bittiming(const struct net_device *dev, struct can_bittimin static int can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *bt, const u32 *bitrate_const, - const unsigned int bitrate_const_cnt) + const unsigned int bitrate_const_cnt, + struct netlink_ext_ack *extack) { unsigned int i; @@ -58,30 +124,30 @@ can_validate_bitrate(const struct net_device *dev, const struct can_bittiming *b return 0; } + NL_SET_ERR_MSG_FMT(extack, "bitrate %u bps not supported", + bt->brp); + return -EINVAL; } int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc, const u32 *bitrate_const, - const unsigned int bitrate_const_cnt) + const unsigned int bitrate_const_cnt, + struct netlink_ext_ack *extack) { - int err; - /* Depending on the given can_bittiming parameter structure the CAN * timing parameters are calculated based on the provided bitrate OR * alternatively the CAN timing parameters (tq, prop_seg, etc.) are * provided directly which are then checked and fixed up. */ if (!bt->tq && bt->bitrate && btc) - err = can_calc_bittiming(dev, bt, btc); - else if (bt->tq && !bt->bitrate && btc) - err = can_fixup_bittiming(dev, bt, btc); - else if (!bt->tq && bt->bitrate && bitrate_const) - err = can_validate_bitrate(dev, bt, bitrate_const, - bitrate_const_cnt); - else - err = -EINVAL; + return can_calc_bittiming(dev, bt, btc, extack); + if (bt->tq && !bt->bitrate && btc) + return can_fixup_bittiming(dev, bt, btc, extack); + if (!bt->tq && bt->bitrate && bitrate_const) + return can_validate_bitrate(dev, bt, bitrate_const, + bitrate_const_cnt, extack); - return err; + return -EINVAL; } diff --git a/drivers/net/can/dev/calc_bittiming.c b/drivers/net/can/dev/calc_bittiming.c index d3caa040614d..3809c148fb88 100644 --- a/drivers/net/can/dev/calc_bittiming.c +++ b/drivers/net/can/dev/calc_bittiming.c @@ -63,7 +63,7 @@ can_update_sample_point(const struct can_bittiming_const *btc, } int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) + const struct can_bittiming_const *btc, struct netlink_ext_ack *extack) { struct can_priv *priv = netdev_priv(dev); unsigned int bitrate; /* current bitrate */ @@ -76,6 +76,7 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, unsigned int best_brp = 0; /* current best value for brp */ unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0; u64 v64; + int err; /* Use CiA recommended sample points */ if (bt->sample_point) { @@ -133,13 +134,14 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, do_div(v64, bt->bitrate); bitrate_error = (u32)v64; if (bitrate_error > CAN_CALC_MAX_ERROR) { - netdev_err(dev, - "bitrate error %d.%d%% too high\n", - bitrate_error / 10, bitrate_error % 10); - return -EDOM; + NL_SET_ERR_MSG_FMT(extack, + "bitrate error: %u.%u%% too high", + bitrate_error / 10, bitrate_error % 10); + return -EINVAL; } - netdev_warn(dev, "bitrate error %d.%d%%\n", - bitrate_error / 10, bitrate_error % 10); + NL_SET_ERR_MSG_FMT(extack, + "bitrate error: %u.%u%%", + bitrate_error / 10, bitrate_error % 10); } /* real sample point */ @@ -154,23 +156,17 @@ int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, bt->phase_seg1 = tseg1 - bt->prop_seg; bt->phase_seg2 = tseg2; - /* check for sjw user settings */ - if (!bt->sjw || !btc->sjw_max) { - bt->sjw = 1; - } else { - /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ - if (bt->sjw > btc->sjw_max) - bt->sjw = btc->sjw_max; - /* bt->sjw must not be higher than tseg2 */ - if (tseg2 < bt->sjw) - bt->sjw = tseg2; - } + can_sjw_set_default(bt); + + err = can_sjw_check(dev, bt, btc, extack); + if (err) + return err; bt->brp = best_brp; /* real bitrate */ bt->bitrate = priv->clock.freq / - (bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2)); + (bt->brp * can_bit_time(bt)); return 0; } diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c index c1956b1e9faf..7f9334a8af50 100644 --- a/drivers/net/can/dev/dev.c +++ b/drivers/net/can/dev/dev.c @@ -498,6 +498,18 @@ static int can_get_termination(struct net_device *ndev) return 0; } +static bool +can_bittiming_const_valid(const struct can_bittiming_const *btc) +{ + if (!btc) + return true; + + if (!btc->sjw_max) + return false; + + return true; +} + /* Register the CAN network device */ int register_candev(struct net_device *dev) { @@ -518,6 +530,15 @@ int register_candev(struct net_device *dev) if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt) return -EINVAL; + /* We only support either fixed bit rates or bit timing const. */ + if ((priv->bitrate_const || priv->data_bitrate_const) && + (priv->bittiming_const || priv->data_bittiming_const)) + return -EINVAL; + + if (!can_bittiming_const_valid(priv->bittiming_const) || + !can_bittiming_const_valid(priv->data_bittiming_const)) + return -EINVAL; + if (!priv->termination_const) { err = can_get_termination(dev); if (err) diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 8efa22d9f214..036d85ef07f5 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -36,10 +36,24 @@ static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { [IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 }, }; +static int can_validate_bittiming(const struct can_bittiming *bt, + struct netlink_ext_ack *extack) +{ + /* sample point is in one-tenth of a percent */ + if (bt->sample_point >= 1000) { + NL_SET_ERR_MSG(extack, "sample point must be between 0 and 100%"); + + return -EINVAL; + } + + return 0; +} + static int can_validate(struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { bool is_can_fd = false; + int err; /* Make sure that valid CAN FD configurations always consist of * - nominal/arbitration bittiming @@ -51,6 +65,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], if (!data) return 0; + if (data[IFLA_CAN_BITTIMING]) { + struct can_bittiming bt; + + memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); + err = can_validate_bittiming(&bt, extack); + if (err) + return err; + } + if (data[IFLA_CAN_CTRLMODE]) { struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK; @@ -71,7 +94,6 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], */ if (data[IFLA_CAN_TDC]) { struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; - int err; err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, data[IFLA_CAN_TDC], @@ -102,6 +124,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], return -EOPNOTSUPP; } + if (data[IFLA_CAN_DATA_BITTIMING]) { + struct can_bittiming bt; + + memcpy(&bt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), sizeof(bt)); + err = can_validate_bittiming(&bt, extack); + if (err) + return err; + } + return 0; } @@ -184,13 +215,15 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], err = can_get_bittiming(dev, &bt, priv->bittiming_const, priv->bitrate_const, - priv->bitrate_const_cnt); + priv->bitrate_const_cnt, + extack); if (err) return err; if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) { - netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n", - priv->bitrate_max); + NL_SET_ERR_MSG_FMT(extack, + "arbitration bitrate %u bps surpasses transceiver capabilities of %u bps", + bt.bitrate, priv->bitrate_max); return -EINVAL; } @@ -288,13 +321,15 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], err = can_get_bittiming(dev, &dbt, priv->data_bittiming_const, priv->data_bitrate_const, - priv->data_bitrate_const_cnt); + priv->data_bitrate_const_cnt, + extack); if (err) return err; if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) { - netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n", - priv->bitrate_max); + NL_SET_ERR_MSG_FMT(extack, + "CANFD data bitrate %u bps surpasses transceiver capabilities of %u bps", + dbt.bitrate, priv->bitrate_max); return -EINVAL; } diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index f6fa7157b99b..ef4e1b9a9e1e 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -21,23 +21,23 @@ * wherever it is modified to a readable name. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #define RCANFD_DRV_NAME "rcar_canfd" @@ -82,8 +82,8 @@ #define RCANFD_GERFL_DEF BIT(0) #define RCANFD_GERFL_ERR(gpriv, x) \ - ((x) & (reg_v3u(gpriv, RCANFD_GERFL_EEF0_7, \ - RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \ + ((x) & (reg_gen4(gpriv, RCANFD_GERFL_EEF0_7, \ + RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \ RCANFD_GERFL_MES | \ ((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))) @@ -91,16 +91,16 @@ /* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */ #define RCANFD_GAFLCFG_SETRNC(gpriv, n, x) \ - (((x) & reg_v3u(gpriv, 0x1ff, 0xff)) << \ - (reg_v3u(gpriv, 16, 24) - (n) * reg_v3u(gpriv, 16, 8))) + (((x) & reg_gen4(gpriv, 0x1ff, 0xff)) << \ + (reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8))) #define RCANFD_GAFLCFG_GETRNC(gpriv, n, x) \ - (((x) >> (reg_v3u(gpriv, 16, 24) - (n) * reg_v3u(gpriv, 16, 8))) & \ - reg_v3u(gpriv, 0x1ff, 0xff)) + (((x) >> (reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8))) & \ + reg_gen4(gpriv, 0x1ff, 0xff)) /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ #define RCANFD_GAFLECTR_AFLDAE BIT(8) -#define RCANFD_GAFLECTR_AFLPN(gpriv, x) ((x) & reg_v3u(gpriv, 0x7f, 0x1f)) +#define RCANFD_GAFLECTR_AFLPN(gpriv, x) ((x) & reg_gen4(gpriv, 0x7f, 0x1f)) /* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ #define RCANFD_GAFLID_GAFLLB BIT(29) @@ -118,13 +118,13 @@ /* RSCFDnCFDCmNCFG - CAN FD only */ #define RCANFD_NCFG_NTSEG2(gpriv, x) \ - (((x) & reg_v3u(gpriv, 0x7f, 0x1f)) << reg_v3u(gpriv, 25, 24)) + (((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 25, 24)) #define RCANFD_NCFG_NTSEG1(gpriv, x) \ - (((x) & reg_v3u(gpriv, 0xff, 0x7f)) << reg_v3u(gpriv, 17, 16)) + (((x) & reg_gen4(gpriv, 0xff, 0x7f)) << reg_gen4(gpriv, 17, 16)) #define RCANFD_NCFG_NSJW(gpriv, x) \ - (((x) & reg_v3u(gpriv, 0x7f, 0x1f)) << reg_v3u(gpriv, 10, 11)) + (((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 10, 11)) #define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0) @@ -186,19 +186,19 @@ #define RCANFD_CERFL_ERR(x) ((x) & (0x7fff)) /* above bits 14:0 */ /* RSCFDnCFDCmDCFG */ -#define RCANFD_DCFG_DSJW(x) (((x) & 0x7) << 24) +#define RCANFD_DCFG_DSJW(gpriv, x) (((x) & reg_gen4(gpriv, 0xf, 0x7)) << 24) #define RCANFD_DCFG_DTSEG2(gpriv, x) \ - (((x) & reg_v3u(gpriv, 0x0f, 0x7)) << reg_v3u(gpriv, 16, 20)) + (((x) & reg_gen4(gpriv, 0x0f, 0x7)) << reg_gen4(gpriv, 16, 20)) #define RCANFD_DCFG_DTSEG1(gpriv, x) \ - (((x) & reg_v3u(gpriv, 0x1f, 0xf)) << reg_v3u(gpriv, 8, 16)) + (((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 8, 16)) #define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0) /* RSCFDnCFDCmFDCFG */ -#define RCANFD_FDCFG_CLOE BIT(30) -#define RCANFD_FDCFG_FDOE BIT(28) +#define RCANFD_GEN4_FDCFG_CLOE BIT(30) +#define RCANFD_GEN4_FDCFG_FDOE BIT(28) #define RCANFD_FDCFG_TDCE BIT(9) #define RCANFD_FDCFG_TDCOC BIT(8) #define RCANFD_FDCFG_TDCO(x) (((x) & 0x7f) >> 16) @@ -233,10 +233,11 @@ /* Common FIFO bits */ /* RSCFDnCFDCFCCk */ -#define RCANFD_CFCC_CFTML(gpriv, x) (((x) & 0xf) << reg_v3u(gpriv, 16, 20)) -#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << reg_v3u(gpriv, 8, 16)) +#define RCANFD_CFCC_CFTML(gpriv, x) \ + (((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 16, 20)) +#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << reg_gen4(gpriv, 8, 16)) #define RCANFD_CFCC_CFIM BIT(12) -#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << reg_v3u(gpriv, 21, 8)) +#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << reg_gen4(gpriv, 21, 8)) #define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4) #define RCANFD_CFCC_CFTXIE BIT(2) #define RCANFD_CFCC_CFE BIT(0) @@ -304,7 +305,7 @@ #define RCANFD_RMND(y) (0x00a8 + (0x04 * (y))) /* RSCFDnCFDRFCCx / RSCFDnRFCCx */ -#define RCANFD_RFCC(gpriv, x) (reg_v3u(gpriv, 0x00c0, 0x00b8) + (0x04 * (x))) +#define RCANFD_RFCC(gpriv, x) (reg_gen4(gpriv, 0x00c0, 0x00b8) + (0x04 * (x))) /* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */ #define RCANFD_RFSTS(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x20) /* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */ @@ -314,13 +315,13 @@ /* RSCFDnCFDCFCCx / RSCFDnCFCCx */ #define RCANFD_CFCC(gpriv, ch, idx) \ - (reg_v3u(gpriv, 0x0120, 0x0118) + (0x0c * (ch)) + (0x04 * (idx))) + (reg_gen4(gpriv, 0x0120, 0x0118) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */ #define RCANFD_CFSTS(gpriv, ch, idx) \ - (reg_v3u(gpriv, 0x01e0, 0x0178) + (0x0c * (ch)) + (0x04 * (idx))) + (reg_gen4(gpriv, 0x01e0, 0x0178) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */ #define RCANFD_CFPCTR(gpriv, ch, idx) \ - (reg_v3u(gpriv, 0x0240, 0x01d8) + (0x0c * (ch)) + (0x04 * (idx))) + (reg_gen4(gpriv, 0x0240, 0x01d8) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDFESTS / RSCFDnFESTS */ #define RCANFD_FESTS (0x0238) @@ -428,16 +429,15 @@ /* RSCFDnRPGACCr */ #define RCANFD_C_RPGACC(r) (0x1900 + (0x04 * (r))) -/* R-Car V3U Classical and CAN FD mode specific register map */ -#define RCANFD_V3U_CFDCFG (0x1314) -#define RCANFD_V3U_DCFG(m) (0x1400 + (0x20 * (m))) +/* R-Car Gen4 Classical and CAN FD mode specific register map */ +#define RCANFD_GEN4_FDCFG(m) (0x1404 + (0x20 * (m))) -#define RCANFD_V3U_GAFL_OFFSET (0x1800) +#define RCANFD_GEN4_GAFL_OFFSET (0x1800) /* CAN FD mode specific register map */ /* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ -#define RCANFD_F_DCFG(m) (0x0500 + (0x20 * (m))) +#define RCANFD_F_DCFG(gpriv, m) (reg_gen4(gpriv, 0x1400, 0x0500) + (0x20 * (m))) #define RCANFD_F_CFDCFG(m) (0x0504 + (0x20 * (m))) #define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m))) #define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m))) @@ -453,7 +453,7 @@ #define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q))) /* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */ -#define RCANFD_F_RFOFFSET(gpriv) reg_v3u(gpriv, 0x6000, 0x3000) +#define RCANFD_F_RFOFFSET(gpriv) reg_gen4(gpriv, 0x6000, 0x3000) #define RCANFD_F_RFID(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + (0x80 * (x))) #define RCANFD_F_RFPTR(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x04 + (0x80 * (x))) #define RCANFD_F_RFFDSTS(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x08 + (0x80 * (x))) @@ -461,7 +461,7 @@ (RCANFD_F_RFOFFSET(gpriv) + 0x0c + (0x80 * (x)) + (0x04 * (df))) /* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */ -#define RCANFD_F_CFOFFSET(gpriv) reg_v3u(gpriv, 0x6400, 0x3400) +#define RCANFD_F_CFOFFSET(gpriv) reg_gen4(gpriv, 0x6400, 0x3400) #define RCANFD_F_CFID(gpriv, ch, idx) \ (RCANFD_F_CFOFFSET(gpriv) + (0x180 * (ch)) + (0x80 * (idx))) @@ -597,28 +597,28 @@ static const struct rcar_canfd_hw_info rcar_gen3_hw_info = { .shared_global_irqs = 1, }; +static const struct rcar_canfd_hw_info rcar_gen4_hw_info = { + .max_channels = 8, + .postdiv = 2, + .shared_global_irqs = 1, +}; + static const struct rcar_canfd_hw_info rzg2l_hw_info = { .max_channels = 2, .postdiv = 1, .multi_channel_irqs = 1, }; -static const struct rcar_canfd_hw_info r8a779a0_hw_info = { - .max_channels = 8, - .postdiv = 2, - .shared_global_irqs = 1, -}; - /* Helper functions */ -static inline bool is_v3u(struct rcar_canfd_global *gpriv) +static inline bool is_gen4(struct rcar_canfd_global *gpriv) { - return gpriv->info == &r8a779a0_hw_info; + return gpriv->info == &rcar_gen4_hw_info; } -static inline u32 reg_v3u(struct rcar_canfd_global *gpriv, - u32 v3u, u32 not_v3u) +static inline u32 reg_gen4(struct rcar_canfd_global *gpriv, + u32 gen4, u32 not_gen4) { - return is_v3u(gpriv) ? v3u : not_v3u; + return is_gen4(gpriv) ? gen4 : not_gen4; } static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg) @@ -688,13 +688,14 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) { - if (is_v3u(gpriv)) { - if (gpriv->fdmode) - rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG, - RCANFD_FDCFG_FDOE); - else - rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG, - RCANFD_FDCFG_CLOE); + if (is_gen4(gpriv)) { + u32 ch, val = gpriv->fdmode ? RCANFD_GEN4_FDCFG_FDOE + : RCANFD_GEN4_FDCFG_CLOE; + + for_each_set_bit(ch, &gpriv->channels_mask, + gpriv->info->max_channels) + rcar_canfd_set_bit(gpriv->base, RCANFD_GEN4_FDCFG(ch), + val); } else { if (gpriv->fdmode) rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, @@ -814,8 +815,8 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, /* Write number of rules for channel */ rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(ch), RCANFD_GAFLCFG_SETRNC(gpriv, ch, num_rules)); - if (is_v3u(gpriv)) - offset = RCANFD_V3U_GAFL_OFFSET; + if (is_gen4(gpriv)) + offset = RCANFD_GEN4_GAFL_OFFSET; else if (gpriv->fdmode) offset = RCANFD_F_GAFL_OFFSET; else @@ -1343,17 +1344,14 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) tseg2 = dbt->phase_seg2 - 1; cfg = (RCANFD_DCFG_DTSEG1(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) | - RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2)); + RCANFD_DCFG_DSJW(gpriv, sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2)); - if (is_v3u(gpriv)) - rcar_canfd_write(priv->base, RCANFD_V3U_DCFG(ch), cfg); - else - rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg); + rcar_canfd_write(priv->base, RCANFD_F_DCFG(gpriv, ch), cfg); netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", brp, sjw, tseg1, tseg2); } else { /* Classical CAN only mode */ - if (is_v3u(gpriv)) { + if (is_gen4(gpriv)) { cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) | RCANFD_NCFG_NBRP(brp) | RCANFD_NCFG_NSJW(gpriv, sjw) | @@ -1510,7 +1508,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, dlc = RCANFD_CFPTR_CFDLC(can_fd_len2dlc(cf->len)); - if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_v3u(gpriv)) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) { rcar_canfd_write(priv->base, RCANFD_F_CFID(gpriv, ch, RCANFD_CFFIFO_IDX), id); rcar_canfd_write(priv->base, @@ -1569,7 +1567,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) u32 ch = priv->channel; u32 ridx = ch + RCANFD_RFFIFO_IDX; - if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_v3u(gpriv)) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) { id = rcar_canfd_read(priv->base, RCANFD_F_RFID(gpriv, ridx)); dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(gpriv, ridx)); @@ -1620,7 +1618,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) cf->len = can_cc_dlc2len(RCANFD_RFPTR_RFDLC(dlc)); if (id & RCANFD_RFID_RFRTR) cf->can_id |= CAN_RTR_FLAG; - else if (is_v3u(gpriv)) + else if (is_gen4(gpriv)) rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0)); else rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0)); @@ -1717,13 +1715,14 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, { const struct rcar_canfd_hw_info *info = gpriv->info; struct platform_device *pdev = gpriv->pdev; + struct device *dev = &pdev->dev; struct rcar_canfd_channel *priv; struct net_device *ndev; int err = -ENODEV; ndev = alloc_candev(sizeof(*priv), RCANFD_FIFO_DEPTH); if (!ndev) { - dev_err(&pdev->dev, "alloc_candev() failed\n"); + dev_err(dev, "alloc_candev() failed\n"); return -ENOMEM; } priv = netdev_priv(ndev); @@ -1736,7 +1735,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, priv->channel = ch; priv->gpriv = gpriv; priv->can.clock.freq = fcan_freq; - dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); + dev_info(dev, "can_clk rate is %u\n", priv->can.clock.freq); if (info->multi_channel_irqs) { char *irq_name; @@ -1755,31 +1754,31 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, goto fail; } - irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, - "canfd.ch%d_err", ch); + irq_name = devm_kasprintf(dev, GFP_KERNEL, "canfd.ch%d_err", + ch); if (!irq_name) { err = -ENOMEM; goto fail; } - err = devm_request_irq(&pdev->dev, err_irq, + err = devm_request_irq(dev, err_irq, rcar_canfd_channel_err_interrupt, 0, irq_name, priv); if (err) { - dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n", + dev_err(dev, "devm_request_irq CH Err(%d) failed, error %d\n", err_irq, err); goto fail; } - irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, - "canfd.ch%d_trx", ch); + irq_name = devm_kasprintf(dev, GFP_KERNEL, "canfd.ch%d_trx", + ch); if (!irq_name) { err = -ENOMEM; goto fail; } - err = devm_request_irq(&pdev->dev, tx_irq, + err = devm_request_irq(dev, tx_irq, rcar_canfd_channel_tx_interrupt, 0, irq_name, priv); if (err) { - dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n", + dev_err(dev, "devm_request_irq Tx (%d) failed, error %d\n", tx_irq, err); goto fail; } @@ -1803,7 +1802,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, priv->can.do_set_mode = rcar_canfd_do_set_mode; priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; - SET_NETDEV_DEV(ndev, &pdev->dev); + SET_NETDEV_DEV(ndev, dev); netif_napi_add_weight(ndev, &priv->napi, rcar_canfd_rx_poll, RCANFD_NAPI_WEIGHT); @@ -1811,11 +1810,10 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, gpriv->ch[priv->channel] = priv; err = register_candev(ndev); if (err) { - dev_err(&pdev->dev, - "register_candev() failed, error %d\n", err); + dev_err(dev, "register_candev() failed, error %d\n", err); goto fail_candev; } - dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel); + dev_info(dev, "device registered (channel %u)\n", priv->channel); return 0; fail_candev: @@ -1839,6 +1837,7 @@ static void rcar_canfd_channel_remove(struct rcar_canfd_global *gpriv, u32 ch) static int rcar_canfd_probe(struct platform_device *pdev) { const struct rcar_canfd_hw_info *info; + struct device *dev = &pdev->dev; void __iomem *addr; u32 sts, ch, fcan_freq; struct rcar_canfd_global *gpriv; @@ -1850,14 +1849,14 @@ static int rcar_canfd_probe(struct platform_device *pdev) char name[9] = "channelX"; int i; - info = of_device_get_match_data(&pdev->dev); + info = of_device_get_match_data(dev); - if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd")) + if (of_property_read_bool(dev->of_node, "renesas,no-can-fd")) fdmode = false; /* Classical CAN only mode */ for (i = 0; i < info->max_channels; ++i) { name[7] = '0' + i; - of_child = of_get_child_by_name(pdev->dev.of_node, name); + of_child = of_get_child_by_name(dev->of_node, name); if (of_child && of_device_is_available(of_child)) channels_mask |= BIT(i); of_node_put(of_child); @@ -1890,7 +1889,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) } /* Global controller context */ - gpriv = devm_kzalloc(&pdev->dev, sizeof(*gpriv), GFP_KERNEL); + gpriv = devm_kzalloc(dev, sizeof(*gpriv), GFP_KERNEL); if (!gpriv) return -ENOMEM; @@ -1899,32 +1898,30 @@ static int rcar_canfd_probe(struct platform_device *pdev) gpriv->fdmode = fdmode; gpriv->info = info; - gpriv->rstc1 = devm_reset_control_get_optional_exclusive(&pdev->dev, - "rstp_n"); + gpriv->rstc1 = devm_reset_control_get_optional_exclusive(dev, "rstp_n"); if (IS_ERR(gpriv->rstc1)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc1), + return dev_err_probe(dev, PTR_ERR(gpriv->rstc1), "failed to get rstp_n\n"); - gpriv->rstc2 = devm_reset_control_get_optional_exclusive(&pdev->dev, - "rstc_n"); + gpriv->rstc2 = devm_reset_control_get_optional_exclusive(dev, "rstc_n"); if (IS_ERR(gpriv->rstc2)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->rstc2), + return dev_err_probe(dev, PTR_ERR(gpriv->rstc2), "failed to get rstc_n\n"); /* Peripheral clock */ - gpriv->clkp = devm_clk_get(&pdev->dev, "fck"); + gpriv->clkp = devm_clk_get(dev, "fck"); if (IS_ERR(gpriv->clkp)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->clkp), + return dev_err_probe(dev, PTR_ERR(gpriv->clkp), "cannot get peripheral clock\n"); /* fCAN clock: Pick External clock. If not available fallback to * CANFD clock */ - gpriv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); + gpriv->can_clk = devm_clk_get(dev, "can_clk"); if (IS_ERR(gpriv->can_clk) || (clk_get_rate(gpriv->can_clk) == 0)) { - gpriv->can_clk = devm_clk_get(&pdev->dev, "canfd"); + gpriv->can_clk = devm_clk_get(dev, "canfd"); if (IS_ERR(gpriv->can_clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(gpriv->can_clk), + return dev_err_probe(dev, PTR_ERR(gpriv->can_clk), "cannot get canfd clock\n"); gpriv->fcan = RCANFD_CANFDCLK; @@ -1947,39 +1944,38 @@ static int rcar_canfd_probe(struct platform_device *pdev) /* Request IRQ that's common for both channels */ if (info->shared_global_irqs) { - err = devm_request_irq(&pdev->dev, ch_irq, + err = devm_request_irq(dev, ch_irq, rcar_canfd_channel_interrupt, 0, "canfd.ch_int", gpriv); if (err) { - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", + dev_err(dev, "devm_request_irq(%d) failed, error %d\n", ch_irq, err); goto fail_dev; } - err = devm_request_irq(&pdev->dev, g_irq, - rcar_canfd_global_interrupt, 0, - "canfd.g_int", gpriv); + err = devm_request_irq(dev, g_irq, rcar_canfd_global_interrupt, + 0, "canfd.g_int", gpriv); if (err) { - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", + dev_err(dev, "devm_request_irq(%d) failed, error %d\n", g_irq, err); goto fail_dev; } } else { - err = devm_request_irq(&pdev->dev, g_recc_irq, + err = devm_request_irq(dev, g_recc_irq, rcar_canfd_global_receive_fifo_interrupt, 0, "canfd.g_recc", gpriv); if (err) { - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", + dev_err(dev, "devm_request_irq(%d) failed, error %d\n", g_recc_irq, err); goto fail_dev; } - err = devm_request_irq(&pdev->dev, g_err_irq, + err = devm_request_irq(dev, g_err_irq, rcar_canfd_global_err_interrupt, 0, "canfd.g_err", gpriv); if (err) { - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", + dev_err(dev, "devm_request_irq(%d) failed, error %d\n", g_err_irq, err); goto fail_dev; } @@ -1997,14 +1993,14 @@ static int rcar_canfd_probe(struct platform_device *pdev) /* Enable peripheral clock for register access */ err = clk_prepare_enable(gpriv->clkp); if (err) { - dev_err(&pdev->dev, - "failed to enable peripheral clock, error %d\n", err); + dev_err(dev, "failed to enable peripheral clock, error %d\n", + err); goto fail_reset; } err = rcar_canfd_reset_controller(gpriv); if (err) { - dev_err(&pdev->dev, "reset controller failed\n"); + dev_err(dev, "reset controller failed\n"); goto fail_clk; } @@ -2034,7 +2030,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, !(sts & RCANFD_GSTS_GNOPM), 2, 500000); if (err) { - dev_err(&pdev->dev, "global operational mode failed\n"); + dev_err(dev, "global operational mode failed\n"); goto fail_mode; } @@ -2045,7 +2041,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, gpriv); - dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n", + dev_info(dev, "global operational state (clk %d, fdmode %d)\n", gpriv->fcan, gpriv->fdmode); return 0; @@ -2099,9 +2095,10 @@ static SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend, rcar_canfd_resume); static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = { + { .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info }, { .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info }, + { .compatible = "renesas,rcar-gen4-canfd", .data = &rcar_gen4_hw_info }, { .compatible = "renesas,rzg2l-canfd", .data = &rzg2l_hw_info }, - { .compatible = "renesas,r8a779a0-canfd", .data = &r8a779a0_hw_info }, { } }; diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 4ab91759a5c6..c56e27223e5f 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -3,6 +3,7 @@ * Copyright (C) 2007 Wolfgang Grandegger * Copyright (C) 2008 Markus Plessing * Copyright (C) 2008 Sebastian Haas + * Copyright (C) 2023 EMS Dr. Thomas Wuensche */ #include @@ -19,12 +20,14 @@ #define DRV_NAME "ems_pci" -MODULE_AUTHOR("Sebastian Haas "); +MODULE_AUTHOR("Sebastian Haas "); +MODULE_AUTHOR("Gerhard Uttenthaler "); MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe/104P CAN cards"); MODULE_LICENSE("GPL v2"); #define EMS_PCI_V1_MAX_CHAN 2 #define EMS_PCI_V2_MAX_CHAN 4 +#define EMS_PCI_V3_MAX_CHAN 4 #define EMS_PCI_MAX_CHAN EMS_PCI_V2_MAX_CHAN struct ems_pci_card { @@ -40,8 +43,7 @@ struct ems_pci_card { #define EMS_PCI_CAN_CLOCK (16000000 / 2) -/* - * Register definitions and descriptions are from LinCAN 0.3.3. +/* Register definitions and descriptions are from LinCAN 0.3.3. * * PSB4610 PITA-2 bridge control registers */ @@ -52,8 +54,7 @@ struct ems_pci_card { #define PITA2_MISC 0x1c /* Miscellaneous Register */ #define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */ -/* - * Register definitions for the PLX 9030 +/* Register definitions for the PLX 9030 */ #define PLX_ICSR 0x4c /* Interrupt Control/Status register */ #define PLX_ICSR_LINTI1_ENA 0x0001 /* LINTi1 Enable */ @@ -62,8 +63,16 @@ struct ems_pci_card { #define PLX_ICSR_ENA_CLR (PLX_ICSR_LINTI1_ENA | PLX_ICSR_PCIINT_ENA | \ PLX_ICSR_LINTI1_CLR) -/* - * The board configuration is probably following: +/* Register definitions for the ASIX99100 + */ +#define ASIX_LINTSR 0x28 /* Interrupt Control/Status register */ +#define ASIX_LINTSR_INT0AC BIT(0) /* Writing 1 enables or clears interrupt */ + +#define ASIX_LIEMR 0x24 /* Local Interrupt Enable / Miscellaneous Register */ +#define ASIX_LIEMR_L0EINTEN BIT(16) /* Local INT0 input assertion enable */ +#define ASIX_LIEMR_LRST BIT(14) /* Local Reset assert */ + +/* The board configuration is probably following: * RX1 is connected to ground. * TX1 is not connected. * CLKO is not connected. @@ -72,23 +81,40 @@ struct ems_pci_card { */ #define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) -/* - * In the CDR register, you should set CBP to 1. +/* In the CDR register, you should set CBP to 1. * You will probably also want to set the clock divider value to 7 * (meaning direct oscillator output) because the second SJA1000 chip * is driven by the first one CLKOUT output. */ #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) -#define EMS_PCI_V1_BASE_BAR 1 -#define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */ -#define EMS_PCI_V2_BASE_BAR 2 -#define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */ -#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ -#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ +#define EMS_PCI_V1_BASE_BAR 1 +#define EMS_PCI_V1_CONF_BAR 0 +#define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */ +#define EMS_PCI_V1_CAN_BASE_OFFSET 0x400 /* offset where the controllers start */ +#define EMS_PCI_V1_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ + +#define EMS_PCI_V2_BASE_BAR 2 +#define EMS_PCI_V2_CONF_BAR 0 +#define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */ +#define EMS_PCI_V2_CAN_BASE_OFFSET 0x400 /* offset where the controllers start */ +#define EMS_PCI_V2_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ + +#define EMS_PCI_V3_BASE_BAR 0 +#define EMS_PCI_V3_CONF_BAR 5 +#define EMS_PCI_V3_CONF_SIZE 128 /* size of ASIX control area */ +#define EMS_PCI_V3_CAN_BASE_OFFSET 0x00 /* offset where the controllers starts */ +#define EMS_PCI_V3_CAN_CTRL_SIZE 0x100 /* memory size for each controller */ #define EMS_PCI_BASE_SIZE 4096 /* size of controller area */ +#ifndef PCI_VENDOR_ID_ASIX +#define PCI_VENDOR_ID_ASIX 0x125b +#define PCI_DEVICE_ID_ASIX_9110 0x9110 +#define PCI_SUBVENDOR_ID_ASIX 0xa000 +#endif +#define PCI_SUBDEVICE_ID_EMS 0x4010 + static const struct pci_device_id ems_pci_tbl[] = { /* CPC-PCI v1 */ {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, @@ -96,12 +122,13 @@ static const struct pci_device_id ems_pci_tbl[] = { {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4000}, /* CPC-104P v2 */ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_PLX, 0x4002}, + /* CPC-PCIe v3 */ + {PCI_VENDOR_ID_ASIX, PCI_DEVICE_ID_ASIX_9110, PCI_SUBVENDOR_ID_ASIX, PCI_SUBDEVICE_ID_EMS}, {0,} }; MODULE_DEVICE_TABLE(pci, ems_pci_tbl); -/* - * Helper to read internal registers from card logic (not CAN) +/* Helper to read internal registers from card logic (not CAN) */ static u8 ems_pci_v1_readb(struct ems_pci_card *card, unsigned int port) { @@ -146,8 +173,25 @@ static void ems_pci_v2_post_irq(const struct sja1000_priv *priv) writel(PLX_ICSR_ENA_CLR, card->conf_addr + PLX_ICSR); } -/* - * Check if a CAN controller is present at the specified location +static u8 ems_pci_v3_read_reg(const struct sja1000_priv *priv, int port) +{ + return readb(priv->reg_base + port); +} + +static void ems_pci_v3_write_reg(const struct sja1000_priv *priv, + int port, u8 val) +{ + writeb(val, priv->reg_base + port); +} + +static void ems_pci_v3_post_irq(const struct sja1000_priv *priv) +{ + struct ems_pci_card *card = (struct ems_pci_card *)priv->priv; + + writel(ASIX_LINTSR_INT0AC, card->conf_addr + ASIX_LINTSR); +} + +/* Check if a CAN controller is present at the specified location * by trying to set 'em into the PeliCAN mode */ static inline int ems_pci_check_chan(const struct sja1000_priv *priv) @@ -185,10 +229,10 @@ static void ems_pci_del_card(struct pci_dev *pdev) free_sja1000dev(dev); } - if (card->base_addr != NULL) + if (card->base_addr) pci_iounmap(card->pci_dev, card->base_addr); - if (card->conf_addr != NULL) + if (card->conf_addr) pci_iounmap(card->pci_dev, card->conf_addr); kfree(card); @@ -202,8 +246,7 @@ static void ems_pci_card_reset(struct ems_pci_card *card) writeb(0, card->base_addr); } -/* - * Probe PCI device for EMS CAN signature and register each available +/* Probe PCI device for EMS CAN signature and register each available * CAN channel to SJA1000 Socket-CAN subsystem. */ static int ems_pci_add_card(struct pci_dev *pdev, @@ -212,7 +255,7 @@ static int ems_pci_add_card(struct pci_dev *pdev, struct sja1000_priv *priv; struct net_device *dev; struct ems_pci_card *card; - int max_chan, conf_size, base_bar; + int max_chan, conf_size, base_bar, conf_bar; int err, i; /* Enabling PCI device */ @@ -222,8 +265,8 @@ static int ems_pci_add_card(struct pci_dev *pdev, } /* Allocating card structures to hold addresses, ... */ - card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL); - if (card == NULL) { + card = kzalloc(sizeof(*card), GFP_KERNEL); + if (!card) { pci_disable_device(pdev); return -ENOMEM; } @@ -234,27 +277,35 @@ static int ems_pci_add_card(struct pci_dev *pdev, card->channels = 0; - if (pdev->vendor == PCI_VENDOR_ID_PLX) { + if (pdev->vendor == PCI_VENDOR_ID_ASIX) { + card->version = 3; /* CPC-PCI v3 */ + max_chan = EMS_PCI_V3_MAX_CHAN; + base_bar = EMS_PCI_V3_BASE_BAR; + conf_bar = EMS_PCI_V3_CONF_BAR; + conf_size = EMS_PCI_V3_CONF_SIZE; + } else if (pdev->vendor == PCI_VENDOR_ID_PLX) { card->version = 2; /* CPC-PCI v2 */ max_chan = EMS_PCI_V2_MAX_CHAN; base_bar = EMS_PCI_V2_BASE_BAR; + conf_bar = EMS_PCI_V2_CONF_BAR; conf_size = EMS_PCI_V2_CONF_SIZE; } else { card->version = 1; /* CPC-PCI v1 */ max_chan = EMS_PCI_V1_MAX_CHAN; base_bar = EMS_PCI_V1_BASE_BAR; + conf_bar = EMS_PCI_V1_CONF_BAR; conf_size = EMS_PCI_V1_CONF_SIZE; } /* Remap configuration space and controller memory area */ - card->conf_addr = pci_iomap(pdev, 0, conf_size); - if (card->conf_addr == NULL) { + card->conf_addr = pci_iomap(pdev, conf_bar, conf_size); + if (!card->conf_addr) { err = -ENOMEM; goto failure_cleanup; } card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE); - if (card->base_addr == NULL) { + if (!card->base_addr) { err = -ENOMEM; goto failure_cleanup; } @@ -276,12 +327,20 @@ static int ems_pci_add_card(struct pci_dev *pdev, } } + if (card->version == 3) { + /* ASIX chip asserts local reset to CAN controllers + * after bootup until it is deasserted + */ + writel(readl(card->conf_addr + ASIX_LIEMR) & ~ASIX_LIEMR_LRST, + card->conf_addr + ASIX_LIEMR); + } + ems_pci_card_reset(card); /* Detect available channels */ for (i = 0; i < max_chan; i++) { dev = alloc_sja1000dev(0); - if (dev == NULL) { + if (!dev) { err = -ENOMEM; goto failure_cleanup; } @@ -292,16 +351,25 @@ static int ems_pci_add_card(struct pci_dev *pdev, priv->irq_flags = IRQF_SHARED; dev->irq = pdev->irq; - priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET - + (i * EMS_PCI_CAN_CTRL_SIZE); + if (card->version == 1) { priv->read_reg = ems_pci_v1_read_reg; priv->write_reg = ems_pci_v1_write_reg; priv->post_irq = ems_pci_v1_post_irq; - } else { + priv->reg_base = card->base_addr + EMS_PCI_V1_CAN_BASE_OFFSET + + (i * EMS_PCI_V1_CAN_CTRL_SIZE); + } else if (card->version == 2) { priv->read_reg = ems_pci_v2_read_reg; priv->write_reg = ems_pci_v2_write_reg; priv->post_irq = ems_pci_v2_post_irq; + priv->reg_base = card->base_addr + EMS_PCI_V2_CAN_BASE_OFFSET + + (i * EMS_PCI_V2_CAN_CTRL_SIZE); + } else { + priv->read_reg = ems_pci_v3_read_reg; + priv->write_reg = ems_pci_v3_write_reg; + priv->post_irq = ems_pci_v3_post_irq; + priv->reg_base = card->base_addr + EMS_PCI_V3_CAN_BASE_OFFSET + + (i * EMS_PCI_V3_CAN_CTRL_SIZE); } /* Check if channel is present */ @@ -313,20 +381,28 @@ static int ems_pci_add_card(struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); dev->dev_id = i; - if (card->version == 1) + if (card->version == 1) { /* reset int flag of pita */ writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, card->conf_addr + PITA2_ICR); - else + } else if (card->version == 2) { /* enable IRQ in PLX 9030 */ writel(PLX_ICSR_ENA_CLR, card->conf_addr + PLX_ICSR); + } else { + /* Enable IRQ in AX99100 */ + writel(ASIX_LINTSR_INT0AC, card->conf_addr + ASIX_LINTSR); + /* Enable local INT0 input enable */ + writel(readl(card->conf_addr + ASIX_LIEMR) | ASIX_LIEMR_L0EINTEN, + card->conf_addr + ASIX_LIEMR); + } /* Register SJA1000 device */ err = register_sja1000dev(dev); if (err) { - dev_err(&pdev->dev, "Registering device failed " - "(err=%d)\n", err); + dev_err(&pdev->dev, + "Registering device failed: %pe\n", + ERR_PTR(err)); free_sja1000dev(dev); goto failure_cleanup; } @@ -334,7 +410,7 @@ static int ems_pci_add_card(struct pci_dev *pdev, card->channels++; dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d\n", - i + 1, priv->reg_base, dev->irq); + i + 1, priv->reg_base, dev->irq); } else { free_sja1000dev(dev); } diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c index bf3f0f150199..bfe4caa0c99d 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c @@ -30,11 +30,23 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, last_byte = mcp251xfd_last_byte_set(mask); len = last_byte - first_byte + 1; - data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte); + data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte, len); val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte); memcpy(data, &val_le32, len); - if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) { + if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) { + len += sizeof(write_reg_buf->nocrc.cmd); + } else if (len == 1) { + u16 crc; + + /* CRC */ + len += sizeof(write_reg_buf->safe.cmd); + crc = mcp251xfd_crc16_compute(&write_reg_buf->safe, len); + put_unaligned_be16(crc, (void *)write_reg_buf + len); + + /* Total length */ + len += sizeof(write_reg_buf->safe.crc); + } else { u16 crc; mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd, @@ -46,8 +58,6 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, /* Total length */ len += sizeof(write_reg_buf->crc.crc); - } else { - len += sizeof(write_reg_buf->nocrc.cmd); } return len; diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h index 2b0309fedfac..7024ff0cc2c0 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h @@ -504,6 +504,11 @@ union mcp251xfd_write_reg_buf { u8 data[4]; __be16 crc; } crc; + struct __packed { + struct mcp251xfd_buf_cmd cmd; + u8 data[1]; + __be16 crc; + } safe; } ____cacheline_aligned; struct mcp251xfd_tx_obj { @@ -758,6 +763,13 @@ mcp251xfd_spi_cmd_write_crc_set_addr(struct mcp251xfd_buf_cmd_crc *cmd, cmd->cmd = cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE_CRC | addr); } +static inline void +mcp251xfd_spi_cmd_write_safe_set_addr(struct mcp251xfd_buf_cmd *cmd, + u16 addr) +{ + cmd->cmd = cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE_CRC_SAFE | addr); +} + static inline void mcp251xfd_spi_cmd_write_crc(struct mcp251xfd_buf_cmd_crc *cmd, u16 addr, u16 len) @@ -769,14 +781,20 @@ mcp251xfd_spi_cmd_write_crc(struct mcp251xfd_buf_cmd_crc *cmd, static inline u8 * mcp251xfd_spi_cmd_write(const struct mcp251xfd_priv *priv, union mcp251xfd_write_reg_buf *write_reg_buf, - u16 addr) + u16 addr, u8 len) { u8 *data; if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) { - mcp251xfd_spi_cmd_write_crc_set_addr(&write_reg_buf->crc.cmd, - addr); - data = write_reg_buf->crc.data; + if (len == 1) { + mcp251xfd_spi_cmd_write_safe_set_addr(&write_reg_buf->safe.cmd, + addr); + data = write_reg_buf->safe.data; + } else { + mcp251xfd_spi_cmd_write_crc_set_addr(&write_reg_buf->crc.cmd, + addr); + data = write_reg_buf->crc.data; + } } else { mcp251xfd_spi_cmd_write_nocrc(&write_reg_buf->nocrc.cmd, addr); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 687dd542f7f6..b211b6e283a2 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -9,10 +9,11 @@ * Many thanks to Klaus Hitschler */ #include + +#include +#include #include #include -#include -#include #include #include @@ -381,23 +382,42 @@ static int pcan_usb_get_serial(struct peak_usb_device *dev, u32 *serial_number) } /* - * read device id from device + * read can channel id from device */ -static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id) +static int pcan_usb_get_can_channel_id(struct peak_usb_device *dev, u32 *can_ch_id) { u8 args[PCAN_USB_CMD_ARGS_LEN]; int err; err = pcan_usb_wait_rsp(dev, PCAN_USB_CMD_DEVID, PCAN_USB_GET, args); if (err) - netdev_err(dev->netdev, "getting device id failure: %d\n", err); + netdev_err(dev->netdev, "getting can channel id failure: %d\n", err); else - *device_id = args[0]; + *can_ch_id = args[0]; return err; } +/* set a new CAN channel id in the flash memory of the device */ +static int pcan_usb_set_can_channel_id(struct peak_usb_device *dev, u32 can_ch_id) +{ + u8 args[PCAN_USB_CMD_ARGS_LEN]; + + /* this kind of device supports 8-bit values only */ + if (can_ch_id > U8_MAX) + return -EINVAL; + + /* during the flash process the device disconnects during ~1.25 s.: + * prohibit access when interface is UP + */ + if (dev->netdev->flags & IFF_UP) + return -EBUSY; + + args[0] = can_ch_id; + return pcan_usb_send_cmd(dev, PCAN_USB_CMD_DEVID, PCAN_USB_SET, args); +} + /* * update current time ref with received timestamp */ @@ -963,9 +983,18 @@ static int pcan_usb_set_phys_id(struct net_device *netdev, return err; } +/* This device only handles 8-bit CAN channel id. */ +static int pcan_usb_get_eeprom_len(struct net_device *netdev) +{ + return sizeof(u8); +} + static const struct ethtool_ops pcan_usb_ethtool_ops = { .set_phys_id = pcan_usb_set_phys_id, .get_ts_info = pcan_get_ts_info, + .get_eeprom_len = pcan_usb_get_eeprom_len, + .get_eeprom = peak_usb_get_eeprom, + .set_eeprom = peak_usb_set_eeprom, }; /* @@ -1017,7 +1046,8 @@ const struct peak_usb_adapter pcan_usb = { .dev_init = pcan_usb_init, .dev_set_bus = pcan_usb_write_mode, .dev_set_bittiming = pcan_usb_set_bittiming, - .dev_get_device_id = pcan_usb_get_device_id, + .dev_get_can_channel_id = pcan_usb_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_set_can_channel_id, .dev_decode_buf = pcan_usb_decode_buf, .dev_encode_msg = pcan_usb_encode_msg, .dev_start = pcan_usb_start, diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 1d996d3320fe..d881e1d30183 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -8,13 +8,15 @@ * * Many thanks to Klaus Hitschler */ +#include +#include #include -#include -#include #include #include +#include +#include +#include #include -#include #include #include @@ -53,6 +55,26 @@ static const struct usb_device_id peak_usb_table[] = { MODULE_DEVICE_TABLE(usb, peak_usb_table); +static ssize_t can_channel_id_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct net_device *netdev = to_net_dev(dev); + struct peak_usb_device *peak_dev = netdev_priv(netdev); + + return sysfs_emit(buf, "%08X\n", peak_dev->can_channel_id); +} +static DEVICE_ATTR_RO(can_channel_id); + +/* mutable to avoid cast in attribute_group */ +static struct attribute *peak_usb_sysfs_attrs[] = { + &dev_attr_can_channel_id.attr, + NULL, +}; + +static const struct attribute_group peak_usb_sysfs_group = { + .name = "peak_usb", + .attrs = peak_usb_sysfs_attrs, +}; + /* * dump memory */ @@ -808,6 +830,86 @@ static const struct net_device_ops peak_usb_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +/* CAN-USB devices generally handle 32-bit CAN channel IDs. + * In case one doesn't, then it have to overload this function. + */ +int peak_usb_get_eeprom_len(struct net_device *netdev) +{ + return sizeof(u32); +} + +/* Every CAN-USB device exports the dev_get_can_channel_id() operation. It is used + * here to fill the data buffer with the user defined CAN channel ID. + */ +int peak_usb_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct peak_usb_device *dev = netdev_priv(netdev); + u32 ch_id; + __le32 ch_id_le; + int err; + + err = dev->adapter->dev_get_can_channel_id(dev, &ch_id); + if (err) + return err; + + /* ethtool operates on individual bytes. The byte order of the CAN + * channel id in memory depends on the kernel architecture. We + * convert the CAN channel id back to the native byte order of the PEAK + * device itself to ensure that the order is consistent for all + * host architectures. + */ + ch_id_le = cpu_to_le32(ch_id); + memcpy(data, (u8 *)&ch_id_le + eeprom->offset, eeprom->len); + + /* update cached value */ + dev->can_channel_id = ch_id; + return err; +} + +/* Every CAN-USB device exports the dev_get_can_channel_id()/dev_set_can_channel_id() + * operations. They are used here to set the new user defined CAN channel ID. + */ +int peak_usb_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct peak_usb_device *dev = netdev_priv(netdev); + u32 ch_id; + __le32 ch_id_le; + int err; + + /* first, read the current user defined CAN channel ID */ + err = dev->adapter->dev_get_can_channel_id(dev, &ch_id); + if (err) { + netdev_err(netdev, "Failed to init CAN channel id (err %d)\n", err); + return err; + } + + /* do update the value with user given bytes. + * ethtool operates on individual bytes. The byte order of the CAN + * channel ID in memory depends on the kernel architecture. We + * convert the CAN channel ID back to the native byte order of the PEAK + * device itself to ensure that the order is consistent for all + * host architectures. + */ + ch_id_le = cpu_to_le32(ch_id); + memcpy((u8 *)&ch_id_le + eeprom->offset, data, eeprom->len); + ch_id = le32_to_cpu(ch_id_le); + + /* flash the new value now */ + err = dev->adapter->dev_set_can_channel_id(dev, ch_id); + if (err) { + netdev_err(netdev, "Failed to write new CAN channel id (err %d)\n", + err); + return err; + } + + /* update cached value with the new one */ + dev->can_channel_id = ch_id; + + return 0; +} + int pcan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { info->so_timestamping = @@ -881,6 +983,9 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, /* add ethtool support */ netdev->ethtool_ops = peak_usb_adapter->ethtool_ops; + /* register peak_usb sysfs files */ + netdev->sysfs_groups[0] = &peak_usb_sysfs_group; + init_usb_anchor(&dev->rx_submitted); init_usb_anchor(&dev->tx_submitted); @@ -921,12 +1026,11 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, goto adap_dev_free; } - /* get device number early */ - if (dev->adapter->dev_get_device_id) - dev->adapter->dev_get_device_id(dev, &dev->device_number); + /* get CAN channel id early */ + dev->adapter->dev_get_can_channel_id(dev, &dev->can_channel_id); - netdev_info(netdev, "attached to %s channel %u (device %u)\n", - peak_usb_adapter->name, ctrl_idx, dev->device_number); + netdev_info(netdev, "attached to %s channel %u (device 0x%08X)\n", + peak_usb_adapter->name, ctrl_idx, dev->can_channel_id); return 0; @@ -964,7 +1068,7 @@ static void peak_usb_disconnect(struct usb_interface *intf) dev->state &= ~PCAN_USB_STATE_CONNECTED; strscpy(name, netdev->name, IFNAMSIZ); - unregister_netdev(netdev); + unregister_candev(netdev); kfree(dev->cmd_buf); dev->next_siblings = NULL; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index f6bdd8b3f290..980e315186cf 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -60,7 +60,8 @@ struct peak_usb_adapter { int (*dev_set_data_bittiming)(struct peak_usb_device *dev, struct can_bittiming *bt); int (*dev_set_bus)(struct peak_usb_device *dev, u8 onoff); - int (*dev_get_device_id)(struct peak_usb_device *dev, u32 *device_id); + int (*dev_get_can_channel_id)(struct peak_usb_device *dev, u32 *can_ch_id); + int (*dev_set_can_channel_id)(struct peak_usb_device *dev, u32 can_ch_id); int (*dev_decode_buf)(struct peak_usb_device *dev, struct urb *urb); int (*dev_encode_msg)(struct peak_usb_device *dev, struct sk_buff *skb, u8 *obuf, size_t *size); @@ -122,7 +123,8 @@ struct peak_usb_device { u8 *cmd_buf; struct usb_anchor rx_submitted; - u32 device_number; + /* equivalent to the device ID in the Windows API */ + u32 can_channel_id; u8 device_rev; u8 ep_msg_in; @@ -147,4 +149,10 @@ void peak_usb_async_complete(struct urb *urb); void peak_usb_restart_complete(struct peak_usb_device *dev); int pcan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info); +/* common 32-bit CAN channel ID ethtool management */ +int peak_usb_get_eeprom_len(struct net_device *netdev); +int peak_usb_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data); +int peak_usb_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data); #endif diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 2ea1500df393..4d85b29a17b7 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -4,10 +4,10 @@ * * Copyright (C) 2013-2014 Stephane Grosjean */ +#include +#include #include #include -#include -#include #include #include @@ -147,6 +147,15 @@ struct __packed pcan_ufd_ovr_msg { u8 unused[3]; }; +#define PCAN_UFD_CMD_DEVID_SET 0x81 + +struct __packed pcan_ufd_device_id { + __le16 opcode_channel; + + u16 unused; + __le32 device_id; +}; + static inline int pufd_omsg_get_channel(struct pcan_ufd_ovr_msg *om) { return om->channel & 0xf; @@ -234,6 +243,15 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) return err; } +static int pcan_usb_fd_read_fwinfo(struct peak_usb_device *dev, + struct pcan_ufd_fw_info *fw_info) +{ + return pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, + PCAN_USBPRO_INFO_FW, + fw_info, + sizeof(*fw_info)); +} + /* build the commands list in the given buffer, to enter operational mode */ static int pcan_usb_fd_build_restart_cmd(struct peak_usb_device *dev, u8 *buf) { @@ -434,6 +452,34 @@ static int pcan_usb_fd_set_bittiming_fast(struct peak_usb_device *dev, return pcan_usb_fd_send_cmd(dev, ++cmd); } +/* read user CAN channel id from device */ +static int pcan_usb_fd_get_can_channel_id(struct peak_usb_device *dev, + u32 *can_ch_id) +{ + int err; + struct pcan_usb_fd_if *usb_if = pcan_usb_fd_dev_if(dev); + + err = pcan_usb_fd_read_fwinfo(dev, &usb_if->fw_info); + if (err) + return err; + + *can_ch_id = le32_to_cpu(usb_if->fw_info.dev_id[dev->ctrl_idx]); + return err; +} + +/* set a new CAN channel id in the flash memory of the device */ +static int pcan_usb_fd_set_can_channel_id(struct peak_usb_device *dev, u32 can_ch_id) +{ + struct pcan_ufd_device_id *cmd = pcan_usb_fd_cmd_buffer(dev); + + cmd->opcode_channel = pucan_cmd_opcode_channel(dev->ctrl_idx, + PCAN_UFD_CMD_DEVID_SET); + cmd->device_id = cpu_to_le32(can_ch_id); + + /* send the command */ + return pcan_usb_fd_send_cmd(dev, ++cmd); +} + /* handle restart but in asynchronously way * (uses PCAN-USB Pro code to complete asynchronous request) */ @@ -907,10 +953,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) fw_info = &pdev->usb_if->fw_info; - err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, - PCAN_USBPRO_INFO_FW, - fw_info, - sizeof(*fw_info)); + err = pcan_usb_fd_read_fwinfo(dev, fw_info); if (err) { dev_err(dev->netdev->dev.parent, "unable to read %s firmware info (err %d)\n", @@ -972,7 +1015,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) } pdev->usb_if->dev[dev->ctrl_idx] = dev; - dev->device_number = + dev->can_channel_id = le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]); /* if vendor rsp is of type 2, then it contains EP numbers to @@ -1081,6 +1124,9 @@ static int pcan_usb_fd_set_phys_id(struct net_device *netdev, static const struct ethtool_ops pcan_usb_fd_ethtool_ops = { .set_phys_id = pcan_usb_fd_set_phys_id, .get_ts_info = pcan_get_ts_info, + .get_eeprom_len = peak_usb_get_eeprom_len, + .get_eeprom = peak_usb_get_eeprom, + .set_eeprom = peak_usb_set_eeprom, }; /* describes the PCAN-USB FD adapter */ @@ -1148,6 +1194,8 @@ const struct peak_usb_adapter pcan_usb_fd = { .dev_set_bus = pcan_usb_fd_set_bus, .dev_set_bittiming = pcan_usb_fd_set_bittiming_slow, .dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast, + .dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id, .dev_decode_buf = pcan_usb_fd_decode_buf, .dev_start = pcan_usb_fd_start, .dev_stop = pcan_usb_fd_stop, @@ -1222,6 +1270,8 @@ const struct peak_usb_adapter pcan_usb_chip = { .dev_set_bus = pcan_usb_fd_set_bus, .dev_set_bittiming = pcan_usb_fd_set_bittiming_slow, .dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast, + .dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id, .dev_decode_buf = pcan_usb_fd_decode_buf, .dev_start = pcan_usb_fd_start, .dev_stop = pcan_usb_fd_stop, @@ -1296,6 +1346,8 @@ const struct peak_usb_adapter pcan_usb_pro_fd = { .dev_set_bus = pcan_usb_fd_set_bus, .dev_set_bittiming = pcan_usb_fd_set_bittiming_slow, .dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast, + .dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id, .dev_decode_buf = pcan_usb_fd_decode_buf, .dev_start = pcan_usb_fd_start, .dev_stop = pcan_usb_fd_stop, @@ -1370,6 +1422,8 @@ const struct peak_usb_adapter pcan_usb_x6 = { .dev_set_bus = pcan_usb_fd_set_bus, .dev_set_bittiming = pcan_usb_fd_set_bittiming_slow, .dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast, + .dev_get_can_channel_id = pcan_usb_fd_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_fd_set_can_channel_id, .dev_decode_buf = pcan_usb_fd_decode_buf, .dev_start = pcan_usb_fd_start, .dev_stop = pcan_usb_fd_stop, 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 5d8f6a40bb2c..f736196383ac 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -6,10 +6,10 @@ * Copyright (C) 2003-2011 PEAK System-Technik GmbH * Copyright (C) 2011-2012 Stephane Grosjean */ +#include +#include #include #include -#include -#include #include #include @@ -76,6 +76,7 @@ static u16 pcan_usb_pro_sizeof_rec[256] = { [PCAN_USBPRO_SETFILTR] = sizeof(struct pcan_usb_pro_filter), [PCAN_USBPRO_SETTS] = sizeof(struct pcan_usb_pro_setts), [PCAN_USBPRO_GETDEVID] = sizeof(struct pcan_usb_pro_devid), + [PCAN_USBPRO_SETDEVID] = sizeof(struct pcan_usb_pro_devid), [PCAN_USBPRO_SETLED] = sizeof(struct pcan_usb_pro_setled), [PCAN_USBPRO_RXMSG8] = sizeof(struct pcan_usb_pro_rxmsg), [PCAN_USBPRO_RXMSG4] = sizeof(struct pcan_usb_pro_rxmsg) - 4, @@ -149,6 +150,7 @@ static int pcan_msg_add_rec(struct pcan_usb_pro_msg *pm, int id, ...) case PCAN_USBPRO_SETBTR: case PCAN_USBPRO_GETDEVID: + case PCAN_USBPRO_SETDEVID: *pc++ = va_arg(ap, int); pc += 2; *(__le32 *)pc = cpu_to_le32(va_arg(ap, u32)); @@ -419,8 +421,8 @@ static int pcan_usb_pro_set_led(struct peak_usb_device *dev, u8 mode, return pcan_usb_pro_send_cmd(dev, &um); } -static int pcan_usb_pro_get_device_id(struct peak_usb_device *dev, - u32 *device_id) +static int pcan_usb_pro_get_can_channel_id(struct peak_usb_device *dev, + u32 *can_ch_id) { struct pcan_usb_pro_devid *pdn; struct pcan_usb_pro_msg um; @@ -439,11 +441,23 @@ static int pcan_usb_pro_get_device_id(struct peak_usb_device *dev, return err; pdn = (struct pcan_usb_pro_devid *)pc; - *device_id = le32_to_cpu(pdn->dev_num); + *can_ch_id = le32_to_cpu(pdn->dev_num); return err; } +static int pcan_usb_pro_set_can_channel_id(struct peak_usb_device *dev, + u32 can_ch_id) +{ + struct pcan_usb_pro_msg um; + + pcan_msg_init_empty(&um, dev->cmd_buf, PCAN_USB_MAX_CMD_LEN); + pcan_msg_add_rec(&um, PCAN_USBPRO_SETDEVID, dev->ctrl_idx, + can_ch_id); + + return pcan_usb_pro_send_cmd(dev, &um); +} + static int pcan_usb_pro_set_bittiming(struct peak_usb_device *dev, struct can_bittiming *bt) { @@ -1023,6 +1037,9 @@ static int pcan_usb_pro_set_phys_id(struct net_device *netdev, static const struct ethtool_ops pcan_usb_pro_ethtool_ops = { .set_phys_id = pcan_usb_pro_set_phys_id, .get_ts_info = pcan_get_ts_info, + .get_eeprom_len = peak_usb_get_eeprom_len, + .get_eeprom = peak_usb_get_eeprom, + .set_eeprom = peak_usb_set_eeprom, }; /* @@ -1076,7 +1093,8 @@ const struct peak_usb_adapter pcan_usb_pro = { .dev_free = pcan_usb_pro_free, .dev_set_bus = pcan_usb_pro_set_bus, .dev_set_bittiming = pcan_usb_pro_set_bittiming, - .dev_get_device_id = pcan_usb_pro_get_device_id, + .dev_get_can_channel_id = pcan_usb_pro_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_pro_set_can_channel_id, .dev_decode_buf = pcan_usb_pro_decode_buf, .dev_encode_msg = pcan_usb_pro_encode_msg, .dev_start = pcan_usb_pro_start, diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h index a34e0fc021c9..28e740af905d 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h @@ -62,6 +62,7 @@ struct __packed pcan_usb_pro_fwinfo { #define PCAN_USBPRO_SETBTR 0x02 #define PCAN_USBPRO_SETBUSACT 0x04 #define PCAN_USBPRO_SETSILENT 0x05 +#define PCAN_USBPRO_SETDEVID 0x06 #define PCAN_USBPRO_SETFILTR 0x0a #define PCAN_USBPRO_SETTS 0x10 #define PCAN_USBPRO_GETDEVID 0x12 diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index ef0a77173e3c..6cb2ae308e3f 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -116,7 +116,7 @@ struct can_tdc_const { #ifdef CONFIG_CAN_CALC_BITTIMING int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc); + const struct can_bittiming_const *btc, struct netlink_ext_ack *extack); void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, const struct can_bittiming *dbt, @@ -138,10 +138,16 @@ can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const, } #endif /* CONFIG_CAN_CALC_BITTIMING */ +void can_sjw_set_default(struct can_bittiming *bt); + +int can_sjw_check(const struct net_device *dev, const struct can_bittiming *bt, + const struct can_bittiming_const *btc, struct netlink_ext_ack *extack); + int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt, const struct can_bittiming_const *btc, const u32 *bitrate_const, - const unsigned int bitrate_const_cnt); + const unsigned int bitrate_const_cnt, + struct netlink_ext_ack *extack); /* * can_bit_time() - Duration of one bit diff --git a/net/can/gw.c b/net/can/gw.c index 23a3d89cad81..37528826935e 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -1139,6 +1139,13 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, if (gwj->dst.dev->type != ARPHRD_CAN) goto out; + /* is sending the skb back to the incoming interface intended? */ + if (gwj->src.dev == gwj->dst.dev && + !(gwj->flags & CGW_FLAGS_CAN_IIF_TX_OK)) { + err = -EINVAL; + goto out; + } + ASSERT_RTNL(); err = cgw_register_filter(net, gwj); diff --git a/net/can/isotp.c b/net/can/isotp.c index fc81d77724a1..9bc344851704 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -1220,6 +1220,9 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) if (len < ISOTP_MIN_NAMELEN) return -EINVAL; + if (addr->can_family != AF_CAN) + return -EINVAL; + /* sanitize tx CAN identifier */ if (tx_id & CAN_EFF_FLAG) tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK);