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

📄 atmel_spi.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
字号:
/* * Copyright (C) 2007 Atmel Corporation * * See file CREDITS for list of people who contributed to this * project. * * 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <spi.h>#include <malloc.h>#include <asm/io.h>#include <asm/arch/clk.h>#include <asm/arch/memory-map.h>#include "atmel_spi.h"void spi_init(){}struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,			unsigned int max_hz, unsigned int mode){	struct atmel_spi_slave	*as;	unsigned int		scbr;	u32			csrx;	void			*regs;	if (cs > 3 || !spi_cs_is_valid(bus, cs))		return NULL;	switch (bus) {	case 0:		regs = (void *)SPI0_BASE;		break;#ifdef SPI1_BASE	case 1:		regs = (void *)SPI1_BASE;		break;#endif#ifdef SPI2_BASE	case 2:		regs = (void *)SPI2_BASE;		break;#endif#ifdef SPI3_BASE	case 3:		regs = (void *)SPI3_BASE;		break;#endif	default:		return NULL;	}	scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz;	if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)		/* Too low max SCK rate */		return NULL;	if (scbr < 1)		scbr = 1;	csrx = ATMEL_SPI_CSRx_SCBR(scbr);	csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);	if (!(mode & SPI_CPHA))		csrx |= ATMEL_SPI_CSRx_NCPHA;	if (mode & SPI_CPOL)		csrx |= ATMEL_SPI_CSRx_CPOL;	as = malloc(sizeof(struct atmel_spi_slave));	if (!as)		return NULL;	as->slave.bus = bus;	as->slave.cs = cs;	as->regs = regs;	as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS			| ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf);	spi_writel(as, CSR(cs), csrx);	return &as->slave;}void spi_free_slave(struct spi_slave *slave){	struct atmel_spi_slave *as = to_atmel_spi(slave);	free(as);}int spi_claim_bus(struct spi_slave *slave){	struct atmel_spi_slave *as = to_atmel_spi(slave);	/* Enable the SPI hardware */	spi_writel(as, CR, ATMEL_SPI_CR_SPIEN);	/*	 * Select the slave. This should set SCK to the correct	 * initial state, etc.	 */	spi_writel(as, MR, as->mr);	return 0;}void spi_release_bus(struct spi_slave *slave){	struct atmel_spi_slave *as = to_atmel_spi(slave);	/* Disable the SPI hardware */	spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS);}int spi_xfer(struct spi_slave *slave, unsigned int bitlen,		const void *dout, void *din, unsigned long flags){	struct atmel_spi_slave *as = to_atmel_spi(slave);	unsigned int	len_tx;	unsigned int	len_rx;	unsigned int	len;	int		ret;	u32		status;	const u8	*txp = dout;	u8		*rxp = din;	u8		value;	ret = 0;	if (bitlen == 0)		/* Finish any previously submitted transfers */		goto out;	/*	 * TODO: The controller can do non-multiple-of-8 bit	 * transfers, but this driver currently doesn't support it.	 *	 * It's also not clear how such transfers are supposed to be	 * represented as a stream of bytes...this is a limitation of	 * the current SPI interface.	 */	if (bitlen % 8) {		/* Errors always terminate an ongoing transfer */		flags |= SPI_XFER_END;		goto out;	}	len = bitlen / 8;	/*	 * The controller can do automatic CS control, but it is	 * somewhat quirky, and it doesn't really buy us much anyway	 * in the context of U-Boot.	 */	if (flags & SPI_XFER_BEGIN)		spi_cs_activate(slave);	for (len_tx = 0, len_rx = 0; len_rx < len; ) {		status = spi_readl(as, SR);		if (status & ATMEL_SPI_SR_OVRES)			return -1;		if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) {			if (txp)				value = *txp++;			else				value = 0;			spi_writel(as, TDR, value);			len_tx++;		}		if (status & ATMEL_SPI_SR_RDRF) {			value = spi_readl(as, RDR);			if (rxp)				*rxp++ = value;			len_rx++;		}	}out:	if (flags & SPI_XFER_END) {		/*		 * Wait until the transfer is completely done before		 * we deactivate CS.		 */		do {			status = spi_readl(as, SR);		} while (!(status & ATMEL_SPI_SR_TXEMPTY));		spi_cs_deactivate(slave);	}	return 0;}

⌨️ 快捷键说明

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