⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 2 页
字号:
diff -Nbur linux26-cvs/arch/mips/au1000/common/clocks.c linux26-cvs.SPI/arch/mips/au1000/common/clocks.c--- linux26.cvs/arch/mips/au1000/common/clocks.c	2005-08-03 11:21:28.000000000 -0500+++ linux26.amd/arch/mips/au1000/common/clocks.c	2005-08-03 10:54:38.000000000 -0500@@ -46,7 +46,7 @@ { 	return au1x00_clock; }-+EXPORT_SYMBOL(get_au1x00_speed);   /*diff -Nbur linux26-cvs/drivers/char/au1xxx_psc_spi.c linux26-cvs.SPI/drivers/char/au1xxx_psc_spi.c--- linux26.cvs/drivers/char/au1xxx_psc_spi.c	1969-12-31 18:00:00.000000000 -0600+++ linux26.amd/drivers/char/au1xxx_psc_spi.c	2005-08-03 10:55:08.000000000 -0500@@ -0,0 +1,552 @@+/*+ *  Driver for Alchemy Au1550 SPI on the PSC.+ *+ * Copyright 2004 Embedded Edge, LLC.+ *	dan@embeddededge.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.+ *+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN+ *  NO  EVENT  SHALL   THE AUTHOR  BE	LIABLE FOR ANY   DIRECT, INDIRECT,+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ *+ *  You should have received a copy of the  GNU General Public License along+ *  with this program; if not, write  to the Free Software Foundation, Inc.,+ *  675 Mass Ave, Cambridge, MA 02139, USA.+ */++#include <linux/module.h>+#include <linux/config.h>+#include <linux/types.h>+#include <linux/kernel.h>+#include <linux/miscdevice.h>+#include <linux/init.h>+#include <linux/fs.h>+#include <asm/uaccess.h>+#include <asm/io.h>+#include <asm/mach-au1x00/au1000.h>+#include <asm/mach-au1x00/au1550_spi.h>+#include <asm/mach-au1x00/au1xxx_psc.h>++#ifdef CONFIG_MIPS_PB1550+#include <asm/mach-pb1x00/pb1550.h>+#endif++#ifdef CONFIG_MIPS_DB1550+#include <asm/mach-db1x00/db1x00.h>+#endif++#ifdef CONFIG_MIPS_PB1200+#include <asm/mach-pb1x00/pb1200.h>+#endif++#ifdef CONFIG_MIPS_DB1200+#include <asm/mach-db1x00/db1200.h>+#endif++#ifdef CONFIG_PM+#include <asm/mach-au1x00/au1xxx_pm.h>+#endif+++/* This is just a simple programmed I/O SPI interface on the PSC of the 1550.+ * We support open, close, write, and ioctl.  The SPI is a full duplex+ * interface, you can't read without writing.  So, the write system call+ * copies the bytes out to the SPI, and whatever is returned is placed+ * in the same buffer.  Kinda weird, maybe we'll change it, but for now+ * it works OK.+ * I didn't implement any DMA yet, and it's a debate about the necessity.+ * The SPI clocks are usually quite fast, so data is sent/received as+ * quickly as you can stuff the FIFO.  The overhead of DMA and interrupts+ * are usually far greater than the data transfer itself.  If, however,+ * we find applications that move large amounts of data, we may choose+ * use the overhead of buffering and DMA to do the work.+ */++/* The maximum clock rate specified in the manual is 2mHz.+*/+#define MAX_BAUD_RATE	(2 * 1000000)+#define PSC_INTCLK_RATE (32 * 1000000)++static	int	inuse;++/* We have to know what the user requested for the data length+ * so we know how to stuff the fifo.  The FIFO is 32 bits wide,+ * and we have to load it with the bits to go in a single transfer.+ */+static	uint	spi_datalen;+ +#ifdef CONFIG_PM +int au1200spi_pm_callback(au1xxx_power_dev_t *dev, +		au1xxx_request_t request, void *data);+au1xxx_power_dev_t *SPI_pm_dev;+#endif+++static int+au1550spi_master_done( int ms )+{+	int timeout=ms;+	volatile psc_spi_t *sp;++	sp = (volatile psc_spi_t *)SPI_PSC_BASE;++	/* Loop until MD is set or timeout has expired */+	while(!(sp->psc_spievent & PSC_SPIEVNT_MD) &&  timeout--) udelay(1000);++	if ( !timeout )+		return 0;+	else+		sp->psc_spievent |= PSC_SPIEVNT_MD;++	return 1;+}++static int+au1550spi_open(struct inode *inode, struct file *file)+{+	if (inuse)+		return -EBUSY;++	inuse = 1;++	+	return 0;+}++static ssize_t+au1550spi_write(struct file *fp, const char *bp, size_t count, loff_t *ppos)+{+	int	bytelen, i;+	size_t	rcount, retval;+	unsigned char	sb, *rp, *wp;+	uint	fifoword, pcr, stat;+	volatile psc_spi_t *sp;++	/* Get the number of bytes per transfer.+	*/+	bytelen = ((spi_datalen - 1) / 8) + 1;++	/* User needs to send us multiple of this count.+	*/+	if ((count % bytelen) != 0)+		return -EINVAL;++	rp = wp = (unsigned char *)bp;+	retval = rcount = count;++	/* Reset the FIFO.+	*/+	sp = (volatile psc_spi_t *)SPI_PSC_BASE;+	sp->psc_spipcr = (PSC_SPIPCR_RC | PSC_SPIPCR_TC);+	au_sync();+	do {+		pcr = sp->psc_spipcr;+		au_sync();+	} while (pcr != 0);++	/* Prime the transmit FIFO.+	*/+	while (count > 0) {+		fifoword = 0;+		for (i=0; i<bytelen; i++) {+			fifoword <<= 8;+			if (get_user(sb, wp) < 0)+				return -EFAULT;+			fifoword |= sb;+			wp++;+		}+		count -= bytelen;+		if (count <= 0)+			fifoword |= PSC_SPITXRX_LC;+		sp->psc_spitxrx = fifoword;+		au_sync();+		stat = sp->psc_spistat;+		au_sync();+		if (stat & PSC_SPISTAT_TF)+			break;+	}++	/* Start the transfer.+	*/+	sp->psc_spipcr = PSC_SPIPCR_MS;+	au_sync();++	/* Now, just keep the transmit fifo full and empty the receive.+	*/+	while (count > 0) {+		stat = sp->psc_spistat;+		au_sync();+		while ((stat & PSC_SPISTAT_RE) == 0) {+			fifoword = sp->psc_spitxrx;+			au_sync();+			for (i=0; i<bytelen; i++) {+				sb = fifoword & 0xff;+				if (put_user(sb, rp) < 0)+					return -EFAULT;+				fifoword >>= 8;+				rp++;+			}+			rcount -= bytelen;+			stat = sp->psc_spistat;+			au_sync();+		}+		if ((stat & PSC_SPISTAT_TF) == 0) {+			fifoword = 0;+			for (i=0; i<bytelen; i++) {+				fifoword <<= 8;+				if (get_user(sb, wp) < 0)+					return -EFAULT;+				fifoword |= sb;+				wp++;+			}+			count -= bytelen;+			if (count <= 0)+				fifoword |= PSC_SPITXRX_LC;+			sp->psc_spitxrx = fifoword;+			au_sync();+		}+	}++	/* All of the bytes for transmit have been written.  Hang+	 * out waiting for any residual bytes that are yet to be+	 * read from the fifo.+	 */+	while (rcount > 0) {+		stat = sp->psc_spistat;+		au_sync();+		if ((stat & PSC_SPISTAT_RE) == 0) {+			fifoword = sp->psc_spitxrx;+			au_sync();+			for (i=0; i<bytelen; i++) {+				sb = fifoword & 0xff;+				if (put_user(sb, rp) < 0)+					return -EFAULT;+				fifoword >>= 8;+				rp++;+			}+			rcount -= bytelen;+		}+	}++	/* Wait for MasterDone event. 30ms timeout */+	if (!au1550spi_master_done(30) ) retval = -EFAULT;+	return retval;+}++static int+au1550spi_release(struct inode *inode, struct file *file)+{+	+	inuse = 0;++	return 0;+}++/* Set the baud rate closest to the request, then return the actual+ * value we are using.+ */+static uint+set_baud_rate(uint baud)+{+	uint	rate, tmpclk, brg, ctl, stat;+	volatile psc_spi_t *sp;++	/* For starters, the input clock is divided by two.+	*/+	tmpclk = PSC_INTCLK_RATE/2;++	rate = tmpclk / baud;++	/* The dividers work as follows:+	 *	baud = tmpclk / (2 * (brg + 1))+	 */+	 brg = (rate/2) - 1;++	 /* Test BRG to ensure it will fit into the 6 bits allocated.+	 */++	 /* Make sure the device is disabled while we make the change.+	 */+	sp = (volatile psc_spi_t *)SPI_PSC_BASE;+	ctl = sp->psc_spicfg;+	au_sync();+	sp->psc_spicfg = ctl & ~PSC_SPICFG_DE_ENABLE;+	au_sync();+	ctl = PSC_SPICFG_CLR_BAUD(ctl);+	ctl |= PSC_SPICFG_SET_BAUD(brg);+	sp->psc_spicfg = ctl;+	au_sync();++	/* If the device was running prior to getting here, wait for+	 * it to restart.+	 */+	if (ctl & PSC_SPICFG_DE_ENABLE) {+		do {+			stat = sp->psc_spistat;+			au_sync();+		} while ((stat & PSC_SPISTAT_DR) == 0);+	}++	/* Return the actual value.+	*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -