blob: 4bf7e3b772a92c04ec25d494b04fa23a5363b60d [file] [log] [blame]
/** \file vp_hal.c
* vp_hal.c
*
* This file contains the platform dependent code for the Hardware Abstraction
* Layer (HAL). This implementation is for embedded Linux. This HAL
* implementation assumes a Linux kernel mode driver and also an application
* level interface to those kernel drivers.
*
* Copyright (c) 2005, Legerity Inc.
* All rights reserved
*
* This software is the property of Legerity , Inc. Please refer to the
* Non Disclosure Agreement (NDA) that you have signed for more information
* on legal obligations in using, modifying or distributing this file.
*/
#include "vp_hal.h"
#include "../../../legerity.h"
extern struct legerity_data *legerity;
extern int spi_write(struct spi_device *spi, const void *buf, size_t len);
extern int spi_read(struct spi_device *spi, void *buf, size_t len);
/**
* VpHalHbiInit(): Configures the HBI bus and glue logic (if any)
*
* This function performs any tasks necessary to prepare the system for
* communicating through the HBI, including writing the HBI configuration
* register. The HBI read and write functions should work after HbiHalInit()
* is successfully executed. HbiHalInit() should be well-behaved even if called
* more than once between system resets. HbiHalInit() is called from
* VpBootLoad() since VpBootLoad() is normally the first VoicePath function
* that the host application will call.
*
* This function is called by VpBootLoad() before sending the DVP firmware
* image through the HBI.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
*
* Returns:
* This function returns FALSE if some error occurred during HBI initialization
* or TRUE otherwise.
*/
bool VpHalHbiInit(
VpDeviceIdType deviceId)
{
/*
* Note that Setting up the basic device should be handled by the
* some board bring up function. That function should setup the
* CPLD based on the line module that is plugged in. Those functions
* would configure the CPLD so that basic communication to the part
* can happen between the HAL and the line module.
*/
/* Write the HBI configuration register. */
return 0;
} /* VpHalHbiInit() */
/**
* VpHalHbiCmd(): Sends a command word over the HBI, with no data words.
*
* Accepts a uint16 HBI command which is little-endian or big-endian,
* depending on the host architecture. Command words on the HBI bus are always
* big-endian. This function is responsible for byte-swapping if required. This
* implementation for Linux does not need any byte swapping.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
* uint16 cmd: the command word to send
*
* Returns:
* TRUE on success, FALSE on failure
*/
bool VpHalHbiCmd(
VpDeviceIdType deviceId,
uint16 cmd)
{
return 0;
} /* VpHalHbiCmdWr() */
/**
* VpHalHbiWrite(): Sends a command word and up to 256 data words over the HBI.
*
* Accepts a uint16 HBI command which is little-endian or big-endian, depending
* on the host architecture. Command words on the HBI bus are always big-
* endian. This function is responsible for byte-swapping the command word, if
* required. Note that this Linux implementation does not need byte swapping.
*
* Accepts an array of uint16 data words. No byte-swapping is necessary on
* data words in this function. Instead, the HBI bus can be configured in
* VpHalHbiInit() to match the endianness of the host platform.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
* uint16 cmd: the command word to send
* uint8 numwords: the number of data words to send, minus 1
* uint16p data: the data itself; use data = (uint16p)0 to send
* zeroes for all data words
*
* Returns:
* TRUE on success, FALSE on failure
*/
bool VpHalHbiWrite(
VpDeviceIdType deviceId,
uint16 cmd,
uint8 numwords,
uint16p data)
{
return 0;
} /* VpHalHbiWrite() */
/**
* VpHalHbiRead(): Sends a command, and receives up to 256 data words over the
* HBI.
*
* Accepts a uint16 HBI command which is little-endian or big-endian, depending
* on the host architecture. Command words on the HBI bus are always big-
* endian. This function is responsible for byte-swapping the command word, if
* required.
*
* Retrieves an array of uint16 data words. No byte-swapping is necessary on
* data words in this function. Instead, the HBI bus can be configured in
* VpHalHbiInit() to match the endianness of the host platform.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
* uint8 numwords: the number of words to receive, minus 1
* uint16p data: where to put them
*
* Returns:
* TRUE on success, FALSE on failure
*/
bool VpHalHbiRead(
VpDeviceIdType deviceId,
uint16 cmd,
uint8 numwords,
uint16p data)
{
return 0;
} /* VpHalHbiRead() */
/**
* VpHalHbiWrite8(): Sends a command word and up to 256 data words over the HBI.
*
* Accepts a uint16 HBI command which is little-endian or big-endian, depending
* on the host architecture. Command words on the HBI bus are always big-
* endian. This function is responsible for byte-swapping the command word, if
* required. Note that this Linux implementation does not need byte swapping.
*
* Accepts an array of uint8 data words. No byte-swapping is necessary on
* data words in this function. Instead, the HBI bus can be configured in
* VpHalHbiInit() to match the endianness of the host platform.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
* uint16 cmd: the command word to send
* uint8 numwords: the number of data words to send, minus 1
* uint8p data: the data itself; use data = (uint8p)0 to send
* zeroes for all data words
*
* Returns:
* TRUE on success, FALSE on failure
*/
bool VpHalHbiWrite8(
VpDeviceIdType deviceId,
uint16 cmd,
uint8 numwords,
uint8p data)
{
return 0;
} /* VpHalHbiWrite8() */
/**
* VpHalHbiRead8(): Sends a command, and receives up to 256 data words over the
* HBI.
*
* Accepts a uint16 HBI command which is little-endian or big-endian, depending
* on the host architecture. Command words on the HBI bus are always big-
* endian. This function is responsible for byte-swapping the command word, if
* required.
*
* Retrieves an array of uint8 data bytes. No byte-swapping is necessary on
* data words in this function. Instead, the HBI bus can be configured in
* VpHalHbiInit() to match the endianness of the host platform.
*
* Params:
* uint8 deviceId: Device Id (chip select ID)
* uint8 numwords: the number of words to receive, minus 1
* uint8p data: where to put them
*
* Returns:
* TRUE on success, FALSE on failure
*/
bool VpHalHbiRead8(
VpDeviceIdType deviceId,
uint16 cmd,
uint8 numwords,
uint8p data)
{
return 0;
} /* VpHalHbiRead8() */
/**
* VpHalHbiBootWr():
*
* This is used by the VpBootLoad() function to send the boot stream to the
* DVP. This function is separate from VpHalHbiWrite(), for the following
* reasons:
*
* 1. This function does not accept a command word; only data words.
* 2. This function accepts uint8 data, instead of uint16 data. Be careful
* not to assume that this data is word-aligned in memory.
* 3. The HBI must be configured for big-endian data words while the boot
* stream is being transmitted, regardless of the endianness of the host
* platform. This is because the boot image is an opaque stream of HBI
* command words and data words. Therefore, commands and data cannot be
* distinguished for separate treatment by this function. Since HBI
* command words are always big-endian, data words have to be big-endian,
* too. The boot stream is stored big-endian in memory, even on little-
* endian hosts.
* If VpHalHbiInit() configures the HBI for little-endian data words,
* then this function must temporarily change the configuration by calling
* VpHalHbiCmd(HBI_CMD_CONFIGURE(...)), and change it back before
* returning. In such a case, this function will need to swap each pair
* of bytes in the boot stream before sending.
* Another possibility (as in the case of our test platform) is a
* little-endian host architecture, with the HBI bus configured for big-
* endian data words. In this case, byte-swapping has to be done in
* VpHalHbiWrite() or in the glue logic between the host and the DVP.
* In these setups, VpHalHbiBootWr() does not need to reconfigure the
* HBI.
* 4. This function takes a VpImagePtrType pointer to char data, which is a
* platform-dependent type defined in vp_hal.h. In our system, a "_huge"
* pointer is needed for this function, since the boot stream is larger
* than 64 kB.
*
* Params
* uint8 deviceId: Device Id (chip select ID)
* 'length' specifies the number of 16-bit words to write to the DVP.
* 'pBuf' points into the boot stream.
*
* Returns
* HbiHalBootWr() returns TRUE on success, FALSE on failure.
*
* Notes
* THIS FUNCTION IS NOT REENTRANT!
*/
bool VpHalHbiBootWr(
VpDeviceIdType deviceId,
uint8 numwords,
VpImagePtrType data)
{
return 0;
} /* VpHalHbiBootWr() */
/*****************************************************************************
* HAL functions for CSLAC devices. Not necessary for VCP and VPP
****************************************************************************/
/**
* VpMpiCmd()
* This function executes a Device MPI command through the MPI port. It
* executes both read and write commands. The read or write operation is
* determined by the "cmd" argument (odd = read, even = write). The caller must
* ensure that the data array is large enough to hold the data being collected.
* Because this command used hardware resources, this procedure is not
* re-entrant.
*
* Preconditions:
* The device must be initialized.
*
* Postconditions:
* The data pointed to by dataPtr, using the command "cmd", with length
* "cmdLen" has been sent to the MPI bus via the chip select associated with
* deviceId.
*/
void
VpMpiCmd(
VpDeviceIdType deviceId, /**< Chip select, connector and 3 or 4 wire
* interface for command
*/
uint8 ecVal, /**< Value to write to the EC register */
uint8 cmd, /**< Command number */
uint8 cmdLen, /**< Number of bytes used by command (cmd) */
uint8 *dataPtr) /**< Pointer to the data location */
{
int i;
char buf[1];
struct legerity_slic_desc *slic = legerity->slic_list;
VpSysEnterCritical(deviceId, VP_MPI_CRITICAL_SEC);
/*
* write the ec register only if the cmd argument is
* not the read ec register command
*/
if (cmd != 0x4B) {
buf[0] = 0x4A;
spi_write((struct spi_device *)slic->spi_client->type_data, &buf, 1);
buf[0] = ecVal;
spi_write((struct spi_device *)slic->spi_client->type_data, &buf, 1);
}
buf[0] = cmd;
spi_write((struct spi_device *)slic->spi_client->type_data, &buf, 1);
if (cmd & 0x01) {
/*
* ZSI devices have a special read requirement that require
* the host to read cmdLen+1 data bytes and to discard the
* first byte. Escentially, we are priming the ZSI RTL
* block pump. We know that the ZSI RTL uses chip select
* number 3 i.e. deviceid 3.
* One other requirement of the ZSI RTL is that the data on
* the MOSI SPI signal be an unrecognized or benign command.
* Therefor we should really be using a spi_write_and_readb()
* of somekind. I need Mindspeed to add the function call
* necessary to make that happen here - Microsemi -S.H.
*/
if (deviceId == 3) {
uint8 discardByte;
spi_read((struct spi_device *)slic->spi_client->type_data, &discardByte, 1);
}
for (i = 0; i < cmdLen; i++) {
spi_read((struct spi_device *)slic->spi_client->type_data, &dataPtr[i], 1);
}
} else {
for (i = 0; i < cmdLen; i++) {
buf[0] = dataPtr[i];
spi_write((struct spi_device *)slic->spi_client->type_data, &buf, 1);
}
}
#ifdef LEGERITY_DEBUG_HAL
PRINT (KERN_INFO "Device(%d): ", deviceId);
PRINT ("SELECT(%02x, %02x) - ", 0x4a, ecVal);
if (cmd & 0x01) {
PRINT ("READ (");
} else {
PRINT ("WRITE(");
}
PRINT("cmd=%02x", cmd);
if (cmdLen > 0) {
int i;
PRINT(", dataPtr=");
for (i = 0; i < cmdLen; i++) {
PRINT("%02x", dataPtr[i]);
if (i < (cmdLen - 1)) PRINT(",");
}
}
PRINT(")\n");
#endif
VpSysExitCritical(deviceId, VP_MPI_CRITICAL_SEC);
return;
} /* End VpMpiCmd */
/**
* VpMpiReset()
* This function executes a 16-bit MPI command with the CS low to cause a
* reset of the device.
*
* Preconditions:
* None.
*
* Postconditions:
* CS for the device specified by deviceId on the MPI bus is high (after being
* held low for 16 clock cycles).
*/
void
VpMpiReset(
VpDeviceIdType deviceId,
VpDeviceType deviceType)
{
char buf[2] = { 0, 0 };
VpSysEnterCritical(deviceId, VP_MPI_CRITICAL_SEC);
spi_write((struct spi_device *)legerity->slic_list->spi_client->type_data, &buf, 2);
#ifdef LEGERITY_DEBUG
PRINT (KERN_INFO "Device(%d): RESET)\n", deviceId);
#endif
VpSysExitCritical(deviceId, VP_MPI_CRITICAL_SEC);
return;
}