root/drivers/net/wireless/st/cw1200/cw1200_spi.c
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Mac80211 SPI driver for ST-Ericsson CW1200 device
 *
 * Copyright (c) 2011, Sagrad Inc.
 * Author:  Solomon Peachy <speachy@sagrad.com>
 *
 * Based on cw1200_sdio.c
 * Copyright (c) 2010, ST-Ericsson
 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
 */

#include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <net/mac80211.h>

#include <linux/spi/spi.h>
#include <linux/device.h>

#include "cw1200.h"
#include "hwbus.h"
#include <linux/platform_data/net-cw1200.h>
#include "hwio.h"

MODULE_AUTHOR("Solomon Peachy <speachy@sagrad.com>");
MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SPI driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:cw1200_wlan_spi");

/* #define SPI_DEBUG */

struct hwbus_priv {
        struct spi_device       *func;
        struct cw1200_common    *core;
        const struct cw1200_platform_data_spi *pdata;
        spinlock_t              lock; /* Serialize all bus operations */
        wait_queue_head_t       wq;
        struct gpio_desc        *reset;
        struct gpio_desc        *powerup;
        int claimed;
};

#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
#define SET_WRITE 0x7FFF /* usage: and operation */
#define SET_READ 0x8000  /* usage: or operation */

/* Notes on byte ordering:
   LE:  B0 B1 B2 B3
   BE:  B3 B2 B1 B0

   Hardware expects 32-bit data to be written as 16-bit BE words:

   B1 B0 B3 B2
*/

static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self,
                                     unsigned int addr,
                                     void *dst, int count)
{
        int ret, i;
        u16 regaddr;
        struct spi_message      m;

        struct spi_transfer     t_addr = {
                .tx_buf         = &regaddr,
                .len            = sizeof(regaddr),
        };
        struct spi_transfer     t_msg = {
                .rx_buf         = dst,
                .len            = count,
        };

        regaddr = (SDIO_TO_SPI_ADDR(addr))<<12;
        regaddr |= SET_READ;
        regaddr |= (count>>1);

#ifdef SPI_DEBUG
        pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, regaddr);
#endif

        /* Header is LE16 */
        regaddr = (__force u16)cpu_to_le16(regaddr);

        /* We have to byteswap if the SPI bus is limited to 8b operation
           or we are running on a Big Endian system
        */
#if defined(__LITTLE_ENDIAN)
        if (self->func->bits_per_word == 8)
#endif
                regaddr = swab16(regaddr);

        spi_message_init(&m);
        spi_message_add_tail(&t_addr, &m);
        spi_message_add_tail(&t_msg, &m);
        ret = spi_sync(self->func, &m);

#ifdef SPI_DEBUG
        pr_info("READ : ");
        for (i = 0; i < t_addr.len; i++)
                printk("%02x ", ((u8 *)t_addr.tx_buf)[i]);
        printk(" : ");
        for (i = 0; i < t_msg.len; i++)
                printk("%02x ", ((u8 *)t_msg.rx_buf)[i]);
        printk("\n");
#endif

        /* We have to byteswap if the SPI bus is limited to 8b operation
           or we are running on a Big Endian system
        */
#if defined(__LITTLE_ENDIAN)
        if (self->func->bits_per_word == 8)
#endif
        {
                uint16_t *buf = (uint16_t *)dst;
                for (i = 0; i < ((count + 1) >> 1); i++)
                        buf[i] = swab16(buf[i]);
        }

        return ret;
}

static int cw1200_spi_memcpy_toio(struct hwbus_priv *self,
                                   unsigned int addr,
                                   const void *src, int count)
{
        int rval, i;
        u16 regaddr;
        struct spi_transfer     t_addr = {
                .tx_buf         = &regaddr,
                .len            = sizeof(regaddr),
        };
        struct spi_transfer     t_msg = {
                .tx_buf         = src,
                .len            = count,
        };
        struct spi_message      m;

        regaddr = (SDIO_TO_SPI_ADDR(addr))<<12;
        regaddr &= SET_WRITE;
        regaddr |= (count>>1);

#ifdef SPI_DEBUG
        pr_info("WRITE: %04d  to  0x%02x (%04x)\n", count, addr, regaddr);
#endif

        /* Header is LE16 */
        regaddr = (__force u16)cpu_to_le16(regaddr);

        /* We have to byteswap if the SPI bus is limited to 8b operation
           or we are running on a Big Endian system
        */
#if defined(__LITTLE_ENDIAN)
        if (self->func->bits_per_word == 8)
#endif
        {
                uint16_t *buf = (uint16_t *)src;
                regaddr = swab16(regaddr);
                for (i = 0; i < ((count + 1) >> 1); i++)
                        buf[i] = swab16(buf[i]);
        }

#ifdef SPI_DEBUG
        pr_info("WRITE: ");
        for (i = 0; i < t_addr.len; i++)
                printk("%02x ", ((u8 *)t_addr.tx_buf)[i]);
        printk(" : ");
        for (i = 0; i < t_msg.len; i++)
                printk("%02x ", ((u8 *)t_msg.tx_buf)[i]);
        printk("\n");
#endif

        spi_message_init(&m);
        spi_message_add_tail(&t_addr, &m);
        spi_message_add_tail(&t_msg, &m);
        rval = spi_sync(self->func, &m);

#ifdef SPI_DEBUG
        pr_info("WROTE: %d\n", m.actual_length);
#endif

#if defined(__LITTLE_ENDIAN)
        /* We have to byteswap if the SPI bus is limited to 8b operation */
        if (self->func->bits_per_word == 8)
#endif
        {
                uint16_t *buf = (uint16_t *)src;
                for (i = 0; i < ((count + 1) >> 1); i++)
                        buf[i] = swab16(buf[i]);
        }
        return rval;
}

static void cw1200_spi_lock(struct hwbus_priv *self)
{
        unsigned long flags;

        DECLARE_WAITQUEUE(wait, current);

        might_sleep();

        add_wait_queue(&self->wq, &wait);
        spin_lock_irqsave(&self->lock, flags);
        while (1) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                if (!self->claimed)
                        break;
                spin_unlock_irqrestore(&self->lock, flags);
                schedule();
                spin_lock_irqsave(&self->lock, flags);
        }
        set_current_state(TASK_RUNNING);
        self->claimed = 1;
        spin_unlock_irqrestore(&self->lock, flags);
        remove_wait_queue(&self->wq, &wait);

        return;
}

static void cw1200_spi_unlock(struct hwbus_priv *self)
{
        unsigned long flags;

        spin_lock_irqsave(&self->lock, flags);
        self->claimed = 0;
        spin_unlock_irqrestore(&self->lock, flags);
        wake_up(&self->wq);

        return;
}

static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
{
        struct hwbus_priv *self = dev_id;

        if (self->core) {
                cw1200_spi_lock(self);
                cw1200_irq_handler(self->core);
                cw1200_spi_unlock(self);
                return IRQ_HANDLED;
        } else {
                return IRQ_NONE;
        }
}

static int cw1200_spi_irq_subscribe(struct hwbus_priv *self)
{
        int ret;

        pr_debug("SW IRQ subscribe\n");

        ret = request_threaded_irq(self->func->irq, NULL,
                                   cw1200_spi_irq_handler,
                                   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
                                   "cw1200_wlan_irq", self);
        if (WARN_ON(ret < 0))
                goto exit;

        ret = enable_irq_wake(self->func->irq);
        if (WARN_ON(ret))
                goto free_irq;

        return 0;

free_irq:
        free_irq(self->func->irq, self);
exit:
        return ret;
}

static void cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
{
        pr_debug("SW IRQ unsubscribe\n");
        disable_irq_wake(self->func->irq);
        free_irq(self->func->irq, self);
}

static int cw1200_spi_off(struct hwbus_priv *self, const struct cw1200_platform_data_spi *pdata)
{
        if (self->reset) {
                /* Assert RESET, note active low */
                gpiod_set_value(self->reset, 1);
                msleep(30); /* Min is 2 * CLK32K cycles */
        }

        if (pdata->power_ctrl)
                pdata->power_ctrl(pdata, false);
        if (pdata->clk_ctrl)
                pdata->clk_ctrl(pdata, false);

        return 0;
}

static int cw1200_spi_on(struct hwbus_priv *self, const struct cw1200_platform_data_spi *pdata)
{
        /* Ensure I/Os are pulled low */
        gpiod_direction_output(self->reset, 1); /* Active low */
        gpiod_direction_output(self->powerup, 0);
        if (self->reset || self->powerup)
                msleep(10); /* Settle time? */

        /* Enable 3v3 and 1v8 to hardware */
        if (pdata->power_ctrl) {
                if (pdata->power_ctrl(pdata, true)) {
                        pr_err("power_ctrl() failed!\n");
                        return -1;
                }
        }

        /* Enable CLK32K */
        if (pdata->clk_ctrl) {
                if (pdata->clk_ctrl(pdata, true)) {
                        pr_err("clk_ctrl() failed!\n");
                        return -1;
                }
                msleep(10); /* Delay until clock is stable for 2 cycles */
        }

        /* Enable POWERUP signal */
        if (self->powerup) {
                gpiod_set_value(self->powerup, 1);
                msleep(250); /* or more..? */
        }
        /* Assert RSTn signal, note active low */
        if (self->reset) {
                gpiod_set_value(self->reset, 0);
                msleep(50); /* Or more..? */
        }
        return 0;
}

static size_t cw1200_spi_align_size(struct hwbus_priv *self, size_t size)
{
        return size & 1 ? size + 1 : size;
}

static int cw1200_spi_pm(struct hwbus_priv *self, bool suspend)
{
        return irq_set_irq_wake(self->func->irq, suspend);
}

static const struct hwbus_ops cw1200_spi_hwbus_ops = {
        .hwbus_memcpy_fromio    = cw1200_spi_memcpy_fromio,
        .hwbus_memcpy_toio      = cw1200_spi_memcpy_toio,
        .lock                   = cw1200_spi_lock,
        .unlock                 = cw1200_spi_unlock,
        .align_size             = cw1200_spi_align_size,
        .power_mgmt             = cw1200_spi_pm,
};

/* Probe Function to be called by SPI stack when device is discovered */
static int cw1200_spi_probe(struct spi_device *func)
{
        const struct cw1200_platform_data_spi *plat_data =
                dev_get_platdata(&func->dev);
        struct hwbus_priv *self;
        int status;

        /* Sanity check speed */
        if (func->max_speed_hz > 52000000)
                func->max_speed_hz = 52000000;
        if (func->max_speed_hz < 1000000)
                func->max_speed_hz = 1000000;

        /* Fix up transfer size */
        if (plat_data->spi_bits_per_word)
                func->bits_per_word = plat_data->spi_bits_per_word;
        if (!func->bits_per_word)
                func->bits_per_word = 16;

        /* And finally.. */
        func->mode = SPI_MODE_0;

        pr_info("cw1200_wlan_spi: Probe called (CS %d M %d BPW %d CLK %d)\n",
                spi_get_chipselect(func, 0), func->mode, func->bits_per_word,
                func->max_speed_hz);

        self = devm_kzalloc(&func->dev, sizeof(*self), GFP_KERNEL);
        if (!self) {
                pr_err("Can't allocate SPI hwbus_priv.");
                return -ENOMEM;
        }

        /* Request reset asserted */
        self->reset = devm_gpiod_get_optional(&func->dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(self->reset))
                return dev_err_probe(&func->dev, PTR_ERR(self->reset),
                                     "could not get reset GPIO\n");
        gpiod_set_consumer_name(self->reset, "cw1200_wlan_reset");

        self->powerup = devm_gpiod_get_optional(&func->dev, "powerup", GPIOD_OUT_LOW);
        if (IS_ERR(self->powerup))
                return dev_err_probe(&func->dev, PTR_ERR(self->powerup),
                                     "could not get powerup GPIO\n");
        gpiod_set_consumer_name(self->reset, "cw1200_wlan_powerup");

        if (cw1200_spi_on(self, plat_data)) {
                pr_err("spi_on() failed!\n");
                return -ENODEV;
        }

        if (spi_setup(func)) {
                pr_err("spi_setup() failed!\n");
                return -ENODEV;
        }

        self->pdata = plat_data;
        self->func = func;
        spin_lock_init(&self->lock);

        spi_set_drvdata(func, self);

        init_waitqueue_head(&self->wq);

        status = cw1200_spi_irq_subscribe(self);

        status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
                                   self, &func->dev, &self->core,
                                   self->pdata->ref_clk,
                                   self->pdata->macaddr,
                                   self->pdata->sdd_file,
                                   self->pdata->have_5ghz);

        if (status) {
                cw1200_spi_irq_unsubscribe(self);
                cw1200_spi_off(self, plat_data);
        }

        return status;
}

/* Disconnect Function to be called by SPI stack when device is disconnected */
static void cw1200_spi_disconnect(struct spi_device *func)
{
        struct hwbus_priv *self = spi_get_drvdata(func);

        if (self) {
                cw1200_spi_irq_unsubscribe(self);
                if (self->core) {
                        cw1200_core_release(self->core);
                        self->core = NULL;
                }
                cw1200_spi_off(self, dev_get_platdata(&func->dev));
        }
}

static int __maybe_unused cw1200_spi_suspend(struct device *dev)
{
        struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev));

        if (self && !cw1200_can_suspend(self->core))
                return -EAGAIN;

        /* XXX notify host that we have to keep CW1200 powered on? */
        return 0;
}

static SIMPLE_DEV_PM_OPS(cw1200_pm_ops, cw1200_spi_suspend, NULL);

static struct spi_driver spi_driver = {
        .probe          = cw1200_spi_probe,
        .remove         = cw1200_spi_disconnect,
        .driver = {
                .name           = "cw1200_wlan_spi",
                .pm             = IS_ENABLED(CONFIG_PM) ? &cw1200_pm_ops : NULL,
        },
};

module_spi_driver(spi_driver);