/* extdrv/interface/ssp/hi_ssp.c
*
* Copyright (c) 2006 Hisilicon Co., Ltd.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
* History:
* 21-April-2006 create this file
*/
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include "hi_ssp.h"
#ifdef __HuaweiLite__
#else
#include <mach/io.h>/* for IO_ADDRESS */
#endif
#define ssp_readw(addr,ret) (ret =(*(volatile unsigned int *)(addr)))
#define ssp_writew(addr,value) ((*(volatile unsigned int *)(addr)) = (value))
#define HI_REG_READ(addr,ret) (ret =(*(volatile unsigned int *)(addr)))
#define HI_REG_WRITE(addr,value) ((*(volatile unsigned int *)(addr)) = (value))
//0x12121000 spi1 0x12122000 spi2 0x12123000 spi3
#define SSP_BASE 0x12123000
#define SSP_SIZE 0x10000 // 64KB
#define SSP_INT 41 // Interrupt No.
#ifdef __HuaweiLite__
#define IO_ADDRESS_VERIFY(x) (x)
#else
void __iomem *reg_ssp_base_va;
#define IO_ADDRESS_VERIFY(x) (reg_ssp_base_va + ((x)-(SSP_BASE)))
#endif
/* SSP register definition .*/
#define SSP_CR0 IO_ADDRESS_VERIFY(SSP_BASE + 0x00)
#define SSP_CR1 IO_ADDRESS_VERIFY(SSP_BASE + 0x04)
#define SSP_DR IO_ADDRESS_VERIFY(SSP_BASE + 0x08)
#define SSP_SR IO_ADDRESS_VERIFY(SSP_BASE + 0x0C)
#define SSP_CPSR IO_ADDRESS_VERIFY(SSP_BASE + 0x10)
#define SSP_IMSC IO_ADDRESS_VERIFY(SSP_BASE + 0x14)
#define SSP_RIS IO_ADDRESS_VERIFY(SSP_BASE + 0x18)
#define SSP_MIS IO_ADDRESS_VERIFY(SSP_BASE + 0x1C)
#define SSP_ICR IO_ADDRESS_VERIFY(SSP_BASE + 0x20)
#define SSP_DMACR IO_ADDRESS_VERIFY(SSP_BASE + 0x24)
#define SPI_SR_BSY (0x1 << 4)/* spi busy flag */
#define SPI_SR_TFE (0x1 << 0)/* Whether to send fifo is empty */
#define MAX_WAIT 10000
/*gpio*/
#define GPIO_BASE0 0x12140000
#define GPIO_BASE1 0x12141000
#define GPIO_BASE2 0x12142000
#define GPIO_BASE3 0x12143000
#define GPIO_BASE4 0x12144000
#define GPIO_BASE5 0x12145000
#define GPIO_BASE6 0x12146000
#define GPIO_BASE7 0x12147000
#define GPIO_BASE8 0x12148000
#define GPIO_BASE9 0x12149000
#define GPIO_BASE10 0x1214a000
#define GPIO_BASE11 0x1214b000
#define GPIO_BASE12 0x1214c000
#define GPIO_BASE13 0x1214d000
#define GPIO_BASE14 0x1214e000
#define GPIO_BASE15 0x0
#define GPIO_BASE16 0x12150000
#define GPIO_DATA(gpio_group_reg_base, gpio_offset) IO_ADDRESS_VERIFY(((gpio_group_reg_base) + 0x000) + (1 << ((gpio_offset) + 2)))
#define GPIO_DIR(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x400)
#define GPIO_IS(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x404)
#define GPIO_IBE(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x408)
#define GPIO_IEV(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x40C)
#define GPIO_IE(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x410)
#define GPIO_MIS(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x418)
#define GPIO_IC(gpio_group_reg_base) IO_ADDRESS_VERIFY((gpio_group_reg_base) + 0x41C)
const static unsigned int g_gpio_group_reg_base[] = {
GPIO_BASE0,
GPIO_BASE1,
GPIO_BASE2,
GPIO_BASE3,
GPIO_BASE4,
GPIO_BASE5,
GPIO_BASE6,
GPIO_BASE7,
GPIO_BASE8,
GPIO_BASE9,
GPIO_BASE10,
GPIO_BASE11,
GPIO_BASE12,
GPIO_BASE13,
GPIO_BASE14,
GPIO_BASE15,
GPIO_BASE16
};
void gpio_dir_config(unsigned char gpio_group, unsigned char gpio_offset, unsigned char flag)
{
unsigned int val = 0;
unsigned int addr = 0;
addr = GPIO_DIR(g_gpio_group_reg_base[gpio_group]);
val = readl(addr);
if(flag)
{
val |= 1 << gpio_offset;
}
else
{
val &= ~(1 << gpio_offset);
}
writel(val, addr);
}
void gpio_write(unsigned char gpio_group, unsigned char gpio_offset, unsigned char flag)
{
unsigned int val = 0;
unsigned int addr = 0;
addr = GPIO_DATA(g_gpio_group_reg_base[gpio_group], gpio_offset);
if(flag)
{
val = 1 << gpio_offset;
}
else
{
val = 0;
}
writel(val,addr);
}
unsigned int gpio_read(unsigned char gpio_group, unsigned char gpio_offset)
{
unsigned int val = 0;
unsigned int addr = 0;
addr = GPIO_DATA(g_gpio_group_reg_base[gpio_group], gpio_offset);
val = readl(addr);
if(val & (1 << gpio_offset))
{
val = 1;
}
else
{
val = 0;
}
return val;
}
/*gpio end*/
static int hi_spi_check_timeout(void)
{
unsigned int value = 0;
unsigned int tmp = 0;
while (1)
{
ssp_readw(SSP_SR,value);
if ((value & SPI_SR_TFE) && (!(value & SPI_SR_BSY)))
{
break;
}
if (tmp++ > MAX_WAIT)
{
printk("spi transfer wait timeout!\n");
return -1;
}
udelay(1);
}
return 0;
}
void hi_ssp_writeOnly(int bWriteOnly)
{
int ret = 0;
bWriteOnly = 0;
ssp_readw(SSP_CR1,ret);
if (bWriteOnly)
{
ret = ret | (0x1 << 5);
}
else
{
ret = ret & (~(0x1 << 5));
}
ssp_writew(SSP_CR1,ret);
}
void hi_ssp_enable(void)
{
int ret = 0;
ssp_readw(SSP_CR1,ret);
ret = (ret & 0xFFFD) | 0x2;
ret = ret | (0x1 << 4); /* big/little end, 1: little, 0: big */
ret = ret | (0x1 << 15); /* wait en */
ssp_writew(SSP_CR1,ret);
hi_ssp_writeOnly(0);
}
void hi_ssp_disable(void)
{
int ret = 0;
ssp_readw(SSP_CR1,ret);
ret = ret & (~(0x1 << 1));
ssp_writew(SSP_CR1,ret);
}
int hi_ssp_set_frameform(unsigned char framemode,unsigned char spo,unsigned char sph,unsigned char datawidth)
{
int ret = 0;
ssp_readw(SSP_CR0,ret);
if(framemode > 3)
{
printk("set frame parameter err.\n");
return -1;
}
ret = (ret & 0xFFCF) | (framemode << 4);
if((ret & 0x30) == 0)
{
if(spo > 1)
{
printk("set spo parameter err.\n");
return -1;
}
if(sph > 1)
{
printk("set sph parameter err.\n");
return -1;
}
ret = (ret & 0xFF3F) | (sph << 7) | (spo << 6);
}
if((datawidth > 16) || (datawidth < 4))
{
printk("set datawidth parameter err.\n");
return -1;
}
ret = (ret & 0xFFF0) | (datawidth -1);
ssp_writew(SSP_CR0,ret);
return 0;
}
int hi_ssp_set_serialclock(unsigned char scr,unsigned char cpsdvsr)
{
int ret = 0;
ssp_readw(SSP_CR0,ret);
ret = (ret & 0xFF) | (scr << 8);
ssp_writew(SSP_CR0,ret);
if((cpsdvsr & 0x1))
{
printk("set cpsdvsr parameter err.\n");
return -1;
}
ssp_writew(SSP_CPSR,cpsdvsr);
return 0;
}
int hi_ssp_alt_mode_set(int enable)
{
int ret = 0;
ssp_readw(SSP_CR1,ret);
if (enable)
{
ret = ret & (~0x40);
}
else
{
ret = (ret & 0xFF) | 0x40;
}
ssp_writew(SSP_CR1,ret);
return 0;
}
static void spi_enable(void)
{
HI_REG_WRITE(SSP_CR
评论0