TI 的无线芯片的支持很好,不过有一个问题,那就是TI总是一堆堆的给你东西,TI的OMAP系列虽然很好,但是贵啊!如果我们想在其他平台上拿TI的某一个模块进来,还真的有点麻烦。
本文尝试在x210上用TI的这个片子。
http://processors.wiki.ti.com/index.php/WL18xx?DCMP=wilink8&HQS=wilink8wiki
Easily add Wi-Fi and Bluetooth (WL183x module only) to embedded applications based on TI's Sitara microprocessors. TI’s WiLink 8 modules are pre-certified and offer high throughput and extended range along with Wi-Fi and Bluetooth coexistence (WL183x modules only) in a power-optimized design. Drivers for the Linux and Android high-level operating systems (HLOSs) are available free of charge from TI for theSitara AM335xmicroprocessor (Linux and Android version restrictions apply).
WiLink 8 - WL18xx | ||||
Getting Started | Hardware System | Software System | Testing and Certification | Support and Community |
Overview
Get the Kit
First Time
DemosWiFi Use Cases
WiFi & BT Use Cases
Stonestreet One Bluetooth Use Cases
|
Modules
Module Evaluation Boards
Host Processor
Guides
Reference Designs
Application Notes
|
http://processors.wiki.ti.com/index.php/WL18xx_Platform_Integration_Guide
The WiLink connectivity module (wl12xx/wl18xx) is connected to the host processor using two main hardware interface and a couple of GPIO pins:
Make sure there is stable vbat/vio and slowclk to the module from the system.
After Vbat and VIO are fed to Device and while WL_EN are de-asserted (LOW), the device is in Shutdownstate. While in Shutdown state all functional blocks, internal DC2DC's and LDO's will be disabled. Thepower supplied to the functional blocks is cut off. When WL_EN are asserted (High), a Power On Reset(POR) is performed. Stable Slow Clock, VIO and Vbat are pre-requisites for successful POR
The following table describes the WLAN Host Interface (SDIO, WLAN enable, WLAN IRQ)
The Host interface the WLAN with SDIO interface. The WLAN chip acts as a slave with the HOST (OMAP and so on) as the master. that is the host generates the SDIO clock and read/write from the WLAN interface.
WLAN-HOST Interface Signals - SDIO
Signal Name | Description |
---|---|
SDIO_CMD | SDIO Command line. This is a bidirectional line. The host sends commands and the WLAN responds to these commands. |
SDIO_CLK | SDIO Clock line. This line is generated by the host. |
SDIO_D0 | SDIO Data 0 line. This is the primary data line used in both 1-bit and 4-bit SDIO mode. This is a bidirectional line. |
SDIO_D1 | SDIO Data 1 line. This is one of four data lines. This line is used only in 4-bit mode. This is a bidirectional line. |
SDIO_D2 | SDIO Data 2 line. This is one of four data lines. This line is used only in 4-bit mode. This is a bidirectional line. |
SDIO_D3 | SDIO Data 3 line. This is one of four data lines. This line is used only in 4- bit mode. This is a bidirectional line. |
WLAN_Enable | WLAN enable signal, should be "1" in order enable the WLAN operation, once the WLAN enable signal is "0" the WLAN part of the chip is reseted in a way that the firmware has to be loaded again after enabling the WLAN. |
WLAN IRQ | generate Interrupt from the WLAN chip toward the HOST, it is used to signal the HOST on many events like received data from the WLAN media is ready at the firmware (WLAN Chip) quque, or that the last Tx frame was transmitted, all king of asynchronous messages (evens) and so on. |
Bluetooth uses the HCI interface to connect to the host. The WL18xx supports both H4 (4-wire) interfaces. UART type.
BT-HOST Interface Signals - UART
Signal Name | Description |
---|---|
UART RX | UART - Receive data. |
UART TX | UART - transmit data. |
RTS | Request to Send. (flow control) |
CTS | Clear to Send . (flow control) |
BT Enable | Enable the BT operation, has to be set to "1" in order to enable the BT part. |
Following is the way HOST is connected to the WL18xx chip through the UART (Bluetooth HCI Interface - H4 Connectivity)
Flow Control:
RTS / CTS is used to Flow Control. RTS (Request to Send) and CTS (Clear to Send). These two lines allow the receiver and the transmitter to alert each other to their state. A transmitter raises its RTS line indicating to the reciver that it request to send data. And If the receiver is in a position to receive the data it will assert its CTS line, acknpwlaging the transmit side that it can start transmitting. Using the RTS/CTS enables device drivers which implement hardware flow control code to maintain a reliable data connection between transmitter and receiver.
WLAN Antenna:
In order to get good RF performance for WLAN and BT, one needs to connect an external antenna. The following are the ordering links for the recomended WLAN/BT Antenna and RF cable:
Antenna: Please refer to the following link
RF Cable: Please refer to the following link
The host communicates via SDIO to the WLAN device. On the device side, the WLAN MAC is responsiblefor the 802.11 MAC functions, and conveys WLAN packets from/to the external host to/from the FW.The MAC is responsible for the timing and the time critical decisions only. The PHY performs the 802.11PHY functions of encoding/decoding and modulation/demodulation, and is responsible for the RF functionsof up/down modulation to carrier frequency, filtering and amplification.
问题:从哪里可以拿到源码?
Note: This presentation is mostly based on board_am335x-evm.c located under “arch/arm/mach-omap2”, but similar initilization is needed for every new platform which is connecting to the same type of WiLink module.
The SDIO related pin muxes are set in the structure below:
/* Module pin mux for wlan and bluetooth */ static struct pinmux_config mmc2_wl12xx_pin_mux[] = { {"gpmc_a1.mmc2_dat0", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP},
{"gpmc_a2.mmc2_dat1", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP}, {"gpmc_a3.mmc2_dat2", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP}, {"gpmc_ben1.mmc2_dat3", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP}, {"gpmc_csn3.mmc2_cmd", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP}, {"gpmc_clk.mmc2_clk", OMAP_MUX_MODE3 | AM33XX_PIN_INPUT_PULLUP}, {NULL, 0}, };
The below function is used for setting up this MMC interface. In this function the pin mux structure is being intialized and then the inteface is initilized as a non-removeable card working in 4-Bit mode.
static void mmc2_wl12xx_init(int evm_id, int profile) { setup_pin_mux(mmc2_wl12xx_pin_mux); am335x_mmc[1].mmc = 3; am335x_mmc[1].name = "wl1271"; am335x_mmc[1].caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD; am335x_mmc[1].nonremovable = true; am335x_mmc[1].gpio_cd = -EINVAL; am335x_mmc[1].gpio_wp = -EINVAL; am335x_mmc[1].ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34; /* 3V3 */ /* mmc will be initialized when mmc0_init is called */ return; }
/* General Purpose EVM */ static struct evm_dev_cfg gen_purp_evm_dev_cfg[] = { {enable_ecap0, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 | PROFILE_2 | PROFILE_7) }, {lcdc_init, DEV_ON_DGHTR_BRD, (PROFILE_0 | PROFILE_1 | PROFILE_2 | PROFILE_7) }, ... ... {mmc1_init, DEV_ON_DGHTR_BRD, PROFILE_2}, {mmc2_wl12xx_init, DEV_ON_BASEBOARD, (PROFILE_0 | PROFILE_3 | PROFILE_5)}, {mmc0_init, DEV_ON_BASEBOARD, (PROFILE_ALL & ~PROFILE_5)}, {mmc0_no_cd_init, DEV_ON_BASEBOARD, PROFILE_5}, {spi0_init, DEV_ON_DGHTR_BRD, PROFILE_2}, {uart1_wl12xx_init, DEV_ON_BASEBOARD, (PROFILE_0 | PROFILE_3 | PROFILE_5)}, {wl12xx_init, DEV_ON_BASEBOARD, (PROFILE_0 | PROFILE_3 | PROFILE_5)}, ... ... {haptics_init, DEV_ON_DGHTR_BRD, (PROFILE_4)}, {NULL, 0, 0}, };
The structure below is used for performing this pin muxing. In strucure we mux the four UART pins (Rx,Tx,CTS,RTS)
static struct pinmux_config uart1_wl12xx_pin_mux[] = { {"uart1_ctsn.uart1_ctsn", OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT}, {"uart1_rtsn.uart1_rtsn", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT}, {"uart1_rxd.uart1_rxd", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP}, {"uart1_txd.uart1_txd", OMAP_MUX_MODE0 | AM33XX_PULL_ENBL}, {NULL, 0}, };
The uart1_wl12xx_init() functions use this structure for performing the UART pin muxing:
static void uart1_wl12xx_init(int evm_id, int profile) { setup_pin_mux(uart1_wl12xx_pin_mux); }
The strucure below is used for setting the muxing of these pins:
static struct pinmux_config wl12xx_pin_mux[] = { {"gpmc_a0.gpio1_16", OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT}, {"mcasp0_ahclkr.gpio3_17", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT}, {"mcasp0_ahclkx.gpio3_21", OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT_PULLUP}, {NULL, 0}, };
The power control mechanism is used for turning the WLAN sub system on/off based on system commands such as:
This is done by registering a GPIO with the MMC device that is enabled (high) when the inteface is brought up and is disabled (low) when the interface is brought down.
There are two methods which can be used for implementing this GPIO control:
In the structure below we are setting a fixed voltage reulator which is using a GPIO(43).
The voltage level on this pin(1.8V) is hardware controlled and is only set here for indecation to the user.
The driver is setting a 70msec start-up delay used to allow the module power to stabilize after startup.
#define GPIO_WIFI_PMENA 43 ... ... static struct regulator_consumer_supply omap3evm_vmmc2_supply = REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"); /* VMMC2 for driving the WL12xx module */ static struct regulator_init_data omap3evm_vmmc2 = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, .consumer_supplies = &omap3evm_vmmc2_supply, }; static struct fixed_voltage_config omap3evm_vwlan = { .supply_name = "vwl1271", .microvolts = 1800000, /* 1.80V */ .gpio = OMAP3EVM_WLAN_PMENA_GPIO, .startup_delay = 70000, /* 70ms */ .enable_high = 1, .enabled_at_boot = 0, .init_data = &omap3evm_vmmc2, }; static struct platform_device omap3evm_wlan_regulator = { .name = "reg-fixed-voltage", .id = 1, .dev = { .platform_data = &omap3evm_vwlan, }, };
This regulator device is then registered with the platform using the platform_device_register() function as seen below:
static void __init omap3_evm_wl12xx_init(void) { #ifdef CONFIG_WL12XX_PLATFORM_DATA int ret; /* WL12xx WLAN Init */ omap3evm_wlan_data.irq = gpio_to_irq(OMAP3EVM_WLAN_IRQ_GPIO); ret = wl12xx_set_platform_data(&omap3evm_wlan_data); if (ret) pr_err("error setting wl12xx data: %d\n", ret); ret = platform_device_register(&omap3evm_wlan_regulator); if (ret) pr_err("error registering wl12xx device: %d\n", ret); #endif }
static int wl12xx_set_power(struct device *dev, int slot, int on, int vdd) { if (on) { gpio_set_value(am335xevm_wlan_data.wlan_enable_gpio, 1); mdelay(70); } else gpio_set_value(am335xevm_wlan_data.wlan_enable_gpio, 0); return 0; }
static void wl12xx_init(int evm_id, int profile) { struct device *dev; struct omap_mmc_platform_data *pdata; … … dev = am335x_mmc[1].dev; if (!dev) { pr_err("wl12xx mmc device initialization failed\n"); goto out; } pdata = dev->platform_data; if (!pdata) { pr_err("Platfrom data of wl12xx device not set\n"); goto out; } … … pdata->slots[0].set_power = wl12xx_set_power; out: return; }
struct wl12xx_platform_data { /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */ int irq; bool use_eeprom; int board_ref_clock; int board_tcxo_clock; unsigned long platform_quirks; };
#define AM335XEVM_WLAN_IRQ_GPIO GPIO_TO_PIN(3, 17) struct wl12xx_platform_data am335xevm_wlan_data = { .irq = OMAP_GPIO_IRQ(AM335XEVM_WLAN_IRQ_GPIO), .board_ref_clock = WL12XX_REFCLOCK_38_XTAL, /* 38.4Mhz */ .platform_quirks = WL12XX_PLATFORM_QUIRK_EDGE_IRQ; };
/* Reference clock values */ enum { WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */ }; /* TCXO clock values */ enum { WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */ };
static void wl12xx_init(int evm_id, int profile) { struct device *dev; struct omap_mmc_platform_data *pdata; int ret; ... ... if (wl12xx_set_platform_data(&am335xevm_wlan_data)) pr_err("error setting wl12xx data\n"); ... ... out: return; }
Q: How do i find the gpio lines being used WLAN and BT?
A: Refer the board schematics to find the WLAN_EN/BT_EN/WLAN_IRQ also the MMC and UART interface used.
Q: I have proper mux/pads set still WLAN does not work.
A: Make sure the Power/Reset sequence as mentioned above is happening. stable vbat/vio and slow clk are essntial. Once WLAN irq is pulled high module will generate the internal clk and host can start communication over SDIO interface.
Q: Yes, I have power/Reset sequence happening still i do not see WLAN working.
A: Make sure WLAN card is detected during device enumeration. Enable MMC_DEBUG and see driver is getting initialized.
Q: Yes, card detection is working but WiFi is still not working.
A: Make sure you have WLAN compat driver built using the WL8 software build process in theWL18xx processor wiki.
Q: Yes, I do have modules built but still i do not waln interface ifconfig wlan0 up ifconfig: SIOCGIFFLAGS: No such device
A: Ok seems like the modules are not loaded properly, try to insert the modules manually. The modules can be found in the /lib/module of file system
Q: How do I know if the WLAN is functional?
A: Try get the WLAN interface up and do a scan using wpa_supplicant or iw utility
3