2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2008-11-12 13:27:14 -08:00
/*
* Silicon Labs C2 port Linux support for Eurotech Duramar 2150
*
* Copyright ( c ) 2008 Rodolfo Giometti < giometti @ linux . it >
* Copyright ( c ) 2008 Eurotech S . p . A . < info @ eurotech . it >
*/
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/io.h>
2012-01-22 23:24:15 -05:00
# include <linux/ioport.h>
2008-11-12 13:27:14 -08:00
# include <linux/c2port.h>
# define DATA_PORT 0x325
# define DIR_PORT 0x326
# define C2D (1 << 0)
# define C2CK (1 << 1)
static DEFINE_MUTEX ( update_lock ) ;
/*
* C2 port operations
*/
static void duramar2150_c2port_access ( struct c2port_device * dev , int status )
{
u8 v ;
mutex_lock ( & update_lock ) ;
v = inb ( DIR_PORT ) ;
/* 0 = input, 1 = output */
if ( status )
outb ( v | ( C2D | C2CK ) , DIR_PORT ) ;
else
/* When access is "off" is important that both lines are set
2011-03-30 22:57:33 -03:00
* as inputs or hi - impedance */
2008-11-12 13:27:14 -08:00
outb ( v & ~ ( C2D | C2CK ) , DIR_PORT ) ;
mutex_unlock ( & update_lock ) ;
}
static void duramar2150_c2port_c2d_dir ( struct c2port_device * dev , int dir )
{
u8 v ;
mutex_lock ( & update_lock ) ;
v = inb ( DIR_PORT ) ;
if ( dir )
outb ( v & ~ C2D , DIR_PORT ) ;
else
outb ( v | C2D , DIR_PORT ) ;
mutex_unlock ( & update_lock ) ;
}
static int duramar2150_c2port_c2d_get ( struct c2port_device * dev )
{
return inb ( DATA_PORT ) & C2D ;
}
static void duramar2150_c2port_c2d_set ( struct c2port_device * dev , int status )
{
u8 v ;
mutex_lock ( & update_lock ) ;
v = inb ( DATA_PORT ) ;
if ( status )
outb ( v | C2D , DATA_PORT ) ;
else
outb ( v & ~ C2D , DATA_PORT ) ;
mutex_unlock ( & update_lock ) ;
}
static void duramar2150_c2port_c2ck_set ( struct c2port_device * dev , int status )
{
u8 v ;
mutex_lock ( & update_lock ) ;
v = inb ( DATA_PORT ) ;
if ( status )
outb ( v | C2CK , DATA_PORT ) ;
else
outb ( v & ~ C2CK , DATA_PORT ) ;
mutex_unlock ( & update_lock ) ;
}
static struct c2port_ops duramar2150_c2port_ops = {
. block_size = 512 , /* bytes */
. blocks_num = 30 , /* total flash size: 15360 bytes */
. access = duramar2150_c2port_access ,
. c2d_dir = duramar2150_c2port_c2d_dir ,
. c2d_get = duramar2150_c2port_c2d_get ,
. c2d_set = duramar2150_c2port_c2d_set ,
. c2ck_set = duramar2150_c2port_c2ck_set ,
} ;
static struct c2port_device * duramar2150_c2port_dev ;
/*
* Module stuff
*/
static int __init duramar2150_c2port_init ( void )
{
struct resource * res ;
int ret = 0 ;
res = request_region ( 0x325 , 2 , " c2port " ) ;
if ( ! res )
return - EBUSY ;
duramar2150_c2port_dev = c2port_device_register ( " uc " ,
& duramar2150_c2port_ops , NULL ) ;
2017-05-08 15:55:17 -07:00
if ( IS_ERR ( duramar2150_c2port_dev ) ) {
ret = PTR_ERR ( duramar2150_c2port_dev ) ;
2008-11-12 13:27:14 -08:00
goto free_region ;
}
return 0 ;
free_region :
release_region ( 0x325 , 2 ) ;
return ret ;
}
static void __exit duramar2150_c2port_exit ( void )
{
/* Setup the GPIOs as input by default (access = 0) */
duramar2150_c2port_access ( duramar2150_c2port_dev , 0 ) ;
c2port_device_unregister ( duramar2150_c2port_dev ) ;
release_region ( 0x325 , 2 ) ;
}
module_init ( duramar2150_c2port_init ) ;
module_exit ( duramar2150_c2port_exit ) ;
MODULE_AUTHOR ( " Rodolfo Giometti <giometti@linux.it> " ) ;
MODULE_DESCRIPTION ( " Silicon Labs C2 port Linux support for Duramar 2150 " ) ;
MODULE_LICENSE ( " GPL " ) ;