drivers/net/irda: remove unused drivers

Change-Id: Ide8b500d07779a7f78df6cd37626b951390594f8
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang
2018-11-05 10:45:05 +08:00
parent 2c4455eecc
commit 6d7597abea
6 changed files with 0 additions and 2711 deletions

View File

@@ -1,762 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/***************************************************************************
*
* File: bu92725guw.c
*
* Description: functions of operating with bu92725guw board.
*
* Created: 2007/9
*
* Rev 1.1
*
*
* Confidential ROHM CO.,LTD.
*
****************************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/random.h>
#include <linux/version.h>
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/highmem.h>
#include <linux/freezer.h>
#include "rk29_ir.h"
#if 0
#define RK29IR_DBG(x...) printk(x)
#else
#define RK29IR_DBG(x...)
#endif
/*---------------------------------------------------------------------------
Data
----------------------------------------------------------------------------*/
/* record current setting
*/
static u32 curTrans_mode; /* SIR, MIR, FIR */
static u32 curTrans_speed; /* 2.4kbps, 9.6kbps,..., 4Mbps */
static u32 curTrans_way; /* idle, send, receive, mir-receive, mir-send, fir-receive, fir-send, auto-multi-receive, multi-receive, multi-send */
static u16 curFIT; /* FIT2,1,0 in PWR/FIT register */
/*---------------------------------------------------------------------------
Function Proto
----------------------------------------------------------------------------*/
static void internal_set(u8 modeChg);
/*---------------------------------------------------------------------------
global Function Implement
----------------------------------------------------------------------------*/
/*
* Synopsis: board initialize
*
* Paras: none
*
* Return: none
*/
void irda_hw_init(struct rk29_irda *si)
{
//smc0_init(&si->irda_base_addr);
//printk("%s [%d]\n",__FUNCTION__,__LINE__);
}
void irda_hw_deinit(struct rk29_irda *si)
{
// smc0_init(&si->irda_base_addr);
}
int irda_hw_startup(void)
{
volatile u16 val;
//int i=0;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
//IER (disable all)
BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);
//MCR (use IrDA Controller func, 9.6kbps, SIR)
BU92725GUW_WRITE_REG(REG_MCR_ADDR, REG_MCR_9600 | REG_MCR_SIR);
//PWR/FIT (default)
BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, REG_PWR_FIT_MPW_3 | REG_PWR_FIT_FPW_2 | REG_PWR_FIT_FIT_0);
//TRCR (idle, clr fifo, IrDA power on, mode select enable)
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_FCLR | REG_TRCR_MS_EN);
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
while (val & REG_TRCR_MS_EN) {
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
}
//FTLV
BU92725GUW_WRITE_REG(REG_FTLV_ADDR, 0x0000);
// for(i=0; i<REG_WREC_ADDR;i=(i+2))//%REG_WREC_ADDR) //
// printk("reg %d = 0x%x\n",i,BU92725GUW_READ_REG(i));
curTrans_mode = BU92725GUW_SIR;
curTrans_speed = 9600;
curTrans_way = BU92725GUW_IDLE;
curFIT = REG_PWR_FIT_FIT_0;
return 0;
}
int irda_hw_shutdown(void)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
//IER (diable all)
BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);
//MCR (use IrDA Controller func, 9.6kbps, SIR)
BU92725GUW_WRITE_REG(REG_MCR_ADDR, REG_MCR_9600 | REG_MCR_SIR);
//PWR/FIT (default)
BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, REG_PWR_FIT_MPW_3 | REG_PWR_FIT_FPW_2 | REG_PWR_FIT_FIT_0);
//TRCR (idle, clr fifo, IrDA , rx, tx power down)
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_FCLR | REG_TRCR_IRPD |REG_TRCR_TXPWD | REG_TRCR_RXPWD);
//FTLV
BU92725GUW_WRITE_REG(REG_FTLV_ADDR, 0x0000);
curTrans_mode = BU92725GUW_SIR;
curTrans_speed = 9600;
curTrans_way = BU92725GUW_IDLE;
curFIT = REG_PWR_FIT_FIT_0;
return 0;
}
/*
* Synopsis: set data transfer speed
*
* Paras: speed - speed value will be set; value is from enum eTrans_Speed
*
* Return: none
*/
int irda_hw_set_speed(u32 speed)
{
u32 mode;
u8 modeChg = 0;
/* do nothing if speed is same as current */
RK29IR_DBG("line %d: enter %s, speed=%d\n", __LINE__, __FUNCTION__, speed);
if (speed == curTrans_speed)
return 0;
/* mode */
switch (speed) {
case 2400:
case 9600:
case 19200:
case 38400:
case 57600:
case 115200:
mode = BU92725GUW_SIR;
break;
case 576000:
case 1152000:
mode = BU92725GUW_MIR;
break;
case 4000000:
mode = BU92725GUW_FIR;
break;
default:
return -1; //invalid
}
/* speed */
curTrans_speed = speed;
/* change trans way if needed */
switch (curTrans_way) {
case BU92725GUW_IDLE:
break;
case BU92725GUW_REV:
if (mode == BU92725GUW_MIR)
curTrans_way = BU92725GUW_MIR_REV;
else if (mode == BU92725GUW_FIR)
curTrans_way = BU92725GUW_AUTO_MULTI_REV;
//curTrans_way = BU92725GUW_MULTI_REV;
//curTrans_way = BU92725GUW_FIR_REV;
break;
case BU92725GUW_SEND:
if (mode == BU92725GUW_MIR)
curTrans_way = BU92725GUW_MIR_SEND;
else if (mode == BU92725GUW_FIR)
curTrans_way = BU92725GUW_MULTI_SEND;
//curTrans_way = BU92725GUW_FIR_SEND;
break;
case BU92725GUW_MIR_REV:
if (mode == BU92725GUW_SIR)
curTrans_way = BU92725GUW_REV;
else if (mode == BU92725GUW_FIR)
curTrans_way = BU92725GUW_AUTO_MULTI_REV;
//curTrans_way = BU92725GUW_MULTI_REV;
//curTrans_way = BU92725GUW_FIR_REV;
break;
case BU92725GUW_MIR_SEND:
if (mode == BU92725GUW_SIR)
curTrans_way = BU92725GUW_SEND;
else if (mode == BU92725GUW_FIR)
curTrans_way = BU92725GUW_MULTI_SEND;
//curTrans_way = BU92725GUW_FIR_SEND;
break;
case BU92725GUW_FIR_REV:
case BU92725GUW_AUTO_MULTI_REV:
case BU92725GUW_MULTI_REV:
if (mode == BU92725GUW_SIR)
curTrans_way = BU92725GUW_REV;
else if (mode == BU92725GUW_MIR)
curTrans_way = BU92725GUW_MIR_REV;
break;
case BU92725GUW_FIR_SEND:
case BU92725GUW_MULTI_SEND:
if (mode == BU92725GUW_SIR)
curTrans_way = BU92725GUW_SEND;
else if (mode == BU92725GUW_MIR)
curTrans_way = BU92725GUW_MIR_SEND;
break;
}
if (mode != curTrans_mode) {
if ((mode == BU92725GUW_FIR) || (curTrans_mode == BU92725GUW_FIR))
modeChg = 1; /* need set TRCR5:MS_EN */
}
curTrans_mode = mode;
/* set bu92725guw registers */
//internal_set(modeChg);
internal_set(1);
return 0;
}
int irda_hw_tx_enable_irq(enum eTrans_Mode mode)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* hardware-specific code
*/
if (mode == BU92725GUW_SIR)
BU92725GUW_set_trans_way(BU92725GUW_SEND);
else if (mode == BU92725GUW_MIR)
BU92725GUW_set_trans_way(BU92725GUW_MIR_SEND);
else
BU92725GUW_set_trans_way(BU92725GUW_MULTI_SEND);
//BU92725GUW_set_trans_way(BU92725GUW_FIR_SEND);
//BU92725GUW_clr_fifo();
return 0;
}
int irda_hw_tx_enable(int len)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
BU92725GUW_WRITE_REG(REG_FTLV_ADDR, len);
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_TX_EN);
return 0;
}
int irda_hw_get_irqsrc(void)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
return BU92725GUW_READ_REG(REG_EIR_ADDR);
}
int irda_hw_get_data16(char* data8)
{
u16 data16 = 0;
int len = 0;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
len = BU92725GUW_READ_REG(REG_FLV_ADDR);
if(len > 0)
{
/* read data from RXD */
data16 = BU92725GUW_READ_REG(REG_RXD_ADDR);
data8[0] = (u8)data16;
data8[1] = (u8)(data16 >> 8);
return 2;
} else {
return 0;
}
}
void irda_hw_set_moderx(void)
{
// frData.ucFlags &= ~(FRMF_TX_ACTIVE);
// frData.ucFlags |= FRMF_RX_ACTIVE;
//int i=0;
/* hardware-specific code
*/
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
//BU92725GUW_clr_fifo();
if (curTrans_mode == BU92725GUW_SIR)
BU92725GUW_set_trans_way(BU92725GUW_REV);
else if (curTrans_mode == BU92725GUW_MIR)
BU92725GUW_set_trans_way(BU92725GUW_MIR_REV);
else
BU92725GUW_set_trans_way(BU92725GUW_AUTO_MULTI_REV);
//BU92725GUW_set_trans_way(BU92725GUW_MULTI_REV);
//BU92725GUW_set_trans_way(BU92725GUW_FIR_REV);
}
int irda_hw_get_mode(void)
{
return curTrans_way;
#if 0
u16 val = 0;
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
RK29IR_DBG("line %d: enter %s, REG_TRCR_ADDR = 0x%x\n", __LINE__, __FUNCTION__, val);
return (val& (REG_TRCR_TX_EN | REG_TRCR_RX_EN));
#endif
}
/*
* Synopsis: set data transfer way
*
* Paras: way - transfer way will be set; value is from enum eThrans_Way
*
* Return: none
*/
void BU92725GUW_set_trans_way(u32 way)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
if (way == curTrans_way)
return;
curTrans_way = way;
/* set bu92725guw registers */
/* [Modify] AIC 2011/09/27
*
* internal_set(1);
*/
internal_set(0);
/* [Modify] AIC 2011/09/27 */
}
/*
* Synopsis: clear fifo
*
* Paras: none
*
* Return: none
*/
void BU92725GUW_clr_fifo(void)
{
volatile u16 val;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* set TRCR4:FCLR */
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
val &= 0xff8f;
val |= REG_TRCR_FCLR;
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, val);
/* wait op complete */
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
while (val & REG_TRCR_FCLR)
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
}
/*
* Synopsis: read frame data from fifo
*
* Paras: buf - point to buffer for storing frame data
*
* Return: number of data got from fifo (in byte)
*/
u16 BU92725GUW_get_data(u8 *buf)
{
volatile u16 data;
u16 len, count, i;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
if (curTrans_way == BU92725GUW_MULTI_REV) {
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_FLV_CP|REG_TRCR_RX_CON|REG_TRCR_RX_EN);
}
/* get data count from FLV or FLVII */
if ((curTrans_way == BU92725GUW_REV) || (curTrans_way == BU92725GUW_MIR_REV)
|| (curTrans_way == BU92725GUW_FIR_REV))
len = BU92725GUW_READ_REG(REG_FLV_ADDR);
else
len = BU92725GUW_READ_REG(REG_FLVII_ADDR);
count = (len % 2)? (len / 2 + 1) : (len / 2);
/* read data from RXD */
for (i=0; i<count; i++) {
data = BU92725GUW_READ_REG(REG_RXD_ADDR);
buf[i * 2] = (u8)data;
buf[i * 2 + 1] = (u8)(data >> 8);
}
/* restart receive mode under SIR */
if ((curTrans_way == BU92725GUW_REV) || (curTrans_way == BU92725GUW_MIR_REV)
|| (curTrans_way == BU92725GUW_FIR_REV)){
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, 0x0000);
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_RX_EN);
}
return len;
}
/*
* Synopsis: write data from buffer1 and buffer2 into fifo
*
* Paras: buf1 - point to buffer 1
* len1 - length of data to write into fifo from buffer 1
* buf2 - point to buffer 2
* len2 - length of data to write into fifo from buffer 2
*
* Return: none
*/
void BU92725GUW_send_data(u8 *buf1, u16 len1, u8 *buf2, u16 len2)
{/* buf2,len2 will be used by framer under MIR/FIR mode */
u16 data, len, pos;
u8 *ptr;
len = len1 + len2;
pos = 0;
ptr = (u8 *)(&data);
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
if (len == 0)
return;
/* set FTLV */
BU92725GUW_WRITE_REG(REG_FTLV_ADDR, len);
/* set TRCR:TX_EN under normal send mode */
if ((curTrans_way == BU92725GUW_SEND) || (curTrans_way == BU92725GUW_MIR_SEND)
|| (curTrans_way == BU92725GUW_FIR_SEND)) {
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_TX_EN);
}
/* set TXD */
while (pos < len) {
*ptr++ = (pos < len1)? buf1[pos] : buf2[pos-len1];
pos++;
if (pos < len) {
*ptr-- = (pos < len1)? buf1[pos] : buf2[pos-len1];
} else
*ptr-- = 0x00;
pos++;
BU92725GUW_WRITE_REG(REG_TXD_ADDR, data);
}
}
/*
* Synopsis: set frame sending interval under multi-window send mode
*
* Paras: us - interval time value to set
*
* Return: none
*/
void BU92725GUW_set_frame_interval(u32 us)
{
volatile u16 val;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* set PWR/FIT */
val = BU92725GUW_READ_REG(REG_PWR_FIT_ADDR);
//val &= 0xf8ff;
val &= 0xf0ff;
if (us <= 100)
val |= REG_PWR_FIT_FIT_0;
else if (us <= 200)
val |= REG_PWR_FIT_FIT_1;
else if (us <= 300)
val |= REG_PWR_FIT_FIT_2;
else if (us <= 400)
val |= REG_PWR_FIT_FIT_3;
else if (us <= 500)
val |= REG_PWR_FIT_FIT_4;
else if (us <= 600)
val |= REG_PWR_FIT_FIT_5;
else if (us <= 800)
val |= REG_PWR_FIT_FIT_6;
else if (us <= 1000)
val |= REG_PWR_FIT_FIT_7;
else if (us <= 1200)
val |= REG_PWR_FIT_FIT_8;
else if (us <= 1400)
val |= REG_PWR_FIT_FIT_9;
else if (us <= 1600)
val |= REG_PWR_FIT_FIT_A;
else if (us <= 1800)
val |= REG_PWR_FIT_FIT_B;
else if (us <= 2000)
val |= REG_PWR_FIT_FIT_C;
else if (us <= 2200)
val |= REG_PWR_FIT_FIT_D;
else if (us <= 2400)
val |= REG_PWR_FIT_FIT_E;
else
val |= REG_PWR_FIT_FIT_F;
BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, val);
//curFIT = val & 0x0700;
curFIT = val & 0x0F00;
}
/*
* Synopsis: return current transfer mode (SIR/MIR/FIR)
*
* Paras: none
*
* Return: current transfer mode
*/
u32 BU92725GUW_get_trans_mode(void)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
return curTrans_mode;
}
/*
* Synopsis: add a IrDA pulse following frame
*
* Paras: none
*
* Return: none
*/
void BU92725GUW_add_pulse(void)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* valid only under M/FIR send mode */
if (curTrans_way != BU92725GUW_MULTI_SEND)
return;
/* set TRCR3:IR_PLS */
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_IR_PLS | REG_TRCR_TX_CON);
}
/*
* Synopsis: soft reset bu92725guw board; will be called after some error happened
*
* Paras: none
*
* Return: none
*/
void BU92725GUW_reset(void)
{
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* set bu925725guw registers */
internal_set(1);
}
/*---------------------------------------------------------------------------
local Function Implement
----------------------------------------------------------------------------*/
/*
* Synopsis: set bu92725guw internal registers
*
* Paras: modeChg - need set TRCR5:MS_EN or not
*
* Return: none
*/
static void internal_set(u8 modeChg)
{
volatile u16 val;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/* disable INT */
BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);
val = BU92725GUW_READ_REG(REG_EIR_ADDR);
/* MCR */
val = 0;
switch (curTrans_mode) {
case BU92725GUW_SIR: //00
val |= REG_MCR_SIR;
break;
case BU92725GUW_MIR: //01
val |= REG_MCR_MIR;
break;
case BU92725GUW_FIR: //10
val |= REG_MCR_FIR;
break;
}
switch (curTrans_speed) {
case 2400: //000
val |= REG_MCR_2400;
break;
case 9600: //010
val |= REG_MCR_9600;
break;
case 19200: //011
val |= REG_MCR_19200;
break;
case 38400: //100
val |= REG_MCR_38400;
break;
case 57600: //101
val |= REG_MCR_57600;
break;
case 115200: //110
val |= REG_MCR_115200;
break;
case 576000: //001
val |= REG_MCR_576K;
break;
case 1152000: //010
val |= REG_MCR_1152K;
break;
case 4000000: //010
val |= REG_MCR_4M;
break;
}
BU92725GUW_WRITE_REG(REG_MCR_ADDR, val);
RK29IR_DBG("REG_MCR_ADDR: 0x%x\n", val);
/* PWR / FIT */
switch (curTrans_mode) {
case BU92725GUW_SIR:
val = 0x0000;
break;
case BU92725GUW_MIR:
val = REG_PWR_FIT_MPW_3 | curFIT;
break;
case BU92725GUW_FIR:
val = REG_PWR_FIT_FPW_2 | curFIT;
break;
}
BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, val);
RK29IR_DBG("REG_PWR_FIT_ADDR: 0x%x\n", val);
/* TRCR:MS_EN */
if (modeChg) {
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_MS_EN);
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
while (val & REG_TRCR_MS_EN) {
val = BU92725GUW_READ_REG(REG_TRCR_ADDR);
}
}
/* TRCR */
switch (curTrans_way) {
case BU92725GUW_IDLE:
val = 0x0000;
break;
case BU92725GUW_REV:
case BU92725GUW_MIR_REV:
case BU92725GUW_FIR_REV:
val = REG_TRCR_RX_EN;
break;
case BU92725GUW_AUTO_MULTI_REV:
val = REG_TRCR_RX_EN | REG_TRCR_AUTO_FLV_CP;
break;
case BU92725GUW_MULTI_REV:
val = REG_TRCR_RX_EN | REG_TRCR_RX_CON;//FIR
break;
case BU92725GUW_SEND:
case BU92725GUW_MIR_SEND:
case BU92725GUW_FIR_SEND:
val = 0x0000;
break;
case BU92725GUW_MULTI_SEND:
val = REG_TRCR_TX_CON;
break;
}
BU92725GUW_WRITE_REG(REG_TRCR_ADDR, val);
RK29IR_DBG("REG_TRCR_ADDR: 0x%x\n", val);
/* IER */
switch (curTrans_way) {
case BU92725GUW_IDLE:
val = 0x0000;
break;
case BU92725GUW_REV: /* SIR use */
val = REG_INT_EOFRX | REG_INT_TO | REG_INT_OE | REG_INT_FE; //IER1, 2, 5, 7
break;
case BU92725GUW_MIR_REV: /* MIR use */
val = REG_INT_STFRX | REG_INT_TO | REG_INT_OE | REG_INT_EOF
| REG_INT_AC | REG_INT_DECE; //IER1,2, 5, 6, 7
break;
case BU92725GUW_FIR_REV: /* FIR use */
val = REG_INT_STFRX | REG_INT_TO | REG_INT_CRC | REG_INT_OE | REG_INT_EOF \
| REG_INT_AC | REG_INT_DECE; //IER1,2, 4, 5, 6, 7
break;
case BU92725GUW_MULTI_REV: /* not used */
val = REG_INT_STFRX | REG_INT_TO | REG_INT_CRC | REG_INT_OE | REG_INT_EOF | REG_INT_AC | REG_INT_DECE \
| REG_INT_RDOE | REG_INT_DEX | REG_INT_RDUE; //IER1,2, 4, 5, 6, 7, 8, 9, 10
break;
case BU92725GUW_AUTO_MULTI_REV: /* M/FIR use */
val = REG_INT_TO | REG_INT_CRC | REG_INT_OE | REG_INT_EOF | REG_INT_AC | REG_INT_DECE\
| REG_INT_RDOE | REG_INT_DEX | REG_INT_RDE; //IER2, 4, 5, 6, 7, 8, 9, 12
break;
case BU92725GUW_SEND: /* SIR use */
val = REG_INT_TXE; //IER3
break;
case BU92725GUW_MIR_SEND:
case BU92725GUW_FIR_SEND:
val = REG_INT_TXE | REG_INT_TO; //IER2, 3
break;
case BU92725GUW_MULTI_SEND: /* M/FIR use */
val = REG_INT_TO | REG_INT_TXE | REG_INT_WRE; //IER2, 3, 11
break;
}
BU92725GUW_WRITE_REG(REG_IER_ADDR, val);
RK29IR_DBG("REG_IER_ADDR: 0x%x\n", val);
}
void BU92725GUW_dump_register(void)
{
printk("bu92725 register value:\n");
printk("MCR: 0x%x\n", BU92725GUW_READ_REG(REG_MCR_ADDR));
printk("FIT: 0x%x\n", BU92725GUW_READ_REG(REG_PWR_FIT_ADDR));
printk("TRCR: 0x%x\n", BU92725GUW_READ_REG(REG_TRCR_ADDR));
printk("IER: 0x%x\n", BU92725GUW_READ_REG(REG_IER_ADDR));
}
/* [Add] AIC 2011/09/29 */
int BU92725GUW_get_length_in_fifo_buffer(void)
{
return( (int)BU92725GUW_READ_REG(REG_FLV_ADDR) );
}
/* [Add-end] AIC 2011/09/29 */

View File

@@ -1,235 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/***************************************************************************
*
* File: bu92725guw.h
*
* Description: This file contains configuration constants for the
* bu92725guw board.
*
* Created: 2007/9
*
* Rev 1.1
*
*
* Confidential ROHM CO.,LTD.
*
****************************************************************************/
#ifndef __BU92725GUW_H
#define __BU92725GUW_H
#include "mach/rk29_smc.h"
/* irda registers addr must be 2*ori_register when use smc control*/
#define REG_TXD_ADDR 0
#define REG_RXD_ADDR 0
#define REG_IER_ADDR 2
#define REG_EIR_ADDR 4
#define REG_MCR_ADDR 6
#define REG_PWR_FIT_ADDR 8
#define REG_TRCR_ADDR 10
#define REG_FTLV_ADDR 12
#define REG_FLV_ADDR 14
#define REG_FLVII_ADDR 16
#define REG_FLVIII_ADDR 18
#define REG_FLVIV_ADDR 20
#define REG_TRCRII_ADDR 22
#define REG_TXEC_ADDR 24
#define REG_WREC_ADDR 26
/*
*register bits definition (registers are all 16 bits)
*/
//interrupt reg (IER and EIR)
#define REG_INT_DRX (0x0001 << 0)
#define REG_INT_EOFRX (0x0001 << 1)
#define REG_INT_STFRX (0x0001 << 1)
#define REG_INT_TO (0x0001 << 2)
#define REG_INT_TXE (0x0001 << 3)
#define REG_INT_CRC (0x0001 << 4)
#define REG_INT_OE (0x0001 << 5)
#define REG_INT_EOF (0x0001 << 6)
#define REG_INT_FE (0x0001 << 7)
#define REG_INT_AC (0x0001 << 7)
#define REG_INT_DECE (0x0001 << 7)
#define REG_INT_RDOE (0x0001 << 8)
#define REG_INT_DEX (0x0001 << 9)
#define REG_INT_RDUE (0x0001 << 10)
#define REG_INT_WRE (0x0001 << 11)
#define REG_INT_RDE (0x0001 << 12)
//MCR
#define REG_MCR_CTLA 0x1000
#define REG_MCR_RC_MODE 0x0800
#define REG_MCR_RC_EN 0x0400
#define REG_MCR_2400 (0x0000 << 5)
#define REG_MCR_9600 (0x0002 << 5) //default
#define REG_MCR_19200 (0x0003 << 5)
#define REG_MCR_38400 (0x0004 << 5)
#define REG_MCR_57600 (0x0005 << 5)
#define REG_MCR_115200 (0x0006 << 5)
#define REG_MCR_576K (0x0001 << 5)
#define REG_MCR_1152K (0x0002 << 5)
#define REG_MCR_4M (0x0002 << 5)
#define REG_MCR_SIR 0x0000 //default
#define REG_MCR_MIR 0x0001
#define REG_MCR_FIR 0x0002
/* flag event bit
*/
#define FRM_EVT_RX_EOFRX REG_INT_EOFRX //IER1
#define FRM_EVT_RX_RDE REG_INT_RDE //IER12
#define FRM_EVT_TX_TXE REG_INT_TXE //IER3
#define FRM_EVT_TX_WRE REG_INT_WRE //IER11
#define FRM_EVT_EXIT_NOW 0x00010000
enum eTrans_Mode {
BU92725GUW_SIR = 0,
BU92725GUW_MIR,
BU92725GUW_FIR,
};
enum eTrans_Speed {
BU92725GUW_2400 = 0,
BU92725GUW_9600,
BU92725GUW_19200,
BU92725GUW_38400,
BU92725GUW_57600,
BU92725GUW_115200,
BU92725GUW_576K,
BU92725GUW_1152K,
BU92725GUW_4M,
};
//PWR/FIT
#define REG_PWR_FIT_SPW 0x0001
#define REG_PWR_FIT_MPW_0 (0x0000 << 1)
#define REG_PWR_FIT_MPW_1 (0x0001 << 1)
#define REG_PWR_FIT_MPW_2 (0x0002 << 1)
#define REG_PWR_FIT_MPW_3 (0x0003 << 1) //default
#define REG_PWR_FIT_MPW_4 (0x0004 << 1)
#define REG_PWR_FIT_MPW_5 (0x0005 << 1)
#define REG_PWR_FIT_MPW_6 (0x0006 << 1)
#define REG_PWR_FIT_MPW_7 (0x0007 << 1)
#define REG_PWR_FIT_MPW_8 (0x0008 << 1)
#define REG_PWR_FIT_MPW_9 (0x0009 << 1)
#define REG_PWR_FIT_MPW_10 (0x000A << 1)
#define REG_PWR_FIT_MPW_11 (0x000B << 1)
#define REG_PWR_FIT_MPW_12 (0x000C << 1)
#define REG_PWR_FIT_MPW_13 (0x000D << 1)
#define REG_PWR_FIT_MPW_14 (0x000E << 1)
#define REG_PWR_FIT_MPW_15 (0x000F << 1)
#define REG_PWR_FIT_FPW_0 (0x0000 << 5)
#define REG_PWR_FIT_FPW_1 (0x0001 << 5)
#define REG_PWR_FIT_FPW_2 (0x0002 << 5) //default
#define REG_PWR_FIT_FPW_3 (0x0003 << 5)
#define REG_PWR_FIT_FIT_0 (0x0000 << 8) //default
#define REG_PWR_FIT_FIT_1 (0x0001 << 8)
#define REG_PWR_FIT_FIT_2 (0x0002 << 8)
#define REG_PWR_FIT_FIT_3 (0x0003 << 8)
#define REG_PWR_FIT_FIT_4 (0x0004 << 8)
#define REG_PWR_FIT_FIT_5 (0x0005 << 8)
#define REG_PWR_FIT_FIT_6 (0x0006 << 8)
#define REG_PWR_FIT_FIT_7 (0x0007 << 8)
#define REG_PWR_FIT_FIT_8 (0x0008 << 8) //default
#define REG_PWR_FIT_FIT_9 (0x0009 << 8)
#define REG_PWR_FIT_FIT_A (0x000A << 8)
#define REG_PWR_FIT_FIT_B (0x000B << 8)
#define REG_PWR_FIT_FIT_C (0x000C << 8)
#define REG_PWR_FIT_FIT_D (0x000D << 8)
#define REG_PWR_FIT_FIT_E (0x000E << 8)
#define REG_PWR_FIT_FIT_F (0x000F << 8)
//TRCR
#define REG_TRCR_TX_EN 0x0001
#define REG_TRCR_RX_EN (0x0001 << 1)
#define REG_TRCR_S_EOT (0x0001 << 2)
#define REG_TRCR_IR_PLS (0x0001 << 3)
#define REG_TRCR_FCLR (0x0001 << 4)
#define REG_TRCR_MS_EN (0x0001 << 5)
#define REG_TRCR_IRPD (0x0001 << 6)
#define REG_TRCR_M_STA (0x0001 << 7)
#define REG_TRCR_RXPWD (0x0001 << 8)
#define REG_TRCR_TXPWD (0x0001 << 9)
#define REG_TRCR_ONE_BIT_R (0x0001 << 10)
#define REG_TRCR_AUTO_FLV_CP (0x0001 << 11)
#define REG_TRCR_RX_CON (0x0001 << 12)
#define REG_TRCR_FLV_CP (0x0001 << 13)
#define REG_TRCR_TX_CON (0x0001 << 14)
#define REG_TRCR_TX_NUM (0x0001 << 15)
enum eThrans_Way {
BU92725GUW_IDLE = 0,
BU92725GUW_REV, /* SIR use */
BU92725GUW_SEND, /* SIR use */
BU92725GUW_MIR_REV, /* MIR use */
BU92725GUW_MIR_SEND, /* MIR use */
BU92725GUW_FIR_REV, /* FIR use */
BU92725GUW_FIR_SEND, /* FIR use */
BU92725GUW_AUTO_MULTI_REV, /* M/FIR use */
BU92725GUW_MULTI_REV, /* not used */
BU92725GUW_MULTI_SEND, /* M/FIR use */
};
#define BU92725GUW_FIFO_SIZE (2560 * 2)
#define BU92725GUW_MAX_FRM_INTERVAL 1000 /* 1000us */
/*---------------------------------------------------------------------------
Functions used by framer
----------------------------------------------------------------------------*/
#define BU92725GUW_READ_REG(regAddr) smc0_read(regAddr)
#define BU92725GUW_WRITE_REG(regAddr, data) smc0_write(regAddr, data)
/* board initialize */
extern void BU92725GUW_init(void);
/* board deinit */
extern void BU92725GUW_deinit(void);
/* set data transfer speed */
extern void BU92725GUW_set_trans_speed(u32 speed);
/* set frame transfer way */
extern void BU92725GUW_set_trans_way(u32 way);
/* flush fifo */
extern void BU92725GUW_clr_fifo(void);
/* set frame sending interval */
extern void BU92725GUW_set_frame_interval(u32 us);
/* insert IrDA pulse follow frame sending */
extern void BU92725GUW_add_pulse(void);
/* soft reset when some error happened */
extern void BU92725GUW_reset(void);
/* return transfer mode */
extern u32 BU92725GUW_get_trans_mode(void);
/* get frame data from fifo */
extern u16 BU92725GUW_get_data(u8 *buf);
/* send frame data into fifo */
extern void BU92725GUW_send_data(u8 *buf1, u16 len1, u8 *buf2, u16 len2);
/*dump register*/
extern void BU92725GUW_dump_register(void);
int irda_hw_tx_enable_irq(enum eTrans_Mode mode);
int irda_hw_get_mode(void);
void irda_hw_set_moderx(void);
int irda_hw_get_irqsrc(void);
int irda_hw_shutdown(void);
int irda_hw_startup(void);
int irda_hw_set_speed(u32 speed);
/* [Add] AIC 2011/09/29 */
int BU92725GUW_get_length_in_fifo_buffer(void);
/* [Add-end] AIC 2011/09/29 */
#endif /*__BU92725GUW_H*/

View File

@@ -1,866 +0,0 @@
/*
*
* Copyright (C) 2011 liuyixing <lyx@rock-chips.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.
*
*
*note: serial driver for IrDA(SIR and FIR) device
*
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/freezer.h>
#include <mach/board.h>
#include <linux/irq.h>
#include <mach/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include "bu92725guw.h"
#include "ir_serial.h"
#define MAX_FRAME_NUM 20
struct rev_frame_length {
unsigned long frame_length[MAX_FRAME_NUM];
int iRead;
int iWrite;
int iCount;
};
#define frame_read_empty(f) ((f)->iCount == 0)
#define frame_write_full(f) ((f)->iCount == MAX_FRAME_NUM)
#define frame_length_buf_clear(f) ((f)->iCount = (f)->iWrite = (f)->iRead = 0)
struct bu92747_port {
struct device *dev;
struct irda_info *pdata;
struct uart_port port;
/*for FIR fream read*/
struct rev_frame_length rev_frames;
//unsigned long last_frame_length;
unsigned long cur_frame_length;
//wait_queue_head_t data_ready_wq;
//atomic_t data_ready;
spinlock_t data_lock;
int tx_empty; /* last TX empty bit */
spinlock_t conf_lock; /* shared data */
int baud; /* current baud rate */
int rx_enabled; /* if we should rx chars */
int irq_pin;
int irq; /* irq assigned to the bu92747 */
int minor; /* minor number */
struct workqueue_struct *workqueue;
struct work_struct work;
/* set to 1 to make the workhandler exit as soon as possible */
int force_end_work;
int open_flag;
/* need to know we are suspending to avoid deadlock on workqueue */
int suspending;
};
#define MAX_BU92747 1
#define BU92747_MAJOR 204
#define BU92747_MINOR 209
static struct bu92747_port *bu92747s[MAX_BU92747]; /* the chips */
static DEFINE_MUTEX(bu92747s_lock); /* race on probe */
#define IS_FIR(s) ((s)->baud >= 4000000)
static int max_rate = 4000000;
static u8 g_receive_buf[BU92725GUW_FIFO_SIZE];
#if 0
#define IRDA_DBG_FUNC(x...) printk(x)
#else
#define IRDA_DBG_FUNC(x...)
#endif
#if 0
#define IRDA_DBG_RECV(x...) printk(x)
#else
#define IRDA_DBG_RECV(x...)
#endif
#if 0
#define IRDA_DBG_SENT(x...) printk(x)
#else
#define IRDA_DBG_SENT(x...)
#endif
/* race on startup&shutdown, mutex lock with CIR driver */
static DEFINE_MUTEX(irda_cir_lock);
int bu92747_try_lock(void)
{
if (mutex_trylock(&irda_cir_lock))
return 1; //ready
else
return 0; //busy
}
void bu92747_unlock(void)
{
return mutex_unlock(&irda_cir_lock);
}
static int add_frame_length(struct rev_frame_length *f, unsigned long length)
{
if (frame_write_full(f))
return -1;
f->frame_length[f->iWrite] = length;
f->iCount++;
f->iWrite = (f->iWrite+1) % MAX_FRAME_NUM;
return 0;
}
static int get_frame_length(struct rev_frame_length *f, unsigned long *length)
{
if (frame_read_empty(f))
return -1;
*length = f->frame_length[f->iRead];
f->iCount--;
f->iRead = (f->iRead+1) % MAX_FRAME_NUM;
return 0;
}
static int bu92747_irda_do_rx(struct bu92747_port *s)
{
//int i;
//unsigned int ch, flag;
int len;
struct tty_struct *tty = s->port.state->port.tty;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (s->rx_enabled == 0) {
BU92725GUW_clr_fifo();
BU92725GUW_reset();
return 0;
}
len = BU92725GUW_get_data(g_receive_buf);
#if 0
flag = TTY_NORMAL;
//printk("receive data:\n");
for (i=0;i<len;i++) {
ch = g_receive_buf[i];
uart_insert_char(&s->port, 0, 0, ch, flag);
s->port.icount.rx++;
//printk("%d ", ch);
}
//printk("\n");
#else
if (len > 0) {
IRDA_DBG_RECV("line %d, enter %s, receive %d data........\n", __LINE__, __func__, len);
tty_insert_flip_string(tty, g_receive_buf, len);
s->port.icount.rx += len;
}
#endif
return len;
}
static int bu92747_irda_do_tx(struct bu92747_port *s)
{
//int i;
struct circ_buf *xmit = &s->port.state->xmit;
int len = uart_circ_chars_pending(xmit);
int len1, len2;
IRDA_DBG_SENT("line %d, enter %s, sending %d data\n", __LINE__, __FUNCTION__, len);
if (IS_FIR(s)) {
irda_hw_tx_enable_irq(BU92725GUW_FIR);
}
else {
irda_hw_tx_enable_irq(BU92725GUW_SIR);
}
if (len>0) {
s->tx_empty = 0;
}
/* [Modify] AIC 2011/09/27
* BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);
*/
if ( (xmit->tail + len) > UART_XMIT_SIZE ) {
len1 = UART_XMIT_SIZE - xmit->tail;
len2 = len - len1;
BU92725GUW_send_data(xmit->buf+xmit->tail, len1, xmit->buf, len2);
} else {
BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);
}
/* [Modify-end] AIC 2011/09/27 */
s->port.icount.tx += len;
xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&s->port);
return len;
}
static void bu92747_irda_dowork(struct bu92747_port *s)
{
if (!s->force_end_work && !work_pending(&s->work) &&
!freezing(current) && !s->suspending)
queue_work(s->workqueue, &s->work);
}
static void bu92747_irda_work(struct work_struct *w)
{
struct bu92747_port *s = container_of(w, struct bu92747_port, work);
struct circ_buf *xmit = &s->port.state->xmit;
IRDA_DBG_SENT("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (!s->force_end_work && !freezing(current)) {
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
if (s->tx_empty)
bu92747_irda_do_tx(s);
else
bu92747_irda_dowork(s);
}
}
}
static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)
{
struct bu92747_port *s = dev_id;
u32 irq_src = 0;
unsigned long len;
struct rev_frame_length *f = &(s->rev_frames);
irq_src = irda_hw_get_irqsrc();
IRDA_DBG_RECV("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);
/* error */
if (irq_src & (REG_INT_CRC | REG_INT_OE | REG_INT_FE
| REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {
printk("[%s][%d]: do err, REG_EIR = 0x%x\n", __FUNCTION__, __LINE__, irq_src);
BU92725GUW_clr_fifo();
BU92725GUW_reset();
if ((BU92725GUW_SEND==irda_hw_get_mode())
|| (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {
s->tx_empty = 1;
}
}
if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {
//fixing CA001 (IrSimple mode sending) failing issue
/* modified to process a frame ending processing first, when RDE_EI and EOF_EI are happen at the same time.
* Before the modification, disconnect packet was processed as the previous packet,
* not as a disconnect packet. The packets were combined.
*/
if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {
tty_flip_buffer_push(s->port.state->port.tty);
if (IS_FIR(s)) {
spin_lock(&s->data_lock);
if (add_frame_length(f, s->cur_frame_length) == 0) {
s->cur_frame_length = 0;
}
else {
printk("func %s,line %d: FIR frame length buf full......\n", __FUNCTION__, __LINE__);
}
spin_unlock(&s->data_lock);
}
}
//~
len = bu92747_irda_do_rx(s);
if (!IS_FIR(s))
tty_flip_buffer_push(s->port.state->port.tty);
else {
spin_lock(&s->data_lock);
s->cur_frame_length += len;
spin_unlock(&s->data_lock);
}
}
if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {
spin_lock(&s->data_lock); // [Modify] AIC 2011/09/30
tty_flip_buffer_push(s->port.state->port.tty);
if (IS_FIR(s)) {
/* [Modify] AIC 2011/09/30
* spin_lock(&s->data_lock);
*/
if (add_frame_length(f, s->cur_frame_length) == 0) {
s->cur_frame_length = 0;
}
else {
printk("func %s,line %d: FIR frame length buf full......\n", __FUNCTION__, __LINE__);
}
/* [Modify] AIC 2011/09/30
* spin_unlock(&s->data_lock);
*/
}
spin_unlock(&s->data_lock); // [Modify] AIC 2011/09/30
}
/* [Modify] AIC 2011/09/27
*
* if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {
* s->tx_empty = 1;
* irda_hw_set_moderx();
* }
*/
/* [Modify] AIC 2011/09/29
*
* if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {
* s->tx_empty = 1;
* if ( irq_src & FRM_EVT_TX_TXE ) {
* irda_hw_set_moderx();
* }
*/
if ( (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) &&
(BU92725GUW_get_length_in_fifo_buffer() == 0) ) {
s->tx_empty = 1;
if ( irq_src & FRM_EVT_TX_TXE ) {
irda_hw_set_moderx();
}
}
/* [Modify-end] AIC 2011/09/29 */
#if 0
/* error */
if (irq_src & REG_INT_TO) {
printk("[%s][%d]: do timeout err\n", __FUNCTION__, __LINE__);
BU92725GUW_clr_fifo();
BU92725GUW_reset();
if ((BU92725GUW_SEND==irda_hw_get_mode())
|| (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {
s->tx_empty = 1;
}
}
#endif
return IRQ_HANDLED;
}
static void bu92747_irda_stop_tx(struct uart_port *port)
{
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
}
static void bu92747_irda_start_tx(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
//wait for start cmd
if (IS_FIR(s))
return ;
bu92747_irda_dowork(s);
}
static void bu92747_irda_stop_rx(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
s->rx_enabled = 0;
}
static unsigned int bu92747_irda_tx_empty(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
/* may not be truly up-to-date */
return s->tx_empty;
}
static const char *bu92747_irda_type(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
return s->port.type == PORT_IRDA ? "BU92747" : NULL;
}
static void bu92747_irda_release_port(struct uart_port *port)
{
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
}
static void bu92747_irda_config_port(struct uart_port *port, int flags)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (flags & UART_CONFIG_TYPE)
s->port.type = PORT_IRDA;
}
static int bu92747_irda_verify_port(struct uart_port *port,
struct serial_struct *ser)
{
int ret = -EINVAL;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (ser->type == PORT_UNKNOWN || ser->type == PORT_IRDA)
ret = 0;
return ret;
}
static void bu92747_irda_shutdown(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
struct rev_frame_length *f = &(s->rev_frames);
printk("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (s->suspending)
return;
s->open_flag = 0;
s->force_end_work = 1;
if (s->workqueue) {
flush_workqueue(s->workqueue);
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
}
spin_lock(&s->data_lock);
frame_length_buf_clear(f);
s->cur_frame_length = 0;
spin_unlock(&s->data_lock);
if (s->irq)
free_irq(s->irq, s);
irda_hw_shutdown();
if (s->pdata->irda_pwr_ctl)
s->pdata->irda_pwr_ctl(0);
bu92747_unlock();
}
static int bu92747_irda_startup(struct uart_port *port)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
char b[32];
struct rev_frame_length *f = &(s->rev_frames);
printk("line %d, enter %s \n", __LINE__, __FUNCTION__);
s->rx_enabled = 1;
if (s->suspending)
return 0;
if (!bu92747_try_lock()) {
printk("func %s, cannot get bu92747 lock, bu92747 in using\n", __func__);
return -EBUSY;
}
s->baud = 9600;
spin_lock(&s->data_lock);
frame_length_buf_clear(f);
s->cur_frame_length = 0;
spin_unlock(&s->data_lock);
s->tx_empty = 1;
s->force_end_work = 0;
sprintf(b, "bu92747_irda-%d", s->minor);
s->workqueue = create_rt_workqueue(b);
if (!s->workqueue) {
dev_warn(s->dev, "cannot create workqueue\n");
bu92747_unlock();
return -EBUSY;
}
INIT_WORK(&s->work, bu92747_irda_work);
if (request_irq(s->irq, bu92747_irda_irq,
IRQF_TRIGGER_LOW, "bu92747_irda", s) < 0) {
dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);
s->irq = 0;
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
bu92747_unlock();
return -EBUSY;
}
disable_irq(s->irq);
if (s->pdata->irda_pwr_ctl)
s->pdata->irda_pwr_ctl(1);
irda_hw_startup();
irda_hw_set_moderx();
enable_irq(s->irq);
s->open_flag = 1;
return 0;
}
static int bu92747_irda_request_port(struct uart_port *port)
{
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
return 0;
}
static void bu92747_irda_break_ctl(struct uart_port *port, int break_state)
{
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
}
static unsigned int bu92747_irda_get_mctrl(struct uart_port *port)
{
return TIOCM_DSR | TIOCM_CAR;
}
static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
}
static void
bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
int baud = 0;
unsigned cflag;
struct tty_struct *tty = s->port.state->port.tty;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (!tty)
return;
cflag = termios->c_cflag;
baud = uart_get_baud_rate(port, termios, old, 0, max_rate);
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 115200:
case 4000000:
if (s->baud!=baud) {
IRDA_DBG_RECV("func %s:irda set baudrate %d........\n", __FUNCTION__, baud);
irda_hw_set_speed(baud);
s->baud = baud;
s->tx_empty = 1;
}
break;
default:
break;
}
uart_update_timeout(port, termios->c_cflag, baud);
}
static int bu92747_get_frame_length(struct bu92747_port *s)
{
struct rev_frame_length *f = &(s->rev_frames);
unsigned long len = 0;
spin_lock(&s->data_lock);
if (get_frame_length(f, &len) != 0) {
IRDA_DBG_RECV("func %s, line %d: FIR data not ready......\n", __FUNCTION__, __LINE__);
len = 0;
}
spin_unlock(&s->data_lock);
return len;
}
static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
{
struct bu92747_port *s = container_of(port,
struct bu92747_port,
port);
void __user *argp = (void __user *)arg;
unsigned long len = 0;
int ret = 0;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
switch (cmd) {
case TTYIR_GETLENGTH:
len = bu92747_get_frame_length(s);
if (len >= 0) {
if (copy_to_user(argp, &len, sizeof(len)))
ret = -EFAULT;
}
else
ret = -EFAULT;
break;
case TTYIR_STARTSEND:
bu92747_irda_dowork(s);
break;
default:
ret = -ENOIOCTLCMD;
break;
}
return ret;
}
static struct uart_ops bu92747_irda_ops = {
.tx_empty = bu92747_irda_tx_empty,
.set_mctrl = bu92747_irda_set_mctrl,
.get_mctrl = bu92747_irda_get_mctrl,
.stop_tx = bu92747_irda_stop_tx,
.start_tx = bu92747_irda_start_tx,
.stop_rx = bu92747_irda_stop_rx,
//.enable_ms = bu92747_irda_enable_ms,
.break_ctl = bu92747_irda_break_ctl,
.startup = bu92747_irda_startup,
.shutdown = bu92747_irda_shutdown,
.set_termios = bu92747_irda_set_termios,
.type = bu92747_irda_type,
.release_port = bu92747_irda_release_port,
.request_port = bu92747_irda_request_port,
.config_port = bu92747_irda_config_port,
.verify_port = bu92747_irda_verify_port,
.ioctl = bu92747_irda_ioctl,
};
static struct uart_driver bu92747_irda_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "ttyIr",
.dev_name = "ttyIr",
.major = BU92747_MAJOR,
.minor = BU92747_MINOR,
.nr = MAX_BU92747,
};
static int uart_driver_registered;
static int __devinit bu92747_irda_probe(struct platform_device *pdev)
{
int i, retval;
struct irda_info *platdata = pdev->dev.platform_data;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (!platdata) {
dev_warn(&pdev->dev, "no platform data info\n");
return -1;
}
mutex_lock(&bu92747s_lock);
if (!uart_driver_registered) {
uart_driver_registered = 1;
retval = uart_register_driver(&bu92747_irda_uart_driver);
if (retval) {
printk(KERN_ERR "Couldn't register bu92747 uart driver\n");
mutex_unlock(&bu92747s_lock);
return retval;
}
}
for (i = 0; i < MAX_BU92747; i++)
if (!bu92747s[i])
break;
if (i == MAX_BU92747) {
dev_warn(&pdev->dev, "too many bu92747 chips\n");
mutex_unlock(&bu92747s_lock);
return -ENOMEM;
}
bu92747s[i] = kzalloc(sizeof(struct bu92747_port), GFP_KERNEL);
if (!bu92747s[i]) {
dev_warn(&pdev->dev,
"kmalloc for bu92747 structure %d failed!\n", i);
mutex_unlock(&bu92747s_lock);
return -ENOMEM;
}
bu92747s[i]->dev = &pdev->dev;
bu92747s[i]->irq_pin = platdata->intr_pin;
bu92747s[i]->irq = gpio_to_irq(platdata->intr_pin);
if (platdata->iomux_init)
platdata->iomux_init();
bu92747s[i]->pdata = platdata;
spin_lock_init(&bu92747s[i]->conf_lock);
dev_set_drvdata(&pdev->dev, bu92747s[i]);
bu92747s[i]->minor = i;
dev_dbg(&pdev->dev, "%s: adding port %d\n", __func__, i);
bu92747s[i]->port.irq = bu92747s[i]->irq;
bu92747s[i]->port.fifosize = BU92725GUW_FIFO_SIZE;
bu92747s[i]->port.ops = &bu92747_irda_ops;
bu92747s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
bu92747s[i]->port.line = i;
bu92747s[i]->port.type = PORT_IRDA;
bu92747s[i]->port.dev = &pdev->dev;
retval = uart_add_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);
if (retval < 0)
dev_warn(&pdev->dev,
"uart_add_one_port failed for line %d with error %d\n",
i, retval);
bu92747s[i]->open_flag = 0;
bu92747s[i]->suspending = 0;
/* set shutdown mode to save power. Will be woken-up on open */
if (bu92747s[i]->pdata->irda_pwr_ctl)
bu92747s[i]->pdata->irda_pwr_ctl(0);
spin_lock_init(&(bu92747s[i]->data_lock));
mutex_unlock(&bu92747s_lock);
return 0;
}
static int __devexit bu92747_irda_remove(struct platform_device *pdev)
{
struct bu92747_port *s = dev_get_drvdata(&pdev->dev);
int i;
IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);
mutex_lock(&bu92747s_lock);
/* find out the index for the chip we are removing */
for (i = 0; i < MAX_BU92747; i++)
if (bu92747s[i] == s)
break;
dev_dbg(&pdev->dev, "%s: removing port %d\n", __func__, i);
uart_remove_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);
kfree(bu92747s[i]);
bu92747s[i] = NULL;
/* check if this is the last chip we have */
for (i = 0; i < MAX_BU92747; i++)
if (bu92747s[i]) {
mutex_unlock(&bu92747s_lock);
return 0;
}
pr_debug("removing bu92747 driver\n");
uart_unregister_driver(&bu92747_irda_uart_driver);
mutex_unlock(&bu92747s_lock);
return 0;
}
#ifdef CONFIG_PM
static int bu92747_irda_suspend(struct platform_device *pdev, pm_message_t state)
{
struct bu92747_port *s = dev_get_drvdata(&pdev->dev);
if (s->open_flag) {
printk("line %d, enter %s \n", __LINE__, __FUNCTION__);
disable_irq(s->irq);
cancel_work_sync(&s->work);
s->suspending = 1;
uart_suspend_port(&bu92747_irda_uart_driver, &s->port);
irda_hw_shutdown();
if (s->pdata->irda_pwr_ctl)
s->pdata->irda_pwr_ctl(0);
}
return 0;
}
static int bu92747_irda_resume(struct platform_device *pdev)
{
struct bu92747_port *s = dev_get_drvdata(&pdev->dev);
if (s->open_flag) {
printk("line %d, enter %s \n", __LINE__, __FUNCTION__);
if (s->pdata->irda_pwr_ctl)
s->pdata->irda_pwr_ctl(1);
irda_hw_startup();
irda_hw_set_speed(s->baud);
irda_hw_set_moderx();
uart_resume_port(&bu92747_irda_uart_driver, &s->port);
s->suspending = 0;
if (!s->tx_empty)
s->tx_empty = 1;
enable_irq(s->irq);
if (s->workqueue && !IS_FIR(s))
bu92747_irda_dowork(s);
}
return 0;
}
#else
#define bu92747_irda_suspend NULL
#define bu92747_irda_resume NULL
#endif
static struct platform_driver bu92747_irda_driver = {
.driver = {
.name = "bu92747_irda",
.owner = THIS_MODULE,
},
.probe = bu92747_irda_probe,
.remove = bu92747_irda_remove,
.suspend = bu92747_irda_suspend,
.resume = bu92747_irda_resume,
};
static int __init bu92747_irda_init(void)
{
if (platform_driver_register(&bu92747_irda_driver) != 0) {
printk("Could not register irda driver\n");
return -EINVAL;
}
return 0;
}
static void __exit bu92747_irda_exit(void)
{
platform_driver_unregister(&bu92747_irda_driver);
}
module_init(bu92747_irda_init);
module_exit(bu92747_irda_exit);
MODULE_DESCRIPTION("BU92747 irda driver");
MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");
MODULE_LICENSE("GPL");

View File

@@ -1,25 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IR_SERIAL_H_
#define _IR_SERIAL_H_
#include "bu92725guw.h"
/*
* define IOCTL macro
*/
/* magic number */
#define TTYIR_IOC_TYPE 0x56
/* TTYIR_STARTSEND */
/* function: start to send a frame in FIR mode */
/* parameter: no parameter */
/* return: no return code */
#define TTYIR_STARTSEND _IO(TTYIR_IOC_TYPE, 0)
/* TTYIR_GETLENGTH */
/* function: get the length of DATA field in the current frame */
/* paramter: no paramter */
/* return: the length of DATA field (unit:byte) */
#define TTYIR_GETLENGTH _IOR(TTYIR_IOC_TYPE, 1, unsigned long)
#endif

View File

@@ -1,783 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the BSD Licence, 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/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/random.h>
#include <linux/version.h>
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/highmem.h>
#include <linux/freezer.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/irq.h>
#include <linux/wakelock.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <mach/board.h>
#include <mach/rk29_iomap.h>
#include <mach/pmu.h>
#include <mach/rk29-dma-pl330.h>
#include "rk29_ir.h"
#if 0
#define RK29IR_DBG(x...) printk(x)
#else
#define RK29IR_DBG(x...)
#endif
#if 0
#define RK29IR_DATA_DBG(x...) printk(x)
#else
#define RK29IR_DATA_DBG(x...)
#endif
#define IRDA_NAME "rk_irda"
struct irda_driver {
struct irda_info *pin_info;
struct device *dev;
};
#define IS_FIR(si) ((si)->speed >= 4000000)
static int max_rate = 4000000;
#define IRDA_FRAME_SIZE_LIMIT BU92725GUW_FIFO_SIZE
#define RK29_MAX_RXLEN 2047
static void rk29_irda_fir_test(struct work_struct *work);
static DECLARE_DELAYED_WORK(dwork, rk29_irda_fir_test);
/*
* Allocate and map the receive buffer, unless it is already allocated.
*/
static int rk29_irda_rx_alloc(struct rk29_irda *si)
{
if (si->rxskb)
return 0;
si->rxskb = alloc_skb(RK29_MAX_RXLEN + 1, GFP_ATOMIC);
if (!si->rxskb) {
printk(KERN_ERR "rk29_ir: out of memory for RX SKB\n");
return -ENOMEM;
}
si->rxskb->len = 0;
/*
* Align any IP headers that may be contained
* within the frame.
*/
skb_reserve(si->rxskb, 1);
return 0;
}
/*
* Set the IrDA communications speed.
*/
static int rk29_irda_set_speed(struct rk29_irda *si, int speed)
{
unsigned long flags;
int ret = -EINVAL;
printk("[%s][%d], speed=%d\n",__FUNCTION__,__LINE__,speed);
switch (speed) {
case 9600: case 19200: case 38400:
case 57600: case 115200:
local_irq_save(flags);
irda_hw_set_speed(speed);
si->speed = speed;
local_irq_restore(flags);
ret = 0;
break;
case 4000000:
local_irq_save(flags);
si->speed = speed;
irda_hw_set_speed(speed);
//irda_hw_set_speed(1152000);//MIR
rk29_irda_rx_alloc(si);
local_irq_restore(flags);
ret = 0;
break;
default:
break;
}
return ret;
}
static irqreturn_t rk29_irda_irq(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct rk29_irda *si = netdev_priv(dev);
u8 data[2048]={0,0};
int tmp_len=0;
int i=0;
u32 irq_src = 0;
u32 irda_setptn = 0;
irq_src = irda_hw_get_irqsrc();
printk("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);
//disable_irq(dev->irq);
/* EIR 1, 3, 11, 12
irda_setptn |= irq_src & (REG_INT_EOFRX | REG_INT_TXE | REG_INT_WRE | REG_INT_RDE\
| REG_INT_CRC | REG_INT_OE | REG_INT_FE | REG_INT_AC\
| REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX) ;*/
irda_setptn = irq_src;
/* error */
if (irq_src & (REG_INT_TO| REG_INT_CRC | REG_INT_OE | REG_INT_FE
| REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {
RK29IR_DBG("[%s][%d]: do err\n",__FUNCTION__,__LINE__);
//BU92725GUW_dump_register();
BU92725GUW_clr_fifo();
BU92725GUW_reset();
}
if (IS_FIR(si)) //FIR
{
RK29IR_DBG("[%s][%d]: FIR\n",__FUNCTION__,__LINE__);
if(irda_hw_get_mode() == BU92725GUW_AUTO_MULTI_REV) {//rx
struct sk_buff *skb = si->rxskb;
RK29IR_DBG("[%s][%d]: rx\n",__FUNCTION__,__LINE__);
if (irda_setptn & (REG_INT_FE | REG_INT_OE | REG_INT_CRC | REG_INT_DECE)) {
if (irda_setptn & REG_INT_FE) {
printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
dev->stats.rx_frame_errors++;
} else {
printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
dev->stats.rx_errors++;
}
}
if (irda_setptn & (FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {
tmp_len = BU92725GUW_get_data(skb->data+skb->len);
skb->len += tmp_len;
}
if (irda_setptn & REG_INT_EOF) {
RK29IR_DBG("[%s][%d]: report data:\n",__FUNCTION__,__LINE__);
si->rxskb = NULL;
RK29IR_DATA_DBG("[%s][%d]: fir report data:\n",__FUNCTION__,__LINE__);
for (i=0;i<skb->len;i++) {
RK29IR_DATA_DBG("0x%2x ", skb->data[i]);
}
RK29IR_DATA_DBG("\n");
skb_put(skb, skb->len);
/* Feed it to IrLAP */
skb->dev = dev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
/*
* Before we pass the buffer up, allocate a new one.
*/
rk29_irda_rx_alloc(si);
netif_rx(skb);
}
}
else if (irda_hw_get_mode() == BU92725GUW_MULTI_SEND) {//tx
struct sk_buff *skb = si->txskb;
si->txskb = NULL;
RK29IR_DBG("[%s][%d]: tx\n",__FUNCTION__,__LINE__);
if (irda_setptn & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {
/*
* Do we need to change speed? Note that we're lazy
* here - we don't free the old rxskb. We don't need
* to allocate a buffer either.
*/
if (si->newspeed) {
rk29_irda_set_speed(si, si->newspeed);
si->newspeed = 0;
}
/*
* Account and free the packet.
*/
if (skb) {
dev->stats.tx_packets ++;
dev->stats.tx_bytes += skb->len;
dev_kfree_skb_irq(skb);
}
/*
* Make sure that the TX queue is available for sending
* (for retries). TX has priority over RX at all times.
*/
netif_wake_queue(dev);
irda_hw_set_moderx();
}
}
}
else //SIR
{
RK29IR_DBG("[%d][%s], sir\n", __LINE__, __FUNCTION__);
if(irda_hw_get_mode() == BU92725GUW_REV) //rx
{
RK29IR_DBG("[%d][%s], receive data:\n", __LINE__, __FUNCTION__);
if(irda_setptn & (REG_INT_OE | REG_INT_FE ))
{
dev->stats.rx_errors++;
if (irda_setptn & REG_INT_FE)
dev->stats.rx_frame_errors++;
if (irda_setptn & REG_INT_OE)
dev->stats.rx_fifo_errors++;
}
if((irda_setptn & ( FRM_EVT_RX_EOFRX| REG_INT_EOF /*|FRM_EVT_RX_RDE*/)))
{
tmp_len = BU92725GUW_get_data(data);
RK29IR_DATA_DBG("[%d][%s], sir receive data:\n", __LINE__, __FUNCTION__);
for(i=0;i<=tmp_len;i++)
{
RK29IR_DATA_DBG("0x%2x ",data[i]);
async_unwrap_char(dev, &dev->stats, &si->rx_buff, data[i]);
}
RK29IR_DATA_DBG("\n");
//BU92725GUW_clr_fifo();
}
}
else if(irda_hw_get_mode() == BU92725GUW_SEND) //tx
{
RK29IR_DBG("[%d][%s], transmit data\n", __LINE__, __FUNCTION__);
if((irda_setptn & FRM_EVT_TX_TXE) && (si->tx_buff.len)) {
RK29IR_DATA_DBG("[%d][%s], sir transmit data:\n", __LINE__, __FUNCTION__);
for (i=0;i<si->tx_buff.len;i++) {
RK29IR_DATA_DBG("0x%2x ", *(si->tx_buff.data)++);
}
RK29IR_DATA_DBG("\n");
BU92725GUW_send_data(si->tx_buff.data, si->tx_buff.len, NULL, 0);
si->tx_buff.len = 0;
}
else if (si->tx_buff.len == 0) {
dev->stats.tx_packets++;
dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;
/*
* Ok, we've finished transmitting. Now enable
* the receiver. Sometimes we get a receive IRQ
* immediately after a transmit...
*/
if (si->newspeed) {
rk29_irda_set_speed(si, si->newspeed);
si->newspeed = 0;
}
irda_hw_set_moderx();
/* I'm hungry! */
netif_wake_queue(dev);
}
}
}
//enable_irq(dev->irq);
return IRQ_HANDLED;
}
static int rk29_irda_start(struct net_device *dev)
{
struct rk29_irda *si = netdev_priv(dev);
int err = 0;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
si->speed = 9600;
/*
* irda module power up
*/
if (si->pdata->irda_pwr_ctl)
si->pdata->irda_pwr_ctl(1);
si->power = 1;
err = request_irq(dev->irq, rk29_irda_irq, IRQ_TYPE_LEVEL_LOW, dev->name, dev);//
if (err) {
printk("line %d: %s request_irq failed\n", __LINE__, __func__);
goto err_irq;
}
/*
* The interrupt must remain disabled for now.
*/
disable_irq(dev->irq);
/*
* Setup the smc port for the specified speed.
*/
err = irda_hw_startup();
if (err) {
printk("line %d: %s irda_hw_startup err\n", __LINE__, __func__);
goto err_startup;
}
irda_hw_set_moderx();
/*
* Open a new IrLAP layer instance.
*/
si->irlap = irlap_open(dev, &si->qos, "rk29");
err = -ENOMEM;
if (!si->irlap) {
printk("line %d: %s irlap_open err\n", __LINE__, __func__);
goto err_irlap;
}
/*
* Now enable the interrupt and start the queue
*/
si->open = 1;
enable_irq(dev->irq);
netif_start_queue(dev);
printk("rk29_ir: irda driver opened\n");
//test
//rk29_irda_set_speed(si, 4000000);
//schedule_delayed_work(&dwork, msecs_to_jiffies(5000));
return 0;
err_irlap:
si->open = 0;
irda_hw_shutdown();
if (si->pdata->irda_pwr_ctl)
si->pdata->irda_pwr_ctl(0);
err_startup:
free_irq(dev->irq, dev);
err_irq:
return err;
}
static int rk29_irda_stop(struct net_device *dev)
{
struct rk29_irda *si = netdev_priv(dev);
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
disable_irq(dev->irq);
irda_hw_shutdown();
/*
* If we have been doing DMA receive, make sure we
* tidy that up cleanly.
*/
if (si->rxskb) {
dev_kfree_skb(si->rxskb);
si->rxskb = NULL;
}
/* Stop IrLAP */
if (si->irlap) {
irlap_close(si->irlap);
si->irlap = NULL;
}
netif_stop_queue(dev);
si->open = 0;
/*
* Free resources
*/
free_irq(dev->irq, dev);
//irda module power down
if (si->pdata->irda_pwr_ctl)
si->pdata->irda_pwr_ctl(0);
si->power = 0;
return 0;
}
static int rk29_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rk29_irda *si = netdev_priv(dev);
int speed = irda_get_next_speed(skb);
int i;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
/*
* Does this packet contain a request to change the interface
* speed? If so, remember it until we complete the transmission
* of this frame.
*/
if (speed != si->speed && speed != -1)
si->newspeed = speed;
/*
* If this is an empty frame, we can bypass a lot.
*/
if (skb->len == 0) {
if (si->newspeed) {
si->newspeed = 0;
rk29_irda_set_speed(si, speed);
}
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
netif_stop_queue(dev);
if (!IS_FIR(si)) {
si->tx_buff.data = si->tx_buff.head;
si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
/* Disable STUART interrupts and switch to transmit mode. */
/* enable STUART and transmit interrupts */
irda_hw_tx_enable_irq(BU92725GUW_SIR);
RK29IR_DATA_DBG("[%d][%s], sir transmit data:\n", __LINE__, __FUNCTION__);
for (i=0;i<si->tx_buff.len;i++) {
RK29IR_DATA_DBG("0x%2x ", *(si->tx_buff.data)++);
}
RK29IR_DATA_DBG("\n");
dev_kfree_skb(skb);
dev->trans_start = jiffies;
BU92725GUW_send_data(si->tx_buff.data, si->tx_buff.len, NULL, 0);
si->tx_buff.len = 0;
}
else {
unsigned long mtt = irda_get_mtt(skb);
si->txskb = skb;
irda_hw_tx_enable_irq(BU92725GUW_FIR);
RK29IR_DATA_DBG("[%d][%s], fir transmit data:\n", __LINE__, __FUNCTION__);
for (i=0;i<skb->len;i++) {
RK29IR_DATA_DBG("0x%2x ", skb->data[i]);
}
RK29IR_DATA_DBG("\n");
dev->trans_start = jiffies;
BU92725GUW_send_data(skb->data, skb->len, NULL, 0);
}
return NETDEV_TX_OK;
}
static int
rk29_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
{
struct if_irda_req *rq = (struct if_irda_req *)ifreq;
struct rk29_irda *si = netdev_priv(dev);
int ret = -EOPNOTSUPP;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
switch (cmd) {
case SIOCSBANDWIDTH:
if (capable(CAP_NET_ADMIN)) {
/*
* We are unable to set the speed if the
* device is not running.
*/
if (si->open) {
ret = rk29_irda_set_speed(si, rq->ifr_baudrate );
} else {
printk("rk29_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
ret = 0;
}
}
break;
case SIOCSMEDIABUSY:
ret = -EPERM;
if (capable(CAP_NET_ADMIN)) {
irda_device_set_media_busy(dev, TRUE);
ret = 0;
}
break;
case SIOCGRECEIVING:
rq->ifr_receiving = IS_FIR(si) ? 0
: si->rx_buff.state != OUTSIDE_FRAME;
break;
default:
break;
}
return ret;
}
static const struct net_device_ops rk29_irda_netdev_ops = {
.ndo_open = rk29_irda_start,
.ndo_stop = rk29_irda_stop,
.ndo_start_xmit = rk29_irda_hard_xmit,
.ndo_do_ioctl = rk29_irda_ioctl,
};
static int rk29_irda_init_iobuf(iobuff_t *io, int size)
{
io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
if (io->head != NULL) {
io->truesize = size;
io->in_frame = FALSE;
io->state = OUTSIDE_FRAME;
io->data = io->head;
}
return io->head ? 0 : -ENOMEM;
}
static void rk29_irda_fir_test(struct work_struct *work)
{
char send_data[4] = {1,0,1,0};
irda_hw_tx_enable_irq(BU92725GUW_FIR);
BU92725GUW_send_data(send_data, 4, NULL, 0);
schedule_delayed_work(&dwork, msecs_to_jiffies(5000));
return ;
}
static int rk29_irda_probe(struct platform_device *pdev)
{
struct irda_info *mach_info = NULL;
struct net_device *dev;
struct rk29_irda *si;
unsigned int baudrate_mask;
int err = -ENOMEM;
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
mach_info = pdev->dev.platform_data;
if (mach_info)
mach_info->iomux_init();
dev = alloc_irdadev(sizeof(struct rk29_irda));
if (!dev) {
printk("line %d: rk29_ir malloc failed\n", __LINE__);
goto err_mem_1;
}
SET_NETDEV_DEV(dev, &pdev->dev);
si = netdev_priv(dev);
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
/*
* Initialise the HP-SIR buffers
*/
err = rk29_irda_init_iobuf(&si->rx_buff, 14384);
if (err) {
printk("line %d: rk29_ir malloc failed\n", __LINE__);
goto err_mem_2;
}
err = rk29_irda_init_iobuf(&si->tx_buff, 4000);
if (err) {
printk("line %d: rk29_ir malloc failed\n", __LINE__);
goto err_mem_3;
}
dev->netdev_ops = &rk29_irda_netdev_ops;
dev->irq = gpio_to_irq(mach_info->intr_pin);
irda_init_max_qos_capabilies(&si->qos);
/*
* We support original IRDA up to 115k2. (we don't currently
* support 4Mbps). Min Turn Time set to 1ms or greater.
*/
baudrate_mask = IR_9600;
switch (max_rate) {
case 4000000: baudrate_mask |= IR_4000000 << 8;
case 115200: baudrate_mask |= IR_115200;
case 57600: baudrate_mask |= IR_57600;
case 38400: baudrate_mask |= IR_38400;
case 19200: baudrate_mask |= IR_19200;
}
si->qos.baud_rate.bits &= baudrate_mask;
si->qos.min_turn_time.bits = 7;
irda_qos_bits_to_value(&si->qos);
/*
* Initially enable HP-SIR modulation, and ensure that the port
* is disabled.
*/
err = register_netdev(dev);
if (err) {
printk("line %d: rk29_ir register_netdev failed\n", __LINE__);
goto err_register;
}
platform_set_drvdata(pdev, dev);
//test
//wake_lock_init(&w_lock, WAKE_LOCK_SUSPEND, "rk29_cir");
//wake_lock(&w_lock);
return 0;
err_register:
kfree(si->tx_buff.head);
err_mem_3:
kfree(si->rx_buff.head);
err_mem_2:
free_netdev(dev);
err_mem_1:
return err;
}
static int rk29_irda_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);
if (dev) {
struct rk29_irda *si = netdev_priv(dev);
unregister_netdev(dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
free_netdev(dev);
}
return 0;
}
#ifdef CONFIG_PM
/*
* Suspend the IrDA interface.
*/
static int rk29_irda_suspend(struct platform_device *pdev, pm_message_t state)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct rk29_irda *si;
if (!dev)
return 0;
si = netdev_priv(dev);
if (si->open) {
/*
* Stop the transmit queue
*/
netif_device_detach(dev);
disable_irq(dev->irq);
irda_hw_shutdown();
if (si->pdata->irda_pwr_ctl)
si->pdata->irda_pwr_ctl(0);
}
return 0;
}
/*
* Resume the IrDA interface.
*/
static int rk29_irda_resume(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct rk29_irda *si;
if (!dev)
return 0;
si = netdev_priv(dev);
if (si->open) {
if (si->pdata->irda_pwr_ctl)
si->pdata->irda_pwr_ctl(1);
/*
* If we missed a speed change, initialise at the new speed
* directly. It is debatable whether this is actually
* required, but in the interests of continuing from where
* we left off it is desireable. The converse argument is
* that we should re-negotiate at 9600 baud again.
*/
if (si->newspeed) {
si->speed = si->newspeed;
si->newspeed = 0;
}
irda_hw_startup();
enable_irq(dev->irq);
/*
* This automatically wakes up the queue
*/
netif_device_attach(dev);
}
return 0;
}
#else
#define rk29_irda_suspend NULL
#define rk29_irda_resume NULL
#endif
static struct platform_driver irda_driver = {
.driver = {
.name = IRDA_NAME,
.owner = THIS_MODULE,
},
.probe = rk29_irda_probe,
.remove = rk29_irda_remove,
.suspend = rk29_irda_suspend,
.resume = rk29_irda_resume,
};
static int __init irda_init(void)
{
if (platform_driver_register(&irda_driver) != 0) {
printk("Could not register irda driver\n");
return -EINVAL;
}
return 0;
}
static void __exit irda_exit(void)
{
platform_driver_unregister(&irda_driver);
}
module_init(irda_init);
module_exit(irda_exit);
MODULE_AUTHOR(" zyw@rock-chips.com");
MODULE_DESCRIPTION("Driver for irda device");
MODULE_LICENSE("GPL");

View File

@@ -1,40 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DRIVERS_NET_IRDA_RK29_IR_H
#define __DRIVERS_NET_IRDA_RK29_IR_H
#include "bu92725guw.h"
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
struct rk29_irda {
unsigned char* irda_base_addr;
unsigned char power;
unsigned char open;
int speed;
int newspeed;
struct sk_buff *txskb;
struct sk_buff *rxskb;
unsigned char *dma_rx_buff;
unsigned char *dma_tx_buff;
u32 dma_rx_buff_phy;
u32 dma_tx_buff_phy;
unsigned int dma_tx_buff_len;
int txdma;
int rxdma;
struct device *dev;
struct irda_info *pdata;
struct irlap_cb *irlap;
struct qos_info qos;
iobuff_t tx_buff;
iobuff_t rx_buff;
};
#endif //__DRIVERS_NET_IRDA_RK29_IR_H