亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? cpm_spi.c

?? 一個非常有用的SPI驅(qū)動程序,是在LINUX平臺下的,但也可以一直到其他平臺
?? C
字號:
/*
 * Simple CPM SPI interface for the MPC 8260.
 *
 * based on the version for MPC860 by:
 * 
 * Copyright (c) 2002 Wolfgang Grandegger (wg@denx.de)
 *
 * This interface is partially derived from code copyrighted
 * by Navin Boppuri (nboppuri@trinetcommunication.co) and
 * Prashant Patel (pmpatel@trinetcommunication.com).
 *
 * This driver implements the function "cpm_spi_io()" to be 
 * used by other drivers and a simple read/write interface 
 * for user-land applications. The latter is mainly useful 
 * for debugging purposes. Some further remarks:
 *
 * - Board specific definitions and code should go into
 *   the file "cpm_spi.h".
 *
 * - For the moment, no interrupts are used. This be useful 
 *   for (very) long transfers.
 */

#include <linux/config.h>
#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <asm/page.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <asm/immap_8260.h>
#include <asm/mpc8260.h>

#include <asm/cpm_8260.h>
#include <asm/cpm_spi.h>

#define DRIVER_NAME "cpm_spi"

MODULE_AUTHOR("Wolfgang Grandegger (wg@denx.de)");
MODULE_DESCRIPTION("Simple Driver for the CPM SPI");

#undef DEBUG
#ifdef DEBUG
# define debugk(fmt,args...)    printk(fmt ,##args)
#else
# define debugk(fmt,args...)
#endif

#define CPM_SPI_MAJOR 65	/* "borrowed" from "plink" driver */

#define CONFIG_CPM_SPI_BDSIZE 16

static volatile immap_t *immap = (immap_t *)IMAP_ADDR;

static unsigned int dp_addr;
static ushort r_tbase, r_rbase; 
static cbd_t *tx_bdf, *rx_bdf;
static u_char *tx_buf, *rx_buf;

extern void invalidate_dcache_range(unsigned long start, unsigned long end);

#if CPM_SPI_SWAP_BYTES
static void swap_bytes(u_char *buf, int len)
{
	u_short *sbuf = (u_short *)buf;
	while (len > 0) {
		*sbuf = cpu_to_le16(*sbuf);
		sbuf++; 
		len -= 2;
	}
}
#else
#define swap_bytes(buf, len)
#endif

/*
 * CPM SPI Kernel API function(s)
 */
ssize_t cpm_spi_io (int chip_id, int serial,
		    u_char *tx_buffer, int tx_size, 
		    u_char *rx_buffer, int rx_size)
{
	unsigned long flags;
	int i;

	/* 
	 * Serialize access to the SPI. We have to disable interrupts
	 * because we may need to call it from interrupt handlers.
	 */
	save_flags(flags); cli();

	rx_bdf->cbd_datlen = 0;
	if (serial)
		tx_bdf->cbd_datlen = tx_size + rx_size;
	else
		tx_bdf->cbd_datlen = tx_size > rx_size ? tx_size : rx_size;
	if (tx_bdf->cbd_datlen > CONFIG_CPM_SPI_BDSIZE) {
		printk("cpm_spi_io: Invalid size\n");
		restore_flags(flags);
		return -EINVAL;
	}
	if (tx_size > 0) {
		memcpy(tx_buf, tx_buffer, tx_size);
#ifdef DEBUG
		printk("Tx:");
		for (i = 0; i < tx_size; i++)
			printk(" %02x", tx_buf[i]);
		printk("\n");
#endif
		swap_bytes(tx_buf, tx_size);
	}

	flush_dcache_range((unsigned long) tx_buf, 
			   (unsigned long) (tx_buf+CONFIG_CPM_SPI_BDSIZE-1));
	flush_dcache_range((unsigned long) rx_buf, 
			   (unsigned long) (rx_buf+CONFIG_CPM_SPI_BDSIZE-1));
	invalidate_dcache_range((unsigned long) rx_buf, 
				(unsigned long) (rx_buf+
						 CONFIG_CPM_SPI_BDSIZE-1));

	/* Setting Rx and Tx BD status and data length */
	tx_bdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
	rx_bdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;

	/* Chip select for device */
	cpm_spi_set_cs(immap, chip_id, 1);

	/* Start SPI Tx/Rx transfer */
	immap->im_spi.spi_spcom |= 0x80;

	/* 
	 * Wait until the Tx/Rx transfer is done. 
	 */
	for (i = 0; i < CPM_SPI_POLL_RETRIES; i++) {
                udelay(5);
		if ((tx_bdf->cbd_sc & BD_SC_EMPTY) == 0 && 
		    (rx_bdf->cbd_sc & BD_SC_EMPTY) == 0)
			break;
        }

	/* De-select device */
	cpm_spi_set_cs(immap, chip_id, 0);

	/* Check for timeout */
	if (i == CPM_SPI_POLL_RETRIES) {
		printk("cpm_spi_io: Tx/Rx transfer timeout\n");
		restore_flags(flags);
		return -EIO;
	}

#ifdef DEBUG
	printk("Transfer time approx. %d us\n", i*5);
	if (rx_bdf->cbd_datlen > 0) {
		printk("Rx:");
		for (i = 0; i < rx_bdf->cbd_datlen; i++)
			printk(" %02x", rx_buf[i]);
		printk("\n");
	}
#endif

	/* Copy receive data if appropriate */
	i = rx_bdf->cbd_datlen;
	swap_bytes(rx_buf, i);
	if (rx_size > 0) {
		if (serial) {
			i -= tx_size;
			if (i != rx_size)
				printk("i=%d rx_size=%d\n", i, rx_size);
			memcpy(rx_buffer, rx_buf + tx_size, i);
		} else {
			if (i != (rx_size > rx_size ? tx_size : rx_size))
				printk("i=%d rx_size=%d tx_size=%d\n", 
				       i, tx_size, rx_size);
			memcpy(rx_buffer, rx_buf, i);
		}
	}
	
	restore_flags(flags);
	
	return i;
}

//EXPORT_SYMBOL(cpm_spi_io);

/*
 * Prototypes for driver entry functions.
 */
static int
cpm_spi_open(struct inode *inode, struct file *filp);
static int
cpm_spi_release(struct inode *inode, struct file *filp);
static ssize_t
cpm_spi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
static ssize_t
cpm_spi_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
static int
cpm_spi_init(void);
static void
cpm_spi_cleanup(void);

/*
 * File operations supported by this driver.
 */
struct file_operations cpm_spi_fops = {
	owner:   THIS_MODULE,
	open:    cpm_spi_open,
	release: cpm_spi_release,
	read:    cpm_spi_read,
	write:   cpm_spi_write,
};


static int 
cpm_spi_open (struct inode *inode, struct file *filp)
{
	int minor = MINOR(inode->i_rdev);

	if (minor >= CPM_SPI_MAX_CHIPS)
		return -ENODEV;

	filp->private_data = (void *)minor;
	MOD_INC_USE_COUNT;
	return 0;
}

static int 
cpm_spi_release(struct inode *inode, struct file *filp)
{
	MOD_DEC_USE_COUNT;
	return 0;
}

static ssize_t 
cpm_spi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
	u_char tx_kbuf[CONFIG_CPM_SPI_BDSIZE];
	u_char rx_kbuf[CONFIG_CPM_SPI_BDSIZE];
	int chip_id = (int)filp->private_data;
	ssize_t size;
	
	debugk(__FUNCTION__ ": count=%d, chip_id=%d\n", count, chip_id);

	if (count > CONFIG_CPM_SPI_BDSIZE)
		return -ENXIO;
	
	if (copy_from_user(tx_kbuf, buf, count))
		return -EFAULT;
	
	size = cpm_spi_io(chip_id, 0, tx_kbuf, count, rx_kbuf, count);
	if (size < 0)
		return size;
	
	if (copy_to_user(buf, rx_kbuf, size))
		return -EFAULT;
	
	return size;
}

static ssize_t 
cpm_spi_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
	int chip_id = (int)filp->private_data;
	u_char tx_kbuf[CONFIG_CPM_SPI_BDSIZE];

	if (count > CONFIG_CPM_SPI_BDSIZE)
		return -ENXIO;

	if (copy_from_user(tx_kbuf, buf, count))
		return -EFAULT;

	return cpm_spi_io(chip_id, 0, tx_kbuf, count, NULL, 0);
}


static int 
cpm_spi_init(void)
{
	int err = 0;
        volatile spi_t    *spi;

        printk (KERN_INFO "CPM SPI Driver: $Revision: 1.0 $ wd@denx.de\n");

	/* Global pointer to internal registers */
	immap = (immap_t *)IMAP_ADDR;

	*(ushort *)(&immap->im_dprambase[PROFF_SPI_BASE]) = PROFF_SPI;
	spi = (spi_t *)&immap->im_dprambase[PROFF_SPI];   

        /* 
	 * Initialize the parameter RAM. We need to make sure
	 * many things are initialized to zero, especially in 
	 * the case of a microcode patch.
         */
        spi->spi_rdp = 0;
        spi->spi_rbptr = 0;
        spi->spi_rbc = 0;   
        spi->spi_rxtmp = 0;
        spi->spi_tstate = 0;
        spi->spi_tdp = 0;
        spi->spi_tbptr = 0;
        spi->spi_tbc = 0;
        spi->spi_txtmp = 0;

	/* 
	 * Allocate space for one transmit and one receive buffer
         * descriptor in the DP RAM.  
         */
        dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2, 8);
        if (dp_addr == CPM_DP_NOSPACE) {
		printk("cpm_spi: m8260_cpm_dpalloc() failed\n");
                return -ENOMEM;
        }

        /* 
	 * Set up the IIC parameters in the parameter RAM. 
	 */
        spi->spi_rbase = r_rbase = dp_addr;
        spi->spi_tbase = r_tbase = dp_addr + sizeof(cbd_t);

	/*
	 * Setting transmit and receive buffer descriptor pointers
	 * intially to rbase and rbase. 
	 */
        spi->spi_rbptr = spi->spi_rbase;
        spi->spi_tbptr = spi->spi_tbase;
	
        /* Setting CPCR */
        cpmp->cp_cpcr |= 
		mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 
			  0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
        while(cpmp->cp_cpcr & CPM_CR_FLG) ;

        /* Set to big endian. */
        spi->spi_tfcr = CPMFCR_EB;
        spi->spi_rfcr = CPMFCR_EB;

        /* Set maximum receive size. */
        spi->spi_mrblr = CONFIG_CPM_SPI_BDSIZE;

	/* 
	 * Clear all pending SPI events and mask all possible SPI
	 * interrupts. For the moment we don't use interrupts.
	 */
	immap->im_spi.spi_spie = 0xff;
	immap->im_spi.spi_spim = 0x00;

	/* 
	 * Set SPI Mode register. 
	 * Note: the board-specific definitions are in cpm_spi.h. 
	 */
        immap->im_spi.spi_spmode = CPM_SPI_SPMODE | SPMODE_EN;

	/* 
	 * Initiliaze port pins for SPI
	 *                  par dir odr
	 * PD16 -> SPIMISO:  1   0   1
	 * PD17 -> SPIMOSI:  1   0   1
	 * PD18 -> SPICLK :  1   0   1
	 */
	immap->im_ioport.iop_ppard |=  0x0000e000;
	immap->im_ioport.iop_psord |=  0x0000e000;
	immap->im_ioport.iop_pdird &= ~0x0000e000;

	/* 
	 * Initialize board-specific port for chip select etc.
	 * Note: the board-specific definitions are in cpm_spi.h. 
	 */
	cpm_spi_init_ports(immap);

	/* Tx and Rx buffer descriptors. */
	tx_bdf = (cbd_t *)&immap->im_dprambase[r_tbase];
	rx_bdf = (cbd_t *)&immap->im_dprambase[r_rbase];

	/* Initialize Tx and Tx BD's */
	rx_bdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
	tx_bdf->cbd_sc = BD_SC_LAST | BD_SC_WRAP;

	/* Allocate memory for Rx and Tx buffers */
	tx_buf = (u_char *)m8260_cpm_hostalloc(CONFIG_CPM_SPI_BDSIZE, 16);
	rx_buf = (u_char *)m8260_cpm_hostalloc(CONFIG_CPM_SPI_BDSIZE, 16);

	/* Set the bd's rx and tx buffer address pointers */
	tx_bdf->cbd_bufaddr = __pa(tx_buf);
	rx_bdf->cbd_bufaddr = __pa(rx_buf);

	/* 
	 * Finally register the driver.
	 */
	err = register_chrdev(CPM_SPI_MAJOR, DRIVER_NAME, &cpm_spi_fops);
	if (err < 0) {
		printk("cpm_spi: Couldn't register driver (major=%d)\n", 
		       CPM_SPI_MAJOR);
		return err;
	}

	return 0;
}

static void 
cpm_spi_cleanup(void)
{
	unregister_chrdev(CPM_SPI_MAJOR, DRIVER_NAME);
}

module_init(cpm_spi_init);
module_exit(cpm_spi_cleanup);

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
美女脱光内衣内裤视频久久网站| 欧洲一区二区三区在线| 欧美精品少妇一区二区三区| 欧美精品一卡二卡| 欧美tickle裸体挠脚心vk| 日韩福利视频导航| 国模少妇一区二区三区| 日韩中文字幕1| 日韩一区二区视频在线观看| 蜜臀av性久久久久av蜜臀妖精| 日韩一区国产二区欧美三区| 狠狠色丁香久久婷婷综| 久久这里只有精品6| 成人国产精品免费网站| 一区二区三区在线免费视频| 欧美日韩久久不卡| 久久激情五月激情| 国产精品美女一区二区在线观看| 91免费观看视频在线| 午夜a成v人精品| 久久蜜桃一区二区| 91香蕉视频污在线| 日韩va欧美va亚洲va久久| 久久久久久亚洲综合| 97久久超碰国产精品| 日韩国产精品大片| 亚洲国产精品成人综合色在线婷婷 | 日韩欧美成人一区| 国产成人午夜精品5599| 亚洲一区在线看| 精品国产91久久久久久久妲己| 成人黄色在线看| 天堂久久一区二区三区| 欧美激情一区不卡| 在线不卡一区二区| av中文字幕不卡| 理论片日本一区| 亚洲欧洲制服丝袜| 精品久久久三级丝袜| 色激情天天射综合网| 国产一区二区三区观看| 亚洲精品国产一区二区三区四区在线 | 日韩理论片一区二区| 91麻豆精品国产91久久久久| 国产传媒久久文化传媒| 五月天欧美精品| 国产精品免费看片| 26uuu国产电影一区二区| 91高清视频在线| 成人一二三区视频| 九色|91porny| 亚洲成a人片综合在线| 国产精品不卡一区二区三区| 日韩一区二区三区电影| 欧美综合一区二区| 成人丝袜高跟foot| 国内精品自线一区二区三区视频| 亚洲无线码一区二区三区| 国产精品成人网| 久久精品夜夜夜夜久久| 精品日韩成人av| 日韩欧美国产wwwww| 欧美精品三级在线观看| 欧美在线影院一区二区| 99re热这里只有精品免费视频| 国产精品1区2区| 麻豆成人久久精品二区三区小说| 亚洲小少妇裸体bbw| 亚洲乱码国产乱码精品精小说| 欧美激情中文字幕一区二区| 亚洲精品一线二线三线无人区| 欧美一区二区三区喷汁尤物| 欧美日韩国产美女| 欧美日本一区二区| 欧美三级日韩在线| 欧美日韩精品福利| 欧美性感一区二区三区| 欧洲视频一区二区| 在线免费av一区| 欧美系列亚洲系列| 欧美精品在线一区二区| 欧美日韩国产高清一区| 欧美肥胖老妇做爰| 6080日韩午夜伦伦午夜伦| 5566中文字幕一区二区电影 | www.亚洲人| 99久久精品费精品国产一区二区| 成人免费毛片app| 成人精品视频一区二区三区| 成人免费高清在线| 91在线观看免费视频| 99热在这里有精品免费| 91小视频在线| 欧日韩精品视频| 宅男噜噜噜66一区二区66| 欧美大片一区二区| 久久久久综合网| 国产精品久久久久久福利一牛影视| 国产精品盗摄一区二区三区| 亚洲免费在线观看视频| 亚洲成人免费电影| 另类小说欧美激情| 粉嫩av一区二区三区粉嫩| 91在线丨porny丨国产| 欧美午夜精品一区二区蜜桃| 91精品欧美综合在线观看最新| 欧美tickling挠脚心丨vk| 欧美激情一区二区| 亚洲第一av色| 国产麻豆欧美日韩一区| 91免费国产在线| 欧美一区二区成人| 国产精品美女久久久久久久网站| 亚洲精品伦理在线| 另类欧美日韩国产在线| 成人高清视频在线| 91精品在线观看入口| 欧美高清在线精品一区| 爽好多水快深点欧美视频| 国产乱色国产精品免费视频| 色一情一乱一乱一91av| 精品国一区二区三区| 伊人一区二区三区| 国产馆精品极品| 欧美日韩成人在线一区| 欧美国产一区二区在线观看| 天天操天天干天天综合网| 国产精品1区2区| 在线播放中文字幕一区| 国产精品盗摄一区二区三区| 欧美aa在线视频| 99国产精品国产精品久久| 日韩视频免费直播| 亚洲精品国产a| 国产传媒一区在线| 日韩亚洲欧美中文三级| 有坂深雪av一区二区精品| 国产91精品在线观看| 正在播放一区二区| 亚洲女人****多毛耸耸8| 国产精品一区二区三区乱码| 欧美精品aⅴ在线视频| 亚洲美女在线国产| 大桥未久av一区二区三区中文| 91精品国产免费久久综合| 亚洲伦理在线精品| 成人av电影免费在线播放| 精品福利视频一区二区三区| 亚洲福中文字幕伊人影院| 97se亚洲国产综合自在线| 国产肉丝袜一区二区| 看电视剧不卡顿的网站| 欧美年轻男男videosbes| 亚洲精品国产成人久久av盗摄| 国产高清无密码一区二区三区| 日韩三级视频在线看| 日韩激情视频在线观看| 欧美日韩美少妇| 亚洲与欧洲av电影| 欧美三日本三级三级在线播放| 亚洲三级免费电影| 一本一本久久a久久精品综合麻豆| 国产日产欧产精品推荐色 | 亚洲成人在线网站| 在线看一区二区| 一区二区三区毛片| 欧美性大战久久| 午夜视频一区在线观看| 欧美日本乱大交xxxxx| 亚洲成人av一区| 欧美美女一区二区三区| 午夜欧美在线一二页| 欧美人体做爰大胆视频| 五月激情丁香一区二区三区| 欧美精品丝袜久久久中文字幕| 无码av免费一区二区三区试看| 欧美精品 日韩| 男女性色大片免费观看一区二区 | 国产91清纯白嫩初高中在线观看 | 中文字幕一区二区三区四区 | 欧美成人高清电影在线| 激情av综合网| 国产亚洲精久久久久久| a美女胸又www黄视频久久| 亚洲麻豆国产自偷在线| 欧美日韩大陆一区二区| 麻豆视频观看网址久久| 久久久欧美精品sm网站| 不卡在线视频中文字幕| 亚洲综合色噜噜狠狠| 在线不卡一区二区| 国产精品综合二区| 亚洲天堂网中文字| 777xxx欧美| 国产成人综合网| 亚洲精品午夜久久久| 日韩一级视频免费观看在线| 国产精华液一区二区三区| 亚洲精品美腿丝袜| 欧美成人伊人久久综合网|