| .. | .. |
|---|
| 1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 2 | 1 | /* |
|---|
| 3 | 2 | * SDIO access interface for drivers - linux specific (pci only) |
|---|
| 4 | 3 | * |
|---|
| 5 | | - * Copyright (C) 1999-2019, Broadcom Corporation |
|---|
| 6 | | - * |
|---|
| 4 | + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation |
|---|
| 5 | + * |
|---|
| 6 | + * Copyright (C) 1999-2017, Broadcom Corporation |
|---|
| 7 | + * |
|---|
| 7 | 8 | * Unless you and Broadcom execute a separate written software license |
|---|
| 8 | 9 | * agreement governing use of this software, this software is licensed to you |
|---|
| 9 | 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
|---|
| 10 | 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
|---|
| 11 | 12 | * following added to such license: |
|---|
| 12 | | - * |
|---|
| 13 | + * |
|---|
| 13 | 14 | * As a special exception, the copyright holders of this software give you |
|---|
| 14 | 15 | * permission to link this software with independent modules, and to copy and |
|---|
| 15 | 16 | * distribute the resulting executable under terms of your choice, provided that |
|---|
| .. | .. |
|---|
| 17 | 18 | * the license of that module. An independent module is a module which is not |
|---|
| 18 | 19 | * derived from this software. The special exception does not apply to any |
|---|
| 19 | 20 | * modifications of the software. |
|---|
| 20 | | - * |
|---|
| 21 | + * |
|---|
| 21 | 22 | * Notwithstanding the above, under no circumstances may you combine this |
|---|
| 22 | 23 | * software in any way with any other Broadcom software provided under a license |
|---|
| 23 | 24 | * other than the GPL, without Broadcom's express prior written consent. |
|---|
| .. | .. |
|---|
| 25 | 26 | * |
|---|
| 26 | 27 | * <<Broadcom-WL-IPTag/Open:>> |
|---|
| 27 | 28 | * |
|---|
| 28 | | - * $Id: bcmsdh_linux.c 579798 2015-08-17 07:00:05Z $ |
|---|
| 29 | + * $Id: bcmsdh_linux.c 689948 2017-03-14 05:21:03Z $ |
|---|
| 29 | 30 | */ |
|---|
| 30 | 31 | |
|---|
| 31 | 32 | /** |
|---|
| .. | .. |
|---|
| 48 | 49 | #include <bcmutils.h> |
|---|
| 49 | 50 | #include <dngl_stats.h> |
|---|
| 50 | 51 | #include <dhd.h> |
|---|
| 51 | | -#if defined(CONFIG_ARCH_ODIN) |
|---|
| 52 | | -#include <linux/platform_data/gpio-odin.h> |
|---|
| 53 | | -#endif /* defined(CONFIG_ARCH_ODIN) */ |
|---|
| 54 | 52 | #include <dhd_linux.h> |
|---|
| 55 | 53 | |
|---|
| 56 | 54 | /* driver info, initialized when bcmsdh_register is called */ |
|---|
| .. | .. |
|---|
| 85 | 83 | } bcmsdh_os_info_t; |
|---|
| 86 | 84 | |
|---|
| 87 | 85 | /* debugging macros */ |
|---|
| 88 | | -#define SDLX_MSG(x) do { printf x; } while (0) |
|---|
| 86 | +#define SDLX_MSG(x) |
|---|
| 89 | 87 | |
|---|
| 90 | 88 | /** |
|---|
| 91 | 89 | * Checks to see if vendor and device IDs match a supported SDIO Host Controller. |
|---|
| .. | .. |
|---|
| 98 | 96 | #ifdef BCMSDIOH_STD |
|---|
| 99 | 97 | /* Check for Arasan host controller */ |
|---|
| 100 | 98 | if (vendor == VENDOR_SI_IMAGE) { |
|---|
| 99 | + return (TRUE); |
|---|
| 100 | + } |
|---|
| 101 | + if (device == SDIOH_FPGA_ID && vendor == VENDOR_CYPRESS) { |
|---|
| 101 | 102 | return (TRUE); |
|---|
| 102 | 103 | } |
|---|
| 103 | 104 | /* Check for BRCM 27XX Standard host controller */ |
|---|
| .. | .. |
|---|
| 161 | 162 | bcmsdh_osinfo->dev = dev; |
|---|
| 162 | 163 | osl_set_bus_handle(osh, bcmsdh); |
|---|
| 163 | 164 | |
|---|
| 164 | | -#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 165 | +#if (!defined(CONFIG_PM_WAKELOCKS) || !defined(CONFIG_HAS_WAKELOCK)) && \ |
|---|
| 166 | + (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 165 | 167 | if (dev && device_init_wakeup(dev, true) == 0) |
|---|
| 166 | 168 | bcmsdh_osinfo->dev_wake_enabled = TRUE; |
|---|
| 167 | | -#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */ |
|---|
| 169 | +#endif /* CONFIG_PM_WAKELOCKS ||CONFIG_HAS_WAKELOCK && |
|---|
| 170 | + * (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 171 | + */ |
|---|
| 168 | 172 | |
|---|
| 169 | 173 | #if defined(OOB_INTR_ONLY) |
|---|
| 170 | 174 | spin_lock_init(&bcmsdh_osinfo->oob_irq_spinlock); |
|---|
| .. | .. |
|---|
| 179 | 183 | |
|---|
| 180 | 184 | /* Read the vendor/device ID from the CIS */ |
|---|
| 181 | 185 | vendevid = bcmsdh_query_device(bcmsdh); |
|---|
| 186 | + |
|---|
| 182 | 187 | /* try to attach to the target device */ |
|---|
| 188 | +#if defined(BCMSPI) && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI)) |
|---|
| 189 | + bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num, |
|---|
| 190 | + slot_num, 0, bus_type, (void *)regs, NULL, bcmsdh); |
|---|
| 191 | +#else |
|---|
| 183 | 192 | bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num, |
|---|
| 184 | 193 | slot_num, 0, bus_type, (void *)regs, osh, bcmsdh); |
|---|
| 194 | +#endif /* BCMSPI && (BCMPCISPIHOST || BCMSDIOH_SPI) */ |
|---|
| 185 | 195 | if (bcmsdh_osinfo->context == NULL) { |
|---|
| 186 | 196 | SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); |
|---|
| 187 | 197 | goto err; |
|---|
| .. | .. |
|---|
| 202 | 212 | { |
|---|
| 203 | 213 | bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; |
|---|
| 204 | 214 | |
|---|
| 205 | | -#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 215 | +#if (!defined(CONFIG_PM_WAKELOCKS) || !defined(CONFIG_HAS_WAKELOCK)) && \ |
|---|
| 216 | + (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 206 | 217 | if (bcmsdh_osinfo->dev) |
|---|
| 207 | 218 | device_init_wakeup(bcmsdh_osinfo->dev, false); |
|---|
| 208 | 219 | bcmsdh_osinfo->dev_wake_enabled = FALSE; |
|---|
| 209 | | -#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */ |
|---|
| 220 | +#endif /* CONFIG_PM_WAKELOCKS ||CONFIG_HAS_WAKELOCK && |
|---|
| 221 | + * (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 222 | + */ |
|---|
| 210 | 223 | |
|---|
| 211 | 224 | drvinfo.remove(bcmsdh_osinfo->context); |
|---|
| 212 | 225 | MFREE(bcmsdh->osh, bcmsdh->os_cxt, sizeof(bcmsdh_os_info_t)); |
|---|
| .. | .. |
|---|
| 214 | 227 | |
|---|
| 215 | 228 | return 0; |
|---|
| 216 | 229 | } |
|---|
| 230 | + |
|---|
| 231 | +#ifdef DHD_WAKE_STATUS |
|---|
| 232 | +int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh) |
|---|
| 233 | +{ |
|---|
| 234 | + return bcmsdh->total_wake_count; |
|---|
| 235 | +} |
|---|
| 236 | + |
|---|
| 237 | +int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag) |
|---|
| 238 | +{ |
|---|
| 239 | + bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; |
|---|
| 240 | + unsigned long flags; |
|---|
| 241 | + int ret; |
|---|
| 242 | + |
|---|
| 243 | + spin_lock_irqsave(&bcmsdh_osinfo->oob_irq_spinlock, flags); |
|---|
| 244 | + |
|---|
| 245 | + ret = bcmsdh->pkt_wake; |
|---|
| 246 | + bcmsdh->total_wake_count += flag; |
|---|
| 247 | + bcmsdh->pkt_wake = flag; |
|---|
| 248 | + |
|---|
| 249 | + spin_unlock_irqrestore(&bcmsdh_osinfo->oob_irq_spinlock, flags); |
|---|
| 250 | + return ret; |
|---|
| 251 | +} |
|---|
| 252 | +#endif /* DHD_WAKE_STATUS */ |
|---|
| 217 | 253 | |
|---|
| 218 | 254 | int bcmsdh_suspend(bcmsdh_info_t *bcmsdh) |
|---|
| 219 | 255 | { |
|---|
| .. | .. |
|---|
| 270 | 306 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) |
|---|
| 271 | 307 | if (bcmsdh_pci_driver.node.next == NULL) |
|---|
| 272 | 308 | return; |
|---|
| 273 | | -#endif |
|---|
| 309 | +#endif // endif |
|---|
| 274 | 310 | |
|---|
| 275 | 311 | bcmsdh_unregister_client_driver(); |
|---|
| 276 | 312 | } |
|---|
| 277 | 313 | |
|---|
| 278 | 314 | void bcmsdh_dev_pm_stay_awake(bcmsdh_info_t *bcmsdh) |
|---|
| 279 | 315 | { |
|---|
| 280 | | -#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 316 | +#if (!defined(CONFIG_PM_WAKELOCKS) || !defined(CONFIG_HAS_WAKELOCK)) && \ |
|---|
| 317 | + (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 281 | 318 | bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; |
|---|
| 282 | 319 | pm_stay_awake(bcmsdh_osinfo->dev); |
|---|
| 283 | | -#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */ |
|---|
| 320 | +#endif /* CONFIG_PM_WAKELOCKS ||CONFIG_HAS_WAKELOCK && |
|---|
| 321 | + * (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 322 | + */ |
|---|
| 284 | 323 | } |
|---|
| 285 | 324 | |
|---|
| 286 | 325 | void bcmsdh_dev_relax(bcmsdh_info_t *bcmsdh) |
|---|
| 287 | 326 | { |
|---|
| 288 | | -#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 327 | +#if (!defined(CONFIG_PM_WAKELOCKS) || !defined(CONFIG_HAS_WAKELOCK)) && \ |
|---|
| 328 | + (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 289 | 329 | bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; |
|---|
| 290 | 330 | pm_relax(bcmsdh_osinfo->dev); |
|---|
| 291 | | -#endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */ |
|---|
| 331 | +#endif /* CONFIG_PM_WAKELOCKS ||CONFIG_HAS_WAKELOCK && |
|---|
| 332 | + * (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) |
|---|
| 333 | + */ |
|---|
| 292 | 334 | } |
|---|
| 293 | 335 | |
|---|
| 294 | 336 | bool bcmsdh_dev_pm_enabled(bcmsdh_info_t *bcmsdh) |
|---|
| .. | .. |
|---|
| 298 | 340 | return bcmsdh_osinfo->dev_wake_enabled; |
|---|
| 299 | 341 | } |
|---|
| 300 | 342 | |
|---|
| 301 | | -#if defined(OOB_INTR_ONLY) |
|---|
| 343 | +#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) |
|---|
| 302 | 344 | void bcmsdh_oob_intr_set(bcmsdh_info_t *bcmsdh, bool enable) |
|---|
| 303 | 345 | { |
|---|
| 304 | 346 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 324 | 366 | bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)dev_id; |
|---|
| 325 | 367 | bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; |
|---|
| 326 | 368 | |
|---|
| 369 | +#ifndef BCMSPI_ANDROID |
|---|
| 327 | 370 | bcmsdh_oob_intr_set(bcmsdh, FALSE); |
|---|
| 371 | +#endif /* !BCMSPI_ANDROID */ |
|---|
| 328 | 372 | bcmsdh_osinfo->oob_irq_handler(bcmsdh_osinfo->oob_irq_handler_context); |
|---|
| 329 | 373 | |
|---|
| 330 | 374 | return IRQ_HANDLED; |
|---|
| .. | .. |
|---|
| 345 | 389 | (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); |
|---|
| 346 | 390 | bcmsdh_osinfo->oob_irq_handler = oob_irq_handler; |
|---|
| 347 | 391 | bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context; |
|---|
| 348 | | -#if defined(CONFIG_ARCH_ODIN) |
|---|
| 349 | | - err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, |
|---|
| 350 | | - bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); |
|---|
| 351 | | -#else |
|---|
| 392 | + bcmsdh_osinfo->oob_irq_enabled = TRUE; |
|---|
| 393 | + bcmsdh_osinfo->oob_irq_registered = TRUE; |
|---|
| 352 | 394 | err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, |
|---|
| 353 | 395 | bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); |
|---|
| 354 | | -#endif /* defined(CONFIG_ARCH_ODIN) */ |
|---|
| 355 | 396 | if (err) { |
|---|
| 356 | 397 | SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err)); |
|---|
| 398 | + bcmsdh_osinfo->oob_irq_enabled = FALSE; |
|---|
| 399 | + bcmsdh_osinfo->oob_irq_registered = FALSE; |
|---|
| 357 | 400 | return err; |
|---|
| 358 | 401 | } |
|---|
| 359 | 402 | |
|---|
| 403 | +#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) |
|---|
| 404 | + if (device_may_wakeup(bcmsdh_osinfo->dev)) { |
|---|
| 405 | +#endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ |
|---|
| 360 | 406 | err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num); |
|---|
| 361 | 407 | if (!err) |
|---|
| 362 | 408 | bcmsdh_osinfo->oob_irq_wake_enabled = TRUE; |
|---|
| 363 | | - bcmsdh_osinfo->oob_irq_enabled = TRUE; |
|---|
| 364 | | - bcmsdh_osinfo->oob_irq_registered = TRUE; |
|---|
| 409 | +#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) |
|---|
| 410 | + } |
|---|
| 411 | +#endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ |
|---|
| 365 | 412 | return err; |
|---|
| 366 | 413 | } |
|---|
| 367 | 414 | |
|---|
| .. | .. |
|---|
| 376 | 423 | return; |
|---|
| 377 | 424 | } |
|---|
| 378 | 425 | if (bcmsdh_osinfo->oob_irq_wake_enabled) { |
|---|
| 426 | +#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) |
|---|
| 427 | + if (device_may_wakeup(bcmsdh_osinfo->dev)) { |
|---|
| 428 | +#endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ |
|---|
| 379 | 429 | err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num); |
|---|
| 380 | 430 | if (!err) |
|---|
| 381 | 431 | bcmsdh_osinfo->oob_irq_wake_enabled = FALSE; |
|---|
| 432 | +#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) |
|---|
| 433 | + } |
|---|
| 434 | +#endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ |
|---|
| 382 | 435 | } |
|---|
| 383 | 436 | if (bcmsdh_osinfo->oob_irq_enabled) { |
|---|
| 384 | 437 | disable_irq(bcmsdh_osinfo->oob_irq_num); |
|---|
| .. | .. |
|---|
| 387 | 440 | free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh); |
|---|
| 388 | 441 | bcmsdh_osinfo->oob_irq_registered = FALSE; |
|---|
| 389 | 442 | } |
|---|
| 390 | | -#endif |
|---|
| 443 | +#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ |
|---|
| 391 | 444 | |
|---|
| 392 | 445 | /* Module parameters specific to each host-controller driver */ |
|---|
| 393 | 446 | |
|---|
| 394 | 447 | extern uint sd_msglevel; /* Debug message level */ |
|---|
| 395 | | -module_param(sd_msglevel, uint, 0664); |
|---|
| 448 | +module_param(sd_msglevel, uint, 0); |
|---|
| 396 | 449 | |
|---|
| 397 | 450 | extern uint sd_power; /* 0 = SD Power OFF, 1 = SD Power ON. */ |
|---|
| 398 | 451 | module_param(sd_power, uint, 0); |
|---|
| .. | .. |
|---|
| 427 | 480 | extern char dhd_sdiod_uhsi_ds_override[2]; |
|---|
| 428 | 481 | module_param_string(dhd_sdiod_uhsi_ds_override, dhd_sdiod_uhsi_ds_override, 2, 0); |
|---|
| 429 | 482 | |
|---|
| 430 | | -#endif |
|---|
| 483 | +#endif // endif |
|---|
| 484 | + |
|---|
| 485 | + |
|---|
| 486 | + |
|---|
| 431 | 487 | |
|---|
| 432 | 488 | #ifdef BCMSDH_MODULE |
|---|
| 433 | 489 | EXPORT_SYMBOL(bcmsdh_attach); |
|---|
| .. | .. |
|---|
| 440 | 496 | |
|---|
| 441 | 497 | #if defined(DHD_DEBUG) |
|---|
| 442 | 498 | EXPORT_SYMBOL(bcmsdh_intr_pending); |
|---|
| 443 | | -#endif |
|---|
| 499 | +#endif // endif |
|---|
| 500 | + |
|---|
| 501 | +#if defined(BT_OVER_SDIO) |
|---|
| 502 | +EXPORT_SYMBOL(bcmsdh_btsdio_interface_init); |
|---|
| 503 | +#endif /* defined (BT_OVER_SDIO) */ |
|---|
| 444 | 504 | |
|---|
| 445 | 505 | EXPORT_SYMBOL(bcmsdh_devremove_reg); |
|---|
| 446 | 506 | EXPORT_SYMBOL(bcmsdh_cfg_read); |
|---|