summaryrefslogtreecommitdiffstats
path: root/shared/opensource/spi/bcmSpiRes.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/opensource/spi/bcmSpiRes.c')
-rwxr-xr-xshared/opensource/spi/bcmSpiRes.c660
1 files changed, 660 insertions, 0 deletions
diff --git a/shared/opensource/spi/bcmSpiRes.c b/shared/opensource/spi/bcmSpiRes.c
new file mode 100755
index 0000000..ed16575
--- /dev/null
+++ b/shared/opensource/spi/bcmSpiRes.c
@@ -0,0 +1,660 @@
+/*
+ Copyright 2000-2010 Broadcom Corporation
+
+ Unless you and Broadcom execute a separate written software license
+ agreement governing use of this software, this software is licensed
+ to you under the terms of the GNU General Public License version 2
+ (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+ with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and to
+ copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+ Notwithstanding the above, under no circumstances may you combine this
+ software in any way with any other Broadcom software provided under a
+ license other than the GPL, without Broadcom's express prior written
+ consent.
+*/
+
+#ifdef _CFE_
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "bcm_map.h"
+#define printk printf
+#else
+#include <linux/version.h>
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+#include <linux/semaphore.h>
+#endif
+#include <linux/spi/spi.h>
+#include <linux/autoconf.h>
+
+#include <bcm_map_part.h>
+#endif
+#include "bcmSpiRes.h"
+
+extern int BcmLegSpiRead(unsigned char * msg_buf, int prependcnt, int nbytes, int devId, int freqHz);
+extern int BcmLegSpiWrite(unsigned char * msg_buf, int nbytes, int devId, int freqHz);
+extern int BcmHsSpiRead(unsigned char * msg_buf, int prependcnt, int nbytes, int devId, int freqHz);
+extern int BcmHsSpiWrite(unsigned char * msg_buf, int nbytes, int devId, int freqHz);
+
+#ifndef _CFE_
+#ifdef SPI
+/* the BCM legacy controller supports up to 8 devices */
+static struct spi_board_info bcmLegSpiDevInfo[8] =
+{
+ {
+ .modalias = "bcm_LegSpiDev0",
+ .chip_select = 0,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev1",
+ .chip_select = 1,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev2",
+ .chip_select = 2,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev3",
+ .chip_select = 3,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev4",
+ .chip_select = 4,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev5",
+ .chip_select = 5,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev6",
+ .chip_select = 6,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "bcm_LegSpiDev7",
+ .chip_select = 7,
+ .max_speed_hz = 781000,
+ .bus_num = LEG_SPI_BUS_NUM,
+ .mode = SPI_MODE_3,
+ },
+};
+
+static struct spi_driver bcmLegSpiDevDrv[8] =
+{
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev0",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev1",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev2",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev3",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev4",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev5",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev6",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_LegSpiDev7",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static struct spi_device * bcmLegSpiDevices[8];
+#endif
+
+#ifdef HS_SPI
+/* the BCM HS controller supports up to 8 devices */
+static struct spi_board_info bcmHSSpiDevInfo[8] =
+{
+ {
+ .modalias = "bcm_HSSpiDev0",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 0,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev1",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 1,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev2",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 2,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev3",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 3,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev4",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 4,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev5",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 5,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev6",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 6,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+ {
+ .modalias = "bcm_HSSpiDev7",
+ .controller_data = (void *)SPI_CONTROLLER_STATE_DEFAULT,
+ .chip_select = 7,
+ .max_speed_hz = 781000,
+ .bus_num = HS_SPI_BUS_NUM,
+ .mode = SPI_MODE_DEFAULT,
+ },
+};
+
+static struct spi_driver bcmHSSpiDevDrv[8] =
+{
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev0",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev1",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev2",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev3",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev4",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev5",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev6",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+ {
+ .driver =
+ {
+ .name = "bcm_HSSpiDev7",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static struct spi_device * bcmHSSpiDevices[8];
+#endif
+
+
+int BcmSpiReserveSlave2(int busNum, int slaveId, int maxFreq, int spiMode, int ctrlState)
+{
+ struct spi_master * pSpiMaster;
+ struct spi_driver * pSpiDriver;
+
+ if ( slaveId > 7 )
+ {
+ return SPI_STATUS_ERR;
+ }
+
+ if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL != bcmLegSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "BcmSpiReserveSlave - slaveId %d, already registerd\n", slaveId);
+ return( SPI_STATUS_ERR );
+ }
+
+ bcmLegSpiDevInfo[slaveId].max_speed_hz = maxFreq;
+ bcmLegSpiDevInfo[slaveId].controller_data = (void *)ctrlState;
+ bcmLegSpiDevInfo[slaveId].mode = spiMode;
+
+ pSpiMaster = spi_busnum_to_master( busNum );
+ bcmLegSpiDevices[slaveId] = spi_new_device(pSpiMaster, &bcmLegSpiDevInfo[slaveId]);
+ pSpiDriver = &bcmLegSpiDevDrv[slaveId];
+#endif
+ }
+ else if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL != bcmHSSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "BcmSpiReserveSlave - slaveId %d, already registerd\n", slaveId);
+ return( SPI_STATUS_ERR );
+ }
+
+ bcmHSSpiDevInfo[slaveId].max_speed_hz = maxFreq;
+ bcmHSSpiDevInfo[slaveId].controller_data = (void *)ctrlState;
+ bcmHSSpiDevInfo[slaveId].mode = spiMode;
+
+ pSpiMaster = spi_busnum_to_master( busNum );
+ bcmHSSpiDevices[slaveId] = spi_new_device(pSpiMaster, &bcmHSSpiDevInfo[slaveId]);
+ pSpiDriver = &bcmHSSpiDevDrv[slaveId];
+#endif
+ }
+ else
+ return( SPI_STATUS_ERR );
+
+ /* register the SPI driver */
+ spi_register_driver(pSpiDriver);
+
+ return 0;
+
+}
+EXPORT_SYMBOL(BcmSpiReserveSlave2);
+
+int BcmSpiReserveSlave(int busNum, int slaveId, int maxFreq)
+{
+ return( BcmSpiReserveSlave2(busNum, slaveId, maxFreq, SPI_MODE_DEFAULT, SPI_CONTROLLER_STATE_DEFAULT) );
+}
+EXPORT_SYMBOL(BcmSpiReserveSlave);
+
+int BcmSpiReleaseSlave(int busNum, int slaveId)
+{
+ if ( slaveId > 7 )
+ {
+ return SPI_STATUS_ERR;
+ }
+
+ if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL == bcmLegSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "BcmSpiReleaseSlave - slaveId %d, already released\n", slaveId);
+ return( SPI_STATUS_ERR );
+ }
+
+ bcmLegSpiDevInfo[slaveId].max_speed_hz = 781000;
+ spi_unregister_driver(&bcmLegSpiDevDrv[slaveId]);
+ spi_unregister_device(bcmLegSpiDevices[slaveId]);
+ bcmLegSpiDevices[slaveId] = 0;
+#endif
+ }
+ else if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL == bcmHSSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "BcmSpiReleaseSlave - slaveId %d, already released\n", slaveId);
+ return( SPI_STATUS_ERR );
+ }
+
+ bcmHSSpiDevInfo[slaveId].max_speed_hz = 781000;
+ spi_unregister_driver(&bcmHSSpiDevDrv[slaveId]);
+ spi_unregister_device(bcmHSSpiDevices[slaveId]);
+ bcmHSSpiDevices[slaveId] = 0;
+#endif
+ }
+ else
+ return( SPI_STATUS_ERR );
+
+ return 0;
+
+}
+EXPORT_SYMBOL(BcmSpiReleaseSlave);
+
+
+int BcmSpiSyncTrans(unsigned char *txBuf, unsigned char *rxBuf, int prependcnt, int nbytes, int busNum, int slaveId)
+{
+ struct spi_message msg;
+ struct spi_transfer xfer[2];
+ int status;
+ int maxLength;
+ struct spi_device *pSpiDevice;
+
+ maxLength = BcmSpi_GetMaxRWSize(busNum);
+ if ( (nbytes > maxLength) || (prependcnt > maxLength) )
+ {
+ printk(KERN_ERR "ERROR BcmSpiSyncTrans: invalid length len %d, pre %d, max %d\n", nbytes, prependcnt, maxLength);
+ return SPI_STATUS_ERR;
+ }
+
+ if ( slaveId > 7 )
+ {
+ printk(KERN_ERR "ERROR BcmSpiSyncTrans: invalid slave id %d\n", slaveId);
+ return SPI_STATUS_ERR;
+ }
+
+ if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL == bcmLegSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "ERROR BcmSpiSyncTrans: device not registered\n");
+ return SPI_STATUS_ERR;
+ }
+ pSpiDevice = bcmLegSpiDevices[slaveId];
+#endif
+ }
+ else if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return( SPI_STATUS_ERR );
+#else
+ if ( NULL == bcmHSSpiDevices[slaveId] )
+ {
+ printk(KERN_ERR "ERROR BcmSpiSyncTrans: device not registered\n");
+ return SPI_STATUS_ERR;
+ }
+ pSpiDevice = bcmHSSpiDevices[slaveId];
+#endif
+ }
+ else
+ return( SPI_STATUS_ERR );
+
+ spi_message_init(&msg);
+ memset(xfer, 0, (sizeof xfer));
+
+ if ( prependcnt )
+ {
+ xfer[0].len = prependcnt;
+ xfer[0].speed_hz = pSpiDevice->max_speed_hz;
+ if ( txBuf )
+ {
+ xfer[0].tx_buf = txBuf;
+ }
+ else
+ {
+ xfer[0].tx_buf = rxBuf;
+ }
+ spi_message_add_tail(&xfer[0], &msg);
+ }
+
+ xfer[1].len = nbytes;
+ xfer[1].speed_hz = pSpiDevice->max_speed_hz;
+ xfer[1].rx_buf = rxBuf;
+
+ /* for the controller to use the prepend count correctly the first operation must be a read and the second a write
+ make sure tx is NULL for second transaction */
+ if ( 0 == prependcnt )
+ {
+ xfer[1].tx_buf = txBuf;
+ }
+ spi_message_add_tail(&xfer[1], &msg);
+
+ status = spi_sync(pSpiDevice, &msg);
+ if (status >= 0)
+ {
+ status = SPI_STATUS_OK;
+ }
+ else
+ {
+ status = SPI_STATUS_ERR;
+ }
+
+ return( status );
+
+}
+EXPORT_SYMBOL(BcmSpiSyncTrans);
+#endif
+
+int BcmSpi_SetFlashCtrl( int opCode, int addrBytes, int dummyBytes, int busNum, int devId )
+{
+ if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return SPI_STATUS_ERR;
+#else
+ int clock;
+
+ clock = HS_SPI_PLL_FREQ/HS_SPI_CLOCK_DEF;
+ if (HS_SPI_PLL_FREQ%HS_SPI_CLOCK_DEF)
+ clock++;
+
+ clock = 2048/clock;
+ if (2048%(clock))
+ clock++;
+
+ HS_SPI_PROFILES[0].clk_ctrl = 1<<HS_SPI_ACCUM_RST_ON_LOOP | 0<<HS_SPI_SPI_CLK_2X_SEL | clock<<HS_SPI_FREQ_CTRL_WORD;
+ HS_SPI->hs_spiFlashCtrl = devId<<HS_SPI_FCTRL_SS_NUM | 0<<HS_SPI_FCTRL_PROFILE_NUM | dummyBytes<<HS_SPI_FCTRL_DUMMY_BYTES |
+ addrBytes<<HS_SPI_FCTRL_ADDR_BYTES | opCode<<HS_SPI_FCTRL_READ_OPCODE;
+#endif
+ }
+ else if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return SPI_STATUS_ERR;
+#endif
+ }
+ else
+ return SPI_STATUS_ERR;
+
+ return SPI_STATUS_OK;
+
+}
+
+
+int BcmSpi_GetMaxRWSize( int busNum )
+{
+ int maxRWSize = 0;
+
+ if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifdef HS_SPI
+ maxRWSize = HS_SPI_BUFFER_LEN;
+#endif
+ }
+ else if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifdef SPI
+ maxRWSize = sizeof(SPI->spiMsgData);
+#endif
+ }
+
+ maxRWSize &= ~0x3;
+
+ return(maxRWSize);
+
+}
+
+
+/* The interface bcmSpi_Read and bcmSpi_Write provide direct access to the SPI controller.
+ these interfaces should only be called by CFE and early spi flash code */
+int BcmSpi_Read( unsigned char *msg_buf, int prependcnt, int nbytes, int busNum, int devId, int freqHz )
+{
+ if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return SPI_STATUS_ERR;
+#else
+ return BcmLegSpiRead( msg_buf, prependcnt, nbytes, devId, freqHz );
+#endif
+ }
+ else if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return SPI_STATUS_ERR;
+#else
+ return BcmHsSpiRead( msg_buf, prependcnt, nbytes, devId, freqHz );
+#endif
+ }
+ else
+ {
+ return SPI_STATUS_ERR;
+ }
+
+}
+
+int BcmSpi_Write( unsigned char *msg_buf, int nbytes, int busNum, int devId, int freqHz )
+{
+ if ( LEG_SPI_BUS_NUM == busNum )
+ {
+#ifndef SPI
+ return SPI_STATUS_ERR;
+#else
+ return BcmLegSpiWrite( msg_buf, nbytes, devId, freqHz );
+#endif
+ }
+ else if ( HS_SPI_BUS_NUM == busNum )
+ {
+#ifndef HS_SPI
+ return SPI_STATUS_ERR;
+#else
+ return BcmHsSpiWrite( msg_buf, nbytes, devId, freqHz );
+#endif
+ }
+ else
+ {
+ return SPI_STATUS_ERR;
+ }
+}
+
+#ifndef _CFE_
+EXPORT_SYMBOL(BcmSpi_SetFlashCtrl);
+EXPORT_SYMBOL(BcmSpi_GetMaxRWSize);
+#endif
+