diff options
| author | Stephen Rothwell <sfr@canb.auug.org.au> | 2011-07-25 13:59:46 -0400 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-25 14:53:52 -0400 | 
| commit | 5f00bcb38ef9a980a33c6dbdc0044964b05f22dd (patch) | |
| tree | 3175fb9375aecb50bde1be0bf4fa8aa8155131d6 /drivers/net/can/at91_can.c | |
| parent | 34006cee28f7344f9557a4be3816c7891b1bbab1 (diff) | |
| parent | b6844e8f64920cdee620157252169ba63afb0c89 (diff) | |
Merge branch 'master' into devel and apply fixup from Stephen Rothwell:
vfs/nfs: fixup for nfs_open_context change
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'drivers/net/can/at91_can.c')
| -rw-r--r-- | drivers/net/can/at91_can.c | 366 | 
1 files changed, 256 insertions, 110 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 74efb5a2ad4..121ede663e2 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -41,32 +41,7 @@  #include <mach/board.h> -#define AT91_NAPI_WEIGHT	11 - -/* - * RX/TX Mailbox split - * don't dare to touch - */ -#define AT91_MB_RX_NUM		11 -#define AT91_MB_TX_SHIFT	2 - -#define AT91_MB_RX_FIRST	1 -#define AT91_MB_RX_LAST		(AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1) - -#define AT91_MB_RX_MASK(i)	((1 << (i)) - 1) -#define AT91_MB_RX_SPLIT	8 -#define AT91_MB_RX_LOW_LAST	(AT91_MB_RX_SPLIT - 1) -#define AT91_MB_RX_LOW_MASK	(AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \ -				 ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST)) - -#define AT91_MB_TX_NUM		(1 << AT91_MB_TX_SHIFT) -#define AT91_MB_TX_FIRST	(AT91_MB_RX_LAST + 1) -#define AT91_MB_TX_LAST		(AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1) - -#define AT91_NEXT_PRIO_SHIFT	(AT91_MB_TX_SHIFT) -#define AT91_NEXT_PRIO_MASK	(0xf << AT91_MB_TX_SHIFT) -#define AT91_NEXT_MB_MASK	(AT91_MB_TX_NUM - 1) -#define AT91_NEXT_MASK		((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK) +#define AT91_MB_MASK(i)		((1 << (i)) - 1)  /* Common registers */  enum at91_reg { @@ -128,12 +103,6 @@ enum at91_mb_mode {  };  /* Interrupt mask bits */ -#define AT91_IRQ_MB_RX		((1 << (AT91_MB_RX_LAST + 1)) \ -				 - (1 << AT91_MB_RX_FIRST)) -#define AT91_IRQ_MB_TX		((1 << (AT91_MB_TX_LAST + 1)) \ -				 - (1 << AT91_MB_TX_FIRST)) -#define AT91_IRQ_MB_ALL		(AT91_IRQ_MB_RX | AT91_IRQ_MB_TX) -  #define AT91_IRQ_ERRA		(1 << 16)  #define AT91_IRQ_WARN		(1 << 17)  #define AT91_IRQ_ERRP		(1 << 18) @@ -156,22 +125,51 @@ enum at91_mb_mode {  #define AT91_IRQ_ALL		(0x1fffffff) +enum at91_devtype { +	AT91_DEVTYPE_SAM9263, +	AT91_DEVTYPE_SAM9X5, +}; + +struct at91_devtype_data { +	unsigned int rx_first; +	unsigned int rx_split; +	unsigned int rx_last; +	unsigned int tx_shift; +	enum at91_devtype type; +}; +  struct at91_priv { -	struct can_priv		can;	   /* must be the first member! */ -	struct net_device	*dev; -	struct napi_struct	napi; +	struct can_priv can;		/* must be the first member! */ +	struct net_device *dev; +	struct napi_struct napi; -	void __iomem		*reg_base; +	void __iomem *reg_base; -	u32			reg_sr; -	unsigned int		tx_next; -	unsigned int		tx_echo; -	unsigned int		rx_next; +	u32 reg_sr; +	unsigned int tx_next; +	unsigned int tx_echo; +	unsigned int rx_next; +	struct at91_devtype_data devtype_data; -	struct clk		*clk; -	struct at91_can_data	*pdata; +	struct clk *clk; +	struct at91_can_data *pdata; -	canid_t			mb0_id; +	canid_t mb0_id; +}; + +static const struct at91_devtype_data at91_devtype_data[] __devinitconst = { +	[AT91_DEVTYPE_SAM9263] = { +		.rx_first = 1, +		.rx_split = 8, +		.rx_last = 11, +		.tx_shift = 2, +	}, +	[AT91_DEVTYPE_SAM9X5] = { +		.rx_first = 0, +		.rx_split = 4, +		.rx_last = 5, +		.tx_shift = 1, +	},  };  static struct can_bittiming_const at91_bittiming_const = { @@ -186,19 +184,111 @@ static struct can_bittiming_const at91_bittiming_const = {  	.brp_inc	= 1,  }; -static inline int get_tx_next_mb(const struct at91_priv *priv) +#define AT91_IS(_model) \ +static inline int at91_is_sam##_model(const struct at91_priv *priv) \ +{ \ +	return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \ +} + +AT91_IS(9263); +AT91_IS(9X5); + +static inline unsigned int get_mb_rx_first(const struct at91_priv *priv) +{ +	return priv->devtype_data.rx_first; +} + +static inline unsigned int get_mb_rx_last(const struct at91_priv *priv) +{ +	return priv->devtype_data.rx_last; +} + +static inline unsigned int get_mb_rx_split(const struct at91_priv *priv) +{ +	return priv->devtype_data.rx_split; +} + +static inline unsigned int get_mb_rx_num(const struct at91_priv *priv) +{ +	return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1; +} + +static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv) +{ +	return get_mb_rx_split(priv) - 1; +} + +static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv) +{ +	return AT91_MB_MASK(get_mb_rx_split(priv)) & +		~AT91_MB_MASK(get_mb_rx_first(priv)); +} + +static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv) +{ +	return priv->devtype_data.tx_shift; +} + +static inline unsigned int get_mb_tx_num(const struct at91_priv *priv) +{ +	return 1 << get_mb_tx_shift(priv); +} + +static inline unsigned int get_mb_tx_first(const struct at91_priv *priv) +{ +	return get_mb_rx_last(priv) + 1; +} + +static inline unsigned int get_mb_tx_last(const struct at91_priv *priv) +{ +	return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1; +} + +static inline unsigned int get_next_prio_shift(const struct at91_priv *priv) +{ +	return get_mb_tx_shift(priv); +} + +static inline unsigned int get_next_prio_mask(const struct at91_priv *priv) +{ +	return 0xf << get_mb_tx_shift(priv); +} + +static inline unsigned int get_next_mb_mask(const struct at91_priv *priv) +{ +	return AT91_MB_MASK(get_mb_tx_shift(priv)); +} + +static inline unsigned int get_next_mask(const struct at91_priv *priv) +{ +	return get_next_mb_mask(priv) | get_next_prio_mask(priv); +} + +static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)  { -	return (priv->tx_next & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST; +	return AT91_MB_MASK(get_mb_rx_last(priv) + 1) & +		~AT91_MB_MASK(get_mb_rx_first(priv));  } -static inline int get_tx_next_prio(const struct at91_priv *priv) +static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)  { -	return (priv->tx_next >> AT91_NEXT_PRIO_SHIFT) & 0xf; +	return AT91_MB_MASK(get_mb_tx_last(priv) + 1) & +		~AT91_MB_MASK(get_mb_tx_first(priv));  } -static inline int get_tx_echo_mb(const struct at91_priv *priv) +static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)  { -	return (priv->tx_echo & AT91_NEXT_MB_MASK) + AT91_MB_TX_FIRST; +	return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv); +} + +static inline unsigned int get_tx_next_prio(const struct at91_priv *priv) +{ +	return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf; +} + +static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv) +{ +	return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);  }  static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg) @@ -259,29 +349,29 @@ static void at91_setup_mailboxes(struct net_device *dev)  	 * overflow.  	 */  	reg_mid = at91_can_id_to_reg_mid(priv->mb0_id); -	for (i = 0; i < AT91_MB_RX_FIRST; i++) { +	for (i = 0; i < get_mb_rx_first(priv); i++) {  		set_mb_mode(priv, i, AT91_MB_MODE_DISABLED);  		at91_write(priv, AT91_MID(i), reg_mid);  		at91_write(priv, AT91_MCR(i), 0x0);	/* clear dlc */  	} -	for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++) +	for (i = get_mb_rx_first(priv); i < get_mb_rx_last(priv); i++)  		set_mb_mode(priv, i, AT91_MB_MODE_RX); -	set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); +	set_mb_mode(priv, get_mb_rx_last(priv), AT91_MB_MODE_RX_OVRWR);  	/* reset acceptance mask and id register */ -	for (i = AT91_MB_RX_FIRST; i <= AT91_MB_RX_LAST; i++) { -		at91_write(priv, AT91_MAM(i), 0x0 ); +	for (i = get_mb_rx_first(priv); i <= get_mb_rx_last(priv); i++) { +		at91_write(priv, AT91_MAM(i), 0x0);  		at91_write(priv, AT91_MID(i), AT91_MID_MIDE);  	}  	/* The last 4 mailboxes are used for transmitting. */ -	for (i = AT91_MB_TX_FIRST; i <= AT91_MB_TX_LAST; i++) +	for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)  		set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);  	/* Reset tx and rx helper pointers */  	priv->tx_next = priv->tx_echo = 0; -	priv->rx_next = AT91_MB_RX_FIRST; +	priv->rx_next = get_mb_rx_first(priv);  }  static int at91_set_bittiming(struct net_device *dev) @@ -336,7 +426,7 @@ static void at91_chip_start(struct net_device *dev)  	priv->can.state = CAN_STATE_ERROR_ACTIVE;  	/* Enable interrupts */ -	reg_ier = AT91_IRQ_MB_RX | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME; +	reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;  	at91_write(priv, AT91_IDR, AT91_IRQ_ALL);  	at91_write(priv, AT91_IER, reg_ier);  } @@ -375,8 +465,8 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)   * mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits   * encode the mailbox number, the upper 4 bits the mailbox priority:   * - * priv->tx_next = (prio << AT91_NEXT_PRIO_SHIFT) || - *                 (mb - AT91_MB_TX_FIRST); + * priv->tx_next = (prio << get_next_prio_shift(priv)) | + *                 (mb - get_mb_tx_first(priv));   *   */  static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -417,7 +507,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)  	stats->tx_bytes += cf->can_dlc;  	/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ -	can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST); +	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));  	/*  	 * we have to stop the queue and deliver all messages in case @@ -430,7 +520,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)  	priv->tx_next++;  	if (!(at91_read(priv, AT91_MSR(get_tx_next_mb(priv))) &  	      AT91_MSR_MRDY) || -	    (priv->tx_next & AT91_NEXT_MASK) == 0) +	    (priv->tx_next & get_next_mask(priv)) == 0)  		netif_stop_queue(dev);  	/* Enable interrupt for this mailbox */ @@ -447,7 +537,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)   */  static inline void at91_activate_rx_low(const struct at91_priv *priv)  { -	u32 mask = AT91_MB_RX_LOW_MASK; +	u32 mask = get_mb_rx_low_mask(priv);  	at91_write(priv, AT91_TCR, mask);  } @@ -513,17 +603,19 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,  		cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;  	reg_msr = at91_read(priv, AT91_MSR(mb)); -	if (reg_msr & AT91_MSR_MRTR) -		cf->can_id |= CAN_RTR_FLAG;  	cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf); -	*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb)); -	*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb)); +	if (reg_msr & AT91_MSR_MRTR) +		cf->can_id |= CAN_RTR_FLAG; +	else { +		*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb)); +		*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb)); +	}  	/* allow RX of extended frames */  	at91_write(priv, AT91_MID(mb), AT91_MID_MIDE); -	if (unlikely(mb == AT91_MB_RX_LAST && reg_msr & AT91_MSR_MMI)) +	if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))  		at91_rx_overflow_err(dev);  } @@ -561,8 +653,9 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)   *   * Theory of Operation:   * - * 11 of the 16 mailboxes on the chip are reserved for RX. we split - * them into 2 groups. The lower group holds 7 and upper 4 mailboxes. + * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last()) + * on the chip are reserved for RX. We split them into 2 groups. The + * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().   *   * Like it or not, but the chip always saves a received CAN message   * into the first free mailbox it finds (starting with the @@ -610,23 +703,23 @@ static int at91_poll_rx(struct net_device *dev, int quota)  	unsigned int mb;  	int received = 0; -	if (priv->rx_next > AT91_MB_RX_LOW_LAST && -	    reg_sr & AT91_MB_RX_LOW_MASK) +	if (priv->rx_next > get_mb_rx_low_last(priv) && +	    reg_sr & get_mb_rx_low_mask(priv))  		netdev_info(dev,  			"order of incoming frames cannot be guaranteed\n");   again: -	for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next); -	     mb < AT91_MB_RX_LAST + 1 && quota > 0; +	for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next); +	     mb < get_mb_tx_first(priv) && quota > 0;  	     reg_sr = at91_read(priv, AT91_SR), -	     mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) { +	     mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {  		at91_read_msg(dev, mb);  		/* reactivate mailboxes */ -		if (mb == AT91_MB_RX_LOW_LAST) +		if (mb == get_mb_rx_low_last(priv))  			/* all lower mailboxed, if just finished it */  			at91_activate_rx_low(priv); -		else if (mb > AT91_MB_RX_LOW_LAST) +		else if (mb > get_mb_rx_low_last(priv))  			/* only the mailbox we read */  			at91_activate_rx_mb(priv, mb); @@ -635,9 +728,9 @@ static int at91_poll_rx(struct net_device *dev, int quota)  	}  	/* upper group completed, look again in lower */ -	if (priv->rx_next > AT91_MB_RX_LOW_LAST && -	    quota > 0 && mb > AT91_MB_RX_LAST) { -		priv->rx_next = AT91_MB_RX_FIRST; +	if (priv->rx_next > get_mb_rx_low_last(priv) && +	    quota > 0 && mb > get_mb_rx_last(priv)) { +		priv->rx_next = get_mb_rx_first(priv);  		goto again;  	} @@ -720,7 +813,7 @@ static int at91_poll(struct napi_struct *napi, int quota)  	u32 reg_sr = at91_read(priv, AT91_SR);  	int work_done = 0; -	if (reg_sr & AT91_IRQ_MB_RX) +	if (reg_sr & get_irq_mb_rx(priv))  		work_done += at91_poll_rx(dev, quota - work_done);  	/* @@ -734,7 +827,7 @@ static int at91_poll(struct napi_struct *napi, int quota)  	if (work_done < quota) {  		/* enable IRQs for frame errors and all mailboxes >= rx_next */  		u32 reg_ier = AT91_IRQ_ERR_FRAME; -		reg_ier |= AT91_IRQ_MB_RX & ~AT91_MB_RX_MASK(priv->rx_next); +		reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);  		napi_complete(napi);  		at91_write(priv, AT91_IER, reg_ier); @@ -783,7 +876,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)  		if (likely(reg_msr & AT91_MSR_MRDY &&  			   ~reg_msr & AT91_MSR_MABT)) {  			/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ -			can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST); +			can_get_echo_skb(dev, mb - get_mb_tx_first(priv));  			dev->stats.tx_packets++;  		}  	} @@ -793,8 +886,8 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)  	 * we get a TX int for the last can frame directly before a  	 * wrap around.  	 */ -	if ((priv->tx_next & AT91_NEXT_MASK) != 0 || -	    (priv->tx_echo & AT91_NEXT_MASK) == 0) +	if ((priv->tx_next & get_next_mask(priv)) != 0 || +	    (priv->tx_echo & get_next_mask(priv)) == 0)  		netif_wake_queue(dev);  } @@ -906,6 +999,29 @@ static void at91_irq_err_state(struct net_device *dev,  	at91_write(priv, AT91_IER, reg_ier);  } +static int at91_get_state_by_bec(const struct net_device *dev, +		enum can_state *state) +{ +	struct can_berr_counter bec; +	int err; + +	err = at91_get_berr_counter(dev, &bec); +	if (err) +		return err; + +	if (bec.txerr < 96 && bec.rxerr < 96) +		*state = CAN_STATE_ERROR_ACTIVE; +	else if (bec.txerr < 128 && bec.rxerr < 128) +		*state = CAN_STATE_ERROR_WARNING; +	else if (bec.txerr < 256 && bec.rxerr < 256) +		*state = CAN_STATE_ERROR_PASSIVE; +	else +		*state = CAN_STATE_BUS_OFF; + +	return 0; +} + +  static void at91_irq_err(struct net_device *dev)  {  	struct at91_priv *priv = netdev_priv(dev); @@ -913,21 +1029,28 @@ static void at91_irq_err(struct net_device *dev)  	struct can_frame *cf;  	enum can_state new_state;  	u32 reg_sr; +	int err; -	reg_sr = at91_read(priv, AT91_SR); - -	/* we need to look at the unmasked reg_sr */ -	if (unlikely(reg_sr & AT91_IRQ_BOFF)) -		new_state = CAN_STATE_BUS_OFF; -	else if (unlikely(reg_sr & AT91_IRQ_ERRP)) -		new_state = CAN_STATE_ERROR_PASSIVE; -	else if (unlikely(reg_sr & AT91_IRQ_WARN)) -		new_state = CAN_STATE_ERROR_WARNING; -	else if (likely(reg_sr & AT91_IRQ_ERRA)) -		new_state = CAN_STATE_ERROR_ACTIVE; -	else { -		netdev_err(dev, "BUG! hardware in undefined state\n"); -		return; +	if (at91_is_sam9263(priv)) { +		reg_sr = at91_read(priv, AT91_SR); + +		/* we need to look at the unmasked reg_sr */ +		if (unlikely(reg_sr & AT91_IRQ_BOFF)) +			new_state = CAN_STATE_BUS_OFF; +		else if (unlikely(reg_sr & AT91_IRQ_ERRP)) +			new_state = CAN_STATE_ERROR_PASSIVE; +		else if (unlikely(reg_sr & AT91_IRQ_WARN)) +			new_state = CAN_STATE_ERROR_WARNING; +		else if (likely(reg_sr & AT91_IRQ_ERRA)) +			new_state = CAN_STATE_ERROR_ACTIVE; +		else { +			netdev_err(dev, "BUG! hardware in undefined state\n"); +			return; +		} +	} else { +		err = at91_get_state_by_bec(dev, &new_state); +		if (err) +			return;  	}  	/* state hasn't changed */ @@ -968,19 +1091,19 @@ static irqreturn_t at91_irq(int irq, void *dev_id)  	handled = IRQ_HANDLED;  	/* Receive or error interrupt? -> napi */ -	if (reg_sr & (AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME)) { +	if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {  		/*  		 * The error bits are clear on read,  		 * save for later use.  		 */  		priv->reg_sr = reg_sr;  		at91_write(priv, AT91_IDR, -			   AT91_IRQ_MB_RX | AT91_IRQ_ERR_FRAME); +			   get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);  		napi_schedule(&priv->napi);  	}  	/* Transmission complete interrupt */ -	if (reg_sr & AT91_IRQ_MB_TX) +	if (reg_sr & get_irq_mb_tx(priv))  		at91_irq_tx(dev, reg_sr);  	at91_irq_err(dev); @@ -1123,6 +1246,8 @@ static struct attribute_group at91_sysfs_attr_group = {  static int __devinit at91_can_probe(struct platform_device *pdev)  { +	const struct at91_devtype_data *devtype_data; +	enum at91_devtype devtype;  	struct net_device *dev;  	struct at91_priv *priv;  	struct resource *res; @@ -1130,6 +1255,9 @@ static int __devinit at91_can_probe(struct platform_device *pdev)  	void __iomem *addr;  	int err, irq; +	devtype = pdev->id_entry->driver_data; +	devtype_data = &at91_devtype_data[devtype]; +  	clk = clk_get(&pdev->dev, "can_clk");  	if (IS_ERR(clk)) {  		dev_err(&pdev->dev, "no clock defined\n"); @@ -1157,7 +1285,8 @@ static int __devinit at91_can_probe(struct platform_device *pdev)  		goto exit_release;  	} -	dev = alloc_candev(sizeof(struct at91_priv), AT91_MB_TX_NUM); +	dev = alloc_candev(sizeof(struct at91_priv), +			   1 << devtype_data->tx_shift);  	if (!dev) {  		err = -ENOMEM;  		goto exit_iounmap; @@ -1166,7 +1295,6 @@ static int __devinit at91_can_probe(struct platform_device *pdev)  	dev->netdev_ops	= &at91_netdev_ops;  	dev->irq = irq;  	dev->flags |= IFF_ECHO; -	dev->sysfs_groups[0] = &at91_sysfs_attr_group;  	priv = netdev_priv(dev);  	priv->can.clock.freq = clk_get_rate(clk); @@ -1174,13 +1302,18 @@ static int __devinit at91_can_probe(struct platform_device *pdev)  	priv->can.do_set_mode = at91_set_mode;  	priv->can.do_get_berr_counter = at91_get_berr_counter;  	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; -	priv->reg_base = addr;  	priv->dev = dev; +	priv->reg_base = addr; +	priv->devtype_data = *devtype_data; +	priv->devtype_data.type = devtype;  	priv->clk = clk;  	priv->pdata = pdev->dev.platform_data;  	priv->mb0_id = 0x7ff; -	netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT); +	netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv)); + +	if (at91_is_sam9263(priv)) +		dev->sysfs_groups[0] = &at91_sysfs_attr_group;  	dev_set_drvdata(&pdev->dev, dev);  	SET_NETDEV_DEV(dev, &pdev->dev); @@ -1230,13 +1363,26 @@ static int __devexit at91_can_remove(struct platform_device *pdev)  	return 0;  } +static const struct platform_device_id at91_can_id_table[] = { +	{ +		.name = "at91_can", +		.driver_data = AT91_DEVTYPE_SAM9263, +	}, { +		.name = "at91sam9x5_can", +		.driver_data = AT91_DEVTYPE_SAM9X5, +	}, { +		/* sentinel */ +	} +}; +  static struct platform_driver at91_can_driver = { -	.probe		= at91_can_probe, -	.remove		= __devexit_p(at91_can_remove), -	.driver		= { -		.name	= KBUILD_MODNAME, -		.owner	= THIS_MODULE, +	.probe = at91_can_probe, +	.remove = __devexit_p(at91_can_remove), +	.driver = { +		.name = KBUILD_MODNAME, +		.owner = THIS_MODULE,  	}, +	.id_table = at91_can_id_table,  };  static int __init at91_can_module_init(void)  | 
