2007-01-30 16:10:24 +01:00
/*
* Cyclades PC300 synchronous serial card driver for Linux
*
2008-07-09 23:13:49 +02:00
* Copyright ( C ) 2000 - 2008 Krzysztof Halasa < khc @ pm . waw . pl >
2007-01-30 16:10:24 +01:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation .
*
* For information see < http : //www.kernel.org/pub/linux/utils/net/hdlc/>.
*
* Sources of information :
* Hitachi HD64572 SCA - II User ' s Manual
2008-07-09 23:13:49 +02:00
* Original Cyclades PC300 Linux driver
2007-01-30 16:10:24 +01:00
*
* This driver currently supports only PC300 / RSV ( V .24 / V .35 ) and
* PC300 / X21 cards .
*/
2011-06-26 19:01:28 +00:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2007-01-30 16:10:24 +01:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/sched.h>
# include <linux/types.h>
# include <linux/fcntl.h>
# include <linux/in.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/ioport.h>
# include <linux/moduleparam.h>
# include <linux/netdevice.h>
# include <linux/hdlc.h>
# include <linux/pci.h>
# include <linux/delay.h>
# include <asm/io.h>
# include "hd64572.h"
# undef DEBUG_PKT
# define DEBUG_RINGS
# define PC300_PLX_SIZE 0x80 /* PLX control window size (128 B) */
# define PC300_SCA_SIZE 0x400 /* SCA window size (1 KB) */
# define MAX_TX_BUFFERS 10
static int pci_clock_freq = 33000000 ;
static int use_crystal_clock = 0 ;
static unsigned int CLOCK_BASE ;
/* Masks to access the init_ctrl PLX register */
# define PC300_CLKSEL_MASK (0x00000004UL)
# define PC300_CHMEDIA_MASK(port) (0x00000020UL << ((port) * 3))
# define PC300_CTYPE_MASK (0x00000800UL)
enum { PC300_RSV = 1 , PC300_X21 , PC300_TE } ; /* card types */
/*
* PLX PCI9050 - 1 local configuration and shared runtime registers .
* This structure can be used to access 9050 registers ( memory mapped ) .
*/
typedef struct {
u32 loc_addr_range [ 4 ] ; /* 00-0Ch : Local Address Ranges */
u32 loc_rom_range ; /* 10h : Local ROM Range */
u32 loc_addr_base [ 4 ] ; /* 14-20h : Local Address Base Addrs */
u32 loc_rom_base ; /* 24h : Local ROM Base */
u32 loc_bus_descr [ 4 ] ; /* 28-34h : Local Bus Descriptors */
u32 rom_bus_descr ; /* 38h : ROM Bus Descriptor */
u32 cs_base [ 4 ] ; /* 3C-48h : Chip Select Base Addrs */
u32 intr_ctrl_stat ; /* 4Ch : Interrupt Control/Status */
u32 init_ctrl ; /* 50h : EEPROM ctrl, Init Ctrl, etc */
} plx9050 ;
typedef struct port_s {
2008-07-09 16:49:37 +02:00
struct napi_struct napi ;
2008-07-09 23:13:49 +02:00
struct net_device * netdev ;
2007-01-30 16:10:24 +01:00
struct card_s * card ;
spinlock_t lock ; /* TX lock */
sync_serial_settings settings ;
int rxpart ; /* partial frame received, next frame invalid*/
unsigned short encoding ;
unsigned short parity ;
unsigned int iface ;
u16 rxin ; /* rx ring buffer 'in' pointer */
u16 txin ; /* tx ring buffer 'in' and 'last' pointers */
u16 txlast ;
u8 rxs , txs , tmc ; /* SCA registers */
2008-07-09 23:13:49 +02:00
u8 chan ; /* physical port # - 0 or 1 */
2007-01-30 16:10:24 +01:00
} port_t ;
typedef struct card_s {
int type ; /* RSV, X21, etc. */
int n_ports ; /* 1 or 2 ports */
2007-02-09 16:40:05 +00:00
u8 __iomem * rambase ; /* buffer memory base (virtual) */
u8 __iomem * scabase ; /* SCA memory base (virtual) */
2007-01-30 16:10:24 +01:00
plx9050 __iomem * plxbase ; /* PLX registers memory base (virtual) */
u32 init_ctrl_value ; /* Saved value - 9050 bug workaround */
u16 rx_ring_buffers ; /* number of buffers in a ring */
u16 tx_ring_buffers ;
u16 buff_offset ; /* offset of first buffer of first channel */
u8 irq ; /* interrupt request level */
port_t ports [ 2 ] ;
} card_t ;
# define get_port(card, port) ((port) < (card)->n_ports ? \
( & ( card ) - > ports [ port ] ) : ( NULL ) )
2008-03-24 16:39:02 +01:00
# include "hd64572.c"
2007-01-30 16:10:24 +01:00
static void pc300_set_iface ( port_t * port )
{
card_t * card = port - > card ;
2007-02-09 16:40:05 +00:00
u32 __iomem * init_ctrl = & card - > plxbase - > init_ctrl ;
2007-01-30 16:10:24 +01:00
u16 msci = get_msci ( port ) ;
u8 rxs = port - > rxs & CLK_BRG_MASK ;
u8 txs = port - > txs & CLK_BRG_MASK ;
2008-07-09 23:13:49 +02:00
sca_out ( EXS_TES1 , ( port - > chan ? MSCI1_OFFSET : MSCI0_OFFSET ) + EXS ,
port - > card ) ;
2007-01-30 16:10:24 +01:00
switch ( port - > settings . clock_type ) {
case CLOCK_INT :
rxs | = CLK_BRG ; /* BRG output */
txs | = CLK_PIN_OUT | CLK_TX_RXCLK ; /* RX clock */
break ;
case CLOCK_TXINT :
rxs | = CLK_LINE ; /* RXC input */
txs | = CLK_PIN_OUT | CLK_BRG ; /* BRG output */
break ;
case CLOCK_TXFROMRX :
rxs | = CLK_LINE ; /* RXC input */
txs | = CLK_PIN_OUT | CLK_TX_RXCLK ; /* RX clock */
break ;
default : /* EXTernal clock */
rxs | = CLK_LINE ; /* RXC input */
txs | = CLK_PIN_OUT | CLK_LINE ; /* TXC input */
break ;
}
port - > rxs = rxs ;
port - > txs = txs ;
sca_out ( rxs , msci + RXS , card ) ;
sca_out ( txs , msci + TXS , card ) ;
sca_set_port ( port ) ;
if ( port - > card - > type = = PC300_RSV ) {
if ( port - > iface = = IF_IFACE_V35 )
writel ( card - > init_ctrl_value |
2008-07-09 23:13:49 +02:00
PC300_CHMEDIA_MASK ( port - > chan ) , init_ctrl ) ;
2007-01-30 16:10:24 +01:00
else
writel ( card - > init_ctrl_value &
2008-07-09 23:13:49 +02:00
~ PC300_CHMEDIA_MASK ( port - > chan ) , init_ctrl ) ;
2007-01-30 16:10:24 +01:00
}
}
static int pc300_open ( struct net_device * dev )
{
port_t * port = dev_to_port ( dev ) ;
int result = hdlc_open ( dev ) ;
if ( result )
return result ;
sca_open ( dev ) ;
pc300_set_iface ( port ) ;
return 0 ;
}
static int pc300_close ( struct net_device * dev )
{
sca_close ( dev ) ;
hdlc_close ( dev ) ;
return 0 ;
}
static int pc300_ioctl ( struct net_device * dev , struct ifreq * ifr , int cmd )
{
const size_t size = sizeof ( sync_serial_settings ) ;
sync_serial_settings new_line ;
sync_serial_settings __user * line = ifr - > ifr_settings . ifs_ifsu . sync ;
int new_type ;
port_t * port = dev_to_port ( dev ) ;
# ifdef DEBUG_RINGS
if ( cmd = = SIOCDEVPRIVATE ) {
sca_dump_rings ( dev ) ;
return 0 ;
}
# endif
if ( cmd ! = SIOCWANDEV )
return hdlc_ioctl ( dev , ifr , cmd ) ;
if ( ifr - > ifr_settings . type = = IF_GET_IFACE ) {
ifr - > ifr_settings . type = port - > iface ;
if ( ifr - > ifr_settings . size < size ) {
ifr - > ifr_settings . size = size ; /* data size wanted */
return - ENOBUFS ;
}
if ( copy_to_user ( line , & port - > settings , size ) )
return - EFAULT ;
return 0 ;
}
if ( port - > card - > type = = PC300_X21 & &
( ifr - > ifr_settings . type = = IF_IFACE_SYNC_SERIAL | |
ifr - > ifr_settings . type = = IF_IFACE_X21 ) )
new_type = IF_IFACE_X21 ;
else if ( port - > card - > type = = PC300_RSV & &
( ifr - > ifr_settings . type = = IF_IFACE_SYNC_SERIAL | |
ifr - > ifr_settings . type = = IF_IFACE_V35 ) )
new_type = IF_IFACE_V35 ;
else if ( port - > card - > type = = PC300_RSV & &
ifr - > ifr_settings . type = = IF_IFACE_V24 )
new_type = IF_IFACE_V24 ;
else
return hdlc_ioctl ( dev , ifr , cmd ) ;
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
if ( copy_from_user ( & new_line , line , size ) )
return - EFAULT ;
if ( new_line . clock_type ! = CLOCK_EXT & &
new_line . clock_type ! = CLOCK_TXFROMRX & &
new_line . clock_type ! = CLOCK_INT & &
new_line . clock_type ! = CLOCK_TXINT )
return - EINVAL ; /* No such clock setting */
if ( new_line . loopback ! = 0 & & new_line . loopback ! = 1 )
return - EINVAL ;
memcpy ( & port - > settings , & new_line , size ) ; /* Update settings */
port - > iface = new_type ;
pc300_set_iface ( port ) ;
return 0 ;
}
static void pc300_pci_remove_one ( struct pci_dev * pdev )
{
int i ;
card_t * card = pci_get_drvdata ( pdev ) ;
for ( i = 0 ; i < 2 ; i + + )
2008-07-09 23:13:49 +02:00
if ( card - > ports [ i ] . card )
unregister_hdlc_device ( card - > ports [ i ] . netdev ) ;
2007-01-30 16:10:24 +01:00
if ( card - > irq )
free_irq ( card - > irq , card ) ;
if ( card - > rambase )
iounmap ( card - > rambase ) ;
if ( card - > scabase )
iounmap ( card - > scabase ) ;
if ( card - > plxbase )
iounmap ( card - > plxbase ) ;
pci_release_regions ( pdev ) ;
pci_disable_device ( pdev ) ;
2008-07-09 23:13:49 +02:00
if ( card - > ports [ 0 ] . netdev )
free_netdev ( card - > ports [ 0 ] . netdev ) ;
if ( card - > ports [ 1 ] . netdev )
free_netdev ( card - > ports [ 1 ] . netdev ) ;
2007-01-30 16:10:24 +01:00
kfree ( card ) ;
}
2009-01-08 22:52:11 +01:00
static const struct net_device_ops pc300_ops = {
. ndo_open = pc300_open ,
. ndo_stop = pc300_close ,
. ndo_start_xmit = hdlc_start_xmit ,
. ndo_do_ioctl = pc300_ioctl ,
} ;
2007-01-30 16:10:24 +01:00
2012-12-03 09:24:19 -05:00
static int pc300_pci_init_one ( struct pci_dev * pdev ,
2012-12-06 14:30:56 +00:00
const struct pci_device_id * ent )
2007-01-30 16:10:24 +01:00
{
card_t * card ;
u32 __iomem * p ;
int i ;
u32 ramsize ;
u32 ramphys ; /* buffer memory base */
u32 scaphys ; /* SCA memory base */
u32 plxphys ; /* PLX registers memory base */
i = pci_enable_device ( pdev ) ;
if ( i )
return i ;
i = pci_request_regions ( pdev , " PC300 " ) ;
if ( i ) {
pci_disable_device ( pdev ) ;
return i ;
}
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 01:49:03 -07:00
card = kzalloc ( sizeof ( card_t ) , GFP_KERNEL ) ;
2007-01-30 16:10:24 +01:00
if ( card = = NULL ) {
pci_release_regions ( pdev ) ;
pci_disable_device ( pdev ) ;
return - ENOBUFS ;
}
pci_set_drvdata ( pdev , card ) ;
if ( pci_resource_len ( pdev , 0 ) ! = PC300_PLX_SIZE | |
pci_resource_len ( pdev , 2 ) ! = PC300_SCA_SIZE | |
pci_resource_len ( pdev , 3 ) < 16384 ) {
2011-06-26 19:01:28 +00:00
pr_err ( " invalid card EEPROM parameters \n " ) ;
2007-01-30 16:10:24 +01:00
pc300_pci_remove_one ( pdev ) ;
return - EFAULT ;
}
2008-11-20 15:51:05 +01:00
plxphys = pci_resource_start ( pdev , 0 ) & PCI_BASE_ADDRESS_MEM_MASK ;
2007-01-30 16:10:24 +01:00
card - > plxbase = ioremap ( plxphys , PC300_PLX_SIZE ) ;
2008-11-20 15:51:05 +01:00
scaphys = pci_resource_start ( pdev , 2 ) & PCI_BASE_ADDRESS_MEM_MASK ;
2007-01-30 16:10:24 +01:00
card - > scabase = ioremap ( scaphys , PC300_SCA_SIZE ) ;
2008-11-20 15:51:05 +01:00
ramphys = pci_resource_start ( pdev , 3 ) & PCI_BASE_ADDRESS_MEM_MASK ;
2008-10-20 21:42:39 -07:00
card - > rambase = pci_ioremap_bar ( pdev , 3 ) ;
2007-01-30 16:10:24 +01:00
if ( card - > plxbase = = NULL | |
card - > scabase = = NULL | |
card - > rambase = = NULL ) {
2011-06-26 19:01:28 +00:00
pr_err ( " ioremap() failed \n " ) ;
2007-01-30 16:10:24 +01:00
pc300_pci_remove_one ( pdev ) ;
2017-04-23 17:38:35 +08:00
return - ENOMEM ;
2007-01-30 16:10:24 +01:00
}
/* PLX PCI 9050 workaround for local configuration register read bug */
pci_write_config_dword ( pdev , PCI_BASE_ADDRESS_0 , scaphys ) ;
2007-02-09 16:40:05 +00:00
card - > init_ctrl_value = readl ( & ( ( plx9050 __iomem * ) card - > scabase ) - > init_ctrl ) ;
2007-01-30 16:10:24 +01:00
pci_write_config_dword ( pdev , PCI_BASE_ADDRESS_0 , plxphys ) ;
2008-11-20 15:51:05 +01:00
if ( pdev - > device = = PCI_DEVICE_ID_PC300_TE_1 | |
pdev - > device = = PCI_DEVICE_ID_PC300_TE_2 )
card - > type = PC300_TE ; /* not fully supported */
else if ( card - > init_ctrl_value & PC300_CTYPE_MASK )
card - > type = PC300_X21 ;
else
card - > type = PC300_RSV ;
if ( pdev - > device = = PCI_DEVICE_ID_PC300_RX_1 | |
pdev - > device = = PCI_DEVICE_ID_PC300_TE_1 )
card - > n_ports = 1 ;
else
card - > n_ports = 2 ;
for ( i = 0 ; i < card - > n_ports ; i + + )
if ( ! ( card - > ports [ i ] . netdev = alloc_hdlcdev ( & card - > ports [ i ] ) ) ) {
2011-06-26 19:01:28 +00:00
pr_err ( " unable to allocate memory \n " ) ;
2008-11-20 15:51:05 +01:00
pc300_pci_remove_one ( pdev ) ;
return - ENOMEM ;
}
2007-01-30 16:10:24 +01:00
/* Reset PLX */
p = & card - > plxbase - > init_ctrl ;
writel ( card - > init_ctrl_value | 0x40000000 , p ) ;
readl ( p ) ; /* Flush the write - do not use sca_flush */
udelay ( 1 ) ;
writel ( card - > init_ctrl_value , p ) ;
readl ( p ) ; /* Flush the write - do not use sca_flush */
udelay ( 1 ) ;
/* Reload Config. Registers from EEPROM */
writel ( card - > init_ctrl_value | 0x20000000 , p ) ;
readl ( p ) ; /* Flush the write - do not use sca_flush */
udelay ( 1 ) ;
writel ( card - > init_ctrl_value , p ) ;
readl ( p ) ; /* Flush the write - do not use sca_flush */
udelay ( 1 ) ;
ramsize = sca_detect_ram ( card , card - > rambase ,
pci_resource_len ( pdev , 3 ) ) ;
if ( use_crystal_clock )
card - > init_ctrl_value & = ~ PC300_CLKSEL_MASK ;
else
card - > init_ctrl_value | = PC300_CLKSEL_MASK ;
writel ( card - > init_ctrl_value , & card - > plxbase - > init_ctrl ) ;
/* number of TX + RX buffers for one port */
i = ramsize / ( card - > n_ports * ( sizeof ( pkt_desc ) + HDLC_MAX_MRU ) ) ;
card - > tx_ring_buffers = min ( i / 2 , MAX_TX_BUFFERS ) ;
card - > rx_ring_buffers = i - card - > tx_ring_buffers ;
card - > buff_offset = card - > n_ports * sizeof ( pkt_desc ) *
( card - > tx_ring_buffers + card - > rx_ring_buffers ) ;
2011-06-26 19:01:28 +00:00
pr_info ( " PC300/%s, %u KB RAM at 0x%x, IRQ%u, using %u TX + %u RX packets rings \n " ,
card - > type = = PC300_X21 ? " X21 " :
card - > type = = PC300_TE ? " TE " : " RSV " ,
ramsize / 1024 , ramphys , pdev - > irq ,
card - > tx_ring_buffers , card - > rx_ring_buffers ) ;
2007-01-30 16:10:24 +01:00
if ( card - > tx_ring_buffers < 1 ) {
2011-06-26 19:01:28 +00:00
pr_err ( " RAM test failed \n " ) ;
2007-01-30 16:10:24 +01:00
pc300_pci_remove_one ( pdev ) ;
return - EFAULT ;
}
/* Enable interrupts on the PCI bridge, LINTi1 active low */
writew ( 0x0041 , & card - > plxbase - > intr_ctrl_stat ) ;
/* Allocate IRQ */
2008-07-09 21:30:17 +02:00
if ( request_irq ( pdev - > irq , sca_intr , IRQF_SHARED , " pc300 " , card ) ) {
2011-06-26 19:01:28 +00:00
pr_warn ( " could not allocate IRQ%d \n " , pdev - > irq ) ;
2007-01-30 16:10:24 +01:00
pc300_pci_remove_one ( pdev ) ;
return - EBUSY ;
}
card - > irq = pdev - > irq ;
sca_init ( card , 0 ) ;
// COTE not set - allows better TX DMA settings
// sca_out(sca_in(PCR, card) | PCR_COTE, PCR, card);
sca_out ( 0x10 , BTCR , card ) ;
for ( i = 0 ; i < card - > n_ports ; i + + ) {
port_t * port = & card - > ports [ i ] ;
2008-07-09 23:13:49 +02:00
struct net_device * dev = port - > netdev ;
2007-01-30 16:10:24 +01:00
hdlc_device * hdlc = dev_to_hdlc ( dev ) ;
2008-07-09 23:13:49 +02:00
port - > chan = i ;
2007-01-30 16:10:24 +01:00
spin_lock_init ( & port - > lock ) ;
dev - > irq = card - > irq ;
dev - > mem_start = ramphys ;
dev - > mem_end = ramphys + ramsize - 1 ;
dev - > tx_queue_len = 50 ;
2009-01-08 22:52:11 +01:00
dev - > netdev_ops = & pc300_ops ;
2007-01-30 16:10:24 +01:00
hdlc - > attach = sca_attach ;
hdlc - > xmit = sca_xmit ;
port - > settings . clock_type = CLOCK_EXT ;
port - > card = card ;
if ( card - > type = = PC300_X21 )
port - > iface = IF_IFACE_X21 ;
else
port - > iface = IF_IFACE_V35 ;
2008-07-09 16:49:37 +02:00
sca_init_port ( port ) ;
2007-01-30 16:10:24 +01:00
if ( register_hdlc_device ( dev ) ) {
2011-06-26 19:01:28 +00:00
pr_err ( " unable to register hdlc device \n " ) ;
2007-01-30 16:10:24 +01:00
port - > card = NULL ;
pc300_pci_remove_one ( pdev ) ;
return - ENOBUFS ;
}
2011-06-26 19:01:28 +00:00
netdev_info ( dev , " PC300 channel %d \n " , port - > chan ) ;
2007-01-30 16:10:24 +01:00
}
return 0 ;
}
2014-08-08 15:56:03 +02:00
static const struct pci_device_id pc300_pci_tbl [ ] = {
2007-01-30 16:10:24 +01:00
{ PCI_VENDOR_ID_CYCLADES , PCI_DEVICE_ID_PC300_RX_1 , PCI_ANY_ID ,
PCI_ANY_ID , 0 , 0 , 0 } ,
{ PCI_VENDOR_ID_CYCLADES , PCI_DEVICE_ID_PC300_RX_2 , PCI_ANY_ID ,
PCI_ANY_ID , 0 , 0 , 0 } ,
{ PCI_VENDOR_ID_CYCLADES , PCI_DEVICE_ID_PC300_TE_1 , PCI_ANY_ID ,
PCI_ANY_ID , 0 , 0 , 0 } ,
{ PCI_VENDOR_ID_CYCLADES , PCI_DEVICE_ID_PC300_TE_2 , PCI_ANY_ID ,
PCI_ANY_ID , 0 , 0 , 0 } ,
{ 0 , }
} ;
static struct pci_driver pc300_pci_driver = {
2007-02-09 16:40:05 +00:00
. name = " PC300 " ,
. id_table = pc300_pci_tbl ,
. probe = pc300_pci_init_one ,
. remove = pc300_pci_remove_one ,
2007-01-30 16:10:24 +01:00
} ;
static int __init pc300_init_module ( void )
{
if ( pci_clock_freq < 1000000 | | pci_clock_freq > 80000000 ) {
2011-06-26 19:01:28 +00:00
pr_err ( " Invalid PCI clock frequency \n " ) ;
2007-01-30 16:10:24 +01:00
return - EINVAL ;
}
if ( use_crystal_clock ! = 0 & & use_crystal_clock ! = 1 ) {
2011-06-26 19:01:28 +00:00
pr_err ( " Invalid 'use_crystal_clock' value \n " ) ;
2007-01-30 16:10:24 +01:00
return - EINVAL ;
}
CLOCK_BASE = use_crystal_clock ? 24576000 : pci_clock_freq ;
2007-02-14 01:40:21 +01:00
return pci_register_driver ( & pc300_pci_driver ) ;
2007-01-30 16:10:24 +01:00
}
static void __exit pc300_cleanup_module ( void )
{
pci_unregister_driver ( & pc300_pci_driver ) ;
}
MODULE_AUTHOR ( " Krzysztof Halasa <khc@pm.waw.pl> " ) ;
MODULE_DESCRIPTION ( " Cyclades PC300 serial port driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DEVICE_TABLE ( pci , pc300_pci_tbl ) ;
module_param ( pci_clock_freq , int , 0444 ) ;
MODULE_PARM_DESC ( pci_clock_freq , " System PCI clock frequency in Hz " ) ;
module_param ( use_crystal_clock , int , 0444 ) ;
MODULE_PARM_DESC ( use_crystal_clock ,
" Use 24.576 MHz clock instead of PCI clock " ) ;
module_init ( pc300_init_module ) ;
module_exit ( pc300_cleanup_module ) ;