cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spi.c (7429B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of wl1251
      4 *
      5 * Copyright (C) 2008 Nokia Corporation
      6 */
      7
      8#include <linux/interrupt.h>
      9#include <linux/irq.h>
     10#include <linux/module.h>
     11#include <linux/slab.h>
     12#include <linux/swab.h>
     13#include <linux/crc7.h>
     14#include <linux/spi/spi.h>
     15#include <linux/wl12xx.h>
     16#include <linux/gpio.h>
     17#include <linux/of.h>
     18#include <linux/of_gpio.h>
     19#include <linux/regulator/consumer.h>
     20
     21#include "wl1251.h"
     22#include "reg.h"
     23#include "spi.h"
     24
     25static irqreturn_t wl1251_irq(int irq, void *cookie)
     26{
     27	struct wl1251 *wl;
     28
     29	wl1251_debug(DEBUG_IRQ, "IRQ");
     30
     31	wl = cookie;
     32
     33	ieee80211_queue_work(wl->hw, &wl->irq_work);
     34
     35	return IRQ_HANDLED;
     36}
     37
     38static struct spi_device *wl_to_spi(struct wl1251 *wl)
     39{
     40	return wl->if_priv;
     41}
     42
     43static void wl1251_spi_reset(struct wl1251 *wl)
     44{
     45	u8 *cmd;
     46	struct spi_transfer t;
     47	struct spi_message m;
     48
     49	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
     50	if (!cmd) {
     51		wl1251_error("could not allocate cmd for spi reset");
     52		return;
     53	}
     54
     55	memset(&t, 0, sizeof(t));
     56	spi_message_init(&m);
     57
     58	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
     59
     60	t.tx_buf = cmd;
     61	t.len = WSPI_INIT_CMD_LEN;
     62	spi_message_add_tail(&t, &m);
     63
     64	spi_sync(wl_to_spi(wl), &m);
     65
     66	wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
     67
     68	kfree(cmd);
     69}
     70
     71static void wl1251_spi_wake(struct wl1251 *wl)
     72{
     73	struct spi_transfer t;
     74	struct spi_message m;
     75	u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
     76
     77	if (!cmd) {
     78		wl1251_error("could not allocate cmd for spi init");
     79		return;
     80	}
     81
     82	memset(&t, 0, sizeof(t));
     83	spi_message_init(&m);
     84
     85	/* Set WSPI_INIT_COMMAND
     86	 * the data is being send from the MSB to LSB
     87	 */
     88	cmd[0] = 0xff;
     89	cmd[1] = 0xff;
     90	cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
     91	cmd[3] = 0;
     92	cmd[4] = 0;
     93	cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
     94	cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
     95
     96	cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
     97		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
     98
     99	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
    100		cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
    101	else
    102		cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
    103
    104	cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END;
    105	/*
    106	 * The above is the logical order; it must actually be stored
    107	 * in the buffer byte-swapped.
    108	 */
    109	__swab32s((u32 *)cmd);
    110	__swab32s((u32 *)cmd+1);
    111
    112	t.tx_buf = cmd;
    113	t.len = WSPI_INIT_CMD_LEN;
    114	spi_message_add_tail(&t, &m);
    115
    116	spi_sync(wl_to_spi(wl), &m);
    117
    118	wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
    119
    120	kfree(cmd);
    121}
    122
    123static void wl1251_spi_reset_wake(struct wl1251 *wl)
    124{
    125	wl1251_spi_reset(wl);
    126	wl1251_spi_wake(wl);
    127}
    128
    129static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
    130			    size_t len)
    131{
    132	struct spi_transfer t[3];
    133	struct spi_message m;
    134	u8 *busy_buf;
    135	u32 *cmd;
    136
    137	cmd = &wl->buffer_cmd;
    138	busy_buf = wl->buffer_busyword;
    139
    140	*cmd = 0;
    141	*cmd |= WSPI_CMD_READ;
    142	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
    143	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
    144
    145	spi_message_init(&m);
    146	memset(t, 0, sizeof(t));
    147
    148	t[0].tx_buf = cmd;
    149	t[0].len = 4;
    150	spi_message_add_tail(&t[0], &m);
    151
    152	/* Busy and non busy words read */
    153	t[1].rx_buf = busy_buf;
    154	t[1].len = WL1251_BUSY_WORD_LEN;
    155	spi_message_add_tail(&t[1], &m);
    156
    157	t[2].rx_buf = buf;
    158	t[2].len = len;
    159	spi_message_add_tail(&t[2], &m);
    160
    161	spi_sync(wl_to_spi(wl), &m);
    162
    163	/* FIXME: check busy words */
    164
    165	wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
    166	wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
    167}
    168
    169static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
    170			     size_t len)
    171{
    172	struct spi_transfer t[2];
    173	struct spi_message m;
    174	u32 *cmd;
    175
    176	cmd = &wl->buffer_cmd;
    177
    178	*cmd = 0;
    179	*cmd |= WSPI_CMD_WRITE;
    180	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
    181	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
    182
    183	spi_message_init(&m);
    184	memset(t, 0, sizeof(t));
    185
    186	t[0].tx_buf = cmd;
    187	t[0].len = sizeof(*cmd);
    188	spi_message_add_tail(&t[0], &m);
    189
    190	t[1].tx_buf = buf;
    191	t[1].len = len;
    192	spi_message_add_tail(&t[1], &m);
    193
    194	spi_sync(wl_to_spi(wl), &m);
    195
    196	wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
    197	wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
    198}
    199
    200static void wl1251_spi_enable_irq(struct wl1251 *wl)
    201{
    202	return enable_irq(wl->irq);
    203}
    204
    205static void wl1251_spi_disable_irq(struct wl1251 *wl)
    206{
    207	return disable_irq(wl->irq);
    208}
    209
    210static int wl1251_spi_set_power(struct wl1251 *wl, bool enable)
    211{
    212	if (gpio_is_valid(wl->power_gpio))
    213		gpio_set_value(wl->power_gpio, enable);
    214
    215	return 0;
    216}
    217
    218static const struct wl1251_if_operations wl1251_spi_ops = {
    219	.read = wl1251_spi_read,
    220	.write = wl1251_spi_write,
    221	.reset = wl1251_spi_reset_wake,
    222	.enable_irq = wl1251_spi_enable_irq,
    223	.disable_irq = wl1251_spi_disable_irq,
    224	.power = wl1251_spi_set_power,
    225};
    226
    227static int wl1251_spi_probe(struct spi_device *spi)
    228{
    229	struct wl1251_platform_data *pdata = dev_get_platdata(&spi->dev);
    230	struct device_node *np = spi->dev.of_node;
    231	struct ieee80211_hw *hw;
    232	struct wl1251 *wl;
    233	int ret;
    234
    235	if (!np && !pdata) {
    236		wl1251_error("no platform data");
    237		return -ENODEV;
    238	}
    239
    240	hw = wl1251_alloc_hw();
    241	if (IS_ERR(hw))
    242		return PTR_ERR(hw);
    243
    244	wl = hw->priv;
    245
    246	SET_IEEE80211_DEV(hw, &spi->dev);
    247	spi_set_drvdata(spi, wl);
    248	wl->if_priv = spi;
    249	wl->if_ops = &wl1251_spi_ops;
    250
    251	/* This is the only SPI value that we need to set here, the rest
    252	 * comes from the board-peripherals file
    253	 */
    254	spi->bits_per_word = 32;
    255
    256	ret = spi_setup(spi);
    257	if (ret < 0) {
    258		wl1251_error("spi_setup failed");
    259		goto out_free;
    260	}
    261
    262	if (np) {
    263		wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom");
    264		wl->power_gpio = of_get_named_gpio(np, "ti,power-gpio", 0);
    265	} else if (pdata) {
    266		wl->power_gpio = pdata->power_gpio;
    267		wl->use_eeprom = pdata->use_eeprom;
    268	}
    269
    270	if (wl->power_gpio == -EPROBE_DEFER) {
    271		ret = -EPROBE_DEFER;
    272		goto out_free;
    273	}
    274
    275	if (gpio_is_valid(wl->power_gpio)) {
    276		ret = devm_gpio_request_one(&spi->dev, wl->power_gpio,
    277					GPIOF_OUT_INIT_LOW, "wl1251 power");
    278		if (ret) {
    279			wl1251_error("Failed to request gpio: %d\n", ret);
    280			goto out_free;
    281		}
    282	} else {
    283		wl1251_error("set power gpio missing in platform data");
    284		ret = -ENODEV;
    285		goto out_free;
    286	}
    287
    288	wl->irq = spi->irq;
    289	if (wl->irq < 0) {
    290		wl1251_error("irq missing in platform data");
    291		ret = -ENODEV;
    292		goto out_free;
    293	}
    294
    295	irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
    296	ret = devm_request_irq(&spi->dev, wl->irq, wl1251_irq, 0,
    297							DRIVER_NAME, wl);
    298	if (ret < 0) {
    299		wl1251_error("request_irq() failed: %d", ret);
    300		goto out_free;
    301	}
    302
    303	irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
    304
    305	wl->vio = devm_regulator_get(&spi->dev, "vio");
    306	if (IS_ERR(wl->vio)) {
    307		ret = PTR_ERR(wl->vio);
    308		wl1251_error("vio regulator missing: %d", ret);
    309		goto out_free;
    310	}
    311
    312	ret = regulator_enable(wl->vio);
    313	if (ret)
    314		goto out_free;
    315
    316	ret = wl1251_init_ieee80211(wl);
    317	if (ret)
    318		goto disable_regulator;
    319
    320	return 0;
    321
    322disable_regulator:
    323	regulator_disable(wl->vio);
    324out_free:
    325	ieee80211_free_hw(hw);
    326
    327	return ret;
    328}
    329
    330static void wl1251_spi_remove(struct spi_device *spi)
    331{
    332	struct wl1251 *wl = spi_get_drvdata(spi);
    333
    334	wl1251_free_hw(wl);
    335	regulator_disable(wl->vio);
    336}
    337
    338static struct spi_driver wl1251_spi_driver = {
    339	.driver = {
    340		.name		= DRIVER_NAME,
    341	},
    342
    343	.probe		= wl1251_spi_probe,
    344	.remove		= wl1251_spi_remove,
    345};
    346
    347module_spi_driver(wl1251_spi_driver);
    348
    349MODULE_LICENSE("GPL");
    350MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
    351MODULE_ALIAS("spi:wl1251");