r4714 - developers/werner/wlan-spi/patches-tracking

werner at docs.openmoko.org werner at docs.openmoko.org
Thu Oct 16 02:50:33 CEST 2008


Author: werner
Date: 2008-10-16 02:50:32 +0200 (Thu, 16 Oct 2008)
New Revision: 4714

Added:
   developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch
   developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi-bitbang.patch
   developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi.patch
   developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch
   developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch
Modified:
   developers/werner/wlan-spi/patches-tracking/hack-mmc-spi-coexistence.patch
   developers/werner/wlan-spi/patches-tracking/series
Log:
- rebasing continues ...

hif-linux-sdio.patch:
- drivers/ar6000/hif/hif2.c: removed setting of EMPC (allow card to draw more
  than 200mA) in SDIO_CCCR_POWER
- drivers/ar6000/hif/hif2.c: forgot to initialize queue_lock



Added: developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch	                        (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -0,0 +1,63 @@
+ar6k-without-sdio.patch
+
+Make the AR6000 WLAN driver compile after moving it outside the
+Atheros SDIO stack. Note that the config option's name changes
+as well.
+
+The choice of a non-standard location (drivers/ar6000/) is
+intentional. The driver is still very far from being in shape for
+mainline inclusion, and the odd location should serve as an
+immediate warning.
+
+Not-Yet-Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+Index: ktrack/arch/arm/Kconfig
+===================================================================
+--- ktrack.orig/arch/arm/Kconfig	2008-10-15 11:12:12.000000000 -0200
++++ ktrack/arch/arm/Kconfig	2008-10-15 21:49:07.000000000 -0200
+@@ -1220,7 +1220,7 @@
+ 
+ source "drivers/usb/Kconfig"
+ 
+-source "drivers/sdio/Kconfig"
++source "drivers/ar6000/Kconfig"
+ 
+ source "drivers/mmc/Kconfig"
+ 
+Index: ktrack/drivers/Makefile
+===================================================================
+--- ktrack.orig/drivers/Makefile	2008-10-15 11:12:12.000000000 -0200
++++ ktrack/drivers/Makefile	2008-10-15 21:49:36.000000000 -0200
+@@ -85,6 +85,7 @@
+ obj-$(CONFIG_MMC)		+= mmc/
+ obj-$(CONFIG_MEMSTICK)		+= memstick/
+ obj-$(CONFIG_SDIO)              += sdio/
++obj-$(CONFIG_AR6000_WLAN)	+= ar6000/
+ obj-$(CONFIG_NEW_LEDS)		+= leds/
+ obj-$(CONFIG_INFINIBAND)	+= infiniband/
+ obj-$(CONFIG_SGI_SN)		+= sn/
+Index: ktrack/drivers/ar6000/Kconfig
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ ktrack/drivers/ar6000/Kconfig	2008-10-15 21:49:07.000000000 -0200
+@@ -0,0 +1,7 @@
++config AR6000_WLAN
++        tristate "ar6000 wireless networking over sdio"
++	depends on MMC
++        select WIRELESS_EXT
++        default m
++        help
++          good luck.
+Index: ktrack/drivers/ar6000/Makefile
+===================================================================
+--- ktrack.orig/drivers/ar6000/Makefile	2008-10-15 11:12:12.000000000 -0200
++++ ktrack/drivers/ar6000/Makefile	2008-10-15 21:49:07.000000000 -0200
+@@ -13,7 +13,7 @@
+ 
+ EXTRA_CFLAGS += -DKERNEL_2_6
+ 
+-obj-$(CONFIG_SDIO_AR6000_WLAN) += ar6000.o
++obj-$(CONFIG_AR6000_WLAN) += ar6000.o
+ 
+ ar6000-objs += htc/ar6k.o      		   \
+ 	       htc/ar6k_events.o 	   \

Added: developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi-bitbang.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi-bitbang.patch	                        (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi-bitbang.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -0,0 +1,151 @@
+gta02-mmc-spio-bitbang.patch
+
+This patch adds the platform definitions for using the AR6000 driver
+with MMC-SPI and the S3C SPI GPIO (bit-banging) driver.
+
+This configuration should work with all GTA02 models. No rework
+required.
+
+Note that this patch disables the acceleration sensors, because they
+also use the SPI GPIO driver. This needs a bit more integration.
+
+Not-Yet-Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+Index: ktrack/arch/arm/mach-s3c2440/Kconfig
+===================================================================
+--- ktrack.orig/arch/arm/mach-s3c2440/Kconfig	2008-10-15 22:15:23.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/Kconfig	2008-10-15 22:27:33.000000000 -0200
+@@ -99,6 +99,20 @@
+ 	   Say Y here if you are using an early hardware revision
+ 	   of the FIC/Openmoko Neo1973 GTA02 GSM Phone.
+ 
++# @@@ Not a great place for this, but still better than dragging platform
++# details into driver land.
++
++choice
++        prompt "AR6K interface"
++        default AR6K_SPI_S3C24XX_GPIO
++        depends on MACH_NEO1973_GTA02 && AR6000_WLAN
++
++        config AR6K_SPI_S3C24XX_GPIO
++                bool "GPIO bit-banging SPI"
++                select MMC_SPI
++                select SPI_S3C24XX_GPIO
++endchoice
++
+ endmenu
+ 
+ #source "arch/arm/mach-s3c2440/camera/Kconfig"
+Index: ktrack/arch/arm/mach-s3c2440/mach-gta02.c
+===================================================================
+--- ktrack.orig/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 22:15:23.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 22:27:52.000000000 -0200
+@@ -37,6 +37,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/glamo.h>
+ #include <linux/spi/spi_bitbang.h>
++#include <linux/spi/mmc_spi.h>
+ #include <linux/mmc/host.h>
+ 
+ #include <linux/mtd/mtd.h>
+@@ -1223,6 +1224,85 @@
+ 	},
+ };
+ 
++
++/* ----- AR6000 WLAN interface --------------------------------------------- */
++
++
++/* shared by all SPI drivers */
++
++#if defined(CONFIG_AR6K_SPI_S3C24XX_GPIO)
++
++static struct spi_board_info gta02_spi_mmc_bdinfo = {
++	.modalias	= "mmc_spi",
++	.irq		= IRQ_EINT3,	/* unused ? */
++	.max_speed_hz	= 12 * 1000 * 1000,
++	.bus_num	= 0,
++	.chip_select	= 0,
++	.mode		= SPI_MODE_0,
++};
++
++#endif /* CONFIG_AR6K_SPI_S3C24XX_GPIO */
++
++
++#ifdef CONFIG_AR6K_SPI_S3C24XX_GPIO
++
++static void spi_wlan_cs(struct s3c2410_spigpio_info *spigpio_info,
++		       int csid, int cs)
++{
++	switch (cs) {
++	case BITBANG_CS_ACTIVE:
++		s3c2410_gpio_setpin(S3C2410_GPE10, 0);
++		break;
++	case BITBANG_CS_INACTIVE:
++		s3c2410_gpio_setpin(S3C2410_GPE10, 1);
++		break;
++	}
++}
++
++static struct s3c2410_spigpio_info spi_gpio_wlan_cfg = {
++	.pin_clk	= S3C2410_GPE5,
++	.pin_mosi	= S3C2410_GPE6,
++	.pin_miso	= S3C2410_GPE7,
++	.board_size	= 1,
++	.board_info	= &gta02_spi_mmc_bdinfo,
++	.chip_select	= &spi_wlan_cs,
++	.num_chipselect = 1,
++};
++
++static struct resource gta02_spi_wlan_resource[] = {
++	[0] = {
++		.start = S3C2410_GPE5,
++		.end   = S3C2410_GPE5,
++	},
++	[1] = {
++		.start = S3C2410_GPE6,
++		.end   = S3C2410_GPE6,
++	},
++	[2] = {
++		.start = S3C2410_GPE7,
++		.end   = S3C2410_GPE7,
++	},
++	[3] = {
++		.start = S3C2410_GPE10,
++		.end   = S3C2410_GPE10,
++	},
++};
++
++static struct platform_device gta02_spi_wlan = {
++	.name		  = "spi_s3c24xx_gpio",
++	.id		  = 1,
++	.num_resources	  = ARRAY_SIZE(gta02_spi_wlan_resource),
++	.resource	  = gta02_spi_wlan_resource,
++	.dev = {
++		.platform_data = &spi_gpio_wlan_cfg,
++	},
++};
++
++#endif /* CONFIG_AR6K_SPI_S3C2410_GPIO */
++
++
++/* ------------------------------------------------------------------------- */
++
+ static struct resource gta02_led_resources[] = {
+ 	{
+ 		.name	= "gta02-power:orange",
+@@ -1638,7 +1718,13 @@
+ 	s3c2410_gpio_pullup(S3C2410_GPF3, 1);
+ 	s3c2410_gpio_pullup(S3C2410_GPG2, 1);
+ 
+-	platform_device_register(&s3c_device_spi_acc);
++#ifdef CONFIG_AR6K_SPI_S3C24XX_GPIO
++	s3c2410_gpio_setpin(S3C2410_GPE10, 1);	/* nSS */
++	s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPIO_OUTPUT);
++	platform_device_register(&gta02_spi_wlan);
++#endif /* CONFIG_AR6K_SPI_S3C24XX_GPIO */
++
++//	platform_device_register(&s3c_device_spi_acc);
+ 	platform_device_register(&gta02_button_dev);
+ 	platform_device_register(&gta02_pm_gsm_dev);
+ 	platform_device_register(&gta02_pm_usbhost_dev);

Added: developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi.patch	                        (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/gta02-mmc-spi.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -0,0 +1,67 @@
+Ongoing work on adding support for MMC-SPI using the S3C SPI driver.
+Note that this doesn't produce a valid bitstream yet.
+
+On GTA02, S3C SPI can only be used with WLAN if the SPI0 interface is
+wired to the SDIO interface. This is described here:
+http://svn.openmoko.org/developers/werner/wlan-spi/gta02-spi/rework.pdf
+
+The correct wiring can be verified with the following script:
+http://svn.openmoko.org/developers/werner/wlan-spi/gta02-spi/verify.sh
+
+Not-Yet-Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+Index: ktrack/arch/arm/mach-s3c2440/Kconfig
+===================================================================
+--- ktrack.orig/arch/arm/mach-s3c2440/Kconfig	2008-10-15 22:04:35.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/Kconfig	2008-10-15 22:05:19.000000000 -0200
+@@ -111,6 +111,15 @@
+                 bool "GPIO bit-banging SPI"
+                 select MMC_SPI
+                 select SPI_S3C24XX_GPIO
++
++	config AR6K_SPI_S3C24XX
++		bool "Hardware-accelerated SPI (modification)"
++		select MMC_SPI
++		select SPI_S3C24XX
++		help
++		  This functionality requires that SPI0 is wired to
++		  the WLAN SDIO interface.
++
+ endchoice
+ 
+ endmenu
+Index: ktrack/arch/arm/mach-s3c2440/mach-gta02.c
+===================================================================
+--- ktrack.orig/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 22:04:35.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 22:06:25.000000000 -0200
+@@ -1228,9 +1228,7 @@
+ /* ----- AR6000 WLAN interface --------------------------------------------- */
+ 
+ 
+-/* shared by all SPI drivers */
+-
+-#if defined(CONFIG_AR6K_SPI_S3C24XX_GPIO)
++#if defined(CONFIG_AR6K_SPI_S3C24XX) || defined(CONFIG_AR6K_SPI_S3C24XX_GPIO)
+ 
+ static struct spi_board_info gta02_spi_mmc_bdinfo = {
+ 	.modalias	= "mmc_spi",
+@@ -1241,7 +1239,18 @@
+ 	.mode		= SPI_MODE_0,
+ };
+ 
+-#endif /* CONFIG_AR6K_SPI_S3C24XX_GPIO */
++#endif /* CONFIG_AR6K_SPI_S3C24XX || CONFIG_AR6K_SPI_S3C24XX_GPIO */
++
++
++#ifdef CONFIG_AR6K_SPI_S3C24XX
++
++static struct s3c2410_spi_info spi_wlan_cfg = {
++	.pin_cs		= S3C2410_GPG2,
++	.board_size	= 1,
++	.board_info	= &gta02_spi_mmc_bdinfo,
++};
++
++#endif /* CONFIG_AR6K_SPI_S3C24XX */
+ 
+ 
+ #ifdef CONFIG_AR6K_SPI_S3C24XX_GPIO

Added: developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch	                        (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -0,0 +1,59 @@
+gta02-remove-sdio.patch
+
+After killing the Atheros SDIO stack, we shall no longer deny ourselves
+the pleasure of also getting rid of the glue that keeps it on the
+platform.
+
+Not-Yet-Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+Index: ktrack/arch/arm/mach-s3c2440/mach-gta02.c
+===================================================================
+--- ktrack.orig/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 21:35:29.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 21:51:04.000000000 -0200
+@@ -813,36 +813,6 @@
+ };
+ 
+ 
+-
+-static struct resource gta02_sdio_resources[] = {
+-	[0] = {
+-		.flags	= IORESOURCE_IRQ,
+-		.start	= IRQ_SDI,
+-		.end	= IRQ_SDI,
+-	},
+-	[1] = {
+-		.flags = IORESOURCE_MEM,
+-		.start = S3C2410_PA_SDI,
+-		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI - 1,
+-	},
+-	[2] = {
+-		.flags = IORESOURCE_DMA,
+-		.start = 0, /* Channel 0 for SDI */
+-		.end = 0,
+-	},
+-};
+-
+-
+-static struct platform_device gta02_sdio_dev = {
+-        .name           = "s3c24xx-sdio",
+-        .id             = -1,
+-        .dev            = {
+-                                .coherent_dma_mask      = 0xffffffff,
+-        },
+-        .resource       = gta02_sdio_resources,
+-        .num_resources  = ARRAY_SIZE(gta02_sdio_resources),
+-};
+-
+ struct platform_device s3c24xx_pwm_device = {
+ 	.name 		= "s3c24xx_pwm",
+ 	.num_resources	= 0,
+@@ -1678,9 +1648,6 @@
+ 	platform_device_register(&gta02_vibrator_dev);
+ 	platform_device_register(&gta02_led_dev);
+ 
+-
+-	platform_device_register(&gta02_sdio_dev);
+-
+ 	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
+ 
+ #ifdef CONFIG_GTA02_HDQ

Modified: developers/werner/wlan-spi/patches-tracking/hack-mmc-spi-coexistence.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/hack-mmc-spi-coexistence.patch	2008-10-15 15:26:47 UTC (rev 4713)
+++ developers/werner/wlan-spi/patches-tracking/hack-mmc-spi-coexistence.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -1,7 +1,16 @@
+In order to drive WLAN with S3C SPI on GTA02, the SPI0 interface has to
+be wired to the SDIO interface. This rework is described here:
+http://svn.openmoko.org/developers/werner/wlan-spi/gta02-spi/rework.pdf
+
+The correct wiring can be verified with the following script:
+http://svn.openmoko.org/developers/werner/wlan-spi/gta02-spi/verify.sh
+
+This patch makes sure that only one interface drives the bus at a time.
+
 Index: ktrack/arch/arm/mach-s3c2440/mach-gta02.c
 ===================================================================
---- ktrack.orig/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 13:13:26.000000000 -0200
-+++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 13:17:28.000000000 -0200
+--- ktrack.orig/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 13:23:37.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c	2008-10-15 22:04:28.000000000 -0200
 @@ -1632,6 +1632,42 @@
  	mangle_glamo_res_by_system_rev();
  	platform_device_register(&gta02_glamo_dev);
@@ -23,7 +32,7 @@
 +	s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPIO_INPUT);	/* MOSI */
 +	s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPIO_INPUT);	/* CLK */
 +	s3c2410_gpio_cfgpin(S3C2410_GPF3, S3C2410_GPIO_INPUT);	/* EINT3 */
-+	s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPIO_INPUT);	/* SS */
++	s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPIO_INPUT);	/* nSS */
 +
 +#endif /* !CONFIG_AR6K_SPI_S3C24XX */
 +

Added: developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch	                        (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch	2008-10-16 00:50:32 UTC (rev 4714)
@@ -0,0 +1,662 @@
+hif-linux-sdio.patch
+
+This is a replacement for Atheros' HIF layer that uses the Linux SDIO
+stack.
+
+Using GPLv2, like Atheros' code this is based on.
+
+Work in progress.
+
+Not-Yet-Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+Index: ktrack/drivers/ar6000/Makefile
+===================================================================
+--- ktrack.orig/drivers/ar6000/Makefile	2008-10-15 22:04:35.000000000 -0200
++++ ktrack/drivers/ar6000/Makefile	2008-10-15 22:04:35.000000000 -0200
+@@ -21,7 +21,7 @@
+                htc/htc_recv.o       	   \
+                htc/htc_services.o          \
+                htc/htc.o     		   \
+-               hif/hif.o     		   \
++               hif/hif2.o     		   \
+                bmi/bmi.o                   \
+                ar6000/ar6000_drv.o         \
+                ar6000/ar6000_raw_if.o	   \
+Index: ktrack/drivers/ar6000/hif/hif2.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ ktrack/drivers/ar6000/hif/hif2.c	2008-10-15 22:32:07.000000000 -0200
+@@ -0,0 +1,633 @@
++/*
++ * hif2.c - HIF layer re-implementation for the Linux SDIO stack
++ *
++ * Copyright (C) 2008 by OpenMoko, Inc.
++ * Written by Werner Almesberger <werner at openmoko.org>
++ * All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation;
++ *
++ * Based on:
++ *
++ * @abstract: HIF layer reference implementation for Atheros SDIO stack
++ * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/kthread.h>
++#include <linux/list.h>
++#include <linux/wait.h>
++#include <linux/spinlock.h>
++#include <linux/mmc/sdio_func.h>
++#include <linux/mmc/sdio.h>
++#include <asm/gpio.h>
++
++#include "athdefs.h"
++#include "a_types.h"
++#include "hif.h"
++
++
++/*
++ * KNOWN BUGS:
++ *
++ * - HIF_DEVICE_IRQ_ASYNC_SYNC doesn't work yet (gets MMC errors)
++ * - does not work with S3C SDI (probably due to bugs in the latter)
++ * - not ready for S3C SPI yet
++ * - no cleanup on setup errors yet
++ * - driver doesn't remove cleanly yet
++ * - latency can reach hundreds of ms, probably because of scheduling delays
++ * - packets go through about three queues before finally hitting the network
++ */
++
++
++//#define dev_dbg dev_info
++#define dev_dbg(dev, ...) ((void) dev)
++
++#define MBOXES			4
++
++#define HIF_MBOX_BLOCK_SIZE	128
++#define	HIF_MBOX_BASE_ADDR	0x800
++#define	HIF_MBOX_WIDTH		0x800
++#define	HIF_MBOX_START_ADDR(mbox) \
++    (HIF_MBOX_BASE_ADDR+(mbox)*HIF_MBOX_WIDTH)
++
++
++struct hif_device {
++	void *htc_handle;
++	struct sdio_func *func;
++
++	/*
++	 * @@@ our sweet little bit of bogosity - the mechanism that lets us
++	 * use the SDIO stack from softirqs. This really wants to use skbs.
++	 */
++	struct list_head queue;
++	spinlock_t queue_lock;
++	struct task_struct *io_task;
++	wait_queue_head_t wait;
++};
++
++struct hif_request {
++	struct list_head list;
++	struct sdio_func *func;
++	int (*read)(struct sdio_func *func,
++	    void *dst, unsigned int addr, int count);
++	int (*write)(struct sdio_func *func,
++	    unsigned int addr, void *src, int count);
++	void *buf;
++	unsigned long addr;
++	int len;
++	A_STATUS (*completion)(void *context, A_STATUS status);
++	void *context;
++};
++
++
++static HIF_DEVICE hif_device;
++static HTC_CALLBACKS htcCallbacks;
++
++
++int HIFInit(HTC_CALLBACKS *callbacks)
++{
++	BUG_ON(!callbacks);
++
++	printk(KERN_INFO "HIFInit\n");
++	htcCallbacks = *callbacks;
++
++	return 0;
++}
++
++
++static A_STATUS process_request(struct hif_request *req)
++{
++	int ret;
++	A_STATUS status;
++
++	dev_dbg(&req->func->dev, "process_request(req %p)\n", req);
++	sdio_claim_host(req->func);
++	if (req->read)
++		ret = req->read(req->func, req->buf, req->addr, req->len);
++	else
++		ret = req->write(req->func, req->addr, req->buf, req->len);
++	sdio_release_host(req->func);
++	status = ret ? A_ERROR : A_OK;
++	if (req->completion)
++		req->completion(req->context, status);
++	kfree(req);
++	return status;
++}
++
++
++static void enqueue_request(struct hif_device *hif, struct hif_request *req)
++{
++	unsigned long flags;
++
++	dev_dbg(&req->func->dev, "enqueue_request(req %p)\n", req);
++	spin_lock_irqsave(&hif->queue_lock, flags);
++	list_add_tail(&req->list, &hif->queue);
++	spin_unlock_irqrestore(&hif->queue_lock, flags);
++	wake_up(&hif->wait);
++}
++
++
++static struct hif_request *dequeue_request(struct hif_device *hif)
++{
++	struct hif_request *req;
++	unsigned long flags;
++
++	spin_lock_irqsave(&hif->queue_lock, flags);
++	if (list_empty(&hif->queue))
++		req = NULL;
++	else {
++		req = list_first_entry(&hif->queue,
++		    struct hif_request, list);
++		list_del(&req->list);
++	}
++	spin_unlock_irqrestore(&hif->queue_lock, flags);
++	return req;
++}
++
++
++static int io(void *data)
++{
++	struct hif_device *hif = data;
++	DECLARE_WAITQUEUE(wait, current);
++	struct hif_request *req;
++
++	while (1) {
++		add_wait_queue(&hif->wait, &wait);
++		while (1) {
++			set_current_state(TASK_INTERRUPTIBLE);
++			if (signal_pending(current)) {
++				req = NULL;
++				break;
++			}
++			req = dequeue_request(hif);
++			if (req)
++				break;
++			schedule();
++		}
++		set_current_state(TASK_RUNNING);
++		remove_wait_queue(&hif->wait, &wait);
++
++		if (!req)
++			break;
++
++		(void) process_request(req);
++	}
++	return 0;
++}
++
++
++A_STATUS HIFReadWrite(HIF_DEVICE *hif, A_UINT32 address, A_UCHAR *buffer,
++    A_UINT32 length, A_UINT32 request, void *context)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++	struct hif_request *req;
++
++	dev_dbg(dev, "HIFReadWrite(device %p, address 0x%x, buffer %p, "
++	    "length %d, request 0x%x, context %p)\n",
++	    hif, address, buffer, length, request, context);
++
++	BUG_ON(!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)));
++	BUG_ON(!(request & (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)));
++	BUG_ON(!(request & (HIF_READ | HIF_WRITE)));
++	BUG_ON(!(request & HIF_EXTENDED_IO));
++
++	if (address >= HIF_MBOX_START_ADDR(0) &&
++	    address < HIF_MBOX_START_ADDR(MBOXES+1)) {
++		BUG_ON(length > HIF_MBOX_WIDTH);
++		/* Adjust the address so that the last byte falls on the EOM
++		   address. */
++		address += HIF_MBOX_WIDTH-length;
++	}
++
++	req = kzalloc(sizeof(*req), GFP_ATOMIC);
++	if (!req) {
++		if (request & HIF_ASYNCHRONOUS)
++			htcCallbacks.rwCompletionHandler(context, A_ERROR);
++		return A_ERROR;
++	}
++
++	req->func = hif->func;
++	req->addr = address;
++	req->buf = buffer;
++	req->len = length;
++
++	if (request & HIF_READ) {
++		if (request & HIF_FIXED_ADDRESS)
++			req->read = sdio_readsb;
++		else
++			req->read = sdio_memcpy_fromio;
++	} else {
++		if (request & HIF_FIXED_ADDRESS)
++			req->write = sdio_writesb;
++		else
++			req->write = sdio_memcpy_toio;
++	}
++
++	if (!(request & HIF_ASYNCHRONOUS))
++		return process_request(req);
++
++	req->completion = htcCallbacks.rwCompletionHandler;
++	req->context = context;
++	enqueue_request(hif, req);
++
++	return A_OK;
++}
++
++
++A_STATUS HIFConfigureDevice(HIF_DEVICE *hif,
++    HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++	HIF_DEVICE_IRQ_PROCESSING_MODE *ipm_cfg = config;
++	A_UINT32 *mbs_cfg = config;
++	int i;
++
++	dev_dbg(dev, "HIFConfigureDevice\n");
++
++	switch (opcode) {
++	case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
++		for (i = 0; i != MBOXES; i++)
++			mbs_cfg[i] = HIF_MBOX_BLOCK_SIZE;
++		break;
++	case HIF_DEVICE_GET_MBOX_ADDR:
++		for (i = 0; i != MBOXES; i++)
++			mbs_cfg[i] = HIF_MBOX_START_ADDR(i);
++		break;
++	case HIF_DEVICE_GET_IRQ_PROC_MODE:
++		*ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY;
++//		*ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC;
++		break;
++	default:
++		return A_ERROR;
++	}
++	return A_OK;
++}
++
++
++void HIFShutDownDevice(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++
++	dev_dbg(dev, "HIFShutDownDevice\n");
++}
++
++
++/* ========================================================================= */
++
++#if 1
++
++/*
++ * Volatile ought to be good enough to make gcc do the right thing on S3C24xx.
++ * No need to use atomic or put barriers, keeping the code more readable.
++ *
++ * Warning: this story changes if going SMP/SMT.
++ */
++
++static volatile int masked = 1;
++static volatile int pending;
++static volatile int in_interrupt;
++
++
++static void ar6000_do_irq(struct sdio_func *func)
++{
++	HIF_DEVICE *hif = sdio_get_drvdata(func);
++	struct device *dev = HIFGetOSDevice(hif);
++	A_STATUS status;
++
++	dev_dbg(dev, "ar6000_do_irq -> %p\n", htcCallbacks.dsrHandler);
++
++	status = htcCallbacks.dsrHandler(hif->htc_handle);
++	BUG_ON(status != A_OK);
++}
++
++
++static void sdio_ar6000_irq(struct sdio_func *func)
++{
++	HIF_DEVICE *hif = sdio_get_drvdata(func);
++	struct device *dev = HIFGetOSDevice(hif);
++
++	dev_dbg(dev, "sdio_ar6000_irq\n");
++
++	in_interrupt = 1;
++	if (masked) {
++		in_interrupt = 0;
++		pending++;
++		return;
++	}
++	/*
++	 * @@@ This is ugly. If we don't drop the lock, we'll deadlock when
++	 * the handler tries to do SDIO. So there are four choices:
++	 *
++	 * 1) Break the call chain by calling the callback from a workqueue.
++	 *    Ugh.
++	 * 2) Make process_request aware that we already have the lock.
++	 * 3) Drop the lock. Which is ugly but should be safe as long as we're
++	 *    making sure the device doesn't go away.
++	 * 4) Change the AR6k driver such that it only issues asynchronous
++	 *    quests when called from an interrupt.
++	 *
++	 * Solution 2) is probably the best for now. Will try it later.
++	 */
++	sdio_release_host(func);
++	ar6000_do_irq(func);
++	sdio_claim_host(func);
++	in_interrupt = 0;
++}
++
++
++void HIFAckInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++
++	dev_dbg(dev, "HIFAckInterrupt\n");
++	/* do nothing */
++}
++
++
++void HIFUnMaskInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++
++	dev_dbg(dev, "HIFUnMaskInterrupt\n");
++	do {
++		masked = 1;
++		if (pending) {
++			pending = 0;
++			ar6000_do_irq(hif->func);
++			/* We may take an interrupt before unmasking and thus
++			   get it pending. In this case, we just loop back. */
++		}
++		masked = 0;
++	}
++	while (pending);
++}
++
++
++void HIFMaskInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++
++	dev_dbg(dev, "HIFMaskInterrupt\n");
++	/*
++	 * Since sdio_ar6000_irq can also be called from a process context, we
++	 * may conceivably end up racing with it. Thus, we need to wait until
++	 * we can be sure that no concurrent interrupt processing is going on
++	 * before we return.
++	 *
++	 * Note: this may be a bit on the paranoid side - the callers may
++	 * actually be nice enough to disable scheduling. Check later.
++	 */
++	masked = 1;
++	while (in_interrupt)
++		yield();
++}
++
++#endif
++
++/* ========================================================================= */
++
++/*
++ * The code below is for handling interrupts signalled out-of-band.
++ */
++#if 0
++#define IRQ_GPIO S3C2410_GPE8 /* SDDAT1 */
++
++
++static atomic_t mask = ATOMIC_INIT(1);
++
++
++static void sdio_ar6000_irq(struct sdio_func *func)
++{
++	HIF_DEVICE *hif = sdio_get_drvdata(func);
++
++	printk(KERN_DEBUG "sdio_ar6000_irq -> %p\n", htcCallbacks.dsrHandler);
++	BUG();
++}
++
++
++static void sdio_ar6000_poll(void *context)
++{
++	HIF_DEVICE *hif = context;
++	A_STATUS status;
++
++	while (1) {
++		yield();
++		if (!gpio_get_value(IRQ_GPIO))
++			continue;
++		if (!atomic_add_unless(&mask, 1, 1))
++			continue;
++		status = htcCallbacks.dsrHandler(hif->htc_handle);
++		BUG_ON(status != A_OK);
++	}
++}
++
++
++void HIFAckInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++	int ret;
++
++	ret = atomic_dec_return(&mask);
++	BUG_ON(ret < 0);
++	dev_dbg(dev, "HIFAckInterrupt (%d)\n", ret);
++}
++
++
++void HIFUnMaskInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++	int ret;
++
++	ret = atomic_dec_return(&mask);
++	BUG_ON(ret < 0);
++	dev_dbg(dev, "HIFUnMaskInterrupt (%d)\n", ret);
++}
++
++
++void HIFMaskInterrupt(HIF_DEVICE *hif)
++{
++	struct device *dev = HIFGetOSDevice(hif);
++	int ret;
++
++	ret = atomic_inc_return(&mask);
++	BUG_ON(ret > 1);
++	dev_dbg(dev, "HIFMaskInterrupt (%d)\n", ret);
++}
++#endif
++
++/* ========================================================================= */
++
++
++/* ----- Some stuff needed for Atheros' API -------------------------------- */
++
++struct device *HIFGetOSDevice(HIF_DEVICE *hif)
++{
++	return &hif->func->dev;
++}
++
++
++void HIFSetHandle(void *hif_handle, void *handle)
++{
++	HIF_DEVICE *hif = (HIF_DEVICE *) hif_handle;
++
++	hif->htc_handle = handle;
++}
++
++
++/* -----  */
++
++
++
++/*
++ * @@@ Atheros' HIF says this hack is necessary. Check this.
++ */
++
++static int inserter(void *data)
++{
++	int ret;
++
++	msleep(1000);
++	ret = htcCallbacks.deviceInsertedHandler(&hif_device);
++	printk(KERN_ERR "got %d\n", ret);
++	return 0;
++}
++
++
++static int sdio_ar6000_probe(struct sdio_func *func,
++    const struct sdio_device_id *id)
++{
++	struct device *dev = &func->dev;
++	int ret;
++	struct task_struct *task;
++
++	dev_dbg(dev, "sdio_ar6000_probe\n");
++	BUG_ON(!htcCallbacks.deviceInsertedHandler);
++
++	sdio_set_drvdata(func, &hif_device);
++	sdio_claim_host(func);
++	sdio_enable_func(func);
++
++	hif_device.func = func;
++	INIT_LIST_HEAD(&hif_device.queue);
++	init_waitqueue_head(&hif_device.wait);
++	spin_lock_init(&hif_device.queue_lock);
++
++	ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
++	if (ret < 0) {
++		dev_err(dev, "sdio_set_block_size returns %d\n", ret);
++		/* @@@ cleanup */
++	}
++	ret = sdio_claim_irq(func, sdio_ar6000_irq);
++	if (ret) {
++		dev_err(dev, "sdio_claim_irq returns %d\n", ret);
++		/* @@@ cleanup */
++	}
++#if 0 /* only for hw SDIO */
++	sdio_f0_writeb(func, SDIO_BUS_CD_DISABLE | SDIO_BUS_WIDTH_4BIT,
++	    SDIO_CCCR_IF, &ret);
++	if (ret) {
++		dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_IF) returns %d\n",
++		    ret);
++		/* @@@ cleanup */
++	}
++#endif
++#if 0
++	sdio_f0_writeb(func, SDIO_CCCR_CAP_E4MI, SDIO_CCCR_CAPS, &ret);
++	if (ret) {
++		dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_CAPS) returns %d\n",
++		    ret);
++		/* @@@ cleanup */
++	}
++#endif
++#if 0
++	/*
++	 * @@@ Samuel's driver sets this, Atheros' Linux SDIO HIF apparently
++	 * doesn't, and things seem to work okay without it here as well.
++	 * Check with Atheros.
++	 */
++	sdio_f0_writeb(func, SDIO_POWER_EMPC, SDIO_CCCR_POWER, &ret);
++	if (ret) {
++		dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_POWER) returns %d\n",
++		    ret);
++		/* @@@ cleanup */
++	}
++#endif
++	sdio_release_host(func);
++
++	hif_device.io_task = kthread_run(io, &hif_device, "ar6000_io");
++	if (IS_ERR(hif_device.io_task)) {
++		dev_err(dev, "kthread_run(ar6000_io): %d\n", ret);
++		/* @@@ cleanup */
++	}
++	task = kthread_run(inserter, NULL, "ar6000_inserter");
++	if (IS_ERR(task)) {
++		dev_err(dev, "kthread_run (ar6000_inserter): %d\n", ret);
++		/* @@@ cleanup */
++	}
++
++	return 0;
++}
++
++
++static void sdio_ar6000_remove(struct sdio_func *func)
++{
++	sdio_claim_host(func);
++	sdio_release_irq(func);
++	sdio_disable_func(func);
++	sdio_release_host(func);
++	/* @@@ remove */
++	/* @@@ kill _tasks */
++}
++
++
++/* @@@ move these definitions to linux/mmc/sdio_ids.h */
++#define SDIO_VENDOR_ID_ATHEROS		0x271
++#define SDIO_DEVICE_ID_ATHEROS_AR6000	0x100
++
++#define ATHEROS_SDIO_DEVICE(id, offset) \
++    SDIO_DEVICE(SDIO_VENDOR_ID_ATHEROS, SDIO_DEVICE_ID_ATHEROS_##id | (offset))
++
++static const struct sdio_device_id sdio_ar6000_ids[] = {
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0)	},
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0x1)	},
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0x8)	},
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0x9)	},
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0xa)	},
++	{ ATHEROS_SDIO_DEVICE(AR6000, 0xb)	},
++	{ /* end: all zeroes */			},
++};
++
++MODULE_DEVICE_TABLE(sdio, sdio_ar6000_ids);
++
++
++static struct sdio_driver sdio_ar6000_driver = {
++	.probe		= sdio_ar6000_probe,
++	.remove		= sdio_ar6000_remove,
++	.name		= "sdio_ar6000",
++	.id_table	= sdio_ar6000_ids,
++};
++
++
++static int __devinit sdio_ar6000_init(void)
++{
++	printk(KERN_INFO "sdio_ar6000_init\n");
++	return sdio_register_driver(&sdio_ar6000_driver);
++}
++
++
++static void __exit sdio_ar6000_exit(void)
++{
++	printk(KERN_INFO "sdio_ar6000_exit\n");
++	sdio_unregister_driver(&sdio_ar6000_driver);
++}
++
++
++module_init(sdio_ar6000_init);
++module_exit(sdio_ar6000_exit);
++
++MODULE_AUTHOR("Werner Almesberger");
++MODULE_LICENSE("GPL");

Modified: developers/werner/wlan-spi/patches-tracking/series
===================================================================
--- developers/werner/wlan-spi/patches-tracking/series	2008-10-15 15:26:47 UTC (rev 4713)
+++ developers/werner/wlan-spi/patches-tracking/series	2008-10-16 00:50:32 UTC (rev 4714)
@@ -1,2 +1,16 @@
+#
+# This patch stack if for the Openmoko stable-tracking branch. Before applying
+# the patches, you need to remove the Atheros SDIO stack as follows:
+#
+# cd drivers
+# mv sdio/function/wlan/ar6000 .
+# rm -rf sdio ../include/linux/sdio
+#
+
 hack-disable-ecc.patch
 hack-mmc-spi-coexistence.patch
+ar6k-without-sdio.patch
+gta02-remove-sdio.patch
+hif-linux-sdio.patch
+gta02-mmc-spi-bitbang.patch
+gta02-mmc-spi.patch




More information about the commitlog mailing list