// SPDX-License-Identifier: GPL-2.0-only /* * NXP Wireless LAN device driver: SDIO specific handling * * Copyright 2011-2020 NXP */ #include <linux/firmware.h> #include "decl.h" #include "ioctl.h" #include "util.h" #include "fw.h" #include "main.h" #include "wmm.h" #include "11n.h" #include "sdio.h" #define SDIO_VERSION … static void mwifiex_sdio_work(struct work_struct *work); static struct mwifiex_if_ops sdio_ops; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = …; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = …; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8977 = …; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = …; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = …; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd89xx = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8977 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8978 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8987 = …; static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = …; static struct memory_type_mapping generic_mem_type_map[] = …; static struct memory_type_mapping mem_type_mapping_tbl[] = …; static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = …; /* This function parse device tree node using mmc subnode devicetree API. * The device node is saved in card->plt_of_node. * if the device tree node exist and include interrupts attributes, this * function will also request platform specific wakeup interrupt. */ static int mwifiex_sdio_probe_of(struct device *dev) { … } /* * SDIO probe. * * This function probes an mwifiex device and registers it. It allocates * the card structure, enables SDIO function number and initiates the * device registration and initialization procedure by adding a logical * interface. */ static int mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { … } /* * SDIO resume. * * Kernel needs to suspend all functions separately. Therefore all * registered functions must have drivers with suspend and resume * methods. Failing that the kernel simply removes the whole card. * * If already not resumed, this function turns on the traffic and * sends a host sleep cancel request to the firmware. */ static int mwifiex_sdio_resume(struct device *dev) { … } /* Write data into SDIO card register. Caller claims SDIO device. */ static int mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) { … } /* This function writes data into SDIO card register. */ static int mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) { … } /* This function reads data from SDIO card register. */ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data) { … } /* This function writes multiple data into SDIO card memory. * * This does not work in suspended mode. */ static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, u32 pkt_len, u32 port) { … } /* This function reads multiple data from SDIO card memory. */ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, u32 len, u32 port, u8 claim) { … } /* This function reads the firmware status. */ static int mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) { … } /* This function checks the firmware status in card. */ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { … } /* This function checks if WLAN is the winner. */ static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) { … } /* * SDIO remove. * * This function removes the interface and frees up the card structure. */ static void mwifiex_sdio_remove(struct sdio_func *func) { … } /* * SDIO suspend. * * Kernel needs to suspend all functions separately. Therefore all * registered functions must have drivers with suspend and resume * methods. Failing that the kernel simply removes the whole card. * * If already not suspended, this function allocates and sends a host * sleep activate request to the firmware and turns off the traffic. */ static int mwifiex_sdio_suspend(struct device *dev) { … } static void mwifiex_sdio_coredump(struct device *dev) { … } /* WLAN IDs */ static const struct sdio_device_id mwifiex_ids[] = …; MODULE_DEVICE_TABLE(sdio, mwifiex_ids); static const struct dev_pm_ops mwifiex_sdio_pm_ops = …; static struct sdio_driver mwifiex_sdio = …; /* * This function wakes up the card. * * A host power up command is written to the card configuration * register to wake up the card. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { … } /* * This function is called after the card has woken up. * * The card configuration register is reset. */ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) { … } static int mwifiex_sdio_dnld_fw(struct mwifiex_adapter *adapter, struct mwifiex_fw_image *fw) { … } /* * This function is used to initialize IO ports for the * chipsets supporting SDIO new mode eg SD8897. */ static int mwifiex_init_sdio_new_mode(struct mwifiex_adapter *adapter) { … } /* This function initializes the IO ports. * * The following operations are performed - * - Read the IO ports (0, 1 and 2) * - Set host interrupt Reset-To-Read to clear * - Set auto re-enable interrupt */ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) { … } /* * This function sends data to the card. */ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, u8 *payload, u32 pkt_len, u32 port) { … } /* * This function gets the read port. * * If control port bit is set in MP read bitmap, the control port * is returned, otherwise the current read port is returned and * the value is increased (provided it does not reach the maximum * limit, in which case it is reset to 1) */ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) { … } /* * This function gets the write port for data. * * The current write port is returned if available and the value is * increased (provided it does not reach the maximum limit, in which * case it is reset to 1) */ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port) { … } /* * This function polls the card status. */ static int mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) { … } /* * This function disables the host interrupt. * * The host interrupt mask is read, the disable bit is reset and * written back to the card host interrupt mask register. */ static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) { … } /* * This function reads the interrupt status from card. */ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) { … } /* * SDIO interrupt handler. * * This function reads the interrupt status from firmware and handles * the interrupt in current thread (ksdioirqd) right away. */ static void mwifiex_sdio_interrupt(struct sdio_func *func) { … } /* * This function enables the host interrupt. * * The host interrupt enable mask is written to the card * host interrupt mask register. */ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) { … } /* * This function sends a data buffer to the card. */ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, u32 *type, u8 *buffer, u32 npayload, u32 ioport) { … } /* * This function downloads the firmware to the card. * * Firmware is downloaded to the card in blocks. Every block download * is tested for CRC errors, and retried a number of times before * returning failure. */ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, struct mwifiex_fw_image *fw) { … } /* * This function decodes sdio aggregation pkt. * * Based on the data block size and pkt_len, * skb data will be decoded to few packets. */ static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, struct sk_buff *skb) { … } /* * This function decodes a received packet. * * Based on the type, the packet is treated as either a data, or * a command response, or an event, and the correct handler * function is invoked. */ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb, u32 upld_typ) { … } /* * This function transfers received packets from card to driver, performing * aggregation if required. * * For data received on control port, or if aggregation is disabled, the * received buffers are uploaded as separate packets. However, if aggregation * is enabled and required, the buffers are copied onto an aggregation buffer, * provided there is space left, processed and finally uploaded. */ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, u16 rx_len, u8 port) { … } /* * This function checks the current interrupt status. * * The following interrupts are checked and handled by this function - * - Data sent * - Command sent * - Packets received * * Since the firmware does not generate download ready interrupt if the * port updated is command port only, command sent interrupt checking * should be done manually, and for every SDIO interrupt. * * In case of Rx packets received, the packets are uploaded from card to * host and processed accordingly. */ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) { … } /* * This function aggregates transmission buffers in driver and downloads * the aggregated packet to card. * * The individual packets are aggregated by copying into an aggregation * buffer and then downloaded to the card. Previous unsent packets in the * aggregation buffer are pre-copied first before new packets are added. * Aggregation is done till there is space left in the aggregation buffer, * or till new packets are available. * * The function will only download the packet to the card when aggregation * stops, otherwise it will just aggregate the packet in aggregation buffer * and return. */ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, u8 *payload, u32 pkt_len, u32 port, u32 next_pkt_len) { … } /* * This function downloads data from driver to card. * * Both commands and data packets are transferred to the card by this * function. * * This function adds the SDIO specific header to the front of the buffer * before transferring. The header contains the length of the packet and * the type. The firmware handles the packets based upon this set type. */ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, u8 type, struct sk_buff *skb, struct mwifiex_tx_param *tx_param) { … } /* * This function allocates the MPA Tx and Rx buffers. */ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) { … } /* * This function unregisters the SDIO device. * * The SDIO IRQ is released, the function is disabled and driver * data is set to null. */ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) { … } /* * This function registers the SDIO device. * * SDIO IRQ is claimed, block size is set and driver data is initialized. */ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) { … } /* * This function initializes the SDIO driver. * * The following initializations steps are followed - * - Read the Host interrupt status register to acknowledge * the first interrupt got from bootloader * - Disable host interrupt mask register * - Get SDIO port * - Initialize SDIO variables in card * - Allocate MP registers * - Allocate MPA Tx and Rx buffers */ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) { … } /* * This function resets the MPA Tx and Rx buffers. */ static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter) { … } /* * This function cleans up the allocated card buffers. * * The following are freed by this function - * - MP registers * - MPA Tx buffer * - MPA Rx buffer */ static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) { … } /* * This function updates the MP end port in card. */ static void mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) { … } static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) { … } /* This function read/write firmware */ static enum rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) { … } /* This function dump firmware memory to file */ static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) { … } static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter) { … } static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter) { … } static void mwifiex_sdio_work(struct work_struct *work) { … } /* This function resets the card */ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) { … } /* This function dumps FW information */ static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter) { … } /* Function to dump SDIO function registers and SDIO scratch registers in case * of FW crash */ static int mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf) { … } /* sdio device/function initialization, code is extracted * from init_if handler and register_dev handler. */ static void mwifiex_sdio_up_dev(struct mwifiex_adapter *adapter) { … } static struct mwifiex_if_ops sdio_ops = …; module_sdio_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…); MODULE_LICENSE(…) …; MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…); MODULE_FIRMWARE(…);