maxmb
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index ea57fed..e3239a9 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c
@@ -258,8 +258,14 @@ struct flexcan_regs { u32 errsr; /* 0xafc */ }; +struct flexcan_devtype_clockratio { + u8 max_mb; + u8 ratio; +}; + struct flexcan_devtype_data { u32 quirks; /* quirks needed for different IP cores */ + const struct flexcan_devtype_clockratio const *clockratio; }; struct flexcan_priv { @@ -280,20 +286,39 @@ struct flexcan_priv { struct regulator *reg_xceiver; }; -static const struct flexcan_devtype_data fsl_p1010_devtype_data = { - .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE, +static const struct flexcan_devtype_clockratio flexcan_clockratio_v2[] = { + /* Define values in descending order of ratio. */ + { .max_mb = 63, .ratio = 16}, + { .max_mb = 31, .ratio = 8}, + { /* sentinel */ } }; -static const struct flexcan_devtype_data fsl_imx28_devtype_data; +static const struct flexcan_devtype_clockratio flexcan_clockratio_v3[] = { + /* Define values in descending order of ratio. */ + { .max_mb = 63, .ratio = 25}, + { .max_mb = 31, .ratio = 16}, + { /* sentinel */ } +}; + +static const struct flexcan_devtype_data fsl_p1010_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE, + .clockratio = flexcan_clockratio_v2, +}; + +static const struct flexcan_devtype_data fsl_imx28_devtype_data = { + .clockratio = flexcan_clockratio_v2, +}; static const struct flexcan_devtype_data fsl_imx6q_devtype_data = { .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, + .clockratio = flexcan_clockratio_v3, }; static const struct flexcan_devtype_data fsl_vf610_devtype_data = { .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, + .clockratio = flexcan_clockratio_v3, }; static const struct can_bittiming_const flexcan_bittiming_const = { @@ -815,6 +840,37 @@ static void flexcan_set_bittiming(struct net_device *dev) flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); } +/* flexcan_get_max_mb + * + * This function calculcated the maximum number of mailboxes usable + * depending on the CAN bittiming and clocking. + */ +static u8 flexcan_get_max_mb(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + const struct can_bittiming *bt = &priv->can.bittiming; + const struct flexcan_devtype_clockratio *clockratio; + unsigned long f_sys; + unsigned int ratio; + + f_sys = clk_get_rate(priv->clk_ipg); + if (!f_sys) + goto fallback; + + ratio = f_sys / bt->bitrate; + + netdev_dbg(dev, "f_sys=%ld, f_can=%d, ratio=%d\n", f_sys, bt->bitrate, ratio); + + for (clockratio = priv->devtype_data->clockratio; + clockratio->ratio; clockratio++) { + if (ratio >= clockratio->ratio) + return clockratio->max_mb; + } + + fallback: + return FLEXCAN_MCR_MAXMB(flexcan_read(&priv->regs->mcr)); +} + /* flexcan_chip_start * * this functions is entered with clocks enabled