From patchwork Fri Jan 22 11:44:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Shevchenko X-Patchwork-Id: 369132 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB423C433DB for ; Fri, 22 Jan 2021 11:47:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7A14222CA1 for ; Fri, 22 Jan 2021 11:47:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727350AbhAVLrI (ORCPT ); Fri, 22 Jan 2021 06:47:08 -0500 Received: from mga12.intel.com ([192.55.52.136]:8555 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727559AbhAVLqx (ORCPT ); Fri, 22 Jan 2021 06:46:53 -0500 IronPort-SDR: XKdb2JLhEtk+EUWK/FTR15ls7sHiqjWPsTb0lGnbuHxFPCBZdMBVzS1I3SDq4lE0m4iTNQNyuV 0E10U0wHtrcQ== X-IronPort-AV: E=McAfee;i="6000,8403,9871"; a="158613359" X-IronPort-AV: E=Sophos;i="5.79,366,1602572400"; d="scan'208";a="158613359" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2021 03:44:49 -0800 IronPort-SDR: 8x4W5KnpUi//EEHwKeN0HAzvqMHb4ZxtrRk8bXLo4ZbgFW7XSRgYWefqazveEleU8da9YDXvQj tsM1oeXc+TwQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,366,1602572400"; d="scan'208";a="351826680" Received: from black.fi.intel.com ([10.237.72.28]) by orsmga003.jf.intel.com with ESMTP; 22 Jan 2021 03:44:47 -0800 Received: by black.fi.intel.com (Postfix, from userid 1003) id ACA5F14F; Fri, 22 Jan 2021 13:44:46 +0200 (EET) From: Andy Shevchenko To: Greg Kroah-Hartman , linux-serial@vger.kernel.org Cc: Andy Shevchenko , Linus Walleij Subject: [PATCH v1] serial: ifx6x60: Remove driver for deprecated platform Date: Fri, 22 Jan 2021 13:44:46 +0200 Message-Id: <20210122114446.39675-1-andriy.shevchenko@linux.intel.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org Intel Moorestown and Medfield are quite old Intel Atom based 32-bit platforms, which were in limited use in some Android phones, tablets and consumer electronics more than eight years ago. There are no bugs or problems ever reported outside from Intel for breaking any of that platforms for years. It seems no real users exists who run more or less fresh kernel on it. The commit 05f4434bc130 ("ASoC: Intel: remove mfld_machine") also in align with this theory. Due to above and to reduce a burden of supporting outdated drivers we remove the support of outdated platforms completely. Signed-off-by: Andy Shevchenko Acked-by: Linus Walleij --- drivers/tty/serial/Kconfig | 7 - drivers/tty/serial/Makefile | 1 - drivers/tty/serial/ifx6x60.c | 1387 ---------------------------------- drivers/tty/serial/ifx6x60.h | 118 --- 4 files changed, 1513 deletions(-) delete mode 100644 drivers/tty/serial/ifx6x60.c delete mode 100644 drivers/tty/serial/ifx6x60.h diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 22e86ba4f827..0c4cd4a348f4 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1182,13 +1182,6 @@ config SERIAL_ALTERA_UART_CONSOLE help Enable a Altera UART port to be the system console. -config SERIAL_IFX6X60 - tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" - depends on GPIOLIB || COMPILE_TEST - depends on SPI && HAS_DMA - help - Support for the IFX6x60 modem devices on Intel MID platforms. - config SERIAL_PCH_UART tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART" depends on PCI && (X86_32 || MIPS || COMPILE_TEST) diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 931dc1d6885e..7da0856cd198 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o -obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c deleted file mode 100644 index d4ef88ee22d0..000000000000 --- a/drivers/tty/serial/ifx6x60.c +++ /dev/null @@ -1,1387 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/**************************************************************************** - * - * Driver for the IFX 6x60 spi modem. - * - * Copyright (C) 2008 Option International - * Copyright (C) 2008 Filip Aben - * Denis Joseph Barrow - * Jan Dumon - * - * Copyright (C) 2009, 2010 Intel Corp - * Russ Gorby - * - * Driver modified by Intel from Option gtm501l_spi.c - * - * Notes - * o The driver currently assumes a single device only. If you need to - * change this then look for saved_ifx_dev and add a device lookup - * o The driver is intended to be big-endian safe but has never been - * tested that way (no suitable hardware). There are a couple of FIXME - * notes by areas that may need addressing - * o Some of the GPIO naming/setup assumptions may need revisiting if - * you need to use this driver for another platform. - * - *****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ifx6x60.h" - -#define IFX_SPI_MORE_MASK 0x10 -#define IFX_SPI_MORE_BIT 4 /* bit position in u8 */ -#define IFX_SPI_CTS_BIT 6 /* bit position in u8 */ -#define IFX_SPI_MODE SPI_MODE_1 -#define IFX_SPI_TTY_ID 0 -#define IFX_SPI_TIMEOUT_SEC 2 -#define IFX_SPI_HEADER_0 (-1) -#define IFX_SPI_HEADER_F (-2) - -#define PO_POST_DELAY 200 - -/* forward reference */ -static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); -static int ifx_modem_reboot_callback(struct notifier_block *nfb, - unsigned long event, void *data); -static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev); - -/* local variables */ -static int spi_bpw = 16; /* 8, 16 or 32 bit word length */ -static struct tty_driver *tty_drv; -static struct ifx_spi_device *saved_ifx_dev; -static struct lock_class_key ifx_spi_key; - -static struct notifier_block ifx_modem_reboot_notifier_block = { - .notifier_call = ifx_modem_reboot_callback, -}; - -static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev) -{ - gpiod_set_value(ifx_dev->gpio.pmu_reset, 1); - msleep(PO_POST_DELAY); - - return 0; -} - -static int ifx_modem_reboot_callback(struct notifier_block *nfb, - unsigned long event, void *data) -{ - if (saved_ifx_dev) - ifx_modem_power_off(saved_ifx_dev); - else - pr_warn("no ifx modem active;\n"); - - return NOTIFY_OK; -} - -/* GPIO/GPE settings */ - -/** - * mrdy_set_high - set MRDY GPIO - * @ifx: device we are controlling - * - */ -static inline void mrdy_set_high(struct ifx_spi_device *ifx) -{ - gpiod_set_value(ifx->gpio.mrdy, 1); -} - -/** - * mrdy_set_low - clear MRDY GPIO - * @ifx: device we are controlling - * - */ -static inline void mrdy_set_low(struct ifx_spi_device *ifx) -{ - gpiod_set_value(ifx->gpio.mrdy, 0); -} - -/** - * ifx_spi_power_state_set - * @ifx_dev: our SPI device - * @val: bits to set - * - * Set bit in power status and signal power system if status becomes non-0 - */ -static void -ifx_spi_power_state_set(struct ifx_spi_device *ifx_dev, unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&ifx_dev->power_lock, flags); - - /* - * if power status is already non-0, just update, else - * tell power system - */ - if (!ifx_dev->power_status) - pm_runtime_get(&ifx_dev->spi_dev->dev); - ifx_dev->power_status |= val; - - spin_unlock_irqrestore(&ifx_dev->power_lock, flags); -} - -/** - * ifx_spi_power_state_clear - clear power bit - * @ifx_dev: our SPI device - * @val: bits to clear - * - * clear bit in power status and signal power system if status becomes 0 - */ -static void -ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&ifx_dev->power_lock, flags); - - if (ifx_dev->power_status) { - ifx_dev->power_status &= ~val; - if (!ifx_dev->power_status) - pm_runtime_put(&ifx_dev->spi_dev->dev); - } - - spin_unlock_irqrestore(&ifx_dev->power_lock, flags); -} - -/** - * swap_buf_8 - * @buf: our buffer - * @len : number of bytes (not words) in the buffer - * @end: end of buffer - * - * Swap the contents of a buffer into big endian format - */ -static inline void swap_buf_8(unsigned char *buf, int len, void *end) -{ - /* don't swap buffer if SPI word width is 8 bits */ - return; -} - -/** - * swap_buf_16 - * @buf: our buffer - * @len : number of bytes (not words) in the buffer - * @end: end of buffer - * - * Swap the contents of a buffer into big endian format - */ -static inline void swap_buf_16(unsigned char *buf, int len, void *end) -{ - int n; - - u16 *buf_16 = (u16 *)buf; - len = ((len + 1) >> 1); - if ((void *)&buf_16[len] > end) { - pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!", - &buf_16[len], end); - return; - } - for (n = 0; n < len; n++) { - *buf_16 = cpu_to_be16(*buf_16); - buf_16++; - } -} - -/** - * swap_buf_32 - * @buf: our buffer - * @len : number of bytes (not words) in the buffer - * @end: end of buffer - * - * Swap the contents of a buffer into big endian format - */ -static inline void swap_buf_32(unsigned char *buf, int len, void *end) -{ - int n; - - u32 *buf_32 = (u32 *)buf; - len = (len + 3) >> 2; - - if ((void *)&buf_32[len] > end) { - pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n", - &buf_32[len], end); - return; - } - for (n = 0; n < len; n++) { - *buf_32 = cpu_to_be32(*buf_32); - buf_32++; - } -} - -/** - * mrdy_assert - assert MRDY line - * @ifx_dev: our SPI device - * - * Assert mrdy and set timer to wait for SRDY interrupt, if SRDY is low - * now. - * - * FIXME: Can SRDY even go high as we are running this code ? - */ -static void mrdy_assert(struct ifx_spi_device *ifx_dev) -{ - int val = gpiod_get_value(ifx_dev->gpio.srdy); - if (!val) { - if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING, - &ifx_dev->flags)) { - mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ); - - } - } - ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING); - mrdy_set_high(ifx_dev); -} - -/** - * ifx_spi_timeout - SPI timeout - * @t: timer in our SPI device - * - * The SPI has timed out: hang up the tty. Users will then see a hangup - * and error events. - */ -static void ifx_spi_timeout(struct timer_list *t) -{ - struct ifx_spi_device *ifx_dev = from_timer(ifx_dev, t, spi_timer); - - dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***"); - tty_port_tty_hangup(&ifx_dev->tty_port, false); - mrdy_set_low(ifx_dev); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); -} - -/* char/tty operations */ - -/** - * ifx_spi_tiocmget - get modem lines - * @tty: our tty device - * - * Map the signal state into Linux modem flags and report the value - * in Linux terms - */ -static int ifx_spi_tiocmget(struct tty_struct *tty) -{ - unsigned int value; - struct ifx_spi_device *ifx_dev = tty->driver_data; - - value = - (test_bit(IFX_SPI_RTS, &ifx_dev->signal_state) ? TIOCM_RTS : 0) | - (test_bit(IFX_SPI_DTR, &ifx_dev->signal_state) ? TIOCM_DTR : 0) | - (test_bit(IFX_SPI_CTS, &ifx_dev->signal_state) ? TIOCM_CTS : 0) | - (test_bit(IFX_SPI_DSR, &ifx_dev->signal_state) ? TIOCM_DSR : 0) | - (test_bit(IFX_SPI_DCD, &ifx_dev->signal_state) ? TIOCM_CAR : 0) | - (test_bit(IFX_SPI_RI, &ifx_dev->signal_state) ? TIOCM_RNG : 0); - return value; -} - -/** - * ifx_spi_tiocmset - set modem bits - * @tty: the tty structure - * @set: bits to set - * @clear: bits to clear - * - * The IFX6x60 only supports DTR and RTS. Set them accordingly - * and flag that an update to the modem is needed. - * - * FIXME: do we need to kick the tranfers when we do this ? - */ -static int ifx_spi_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - - if (set & TIOCM_RTS) - set_bit(IFX_SPI_RTS, &ifx_dev->signal_state); - if (set & TIOCM_DTR) - set_bit(IFX_SPI_DTR, &ifx_dev->signal_state); - if (clear & TIOCM_RTS) - clear_bit(IFX_SPI_RTS, &ifx_dev->signal_state); - if (clear & TIOCM_DTR) - clear_bit(IFX_SPI_DTR, &ifx_dev->signal_state); - - set_bit(IFX_SPI_UPDATE, &ifx_dev->signal_state); - return 0; -} - -/** - * ifx_spi_open - called on tty open - * @tty: our tty device - * @filp: file handle being associated with the tty - * - * Open the tty interface. We let the tty_port layer do all the work - * for us. - * - * FIXME: Remove single device assumption and saved_ifx_dev - */ -static int ifx_spi_open(struct tty_struct *tty, struct file *filp) -{ - return tty_port_open(&saved_ifx_dev->tty_port, tty, filp); -} - -/** - * ifx_spi_close - called when our tty closes - * @tty: the tty being closed - * @filp: the file handle being closed - * - * Perform the close of the tty. We use the tty_port layer to do all - * our hard work. - */ -static void ifx_spi_close(struct tty_struct *tty, struct file *filp) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - tty_port_close(&ifx_dev->tty_port, tty, filp); - /* FIXME: should we do an ifx_spi_reset here ? */ -} - -/** - * ifx_decode_spi_header - decode received header - * @buffer: the received data - * @length: decoded length - * @more: decoded more flag - * @received_cts: status of cts we received - * - * Note how received_cts is handled -- if header is all F it is left - * the same as it was, if header is all 0 it is set to 0 otherwise it is - * taken from the incoming header. - * - * FIXME: endianness - */ -static int ifx_spi_decode_spi_header(unsigned char *buffer, int *length, - unsigned char *more, unsigned char *received_cts) -{ - u16 h1; - u16 h2; - u16 *in_buffer = (u16 *)buffer; - - h1 = *in_buffer; - h2 = *(in_buffer+1); - - if (h1 == 0 && h2 == 0) { - *received_cts = 0; - *more = 0; - return IFX_SPI_HEADER_0; - } else if (h1 == 0xffff && h2 == 0xffff) { - *more = 0; - /* spi_slave_cts remains as it was */ - return IFX_SPI_HEADER_F; - } - - *length = h1 & 0xfff; /* upper bits of byte are flags */ - *more = (buffer[1] >> IFX_SPI_MORE_BIT) & 1; - *received_cts = (buffer[3] >> IFX_SPI_CTS_BIT) & 1; - return 0; -} - -/** - * ifx_setup_spi_header - set header fields - * @txbuffer: pointer to start of SPI buffer - * @tx_count: bytes - * @more: indicate if more to follow - * - * Format up an SPI header for a transfer - * - * FIXME: endianness? - */ -static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count, - unsigned char more) -{ - *(u16 *)(txbuffer) = tx_count; - *(u16 *)(txbuffer+2) = IFX_SPI_PAYLOAD_SIZE; - txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK; -} - -/** - * ifx_spi_prepare_tx_buffer - prepare transmit frame - * @ifx_dev: our SPI device - * - * The transmit buffr needs a header and various other bits of - * information followed by as much data as we can pull from the FIFO - * and transfer. This function formats up a suitable buffer in the - * ifx_dev->tx_buffer - * - * FIXME: performance - should we wake the tty when the queue is half - * empty ? - */ -static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev) -{ - int temp_count; - int queue_length; - int tx_count; - unsigned char *tx_buffer; - - tx_buffer = ifx_dev->tx_buffer; - - /* make room for required SPI header */ - tx_buffer += IFX_SPI_HEADER_OVERHEAD; - tx_count = IFX_SPI_HEADER_OVERHEAD; - - /* clear to signal no more data if this turns out to be the - * last buffer sent in a sequence */ - ifx_dev->spi_more = 0; - - /* if modem cts is set, just send empty buffer */ - if (!ifx_dev->spi_slave_cts) { - /* see if there's tx data */ - queue_length = kfifo_len(&ifx_dev->tx_fifo); - if (queue_length != 0) { - /* data to mux -- see if there's room for it */ - temp_count = min(queue_length, IFX_SPI_PAYLOAD_SIZE); - temp_count = kfifo_out_locked(&ifx_dev->tx_fifo, - tx_buffer, temp_count, - &ifx_dev->fifo_lock); - - /* update buffer pointer and data count in message */ - tx_buffer += temp_count; - tx_count += temp_count; - if (temp_count == queue_length) - /* poke port to get more data */ - tty_port_tty_wakeup(&ifx_dev->tty_port); - else /* more data in port, use next SPI message */ - ifx_dev->spi_more = 1; - } - } - /* have data and info for header -- set up SPI header in buffer */ - /* spi header needs payload size, not entire buffer size */ - ifx_spi_setup_spi_header(ifx_dev->tx_buffer, - tx_count-IFX_SPI_HEADER_OVERHEAD, - ifx_dev->spi_more); - /* swap actual data in the buffer */ - ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count, - &ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]); - return tx_count; -} - -/** - * ifx_spi_write - line discipline write - * @tty: our tty device - * @buf: pointer to buffer to write (kernel space) - * @count: size of buffer - * - * Write the characters we have been given into the FIFO. If the device - * is not active then activate it, when the SRDY line is asserted back - * this will commence I/O - */ -static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - unsigned char *tmp_buf = (unsigned char *)buf; - unsigned long flags; - bool is_fifo_empty; - int tx_count; - - spin_lock_irqsave(&ifx_dev->fifo_lock, flags); - is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo); - tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count); - spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags); - if (is_fifo_empty) - mrdy_assert(ifx_dev); - - return tx_count; -} - -/** - * ifx_spi_chars_in_buffer - line discipline helper - * @tty: our tty device - * - * Report how much data we can accept before we drop bytes. As we use - * a simple FIFO this is nice and easy. - */ -static int ifx_spi_write_room(struct tty_struct *tty) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - return IFX_SPI_FIFO_SIZE - kfifo_len(&ifx_dev->tx_fifo); -} - -/** - * ifx_spi_chars_in_buffer - line discipline helper - * @tty: our tty device - * - * Report how many characters we have buffered. In our case this is the - * number of bytes sitting in our transmit FIFO. - */ -static int ifx_spi_chars_in_buffer(struct tty_struct *tty) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - return kfifo_len(&ifx_dev->tx_fifo); -} - -/** - * ifx_port_hangup - * @tty: our tty - * - * tty port hang up. Called when tty_hangup processing is invoked either - * by loss of carrier, or by software (eg vhangup). Serialized against - * activate/shutdown by the tty layer. - */ -static void ifx_spi_hangup(struct tty_struct *tty) -{ - struct ifx_spi_device *ifx_dev = tty->driver_data; - tty_port_hangup(&ifx_dev->tty_port); -} - -/** - * ifx_port_activate - * @port: our tty port - * @tty: our tty device - * - * tty port activate method - called for first open. Serialized - * with hangup and shutdown by the tty layer. - */ -static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct ifx_spi_device *ifx_dev = - container_of(port, struct ifx_spi_device, tty_port); - - /* clear any old data; can't do this in 'close' */ - kfifo_reset(&ifx_dev->tx_fifo); - - /* clear any flag which may be set in port shutdown procedure */ - clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags); - clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags); - - /* put port data into this tty */ - tty->driver_data = ifx_dev; - - /* set flag to allows data transfer */ - set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); - - return 0; -} - -/** - * ifx_port_shutdown - * @port: our tty port - * - * tty port shutdown method - called for last port close. Serialized - * with hangup and activate by the tty layer. - */ -static void ifx_port_shutdown(struct tty_port *port) -{ - struct ifx_spi_device *ifx_dev = - container_of(port, struct ifx_spi_device, tty_port); - - clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); - mrdy_set_low(ifx_dev); - del_timer(&ifx_dev->spi_timer); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); - tasklet_kill(&ifx_dev->io_work_tasklet); -} - -static const struct tty_port_operations ifx_tty_port_ops = { - .activate = ifx_port_activate, - .shutdown = ifx_port_shutdown, -}; - -static const struct tty_operations ifx_spi_serial_ops = { - .open = ifx_spi_open, - .close = ifx_spi_close, - .write = ifx_spi_write, - .hangup = ifx_spi_hangup, - .write_room = ifx_spi_write_room, - .chars_in_buffer = ifx_spi_chars_in_buffer, - .tiocmget = ifx_spi_tiocmget, - .tiocmset = ifx_spi_tiocmset, -}; - -/** - * ifx_spi_insert_fip_string - queue received data - * @ifx_dev: our SPI device - * @chars: buffer we have received - * @size: number of chars reeived - * - * Queue bytes to the tty assuming the tty side is currently open. If - * not the discard the data. - */ -static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev, - unsigned char *chars, size_t size) -{ - tty_insert_flip_string(&ifx_dev->tty_port, chars, size); - tty_flip_buffer_push(&ifx_dev->tty_port); -} - -/** - * ifx_spi_complete - SPI transfer completed - * @ctx: our SPI device - * - * An SPI transfer has completed. Process any received data and kick off - * any further transmits we can commence. - */ -static void ifx_spi_complete(void *ctx) -{ - struct ifx_spi_device *ifx_dev = ctx; - int length; - int actual_length; - unsigned char more = 0; - unsigned char cts; - int local_write_pending = 0; - int queue_length; - int srdy; - int decode_result; - - mrdy_set_low(ifx_dev); - - if (!ifx_dev->spi_msg.status) { - /* check header validity, get comm flags */ - ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD, - &ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]); - decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer, - &length, &more, &cts); - if (decode_result == IFX_SPI_HEADER_0) { - dev_dbg(&ifx_dev->spi_dev->dev, - "ignore input: invalid header 0"); - ifx_dev->spi_slave_cts = 0; - goto complete_exit; - } else if (decode_result == IFX_SPI_HEADER_F) { - dev_dbg(&ifx_dev->spi_dev->dev, - "ignore input: invalid header F"); - goto complete_exit; - } - - ifx_dev->spi_slave_cts = cts; - - actual_length = min((unsigned int)length, - ifx_dev->spi_msg.actual_length); - ifx_dev->swap_buf( - (ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD), - actual_length, - &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]); - ifx_spi_insert_flip_string( - ifx_dev, - ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD, - (size_t)actual_length); - } else { - more = 0; - dev_dbg(&ifx_dev->spi_dev->dev, "SPI transfer error %d", - ifx_dev->spi_msg.status); - } - -complete_exit: - if (ifx_dev->write_pending) { - ifx_dev->write_pending = 0; - local_write_pending = 1; - } - - clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags)); - - queue_length = kfifo_len(&ifx_dev->tx_fifo); - srdy = gpiod_get_value(ifx_dev->gpio.srdy); - if (!srdy) - ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY); - - /* schedule output if there is more to do */ - if (test_and_clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags)) - tasklet_schedule(&ifx_dev->io_work_tasklet); - else { - if (more || ifx_dev->spi_more || queue_length > 0 || - local_write_pending) { - if (ifx_dev->spi_slave_cts) { - if (more) - mrdy_assert(ifx_dev); - } else - mrdy_assert(ifx_dev); - } else { - /* - * poke line discipline driver if any for more data - * may or may not get more data to write - * for now, say not busy - */ - ifx_spi_power_state_clear(ifx_dev, - IFX_SPI_POWER_DATA_PENDING); - tty_port_tty_wakeup(&ifx_dev->tty_port); - } - } -} - -/** - * ifx_spio_io - I/O tasklet - * @t: tasklet construct used to fetch the SPI device - * - * Queue data for transmission if possible and then kick off the - * transfer. - */ -static void ifx_spi_io(struct tasklet_struct *t) -{ - int retval; - struct ifx_spi_device *ifx_dev = from_tasklet(ifx_dev, t, - io_work_tasklet); - - if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) && - test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) { - if (ifx_dev->gpio.unack_srdy_int_nb > 0) - ifx_dev->gpio.unack_srdy_int_nb--; - - ifx_spi_prepare_tx_buffer(ifx_dev); - - spi_message_init(&ifx_dev->spi_msg); - INIT_LIST_HEAD(&ifx_dev->spi_msg.queue); - - ifx_dev->spi_msg.context = ifx_dev; - ifx_dev->spi_msg.complete = ifx_spi_complete; - - /* set up our spi transfer */ - /* note len is BYTES, not transfers */ - ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE; - ifx_dev->spi_xfer.cs_change = 0; - ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; - /* ifx_dev->spi_xfer.speed_hz = 390625; */ - ifx_dev->spi_xfer.bits_per_word = - ifx_dev->spi_dev->bits_per_word; - - ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; - ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; - - /* - * setup dma pointers - */ - if (ifx_dev->use_dma) { - ifx_dev->spi_msg.is_dma_mapped = 1; - ifx_dev->tx_dma = ifx_dev->tx_bus; - ifx_dev->rx_dma = ifx_dev->rx_bus; - ifx_dev->spi_xfer.tx_dma = ifx_dev->tx_dma; - ifx_dev->spi_xfer.rx_dma = ifx_dev->rx_dma; - } else { - ifx_dev->spi_msg.is_dma_mapped = 0; - ifx_dev->tx_dma = (dma_addr_t)0; - ifx_dev->rx_dma = (dma_addr_t)0; - ifx_dev->spi_xfer.tx_dma = (dma_addr_t)0; - ifx_dev->spi_xfer.rx_dma = (dma_addr_t)0; - } - - spi_message_add_tail(&ifx_dev->spi_xfer, &ifx_dev->spi_msg); - - /* Assert MRDY. This may have already been done by the write - * routine. - */ - mrdy_assert(ifx_dev); - - retval = spi_async(ifx_dev->spi_dev, &ifx_dev->spi_msg); - if (retval) { - clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, - &ifx_dev->flags); - tasklet_schedule(&ifx_dev->io_work_tasklet); - return; - } - } else - ifx_dev->write_pending = 1; -} - -/** - * ifx_spi_free_port - free up the tty side - * @ifx_dev: IFX device going away - * - * Unregister and free up a port when the device goes away - */ -static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev) -{ - if (ifx_dev->tty_dev) - tty_unregister_device(tty_drv, ifx_dev->minor); - tty_port_destroy(&ifx_dev->tty_port); - kfifo_free(&ifx_dev->tx_fifo); -} - -/** - * ifx_spi_create_port - create a new port - * @ifx_dev: our spi device - * - * Allocate and initialise the tty port that goes with this interface - * and add it to the tty layer so that it can be opened. - */ -static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev) -{ - int ret = 0; - struct tty_port *pport = &ifx_dev->tty_port; - - spin_lock_init(&ifx_dev->fifo_lock); - lockdep_set_class_and_subclass(&ifx_dev->fifo_lock, - &ifx_spi_key, 0); - - if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE, GFP_KERNEL)) { - ret = -ENOMEM; - goto error_ret; - } - - tty_port_init(pport); - pport->ops = &ifx_tty_port_ops; - ifx_dev->minor = IFX_SPI_TTY_ID; - ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv, - ifx_dev->minor, &ifx_dev->spi_dev->dev); - if (IS_ERR(ifx_dev->tty_dev)) { - dev_dbg(&ifx_dev->spi_dev->dev, - "%s: registering tty device failed", __func__); - ret = PTR_ERR(ifx_dev->tty_dev); - goto error_port; - } - return 0; - -error_port: - tty_port_destroy(pport); -error_ret: - ifx_spi_free_port(ifx_dev); - return ret; -} - -/** - * ifx_spi_handle_srdy - handle SRDY - * @ifx_dev: device asserting SRDY - * - * Check our device state and see what we need to kick off when SRDY - * is asserted. This usually means killing the timer and firing off the - * I/O processing. - */ -static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev) -{ - if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) { - del_timer(&ifx_dev->spi_timer); - clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); - } - - ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_SRDY); - - if (!test_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) - tasklet_schedule(&ifx_dev->io_work_tasklet); - else - set_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags); -} - -/** - * ifx_spi_srdy_interrupt - SRDY asserted - * @irq: our IRQ number - * @dev: our ifx device - * - * The modem asserted SRDY. Handle the srdy event - */ -static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev) -{ - struct ifx_spi_device *ifx_dev = dev; - ifx_dev->gpio.unack_srdy_int_nb++; - ifx_spi_handle_srdy(ifx_dev); - return IRQ_HANDLED; -} - -/** - * ifx_spi_reset_interrupt - Modem has changed reset state - * @irq: interrupt number - * @dev: our device pointer - * - * The modem has either entered or left reset state. Check the GPIO - * line to see which. - * - * FIXME: review locking on MR_INPROGRESS versus - * parallel unsolicited reset/solicited reset - */ -static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev) -{ - struct ifx_spi_device *ifx_dev = dev; - int val = gpiod_get_value(ifx_dev->gpio.reset_out); - int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state); - - if (val == 0) { - /* entered reset */ - set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state); - if (!solreset) { - /* unsolicited reset */ - tty_port_tty_hangup(&ifx_dev->tty_port, false); - } - } else { - /* exited reset */ - clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state); - if (solreset) { - set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state); - wake_up(&ifx_dev->mdm_reset_wait); - } - } - return IRQ_HANDLED; -} - -/** - * ifx_spi_free_device - free device - * @ifx_dev: device to free - * - * Free the IFX device - */ -static void ifx_spi_free_device(struct ifx_spi_device *ifx_dev) -{ - ifx_spi_free_port(ifx_dev); - dma_free_coherent(&ifx_dev->spi_dev->dev, - IFX_SPI_TRANSFER_SIZE, - ifx_dev->tx_buffer, - ifx_dev->tx_bus); - dma_free_coherent(&ifx_dev->spi_dev->dev, - IFX_SPI_TRANSFER_SIZE, - ifx_dev->rx_buffer, - ifx_dev->rx_bus); -} - -/** - * ifx_spi_reset - reset modem - * @ifx_dev: modem to reset - * - * Perform a reset on the modem - */ -static int ifx_spi_reset(struct ifx_spi_device *ifx_dev) -{ - int ret; - /* - * set up modem power, reset - * - * delays are required on some platforms for the modem - * to reset properly - */ - set_bit(MR_START, &ifx_dev->mdm_reset_state); - gpiod_set_value(ifx_dev->gpio.po, 0); - gpiod_set_value(ifx_dev->gpio.reset, 0); - msleep(25); - gpiod_set_value(ifx_dev->gpio.reset, 1); - msleep(1); - gpiod_set_value(ifx_dev->gpio.po, 1); - msleep(1); - gpiod_set_value(ifx_dev->gpio.po, 0); - ret = wait_event_timeout(ifx_dev->mdm_reset_wait, - test_bit(MR_COMPLETE, - &ifx_dev->mdm_reset_state), - IFX_RESET_TIMEOUT); - if (!ret) - dev_warn(&ifx_dev->spi_dev->dev, "Modem reset timeout: (state:%lx)", - ifx_dev->mdm_reset_state); - - ifx_dev->mdm_reset_state = 0; - return ret; -} - -/** - * ifx_spi_spi_probe - probe callback - * @spi: our possible matching SPI device - * - * Probe for a 6x60 modem on SPI bus. Perform any needed device and - * GPIO setup. - * - * FIXME: - * - Support for multiple devices - * - Split out MID specific GPIO handling eventually - */ - -static int ifx_spi_spi_probe(struct spi_device *spi) -{ - int ret; - int srdy; - struct ifx_modem_platform_data *pl_data; - struct ifx_spi_device *ifx_dev; - struct device *dev = &spi->dev; - - if (saved_ifx_dev) { - dev_dbg(dev, "ignoring subsequent detection"); - return -ENODEV; - } - - pl_data = dev_get_platdata(dev); - if (!pl_data) { - dev_err(dev, "missing platform data!"); - return -ENODEV; - } - - /* initialize structure to hold our device variables */ - ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL); - if (!ifx_dev) { - dev_err(dev, "spi device allocation failed"); - return -ENOMEM; - } - saved_ifx_dev = ifx_dev; - ifx_dev->spi_dev = spi; - clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags); - spin_lock_init(&ifx_dev->write_lock); - spin_lock_init(&ifx_dev->power_lock); - ifx_dev->power_status = 0; - timer_setup(&ifx_dev->spi_timer, ifx_spi_timeout, 0); - ifx_dev->modem = pl_data->modem_type; - ifx_dev->use_dma = pl_data->use_dma; - ifx_dev->max_hz = pl_data->max_hz; - /* initialize spi mode, etc */ - spi->max_speed_hz = ifx_dev->max_hz; - spi->mode = IFX_SPI_MODE | (SPI_LOOP & spi->mode); - spi->bits_per_word = spi_bpw; - ret = spi_setup(spi); - if (ret) { - dev_err(dev, "SPI setup wasn't successful %d", ret); - kfree(ifx_dev); - return -ENODEV; - } - - /* init swap_buf function according to word width configuration */ - if (spi->bits_per_word == 32) - ifx_dev->swap_buf = swap_buf_32; - else if (spi->bits_per_word == 16) - ifx_dev->swap_buf = swap_buf_16; - else - ifx_dev->swap_buf = swap_buf_8; - - /* ensure SPI protocol flags are initialized to enable transfer */ - ifx_dev->spi_more = 0; - ifx_dev->spi_slave_cts = 0; - - /*initialize transfer and dma buffers */ - ifx_dev->tx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, - IFX_SPI_TRANSFER_SIZE, - &ifx_dev->tx_bus, - GFP_KERNEL); - if (!ifx_dev->tx_buffer) { - dev_err(dev, "DMA-TX buffer allocation failed"); - ret = -ENOMEM; - goto error_ret; - } - ifx_dev->rx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, - IFX_SPI_TRANSFER_SIZE, - &ifx_dev->rx_bus, - GFP_KERNEL); - if (!ifx_dev->rx_buffer) { - dev_err(dev, "DMA-RX buffer allocation failed"); - ret = -ENOMEM; - goto error_ret; - } - - /* initialize waitq for modem reset */ - init_waitqueue_head(&ifx_dev->mdm_reset_wait); - - spi_set_drvdata(spi, ifx_dev); - tasklet_setup(&ifx_dev->io_work_tasklet, ifx_spi_io); - - set_bit(IFX_SPI_STATE_PRESENT, &ifx_dev->flags); - - /* create our tty port */ - ret = ifx_spi_create_port(ifx_dev); - if (ret != 0) { - dev_err(dev, "create default tty port failed"); - goto error_ret; - } - - ifx_dev->gpio.reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(ifx_dev->gpio.reset)) { - dev_err(dev, "could not obtain reset GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.reset); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.reset, "ifxModem reset"); - ifx_dev->gpio.po = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); - if (IS_ERR(ifx_dev->gpio.po)) { - dev_err(dev, "could not obtain power GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.po); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.po, "ifxModem power"); - ifx_dev->gpio.mrdy = devm_gpiod_get(dev, "mrdy", GPIOD_OUT_LOW); - if (IS_ERR(ifx_dev->gpio.mrdy)) { - dev_err(dev, "could not obtain mrdy GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.mrdy); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.mrdy, "ifxModem mrdy"); - ifx_dev->gpio.srdy = devm_gpiod_get(dev, "srdy", GPIOD_IN); - if (IS_ERR(ifx_dev->gpio.srdy)) { - dev_err(dev, "could not obtain srdy GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.srdy); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.srdy, "ifxModem srdy"); - ifx_dev->gpio.reset_out = devm_gpiod_get(dev, "rst_out", GPIOD_IN); - if (IS_ERR(ifx_dev->gpio.reset_out)) { - dev_err(dev, "could not obtain rst_out GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.reset_out); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.reset_out, "ifxModem reset out"); - ifx_dev->gpio.pmu_reset = devm_gpiod_get(dev, "pmu_reset", GPIOD_ASIS); - if (IS_ERR(ifx_dev->gpio.pmu_reset)) { - dev_err(dev, "could not obtain pmu_reset GPIO\n"); - ret = PTR_ERR(ifx_dev->gpio.pmu_reset); - goto error_ret; - } - gpiod_set_consumer_name(ifx_dev->gpio.pmu_reset, "ifxModem PMU reset"); - - ret = request_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), - ifx_spi_reset_interrupt, - IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME, - ifx_dev); - if (ret) { - dev_err(dev, "Unable to get irq %x\n", - gpiod_to_irq(ifx_dev->gpio.reset_out)); - goto error_ret; - } - - ret = ifx_spi_reset(ifx_dev); - - ret = request_irq(gpiod_to_irq(ifx_dev->gpio.srdy), - ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME, - ifx_dev); - if (ret) { - dev_err(dev, "Unable to get irq %x", - gpiod_to_irq(ifx_dev->gpio.srdy)); - goto error_ret2; - } - - /* set pm runtime power state and register with power system */ - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - /* handle case that modem is already signaling SRDY */ - /* no outgoing tty open at this point, this just satisfies the - * modem's read and should reset communication properly - */ - srdy = gpiod_get_value(ifx_dev->gpio.srdy); - - if (srdy) { - mrdy_assert(ifx_dev); - ifx_spi_handle_srdy(ifx_dev); - } else - mrdy_set_low(ifx_dev); - return 0; - -error_ret2: - free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); -error_ret: - ifx_spi_free_device(ifx_dev); - saved_ifx_dev = NULL; - return ret; -} - -/** - * ifx_spi_spi_remove - SPI device was removed - * @spi: SPI device - * - * FIXME: We should be shutting the device down here not in - * the module unload path. - */ - -static int ifx_spi_spi_remove(struct spi_device *spi) -{ - struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); - /* stop activity */ - tasklet_kill(&ifx_dev->io_work_tasklet); - - pm_runtime_disable(&spi->dev); - - /* free irq */ - free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); - free_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_dev); - - /* free allocations */ - ifx_spi_free_device(ifx_dev); - - saved_ifx_dev = NULL; - return 0; -} - -/** - * ifx_spi_spi_shutdown - called on SPI shutdown - * @spi: SPI device - * - * No action needs to be taken here - */ - -static void ifx_spi_spi_shutdown(struct spi_device *spi) -{ - struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); - - ifx_modem_power_off(ifx_dev); -} - -/* - * various suspends and resumes have nothing to do - * no hardware to save state for - */ - -/** - * ifx_spi_pm_suspend - suspend modem on system suspend - * @dev: device being suspended - * - * Suspend the modem. No action needed on Intel MID platforms, may - * need extending for other systems. - */ -static int ifx_spi_pm_suspend(struct device *dev) -{ - return 0; -} - -/** - * ifx_spi_pm_resume - resume modem on system resume - * @dev: device being suspended - * - * Allow the modem to resume. No action needed. - * - * FIXME: do we need to reset anything here ? - */ -static int ifx_spi_pm_resume(struct device *dev) -{ - return 0; -} - -/** - * ifx_spi_pm_runtime_resume - suspend modem - * @dev: device being suspended - * - * Allow the modem to resume. No action needed. - */ -static int ifx_spi_pm_runtime_resume(struct device *dev) -{ - return 0; -} - -/** - * ifx_spi_pm_runtime_suspend - suspend modem - * @dev: device being suspended - * - * Allow the modem to suspend and thus suspend to continue up the - * device tree. - */ -static int ifx_spi_pm_runtime_suspend(struct device *dev) -{ - return 0; -} - -/** - * ifx_spi_pm_runtime_idle - check if modem idle - * @dev: our device - * - * Check conditions and queue runtime suspend if idle. - */ -static int ifx_spi_pm_runtime_idle(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); - - if (!ifx_dev->power_status) - pm_runtime_suspend(dev); - - return 0; -} - -static const struct dev_pm_ops ifx_spi_pm = { - .resume = ifx_spi_pm_resume, - .suspend = ifx_spi_pm_suspend, - .runtime_resume = ifx_spi_pm_runtime_resume, - .runtime_suspend = ifx_spi_pm_runtime_suspend, - .runtime_idle = ifx_spi_pm_runtime_idle -}; - -static const struct spi_device_id ifx_id_table[] = { - {"ifx6160", 0}, - {"ifx6260", 0}, - { } -}; -MODULE_DEVICE_TABLE(spi, ifx_id_table); - -/* spi operations */ -static struct spi_driver ifx_spi_driver = { - .driver = { - .name = DRVNAME, - .pm = &ifx_spi_pm, - }, - .probe = ifx_spi_spi_probe, - .shutdown = ifx_spi_spi_shutdown, - .remove = ifx_spi_spi_remove, - .id_table = ifx_id_table -}; - -/** - * ifx_spi_exit - module exit - * - * Unload the module. - */ - -static void __exit ifx_spi_exit(void) -{ - /* unregister */ - spi_unregister_driver(&ifx_spi_driver); - tty_unregister_driver(tty_drv); - put_tty_driver(tty_drv); - unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); -} - -/** - * ifx_spi_init - module entry point - * - * Initialise the SPI and tty interfaces for the IFX SPI driver - * We need to initialize upper-edge spi driver after the tty - * driver because otherwise the spi probe will race - */ - -static int __init ifx_spi_init(void) -{ - int result; - - tty_drv = alloc_tty_driver(1); - if (!tty_drv) { - pr_err("%s: alloc_tty_driver failed", DRVNAME); - return -ENOMEM; - } - - tty_drv->driver_name = DRVNAME; - tty_drv->name = TTYNAME; - tty_drv->minor_start = IFX_SPI_TTY_ID; - tty_drv->type = TTY_DRIVER_TYPE_SERIAL; - tty_drv->subtype = SERIAL_TYPE_NORMAL; - tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - tty_drv->init_termios = tty_std_termios; - - tty_set_operations(tty_drv, &ifx_spi_serial_ops); - - result = tty_register_driver(tty_drv); - if (result) { - pr_err("%s: tty_register_driver failed(%d)", - DRVNAME, result); - goto err_free_tty; - } - - result = spi_register_driver(&ifx_spi_driver); - if (result) { - pr_err("%s: spi_register_driver failed(%d)", - DRVNAME, result); - goto err_unreg_tty; - } - - result = register_reboot_notifier(&ifx_modem_reboot_notifier_block); - if (result) { - pr_err("%s: register ifx modem reboot notifier failed(%d)", - DRVNAME, result); - goto err_unreg_spi; - } - - return 0; -err_unreg_spi: - spi_unregister_driver(&ifx_spi_driver); -err_unreg_tty: - tty_unregister_driver(tty_drv); -err_free_tty: - put_tty_driver(tty_drv); - - return result; -} - -module_init(ifx_spi_init); -module_exit(ifx_spi_exit); - -MODULE_AUTHOR("Intel"); -MODULE_DESCRIPTION("IFX6x60 spi driver"); -MODULE_LICENSE("GPL"); -MODULE_INFO(Version, "0.1-IFX6x60"); diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h deleted file mode 100644 index ecb841d928a7..000000000000 --- a/drivers/tty/serial/ifx6x60.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/**************************************************************************** - * - * Driver for the IFX spi modem. - * - * Copyright (C) 2009, 2010 Intel Corp - * Jim Stanley - * - *****************************************************************************/ -#ifndef _IFX6X60_H -#define _IFX6X60_H - -struct gpio_desc; - -#define DRVNAME "ifx6x60" -#define TTYNAME "ttyIFX" - -#define IFX_SPI_MAX_MINORS 1 -#define IFX_SPI_TRANSFER_SIZE 2048 -#define IFX_SPI_FIFO_SIZE 4096 - -#define IFX_SPI_HEADER_OVERHEAD 4 -#define IFX_RESET_TIMEOUT msecs_to_jiffies(50) - -/* device flags bitfield definitions */ -#define IFX_SPI_STATE_PRESENT 0 -#define IFX_SPI_STATE_IO_IN_PROGRESS 1 -#define IFX_SPI_STATE_IO_READY 2 -#define IFX_SPI_STATE_TIMER_PENDING 3 -#define IFX_SPI_STATE_IO_AVAILABLE 4 - -/* flow control bitfields */ -#define IFX_SPI_DCD 0 -#define IFX_SPI_CTS 1 -#define IFX_SPI_DSR 2 -#define IFX_SPI_RI 3 -#define IFX_SPI_DTR 4 -#define IFX_SPI_RTS 5 -#define IFX_SPI_TX_FC 6 -#define IFX_SPI_RX_FC 7 -#define IFX_SPI_UPDATE 8 - -#define IFX_SPI_PAYLOAD_SIZE (IFX_SPI_TRANSFER_SIZE - \ - IFX_SPI_HEADER_OVERHEAD) - -#define IFX_SPI_IRQ_TYPE DETECT_EDGE_RISING -#define IFX_SPI_GPIO_TARGET 0 -#define IFX_SPI_GPIO0 0x105 - -#define IFX_SPI_STATUS_TIMEOUT (2000*HZ) - -/* values for bits in power status byte */ -#define IFX_SPI_POWER_DATA_PENDING 1 -#define IFX_SPI_POWER_SRDY 2 - -struct ifx_spi_device { - /* Our SPI device */ - struct spi_device *spi_dev; - - /* Port specific data */ - struct kfifo tx_fifo; - spinlock_t fifo_lock; - unsigned long signal_state; - - /* TTY Layer logic */ - struct tty_port tty_port; - struct device *tty_dev; - int minor; - - /* Low level I/O work */ - struct tasklet_struct io_work_tasklet; - unsigned long flags; - dma_addr_t rx_dma; - dma_addr_t tx_dma; - - int modem; /* Modem type */ - int use_dma; /* provide dma-able addrs in SPI msg */ - long max_hz; /* max SPI frequency */ - - spinlock_t write_lock; - int write_pending; - spinlock_t power_lock; - unsigned char power_status; - - unsigned char *rx_buffer; - unsigned char *tx_buffer; - dma_addr_t rx_bus; - dma_addr_t tx_bus; - unsigned char spi_more; - unsigned char spi_slave_cts; - - struct timer_list spi_timer; - - struct spi_message spi_msg; - struct spi_transfer spi_xfer; - - struct { - /* gpio lines */ - struct gpio_desc *srdy; /* slave-ready gpio */ - struct gpio_desc *mrdy; /* master-ready gpio */ - struct gpio_desc *reset; /* modem-reset gpio */ - struct gpio_desc *po; /* modem-on gpio */ - struct gpio_desc *reset_out; /* modem-in-reset gpio */ - struct gpio_desc *pmu_reset; /* PMU reset gpio */ - /* state/stats */ - int unack_srdy_int_nb; - } gpio; - - /* modem reset */ - unsigned long mdm_reset_state; -#define MR_START 0 -#define MR_INPROGRESS 1 -#define MR_COMPLETE 2 - wait_queue_head_t mdm_reset_wait; - void (*swap_buf)(unsigned char *buf, int len, void *end); -}; - -#endif /* _IFX6X60_H */