ckfwq/linux-3.0.4/drivers/net/can/gsc3280_can.c-new

888 lines
22 KiB
Plaintext

/*
* gsc3280_can.c - CAN network driver for GSC3280 SoC CAN controller
*
* (C) 2013 by Clive Chen, chenguangyu@china-cpu.com
* (C) 2016 by Merlin Song, songxingjia@china-cpu.com
*
* This software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2 as distributed in the 'COPYING'
* file from the main directory of the linux kernel source.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*
* Your platform definition file should specify something like:
*
* static struct at91_can_data ek_can_data = {
* transceiver_switch = sam9263ek_transceiver_switch,
* };
*
* at91_add_device_can(&ek_can_data);
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/cpu.h>
#include <asm/cpu.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include "gsc3280_can.h"
#define DRV_NAME "gsc3280-can"
#define TX_ECHO_SKB_MAX 1
#ifdef CONFIG_GSC3280_CAN_DEBUG
#define DBG(msg...) do { \
printk(KERN_INFO msg); \
} while (0)
#else
#define DBG(msg...) do { } while(0)
#endif
/****************gsc3280 can module register enum************************/
enum gsc3280_reg {
CAN_MOD = 0x00,
CAN_CMR = 0x04,
CAN_SR = 0x08,
CAN_IR = 0x0C,
CAN_IER = 0x10,
CAN_BTR = 0x14,
CAN_ALC = 0x18,
CAN_ECC = 0x1C,
CAN_EWLR = 0x20,
CAN_RXERR = 0x24,
CAN_TXERR = 0x28,
CAN_RMC = 0x2C,
CAN_ACR = 0x80,
CAN_AMR = 0x84,
CAN_TXB0 = 0x80,
CAN_TXB1 = 0x84,
CAN_TXB2 = 0x88,
CAN_TXB3 = 0x8C,
CAN_RXB0 = 0x80,
CAN_RXB1 = 0x84,
CAN_RXB2 = 0x88,
CAN_RXB3 = 0x8C,
};
enum BLX_devtype {
BLX_DEVTYPE_GSC3280,
};
struct gsc3280_priv{
struct can_priv can; /*must be the first member!*/
struct net_device *dev;
void __iomem *reg_base;
int open_time;
void (*pre_irq) (const struct gsc3280_priv *priv);
void (*post_irq) (const struct gsc3280_priv *priv);
u32 reg_sr;
int irq;
unsigned short *pin_list;
spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
};
static inline u32 gsc3280_read(const struct gsc3280_priv *priv, enum gsc3280_reg reg)
{
return __raw_readl((priv->reg_base + reg) + 0xa0000000);
}
static inline void gsc3280_write(const struct gsc3280_priv *priv, enum gsc3280_reg reg, u32 value )
{
__raw_writel(value, (priv->reg_base + reg + 0xa0000000));
}
static struct can_bittiming_const gsc3280_can_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 1,
.tseg1_max = 16,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 2,
.brp_max = 128,
.brp_inc = 1,
};
/*
* gsc3280_can_set_reset_mode - gsc3280 can set reset mode routine
* @dev net device structure
*/
static void gsc3280_can_set_reset_mode (struct net_device *dev)
{
struct gsc3280_priv *priv = netdev_priv(dev);
int i;
unsigned char status = gsc3280_read(priv, CAN_MOD) & 0xff;
DBG("status is 0x%x, GSC3280_IER 0x%2x,IRQ_OFF 0x%2x\n", status, GSC3280_IER, IRQ_OFF);
/* disable interrupts */
gsc3280_write(priv, CAN_IER, IRQ_OFF);
for (i = 0; i < 100; i++) {
/* check reset bit */
if (status & MOD_RM) {
priv->can.state = CAN_STATE_STOPPED;
return ;
}
/* reset chip */
gsc3280_write(priv, CAN_MOD, MOD_RM);
udelay(10);
status = gsc3280_read(priv, CAN_MOD) & 0xff;
}
DBG("setting GSC3280 CAN into reset mode failed!\n");
}
/*
* gsc3280_can_set_normal_mode - gsc3280 can set normal mode routine
* @dev net device structure
*/
static void gsc3280_can_set_normal_mode(struct net_device *dev)
{
struct gsc3280_priv *priv = netdev_priv(dev);
int i;
u32 status = gsc3280_read ( priv, CAN_MOD );
/*printk("Enter gsc3280_can_set_normal_mod, reg_base is %x\n", priv->reg_base);*/
for ( i = 0; i < 100; i++){
/* check reset bit */
if (( status & MOD_RM) == 0) {
/* enable interrupts */
priv->can.state = CAN_STATE_ERROR_ACTIVE;
gsc3280_write(priv, CAN_IER, IRQ_ALL);
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
gsc3280_write(priv, CAN_IER, IRQ_ALL);
else
gsc3280_write(priv, CAN_IER, IRQ_ALL & ~IRQ_BEI);
return;
}
/* set chip to normal mode */
gsc3280_write (priv, CAN_MOD, 0x00);
udelay(10);
status = gsc3280_read ( priv, CAN_MOD);
DBG("normal_mod status is 0x%x, mode is 0x%x\n", status, mode);
}
DBG("setting GSC3280 CAN into normal mode failed!\n");
}
/*
* gsc3280_can_start - gsc3280 can start routine
* @dev net device structure
*/
static void gsc3280_can_start(struct net_device *dev)
{
struct gsc3280_priv *priv = netdev_priv(dev);
/* leave reset mode */
if (priv->can.state != CAN_STATE_STOPPED)
gsc3280_can_set_reset_mode(dev);
/* Clear error counters and error code capture */
gsc3280_write (priv, CAN_TXERR, 0x0 );
gsc3280_write (priv, CAN_RXERR, 0x0 );
gsc3280_read(priv, CAN_ECC);
/* leave reset mode */
gsc3280_can_set_normal_mode(dev);
}
/*
* gsc3280_can_set_bittiming - get can controller bittimg parameters from app
* @dev: netdevice structure
*/
static int gsc3280_can_set_bittiming(struct net_device *dev)
{
struct gsc3280_priv *priv = netdev_priv(dev);
struct can_bittiming *bt = &priv->can.bittiming;
unsigned int btr;
uint8_t tseg1, tseg2, sjw, brp, sam;
//fxtal = priv->can.clock.freq;
tseg1 = (bt->prop_seg + bt->phase_seg1 - 1) & 0xf;
tseg2 = (bt->phase_seg2 - 1) & 0x7;
sjw = (bt->sjw - 1) & 0x3;
brp = (bt->brp - 1) & 0x3f ;
btr = (tseg2<<12) | (tseg1<<8) | (sjw<<6) | brp;
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
{
sam = 0x1;
btr = btr| (sam<<15);
}
gsc3280_write ( priv, CAN_BTR, btr );
btr = gsc3280_read ( priv, CAN_BTR);
DBG("Setting CAN BTR=0x%04x\n",btr);
return 0;
}
static int gsc3280_can_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
{
struct gsc3280_priv *priv = netdev_priv(dev);
bec->txerr = gsc3280_read(priv, CAN_TXERR);
bec->rxerr = gsc3280_read(priv, CAN_RXERR);
return 0;
}
/*
* gsc3280_can_start_xmit - can controller transmiter function
* @dev: netdevice structure
* @skb: socket buffer structure
*/
static int gsc3280_can_start_xmit ( struct sk_buff * skb , struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
struct can_frame *cf = ( struct can_frame *)skb->data;
uint8_t fi;
uint8_t dlc;
canid_t id;
unsigned long flags;
u32 buf1,buf2;
DBG("Enter gsc3280_can_start_xmit\n");
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
netif_stop_queue(dev);
fi = dlc = cf->can_dlc;
id = cf->can_id;
DBG(" can_dlc 0x%x \n", cf->can_dlc);
DBG(" can_id 0x%x \n", cf->can_id);
//if(fi & FI_RTR){
if((id>>24) & FI_RTR)
{
fi |= FI_RTR;
DBG("remote frame |");
gsc3280_write(priv, CAN_TXB0, fi);
}else{
DBG("data frame |");
}
//if( fi & FI_FF )
if((id>>24) & FI_FF)
{
DBG("extend");
fi |= FI_FF;
gsc3280_write (priv, CAN_TXB0, fi);
DBG("id=0x%x, \n", id<<3);
gsc3280_write (priv, CAN_TXB1, id<<3);
}else{
DBG("standard");
gsc3280_write (priv, CAN_TXB0, fi);
DBG("id=0x%x, \n",id);
gsc3280_write (priv, CAN_TXB1, id<<21);
}
DBG ("ID: %x |", id);
if (dlc){
DBG("dlc = %d \n", dlc);
DBG("DATA:%x %x %x %x %x %x %x %x", cf->data[0], cf->data[1],cf->data[2],cf->data[3],cf->data[4],cf->data[5],cf->data[6],cf->data[7]);
buf1= ((cf->data[3]&0xff)<<24) | ((cf->data[2]&0xff)<<16) | ((cf->data[1]&0xff)<<8) | (cf->data[0]);
DBG("GSC3280_TXB3 data %x \n",buf1);
buf2= ((cf->data[7]&0xff)<<24) | ((cf->data[6]&0xff)<<16) | ((cf->data[5]&0xff)<<8) | (cf->data[4]);
DBG("GSC3280_TXB4 data %x \n",buf2);
gsc3280_write ( priv, CAN_TXB2, buf1);
gsc3280_write ( priv, CAN_TXB3, buf2);
}
can_put_echo_skb ( skb, dev, 0 );
while (!(gsc3280_read(priv, CAN_SR) & 0x4)); /*tx fifo ok*/
spin_lock_irqsave(&priv->cmdreg_lock, flags);
gsc3280_write(priv, CAN_CMR, CMD_TR);
spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
while (!(gsc3280_read(priv, CAN_SR) & 0x8)); /*tx fifo ok*/
#if 0
printk("REG info: \n");
printk("REG CAN_ALC: 0x%08x \n", gsc3280_read(priv, CAN_ALC));
printk("REG CAN_ECC: 0x%08x \n", gsc3280_read(priv, CAN_ECC));
printk("REG CAN_EWLR: 0x%08x \n", gsc3280_read(priv, CAN_EWLR));
printk("REG CAN_RXERR: 0x%08x \n", gsc3280_read(priv, CAN_RXERR));
printk("REG CAN_TXERR: 0x%08x \n", gsc3280_read(priv, CAN_TXERR));
printk("T over \n");
#endif
return NETDEV_TX_OK;
}
/*
* gsc3280_can_rx - gsc3280 can receive routine
* @dev net device structure
*/
static void gsc3280_can_rx ( struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
unsigned long flags;
unsigned char ff;
unsigned char fi;
unsigned char id;
unsigned char dlc;
skb = alloc_can_skb(dev, &cf);
if ( skb == NULL )
return;
/*struct net_device *dev = dev_id;*/
DBG("Enter gsc3280_can_rx\n");
ff = gsc3280_read ( priv, CAN_RXB0);
fi = ff & 0xc0;
dlc = ff & 0x0F;
cf->can_dlc = get_can_dlc(dlc);
DBG( "rx: ff is 0x%x,fi is 0x%x,dlc is 0x%x\n", ff, fi, dlc );
if ( fi & FI_FF ){
/* extended frame format (EFF) */
DBG("extend ");
id = (gsc3280_read (priv, CAN_RXB1)) >> 3;
}else {
/* standard frame format (SFF) */
DBG("standard ");
id = (gsc3280_read (priv, CAN_RXB1)) >> 21;
}
cf->can_id = id;
DBG("ID: %x |", id);
if ( fi & FI_RTR ){
DBG("remote frame |");
}else{
DBG("data frame |");
}
if (dlc){
cf->data[0] = gsc3280_read ( priv, CAN_RXB2);
cf->data[1] = (gsc3280_read ( priv, CAN_RXB2))>>8;
cf->data[2] = (gsc3280_read ( priv, CAN_RXB2))>>16;
cf->data[3] = (gsc3280_read ( priv, CAN_RXB2))>>24;
cf->data[4] = gsc3280_read ( priv, CAN_RXB3);
cf->data[5] = (gsc3280_read ( priv, CAN_RXB3))>>8;
cf->data[6] = (gsc3280_read ( priv, CAN_RXB3))>>16;
cf->data[7] = (gsc3280_read ( priv, CAN_RXB3))>>24;
DBG("DATA: ");
DBG("%x", gsc3280_read(priv, CAN_RXB3));
DBG("%x", gsc3280_read(priv, CAN_RXB2));
}
netif_rx (skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
spin_lock_irqsave(&priv->cmdreg_lock, flags);
gsc3280_write(priv, CAN_CMR, CMD_RRB);
spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
#if 0
printk("REG info: \n");
printk("REG CAN_ALC: 0x%08x \n", gsc3280_read(priv, CAN_ALC));
printk("REG CAN_ECC: 0x%08x \n", gsc3280_read(priv, CAN_ECC));
printk("REG CAN_EWLR: 0x%08x \n", gsc3280_read(priv, CAN_EWLR));
printk("REG CAN_RXERR: 0x%08x \n", gsc3280_read(priv, CAN_RXERR));
printk("REG CAN_TXERR: 0x%08x \n", gsc3280_read(priv, CAN_TXERR));
printk("R over!\n");
#endif
}
static int gsc3280_can_err ( struct net_device * dev, u8 isrc, u8 status )
{
struct gsc3280_priv *priv = netdev_priv (dev);
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
uint8_t ecc, alc;
enum can_state state = priv->can.state;
DBG("Enter gsc3280_can_err\n");
skb = alloc_can_err_skb ( dev, &cf );
if ( skb == NULL )
return -ENOMEM;
if ( isrc & IRQ_DOI )
{
/* data overrun interrupt */
DBG("data overflow interrupt\n" );
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
stats->rx_over_errors++;
stats->rx_errors++;
/* gsc3280 can controllor used read reg clear bit */
/* read CAN_IR or set reset mode can clear it */
}
if ( isrc & IRQ_EI ) {
/* error warning interrupt */
DBG("error warning interrupt\n");
if (status & SR_BS) {
state = CAN_STATE_BUS_OFF;
cf->can_id |= CAN_ERR_BUSOFF;
can_bus_off(dev);
} else if (status & SR_ES) {
state = CAN_STATE_ERROR_WARNING;
} else
state = CAN_STATE_ERROR_ACTIVE;
}
if (isrc & IRQ_BEI) {
/* bus error interrupt */
priv->can.can_stats.bus_error++;
stats->rx_errors++;
ecc = gsc3280_read(priv, CAN_ECC);
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
switch (ecc & ECC_MASK) {
case ECC_BIT:
cf->data[2] |= CAN_ERR_PROT_BIT;
break;
case ECC_FORM:
cf->data[2] |= CAN_ERR_PROT_FORM;
break;
case ECC_STUFF:
cf->data[2] |= CAN_ERR_PROT_STUFF;
break;
default:
cf->data[2] |= CAN_ERR_PROT_UNSPEC;
cf->data[3] = ecc & ECC_SEG;
break;
}
/* Error occurred during transmission? */
if ((ecc & ECC_DIR) == 0)
cf->data[2] |= CAN_ERR_PROT_TX;
}
if ( isrc & IRQ_EPI )
{
/* error passive interrupt */
DBG( "error passive interrupt\n");
if (status & SR_ES)
state = CAN_STATE_ERROR_PASSIVE;
else
state = CAN_STATE_ERROR_ACTIVE;
}
if (isrc & IRQ_ALI) {
/* arbitration lost interrupt */
DBG("arbitration lost interrupt\n");
alc = gsc3280_read(priv, CAN_ALC);
priv->can.can_stats.arbitration_lost++;
stats->tx_errors++;
cf->can_id |= CAN_ERR_LOSTARB;
cf->data[0] = alc & 0x1f;
}
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
uint8_t rxerr = gsc3280_read(priv, CAN_RXERR);
uint8_t txerr = gsc3280_read(priv, CAN_TXERR);
cf->can_id |= CAN_ERR_CRTL;
if (state == CAN_STATE_ERROR_WARNING) {
priv->can.can_stats.error_warning++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
} else {
priv->can.can_stats.error_passive++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
}
cf->data[6] = txerr;
cf->data[7] = rxerr;
}
priv->can.state = state;
netif_rx ( skb );
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
return 0;
}
irqreturn_t gsc3280_can_interrupt ( int irq, void * dev_id )
{
struct net_device *dev = dev_id;
struct gsc3280_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
uint8_t status, isrc;
/* Shared interrupts and IRQ off? */
if (gsc3280_read(priv, CAN_IER) == IRQ_OFF)
return IRQ_NONE;
if (priv->pre_irq)
priv->pre_irq(priv);
while ((isrc = gsc3280_read(priv, CAN_IR)))
{
status = gsc3280_read( priv, CAN_SR);
if(isrc & IRQ_TI ){
/*trammiter interrupt*/
DBG("Enter gsc3280_can_interrupt tx\n");
stats->tx_bytes += gsc3280_read (priv, CAN_TXB0)&0xf;
stats->tx_packets++;
can_get_echo_skb ( dev, 0 );
netif_wake_queue ( dev );
}
if( isrc & IRQ_RI ){
/*receive interrupt*/
DBG("Enter gsc3280_can_interrupt rx\n");
while (status & SR_RBS) {
gsc3280_can_rx ( dev );
status = gsc3280_read(priv, CAN_SR);
}
}
if (isrc & IRQ_WUI){
DBG("wakeup interrupt\n");
}
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
/* error interrupt */
if (gsc3280_can_err(dev, isrc, status))
break;
}
}
if (priv->post_irq)
priv->post_irq(priv);
return IRQ_HANDLED;
}
/*
* gsc3280_can_open - gsc3280 can open routine
* @dev net device structure
*/
static int gsc3280_can_open ( struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
int err;
DBG(" gsc3280_can_open \n");
gsc3280_can_set_reset_mode(dev);
err = open_candev(dev);
if(err)
goto exit_open;
err = request_irq(priv->irq, &gsc3280_can_interrupt, 0, "gsc3280-can-irq" , dev);
if(err)
goto exit_err_irq;
/*this must set in reset mode*/
// gsc3280_write(priv, CAN_ACR, 0x100);
// gsc3280_write(priv, CAN_AMR, 0xffffffff);
gsc3280_can_start(dev);
priv->open_time = jiffies;
netif_start_queue (dev);
return 0;
exit_err_irq:
close_candev(dev);
free_irq(priv->irq,dev);
exit_open:
return err;
}
static int gsc3280_can_close ( struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
DBG("Enter gsc3280_can_close\n");
netif_stop_queue (dev);
gsc3280_can_set_reset_mode(dev);
close_candev(dev);
free_irq(priv->irq,dev);
priv->open_time = 0;
return 0;
}
static int gsc3280_can_set_mode(struct net_device *dev, enum can_mode mode)
{
struct gsc3280_priv *priv = netdev_priv(dev);
if (!priv->open_time)
return -EINVAL;
switch (mode) {
case CAN_MODE_START:
gsc3280_can_start(dev);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
struct net_device *alloc_gsc3280_candev(void)
{
struct net_device *dev;
struct gsc3280_priv *priv;
dev = alloc_candev ( sizeof(*priv), TX_ECHO_SKB_MAX);
DBG("alloc_gsc3280_candev,dev is 0x%x, dev->dev is 0x%x\n", dev, dev->dev);
if ( !dev)
return NULL;
priv = netdev_priv (dev);
priv->dev = dev;
priv->can.bittiming_const = &gsc3280_can_bittiming_const;
priv->can.do_set_bittiming = gsc3280_can_set_bittiming;
//priv->can.do_set_mode = gsc3280_can_set_mode;
priv->can.do_set_mode = gsc3280_can_set_reset_mode;
priv->can.do_get_berr_counter = gsc3280_can_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
spin_lock_init(&priv->cmdreg_lock);
return dev;
}
static const struct net_device_ops gsc3280_can_netdev_ops = {
.ndo_open = gsc3280_can_open,
.ndo_stop = gsc3280_can_close,
.ndo_start_xmit = gsc3280_can_start_xmit,
};
static int __devinit gsc3280_can_probe (struct platform_device *pdev)
{
struct net_device *dev;
struct gsc3280_priv *priv;
struct resource *res_mem, *irq;
struct clk *clk;
unsigned long rate;
unsigned short *pdata;
int err;
//void __iomem *addr;
//SYSCTL_CLK_DIV_CAN;
*(volatile unsigned int *)0xbc04a030 = 0x1; // rate=55.6M/2
//__raw_writel( 0x1 , 0xbc04a030); // rate=55.6M/2
//__raw_writel( 0x9 , 0xbc04a030); // rate=55.6M/10
//__raw_writel( 0x1f , 0xbc04a030); // rate=55.6M/32
clk = clk_get ( &pdev->dev , "can" );
rate = clk_get_rate ( clk );
clk_set_rate(clk, rate);
if ( IS_ERR(clk)){
DBG("no clock defined\n");
err = -ENODEV;
goto exit;
}
pdata = pdev->dev.platform_data;
if(!pdata){
DBG("No platform data provided!\n");
err = -EINVAL;
goto exit;
}
res_mem = platform_get_resource (pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource (pdev, IORESOURCE_IRQ, 0);
DBG("res_mem is 0x%x, irq is %d\n", res_mem->start, irq->start);
/* if ( !res_mem || irq<0 || !tx_irq || !rx_irq ){
err = -ENODEV;
goto exit;
}
*/
if (!request_mem_region( res_mem->start , resource_size(res_mem), dev_name(&pdev->dev) )){
printk("request_mem_region is null\n");
err = -ENOMEM;
goto exit_release;
}
dev = alloc_gsc3280_candev();
if (!dev){
err = -ENOMEM;
goto exit_iounmap;
}
priv = netdev_priv (dev);
priv->can.clock.freq = rate;
priv->can.bittiming_const = &gsc3280_can_bittiming_const;
priv->can.do_set_bittiming = gsc3280_can_set_bittiming;
priv->can.do_get_berr_counter = gsc3280_can_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
priv->dev = dev;
priv->reg_base = (void __iomem*) (res_mem->start);
/* DBG("priv->reg_base is 0x%x\n", priv->reg_base);*/
priv->irq = irq->start;
priv->pin_list = pdata;
DBG("priv_irq is %d\n", priv->irq);
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
dev->netdev_ops = &gsc3280_can_netdev_ops;
dev->flags |= IFF_ECHO;
gsc3280_can_set_reset_mode(dev);
gsc3280_can_set_bittiming(dev);
err = register_candev(dev);
if(err){
DBG("registering netdev failed\n");
goto exit_free;
}
DBG("device registered (reg_base=0x%x,irq=%d)\n", priv->reg_base, priv->irq);
return 0;
exit_free:
free_candev(dev);
exit_iounmap:
// iounmap(addr);
exit_release:
release_mem_region ( res_mem->start, resource_size(res_mem));
exit:
return err;
}
static int __devexit gsc3280_can_remove ( struct platform_device *pdev )
{
struct net_device *dev = dev_get_drvdata ( &pdev->dev );
/* struct gsc3280_priv *priv = netdev_priv (dev);*/
struct resource *res;
gsc3280_can_set_reset_mode(dev);
unregister_candev(dev);
dev_set_drvdata(&pdev->dev, NULL);
res = platform_get_resource ( pdev, IORESOURCE_MEM, 0 );
release_mem_region (res->start, resource_size(res));
free_candev(dev);
return 0;
}
static const struct platform_device_id gsc3280_can_id_table[] = {
{
.name = "gsc3280_can_driver",
.driver_data = BLX_DEVTYPE_GSC3280,
},{
}
};
static struct platform_driver gsc3280_can_driver = {
.probe = gsc3280_can_probe,
.remove = __devexit_p ( gsc3280_can_remove ),
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
.id_table = gsc3280_can_id_table,
};
static int __init gsc3280_can_module_init (void)
{
printk("gsc3280_can_init\n");
return platform_driver_register (&gsc3280_can_driver);
}
static void __exit gsc3280_can_module_exit (void)
{
platform_driver_unregister(&gsc3280_can_driver);
}
module_init(gsc3280_can_module_init);
module_exit(gsc3280_can_module_exit);
MODULE_AUTHOR("Merlin Song <songxingjia@china-cpu.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION(KBUILD_MODNAME " CAN netdevice driver");