【实践驱动开发3-001】TI WL1835MODCOM8 在android的移植 - 准备

TI 的无线芯片的支持很好,不过有一个问题,那就是TI总是一堆堆的给你东西,TI的OMAP系列虽然很好,但是贵啊!如果我们想在其他平台上拿TI的某一个模块进来,还真的有点麻烦。

本文尝试在x210上用TI的这个片子。

WIFI 的基础知识:


1 TI WIKI: (TI芯片的WIKI东西确实很多)

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

2 Quoto from porting guide:WL18xx Platform Integration Guide

http://processors.wiki.ti.com/index.php/WL18xx_Platform_Integration_Guide

平台的整合说明,应该是开始移植的第一份参考文件。

首选是硬件接口的实际说明,这点将来在驱动开发的时候也是重要的参考。

Hardware/Platform Porting

Host connection to the WiLink connectivity module

WiLink8 AM335x and Module TI.png
 

The WiLink connectivity module (wl12xx/wl18xx) is connected to the host processor using two main hardware interface and a couple of GPIO pins:

  • The WLAN subsystem is connected using an MMC interface running is SDIO mode and two GPIO pins.
    • One GPIO is used for controlling power to the WLAN subsystem (WLAN Enable)
    • The second GPIO pin is used for incoming interrupts from the WLAN subsystem (WLAN IRQ).
  • The Bluetooth, GPS and are all sharing a UARTconnection (using CTS/RTS flow control) and is using an additional GPIO for power controll (BT Enable).

WLAN Reset/Power up sequence

Make sure there is stable vbat/vio and slowclk to the module from the system.


Wlanpower.jpg

Reset / Power up 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

GPIO design considerations

  • For the WLAN Enable pin and BT/GPSenable pins we should select pins that can have Pull-UP enabled on them for alllowing these pins to remain "high" during suspend.
  • For the WLAN interrupt pin it is preffered that we select a GPIO ping that is capable of waking up the host from suspend. This is needed in case we would like to activate the "Wake on WLAN feature" where the system could be waked up based on a configures specific packet recived from the air.


WLAN Interface

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 NameDescription
SDIO_CMDSDIO Command line. This is a bidirectional line. The host sends commands and the WLAN responds to these commands.
SDIO_CLKSDIO Clock line. This line is generated by the host.
SDIO_D0SDIO 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_D1SDIO 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_D2SDIO 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_D3SDIO 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_EnableWLAN 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 IRQgenerate 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 Interface

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 NameDescription
UART RXUART - Receive data.
UART TXUART - transmit data.
RTSRequest to Send. (flow control)
CTSClear to Send . (flow control)
BT EnableEnable 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)
Solution Hardware-Figure4.jpg

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.

Antennas

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 <WLAN RF Antenna>
RF Cable: Please refer to the following link <RF cable>




然后是下面的软件移植说明:

Software Porting

WLAN SW Blocks

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.
SW-Block.jpg

Board Initialization file

  • For each platform there is a board file inside the PSP where the initial board related software bringup is done
  • The board file is located inside the linux kernel source tree under “arch/arm/mach-(omap2/davinci)/board-xxxx.c

显然这个整合说明是针对TI的AM335X,这是个问题,不过可以作为重要的参考

问题:从哪里可以拿到源码?

NoteNote: 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.

Initialization sequence

  • Inside the am335x-evm board file there is an initialization function called am335x_evm_setup(). This function is called when the Linux kernel boots.
  • For the standard am335x-evm this function is calling setup_general_purpose_evm() function which sets up all the peripherals that are in use.
  • This function initiates calls to all the initialization functions which are located inside the gen_purp_evm_dev_cfg[] device configuration structure.
  • The functions which are related to the connectivity parts are mmc2_wl12xx_init, uart1_wl12xx_init and wl12xx_init. These functions are descibed below.

MMC initialization

  • The WLAN subsystem is usually connected using a second MMC port of the host processor. The first MMC is normally used for SD card.
  • On the Aam335x-evm MMC3 is being used and an init function is provided for initializing this MMC structure data.
  • Before we can use the SDIO pins they need to be muxed in the kernel for SDIO mode.

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},<br>
	{"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;
}
  • The mmc2_wl12xx_init() function is placed inside the board configuration structure seen below and when it is called during board startup a second mmc interface is created in the kernel (mmc1) which is used for communicating with the WLAN sub-system.
/* 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},
};

UART Initialization

  • The UART is used for communicating with the rest of the connectivity sub-systems (Bluetooth, GPS,.)
  • On the am335x-evm UART1 is used and we need to mux it's pins into UART mode in order to work with it.

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);
}

GPIO Pins Configuration

  • In addition to the MMC, UART intefcaes, the WiLink module needs three additional GPIO lines:
    • WLAN Enable (GPIO1_16): Set as an output pin
    • WLAN Irq (GPIO3_17): Set as a GPIO input pin
    • BT/GPS Enable (GPIO3_21): Set as a GPIO output pin with pull-up enabled. The pullup is needed for keeping the chip enabled when system is suspending so we would not need to releoad the firmware after each suspend/resume cycle.


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},
};

Power Control

The power control mechanism is used for turning the WLAN sub system on/off based on system commands such as:

  • down/up of the interface (ifconfig wlan0 down/up...)
  • Suspend/resume


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:

  • Using a fixed voltage regulator
  • Using a set_power() function registered with the MMMC device


Power Control – using a fixed voltage regulator

  • For power up/down we can initialize a software(GPIO based) fixed voltage regulator structure that is used for controlling the WLAN_Enable pin by the kernel power manager.
  • For the AM37x platform, this is defined by the structure called “omap3evm_wlan_regulator” and its supporting structures (omap3evm_vwlan, omap3evm_vmmc2, omap3evm_vmmc2_supply).

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
}


Power Control – without voltage regulator

  • An altenrative to using a fixed voltage regulator is using a specific function for power on/off operations.
  • This function can be registered with the MMC driver for power control of the wl12xx module.
  • See the below example of such an off on function used with the am335x-evm board.
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;
}


Power Control – registering the set_power function

  • Once created, the wl12xx_set_power function can be registered with the MMC device connected to the wl12xx module.
  • This is done by initializing the “.set_power” element of the respective “omap_mmc_platform_data” structure
  • In the example below MMC1 is used for WLAN
  • Once initialized each time the wlan0 interface is brought up/down this function would be called by the mmc driver.
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;
}


Platform Data

  • The platfrom_data structure is used for passing initialization data to the wl12xx driver.
  • This structure is initialized inside the board file when the kernel boots up and later read and used by the wl12xx module when it is being loaded.
  • This structure holds information about:
    • Interrupt line used for WLAN
    • Reference clocks (in nlcp the ref clock is NOT read from the ini file)
    • Platform specific quircks
  • Below is the definition of the wl12xx_platform_data structure
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;
};


  • In the example below for AM335x platform we are setting the structure to use a 38.4Mhz crystal clock and the WLAN_IRQ pin is set to GPIO 113 (GPIO3_17).
  • For the am335x platform we are setting an edge interrupt using the platform_quirks field. This is not needed in case of working with a platform that uses level interrupts.
  • In case of using a quatro device (wl128x) instead of wl127x/wl18xx device we also need to setup theboard_tcxo_clock structure element.
#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

  • The available REF_CLOCK values and TCXO_CLOCK values are defined in the include/linux/wl12xx.h
  • Each module vendor may use a different clock setup and the values set in the platform_data structure should match the hardware design of each respective module used.
  • Unfortunately in case of using a different module for the same platform (such as when switching between different types of COMx modules) we need to re-compile the kernel (uImage) after setting the right value based on the module vendor data.
  • Even though the module ini file holds an entry for setting the ref_clock, it is not being used by nlcp, so changing it there would make no effect.
  • The values that can be selected for the platform_data structure in the previous slide are shown below
/* 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 */
};


Platform Registration

  • After we have defined the platform data structures we need to register it with the kernel.
  • For am335x-evm this is done inside wl12xx_init() which calls wl12xx_set_platform_data that sets the platform data parameters that are later used by the wl1xxx driver.
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;
}

WLAN Trouble shoot

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




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Franklin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值