Re: [PATCH v2] Add smsspi driver to support Siano SPI connected device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em 03-11-2011 09:33, Doron Cohen escreveu:
> 
>>From 80d279ec11492ca6729f1421983f52b8e7144cd4 Mon Sep 17 00:00:00 2001
> From: Doron Cohen <doronc@xxxxxxxxxxxx>
> Date: Sun, 25 Sep 2011 17:47:12 +0300
> Subject: [PATCH v2] Add smsspi driver to support Siano SPI connected
> device 
> using SPI generic driver
> 
> 	modified:   drivers/media/dvb/siano/smsspidrv.c
> 	modified:   drivers/media/dvb/siano/smsspiphy.c
> 
> 	new file:   drivers/media/dvb/siano/smsspidrv.c
> 	new file:   drivers/media/dvb/siano/smsspiphy.c
> 
> 	new file:   drivers/media/dvb/siano/smsspidrv.c
> 	new file:   drivers/media/dvb/siano/smsspiphy.c
> 	new file:   drivers/media/dvb/siano/smsspiphy.h
> 
> 	modified:   drivers/media/dvb/siano/Kconfig
> 	new file:   drivers/media/dvb/siano/smsspiphy.c
> 
> Signed-off-by: Doron Cohen <doronc@xxxxxxxxxxxx>
> ---
>  drivers/media/dvb/siano/Kconfig        |   23 ++
>  drivers/media/dvb/siano/Makefile       |    2 +
>  drivers/media/dvb/siano/smscoreapi.c   |    2 +-
>  drivers/media/dvb/siano/smsdbg_prn.h   |   56 ++++
>  drivers/media/dvb/siano/smsspicommon.c |  407
> +++++++++++++++++++++++++++
>  drivers/media/dvb/siano/smsspicommon.h |   96 +++++++
>  drivers/media/dvb/siano/smsspidrv.c    |  472
> ++++++++++++++++++++++++++++++++

Hi Doron,

your patch doesn't apply, because your emailer broke long lines and did
some other random whitespace wrapping. Please, re-send it. The best way
for you to send patches is to use "git send-email". You need to configure
your sendmail for it to work with your smarthost, but, once done, it works
like a charm.

It is also hard to read the code with this broken indentation, due to the line
wrapping. I just did a few comments. I'll take a more detailed look after your
re-send.

Regards,
Mauro

>  drivers/media/dvb/siano/smsspiphy.c    |  218 +++++++++++++++
>  drivers/media/dvb/siano/smsspiphy.h    |   38 +++
>  9 files changed, 1313 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/media/dvb/siano/smsdbg_prn.h
>  create mode 100644 drivers/media/dvb/siano/smsspicommon.c
>  create mode 100644 drivers/media/dvb/siano/smsspicommon.h
>  create mode 100644 drivers/media/dvb/siano/smsspidrv.c
>  create mode 100644 drivers/media/dvb/siano/smsspiphy.c
>  create mode 100644 drivers/media/dvb/siano/smsspiphy.h
> 
> diff --git a/drivers/media/dvb/siano/Kconfig
> b/drivers/media/dvb/siano/Kconfig
> index bc6456e..a47a131 100644
> --- a/drivers/media/dvb/siano/Kconfig
> +++ b/drivers/media/dvb/siano/Kconfig
> @@ -17,6 +17,15 @@ config SMS_SIANO_MDTV
>  if SMS_SIANO_MDTV
>  menu "Siano module components"
>  
> +# Kernel sub systems support
> +
> +config SMS_NET_SUBSYS
> +	tristate "Siano Network Adapter"
> +	depends on NET
> +	default n
> +	---help---
> +	Choose if you would like to have Siano's network adapter
> support.
> +

What the Net Subsys has to do with "Add smsspi driver to support Siano SPI connected"?
Please, don't mix different subjects into the same patch, as it makes harder for review,
expecially on big patches like this.

>  # Hardware interfaces support
>  
>  config SMS_USB_DRV
> @@ -30,5 +39,19 @@ config SMS_SDIO_DRV
>  	depends on DVB_CORE && MMC
>  	---help---
>  	  Choose if you would like to have Siano's support for SDIO
> interface
> +
> +config SMS_SPI_DRV
> +	tristate "SPI interface support"
> +	depends on SPI
> +	default y if SPI
> +	---help---
> +	Choose if you would like to have Siano's support for SPI
> interface
> +
> +config SMS_I2C_DRV
> +	tristate "I2C interface support"
> +	depends on DVB_CORE && I2C
> +	---help---
> +	Choose if you would like to have Siano's support for I2C
> interface
> +
>  endmenu
>  endif # SMS_SIANO_MDTV
> diff --git a/drivers/media/dvb/siano/Makefile
> b/drivers/media/dvb/siano/Makefile
> index c54140b..affaf01 100644
> --- a/drivers/media/dvb/siano/Makefile
> +++ b/drivers/media/dvb/siano/Makefile
> @@ -1,9 +1,11 @@
>  
>  smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
> +smsspi-objs := smsspicommon.o smsspidrv.o smsspiphy.o
>  
>  obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
>  obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
>  obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
> +obj-$(CONFIG_SMS_SPI_DRV) += smsspi.o
>  
>  EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
>  
> diff --git a/drivers/media/dvb/siano/smscoreapi.c 
> b/drivers/media/dvb/siano/smscoreapi.c
> index 78765ed..239f453 100644
> --- a/drivers/media/dvb/siano/smscoreapi.c
> +++ b/drivers/media/dvb/siano/smscoreapi.c
> @@ -39,7 +39,7 @@
>  #include "smsir.h"
>  #include "smsendian.h"
>  
> -static int sms_dbg;
> +int sms_dbg;
>  module_param_named(debug, sms_dbg, int, 0644);
>  MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
>  
> diff --git a/drivers/media/dvb/siano/smsdbg_prn.h 
> b/drivers/media/dvb/siano/smsdbg_prn.h
> new file mode 100644
> index 0000000..ea157da
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsdbg_prn.h
> @@ -0,0 +1,56 @@
> +/****************************************************************
> +
> +Siano Mobile Silicon, Inc.
> +MDTV receiver kernel modules.
> +Copyright (C) 2006-2008, Uri Shkolnik
> +
> +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, see <http://www.gnu.org/licenses/>.
> +
> +****************************************************************/
> +
> +#ifndef _SMS_DBG_H_
> +#define _SMS_DBG_H_
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +/**********************************************************************
> **/
> +/* Debug Zones definitions.
> */
> +/**********************************************************************
> **/
> +#undef PERROR
> +#  define PERROR(fmt, args...) \
> +	printk(KERN_ERR "spibus error: line %d- %s(): " fmt, __LINE__,\
> +	  __func__, ## args)
> +#undef PWARNING
> +#  define PWARNING(fmt, args...) \
> +	printk(KERN_WARNING "spibus warning: line %d- %s(): " fmt,
> __LINE__,  \
> +	__func__, ## args)
> +
> +/* the debug macro - conditional compilation from the makefile */
> +#undef PDEBUG			/* undef it, just in case */
> +#ifdef SPIBUS_DEBUG
> +#  define PDEBUG(fmt, args...) \
> +	printk(KERN_DEBUG "spibus: line %d- %s(): " fmt, __LINE__, \
> +	 __func__, ## args)
> +#else
> +#  define PDEBUG(fmt, args...)	/* not debugging: nothing */
> +#endif
> +
> +/* The following defines are used for printing and
> +are mandatory for compilation. */
> +#define TXT(str) str
> +#define PRN_DBG(str) PDEBUG str
> +#define PRN_ERR(str) PERROR str
> +
> +#endif /*_SMS_DBG_H_*/
> diff --git a/drivers/media/dvb/siano/smsspicommon.c 
> b/drivers/media/dvb/siano/smsspicommon.c
> new file mode 100644
> index 0000000..9fd9508
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsspicommon.c
> @@ -0,0 +1,407 @@
> +/****************************************************************
> +
> +Siano Mobile Silicon, Inc.
> +MDTV receiver kernel modules.
> +Copyright (C) 2006-2008, Uri Shkolnik
> +
> +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, see <http://www.gnu.org/licenses/>.
> +
> +****************************************************************/
> +#include "smsspicommon.h"
> +#include "smsdbg_prn.h"
> +
> +static struct _rx_buffer_st *smsspi_handle_unused_bytes_buf(
> +		struct _spi_dev *dev,
> +		struct _rx_buffer_st *buf, int offset, int len,
> +		int unused_bytes)
> +{
> +	struct _rx_buffer_st *tmp_buf;
> +	tmp_buf = dev->cb.allocate_rx_buf(dev->context,
> +		RX_PACKET_SIZE);
> +	if (!tmp_buf) {
> +		PRN_ERR((TXT
> +			("Failed to allocate RX buffer.\n")));
> +		return NULL;
> +	}
> +	if (unused_bytes > 0) {
> +		/* Copy the remaining bytes to the end of
> +		alignment block (256 bytes) so next read
> +		will be aligned. */
> +		int align_block =
> +			(((unused_bytes + SPI_PACKET_SIZE -
> +			1) >> SPI_PACKET_SIZE_BITS) <<
> +			SPI_PACKET_SIZE_BITS);
> +		memset(tmp_buf->ptr, 0,
> +			align_block - unused_bytes);
> +		memcpy((char *)tmp_buf->ptr +
> +			(align_block - unused_bytes),
> +			(char *)buf->ptr + offset + len -
> +			unused_bytes, unused_bytes);
> +	}
> +	return tmp_buf;
> +}
> +
> +static struct _rx_buffer_st *smsspi_common_find_msg(struct _spi_dev
> *dev,
> +		struct _rx_buffer_st *buf, int offset, int len,
> +		int *unused_bytes, int *missing_bytes)
> +{
> +	int i;
> +	int recieved_bytes, padded_msg_len;
> +	int align_fix;
> +	int msg_offset;
> +	unsigned char *ptr = (unsigned char *)buf->ptr + offset;
> +	if (unused_bytes == NULL || missing_bytes == NULL)
> +		return NULL;
> +
> +	*missing_bytes = 0;
> +	*unused_bytes = 0;
> +
> +	PRN_DBG((TXT("entering with %d bytes.\n"), len));
> +	for (i = 0; i < len; i++, ptr++) {
> +		switch (dev->rxState) {
> +		case RxsWait_a5:
> +			dev->rxState =
> +			    ((*ptr & 0xff) == 0xa5) ? RxsWait_5a :
> RxsWait_a5;
> +			dev->rxPacket.msg_offset =
> +			    (unsigned long)ptr - (unsigned long)buf->ptr
> + 4;
> +			break;
> +		case RxsWait_5a:
> +			if ((*ptr & 0xff) == 0x5a) {
> +				dev->rxState = RxsWait_e7;
> +			} else{
> +				dev->rxState = RxsWait_a5;
> +				i--;
> +				ptr--;	/* re-scan current byte*/
> +			}
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsWait_e7:
> +			if ((*ptr & 0xff) == 0xe7) {
> +				dev->rxState = RxsWait_7e;
> +			} else{
> +				dev->rxState = RxsWait_a5;
> +				i--;
> +				ptr--;	/* re-scan current byte*/
> +			}
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsWait_7e:
> +			if ((*ptr & 0xff) == 0x7e) {
> +				dev->rxState = RxsTypeH;
> +			} else{
> +				dev->rxState = RxsWait_a5;
> +				i--;
> +				ptr--;	/* re-scan current byte*/
> +			}
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsTypeH:
> +			dev->rxPacket.msg_buf = buf;
> +			dev->rxPacket.msg_offset =
> +			    (unsigned long)ptr - (unsigned
> long)buf->ptr;
> +			dev->rxState = RxsTypeL;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsTypeL:
> +			dev->rxState = RxsGetSrcId;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsGetSrcId:
> +			dev->rxState = RxsGetDstId;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsGetDstId:
> +			dev->rxState = RxsGetLenL;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsGetLenL:
> +			dev->rxState = RxsGetLenH;
> +			dev->rxPacket.msg_len = (*ptr & 0xff);
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsGetLenH:
> +			dev->rxState = RxsFlagsL;
> +			dev->rxPacket.msg_len += (*ptr & 0xff) << 8;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsFlagsL:
> +			dev->rxState = RxsFlagsH;
> +			dev->rxPacket.msg_flags = (*ptr & 0xff);
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsFlagsH:
> +			dev->rxState = RxsData;
> +			dev->rxPacket.msg_flags += (*ptr & 0xff) << 8;
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		case RxsData:
> +			recieved_bytes =
> +			    len + offset - dev->rxPacket.msg_offset;
> +			padded_msg_len =
> +			    ((dev->rxPacket.msg_len + 4 +
> SPI_PACKET_SIZE -
> +			      1) >> SPI_PACKET_SIZE_BITS) <<
> +			    SPI_PACKET_SIZE_BITS;
> +			if (recieved_bytes < padded_msg_len) {
> +				*unused_bytes = 0;
> +				*missing_bytes = padded_msg_len -
> +						recieved_bytes;
> +				return buf;
> +			}
> +			dev->rxState = RxsWait_a5;
> +			if (dev->cb.msg_found_cb) {
> +				align_fix = 0;
> +				if (dev->rxPacket.
> +				    msg_flags &
> MSG_HDR_FLAG_SPLIT_MSG_HDR) {
> +					align_fix =
> +					    (dev->rxPacket.
> +					     msg_flags >> 8) & 0x3;
> +					/* The FW aligned the message
> data
> +					therefore - alignment bytes
> should be
> +					thrown away. Throw the alignment
> bytes
> +					by moving the header ahead over
> the
> +					alignment bytes. */
> +					if (align_fix) {
> +						int length;
> +						ptr = (unsigned char *)
> +					 	    dev->rxPacket.
> +						    msg_buf->ptr +
> +
> dev->rxPacket.msg_offset;
> +
> +						/* Restore header to
> original
> +						state before alignment
> changes
> +						*/
> +						length =
> +						    (ptr[5] << 8) |
> ptr[4];
> +						length -= align_fix;
> +						ptr[5] = length >> 8;
> +						ptr[4] = length & 0xff;
> +						/* Zero alignment flags
> */
> +						ptr[7] &= 0xfc;
> +
> +						for (i = MSG_HDR_LEN -
> 1;
> +						     i >= 0; i--) {
> +							ptr[i +
> align_fix] =
> +							    ptr[i];
> +						}
> +						dev->rxPacket.msg_offset
> +=
> +						    align_fix;
> +					}
> +				}
> +
> +				PRN_DBG((TXT
> +				("Msg found and sent to callback
> func.\n")));
> +
> +				/* force all messages to start on
> +				 * 4-byte boundary */
> +				msg_offset = dev->rxPacket.msg_offset;
> +				if (msg_offset & 0x3) {
> +					msg_offset &= (~0x3);
> +					memmove((unsigned char *)
> +
> (dev->rxPacket.msg_buf->ptr)
> +						+ msg_offset,
> +						(unsigned char *)
> +
> (dev->rxPacket.msg_buf->ptr)
> +						+
> dev->rxPacket.msg_offset,
> +						dev->rxPacket.msg_len -
> +						align_fix);
> +				}
> +
> +				*unused_bytes =
> +				    len + offset -
> dev->rxPacket.msg_offset -
> +				    dev->rxPacket.msg_len;
> +
> +				/* In any case we got here -
> unused_bytes
> +				 * should not be 0 Because we want to
> force
> +				 * reading at least 256 after the end
> +				 * of any found message */
> +				if (*unused_bytes == 0)
> +					*unused_bytes = -1;
> +
> +				buf =
> smsspi_handle_unused_bytes_buf(dev, buf,
> +						offset, len,
> *unused_bytes);
> +
> +				dev->cb.msg_found_cb(dev->context,
> +
> dev->rxPacket.msg_buf,
> +						     msg_offset,
> +
> dev->rxPacket.msg_len -
> +						     align_fix);
> +				*missing_bytes = 0;
> +				return buf;
> +			} else {
> +				PRN_DBG((TXT
> +		 ("Msg found but no callback. therefore - thrown
> away.\n")));
> +			}
> +			PRN_DBG((TXT("state %d.\n"), dev->rxState));
> +			break;
> +		}
> +	}
> +
> +	if (dev->rxState == RxsWait_a5) {
> +		*unused_bytes = 0;
> +		*missing_bytes = 0;
> +		return buf;
> +	} else {
> +		/* Workaround to corner case: if the last byte of the
> buffer
> +		is "a5" (first byte of the preamble), the host thinks it
> should
> +		send another 256 bytes.  In case the a5 is the firmware
> +		underflow byte, this will cause an infinite loop, so we
> check
> +		for this case explicitly. */
> +		if (dev->rxState == RxsWait_5a) {
> +			if ((*(ptr - 2) == 0xa5) || 
> +			(*((unsigned int *)(void *)(ptr-4)) == 
> +			 *((unsigned int *)(void *)(ptr-8)))) {
> +				dev->rxState = RxsWait_a5;
> +				*unused_bytes = 0;
> +				*missing_bytes = 0;
> +
> +				return buf;
> +			}
> +		}
> +
> +		if (dev->rxPacket.msg_offset >= (SPI_PACKET_SIZE + 4))
> +			/* adding 4 for the preamble. */
> +		{		/*The packet will be copied to a new
> buffer
> +				   and rescaned by the state machine */
> +			struct _rx_buffer_st *tmp_buf = buf;
> +			*unused_bytes = dev->rxState - RxsWait_a5;
> +			tmp_buf = smsspi_handle_unused_bytes_buf(dev,
> buf,
> +					offset, len, *unused_bytes);
> +			dev->rxState = RxsWait_a5;
> +			dev->cb.free_rx_buf(dev->context, buf);
> +			*missing_bytes = 0;
> +			return tmp_buf;
> +		} else {
> +			/* report missing bytes and continue
> +			   with message scan. */
> +			*unused_bytes = 0;
> +			*missing_bytes = SPI_PACKET_SIZE;
> +			return buf;
> +		}
> +	}
> +}
> +
> +void smsspi_common_transfer_msg(struct _spi_dev *dev, struct _spi_msg
> *txmsg,
> +				int padding_allowed)
> +{
> +	int len, bytes_to_transfer;
> +	unsigned long tx_phy_addr;
> +	int missing_bytes, tx_bytes;
> +	int offset, unused_bytes;
> +	int align_block;
> +	char *txbuf;
> +	struct _rx_buffer_st *buf, *tmp_buf;
> +
> +	len = 0;
> +	if (!dev->cb.transfer_data_cb) {
> +		PRN_ERR((TXT
> +		("function called while module is not
> initialized.\n")));
> +		return;
> +	}
> +	if (txmsg == 0) {
> +		bytes_to_transfer = SPI_PACKET_SIZE;
> +		txbuf = 0;
> +		tx_phy_addr = 0;
> +		tx_bytes = 0;
> +	} else {
> +		tx_bytes = txmsg->len;
> +		if (padding_allowed)
> +			bytes_to_transfer =
> +			    (((tx_bytes + SPI_PACKET_SIZE -
> +			       1) >> SPI_PACKET_SIZE_BITS) <<
> +			     SPI_PACKET_SIZE_BITS);
> +		else
> +			bytes_to_transfer = (((tx_bytes + 3) >> 2) <<
> 2);
> +		txbuf = txmsg->buf;
> +		tx_phy_addr = txmsg->buf_phy_addr;
> +	}
> +	offset = 0;
> +	unused_bytes = 0;
> +	buf =
> +	    dev->cb.allocate_rx_buf(dev->context,
> +				    RX_PACKET_SIZE + SPI_PACKET_SIZE*2);
> +	if (!buf) {
> +		PRN_ERR((TXT("Failed to allocate RX buffer.\n")));
> +		return;
> +	}
> +	while (bytes_to_transfer || unused_bytes) {
> +		if ((unused_bytes <= 0) && (bytes_to_transfer > 0)) {
> +			len = min(bytes_to_transfer, RX_PACKET_SIZE);
> +			PRN_DBG((TXT("transfering block of %d bytes\n"),
> len));
> +			dev->cb.transfer_data_cb(dev->phy_context,
> +					(unsigned char *)txbuf,
> +					tx_phy_addr,
> +					(unsigned char *)buf->ptr +
> offset,
> +					buf->phy_addr + offset, len);
> +		}
> +
> +		tmp_buf =
> +		    smsspi_common_find_msg(dev, buf, offset, len,
> +					   &unused_bytes,
> &missing_bytes);
> +		if (bytes_to_transfer)
> +			bytes_to_transfer -= len;
> +
> +		if (tx_bytes)
> +			tx_bytes -= len;
> +
> +		if (missing_bytes)
> +			offset += len;
> +
> +		if (unused_bytes) {
> +			/* In this case tmp_buf is a new buffer
> allocated
> +			 * in smsspi_common_find_msg
> +			 * and it already contains the unused bytes */
> +			if (unused_bytes > 0) {
> +				align_block =
> +				    (((unused_bytes + SPI_PACKET_SIZE -
> +				       1) >> SPI_PACKET_SIZE_BITS) <<
> +				     SPI_PACKET_SIZE_BITS);
> +				len = align_block;
> +			}
> +			offset = 0;
> +			buf = tmp_buf;
> +		}
> +		if (tx_bytes <= 0) {
> +			txbuf = 0;
> +			tx_bytes = 0;
> +		}
> +		if (bytes_to_transfer < missing_bytes) {
> +			bytes_to_transfer =
> +			    (((missing_bytes + SPI_PACKET_SIZE -
> +			       1) >> SPI_PACKET_SIZE_BITS) <<
> +			     SPI_PACKET_SIZE_BITS);
> +			PRN_DBG((TXT
> +	("a message was found, adding bytes to transfer, txmsg %d, total
> %d\n")
> +			, tx_bytes, bytes_to_transfer));
> +		}
> +	}
> +	dev->cb.free_rx_buf(dev->context, buf);
> +}
> +
> +int smsspicommon_init(struct _spi_dev *dev, void *context, void
> *phy_context,
> +		      struct _spi_dev_cb_st *cb)
> +{
> +	PRN_DBG((TXT("entering.\n")));
> +	if (cb->transfer_data_cb == 0 ||
> +	    cb->msg_found_cb == 0 ||
> +	    cb->allocate_rx_buf == 0 || cb->free_rx_buf == 0) {
> +		PRN_ERR((TXT("Invalid input parameters of init
> routine.\n")));
> +		return -1;
> +	}
> +	dev->context = context;
> +	dev->phy_context = phy_context;
> +	memcpy(&dev->cb, cb, sizeof(struct _spi_dev_cb_st));
> +	dev->rxState = RxsWait_a5;
> +	PRN_DBG((TXT("exiting.\n")));
> +	return 0;
> +}
> diff --git a/drivers/media/dvb/siano/smsspicommon.h 
> b/drivers/media/dvb/siano/smsspicommon.h
> new file mode 100644
> index 0000000..8976d04
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsspicommon.h
> @@ -0,0 +1,96 @@
> +/****************************************************************
> +
> +Siano Mobile Silicon, Inc.
> +MDTV receiver kernel modules.
> +Copyright (C) 2006-2008, Uri Shkolnik
> +
> +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, see <http://www.gnu.org/licenses/>.
> +
> +****************************************************************/
> +#ifndef _SMS_SPI_COMMON_H_
> +#define _SMS_SPI_COMMON_H_
> +
> +#define RX_PACKET_SIZE  		0x1000
> +#define SPI_PACKET_SIZE_BITS		8
> +#define SPI_PACKET_SIZE 		(1<<SPI_PACKET_SIZE_BITS)
> +#define SPI_MAX_CTRL_MSG_SIZE		0x100
> +
> +#define MSG_HDR_FLAG_SPLIT_MSG_HDR	0x0004
> +#define MSG_HDR_LEN			8
> +
> +enum _spi_rx_state {
> +	RxsWait_a5 = 0,
> +	RxsWait_5a,
> +	RxsWait_e7,
> +	RxsWait_7e,
> +	RxsTypeH,
> +	RxsTypeL,
> +	RxsGetSrcId,
> +	RxsGetDstId,
> +	RxsGetLenL,
> +	RxsGetLenH,
> +	RxsFlagsL,
> +	RxsFlagsH,
> +	RxsData
> +};
> +
> +struct _rx_buffer_st {
> +	void *ptr;
> +	unsigned long phy_addr;
> +};
> +
> +struct _rx_packet_request {
> +	struct _rx_buffer_st *msg_buf;
> +	int msg_offset;
> +	int msg_len;
> +	int msg_flags;
> +};
> +
> +struct _spi_dev_cb_st {
> +	void (*transfer_data_cb) (void *context, unsigned char *, 
> +			 unsigned long, unsigned char *, unsigned long,
> int);
> +	void (*msg_found_cb) (void *, void *, int, int);
> +	struct _rx_buffer_st *(*allocate_rx_buf) (void *, int);
> +	void (*free_rx_buf) (void *, struct _rx_buffer_st *);
> +};
> +
> +struct _spi_dev {
> +	void *context;
> +	void *phy_context;
> +	struct _spi_dev_cb_st cb;
> +	char *rxbuf;
> +	enum _spi_rx_state rxState;
> +	struct _rx_packet_request rxPacket;
> +	char *internal_tx_buf;
> +};
> +
> +struct _spi_msg {
> +	char *buf;
> +	unsigned long buf_phy_addr;
> +	int len;
> +};
> +
> +void smsspi_common_transfer_msg(struct _spi_dev *dev, struct _spi_msg
> *txmsg,
> +				int padding_allowed);
> +int smsspicommon_init(struct _spi_dev *dev, void *contex, void
> *phy_context,
> +		      struct _spi_dev_cb_st *cb);
> +
> +#if defined HEXDUMP_DEBUG && defined SPIBUS_DEBUG
> +/*! dump a human readable print of a binary buffer */
> +void smsspi_khexdump(char *buf, int len);
> +#else
> +#define smsspi_khexdump(buf, len)
> +#endif

Don't do that. Those symbols cannot be selected via Kconfig. Also, Kernel already
offers a standard way to print hexdumps (print_hex_dump).

> +
> +#endif /*_SMS_SPI_COMMON_H_*/
> diff --git a/drivers/media/dvb/siano/smsspidrv.c 
> b/drivers/media/dvb/siano/smsspidrv.c
> new file mode 100644
> index 0000000..4526cb8
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsspidrv.c
> @@ -0,0 +1,472 @@
> +/****************************************************************
> +
> +Siano Mobile Silicon, Inc.
> +MDTV receiver kernel modules.
> + Copyright (C) 2006-2010, Erez Cohen
> +
> +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, see <http://www.gnu.org/licenses/>.
> +
> +****************************************************************/
> +/*!
> +	\file	spibusdrv.c
> +
> +	\brief	spi bus driver module
> +
> +	This file contains implementation of the spi bus driver.
> +*/

Wrong format for function documentation. See: Documentation/kernel-doc-nano-HOWTO.txt

> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +
> +#include "smscoreapi.h"
> +#include "smsspicommon.h"
> +#include "smsspiphy.h"
> +
> +#define SMS_INTR_PIN			19  /* 0 for nova sip, 26 for
> vega */
> +#define TX_BUFFER_SIZE			0x200
> +#define RX_BUFFER_SIZE			(0x1000 + SPI_PACKET_SIZE +
> 0x100)
> +#define NUM_RX_BUFFERS			72
> +
> +struct _spi_device_st {
> +	struct _spi_dev dev;
> +	void *phy_dev;
> +
> +	struct completion write_operation;
> +	struct list_head tx_queue;
> +	int allocatedPackets;
> +	int padding_allowed;
> +	char *rxbuf;
> +
> +	struct smscore_device_t *coredev;
> +	struct list_head txqueue;
> +	char *txbuf;
> +	dma_addr_t txbuf_phy_addr;
> +};
> +
> +struct _smsspi_txmsg {
> +	struct list_head node;	/*! internal management */
> +	void *buffer;
> +	size_t size;
> +	int alignment;
> +	int add_preamble;
> +	struct completion completion;
> +	void (*prewrite) (void *);
> +	void (*postwrite) (void *);
> +};
> +
> +struct _Msg {
> +	struct SmsMsgHdr_ST hdr;
> +	u32 data[3];
> +};
> +
> +struct _spi_device_st *spi_dev;
> +
> +int sms_dbg;
> +static void spi_worker_thread(void *arg);
> +static DECLARE_WORK(spi_work_queue, (void *)spi_worker_thread);
> +static u8 smsspi_preamble[] = { 0xa5, 0x5a, 0xe7, 0x7e };
> +static u8 smsspi_startup[] = { 0, 0, 0xde, 0xc1, 0xa5, 0x51, 0xf1, 0xed
> };
> +static u32 sms_intr_pin = SMS_INTR_PIN;
> +
> +static u32 default_type = SMS_NOVA_B0;
> +
> +module_param_named(debug, sms_dbg, int, S_IRUGO|S_IWUSR);
> +MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
> +
> +module_param(default_type, int, S_IRUGO);
> +MODULE_PARM_DESC(default_type, "default SMS device type.");
> +
> +module_param(sms_intr_pin, int, S_IRUGO);
> +MODULE_PARM_DESC(sms_intr_pin, "interrupt pin number used by SMS
> chip.");
> +
> +module_param(host_intr_pin, int, S_IRUGO);
> +MODULE_PARM_DESC(host_intr_pin, "interrupt pin number used by Host.");
> +
> +/******************************************/
> +static void spi_worker_thread(void *arg)
> +{
> +	struct _spi_device_st *spi_device = spi_dev;
> +	struct _smsspi_txmsg *msg = NULL;
> +	struct _spi_msg txmsg;
> +
> +	sms_info("worker start\n");
> +	do {
> +		/* do we have a msg to write ? */
> +		if (!msg && !list_empty(&spi_device->txqueue))
> +			msg = (struct _smsspi_txmsg *)
> +					list_entry(spi_device->txqueue.
> +					next, struct _smsspi_txmsg,
> node);
> +
> +		if (msg) {
> +			if (msg->add_preamble) {
> +				txmsg.len =
> +				    min(msg->size +
> sizeof(smsspi_preamble),
> +					(size_t) TX_BUFFER_SIZE);
> +				txmsg.buf = spi_device->txbuf;
> +				txmsg.buf_phy_addr = 
> +					spi_device->txbuf_phy_addr;
> +				memcpy(txmsg.buf, smsspi_preamble,
> +				       sizeof(smsspi_preamble));
> +
> memcpy(&txmsg.buf[sizeof(smsspi_preamble)],
> +				       msg->buffer,
> +				       txmsg.len -
> sizeof(smsspi_preamble));
> +				msg->add_preamble = 0;
> +				msg->buffer +=
> +				    txmsg.len - sizeof(smsspi_preamble);
> +				msg->size -=
> +				    txmsg.len - sizeof(smsspi_preamble);
> +				/* zero out the rest of aligned buffer
> */
> +				memset(&txmsg.buf[txmsg.len], 0,
> +				       TX_BUFFER_SIZE - txmsg.len);
> +
> smsspi_common_transfer_msg(&spi_device->dev,
> +							   &txmsg, 1);
> +			} else {
> +				txmsg.len =
> +				    min(msg->size, (size_t)
> TX_BUFFER_SIZE);
> +				txmsg.buf = spi_device->txbuf;
> +				txmsg.buf_phy_addr = 
> +					spi_device->txbuf_phy_addr;
> +				memcpy(txmsg.buf, msg->buffer,
> txmsg.len);
> +
> +				msg->buffer += txmsg.len;
> +				msg->size -= txmsg.len;
> +				/* zero out the rest of aligned buffer
> */
> +				memset(&txmsg.buf[txmsg.len], 0,
> +				       TX_BUFFER_SIZE - txmsg.len);
> +
> smsspi_common_transfer_msg(&spi_device->dev,
> +							   &txmsg, 0);
> +			}
> +
> +		} else {
> +			smsspi_common_transfer_msg(&spi_device->dev,
> NULL, 1);
> +		}
> +
> +		/* if there was write, have we finished ? */
> +		if (msg && !msg->size) {
> +			/* call postwrite call back */
> +			if (msg->postwrite)
> +				msg->postwrite(spi_device);
> +
> +			list_del(&msg->node);
> +			complete(&msg->completion);
> +			msg = NULL;
> +		}
> +		/* if there was read, did we read anything ? */
> +
> +	} while (!list_empty(&spi_device->txqueue) || msg);
> +
> +	sms_info("worker end\n");
> +
> +}
> +
> +static void msg_found(void *context, void *buf, int offset, int len)
> +{
> +	struct _spi_device_st *spi_device = (struct _spi_device_st *)
> context;
> +	struct smscore_buffer_t *cb =
> +	    (struct smscore_buffer_t
> +	     *)(container_of(buf, struct smscore_buffer_t, p));
> +
> +	sms_info("entering\n");
> +	cb->offset = offset;
> +	cb->size = len;
> +	/* sms_err ("buffer %p is sent back to core databuf=%p,
> +		offset=%d.\n", cb, cb->p, cb->offset); */
> +	smscore_onresponse(spi_device->coredev, cb);
> +
> +	sms_info("exiting\n");
> +
> +}
> +
> +static void smsspi_int_handler(void *context)
> +{
> +	sms_info("interrupt\n");
> +	PREPARE_WORK(&spi_work_queue, (void *)spi_worker_thread);
> +	schedule_work(&spi_work_queue);
> +}
> +
> +static int smsspi_queue_message_and_wait(struct _spi_device_st
> *spi_device,
> +					 struct _smsspi_txmsg *msg)
> +{
> +	init_completion(&msg->completion);
> +	list_add_tail(&msg->node, &spi_device->txqueue);
> +	schedule_work(&spi_work_queue);
> +	wait_for_completion(&msg->completion);
> +
> +	return 0;
> +}
> +
> +static int smsspi_preload(void *context)
> +{
> +	struct _smsspi_txmsg msg;
> +	struct _spi_device_st *spi_device = (struct _spi_device_st *)
> context;
> +	struct _Msg Msg = {
> +		{
> +		MSG_SMS_SPI_INT_LINE_SET_REQ, 0, HIF_TASK,
> +			sizeof(struct _Msg), 0}, {
> +		0, sms_intr_pin, 0}
> +	};
> +	int rc;
> +
> +	sms_err("preparing for download\n");
> +	prepareForFWDnl(spi_device->phy_dev);
> +	sms_err("Sending SPI init sequence\n");
> +	msg.buffer = smsspi_startup;
> +	msg.size = sizeof(smsspi_startup);
> +	msg.alignment = 4;
> +	msg.add_preamble = 0;
> +	msg.prewrite = NULL;	/* smsspiphy_reduce_clock; */
> +	msg.postwrite = NULL;   /* smsspiphy_restore_clock; */
> +
> +	rc = smsspi_queue_message_and_wait(context, &msg);
> +	if (rc < 0) {
> +		sms_err("smsspi_queue_message_and_wait error, rc =
> %d\n", rc);
> +		return rc;
> +	}
> +
> +	sms_debug("sending MSG_SMS_SPI_INT_LINE_SET_REQ");
> +	sms_info("Sending SPI Set Interrupt command sequence\n");
> +	msg.buffer = &Msg;
> +	msg.size = sizeof(Msg);
> +	msg.alignment = SPI_PACKET_SIZE;
> +	msg.add_preamble = 1;
> +
> +	rc = smsspi_queue_message_and_wait(context, &msg);
> +	if (rc < 0) {
> +		sms_err("set interrupt line failed, rc = %d\n", rc);
> +		return rc;
> +	}
> +
> +	return rc;
> +}
> +
> +static int smsspi_postload(void *context)
> +{
> +	struct _spi_device_st *spi_device = (struct _spi_device_st *)
> context;
> +	int mode =
> smscore_registry_getmode(spi_device->coredev->devpath);
> +	if ((mode != DEVICE_MODE_ISDBT) &&
> +	    (mode != DEVICE_MODE_ISDBT_BDA)) {
> +		fwDnlComplete(spi_device->phy_dev, 0);
> +		
> +	}
> +	
> +	return 0;
> +}
> +
> +static int smsspi_write(void *context, void *txbuf, size_t len)
> +{
> +	struct _smsspi_txmsg msg;
> +	msg.buffer = txbuf;
> +	msg.size = len;
> +	msg.prewrite = NULL;
> +	msg.postwrite = NULL;
> +	if (len > 0x1000) {
> +		/* The FW is the only long message. Do not add preamble,
> +		and do not padd it */
> +		msg.alignment = 4;
> +		msg.add_preamble = 0;
> +		msg.prewrite = smschipreset;
> +	} else {
> +		msg.alignment = SPI_PACKET_SIZE;
> +		msg.add_preamble = 1;
> +	}
> +	sms_info("Writing message to  SPI.\n");
> +	sms_info("msg hdr: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x,
> 0x%x.\n",
> +	       ((u8 *) txbuf)[0], ((u8 *) txbuf)[1], ((u8 *) txbuf)[2],
> +	       ((u8 *) txbuf)[3], ((u8 *) txbuf)[4], ((u8 *) txbuf)[5],
> +	       ((u8 *) txbuf)[6], ((u8 *) txbuf)[7]);
> +	return smsspi_queue_message_and_wait(context, &msg);
> +}
> +
> +struct _rx_buffer_st *allocate_rx_buf(void *context, int size)
> +{
> +	struct smscore_buffer_t *buf;
> +	struct _spi_device_st *spi_device = (struct _spi_device_st *)
> context;
> +	if (size > RX_BUFFER_SIZE) {
> +		sms_err("Requested size is bigger than max buffer
> size.\n");
> +		return NULL;
> +	}
> +	buf = smscore_getbuffer(spi_device->coredev);
> +	sms_info("Recieved Rx buf %p physical 0x%x (contained in %p)\n",
> 
> +						buf->p, buf->phys, buf);
> +
> +	/* note: this is not mistake! the rx_buffer_st is identical to
> part of
> +	   smscore_buffer_t and we return the address of the start of
> the
> +	   identical part */
> +	return (struct _rx_buffer_st *) &buf->p;
> +}
> +
> +static void free_rx_buf(void *context, struct _rx_buffer_st *buf)
> +{
> +	struct _spi_device_st *spi_device = (struct _spi_device_st *)
> context;
> +	struct smscore_buffer_t *cb =
> +	    (struct smscore_buffer_t
> +	     *)(container_of(((void *)buf), struct smscore_buffer_t,
> p));
> +	sms_info("buffer %p is released.\n", cb);
> +	smscore_putbuffer(spi_device->coredev, cb);
> +}
> +
> +/*! Release device STUB
> +
> +\param[in]	dev:		device control block
> +\return		void
> +*/
> +static void smsspi_release(struct device *dev)
> +{
> +	sms_info("nothing to do\n");
> +	/* Nothing to release */
> +}
> +
> +static struct platform_device smsspi_device = {
> +	.name = "smsspi",
> +	.id = 1,
> +	.dev = {
> +		.release = smsspi_release,
> +		},
> +};
> +
> +static int __init smsspi_module_init(void)
> +{
> +	struct smsdevice_params_t params;
> +	int ret;
> +	struct _spi_device_st *spi_device;
> +	struct _spi_dev_cb_st common_cb;
> +
> +	sms_info("entering\n");
> +
> +	spi_device =
> +	    kmalloc(sizeof(struct _spi_device_st), GFP_KERNEL);
> +	spi_dev = spi_device;
> +
> +	INIT_LIST_HEAD(&spi_device->txqueue);
> +
> +	ret = platform_device_register(&smsspi_device);
> +	if (ret < 0) {
> +		sms_err("platform_device_register failed\n");
> +		return ret;
> +	}
> +
> +	spi_device->txbuf =
> +	    dma_alloc_coherent(NULL, TX_BUFFER_SIZE,
> +			       &spi_device->txbuf_phy_addr,
> +			       GFP_KERNEL | GFP_DMA);
> +	if (!spi_device->txbuf) {
> +		printk(KERN_INFO "%s dma_alloc_coherent(...) failed\n",
> +		       __func__);
> +		ret = -ENOMEM;
> +		goto txbuf_error;
> +	}
> +
> +	spi_device->phy_dev =
> +	    smsspiphy_init(NULL, smsspi_int_handler, spi_device);
> +	if (spi_device->phy_dev == 0) {
> +		printk(KERN_INFO "%s smsspiphy_init(...) failed\n",
> __func__);
> +		goto phy_error;
> +	}
> +
> +	common_cb.allocate_rx_buf = allocate_rx_buf;
> +	common_cb.free_rx_buf = free_rx_buf;
> +	common_cb.msg_found_cb = msg_found;
> +	common_cb.transfer_data_cb = smsspibus_xfer;
> +
> +	ret =
> +	    smsspicommon_init(&spi_device->dev, spi_device, 
> +			spi_device->phy_dev, &common_cb);
> +	if (ret) {
> +		printk(KERN_INFO "%s smsspiphy_init(...) failed\n",
> __func__);
> +		goto common_error;
> +	}
> +
> +	/* register in smscore */
> +	memset(&params, 0, sizeof(params));
> +	params.context = spi_device;
> +	params.device = &smsspi_device.dev;
> +	params.buffer_size = RX_BUFFER_SIZE;
> +	params.num_buffers = NUM_RX_BUFFERS;
> +	params.flags = SMS_DEVICE_NOT_READY;
> +	params.sendrequest_handler = smsspi_write;
> +	strcpy(params.devpath, "spi");
> +	params.device_type = default_type;
> +
> +	params.flags =
> +	    SMS_DEVICE_FAMILY2 | SMS_DEVICE_NOT_READY;
> +	params.preload_handler = smsspi_preload;
> +	params.postload_handler = smsspi_postload;
> +	sms_info("registering spi device type %d", params.device_type); 
> +	ret = smscore_register_device(&params, &spi_device->coredev);
> +	if (ret < 0) {
> +		printk(KERN_INFO "%s smscore_register_device(...)
> failed\n",
> +		       __func__);
> +		goto reg_device_error;
> +	}
> +
> +	ret = smscore_start_device(spi_device->coredev);
> +	if (ret < 0) {
> +		printk(KERN_INFO "%s smscore_start_device(...)
> failed\n",
> +		       __func__);
> +		goto start_device_error;
> +	}
> +
> +	sms_info("exiting\n");
> +	return 0;
> +
> +start_device_error:
> +	smscore_unregister_device(spi_device->coredev);
> +
> +reg_device_error:
> +
> +common_error:
> +	smsspiphy_deinit(spi_device->phy_dev);
> +
> +phy_error:
> +	dma_free_coherent(NULL, TX_BUFFER_SIZE, spi_device->txbuf,
> +			  spi_device->txbuf_phy_addr);
> +
> +txbuf_error:
> +	platform_device_unregister(&smsspi_device);
> +
> +	sms_info("exiting error %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static void __exit smsspi_module_exit(void)
> +{
> +	struct _spi_device_st *spi_device = spi_dev;
> +	sms_info("entering\n");
> +
> +	/* stop interrupts */
> +	smsspiphy_deinit(spi_device->phy_dev);
> +	smscore_unregister_device(spi_device->coredev);
> +
> +	dma_free_coherent(NULL, TX_BUFFER_SIZE, spi_device->txbuf,
> +			  spi_device->txbuf_phy_addr);
> +
> +	platform_device_unregister(&smsspi_device);
> +	sms_info("exiting\n");
> +}
> +
> +
> +module_init(smsspi_module_init);
> +module_exit(smsspi_module_exit);
> +
> +MODULE_DESCRIPTION("Siano MDTV SPI device driver");
> +MODULE_AUTHOR("Siano Mobile Silicon, Inc. (doronc@xxxxxxxxxxxx)");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/dvb/siano/smsspiphy.c 
> b/drivers/media/dvb/siano/smsspiphy.c
> new file mode 100644
> index 0000000..f55131c
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsspiphy.c
> @@ -0,0 +1,218 @@
> +#include <linux/kernel.h>
> +#include <linux/delay.h>
> +#include <linux/spi/spi.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/gpio.h>
> +
> +#include "smscoreapi.h"
> +#include "smsspiphy.h"
> +
> +#define MAX_SPEED_DURING_DOWNLOAD	6000000
> +#define MAX_SPEED_DURING_WORK		6000000	
> +#define SPI_PACKET_SIZE 		256	
> +
> +int sms_spi_interrupt = 135;
> +module_param_named(debug, sms_spi_interrupt, int, 0644);
> +MODULE_PARM_DESC(debug, "set interrupt gpio pin for spi device.");
> +
> +
> +int spi_max_speed = MAX_SPEED_DURING_WORK;
> +
> +struct sms_spi {
> +	struct spi_device	*spi_dev;
> +	char			*zero_txbuf;
> +	dma_addr_t 		zero_txbuf_phy_addr;
> +	int 			bus_speed;
> +	void (*interruptHandler) (void *);
> +	void			*intr_context;
> +};
> +
> +/*!
> +invert the endianness of a single 32it integer
> +
> +\param[in]		u: word to invert
> +
> +\return		the inverted word
> +*/
> +static inline u32 invert_bo(u32 u)
> +{
> +	return ((u & 0xff) << 24) | ((u & 0xff00) << 8) | ((u &
> 0xff0000) >> 8)
> +		| ((u & 0xff000000) >> 24);
> +}
> +
> +/*!
> +invert the endianness of a data buffer
> +
> +\param[in]		buf: buffer to invert
> +\param[in]		len: buffer length
> +
> +\return		the inverted word
> +*/
> +
> +
> +static int invert_endianness(char *buf, int len)
> +{
> +	int i;
> +	u32 *ptr = (u32 *) buf;
> +
> +	len = (len + 3) / 4;
> +	for (i = 0; i < len; i++, ptr++)
> +		*ptr = invert_bo(*ptr);
> +	
> +	return 4 * ((len + 3) & (~3));
> +}
> +
> +static irqreturn_t spibus_interrupt(int irq, void *context)
> +{
> +	struct sms_spi *sms_spi = (struct sms_spi *)context;
> +	if (sms_spi->interruptHandler)
> +		sms_spi->interruptHandler(sms_spi->intr_context);
> +	return IRQ_HANDLED;
> +
> +}
> +
> +void prepareForFWDnl(void *context)
> +{
> +	/*Reduce clock rate for FW download*/
> +	struct sms_spi *sms_spi = (struct sms_spi *)context;
> +	sms_spi->bus_speed = MAX_SPEED_DURING_DOWNLOAD;
> +	sms_err("Start FW download.");
> +	msleep(100);
> +	sms_err("done sleeping.");
> +}
> +
> +void fwDnlComplete(void *context, int App)
> +{
> +	/*Set clock rate for working mode*/
> +	struct sms_spi *sms_spi = (struct sms_spi *)context;
> +	sms_spi->bus_speed = spi_max_speed;
> +	sms_err("FW download complete.");
> +	msleep(100);
> +}
> +
> +
> +void smsspibus_xfer(void *context, unsigned char *txbuf,
> +		    unsigned long txbuf_phy_addr, unsigned char *rxbuf,
> +		    unsigned long rxbuf_phy_addr, int len)
> +{
> +	struct sms_spi *sms_spi = (struct sms_spi *)context;
> +	struct spi_message msg;
> +	struct spi_transfer xfer = {
> +		.tx_buf = txbuf,
> +		.rx_buf = rxbuf,
> +		.len = len,
> +		.tx_dma = txbuf_phy_addr,
> +		.rx_dma = rxbuf_phy_addr,
> +		.cs_change = 0,
> +		.speed_hz = sms_spi->bus_speed,
> +		.bits_per_word = 0,
> +	};
> +
> +	if (txbuf) 
> +		invert_endianness(txbuf, len);
> +
> +
> +	if (!txbuf) {
> +		xfer.tx_buf = sms_spi->zero_txbuf;
> +		xfer.tx_dma = sms_spi->zero_txbuf_phy_addr;
> +		
> +	}
> +
> +	spi_message_init(&msg);
> +	msg.is_dma_mapped = 1;
> +	spi_message_add_tail(&xfer, &msg);
> +	spi_sync(sms_spi->spi_dev, &msg);
> +	invert_endianness(rxbuf, len);
> +
> +}
> +
> +
> +
> +void *smsspiphy_init(void *context, void (*smsspi_interruptHandler)
> (void *),
> +		     void *intr_context)
> +{
> +	int ret;
> +	struct sms_spi *sms_spi; 
> +	struct spi_device *sms_device;
> +
> +	struct spi_master *master = spi_busnum_to_master(3);
> +	struct spi_board_info sms_chip = {
> +		.modalias = "SmsSPI",
> +		.platform_data 	= NULL,
> +		.controller_data = NULL,
> +		.irq		= 0, /*OMAP_GPIO_IRQ(4)*/
> +		.max_speed_hz	= spi_max_speed,
> +		.bus_num	= 3,
> +		.chip_select 	= 1,
> +		.mode		= SPI_MODE_0,
> +	};
> +
> +	sms_err("sms_debug = %d\n", sms_dbg);
> +
> +	sms_device = spi_new_device(master, &sms_chip);	
> +	if (!sms_device) {
> +		sms_err("Failed on allocating new SPI device for SMS");
> +		return NULL;
> +	}
> +	sms_device->bits_per_word = 32;
> +	if (spi_setup(sms_device)) {
> +		sms_err("SMS device setup failed");
> +		return NULL;
> +	}
> +
> +	sms_spi = kzalloc(sizeof(struct sms_spi), GFP_KERNEL);
> +
> +	sms_spi->zero_txbuf =  dma_alloc_coherent(NULL, SPI_PACKET_SIZE,
> +			       &sms_spi->zero_txbuf_phy_addr,
> +			       GFP_KERNEL | GFP_DMA);
> +	if (!sms_spi->zero_txbuf) {
> +		sms_err("dma_alloc_coherent(...) failed\n");
> +		kfree(sms_spi);
> +		return NULL;
> +	}
> +	memset(sms_spi->zero_txbuf, 0, SPI_PACKET_SIZE);
> +	sms_spi->interruptHandler = smsspi_interruptHandler;
> +	sms_spi->intr_context = intr_context;
> +
> +
> +	if ((gpio_request(sms_spi_interrupt, "SMSSPI") == 0) &&
> +	    (gpio_direction_input(sms_spi_interrupt) == 0)) {
> +		gpio_export(sms_spi_interrupt, 0);
> +	}
> +
> +	irq_set_irq_type(gpio_to_irq(sms_spi_interrupt), 
> +					IRQ_TYPE_EDGE_FALLING);
> +	ret = request_irq(gpio_to_irq(sms_spi_interrupt), 
> +				spibus_interrupt, IRQF_TRIGGER_FALLING, 
> +				"SMSSPI", sms_spi);
> +	if (ret) {
> +		sms_err("Could not get intrpt for SMS device. status
> =%d\n",
> +								 ret);
> +		return NULL;
> +	}
> +
> +	sms_spi->spi_dev = sms_device;
> +	sms_spi->bus_speed = spi_max_speed;
> +	sms_err("after init sms_spi=0x%x, spi_dev = 0x%x", 
> +				(int)sms_spi, (int)sms_spi->spi_dev);
> +
> +	return sms_spi;
> +}
> +
> +void smsspiphy_deinit(void *context)
> +{
> +	struct sms_spi *sms_spi = (struct sms_spi *)context;
> +	printk(KERN_INFO "smsspiphy_deinit\n");
> +	kfree(sms_spi);
> +
> +}
> +
> +void smschipreset(void *context)
> +{
> +	sms_err("sms chip reset");
> +}
> +
> +
> +
> diff --git a/drivers/media/dvb/siano/smsspiphy.h 
> b/drivers/media/dvb/siano/smsspiphy.h
> new file mode 100644
> index 0000000..a70198b
> --- /dev/null
> +++ b/drivers/media/dvb/siano/smsspiphy.h
> @@ -0,0 +1,38 @@
> +/****************************************************************
> +
> +Siano Mobile Silicon, Inc.
> +MDTV receiver kernel modules.
> +Copyright (C) 2006-2008, Uri Shkolnik
> +
> +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, see <http://www.gnu.org/licenses/>.
> +
> +****************************************************************/
> +
> +#ifndef __SMS_SPI_PHY_H__
> +#define __SMS_SPI_PHY_H__
> +
> +extern int host_intr_pin;
> +extern int sms_dbg;
> +void smsspibus_xfer(void *context, unsigned char *txbuf,
> +		    unsigned long txbuf_phy_addr, unsigned char *rxbuf,
> +		    unsigned long rxbuf_phy_addr, int len);
> +void *smsspiphy_init(void *context, void (*smsspi_interruptHandler)
> (void *),
> +		     void *intr_context);
> +void smsspiphy_deinit(void *context);
> +void smschipreset(void *context);
> +void WriteFWtoStellar(void *pSpiPhy, unsigned char *pFW, unsigned long
> Len);
> +void prepareForFWDnl(void *pSpiPhy);
> +void fwDnlComplete(void *context, int App);
> +
> +#endif /* __SMS_SPI_PHY_H__ */

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux