mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-20 04:21:14 +09:00
[ARM] tegra: olympus: Add Wlan platform support
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
committed by
Colin Cross
parent
4d8c0ebd01
commit
f2e8abd844
@@ -258,6 +258,7 @@ CONFIG_TEGRA_DEBUG_UARTB=y
|
||||
# CONFIG_TEGRA_DEBUG_UARTD is not set
|
||||
# CONFIG_TEGRA_DEBUG_UARTE is not set
|
||||
CONFIG_TEGRA_SYSTEM_DMA=y
|
||||
CONFIG_WIFI_CONTROL_FUNC=y
|
||||
|
||||
#
|
||||
# Processor Type
|
||||
|
||||
26
arch/arm/include/asm/mach/mmc.h
Normal file
26
arch/arm/include/asm/mach/mmc.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* arch/arm/include/asm/mach/mmc.h
|
||||
*/
|
||||
#ifndef ASMARM_MACH_MMC_H
|
||||
#define ASMARM_MACH_MMC_H
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
struct embedded_sdio_data {
|
||||
struct sdio_cis cis;
|
||||
struct sdio_cccr cccr;
|
||||
struct sdio_embedded_func *funcs;
|
||||
int num_funcs;
|
||||
};
|
||||
|
||||
struct mmc_platform_data {
|
||||
unsigned int ocr_mask; /* available voltages */
|
||||
u32 (*translate_vdd)(struct device *, unsigned int);
|
||||
unsigned int (*status)(struct device *);
|
||||
struct embedded_sdio_data *embedded_sdio;
|
||||
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -73,6 +73,11 @@ config TEGRA_PWM
|
||||
help
|
||||
Enable support for the Tegra PWM controller(s).
|
||||
|
||||
config WIFI_CONTROL_FUNC
|
||||
bool "Enable WiFi control function abstraction"
|
||||
help
|
||||
Enables Power/Reset/Carddetect function abstraction
|
||||
|
||||
endif
|
||||
|
||||
config TEGRA_IOVMM_GART
|
||||
|
||||
@@ -49,3 +49,4 @@ obj-${CONFIG_MACH_OLYMPUS} += board-olympus-pinmux.o
|
||||
obj-${CONFIG_MACH_OLYMPUS} += board-olympus-panel.o
|
||||
obj-${CONFIG_MACH_OLYMPUS} += board-olympus-i2c.o
|
||||
obj-${CONFIG_MACH_OLYMPUS} += board-olympus-keypad.o
|
||||
obj-${CONFIG_MACH_OLYMPUS} += board-olympus-wifi.o
|
||||
|
||||
@@ -45,7 +45,7 @@ static struct tegra_pingroup_config olympus_pinmux[] = {
|
||||
{TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
|
||||
{TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
|
||||
{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
|
||||
@@ -105,7 +105,7 @@ static struct tegra_pingroup_config olympus_pinmux[] = {
|
||||
{TEGRA_PINGROUP_SDB, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_SDC, TEGRA_MUX_SDIO3, TEGRA_TRI_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_SDD, TEGRA_MUX_SDIO3, TEGRA_TRI_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
|
||||
{TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
|
||||
{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
|
||||
{TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
|
||||
|
||||
212
arch/arm/mach-tegra/board-olympus-wifi.c
Normal file
212
arch/arm/mach-tegra/board-olympus-wifi.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/* linux/arch/arm/mach-msm/board-olympus-wifi.c
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wlan_plat.h>
|
||||
#include <mach/sdhci.h>
|
||||
|
||||
#include "gpio-names.h"
|
||||
|
||||
#define OLYMPUS_WLAN_IRQ TEGRA_GPIO_PU5
|
||||
#define OLYMPUS_WLAN_PWR TEGRA_GPIO_PU3
|
||||
#define OLYMPUS_WLAN_RST TEGRA_GPIO_PU2
|
||||
|
||||
#define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4
|
||||
#define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160
|
||||
#define PREALLOC_WLAN_SECTION_HEADER 24
|
||||
|
||||
#define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
|
||||
#define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
|
||||
#define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512)
|
||||
#define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024)
|
||||
|
||||
#define WLAN_SKB_BUF_NUM 16
|
||||
|
||||
static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
|
||||
|
||||
typedef struct wifi_mem_prealloc_struct {
|
||||
void *mem_ptr;
|
||||
unsigned long size;
|
||||
} wifi_mem_prealloc_t;
|
||||
|
||||
static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = {
|
||||
{ NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) },
|
||||
{ NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) },
|
||||
{ NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) },
|
||||
{ NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) }
|
||||
};
|
||||
|
||||
static void *olympus_wifi_mem_prealloc(int section, unsigned long size)
|
||||
{
|
||||
if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS)
|
||||
return wlan_static_skb;
|
||||
if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS))
|
||||
return NULL;
|
||||
if (wifi_mem_array[section].size < size)
|
||||
return NULL;
|
||||
return wifi_mem_array[section].mem_ptr;
|
||||
}
|
||||
|
||||
int __init olympus_init_wifi_mem(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0;( i < WLAN_SKB_BUF_NUM );i++) {
|
||||
if (i < (WLAN_SKB_BUF_NUM/2))
|
||||
wlan_static_skb[i] = dev_alloc_skb(4096);
|
||||
else
|
||||
wlan_static_skb[i] = dev_alloc_skb(8192);
|
||||
}
|
||||
for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) {
|
||||
wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size,
|
||||
GFP_KERNEL);
|
||||
if (wifi_mem_array[i].mem_ptr == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource olympus_wifi_resources[] = {
|
||||
[0] = {
|
||||
.name = "bcm4329_wlan_irq",
|
||||
.start = TEGRA_GPIO_TO_IRQ(OLYMPUS_WLAN_IRQ),
|
||||
.end = TEGRA_GPIO_TO_IRQ(OLYMPUS_WLAN_IRQ),
|
||||
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
|
||||
},
|
||||
};
|
||||
|
||||
/* BCM4329 returns wrong sdio_vsn(1) when we read cccr,
|
||||
* we use predefined value (sdio_vsn=2) here to initial sdio driver well
|
||||
*/
|
||||
static struct embedded_sdio_data olympus_wifi_emb_data = {
|
||||
.cccr = {
|
||||
.sdio_vsn = 2,
|
||||
.multi_block = 1,
|
||||
.low_speed = 0,
|
||||
.wide_bus = 0,
|
||||
.high_power = 1,
|
||||
.high_speed = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static int olympus_wifi_cd = 0; /* WIFI virtual 'card detect' status */
|
||||
static void (*wifi_status_cb)(int card_present, void *dev_id);
|
||||
static void *wifi_status_cb_devid;
|
||||
|
||||
static int olympus_wifi_status_register(
|
||||
void (*callback)(int card_present, void *dev_id),
|
||||
void *dev_id)
|
||||
{
|
||||
if (wifi_status_cb)
|
||||
return -EAGAIN;
|
||||
wifi_status_cb = callback;
|
||||
wifi_status_cb_devid = dev_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int olympus_wifi_status(struct device *dev)
|
||||
{
|
||||
return olympus_wifi_cd;
|
||||
}
|
||||
|
||||
struct tegra_sdhci_platform_data olympus_wifi_data = {
|
||||
.clk_id = NULL,
|
||||
.force_hs = 0,
|
||||
.mmc_data = {
|
||||
.ocr_mask = MMC_VDD_165_195,
|
||||
.status = olympus_wifi_status,
|
||||
.register_status_notify = olympus_wifi_status_register,
|
||||
.embedded_sdio = &olympus_wifi_emb_data,
|
||||
}
|
||||
};
|
||||
|
||||
int olympus_wifi_set_carddetect(int val)
|
||||
{
|
||||
pr_debug("%s: %d\n", __func__, val);
|
||||
olympus_wifi_cd = val;
|
||||
if (wifi_status_cb) {
|
||||
wifi_status_cb(val, wifi_status_cb_devid);
|
||||
} else
|
||||
pr_warning("%s: Nobody to notify\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int olympus_wifi_power_state;
|
||||
|
||||
int olympus_wifi_power(int on)
|
||||
{
|
||||
pr_debug("%s: %d\n", __func__, on);
|
||||
|
||||
mdelay(100);
|
||||
gpio_set_value(OLYMPUS_WLAN_PWR, on);
|
||||
mdelay(100);
|
||||
gpio_set_value(OLYMPUS_WLAN_RST, on);
|
||||
mdelay(200);
|
||||
|
||||
olympus_wifi_power_state = on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int olympus_wifi_reset_state;
|
||||
|
||||
int olympus_wifi_reset(int on)
|
||||
{
|
||||
pr_debug("%s: do nothing\n", __func__);
|
||||
olympus_wifi_reset_state = on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct wifi_platform_data olympus_wifi_control = {
|
||||
.set_power = olympus_wifi_power,
|
||||
.set_reset = olympus_wifi_reset,
|
||||
.set_carddetect = olympus_wifi_set_carddetect,
|
||||
.mem_prealloc = olympus_wifi_mem_prealloc,
|
||||
};
|
||||
|
||||
static struct platform_device olympus_wifi_device = {
|
||||
.name = "bcm4329_wlan",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(olympus_wifi_resources),
|
||||
.resource = olympus_wifi_resources,
|
||||
.dev = {
|
||||
.platform_data = &olympus_wifi_control,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init olympus_wlan_gpio(void)
|
||||
{
|
||||
tegra_gpio_enable(OLYMPUS_WLAN_PWR);
|
||||
gpio_request(OLYMPUS_WLAN_PWR, "wlan_pwr");
|
||||
gpio_direction_output(OLYMPUS_WLAN_PWR, 0);
|
||||
|
||||
tegra_gpio_enable(OLYMPUS_WLAN_RST);
|
||||
gpio_request(OLYMPUS_WLAN_RST, "wlan_rst");
|
||||
gpio_direction_output(OLYMPUS_WLAN_RST, 0);
|
||||
|
||||
tegra_gpio_enable(OLYMPUS_WLAN_IRQ);
|
||||
gpio_request(OLYMPUS_WLAN_IRQ, "wlan_irq");
|
||||
gpio_direction_input(OLYMPUS_WLAN_IRQ);
|
||||
}
|
||||
|
||||
static int __init olympus_wlan_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!machine_is_olympus())
|
||||
return 0;
|
||||
|
||||
pr_debug("%s: start\n", __func__);
|
||||
olympus_wlan_gpio();
|
||||
olympus_init_wifi_mem();
|
||||
ret = platform_device_register(&olympus_wifi_device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
late_initcall(olympus_wlan_init);
|
||||
@@ -203,6 +203,8 @@ static struct platform_device *olympus_devices[] __initdata = {
|
||||
&hsuart,
|
||||
};
|
||||
|
||||
extern struct tegra_sdhci_platform_data olympus_wifi_data; /* sdhci1 */
|
||||
|
||||
static struct tegra_sdhci_platform_data olympus_sdhci_platform_data3 = {
|
||||
.clk_id = NULL,
|
||||
.force_hs = 0,
|
||||
@@ -220,10 +222,11 @@ static struct tegra_sdhci_platform_data olympus_sdhci_platform_data4 = {
|
||||
static void olympus_sdhci_init(void)
|
||||
{
|
||||
/* TODO: setup GPIOs for cd, wd, and power */
|
||||
tegra_sdhci_device1.dev.platform_data = &olympus_wifi_data;
|
||||
tegra_sdhci_device3.dev.platform_data = &olympus_sdhci_platform_data3;
|
||||
tegra_sdhci_device4.dev.platform_data = &olympus_sdhci_platform_data4;
|
||||
|
||||
|
||||
platform_device_register(&tegra_sdhci_device1);
|
||||
platform_device_register(&tegra_sdhci_device3);
|
||||
platform_device_register(&tegra_sdhci_device4);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define __ASM_ARM_ARCH_TEGRA_SDHCI_H
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <asm/mach/mmc.h>
|
||||
|
||||
struct tegra_sdhci_platform_data {
|
||||
const char *clk_id;
|
||||
@@ -25,6 +26,7 @@ struct tegra_sdhci_platform_data {
|
||||
int cd_gpio;
|
||||
int wp_gpio;
|
||||
int power_gpio;
|
||||
struct mmc_platform_data mmc_data;
|
||||
|
||||
void (*board_probe)(int id, struct mmc_host *);
|
||||
void (*board_remove)(int id, struct mmc_host *);
|
||||
|
||||
Reference in New Issue
Block a user