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

856 lines
22 KiB
Plaintext

/*
* GSC3280 SoC CAN controller Controller Driver
*
* Copyright (C) 2013 BLX IC Design Corp.,Ltd.
* Author: Clive Chen, chenguangyu@china-cpu.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/clk.h>
#include <linux/cpu.h>
#include <asm/cpu.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include "gsc3280_can.h"
/****************gsc3280 can module register enum************************/
enum gsc3280_reg {
GSC3280_MOD = 0x000,
GSC3280_CMR = 0x004,
GSC3280_SR = 0x008,
GSC3280_IR = 0x00C,
GSC3280_IER = 0x010,
GSC3280_BTR = 0x014,
GSC3280_ALC = 0x018,
GSC3280_ECC = 0x01C,
GSC3280_EWLR = 0x020,
GSC3280_RXERR = 0x024,
GSC3280_TXERR = 0x028,
GSC3280_RMC = 0x02C, /*there is a error in datasheet */
GSC3280_ACR = 0x080,
GSC3280_AMR = 0x084,
GSC3280_TXB1 = 0x080,
GSC3280_TXB2 = 0x084,
GSC3280_TXB3 = 0x088,
GSC3280_TXB4 = 0x08C,
GSC3280_RXB1 = 0x080,
GSC3280_RXB2 = 0x084,
GSC3280_RXB3 = 0x088,
GSC3280_RXB4 = 0x08C,
};
enum BLX_devtype {
BLX_DEVTYPE_GSC3280,
};
/* no need to be used in this file*/
struct BLX_devtype_data {
unsigned int rx_first;
unsigned int rx_split;
unsigned int rx_last;
unsigned int tx_shift;
enum BLX_devtype type;
};
struct gsc3280_priv{
struct can_priv can; /*must be the first member!*/
struct net_device *dev;
void __iomem *reg_base;
u32 reg_sr;
int irq;
unsigned short *pin_list;
};
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));
}
#define DRV_NAME "gsc3280_can"
static struct can_bittiming gsc3280_can_bittiming = {
.bitrate = 500000, /* Bit-rate in bits/second */
.sample_point = 2, /* Sample point in one-tenth of a percent */
.tq = 50, /* Time quanta (TQ) in nanoseconds */
.prop_seg = 1, /* Propagation segment in TQs */
.phase_seg1 = 4, /* Phase buffer segment 1 in TQs */
.phase_seg2 = 5, /* Phase buffer segment 2 in TQs */
.sjw = 4, /* Synchronisation jump width in TQs */
.brp = 4, /* Bit-rate prescaler */
};
/***** according the set of datasheet*****/
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_print_regs - gsc3280 debug routine
* @if need debug the can registers, uncomment of content of routine
*/
static void gsc3280_print_regs( void )
{
/* int i=0;
unsigned int *cc;
cc = (unsigned int *)0xbc100000;
for ( i = 0; i<10; i++)
{
printk("cc: %x, %x\n",cc, *cc);
cc=cc+1;
}
*/
}
/*
* gsc3280_can_set_normal_mod - gsc3280 can set normal mode routine
* @dev net device structure
* @mode gsc3280 can mode
*/
static void gsc3280_can_set_normal_mod (struct net_device *dev, int mode)
{
struct gsc3280_priv *priv = netdev_priv(dev);
int i;
u32 status = gsc3280_read ( priv, GSC3280_MOD );
/*printk("Enter gsc3280_can_set_normal_mod, reg_base is %x\n", priv->reg_base);*/
for ( i = 0; i < 100; i++){
if (( status & MOD_RM) == 0 || ( status&( MOD_SM | MOD_STM | MOD_LOM))){
gsc3280_write(priv, GSC3280_IER, IRQ_ALL);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
return;
}
gsc3280_write (priv, GSC3280_MOD, mode);
udelay(10);
status = gsc3280_read ( priv, GSC3280_MOD);
printk(KERN_INFO "normal_mod status is 0x%x, mode is 0x%x\n", status, mode);
}
}
/*
* gsc3280_can_set_reset_mod - gsc3280 can set reset mode routine
* @dev net device structure
*/
static void gsc3280_can_set_reset_mod ( struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
int i;
unsigned char status = gsc3280_read ( priv, GSC3280_MOD ) & 0xff;
printk( "status 1 is 0x%x, GSC3280_IER 0x%2x,IRQ_OFF 0x%2x\n", status, GSC3280_IER, IRQ_OFF);
gsc3280_write ( priv, GSC3280_IER, IRQ_OFF);
for ( i=0; i<100; i++)
{
if ( status & MOD_RM){
priv->can.state = CAN_STATE_STOPPED;
return;
}
gsc3280_write ( priv, GSC3280_MOD, MOD_RM);
status = gsc3280_read(priv, GSC3280_MOD);
printk(KERN_INFO "status 2 is 0x%x\n", status);
}
}
/*
* gsc3280_can_start - gsc3280 can start routine
* @dev net device structure
* @mode gsc3280 can mode
*/
static void gsc3280_can_start (struct net_device *dev, int mode)
{
struct gsc3280_priv *priv = netdev_priv(dev);
gsc3280_write ( priv, GSC3280_TXERR, 0x0 );
gsc3280_write ( priv, GSC3280_RXERR, 0x0 );
gsc3280_can_set_normal_mod(dev, mode);
}
/*
* gsc3280_can_set_bittimg - 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;
int fxtal;
unsigned int btr;
u8 btr0, btr1;
fxtal = priv->can.clock.freq;
printk(KERN_INFO "Enter gsc3280_can_set_bittiming\n");
/* btr = (bt->sample_point << 15) | ((bt->phase_seg2 - 1) << 12 ) | (bt->phase_seg1 - 1 ) << 8 | (( bt->sjw - 1 ) << 6 ) | ( bt->brp - 1 );*/
btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
(((bt->phase_seg2 - 1) & 0x7) << 4);
/* if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) */
if (bt->bitrate < 250000 )
btr1 |= 0x80;
btr = (btr1<<8) | btr0;
printk (KERN_INFO " btr0 is 0x%02x, btr1 is 0x%02x, btr = 0x%x\n", btr0, btr1, btr );
gsc3280_write ( priv, GSC3280_BTR, btr );
/* dev_info(dev->dev.parent, "setting brp=0x%04x\n",btr); */
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 ff;
uint8_t fi;
uint8_t dlc;
canid_t id;
printk("Enter gsc3280_can_start_xmit\n");
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
netif_stop_queue(dev);
/*need to be changed ff and canid_id*/
fi = dlc = cf->can_dlc;
id = cf->can_id;
ff = cf->can_id & 0xff;
printk(KERN_INFO "tx :");
if( fi & FI_FF )
{
printk (KERN_INFO "extend" );
ff |= FI_FF;
gsc3280_write (priv, GSC3280_TXB1, ff);
gsc3280_write (priv, GSC3280_TXB2, id<<3);
}else
{
printk (KERN_INFO "standard");
gsc3280_write (priv,GSC3280_TXB1, ff);
gsc3280_write (priv,GSC3280_TXB2, id<<20);
}
if(fi & FI_RTR){
ff |= FI_RTR;
printk("remote frame |");
}else{
printk("data frame |");
}
printk (KERN_INFO "ID: %x |", id);
if (dlc){
printk(KERN_INFO "DATA:%x %x", cf->data[0], cf->data[1]);
gsc3280_write ( priv, GSC3280_TXB3, cf->data[0]);
gsc3280_write ( priv, GSC3280_TXB4, cf->data[1]);
}
can_put_echo_skb ( skb, dev, 0 );
while (!(gsc3280_read(priv, GSC3280_SR) & 0x4)); /*tx fifo ok*/
gsc3280_write(priv, GSC3280_CMR, CMD_TR);
while (!(gsc3280_read(priv, GSC3280_SR) & 0x8)); /*tx fifo ok*/
printk("tok \n");
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;
/*void __iomem *reg = priv->reg_base;*/
struct can_frame *cf;
struct sk_buff *skb;
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;*/
printk("Enter gsc3280_can_rx\n");
ff = gsc3280_read ( priv, GSC3280_RXB1 );
fi = ff & 0xc0;
dlc = ff & 0x0F;
/* cf->can_id = fi;*/
cf->can_dlc = get_can_dlc(dlc);
printk ( "rx: ff is 0x%x,fi is 0x%x,dlc is 0x%x\n", ff, fi, dlc );
if ( fi & FI_FF ){
printk (KERN_INFO "extend ");
id = (gsc3280_read (priv, GSC3280_RXB2)) >> 3;
}else {
printk (KERN_INFO "standard ");
id = (gsc3280_read (priv, GSC3280_RXB2)) >> 21;
}
if ( fi & FI_RTR ){
printk("remote frame |");
}else{
printk("data frame |");
}
printk(KERN_INFO "ID: %x |", id);
if (dlc){
cf->data[0] = gsc3280_read ( priv, GSC3280_RXB4);
cf->data[1] = gsc3280_read ( priv, GSC3280_RXB3);
printk(KERN_INFO "DATA: ");
printk("%x", gsc3280_read(priv, GSC3280_RXB4));
printk("%x", gsc3280_read(priv, GSC3280_RXB3));
}
netif_rx (skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
gsc3280_write(priv, GSC3280_CMR, CMD_RRB);
printk("ok!\n");
}
/*
* gsc3280_can_err - can controller errors handle funciton
* @dev: netdevice structure
* @isrc: error code
* @status: status info
*/
static int gsc3280_can_err ( struct net_device * dev, u16 isrc, u16 status )
{
struct gsc3280_priv *priv = netdev_priv (dev);
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
enum can_state state = priv->can.state;
printk("Enter gsc3280_can_err\n");
skb = alloc_can_err_skb ( dev, &cf );
if ( skb == NULL )
return -ENOMEM;
if ( isrc & IRQ_BEI ){ /* check bus error*/
dev_dbg(dev->dev.parent, "catched bus error\n" );
}
/* if ( isrc & ALI )
{
dev_dbg(dev->dev.parent, "lost arbiter, become receiver\n" );
}
*/ if ( isrc & IRQ_EPI )
{
dev_dbg(dev->dev.parent, "reached error passive state or changed to error activity state\n" );
state = CAN_STATE_ERROR_PASSIVE;
}
if ( isrc & IRQ_DOI )
{
dev_dbg(dev->dev.parent, "data overflow,\n" );
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
stats->rx_over_errors++;
stats->rx_errors++;
}
if ( (isrc & IRQ_TI) || (isrc & IRQ_RI) )
{
dev_dbg(dev->dev.parent, "Error Warning Transmit/Receive Interrupt\n" );
state = CAN_STATE_ERROR_WARNING;
}
if ( state != priv->can.state && ( state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE ))
{
cf->can_id |= CAN_ERR_CRTL;
if ( state == CAN_STATE_ERROR_WARNING ){
priv->can.can_stats.error_warning++;
/*inter error frame*/
}else{
priv->can.can_stats.error_passive++;
/* inter error frame*/
}
}
if ( status ){
priv->can.can_stats.bus_error++;
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
/*inter serveral states*/
}
priv->can.state = state;
netif_rx ( skb );
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
return 0;
}
/*
static int gsc3280_can_suspend (struct platform_device *pdev, pm_message_t mesg)
{
return 0;
}
static int gsc3280_can_resume ( struct platform_device *pdev )
{
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);
/* void __iomem *reg = priv->reg_base;*/
struct net_device_stats *stats = &dev->stats;
u16 status,status1, isrc;
/* unsigned char ff;
unsigned char fi;
unsigned char id;
unsigned char dlc;
printk("Enter gsc3280_can_interrupt\n");
*/
status = gsc3280_read( priv, GSC3280_IR);
status1 = gsc3280_read( priv, IRQ_ALL );
printk( "Enter interrupt status is 0x%x, status1 is 0x%x, irq is 0x%d\n", status,status1, irq);
/* gsc3280_can_rx ( dev ); */
if(status & 0x02 )
{ /*trammiter interrupt*/
stats->tx_packets++;
printk("Enter gsc3280_can_interrupt tx\n");
stats->tx_bytes += gsc3280_read (priv, GSC3280_TXB1)&0xf;
can_get_echo_skb ( dev, 0 );
netif_wake_queue ( dev );
/* gsc3280_can_start_xmit(skb, dev);*/
}else if(( status & 0x1 ))
{ /*receive interrupt*/
printk("Enter gsc3280_can_interrupt rx\n");
gsc3280_can_rx ( dev );
}else if(( status & ~0x3 ))
{
printk("Enter gsc3280_can_interrupt err\n");
gsc3280_print_regs();
gsc3280_can_err ( dev, isrc, status );
}else
{
return IRQ_NONE;
}
return IRQ_HANDLED;
}
extern void blx_timer_init( int mode, unsigned long count);
extern void gsc3280_request_timer( int mode, int count, void(*fn)(unsigned long));
extern void gsc3280_watchdog_init(char wdt_cr, char top);
/*
* 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;
int mode;
/* struct can_frame *cf;*/
printk(" gsc3280_can_open \n");
gsc3280_print_regs();
gsc3280_can_set_reset_mod(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_rx_irq;
mode = 0x8; /*set MOD register to normal mode*/
printk("before gsc3280_can_start\n");
/*this must set in reset mode*/
gsc3280_write(priv, GSC3280_ACR, 0x100);
gsc3280_write(priv, GSC3280_AMR, 0xffffffff);
gsc3280_can_start(dev, mode);
netif_start_queue (dev);
return 0;
exit_rx_irq:
free_irq(priv->irq, dev);
/*
exit_tx_irq:
free_irq(priv->irq,dev);
exit_err_irq:
close_candev(dev);
*/
exit_open:
return err;
}
/*
* gsc3280_can_close - gsc3280 can close routine
* @dev net device structure
*/
static int gsc3280_can_close ( struct net_device *dev )
{
struct gsc3280_priv *priv = netdev_priv(dev);
printk("Enter gsc3280_can_close\n");
netif_stop_queue (dev);
gsc3280_can_set_reset_mod (dev);
close_candev(dev);
free_irq(priv->irq,dev);
/* free_irq(priv->tx_irq,dev);
free_irq(priv->err_irq,dev);
*/
return 0;
}
#define TX_ECHO_SKB_MAX 1
struct net_device *alloc_gsc3280_candev(void)
{
struct net_device *dev;
struct gsc3280_priv *priv;
dev = alloc_candev ( sizeof(*priv), TX_ECHO_SKB_MAX);
/*printk("cc alloc_gsc3280_candev 1,dev is 0x%x, dev->dev is 0x%x\n", dev, dev->dev);*/
if ( !dev)
return NULL;
printk("cc alloc_gsc3280_candev 2\n");
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_reset_mod;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
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;
gsc3280_print_regs();
clk = clk_get ( &pdev->dev , "can" );
rate = clk_get_rate ( clk );
/*test for 55.6M/2*/
rate = 27777777;
clk_set_rate(clk, rate);
if ( IS_ERR(clk)){
dev_err(&pdev->dev, "no clock defined\n");
err = -ENODEV;
goto exit;
}
pdata = pdev->dev.platform_data;
printk("Enter can model 2\n");
if(!pdata){
dev_err (&pdev->dev, "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);
printk("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 = gsc3280_can_bittiming;
/* priv->can.do_get_berr_counter = gsc3280_get_berr_counter;*/
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
priv->dev = dev;
priv->reg_base = (void __iomem*) (res_mem->start);
/* printk("priv->reg_base is 0x%x\n", priv->reg_base);*/
priv->irq = irq->start;
priv->pin_list = pdata;
printk("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;
/*printk(KERN_INFO " 1before can_reset_mod, %x, %x\n", __raw_readl(0xbc04a008), __raw_readl(0xbc04a0b0));*/
__raw_writel(( __raw_readl(0xbc04a008)| 0x4) , 0xbc04a008);
/*printk(KERN_INFO " 2before can_reset_mod, %x, %x\n", __raw_readl(0xbc04a008), __raw_readl(0xbc04a0b0));*/
gsc3280_can_set_reset_mod (dev);
gsc3280_can_set_bittiming (dev);
printk(" after can_reset_mod\n");
err = register_candev(dev);
if(err){
dev_err(&pdev->dev, "registering netdev failed\n");
goto exit_free;
}
dev_info(&pdev->dev, "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_put:
clk_put(clk);*/
exit:
return err;
}
/*
* gsc3280_can_remove - gsc3280 can remove routine
* @pdev platform device structure
*/
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_mod(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));
/* peripheral_free_list(priv->pin_list);*/
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);