2 * This file is part of wl1251
4 * Copyright (C) 2008 Nokia Corporation
6 * Contact: Kalle Valo <kalle.valo@nokia.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 #include <linux/module.h>
25 #include <linux/crc7.h>
26 #include <linux/spi/spi.h>
30 #include "wl1251_spi.h"
32 static void wl1251_spi_reset(struct wl1251 *wl)
35 struct spi_transfer t;
38 cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
40 wl1251_error("could not allocate cmd for spi reset");
44 memset(&t, 0, sizeof(t));
47 memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
50 t.len = WSPI_INIT_CMD_LEN;
51 spi_message_add_tail(&t, &m);
53 spi_sync(wl->spi, &m);
55 wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
58 static void wl1251_spi_init(struct wl1251 *wl)
60 u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
61 struct spi_transfer t;
64 cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
66 wl1251_error("could not allocate cmd for spi init");
70 memset(crc, 0, sizeof(crc));
71 memset(&t, 0, sizeof(t));
75 * Set WSPI_INIT_COMMAND
76 * the data is being send from the MSB to LSB
80 cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
83 cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
84 cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
86 if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
87 cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
89 cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
91 cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
92 | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
100 cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
101 cmd[4] |= WSPI_INIT_CMD_END;
104 t.len = WSPI_INIT_CMD_LEN;
105 spi_message_add_tail(&t, &m);
107 spi_sync(wl->spi, &m);
109 wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
112 static void wl1251_spi_reset_wake(struct wl1251 *wl)
114 wl1251_spi_reset(wl);
118 static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
121 struct spi_transfer t[3];
122 struct spi_message m;
126 cmd = &wl->buffer_cmd;
127 busy_buf = wl->buffer_busyword;
130 *cmd |= WSPI_CMD_READ;
131 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
132 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
134 spi_message_init(&m);
135 memset(t, 0, sizeof(t));
139 spi_message_add_tail(&t[0], &m);
141 /* Busy and non busy words read */
142 t[1].rx_buf = busy_buf;
143 t[1].len = WL1251_BUSY_WORD_LEN;
144 spi_message_add_tail(&t[1], &m);
148 spi_message_add_tail(&t[2], &m);
150 spi_sync(wl->spi, &m);
152 /* FIXME: check busy words */
154 wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
155 wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
158 static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
161 struct spi_transfer t[2];
162 struct spi_message m;
165 cmd = &wl->buffer_cmd;
168 *cmd |= WSPI_CMD_WRITE;
169 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
170 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
172 spi_message_init(&m);
173 memset(t, 0, sizeof(t));
176 t[0].len = sizeof(*cmd);
177 spi_message_add_tail(&t[0], &m);
181 spi_message_add_tail(&t[1], &m);
183 spi_sync(wl->spi, &m);
185 wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
186 wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
189 const struct wl1251_if_operations wl1251_spi_ops = {
190 .read = wl1251_spi_read,
191 .write = wl1251_spi_write,
192 .reset = wl1251_spi_reset_wake,