2c7828cf5fd17cbf3a3bd5698e18c97617ed20c0
[oweals/openwrt.git] /
1 From 35cb51b2162a1a7c5cd977f92595e60ab14d3b22 Mon Sep 17 00:00:00 2001
2 From: Chi-Hsien Lin <Chi-Hsien.Lin@cypress.com>
3 Date: Wed, 21 Nov 2018 07:53:47 +0000
4 Subject: [PATCH] brcmfmac: add support for CYW43012 SDIO chipset
5
6 CYW43012 is a 1x1 802.11a/b/g/n Dual-Band HT20, 256-QAM/Turbo QAM. It
7 is an Ultra Low Power WLAN+BT combo chip.
8
9 Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
10 Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
11 Signed-off-by: Praveen Babu C <praveen.chandran@cypress.com>
12 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
13 ---
14  .../broadcom/brcm80211/brcmfmac/bcmsdh.c      |  1 +
15  .../broadcom/brcm80211/brcmfmac/chip.c        | 14 +++-
16  .../broadcom/brcm80211/brcmfmac/sdio.c        | 74 ++++++++++++++++---
17  .../broadcom/brcm80211/include/brcm_hw_ids.h  |  1 +
18  include/linux/mmc/sdio_ids.h                  |  1 +
19  5 files changed, 78 insertions(+), 13 deletions(-)
20
21 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
22 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
23 @@ -972,6 +972,7 @@ static const struct sdio_device_id brcmf
24         BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
25         BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
26         BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373),
27 +       BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_43012),
28         { /* end: all zeroes */ }
29  };
30  MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
31 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
32 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
33 @@ -165,6 +165,7 @@ struct sbconfig {
34  #define SRCI_LSS_MASK          0x00f00000
35  #define SRCI_LSS_SHIFT         20
36  #define        SRCI_SRNB_MASK          0xf0
37 +#define        SRCI_SRNB_MASK_EXT      0x100
38  #define        SRCI_SRNB_SHIFT         4
39  #define        SRCI_SRBSZ_MASK         0xf
40  #define        SRCI_SRBSZ_SHIFT        0
41 @@ -592,7 +593,13 @@ static void brcmf_chip_socram_ramsize(st
42                 if (lss != 0)
43                         *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
44         } else {
45 -               nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
46 +               /* length of SRAM Banks increased for corerev greater than 23 */
47 +               if (sr->pub.rev >= 23) {
48 +                       nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT))
49 +                               >> SRCI_SRNB_SHIFT;
50 +               } else {
51 +                       nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
52 +               }
53                 for (i = 0; i < nb; i++) {
54                         retent = brcmf_chip_socram_banksize(sr, i, &banksize);
55                         *ramsize += banksize;
56 @@ -1356,6 +1363,11 @@ bool brcmf_chip_sr_capable(struct brcmf_
57                 addr = CORE_CC_REG(base, sr_control1);
58                 reg = chip->ops->read32(chip->ctx, addr);
59                 return reg != 0;
60 +       case CY_CC_43012_CHIP_ID:
61 +               addr = CORE_CC_REG(pmu->base, retention_ctl);
62 +               reg = chip->ops->read32(chip->ctx, addr);
63 +               return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
64 +                              PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
65         default:
66                 addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
67                 reg = chip->ops->read32(chip->ctx, addr);
68 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
69 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
70 @@ -624,6 +624,7 @@ BRCMF_FW_DEF(43455, "brcmfmac43455-sdio"
71  BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
72  BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
73  BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
74 +BRCMF_FW_DEF(43012, "brcmfmac43012-sdio");
75  
76  static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
77         BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
78 @@ -643,7 +644,8 @@ static const struct brcmf_firmware_mappi
79         BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
80         BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
81         BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
82 -       BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
83 +       BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
84 +       BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012)
85  };
86  
87  static void pkt_align(struct sk_buff *p, int len, int align)
88 @@ -683,6 +685,14 @@ brcmf_sdio_kso_control(struct brcmf_sdio
89         /* 1st KSO write goes to AOS wake up core if device is asleep  */
90         brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
91  
92 +       /* In case of 43012 chip, the chip could go down immediately after
93 +        * KSO bit is cleared. So the further reads of KSO register could
94 +        * fail. Thereby just bailing out immediately after clearing KSO
95 +        * bit, to avoid polling of KSO bit.
96 +        */
97 +       if (!on && bus->ci->chip == CY_CC_43012_CHIP_ID)
98 +               return err;
99 +
100         if (on) {
101                 /* device WAKEUP through KSO:
102                  * write bit 0 & read back until
103 @@ -2413,6 +2423,14 @@ static int brcmf_sdio_tx_ctrlframe(struc
104         return ret;
105  }
106  
107 +static bool brcmf_chip_is_ulp(struct brcmf_chip *ci)
108 +{
109 +       if (ci->chip == CY_CC_43012_CHIP_ID)
110 +               return true;
111 +       else
112 +               return false;
113 +}
114 +
115  static void brcmf_sdio_bus_stop(struct device *dev)
116  {
117         struct brcmf_bus *bus_if = dev_get_drvdata(dev);
118 @@ -2420,7 +2438,7 @@ static void brcmf_sdio_bus_stop(struct d
119         struct brcmf_sdio *bus = sdiodev->bus;
120         struct brcmf_core *core = bus->sdio_core;
121         u32 local_hostintmask;
122 -       u8 saveclk;
123 +       u8 saveclk, bpreq;
124         int err;
125  
126         brcmf_dbg(TRACE, "Enter\n");
127 @@ -2447,9 +2465,14 @@ static void brcmf_sdio_bus_stop(struct d
128                 /* Force backplane clocks to assure F2 interrupt propagates */
129                 saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
130                                             &err);
131 -               if (!err)
132 -                       brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
133 -                                          (saveclk | SBSDIO_FORCE_HT), &err);
134 +               if (!err) {
135 +                       bpreq = saveclk;
136 +                       bpreq |= brcmf_chip_is_ulp(bus->ci) ?
137 +                               SBSDIO_HT_AVAIL_REQ : SBSDIO_FORCE_HT;
138 +                       brcmf_sdiod_writeb(sdiodev,
139 +                                          SBSDIO_FUNC1_CHIPCLKCSR,
140 +                                          bpreq, &err);
141 +               }
142                 if (err)
143                         brcmf_err("Failed to force clock for F2: err %d\n",
144                                   err);
145 @@ -3339,20 +3362,45 @@ err:
146         return bcmerror;
147  }
148  
149 +static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
150 +{
151 +       if (bus->ci->chip == CY_CC_43012_CHIP_ID)
152 +               return true;
153 +       else
154 +               return false;
155 +}
156 +
157  static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
158  {
159         int err = 0;
160         u8 val;
161 +       u8 wakeupctrl;
162 +       u8 cardcap;
163 +       u8 chipclkcsr;
164  
165         brcmf_dbg(TRACE, "Enter\n");
166  
167 +       if (brcmf_chip_is_ulp(bus->ci)) {
168 +               wakeupctrl = SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
169 +               chipclkcsr = SBSDIO_HT_AVAIL_REQ;
170 +       } else {
171 +               wakeupctrl = SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
172 +               chipclkcsr = SBSDIO_FORCE_HT;
173 +       }
174 +
175 +       if (brcmf_sdio_aos_no_decode(bus)) {
176 +               cardcap = SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC;
177 +       } else {
178 +               cardcap = (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
179 +                          SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT);
180 +       }
181 +
182         val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
183         if (err) {
184                 brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
185                 return;
186         }
187 -
188 -       val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
189 +       val |= 1 << wakeupctrl;
190         brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
191         if (err) {
192                 brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
193 @@ -3361,8 +3409,7 @@ static void brcmf_sdio_sr_init(struct br
194  
195         /* Add CMD14 Support */
196         brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
197 -                            (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
198 -                             SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
199 +                            cardcap,
200                              &err);
201         if (err) {
202                 brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
203 @@ -3370,7 +3417,7 @@ static void brcmf_sdio_sr_init(struct br
204         }
205  
206         brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
207 -                          SBSDIO_FORCE_HT, &err);
208 +                          chipclkcsr, &err);
209         if (err) {
210                 brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
211                 return;
212 @@ -4062,7 +4109,7 @@ static void brcmf_sdio_firmware_callback
213         const struct firmware *code;
214         void *nvram;
215         u32 nvram_len;
216 -       u8 saveclk;
217 +       u8 saveclk, bpreq;
218         u8 devctl;
219  
220         brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
221 @@ -4096,8 +4143,11 @@ static void brcmf_sdio_firmware_callback
222         /* Force clocks on backplane to be sure F2 interrupt propagates */
223         saveclk = brcmf_sdiod_readb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR, &err);
224         if (!err) {
225 +               bpreq = saveclk;
226 +               bpreq |= brcmf_chip_is_ulp(bus->ci) ?
227 +                       SBSDIO_HT_AVAIL_REQ : SBSDIO_FORCE_HT;
228                 brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
229 -                                  (saveclk | SBSDIO_FORCE_HT), &err);
230 +                                  bpreq, &err);
231         }
232         if (err) {
233                 brcmf_err("Failed to force clock for F2: err %d\n", err);
234 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
235 +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
236 @@ -60,6 +60,7 @@
237  #define BRCM_CC_43664_CHIP_ID          43664
238  #define BRCM_CC_4371_CHIP_ID           0x4371
239  #define CY_CC_4373_CHIP_ID             0x4373
240 +#define CY_CC_43012_CHIP_ID            43012
241  
242  /* USB Device IDs */
243  #define BRCM_USB_43143_DEVICE_ID       0xbd1e
244 --- a/include/linux/mmc/sdio_ids.h
245 +++ b/include/linux/mmc/sdio_ids.h
246 @@ -42,6 +42,7 @@
247  #define SDIO_DEVICE_ID_BROADCOM_4354           0x4354
248  #define SDIO_DEVICE_ID_BROADCOM_4356           0x4356
249  #define SDIO_DEVICE_ID_CYPRESS_4373            0x4373
250 +#define SDIO_DEVICE_ID_CYPRESS_43012           43012
251  
252  #define SDIO_VENDOR_ID_INTEL                   0x0089
253  #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX     0x1402