wl1251: make wl1251_set_partition bus agnostic
[pandora-kernel.git] / drivers / net / wireless / wl12xx / wl1251_spi.c
1 /*
2  * This file is part of wl1251
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  *
6  * Contact: Kalle Valo <kalle.valo@nokia.com>
7  *
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.
11  *
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.
16  *
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
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/module.h>
25 #include <linux/crc7.h>
26 #include <linux/spi/spi.h>
27
28 #include "wl1251.h"
29 #include "reg.h"
30 #include "wl1251_spi.h"
31
32 static void wl1251_spi_reset(struct wl1251 *wl)
33 {
34         u8 *cmd;
35         struct spi_transfer t;
36         struct spi_message m;
37
38         cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
39         if (!cmd) {
40                 wl1251_error("could not allocate cmd for spi reset");
41                 return;
42         }
43
44         memset(&t, 0, sizeof(t));
45         spi_message_init(&m);
46
47         memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
48
49         t.tx_buf = cmd;
50         t.len = WSPI_INIT_CMD_LEN;
51         spi_message_add_tail(&t, &m);
52
53         spi_sync(wl->spi, &m);
54
55         wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
56 }
57
58 static void wl1251_spi_init(struct wl1251 *wl)
59 {
60         u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
61         struct spi_transfer t;
62         struct spi_message m;
63
64         cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
65         if (!cmd) {
66                 wl1251_error("could not allocate cmd for spi init");
67                 return;
68         }
69
70         memset(crc, 0, sizeof(crc));
71         memset(&t, 0, sizeof(t));
72         spi_message_init(&m);
73
74         /*
75          * Set WSPI_INIT_COMMAND
76          * the data is being send from the MSB to LSB
77          */
78         cmd[2] = 0xff;
79         cmd[3] = 0xff;
80         cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
81         cmd[0] = 0;
82         cmd[7] = 0;
83         cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
84         cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
85
86         if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
87                 cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
88         else
89                 cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
90
91         cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
92                 | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
93
94         crc[0] = cmd[1];
95         crc[1] = cmd[0];
96         crc[2] = cmd[7];
97         crc[3] = cmd[6];
98         crc[4] = cmd[5];
99
100         cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
101         cmd[4] |= WSPI_INIT_CMD_END;
102
103         t.tx_buf = cmd;
104         t.len = WSPI_INIT_CMD_LEN;
105         spi_message_add_tail(&t, &m);
106
107         spi_sync(wl->spi, &m);
108
109         wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
110 }
111
112 static void wl1251_spi_reset_wake(struct wl1251 *wl)
113 {
114         wl1251_spi_reset(wl);
115         wl1251_spi_init(wl);
116 }
117
118 static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
119                             size_t len)
120 {
121         struct spi_transfer t[3];
122         struct spi_message m;
123         u8 *busy_buf;
124         u32 *cmd;
125
126         cmd = &wl->buffer_cmd;
127         busy_buf = wl->buffer_busyword;
128
129         *cmd = 0;
130         *cmd |= WSPI_CMD_READ;
131         *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
132         *cmd |= addr & WSPI_CMD_BYTE_ADDR;
133
134         spi_message_init(&m);
135         memset(t, 0, sizeof(t));
136
137         t[0].tx_buf = cmd;
138         t[0].len = 4;
139         spi_message_add_tail(&t[0], &m);
140
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);
145
146         t[2].rx_buf = buf;
147         t[2].len = len;
148         spi_message_add_tail(&t[2], &m);
149
150         spi_sync(wl->spi, &m);
151
152         /* FIXME: check busy words */
153
154         wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
155         wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
156 }
157
158 static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
159                              size_t len)
160 {
161         struct spi_transfer t[2];
162         struct spi_message m;
163         u32 *cmd;
164
165         cmd = &wl->buffer_cmd;
166
167         *cmd = 0;
168         *cmd |= WSPI_CMD_WRITE;
169         *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
170         *cmd |= addr & WSPI_CMD_BYTE_ADDR;
171
172         spi_message_init(&m);
173         memset(t, 0, sizeof(t));
174
175         t[0].tx_buf = cmd;
176         t[0].len = sizeof(*cmd);
177         spi_message_add_tail(&t[0], &m);
178
179         t[1].tx_buf = buf;
180         t[1].len = len;
181         spi_message_add_tail(&t[1], &m);
182
183         spi_sync(wl->spi, &m);
184
185         wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
186         wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
187 }
188
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,
193 };