brcm80211: fmac: chip attach code flow clean up
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / sdio_chip.c
CommitLineData
a83369b6
FL
1/*
2 * Copyright (c) 2011 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/* ***** SDIO interface chip backplane handle functions ***** */
17
18#include <linux/types.h>
19#include <linux/netdevice.h>
20#include <linux/mmc/card.h>
21#include <chipcommon.h>
22#include <brcm_hw_ids.h>
23#include <brcmu_wifi.h>
24#include <brcmu_utils.h>
2d4a9af1 25#include <soc.h>
a83369b6
FL
26#include "dhd.h"
27#include "dhd_dbg.h"
28#include "sdio_host.h"
29#include "sdio_chip.h"
30
31/* chip core base & ramsize */
32/* bcm4329 */
33/* SDIO device core, ID 0x829 */
34#define BCM4329_CORE_BUS_BASE 0x18011000
35/* internal memory core, ID 0x80e */
36#define BCM4329_CORE_SOCRAM_BASE 0x18003000
37/* ARM Cortex M3 core, ID 0x82a */
38#define BCM4329_CORE_ARM_BASE 0x18002000
39#define BCM4329_RAMSIZE 0x48000
40
41
42/* SB regs */
43/* sbidhigh */
44#define SBIDH_RC_MASK 0x000f /* revision code */
45#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
46#define SBIDH_RCE_SHIFT 8
47#define SBCOREREV(sbidh) \
48 ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
49 ((sbidh) & SBIDH_RC_MASK))
50#define SBIDH_CC_MASK 0x8ff0 /* core code */
51#define SBIDH_CC_SHIFT 4
52#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
53#define SBIDH_VC_SHIFT 16
54
2d4a9af1
FL
55void
56brcmf_sdio_chip_coredisable(struct brcmf_sdio_dev *sdiodev, u32 corebase)
57{
58 u32 regdata;
59
60 regdata = brcmf_sdcard_reg_read(sdiodev,
61 CORE_SB(corebase, sbtmstatelow), 4);
62 if (regdata & SBTML_RESET)
63 return;
64
65 regdata = brcmf_sdcard_reg_read(sdiodev,
66 CORE_SB(corebase, sbtmstatelow), 4);
67 if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
68 /*
69 * set target reject and spin until busy is clear
70 * (preserve core-specific bits)
71 */
72 regdata = brcmf_sdcard_reg_read(sdiodev,
73 CORE_SB(corebase, sbtmstatelow), 4);
74 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
75 4, regdata | SBTML_REJ);
76
77 regdata = brcmf_sdcard_reg_read(sdiodev,
78 CORE_SB(corebase, sbtmstatelow), 4);
79 udelay(1);
80 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
81 CORE_SB(corebase, sbtmstatehigh), 4) &
82 SBTMH_BUSY), 100000);
83
84 regdata = brcmf_sdcard_reg_read(sdiodev,
85 CORE_SB(corebase, sbtmstatehigh), 4);
86 if (regdata & SBTMH_BUSY)
87 brcmf_dbg(ERROR, "core state still busy\n");
88
89 regdata = brcmf_sdcard_reg_read(sdiodev,
90 CORE_SB(corebase, sbidlow), 4);
91 if (regdata & SBIDL_INIT) {
92 regdata = brcmf_sdcard_reg_read(sdiodev,
93 CORE_SB(corebase, sbimstate), 4) |
94 SBIM_RJ;
95 brcmf_sdcard_reg_write(sdiodev,
96 CORE_SB(corebase, sbimstate), 4,
97 regdata);
98 regdata = brcmf_sdcard_reg_read(sdiodev,
99 CORE_SB(corebase, sbimstate), 4);
100 udelay(1);
101 SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
102 CORE_SB(corebase, sbimstate), 4) &
103 SBIM_BY), 100000);
104 }
105
106 /* set reset and reject while enabling the clocks */
107 brcmf_sdcard_reg_write(sdiodev,
108 CORE_SB(corebase, sbtmstatelow), 4,
109 (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
110 SBTML_REJ | SBTML_RESET));
111 regdata = brcmf_sdcard_reg_read(sdiodev,
112 CORE_SB(corebase, sbtmstatelow), 4);
113 udelay(10);
114
115 /* clear the initiator reject bit */
116 regdata = brcmf_sdcard_reg_read(sdiodev,
117 CORE_SB(corebase, sbidlow), 4);
118 if (regdata & SBIDL_INIT) {
119 regdata = brcmf_sdcard_reg_read(sdiodev,
120 CORE_SB(corebase, sbimstate), 4) &
121 ~SBIM_RJ;
122 brcmf_sdcard_reg_write(sdiodev,
123 CORE_SB(corebase, sbimstate), 4,
124 regdata);
125 }
126 }
127
128 /* leave reset and reject asserted */
129 brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
130 (SBTML_REJ | SBTML_RESET));
131 udelay(1);
132}
133
a83369b6
FL
134static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
135 struct chip_info *ci, u32 regs)
136{
137 u32 regdata;
138
139 /*
140 * Get CC core rev
141 * Chipid is assume to be at offset 0 from regs arg
142 * For different chiptypes or old sdio hosts w/o chipcommon,
143 * other ways of recognition should be added here.
144 */
145 ci->cccorebase = regs;
146 regdata = brcmf_sdcard_reg_read(sdiodev,
147 CORE_CC_REG(ci->cccorebase, chipid), 4);
148 ci->chip = regdata & CID_ID_MASK;
149 ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
150
151 brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
152
153 /* Address of cores for new chips should be added here */
154 switch (ci->chip) {
155 case BCM4329_CHIP_ID:
156 ci->buscorebase = BCM4329_CORE_BUS_BASE;
157 ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
158 ci->armcorebase = BCM4329_CORE_ARM_BASE;
159 ci->ramsize = BCM4329_RAMSIZE;
160 break;
161 default:
162 brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
163 return -ENODEV;
164 }
165
a83369b6
FL
166 return 0;
167}
168
e63ac6b8
FL
169static int
170brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
171{
172 int err = 0;
173 u8 clkval, clkset;
174
175 /* Try forcing SDIO core to do ALPAvail request only */
176 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
177 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
178 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
179 if (err) {
180 brcmf_dbg(ERROR, "error writing for HT off\n");
181 return err;
182 }
183
184 /* If register supported, wait for ALPAvail and then force ALP */
185 /* This may take up to 15 milliseconds */
186 clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
187 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
188
189 if ((clkval & ~SBSDIO_AVBITS) != clkset) {
190 brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
191 clkset, clkval);
192 return -EACCES;
193 }
194
195 SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
196 SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
197 !SBSDIO_ALPAV(clkval)),
198 PMU_MAX_TRANSITION_DLY);
199 if (!SBSDIO_ALPAV(clkval)) {
200 brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
201 clkval);
202 return -EBUSY;
203 }
204
205 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
206 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
207 SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
208 udelay(65);
209
210 /* Also, disable the extra SDIO pull-ups */
211 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
212 SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
213
214 return 0;
215}
216
5b45e54e
FL
217static void
218brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
219 struct chip_info *ci)
220{
221 u32 regdata;
222
223 /* get chipcommon rev */
224 regdata = brcmf_sdcard_reg_read(sdiodev,
225 CORE_SB(ci->cccorebase, sbidhigh), 4);
226 ci->ccrev = SBCOREREV(regdata);
227
228 /* get chipcommon capabilites */
229 ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
230 CORE_CC_REG(ci->cccorebase, capabilities), 4);
231
232 /* get pmu caps & rev */
233 if (ci->cccaps & CC_CAP_PMU) {
234 ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
235 CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
236 ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
237 }
238
239 regdata = brcmf_sdcard_reg_read(sdiodev,
240 CORE_SB(ci->buscorebase, sbidhigh), 4);
241 ci->buscorerev = SBCOREREV(regdata);
242 ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
243
244 brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
245 ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
966414da
FL
246
247 /*
248 * Make sure any on-chip ARM is off (in case strapping is wrong),
249 * or downloaded code was already running.
250 */
251 brcmf_sdio_chip_coredisable(sdiodev, ci->armcorebase);
5b45e54e
FL
252}
253
a83369b6 254int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
a97e4fc5 255 struct chip_info **ci_ptr, u32 regs)
a83369b6 256{
a97e4fc5
FL
257 int ret;
258 struct chip_info *ci;
259
260 brcmf_dbg(TRACE, "Enter\n");
261
262 /* alloc chip_info_t */
263 ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
264 if (!ci)
265 return -ENOMEM;
a83369b6 266
e63ac6b8
FL
267 ret = brcmf_sdio_chip_buscoreprep(sdiodev);
268 if (ret != 0)
a97e4fc5 269 goto err;
e63ac6b8 270
a83369b6
FL
271 ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
272 if (ret != 0)
a97e4fc5 273 goto err;
a83369b6 274
5b45e54e
FL
275 brcmf_sdio_chip_buscoresetup(sdiodev, ci);
276
960908dc
FL
277 brcmf_sdcard_reg_write(sdiodev,
278 CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
279 brcmf_sdcard_reg_write(sdiodev,
280 CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
281
a97e4fc5
FL
282 *ci_ptr = ci;
283 return 0;
284
285err:
286 kfree(ci);
a83369b6
FL
287 return ret;
288}
This page took 0.035585 seconds and 5 git commands to generate.