blob: 83ed48d206b2baf7eeccbb6acdd4b58c420c903e [file] [log] [blame]
Luciano Coelhob2ba99f2011-11-20 23:32:10 +02001/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2010 Nokia Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/platform_device.h>
24
Luciano Coelhoffeb5012011-11-21 18:55:51 +020025#include <linux/err.h>
26
Luciano Coelhob2ba99f2011-11-20 23:32:10 +020027#include "../wlcore/wlcore.h"
Luciano Coelhoffeb5012011-11-21 18:55:51 +020028#include "../wlcore/debug.h"
29
Luciano Coelho00782132011-11-29 13:38:37 +020030#include "reg.h"
Luciano Coelho25a43d72011-11-21 20:37:14 +020031
Luciano Coelho25a43d72011-11-21 20:37:14 +020032static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = {
33 [PART_DOWN] = {
34 .mem = {
35 .start = 0x00000000,
36 .size = 0x000177c0
37 },
38 .reg = {
39 .start = REGISTERS_BASE,
40 .size = 0x00008800
41 },
42 .mem2 = {
43 .start = 0x00000000,
44 .size = 0x00000000
45 },
46 .mem3 = {
47 .start = 0x00000000,
48 .size = 0x00000000
49 },
50 },
51
Luciano Coelho00782132011-11-29 13:38:37 +020052 [PART_BOOT] = { /* in wl12xx we can use a mix of work and down
53 * partition here */
54 .mem = {
55 .start = 0x00040000,
56 .size = 0x00014fc0
57 },
58 .reg = {
59 .start = REGISTERS_BASE,
60 .size = 0x00008800
61 },
62 .mem2 = {
63 .start = 0x00000000,
64 .size = 0x00000000
65 },
66 .mem3 = {
67 .start = 0x00000000,
68 .size = 0x00000000
69 },
70 },
71
Luciano Coelho25a43d72011-11-21 20:37:14 +020072 [PART_WORK] = {
73 .mem = {
74 .start = 0x00040000,
75 .size = 0x00014fc0
76 },
77 .reg = {
78 .start = REGISTERS_BASE,
79 .size = 0x0000a000
80 },
81 .mem2 = {
82 .start = 0x003004f8,
83 .size = 0x00000004
84 },
85 .mem3 = {
86 .start = 0x00040404,
87 .size = 0x00000000
88 },
89 },
90
91 [PART_DRPW] = {
92 .mem = {
93 .start = 0x00040000,
94 .size = 0x00014fc0
95 },
96 .reg = {
97 .start = DRPW_BASE,
98 .size = 0x00006000
99 },
100 .mem2 = {
101 .start = 0x00000000,
102 .size = 0x00000000
103 },
104 .mem3 = {
105 .start = 0x00000000,
106 .size = 0x00000000
107 }
108 }
109};
110
Luciano Coelho00782132011-11-29 13:38:37 +0200111static const int wl12xx_rtable[REG_TABLE_LEN] = {
112 [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL,
113 [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR,
114 [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK,
115 [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR,
116 [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR,
117 [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG,
118 [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK,
119 [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4,
120 [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B,
121 [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS,
122
123 /* data access memory addresses, used with partition translation */
124 [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA,
125 [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA,
126
127 /* raw data access memory addresses */
128 [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR,
129};
130
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200131/* TODO: maybe move to a new header file? */
132#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
133#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
134#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
135
136#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
137#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
138#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
139
140static int wl12xx_identify_chip(struct wl1271 *wl)
141{
142 int ret = 0;
143
144 switch (wl->chip.id) {
145 case CHIP_ID_1271_PG10:
146 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
147 wl->chip.id);
148
149 wl->quirks |= WLCORE_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
150 wl->plt_fw_name = WL127X_PLT_FW_NAME;
151 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
152 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
153 break;
154
155 case CHIP_ID_1271_PG20:
156 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
157 wl->chip.id);
158
159 wl->quirks |= WLCORE_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
160 wl->plt_fw_name = WL127X_PLT_FW_NAME;
161 wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
162 wl->mr_fw_name = WL127X_FW_NAME_MULTI;
163 break;
164
165 case CHIP_ID_1283_PG20:
166 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
167 wl->chip.id);
168 wl->plt_fw_name = WL128X_PLT_FW_NAME;
169 wl->sr_fw_name = WL128X_FW_NAME_SINGLE;
170 wl->mr_fw_name = WL128X_FW_NAME_MULTI;
171 break;
172 case CHIP_ID_1283_PG10:
173 default:
174 wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
175 ret = -ENODEV;
176 goto out;
177 }
178
179out:
180 return ret;
181}
182
183static struct wlcore_ops wl12xx_ops = {
184 .identify_chip = wl12xx_identify_chip,
185};
186
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200187static int __devinit wl12xx_probe(struct platform_device *pdev)
188{
189 struct wl1271 *wl;
190 struct ieee80211_hw *hw;
191
192 hw = wlcore_alloc_hw();
193 if (IS_ERR(hw)) {
194 wl1271_error("can't allocate hw");
195 return PTR_ERR(hw);
196 }
197
198 wl = hw->priv;
Luciano Coelhoc31be252011-11-21 19:25:24 +0200199 wl->ops = &wl12xx_ops;
Luciano Coelho25a43d72011-11-21 20:37:14 +0200200 wl->ptable = wl12xx_ptable;
Luciano Coelho00782132011-11-29 13:38:37 +0200201 wl->rtable = wl12xx_rtable;
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200202
203 return wlcore_probe(wl, pdev);
204}
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200205
206static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
207 { "wl12xx", 0 },
208 { } /* Terminating Entry */
209};
210MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
211
212static struct platform_driver wl12xx_driver = {
Luciano Coelhoffeb5012011-11-21 18:55:51 +0200213 .probe = wl12xx_probe,
Luciano Coelhob2ba99f2011-11-20 23:32:10 +0200214 .remove = __devexit_p(wlcore_remove),
215 .id_table = wl12xx_id_table,
216 .driver = {
217 .name = "wl12xx_driver",
218 .owner = THIS_MODULE,
219 }
220};
221
222static int __init wl12xx_init(void)
223{
224 return platform_driver_register(&wl12xx_driver);
225}
226module_init(wl12xx_init);
227
228static void __exit wl12xx_exit(void)
229{
230 platform_driver_unregister(&wl12xx_driver);
231}
232module_exit(wl12xx_exit);
233
234MODULE_LICENSE("GPL v2");
235MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
Luciano Coelho6f7dd162011-11-29 16:27:31 +0200236MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
237MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
238MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
239MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
240MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
241MODULE_FIRMWARE(WL128X_PLT_FW_NAME);