generic-poky/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-ifx...

1649 lines
42 KiB
Diff

Index: linux-2.6.33/drivers/spi/Kconfig
===================================================================
--- linux-2.6.33.orig/drivers/spi/Kconfig
+++ linux-2.6.33/drivers/spi/Kconfig
@@ -339,6 +339,10 @@ config SPI_MRST_GTM501
tristate "SPI protocol driver for GTM501l"
depends on SPI_MRST
+config SPI_IFX_GPS
+ tristate "SPI protocol driver for IFX HH2 GPS"
+ depends on SPI_MRST
+
config SPI_SPIDEV
tristate "User mode SPI device driver support"
depends on EXPERIMENTAL
Index: linux-2.6.33/drivers/spi/Makefile
===================================================================
--- linux-2.6.33.orig/drivers/spi/Makefile
+++ linux-2.6.33/drivers/spi/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
obj-$(CONFIG_SPI_MRST) += mrst_spi.o
obj-$(CONFIG_SPI_MRST_GTM501) += gtm501l_spi.o
+obj-$(CONFIG_SPI_IFX_GPS) += hh2serial.o
# special build for s3c24xx spi driver with fiq support
spi_s3c24xx_hw-y := spi_s3c24xx.o
Index: linux-2.6.33/drivers/spi/hh2serial.c
===================================================================
--- /dev/null
+++ linux-2.6.33/drivers/spi/hh2serial.c
@@ -0,0 +1,1572 @@
+/*
+ * HH2 SPI Serial driver
+ *
+ * Copyright (C) 2009 Markus Burvall (Markus.Burvall@swedenconnectivity.com)
+ *
+ * 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, version 2 of the License.
+ *
+ */
+
+
+#define DEBUG 1
+
+//#define HH2_TTY_ECHO
+//#define HH2_TTY_SEND_POLL
+//#define HH2_NO_SPI
+#define HH2SERIAL_SPI_16BIT
+//#define HH2SERIAL_ENABLE_DEBUG
+#define HH2SERIAL_SPI_POLL
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <asm/atomic.h>
+
+#ifndef HH2_NO_SPI
+#include <linux/spi/spi.h>
+#include <linux/spi/mrst_spi.h>
+#endif
+
+MODULE_AUTHOR("Markus Burvall <Markus.Burvall@swedenconnectivity.com>");
+MODULE_DESCRIPTION("HH2 Serial Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("hh2serial");
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+
+#define FUNC_ENTER() do { printk("ENTER: %s\n", __func__); } while (0)
+
+#else
+
+#define FUNC_ENTER()
+
+#endif
+
+
+struct hh2serial_dev {
+ struct uart_port port;
+ bool tx_enabled;
+ bool rx_enabled;
+ struct spi_device *spi;
+
+ struct task_struct *main_thread;
+ struct task_struct *poll_thread;
+
+ wait_queue_head_t wq;
+ atomic_t spi_need_read;
+ atomic_t tty_need_read;
+ atomic_t spi_irq_pending;
+ int mthread_up;
+};
+
+static const char driver_name[] = "hh2serial";
+static const char tty_dev_name[] = "ttyHH2";
+static struct hh2serial_dev priv0;
+
+
+/* max len for a spi transfer is 18B */
+#define HH2SERIAL_SPI_MAX_BYTES 18
+/* 16 bits / byte + read and write gives 4*18 = 72 */
+#define HH2SERIAL_BUFSIZE 72
+
+
+#ifdef HH2SERIAL_SPI_POLL
+#define HH2SERIAL_POLL_TIMEOUT 100
+#endif
+
+/* HH2 DATA OPERATIONS */
+#define GPSD_SRREAD 0x80 /* bit 7 */
+#define GPSD_DWRITE 0x40 /* bit 6 */
+#define GPSD_DREAD 0xC0 /* bit 7 and 6 */
+#define GPSD_CRWRITE 0x00 /* All zero */
+
+#ifdef HH2SERIAL_SPI_16BIT
+/* HH2 DATA OPERATIONS */
+#define GPSD_16BIT_SRREAD 0x8000 /* bit 7 */
+#define GPSD_16BIT_DWRITE 0x4000 /* bit 6 */
+#define GPSD_16BIT_DREAD 0xC000 /* bit 7 and 6 */
+#define GPSD_16BIT_CRWRITE 0x0000 /* All zero */
+#endif
+
+/* HH2 STATUS REGISTER */
+#define GPSS_TCNT 0x1F /* bits [4..0] */
+#define GPSS_REMPTY 0x20 /* bit 5 */
+#define GPSS_TERR 0x40 /* bit 6 */
+#define GPSS_RERR 0x80 /* bit 7 */
+
+/* HH2 CONTROL REGISTER */
+#define GPSC_ENABLE_TCNT_INTR 0x10 /* Enable Rx interrupt */
+#define GPSC_ENABLE_REMPTY_INTR 0x20 /* Enable Tx interrupt */
+#define GPSC_CLEAR_TERR 0x40 /* Clear TERR */
+#define GPSC_CLEAR_RERR 0x80 /* Clear RERR */
+#define GPSC_ENABLE_INTERRUPTS 0x30 /* Enable Interrupts through control register */
+#define GPSC_DISABLE_INTERRUPTS 0x00 /* Disable Interrupts through control register */
+
+
+/* ************************* */
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_stop_tx
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_stop_tx(struct uart_port *port)
+{
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+ FUNC_ENTER();
+ priv->tx_enabled = false;
+}
+
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_spi_get_rx_len
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+#ifndef HH2_NO_SPI
+/* Reads status register from HH2 */
+/* Negative for error */
+int hh2serial_spi_get_rx_len(struct hh2serial_dev *hh2serial)
+{
+ struct spi_device *spi = hh2serial->spi;
+ int ret;
+ struct spi_message message;
+ struct spi_transfer x;
+ u8 *local_buf;
+ u8 *buf_ptr;
+
+ FUNC_ENTER();
+
+ spi_message_init(&message);
+ memset(&x, 0, sizeof x);
+#ifndef HH2SERIAL_SPI_16BIT
+ x.len = 1;
+#else
+ x.len = 2;
+#endif
+ spi_message_add_tail(&x, &message);
+
+ local_buf = kzalloc((x.len * 2), GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+
+
+#ifndef HH2SERIAL_SPI_16BIT
+ local_buf[0] = GPSD_SRREAD;
+#else /* if 16 bit, write control to get status */
+ local_buf[1] = GPSD_CRWRITE;
+ local_buf[0] = GPSC_CLEAR_TERR | GPSC_CLEAR_RERR;
+ /*FIXME if not clearing errors */
+ //local_buf[0] = 0;
+#endif
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf + x.len;
+
+ x.cs_change = 0;
+ x.speed_hz = 1562500;
+
+ /* do the i/o */
+ ret = spi_sync(spi, &message);
+ if (ret == 0)
+ {
+
+ buf_ptr = x.rx_buf;
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial RD:%02X, %02X\n",
+ *buf_ptr,
+ buf_ptr[1]);
+#endif
+
+#ifndef HH2SERIAL_SPI_16BIT
+ /* 8 bit First byte is status register */
+ /* Available bytes */
+ ret = *buf_ptr & GPSS_TCNT;
+
+ /* Check buffer overrun or underrun errors */
+ if (*buf_ptr & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (*buf_ptr & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+
+#else
+ /* 16 bit second byte is status register */
+ /* Available bytes */
+ ret = buf_ptr[1] & GPSS_TCNT;
+
+ /* Check buffer overrun or underrun errors */
+ if (buf_ptr[1] & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (buf_ptr[1] & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#endif
+ /* Take care of errors */
+ /* FIX ME */
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial SR:%02X, rx len %d\n",
+ buf_ptr[1],
+ ret);
+#endif
+ }
+
+ kfree(local_buf);
+ return ret;
+
+}
+#endif
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_spi_read
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+#ifndef HH2_NO_SPI
+/* Reads maximum 18 bytes of data from SPI buffer */
+int hh2serial_spi_read(struct hh2serial_dev *hh2serial,
+ u8 *rxbuf, u8 *spiAvailData, unsigned len)
+{
+ struct spi_device *spi = hh2serial->spi;
+ int status, available_rd;
+ struct spi_message message;
+ struct spi_transfer x;
+ u8 *local_buf;
+ u8 *buf_ptr;
+ unsigned len_inc_hdr;
+
+ FUNC_ENTER();
+ /* FIXME check header */
+ if ((len * 2) > HH2SERIAL_BUFSIZE || !rxbuf)
+ return -EINVAL;
+
+ spi_message_init(&message);
+ memset(&x, 0, sizeof x);
+
+ /* Add header length */
+#ifndef HH2SERIAL_SPI_16BIT
+ len_inc_hdr = len+1;
+#else
+ len_inc_hdr = len;
+#endif
+
+ x.len = len_inc_hdr;
+ spi_message_add_tail(&x, &message);
+
+ local_buf = kzalloc(HH2SERIAL_BUFSIZE, GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+
+ /* Add DATA READ as every second byte */
+ local_buf[1] = GPSD_DREAD;
+#ifdef HH2SERIAL_SPI_16BIT
+ if (len_inc_hdr > 2)
+ {
+ int byte_index = 1;
+ while (byte_index < len_inc_hdr)
+ {
+ local_buf[byte_index] = GPSD_DREAD;
+ byte_index = byte_index + 2;
+ }
+ }
+
+#endif
+
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf + len_inc_hdr;
+
+
+ x.cs_change = 0;
+ x.speed_hz = 1562500;
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ if (len > 0)
+ {
+ int byte_index = 0;
+ printk(KERN_INFO "hh2serial_spi_read:\n:wr data");
+ while (byte_index < len_inc_hdr)
+ {
+ printk(KERN_INFO "%02X", (local_buf[byte_index++]));
+ }
+
+ printk(KERN_INFO "\n");
+
+
+ }
+#endif
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ {
+ /* First byte of read data */
+ buf_ptr = x.rx_buf;
+
+#ifndef HH2SERIAL_SPI_16BIT
+ /* 8 bit First byte is status register */
+ /* Available bytes */
+ available_rd = *buf_ptr & GPSS_TCNT;
+
+ /* Check buffer overrun or underrun errors */
+ if (*buf_ptr & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (*buf_ptr & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#else
+ /* 16 bit second byte is status register */
+ /* Every other byte is status register */
+ /* Last status register contains Available bytes at end of op*/
+ /* This is status before the last byte is read, so -1 */
+ available_rd = (buf_ptr[len_inc_hdr-1] & GPSS_TCNT) - 1;
+
+ /* Check buffer overrun or underrun errors */
+ if (buf_ptr[len_inc_hdr-1] & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (buf_ptr[len_inc_hdr-1] & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#endif
+
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial_spi_read len inc hdr wr:%d, avail rd %d, cs_change:%d\n",
+ len_inc_hdr,
+ available_rd,
+ x.cs_change);
+ printk(KERN_INFO "hh2serial_spi_read:%02X, %02X\n",
+ *buf_ptr,
+ buf_ptr[1]);
+
+#endif
+
+ /* Don't copy status byte */
+#ifndef HH2SERIAL_SPI_16BIT
+ buf_ptr++;
+#endif
+
+ *spiAvailData = available_rd;
+ memcpy(rxbuf, buf_ptr, len);
+
+ /* Print incoming message */
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ if (len > 0)
+ {
+ int byte_index = 0;
+ printk(KERN_INFO "hh2serial_spi_read:\n:rd data");
+ while (byte_index < len)
+ {
+ printk(KERN_INFO "%02X", (rxbuf[byte_index++]));
+ }
+ printk(KERN_INFO "\n");
+
+ }
+#endif
+
+ }
+
+ kfree(local_buf);
+ return status;
+}
+#endif
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_spi_write
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+#ifndef HH2_NO_SPI
+int hh2serial_spi_write(struct hh2serial_dev *hh2serial,
+ const u8 *txbuf, u8 *spiAvailData, unsigned len)
+{
+ struct spi_device *spi = hh2serial->spi;
+ int status, available_rd;
+ struct spi_message message;
+ struct spi_transfer x;
+ u8 *local_buf;
+ u8 *buf_ptr;
+ unsigned len_inc_hdr;
+
+ FUNC_ENTER();
+
+ if ((len * 2) > HH2SERIAL_BUFSIZE )
+ return -EINVAL;
+
+
+ spi_message_init(&message);
+ memset(&x, 0, sizeof x);
+
+ /* Add header length */
+#ifndef HH2SERIAL_SPI_16BIT
+ len_inc_hdr = len+1;
+#else
+ len_inc_hdr = len;
+#endif
+
+ x.len = len_inc_hdr;
+ spi_message_add_tail(&x, &message);
+
+ /* Allocate and make room for 1 byte header */
+ local_buf = kzalloc(HH2SERIAL_BUFSIZE+1, GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+
+ /* Add write header */
+ local_buf[1] = GPSD_DWRITE;
+ local_buf[0] = txbuf[0];
+
+
+#ifndef HH2SERIAL_SPI_16BIT
+ memcpy(&(local_buf[1]), txbuf, len);
+#else
+ if (len_inc_hdr > 2)
+ {
+ int byte_index = 2;
+ while (byte_index < len_inc_hdr)
+ {
+
+ local_buf[byte_index] = txbuf[byte_index];
+ local_buf[byte_index+1] = GPSD_DWRITE;
+ byte_index = byte_index + 2;
+ }
+ }
+#endif
+
+ x.tx_buf = local_buf;
+ x.rx_buf = local_buf +(len_inc_hdr);
+
+ x.cs_change = 0;
+ x.speed_hz = 1562500;
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ if (len > 0)
+ {
+ int byte_index = 0;
+ printk(KERN_INFO "hh2serial_spi_write:\n:wr data");
+ while (byte_index < len_inc_hdr)
+ {
+ printk(KERN_INFO "%02X", (local_buf[byte_index++]));
+ }
+ printk(KERN_INFO "\n");
+
+
+ }
+#endif
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ {
+ /* read data */
+ buf_ptr = x.rx_buf;
+
+#ifndef HH2SERIAL_SPI_16BIT
+ /* 8 bit First byte is status register */
+ /* Available bytes */
+ available_rd = *buf_ptr & GPSS_TCNT;
+
+ /* Check buffer overrun or underrun errors */
+ if (*buf_ptr & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (*buf_ptr & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#else
+ /* 16 bit second byte is status register */
+ /* Available bytes */
+ available_rd = buf_ptr[1] & GPSS_TCNT;
+
+ /* Check buffer overrun or underrun errors */
+ if (buf_ptr[1] & GPSS_TERR)
+ printk(KERN_INFO "hh2serial HH2 transmitter underrun!\n");
+
+ if (buf_ptr[1] & GPSS_RERR)
+ printk(KERN_INFO "hh2serial HH2 receiver overrun!\n");
+#endif
+
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial_spi_write:%02X, %02X\n",
+ *buf_ptr,
+ buf_ptr[1]);
+
+ printk(KERN_INFO "hh2serial_spi_write: wr:%d, avail rd %d\n",
+ len,
+ available_rd);
+#endif
+
+ *spiAvailData = available_rd;
+
+
+ }
+
+
+
+ kfree(local_buf);
+ return status;
+}
+#endif
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_write2tty
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_write2tty(
+ struct hh2serial_dev *priv, unsigned char *str, int len)
+{
+ struct uart_port *port = &priv->port;
+ struct tty_struct *tty;
+ int usable;
+
+ FUNC_ENTER();
+
+ /* if uart is not opened, will just return */
+ if (!port->state)
+ return;
+
+ tty = port->state->port.tty;
+ if (!tty)
+ return; /* receive some char before the tty is opened */
+
+ /* MRB could lock forever if no space in tty buffer */
+ while (len) {
+ usable = tty_buffer_request_room(tty, len);
+ if (usable) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial_output_tty buf space: %d\n", usable);
+#endif
+ tty_insert_flip_string(tty, str, usable);
+ str += usable;
+ port->icount.rx += usable;
+ tty_flip_buffer_push(tty);
+ }
+ len -= usable;
+ }
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_write_circ_buf2spi
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+#ifndef HH2_NO_SPI
+static inline void hh2serial_write_circ_buf2spi(struct hh2serial_dev *priv,
+ struct circ_buf *xmit)
+{
+ int len, left = 0;
+#ifndef HH2SERIAL_SPI_16BIT
+ u8 obuf[HH2SERIAL_SPI_MAX_BYTES], ibuf[HH2SERIAL_SPI_MAX_BYTES];
+#else
+ u16 obuf[HH2SERIAL_SPI_MAX_BYTES], ibuf[HH2SERIAL_SPI_MAX_BYTES];
+#endif
+ u8 rxlen;
+ u8 valid_str[HH2SERIAL_SPI_MAX_BYTES];
+
+ int i, j;
+
+ FUNC_ENTER();
+
+ while (!uart_circ_empty(xmit)) {
+ /*
+ printk(KERN_INFO "MrB set CR get SR: %d\n",
+ hh2serial_spi_get_rx_len(priv));
+ */
+
+ left = uart_circ_chars_pending(xmit);
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "Bytes in circ buffer: %d\n", left);
+#endif
+ while (left) {
+ /* MrB Change below to 1 and word length to 16 to write 16 bit
+ word by word */
+#ifndef HH2SERIAL_SPI_16BIT
+ len = (left >= HH2SERIAL_SPI_MAX_BYTES) ? HH2SERIAL_SPI_MAX_BYTES : left;
+#else
+ len = (left >= HH2SERIAL_SPI_MAX_BYTES) ? HH2SERIAL_SPI_MAX_BYTES : left;
+#endif
+
+ memset(obuf, 0, len);
+ memset(ibuf, 0, len);
+ for (i = 0; i < len; i++) {
+
+ obuf[i] = (u8)xmit->buf[xmit->tail];
+
+ xmit->tail = (xmit->tail + 1) &
+ (UART_XMIT_SIZE - 1);
+ }
+#ifndef HH2SERIAL_SPI_16BIT
+
+ hh2serial_spi_write(priv, (u8 *)obuf,
+ &rxlen, len);
+
+#else
+ /* len * 2 since 16 bits instead of 8 bits */
+ hh2serial_spi_write(priv, (u8 *)obuf,
+ &rxlen, len*2);
+
+#endif
+ left -= len;
+ }
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: Bytes avail to read: %d\n", rxlen);
+#endif
+ /* Read if available bytes */
+ /* FIXME: Could add a maximum read loop here */
+ while (rxlen > 0)
+ {
+
+ len = rxlen;
+#ifndef HH2SERIAL_SPI_16BIT
+ hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len);
+#else
+ hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len*2);
+#endif
+
+ for (i = 0, j = 0; i < len; i++) {
+ valid_str[j++] = (u8)(ibuf[i]);
+ }
+
+ if (j)
+ hh2serial_write2tty(priv, valid_str, j);
+
+ priv->port.icount.tx += len;
+ }
+ }
+}
+#endif
+
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_handle_tty_input
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_handle_tty_input(struct hh2serial_dev *priv)
+{
+ struct uart_port *port = &priv->port;
+ struct circ_buf *xmit = &port->state->xmit;
+
+ FUNC_ENTER();
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ return;
+#ifndef HH2_NO_SPI
+ hh2serial_write_circ_buf2spi(priv, xmit);
+#endif
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ hh2serial_stop_tx(port);
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_transfer_spi2tty
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_transfer_spi2tty(struct hh2serial_dev *priv)
+{
+ int loop = 10, len;
+ int i, j;
+ u8 valid_str[HH2SERIAL_SPI_MAX_BYTES], rxlen = 0;
+#ifndef HH2SERIAL_SPI_16BIT
+ u8 ibuf[HH2SERIAL_SPI_MAX_BYTES];
+#else
+ u16 ibuf[HH2SERIAL_SPI_MAX_BYTES];
+#endif
+
+ FUNC_ENTER();
+
+ rxlen = hh2serial_spi_get_rx_len(priv);
+
+ /* FIXME No of loops to be investigated */
+ while (rxlen > 0 && loop > 0)
+ {
+
+ len = rxlen;
+#ifndef HH2SERIAL_SPI_16BIT
+ hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len);
+#else
+ hh2serial_spi_read(priv, (u8 *)ibuf, &rxlen, len*2);
+#endif
+
+ for (i = 0, j = 0; i < len; i++) {
+ valid_str[j++] = (u8)(ibuf[i]);
+ }
+
+ if (j)
+ hh2serial_write2tty(priv, valid_str, j);
+
+ priv->port.icount.tx += len;
+
+ loop--;
+ }
+
+}
+
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_main_thread
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int hh2serial_main_thread(void *_priv)
+{
+ struct hh2serial_dev *priv = _priv;
+ wait_queue_head_t *wq = &priv->wq;
+
+ int ret = 0;
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: start main thread\n");
+#endif
+ init_waitqueue_head(wq);
+
+ do {
+ //udelay(delay);
+ wait_event_interruptible(*wq, (atomic_read(&priv->spi_irq_pending) ||
+ atomic_read(&priv->spi_need_read) ||
+ atomic_read(&priv->tty_need_read) ||
+ kthread_should_stop()));
+
+ priv->mthread_up = 1;
+
+ /* tty has data to be read */
+ if (atomic_read(&priv->tty_need_read)) {
+ atomic_set(&priv->tty_need_read, 0);
+ /* Read from tty send to spi */
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: Read from tty send to spi\n");
+#endif
+ /* Read from tty send to spi */
+ /* Receive data from spi send to UART */
+
+ hh2serial_handle_tty_input(priv);
+
+ }
+
+#ifdef HH2SERIAL_SPI_POLL
+ if (atomic_read(&priv->spi_need_read)) {
+ atomic_set(&priv->spi_need_read, 0);
+ /* Read from SPI send to UART */
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: Read from SPI send to UART\n");
+#endif
+#ifndef HH2_TTY_SEND_POLL
+ hh2serial_transfer_spi2tty(priv);
+#else
+ if (priv->tx_enabled) {
+ struct uart_port *port = &priv->port;
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("TX enabled!\n");
+#endif
+ spin_lock_irqsave(&port->lock, flags);
+
+
+ if (priv->rx_enabled) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "RX enabled!\n");
+#endif
+ hh2serial_write2tty(priv, "testar", 6);
+ }
+
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+#endif /* HH2_TTY_SEND_POLL */
+
+ }
+#endif
+
+
+
+ if (atomic_read(&priv->spi_irq_pending)) {
+ atomic_set(&priv->spi_irq_pending, 0);
+ /* Read from SPI send to UART */
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: Read from SPI send to UART\n");
+#endif
+ }
+
+
+ priv->mthread_up = 0;
+ } while (!kthread_should_stop());
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: stopped main thread\n");
+#endif
+ return ret;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_poll_thread
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+#ifdef HH2SERIAL_SPI_POLL
+static int hh2serial_poll_thread(void *_priv)
+{
+
+ int ret = 0;
+ struct hh2serial_dev *priv = _priv;
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: start poll thread\n");
+#endif
+ do {
+ //udelay(delay);
+
+ if (HH2SERIAL_POLL_TIMEOUT > 999)
+ ssleep(HH2SERIAL_POLL_TIMEOUT/1000);
+ else
+ msleep(HH2SERIAL_POLL_TIMEOUT);
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: poll\n");
+#endif
+ if (!priv->mthread_up)
+ {
+ /* Send poll event to main */
+ if (!atomic_read(&priv->spi_need_read)) {
+ atomic_set(&priv->spi_need_read, 1);
+ wake_up_process(priv->main_thread);
+ }
+ }
+
+ } while (!kthread_should_stop());
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk(KERN_INFO "hh2serial: stopped poll thread\n");
+#endif
+ return ret;
+}
+#endif /* #ifdef HH2SERIAL_SPI_POLL */
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_tx_empty
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static unsigned int hh2serial_tx_empty(struct uart_port *port)
+{
+ FUNC_ENTER();
+ return TIOCSER_TEMT;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_set_mctrl
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ FUNC_ENTER();
+
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("MCTRL RTS: %d\n", mctrl & TIOCM_RTS);
+ printk("MCTRL DTR: %d\n", mctrl & TIOCM_DTR);
+ printk("MCTRL OUT1: %d\n", mctrl & TIOCM_OUT1);
+ printk("MCTRL OUT2: %d\n", mctrl & TIOCM_OUT2);
+ printk("MCTRL LOOP: %d\n", mctrl & TIOCM_LOOP);
+#endif
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_get_mctrl
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static unsigned int hh2serial_get_mctrl(struct uart_port *port)
+{
+ FUNC_ENTER();
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_tx_chars
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_tx_chars(struct uart_port *port)
+{
+#ifndef HH2_TTY_ECHO
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+
+ FUNC_ENTER();
+
+ if (priv->tx_enabled) {
+
+ /* if writing to SPI enabled */
+
+ /* Send message to main thread to read from tty send to SPI */
+ /* Send poll event to main */
+ if (!atomic_read(&priv->tty_need_read)) {
+ atomic_set(&priv->tty_need_read, 1);
+ wake_up_process(priv->main_thread);
+ }
+
+
+ }
+
+#else
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+ struct circ_buf *xmit = &port->state->xmit;
+
+
+
+ struct uart_port *recv_port = &priv->port;
+ struct tty_struct *recv_tty;
+
+ unsigned long flags;
+ char ch;
+
+ FUNC_ENTER();
+
+ if (priv->tx_enabled) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("TX enabled!\n");
+#endif
+ //spin_lock_irqsave(&other_port->lock, flags);
+ if (priv->rx_enabled) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("RX enabled!\n");
+#endif
+
+ recv_tty = recv_port->state->port.tty;
+
+ if (port->x_char) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("One char %c!\n", port->x_char);
+#endif
+ tty_insert_flip_char(recv_tty, port->x_char, TTY_NORMAL);
+ tty_flip_buffer_push(recv_tty);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ pr_debug("STOP TX_CHARS 1\n");
+#endif
+ hh2serial_stop_tx(port);
+ return;
+ }
+
+ while (!uart_circ_empty(xmit)) {
+
+ ch = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("Loop one char %c!\n", ch);
+#endif
+ tty_insert_flip_char(recv_tty, ch, TTY_NORMAL);
+ tty_flip_buffer_push(recv_tty);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("Uart wakeup!\n");
+#endif
+ uart_write_wakeup(port);
+ }
+
+ if (uart_circ_empty(xmit)) {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ pr_debug("STOP TX_CHARS 2\n");
+#endif
+ hh2serial_stop_tx(port);
+ }
+ }
+ else
+ {
+#ifdef HH2SERIAL_ENABLE_DEBUG
+ printk("Other port disabled!\n");
+#endif
+ }
+ //spin_unlock_irqrestore(&priv->other_priv->port.lock, flags);
+ }
+
+#endif
+
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_start_tx
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_start_tx(struct uart_port *port)
+{
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+ FUNC_ENTER();
+ priv->tx_enabled = true;
+
+ hh2serial_tx_chars(port);
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_stop_rx
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_stop_rx(struct uart_port *port)
+{
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+ FUNC_ENTER();
+ priv->rx_enabled = false;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_enable_ms
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_enable_ms(struct uart_port *port)
+{
+ FUNC_ENTER();
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_break_ctl
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_break_ctl(struct uart_port *port, int break_state)
+{
+ FUNC_ENTER();
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_startup
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int hh2serial_startup(struct uart_port *port)
+{
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+ FUNC_ENTER();
+
+#ifdef HH2SERIAL_SPI_POLL
+ priv->poll_thread = kthread_run(hh2serial_poll_thread,
+ priv, "hh2serial_poll");
+ if (IS_ERR(priv->poll_thread)) {
+ printk(KERN_INFO "hh2serial Failed to start poll thread: %ld",
+ PTR_ERR(priv->poll_thread));
+ }
+#endif
+
+ spin_lock(&port->lock);
+ priv->rx_enabled = true;
+ spin_unlock(&port->lock);
+ return 0;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_shutdown
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_shutdown(struct uart_port *port)
+{
+#ifdef HH2SERIAL_SPI_POLL
+ struct hh2serial_dev *priv = container_of(port, struct hh2serial_dev, port);
+#endif
+ FUNC_ENTER();
+#ifdef HH2SERIAL_SPI_POLL
+ if (priv->poll_thread)
+ kthread_stop(priv->poll_thread);
+#endif
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_set_termios
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ FUNC_ENTER();
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ pr_debug("CS5: data bits 5\n");
+ break;
+ case CS6:
+ pr_debug("CS6: data bits 6\n");
+ break;
+ case CS7:
+ pr_debug("CS7: data bits 7\n");
+ break;
+ case CS8:
+ pr_debug("CS8: data bits 8\n");
+ break;
+ default:
+ pr_debug("CS: Unknown\n");
+ break;
+ }
+
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & PARODD)
+ pr_debug("PARITY ODD\n");
+ else
+ pr_debug("PARITY EVEN\n");
+ } else {
+ pr_debug("PARITY NONE\n");
+ }
+
+ if (termios->c_cflag & CSTOPB)
+ pr_debug("STOP BITS 2\n");
+ else
+ pr_debug("STOP BITS 1\n");
+
+ if (termios->c_cflag & CRTSCTS)
+ pr_debug("RTS CTS ENABLED\n");
+ else
+ pr_debug("RTS CTS DISABLED\n");
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_type
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static const char *hh2serial_type(struct uart_port *port)
+{
+ FUNC_ENTER();
+ return "VUART";
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_request_port
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int hh2serial_request_port(struct uart_port *port)
+{
+ FUNC_ENTER();
+ return 0;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_config_port
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_config_port(struct uart_port *port, int flags)
+{
+ FUNC_ENTER();
+
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_16550A;
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_release_port
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void hh2serial_release_port(struct uart_port *port)
+{
+ FUNC_ENTER();
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_verify_port
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int hh2serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ FUNC_ENTER();
+ return 0;
+}
+
+static struct uart_ops hh2serial_uart_ops = {
+ .tx_empty = hh2serial_tx_empty,
+ .set_mctrl = hh2serial_set_mctrl,
+ .get_mctrl = hh2serial_get_mctrl,
+ .stop_tx = hh2serial_stop_tx,
+ .start_tx = hh2serial_start_tx,
+ .stop_rx = hh2serial_stop_rx,
+ .enable_ms = hh2serial_enable_ms,
+ .break_ctl = hh2serial_break_ctl,
+ .startup = hh2serial_startup,
+ .shutdown = hh2serial_shutdown,
+ .set_termios = hh2serial_set_termios,
+ .type = hh2serial_type,
+ .release_port = hh2serial_release_port,
+ .request_port = hh2serial_request_port,
+ .config_port = hh2serial_config_port,
+ .verify_port = hh2serial_verify_port,
+};
+
+#ifndef HH2_NO_SPI
+/* pure SPI related functions */
+/*******************************************************************************
+ * FUNCTION: serial_hh2serial_suspend
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int serial_hh2serial_suspend(struct spi_device *spi, pm_message_t state)
+{
+ FUNC_ENTER();
+ return 0;
+}
+
+/*******************************************************************************
+ * FUNCTION: serial_hh2serial_resume
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int serial_hh2serial_resume(struct spi_device *spi)
+{
+ FUNC_ENTER();
+ return 0;
+}
+
+
+static struct mrst_spi_chip hh2spi0 = {
+ .poll_mode = 1,
+ .enable_dma = 0,
+ .type = SPI_FRF_SPI,
+};
+
+
+/*******************************************************************************
+ * FUNCTION: serial_hh2serial_probe
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int serial_hh2serial_probe(struct spi_device *spi)
+{
+ FUNC_ENTER();
+#ifndef HH2_NO_SPI
+
+ /* set spi info */
+ spi->mode = SPI_MODE_0;
+#ifndef HH2SERIAL_SPI_16BIT
+ spi->bits_per_word = 8; /* HH2 uses 8 bits */
+#else
+ spi->bits_per_word = 16; /* HH2 uses 8 bits, test with 16, sends byte by byte */
+#endif
+
+ spi->controller_data = &hh2spi0;
+
+ spi_setup(spi);
+ priv0.spi = spi;
+ atomic_set(&priv0.spi_irq_pending, 0);
+#endif
+
+
+ return 0;
+
+
+}
+
+/*******************************************************************************
+ * FUNCTION: hh2serial_remove
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int hh2serial_remove(struct spi_device *dev)
+{
+ FUNC_ENTER();
+
+ return 0;
+}
+
+
+static struct spi_driver spi_hh2serial_driver = {
+ .driver = {
+ .name = "spi_ifx_gps",
+ //.name = "spi_flash",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = serial_hh2serial_probe,
+ .remove = __devexit_p(hh2serial_remove),
+ .suspend = serial_hh2serial_suspend,
+ .resume = serial_hh2serial_resume,
+};
+
+#endif
+
+static struct uart_driver hh2serial_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = driver_name,
+ .dev_name = tty_dev_name,
+ .major = 240,
+ .minor = 0,
+ .nr = 1,
+};
+
+/*******************************************************************************
+ * FUNCTION: __init
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static int __init
+hh2serial_init (void)
+{
+ int ret;
+
+ ret = uart_register_driver(&hh2serial_driver);
+
+ if (ret) {
+ pr_err("%s: could not register UART driver\n", driver_name);
+ goto out_register_driver;
+ }
+
+ memset(&priv0, sizeof(struct hh2serial_dev), 0);
+ priv0.port.line = 0;
+ priv0.port.ops = &hh2serial_uart_ops;
+ priv0.port.type = PORT_16550A;
+ spin_lock_init(&priv0.port.lock);
+
+ ret = uart_add_one_port(&hh2serial_driver, &priv0.port);
+
+ if (ret) {
+ pr_err("%s: could not add port hh2serial0\n", driver_name);
+ goto out_add_port0;
+ }
+
+ atomic_set(&priv0.spi_need_read, 0);
+ atomic_set(&priv0.tty_need_read, 0);
+ atomic_set(&priv0.spi_irq_pending, 0);
+
+
+
+#ifndef HH2_NO_SPI
+ /* Register SPI device driver*/
+ ret = spi_register_driver(&spi_hh2serial_driver);
+ if (ret)
+ {
+ pr_err("%s: could not register driver spi_hh2serial_driver\n", driver_name);
+ goto out_add_spi;
+ }
+#endif
+
+
+ priv0.main_thread = kthread_run(hh2serial_main_thread,
+ &priv0, "hh2serial_main");
+ if (IS_ERR(priv0.main_thread)) {
+ ret = PTR_ERR(priv0.main_thread);
+ goto err_kthread;
+ }
+
+
+
+ printk ("Module %s loaded\n", driver_name);
+ return 0;
+
+err_kthread:
+
+#ifndef HH2_NO_SPI
+out_add_spi:
+ uart_remove_one_port(&hh2serial_driver, &priv0.port);
+#endif
+out_add_port0:
+ uart_unregister_driver(&hh2serial_driver);
+out_register_driver:
+ return ret;
+}
+
+/*******************************************************************************
+ * FUNCTION: __exit
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ ******************************************************************************/
+static void __exit
+hh2serial_exit (void)
+{
+ if (priv0.main_thread)
+ kthread_stop(priv0.main_thread);
+
+#ifndef HH2_NO_SPI
+ /* unregister SPI driver */
+ spi_unregister_driver(&spi_hh2serial_driver);
+#endif
+ uart_remove_one_port(&hh2serial_driver, &priv0.port);
+
+ uart_unregister_driver(&hh2serial_driver);
+ printk ("Module %s removed\n", driver_name);
+}
+
+
+
+module_init(hh2serial_init);
+module_exit(hh2serial_exit);
Index: linux-2.6.33/drivers/misc/intel_mrst.c
===================================================================
--- linux-2.6.33.orig/drivers/misc/intel_mrst.c
+++ linux-2.6.33/drivers/misc/intel_mrst.c
@@ -131,9 +131,11 @@ static int intel_mrst_bringup_8688_sdio2
{
unsigned int temp = 0;
- /* Register 0xf4 has 2 GPIO lines connected to the MRVL 8688:
+ /* Register 0xf4 has 4 GPIO lines connected to the MRVL 8688 * IFX GPS:
* bit 4: PDn
- * bit 3: WiFi RESETn */
+ * bit 3: WiFi RESETn
+ * bit 2: GPS RESET_N
+ * bit 1: GPS PD_N*/
intel_mrst_pmic_read(0xf4, &temp);
temp = temp|0x8;
@@ -142,6 +144,12 @@ static int intel_mrst_bringup_8688_sdio2
temp = temp|0x10;
intel_mrst_pmic_write(0xf4, temp);
+ temp = temp|0x04;
+ intel_mrst_pmic_write(0xf4, temp);
+
+ temp = temp|0x02;
+ intel_mrst_pmic_write(0xf4, temp);
+
return 0;
}
@@ -187,10 +195,10 @@ static int __init intel_mrst_module_init
/* We only need the following PMIC register initializations if
* we are using the Marvell 8688 WLAN card on the SDIO2 port */
-#ifdef CONFIG_8688_RC
+#if defined(CONFIG_8688_RC) || defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_SPI_IFX_GPS)
printk(KERN_INFO "intel_mrst_module_init: bringing up power for "
- "8688 WLAN on SDIO2...\n");
+ "8688 WLAN on SDIO2 & IFX GPS over SPI...\n");
ret = intel_mrst_bringup_8688_sdio2();
#endif /* CONFIG_8688_RC */