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

📄 mxcspi.c

📁 QNX ADS BSP code for i.MX27 chips
💻 C
字号:
/* * $QNXLicenseC:  * Copyright 2007, QNX Software Systems.   *   * Licensed under the Apache License, Version 2.0 (the "License"). You   * may not reproduce, modify or distribute this software except in   * compliance with the License. You may obtain a copy of the License   * at: http://www.apache.org/licenses/LICENSE-2.0   *   * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" basis,   * WITHOUT WARRANTIES OF ANY KIND, either express or implied.  *  * This file may contain contributions from others, either as   * contributors under the License or as licensors under other terms.    * Please review this entire file for other proprietary rights or license   * notices, as well as the QNX Development Suite License Guide at   * http://licensing.qnx.com/license-guide/ for other information.  * $ */#include "mxcspi.h"static char *mx21_opts[] = {	"base",			/* Base address for this CSPI controller */	"irq",			/* IRQ for this CSPI intereface */	"clock",		/* CSPI clock */	"period",		/* CSPI sample period clock */	NULL};spi_funcs_t spi_drv_entry = {	sizeof(spi_funcs_t),	mx21_init,		/* init() */	mx21_dinit,		/* fini() */	mx21_drvinfo,	/* drvinfo() */	mx21_devinfo,	/* devinfo() */	mx21_setcfg,	/* setcfg() */	mx21_xfer,		/* xfer() */	NULL			/* dma_xfer() */};/* * Note: * The devices listed are just examples, users should change * this according to their own hardware spec. */static spi_devinfo_t devlist[4] = {	{		0x00,				// Device ID, for SS0		"CSPI-DEV0",		// Description		{ 			16 | SPI_MODE_BODER_MSB,		// data length 16bit, MSB			5000000			// Clock rate 5M		},	},	{		0x01,				// Device ID, for SS1		"CSPI-DEV1",		// Description		{ 			16 | SPI_MODE_BODER_MSB,		// data length 16bit, MSB			5000000			// Clock rate 5M		},	},	{		0x02,				// Device ID, for SS2		"CSPI-DEV2",		// Description		{ 			16 | SPI_MODE_BODER_MSB,		// data length 16bit, MSB			5000000			// Clock rate 5M		},	},};static uint32_t devctrl[3];static int mx21_options(mx21_cspi_t *dev, char *optstring){	int		opt, rc = 0, err = EOK;	char	*options, *freeptr, *c, *value;	if (optstring == NULL)		return 0;	freeptr = options = strdup(optstring);	while (options && *options != '\0') {		c = options;		if ((opt = getsubopt(&options, mx21_opts, &value)) == -1)			goto error;		switch (opt) {			case 0:				dev->pbase = strtoul(value, 0, 0); 				continue;			case 1:				dev->irq   = strtoul(value, 0, 0);				continue;			case 2:				dev->clock = strtoul(value, 0, 0);				continue;			case 3:				if (strncmp(value, "32K=", 4) == 0) {					dev->period = 0x8000;					value += 4;				}				dev->period |= strtoul(value, 0, 0);				continue;		}error:		fprintf(stderr, "spi-mx21: unknown option %s", c);		err = EINVAL;		rc = -1;	}	free(freeptr);	return rc;}void *mx21_init(void *hdl, char *options){	mx21_cspi_t	*dev;	uintptr_t	base;	int			i;	dev = calloc(1, sizeof(mx21_cspi_t));	if (dev == NULL)		return NULL;	dev->pbase = 0x1000F000;//MX21_CSPI1_BASE;	dev->irq   = 15;	//16;	dev->clock = 33250000;			/* 33.25 MHz CSPI clock */	if (mx21_options(dev, options))		goto fail0;	/*	 * Map in SPI and EDMA register	 */	if ((base = mmap_device_io(0x20, dev->pbase)) == (uintptr_t)MAP_FAILED)		goto fail0;	dev->vbase = base;	/*	 * Perform a software reset	 */	out32(base + MX21_CSPI_RESETREG, 0x01);	delay(1);	out32(base + MX21_CSPI_PERIODREG, 0x00000000);	/* FIXME commandline option ? */	/*	 * Calculate all device configuration here	 */	for (i = 0; i < 3; i++)		devctrl[i] = mx21_cfg(dev, &devlist[i].cfg);	/*	 * Attach SPI interrupt	 */	if (mx21_attach_intr(dev))		goto fail1;	dev->spi.hdl = hdl;   	return dev;fail1:	munmap_device_io(dev->vbase, 0x20);fail0:	free(dev);	return NULL;}void mx21_dinit(void *hdl){	mx21_cspi_t	*dev = hdl;	/*	 * unmap the register, detach the interrupt	 */	InterruptDetach(dev->iid);	ConnectDetach(dev->coid);	ChannelDestroy(dev->chid);	/*	 * Disable SPI	 */	out32(dev->vbase + MX21_CSPI_RESETREG, 0x01);	munmap_device_io(dev->vbase, 0x20);	free(hdl);}int mx21_drvinfo(void *hdl, spi_drvinfo_t *info){	info->version = (SPI_VERSION_MAJOR << SPI_VERMAJOR_SHIFT) | (SPI_VERSION_MINOR << SPI_VERMINOR_SHIFT) | (SPI_REVISION << SPI_VERREV_SHIFT);	strcpy(info->name, "MX21 CSPI");	info->feature = 0;	return (EOK);}int mx21_setcfg(void *hdl, uint16_t device, spi_cfg_t *cfg){	uint32_t	control;	if (device > 2)		return (EINVAL);	memcpy(&devlist[device].cfg, cfg, sizeof(spi_cfg_t));	control = mx21_cfg(hdl, &devlist[device].cfg);	if (control == 0)		return (EINVAL);	devctrl[device] = control;	return (EOK);}int mx21_devinfo(void *hdl, uint32_t device, spi_devinfo_t *info){	int		dev = device & SPI_DEV_ID_MASK;	if (!(device & SPI_DEV_DEFAULT)) {		if (dev != SPI_DEV_ID_NONE)			dev++;		else			dev = 0;	}	if (dev > 2)		return (EINVAL);	memcpy(info, &devlist[dev], sizeof(spi_devinfo_t));	return (EOK);}void *mx21_xfer(void *hdl, uint32_t device, uint8_t *buf, int *len){	mx21_cspi_t	*dev = hdl;	uintptr_t	base = dev->vbase;	uint32_t	ctrl, i, id;	id = device & SPI_DEV_ID_MASK;	if (id > 2) {		*len = -1;		return buf;	}	dev->xlen = *len;	dev->rlen = 0;	dev->pbuf = buf;	dev->dlen = ((devlist[id].cfg.mode & 0x1F) + 7) >> 3;	dev->dtime = dev->dlen * 8 * 1000 * 1000 / devlist[id].cfg.clock_rate;	ctrl = devctrl[id] | (id << 19);	out32(base + MX21_CSPI_CONREG, ctrl | (1 << 11));				/* Flush FIFO */	out32(base + MX21_CSPI_CONREG, ctrl | (1 << 10) | (1 << 11));	/* Enable SPI */	for (dev->tlen = 0, i = 0; i < 8; i++) {		if (dev->tlen >= dev->xlen)			break;		switch (dev->dlen) {			case 1:				out32(base + MX21_CSPI_TXDATA, buf[dev->tlen]);				dev->tlen++;				break;			case 2:				out32(base + MX21_CSPI_TXDATA, *(uint16_t *)(&buf[dev->tlen]));				dev->tlen += 2;				break;			case 3:			case 4:				out32(base + MX21_CSPI_TXDATA, *(uint32_t *)(&buf[dev->tlen]));				dev->tlen += 4;				break;		}	}	/*	 * Enable interrupt	 */	if (i >= 4)		out32(base + MX21_CSPI_INTREG, 1 << 14);	/* Enable RxFIFO half interrupt */	else		out32(base + MX21_CSPI_INTREG, 1 << 12);	/* Enable RxFIFO data ready interrupt */	out32(base + MX21_CSPI_CONREG, ctrl | (1 << 9) | (1 << 10) | (1 << 11));	/* Start exchange */	/*	 * Wait for exchange to finish with timeout	 */	if (mx21_wait(dev, dev->xlen * 10))		dev->rlen = -1;	/*	 * Disable CSPI	 */	out32(base + MX21_CSPI_CONREG, 1 << 11);	*len = dev->rlen;	return buf;}

⌨️ 快捷键说明

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