r4795 - in developers/werner/wlan-spi/patches-tracking: . attic2 nand
werner at docs.openmoko.org
werner at docs.openmoko.org
Mon Nov 17 09:46:25 CET 2008
Author: werner
Date: 2008-11-17 09:46:24 +0100 (Mon, 17 Nov 2008)
New Revision: 4795
Added:
developers/werner/wlan-spi/patches-tracking/attic2/
developers/werner/wlan-spi/patches-tracking/attic2/ar6k-without-sdio.patch
developers/werner/wlan-spi/patches-tracking/attic2/gta02-remove-sdio.patch
developers/werner/wlan-spi/patches-tracking/attic2/hif-linux-sdio.patch
developers/werner/wlan-spi/patches-tracking/attic2/sdio-add-atheros-ar6k.patch
developers/werner/wlan-spi/patches-tracking/attic2/series
developers/werner/wlan-spi/patches-tracking/nand/
developers/werner/wlan-spi/patches-tracking/nand/hack-disable-ecc.patch
developers/werner/wlan-spi/patches-tracking/nand/reverse-ecc-fix.patch
developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-handle-bytes.patch
developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-shift-not-div.patch
developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-use-iomem.patch
Removed:
developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch
developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch
developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch
developers/werner/wlan-spi/patches-tracking/sdio-add-atheros-ar6k.patch
developers/werner/wlan-spi/patches-tracking/series
Log:
- move patches now in stable-tracking over to attic2/
- keep NAND patches for posteriority (note: they're on a parallel track via
Ben's tree - this is merely a backup)
Deleted: developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch 2008-11-16 07:57:38 UTC (rev 4794)
+++ developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -1,63 +0,0 @@
-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-11-02 02:50:01.000000000 -0200
-+++ ktrack/arch/arm/Kconfig 2008-11-02 04:29:20.000000000 -0200
-@@ -1269,7 +1269,7 @@
-
- source "drivers/uwb/Kconfig"
-
--source "drivers/sdio/Kconfig"
-+source "drivers/ar6000/Kconfig"
-
- source "drivers/mmc/Kconfig"
-
-Index: ktrack/drivers/Makefile
-===================================================================
---- ktrack.orig/drivers/Makefile 2008-11-02 02:50:02.000000000 -0200
-+++ ktrack/drivers/Makefile 2008-11-02 04:29:20.000000000 -0200
-@@ -87,6 +87,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-11-02 04:29:20.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-11-02 02:50:02.000000000 -0200
-+++ ktrack/drivers/ar6000/Makefile 2008-11-02 04:29:20.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 \
Copied: developers/werner/wlan-spi/patches-tracking/attic2/ar6k-without-sdio.patch (from rev 4746, developers/werner/wlan-spi/patches-tracking/ar6k-without-sdio.patch)
===================================================================
--- developers/werner/wlan-spi/patches-tracking/attic2/ar6k-without-sdio.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/attic2/ar6k-without-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -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-11-02 02:50:01.000000000 -0200
++++ ktrack/arch/arm/Kconfig 2008-11-02 04:29:20.000000000 -0200
+@@ -1269,7 +1269,7 @@
+
+ source "drivers/uwb/Kconfig"
+
+-source "drivers/sdio/Kconfig"
++source "drivers/ar6000/Kconfig"
+
+ source "drivers/mmc/Kconfig"
+
+Index: ktrack/drivers/Makefile
+===================================================================
+--- ktrack.orig/drivers/Makefile 2008-11-02 02:50:02.000000000 -0200
++++ ktrack/drivers/Makefile 2008-11-02 04:29:20.000000000 -0200
+@@ -87,6 +87,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-11-02 04:29:20.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-11-02 02:50:02.000000000 -0200
++++ ktrack/drivers/ar6000/Makefile 2008-11-02 04:29:20.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 \
Copied: developers/werner/wlan-spi/patches-tracking/attic2/gta02-remove-sdio.patch (from rev 4733, developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch)
===================================================================
--- developers/werner/wlan-spi/patches-tracking/attic2/gta02-remove-sdio.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/attic2/gta02-remove-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,57 @@
+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-29 03:31:14.000000000 -0200
++++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c 2008-10-29 03:33:37.000000000 -0200
+@@ -876,36 +876,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,
+@@ -1582,7 +1552,6 @@
+ >a01_pm_gps_dev,
+ >a01_pm_bt_dev,
+ >a02_pm_gsm_dev,
+- >a02_sdio_dev,
+ >a02_pm_usbhost_dev,
+ &s3c_device_spi_acc1, /* input 2 */
+ &s3c_device_spi_acc2, /* input 3 */
Copied: developers/werner/wlan-spi/patches-tracking/attic2/hif-linux-sdio.patch (from rev 4744, developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch)
===================================================================
--- developers/werner/wlan-spi/patches-tracking/attic2/hif-linux-sdio.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/attic2/hif-linux-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,627 @@
+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-11-02 23:09:13.000000000 -0200
++++ ktrack/drivers/ar6000/Makefile 2008-11-02 23:09:15.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-11-02 23:46:53.000000000 -0200
+@@ -0,0 +1,598 @@
++/*
++ * 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/sched.h>
++#include <linux/mmc/sdio_func.h>
++#include <linux/mmc/sdio.h>
++#include <linux/mmc/sdio_ids.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)
++ * - 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
++ */
++
++/*
++ * Differences from Atheros' HIFs:
++ *
++ * - synchronous and asynchronous requests may get reordered with respect to
++ * each other, e.g., if HIFReadWrite returns for an asynchronous request and
++ * then HIFReadWrite is called for a synchronous request, the synchronous
++ * request may be executed before the asynchronous request.
++ *
++ * - request queue locking seems unnecessarily complex in the Atheros HIFs.
++ *
++ * - Atheros mask interrupts by calling sdio_claim_irq/sdio_release_irq, which
++ * can cause quite a bit of overhead. This HIF has its own light-weight
++ * interrupt masking.
++ *
++ * - Atheros call deviceInsertedHandler from a thread spawned off the probe or
++ * device insertion function. The original explanation for the Atheros SDIO
++ * stack said that this is done because a delay is needed to let the chip
++ * complete initialization. There is indeed a one second delay in the thread.
++ *
++ * The Atheros Linux SDIO HIF removes the delay and only retains the thread.
++ * Experimentally removing the thread didn't show any conflicts, so let's get
++ * rid of it for good.
++ *
++ * - The Atheros SDIO stack with Samuel's driver sets SDIO_CCCR_POWER in
++ * SDIO_POWER_EMPC. Atheros' Linux SDIO code apparently doesn't. We don't
++ * either, and this seems to work fine.
++ * @@@ Need to check this with Atheros.
++ */
++
++
++#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 HTC_CALLBACKS htcCallbacks;
++
++
++/* ----- Request processing ------------------------------------------------ */
++
++
++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 void wait_queue_empty(struct hif_device *hif)
++{
++ unsigned long flags;
++ int empty;
++
++ while (1) {
++ spin_lock_irqsave(&hif->queue_lock, flags);
++ empty = list_empty(&hif->queue);
++ spin_unlock_irqrestore(&hif->queue_lock, flags);
++ if (empty)
++ break;
++ else
++ yield();
++ }
++}
++
++
++static int io(void *data)
++{
++ struct hif_device *hif = data;
++ struct sched_param param = { .sched_priority = 2 };
++ /* one priority level slower than ksdioirqd (which is at 1) */
++ DEFINE_WAIT(wait);
++ struct hif_request *req;
++
++ sched_setscheduler(current, SCHED_FIFO, ¶m);
++
++ while (1) {
++ while (1) {
++ /*
++ * Since we never use signals here, one might think
++ * that this ought to be TASK_UNINTERRUPTIBLE. However,
++ * such a task would increase the load average and,
++ * worse, it would trigger the softlockup check.
++ */
++ prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE);
++ if (kthread_should_stop()) {
++ finish_wait(&hif->wait, &wait);
++ return 0;
++ }
++ req = dequeue_request(hif);
++ if (req)
++ break;
++ schedule();
++ }
++ finish_wait(&hif->wait, &wait);
++
++ (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;
++}
++
++
++/* ----- Interrupt handling ------------------------------------------------ */
++
++/*
++ * 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();
++}
++
++
++/* ----- HIF API glue functions -------------------------------------------- */
++
++
++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;
++}
++
++
++/* ----- Device configuration (HIF side) ----------------------------------- */
++
++
++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;
++}
++
++
++/* ----- Device probe and removal (Linux side) ----------------------------- */
++
++
++static int sdio_ar6000_probe(struct sdio_func *func,
++ const struct sdio_device_id *id)
++{
++ struct device *dev = &func->dev;
++ struct hif_device *hif;
++ int ret;
++
++ dev_dbg(dev, "sdio_ar6000_probe\n");
++ BUG_ON(!htcCallbacks.deviceInsertedHandler);
++
++ hif = kzalloc(sizeof(*hif), GFP_KERNEL);
++ if (!hif)
++ return -ENOMEM;
++
++ sdio_set_drvdata(func, hif);
++ sdio_claim_host(func);
++ sdio_enable_func(func);
++
++ hif->func = func;
++ INIT_LIST_HEAD(&hif->queue);
++ init_waitqueue_head(&hif->wait);
++ spin_lock_init(&hif->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);
++ goto out_enabled;
++ }
++ ret = sdio_claim_irq(func, sdio_ar6000_irq);
++ if (ret) {
++ dev_err(dev, "sdio_claim_irq returns %d\n", ret);
++ goto out_enabled;
++ }
++ /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */
++#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);
++ goto out_got_irq;
++ }
++#endif
++
++ sdio_release_host(func);
++
++ hif->io_task = kthread_run(io, hif, "ar6000_io");
++ if (IS_ERR(hif->io_task)) {
++ dev_err(dev, "kthread_run(ar6000_io): %d\n", ret);
++ goto out_func_ready;
++ }
++
++ ret = htcCallbacks.deviceInsertedHandler(hif);
++ if (ret == A_OK)
++ return 0;
++
++ dev_err(dev, "deviceInsertedHandler: %d\n", ret);
++
++ ret = kthread_stop(hif->io_task);
++ if (ret)
++ dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
++
++out_func_ready:
++ sdio_claim_host(func);
++
++/* generates a warning */
++out_got_irq:
++ sdio_release_irq(func);
++
++out_enabled:
++ sdio_set_drvdata(func, NULL);
++ sdio_disable_func(func);
++ sdio_release_host(func);
++
++ return ret;
++}
++
++
++static void sdio_ar6000_remove(struct sdio_func *func)
++{
++ struct device *dev = &func->dev;
++ HIF_DEVICE *hif = sdio_get_drvdata(func);
++ int ret;
++
++#if 0
++ /*
++ * Funny, Atheros' HIF does this call, but this just puts us in a
++ * recursion through HTCShutDown/HIFShutDown if unloading the
++ * module.
++ */
++ ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK);
++ if (ret != A_OK)
++ dev_err(dev, "deviceRemovedHandler: %d\n", ret);
++#endif
++ wait_queue_empty(hif);
++ ret = kthread_stop(hif->io_task);
++ if (ret)
++ dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
++ sdio_claim_host(func);
++ sdio_release_irq(func);
++ sdio_set_drvdata(func, NULL);
++ sdio_disable_func(func);
++ sdio_release_host(func);
++ kfree(hif);
++}
++
++
++/* ----- Device registration/unregistration (called by HIF) ---------------- */
++
++
++#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,
++};
++
++
++int HIFInit(HTC_CALLBACKS *callbacks)
++{
++ int ret;
++
++ BUG_ON(!callbacks);
++
++ printk(KERN_DEBUG "HIFInit\n");
++ htcCallbacks = *callbacks;
++
++ ret = sdio_register_driver(&sdio_ar6000_driver);
++ if (ret) {
++ printk(KERN_ERR
++ "sdio_register_driver(sdio_ar6000_driver): %d\n", ret);
++ return A_ERROR;
++ }
++
++ return 0;
++}
++
++
++void HIFShutDownDevice(HIF_DEVICE *hif)
++{
++ /* Beware, HTCShutDown calls us with hif == NULL ! */
++ sdio_unregister_driver(&sdio_ar6000_driver);
++}
Copied: developers/werner/wlan-spi/patches-tracking/attic2/sdio-add-atheros-ar6k.patch (from rev 4740, developers/werner/wlan-spi/patches-tracking/sdio-add-atheros-ar6k.patch)
===================================================================
--- developers/werner/wlan-spi/patches-tracking/attic2/sdio-add-atheros-ar6k.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/attic2/sdio-add-atheros-ar6k.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,12 @@
+Index: ktrack/include/linux/mmc/sdio_ids.h
+===================================================================
+--- ktrack.orig/include/linux/mmc/sdio_ids.h 2008-11-02 08:02:38.000000000 -0200
++++ ktrack/include/linux/mmc/sdio_ids.h 2008-11-02 08:02:55.000000000 -0200
+@@ -25,5 +25,7 @@
+
+ #define SDIO_VENDOR_ID_MARVELL 0x02df
+ #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
++#define SDIO_VENDOR_ID_ATHEROS 0x0271
++#define SDIO_DEVICE_ID_ATHEROS_AR6000 0x0100
+
+ #endif
Copied: developers/werner/wlan-spi/patches-tracking/attic2/series (from rev 4794, developers/werner/wlan-spi/patches-tracking/series)
===================================================================
--- developers/werner/wlan-spi/patches-tracking/attic2/series (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/attic2/series 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,31 @@
+#
+# This patch stack is for the Openmoko stable-tracking branch. Before applying
+# the patches, you need to remove the Atheros SDIO stack as follows:
+#
+# cd drivers
+# rm -rf ar6000
+# mv sdio/function/wlan/ar6000 .
+# rm -rf sdio ../include/linux/sdio
+#
+# Alternative procedure:
+#
+# rm -rf drivers/ar6000 # in case this operation is repeated
+# git mv drivers/sdio/function/wlan/ar6000 drivers/ar6000
+# git rm -r drivers/sdio include/linux/sdio
+# git commit -m "Remove Atheros SDIO stack."
+# rm -rf drivers/sdio
+#
+
+ar6k-without-sdio.patch
+gta02-remove-sdio.patch
+sdio-add-atheros-ar6k.patch
+hif-linux-sdio.patch
+
+gta02-mmc-mci.patch
+
+# dirty experimental stuff follows
+
+#hif-can-do-async.patch
+
+# still needs a bit more love ...
+#s3c-mmc-sdio-int.patch
Deleted: developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch 2008-11-16 07:57:38 UTC (rev 4794)
+++ developers/werner/wlan-spi/patches-tracking/gta02-remove-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -1,57 +0,0 @@
-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-29 03:31:14.000000000 -0200
-+++ ktrack/arch/arm/mach-s3c2440/mach-gta02.c 2008-10-29 03:33:37.000000000 -0200
-@@ -876,36 +876,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,
-@@ -1582,7 +1552,6 @@
- >a01_pm_gps_dev,
- >a01_pm_bt_dev,
- >a02_pm_gsm_dev,
-- >a02_sdio_dev,
- >a02_pm_usbhost_dev,
- &s3c_device_spi_acc1, /* input 2 */
- &s3c_device_spi_acc2, /* input 3 */
Deleted: developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch 2008-11-16 07:57:38 UTC (rev 4794)
+++ developers/werner/wlan-spi/patches-tracking/hif-linux-sdio.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -1,627 +0,0 @@
-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-11-02 23:09:13.000000000 -0200
-+++ ktrack/drivers/ar6000/Makefile 2008-11-02 23:09:15.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-11-02 23:46:53.000000000 -0200
-@@ -0,0 +1,598 @@
-+/*
-+ * 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/sched.h>
-+#include <linux/mmc/sdio_func.h>
-+#include <linux/mmc/sdio.h>
-+#include <linux/mmc/sdio_ids.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)
-+ * - 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
-+ */
-+
-+/*
-+ * Differences from Atheros' HIFs:
-+ *
-+ * - synchronous and asynchronous requests may get reordered with respect to
-+ * each other, e.g., if HIFReadWrite returns for an asynchronous request and
-+ * then HIFReadWrite is called for a synchronous request, the synchronous
-+ * request may be executed before the asynchronous request.
-+ *
-+ * - request queue locking seems unnecessarily complex in the Atheros HIFs.
-+ *
-+ * - Atheros mask interrupts by calling sdio_claim_irq/sdio_release_irq, which
-+ * can cause quite a bit of overhead. This HIF has its own light-weight
-+ * interrupt masking.
-+ *
-+ * - Atheros call deviceInsertedHandler from a thread spawned off the probe or
-+ * device insertion function. The original explanation for the Atheros SDIO
-+ * stack said that this is done because a delay is needed to let the chip
-+ * complete initialization. There is indeed a one second delay in the thread.
-+ *
-+ * The Atheros Linux SDIO HIF removes the delay and only retains the thread.
-+ * Experimentally removing the thread didn't show any conflicts, so let's get
-+ * rid of it for good.
-+ *
-+ * - The Atheros SDIO stack with Samuel's driver sets SDIO_CCCR_POWER in
-+ * SDIO_POWER_EMPC. Atheros' Linux SDIO code apparently doesn't. We don't
-+ * either, and this seems to work fine.
-+ * @@@ Need to check this with Atheros.
-+ */
-+
-+
-+#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 HTC_CALLBACKS htcCallbacks;
-+
-+
-+/* ----- Request processing ------------------------------------------------ */
-+
-+
-+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 void wait_queue_empty(struct hif_device *hif)
-+{
-+ unsigned long flags;
-+ int empty;
-+
-+ while (1) {
-+ spin_lock_irqsave(&hif->queue_lock, flags);
-+ empty = list_empty(&hif->queue);
-+ spin_unlock_irqrestore(&hif->queue_lock, flags);
-+ if (empty)
-+ break;
-+ else
-+ yield();
-+ }
-+}
-+
-+
-+static int io(void *data)
-+{
-+ struct hif_device *hif = data;
-+ struct sched_param param = { .sched_priority = 2 };
-+ /* one priority level slower than ksdioirqd (which is at 1) */
-+ DEFINE_WAIT(wait);
-+ struct hif_request *req;
-+
-+ sched_setscheduler(current, SCHED_FIFO, ¶m);
-+
-+ while (1) {
-+ while (1) {
-+ /*
-+ * Since we never use signals here, one might think
-+ * that this ought to be TASK_UNINTERRUPTIBLE. However,
-+ * such a task would increase the load average and,
-+ * worse, it would trigger the softlockup check.
-+ */
-+ prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE);
-+ if (kthread_should_stop()) {
-+ finish_wait(&hif->wait, &wait);
-+ return 0;
-+ }
-+ req = dequeue_request(hif);
-+ if (req)
-+ break;
-+ schedule();
-+ }
-+ finish_wait(&hif->wait, &wait);
-+
-+ (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;
-+}
-+
-+
-+/* ----- Interrupt handling ------------------------------------------------ */
-+
-+/*
-+ * 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();
-+}
-+
-+
-+/* ----- HIF API glue functions -------------------------------------------- */
-+
-+
-+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;
-+}
-+
-+
-+/* ----- Device configuration (HIF side) ----------------------------------- */
-+
-+
-+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;
-+}
-+
-+
-+/* ----- Device probe and removal (Linux side) ----------------------------- */
-+
-+
-+static int sdio_ar6000_probe(struct sdio_func *func,
-+ const struct sdio_device_id *id)
-+{
-+ struct device *dev = &func->dev;
-+ struct hif_device *hif;
-+ int ret;
-+
-+ dev_dbg(dev, "sdio_ar6000_probe\n");
-+ BUG_ON(!htcCallbacks.deviceInsertedHandler);
-+
-+ hif = kzalloc(sizeof(*hif), GFP_KERNEL);
-+ if (!hif)
-+ return -ENOMEM;
-+
-+ sdio_set_drvdata(func, hif);
-+ sdio_claim_host(func);
-+ sdio_enable_func(func);
-+
-+ hif->func = func;
-+ INIT_LIST_HEAD(&hif->queue);
-+ init_waitqueue_head(&hif->wait);
-+ spin_lock_init(&hif->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);
-+ goto out_enabled;
-+ }
-+ ret = sdio_claim_irq(func, sdio_ar6000_irq);
-+ if (ret) {
-+ dev_err(dev, "sdio_claim_irq returns %d\n", ret);
-+ goto out_enabled;
-+ }
-+ /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */
-+#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);
-+ goto out_got_irq;
-+ }
-+#endif
-+
-+ sdio_release_host(func);
-+
-+ hif->io_task = kthread_run(io, hif, "ar6000_io");
-+ if (IS_ERR(hif->io_task)) {
-+ dev_err(dev, "kthread_run(ar6000_io): %d\n", ret);
-+ goto out_func_ready;
-+ }
-+
-+ ret = htcCallbacks.deviceInsertedHandler(hif);
-+ if (ret == A_OK)
-+ return 0;
-+
-+ dev_err(dev, "deviceInsertedHandler: %d\n", ret);
-+
-+ ret = kthread_stop(hif->io_task);
-+ if (ret)
-+ dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
-+
-+out_func_ready:
-+ sdio_claim_host(func);
-+
-+/* generates a warning */
-+out_got_irq:
-+ sdio_release_irq(func);
-+
-+out_enabled:
-+ sdio_set_drvdata(func, NULL);
-+ sdio_disable_func(func);
-+ sdio_release_host(func);
-+
-+ return ret;
-+}
-+
-+
-+static void sdio_ar6000_remove(struct sdio_func *func)
-+{
-+ struct device *dev = &func->dev;
-+ HIF_DEVICE *hif = sdio_get_drvdata(func);
-+ int ret;
-+
-+#if 0
-+ /*
-+ * Funny, Atheros' HIF does this call, but this just puts us in a
-+ * recursion through HTCShutDown/HIFShutDown if unloading the
-+ * module.
-+ */
-+ ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK);
-+ if (ret != A_OK)
-+ dev_err(dev, "deviceRemovedHandler: %d\n", ret);
-+#endif
-+ wait_queue_empty(hif);
-+ ret = kthread_stop(hif->io_task);
-+ if (ret)
-+ dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
-+ sdio_claim_host(func);
-+ sdio_release_irq(func);
-+ sdio_set_drvdata(func, NULL);
-+ sdio_disable_func(func);
-+ sdio_release_host(func);
-+ kfree(hif);
-+}
-+
-+
-+/* ----- Device registration/unregistration (called by HIF) ---------------- */
-+
-+
-+#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,
-+};
-+
-+
-+int HIFInit(HTC_CALLBACKS *callbacks)
-+{
-+ int ret;
-+
-+ BUG_ON(!callbacks);
-+
-+ printk(KERN_DEBUG "HIFInit\n");
-+ htcCallbacks = *callbacks;
-+
-+ ret = sdio_register_driver(&sdio_ar6000_driver);
-+ if (ret) {
-+ printk(KERN_ERR
-+ "sdio_register_driver(sdio_ar6000_driver): %d\n", ret);
-+ return A_ERROR;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+void HIFShutDownDevice(HIF_DEVICE *hif)
-+{
-+ /* Beware, HTCShutDown calls us with hif == NULL ! */
-+ sdio_unregister_driver(&sdio_ar6000_driver);
-+}
Added: developers/werner/wlan-spi/patches-tracking/nand/hack-disable-ecc.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/nand/hack-disable-ecc.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/nand/hack-disable-ecc.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,32 @@
+Index: ktrack/drivers/mtd/nand/nand_base.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/nand_base.c 2008-10-29 00:57:08.000000000 -0200
++++ ktrack/drivers/mtd/nand/nand_base.c 2008-10-29 03:17:39.000000000 -0200
+@@ -775,6 +775,7 @@
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+
+ chip->ecc.read_page_raw(mtd, chip, buf);
++ return 0;
+
+ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+@@ -830,6 +831,7 @@
+
+ p = bufpoi + data_col_addr;
+ chip->read_buf(mtd, p, datafrag_len);
++ return 0;
+
+ /* Calculate ECC */
+ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
+Index: ktrack/drivers/mtd/nand/nand_ecc.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/nand_ecc.c 2008-10-29 00:57:08.000000000 -0200
++++ ktrack/drivers/mtd/nand/nand_ecc.c 2008-10-29 03:17:56.000000000 -0200
+@@ -434,6 +434,7 @@
+ const uint32_t eccsize_mult =
+ (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+
++ return 0;
+ /*
+ * b0 to b2 indicate which bit is faulty (if any)
+ * we might need the xor result more than once,
Added: developers/werner/wlan-spi/patches-tracking/nand/reverse-ecc-fix.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/nand/reverse-ecc-fix.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/nand/reverse-ecc-fix.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,17 @@
+Index: ktrack/drivers/mtd/nand/s3c2410.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/s3c2410.c 2008-11-03 12:55:06.000000000 -0200
++++ ktrack/drivers/mtd/nand/s3c2410.c 2008-11-03 12:55:11.000000000 -0200
+@@ -530,12 +530,7 @@
+ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+ {
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+- u8 *ptr = buf + (len & ~3);
+- int i;
+-
+ readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
+- for (i = 0; i != (len & 3); i++)
+- ptr[i] = readb(info->regs + S3C2440_NFDATA);
+ }
+
+ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
Added: developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-handle-bytes.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-handle-bytes.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-handle-bytes.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,43 @@
+s3c2440-nand-handle-bytes.patch
+
+With the introduction of optimized OOB reads in nand_read_subpage,
+the length of the data requested may not be a multiple of four bytes.
+
+This caused a partial read on the 2440, leading to false ECC errors
+and, worse, attempts to "correct" them.
+
+This patch adds reading/writing of trailing bytes to
+s3c2440_nand_read_buf and (untested) s3c2410_nand_write_buf.
+
+Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+---
+
+Index: ktrack/drivers/mtd/nand/s3c2410.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/s3c2410.c 2008-11-03 14:06:00.000000000 -0200
++++ ktrack/drivers/mtd/nand/s3c2410.c 2008-11-03 14:06:20.000000000 -0200
+@@ -530,7 +530,11 @@
+ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+ {
+ struct nand_chip *chip = mtd->priv;
++ int i;
++
+ readsl(chip->IO_ADDR_R, buf, len >> 2);
++ for (i = len & ~3; unlikely(i != len); i++)
++ buf[i] = readb(chip->IO_ADDR_R);
+ }
+
+ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+@@ -542,7 +546,11 @@
+ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+ {
+ struct nand_chip *chip = mtd->priv;
++ int i;
++
+ writesl(chip->IO_ADDR_W, buf, len >> 2);
++ for (i = len & ~3; unlikely(i != len); i++)
++ writeb(buf[i], chip->IO_ADDR_W);
+ }
+
+ /* cpufreq driver support */
Added: developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-shift-not-div.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-shift-not-div.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-shift-not-div.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,33 @@
+s3c2440-nand-shift-not-div.patch
+
+The divisions of the signed access lengths caused GCC to emit
+unnecessary code for handling negative values.
+
+Changing them to shifts saves 24 bytes.
+
+Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+---
+
+Index: ktrack/drivers/mtd/nand/s3c2410.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/s3c2410.c 2008-11-03 12:55:53.000000000 -0200
++++ ktrack/drivers/mtd/nand/s3c2410.c 2008-11-03 12:58:18.000000000 -0200
+@@ -530,7 +530,7 @@
+ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+ {
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+- readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
++ readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
+ }
+
+ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+@@ -542,7 +542,7 @@
+ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+ {
+ struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+- writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
++ writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
+ }
+
+ /* cpufreq driver support */
Added: developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-use-iomem.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-use-iomem.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/nand/s3c2440-nand-use-iomem.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -0,0 +1,35 @@
+s3c2440-nand-use-iomem.patch
+
+Using chip->IO_ADDR_R/IO_ADDR_W, which is __iomem, prevents the
+compiler from needlessly reloading constant data.
+
+Signed-off-by: Werner Almesberger <werner at openmoko.org>
+
+---
+
+Index: ktrack/drivers/mtd/nand/s3c2410.c
+===================================================================
+--- ktrack.orig/drivers/mtd/nand/s3c2410.c 2008-11-03 14:05:19.000000000 -0200
++++ ktrack/drivers/mtd/nand/s3c2410.c 2008-11-03 14:06:00.000000000 -0200
+@@ -529,8 +529,8 @@
+
+ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+ {
+- struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+- readsl(info->regs + S3C2440_NFDATA, buf, len >> 2);
++ struct nand_chip *chip = mtd->priv;
++ readsl(chip->IO_ADDR_R, buf, len >> 2);
+ }
+
+ static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+@@ -541,8 +541,8 @@
+
+ static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+ {
+- struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+- writesl(info->regs + S3C2440_NFDATA, buf, len >> 2);
++ struct nand_chip *chip = mtd->priv;
++ writesl(chip->IO_ADDR_W, buf, len >> 2);
+ }
+
+ /* cpufreq driver support */
Deleted: developers/werner/wlan-spi/patches-tracking/sdio-add-atheros-ar6k.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/sdio-add-atheros-ar6k.patch 2008-11-16 07:57:38 UTC (rev 4794)
+++ developers/werner/wlan-spi/patches-tracking/sdio-add-atheros-ar6k.patch 2008-11-17 08:46:24 UTC (rev 4795)
@@ -1,12 +0,0 @@
-Index: ktrack/include/linux/mmc/sdio_ids.h
-===================================================================
---- ktrack.orig/include/linux/mmc/sdio_ids.h 2008-11-02 08:02:38.000000000 -0200
-+++ ktrack/include/linux/mmc/sdio_ids.h 2008-11-02 08:02:55.000000000 -0200
-@@ -25,5 +25,7 @@
-
- #define SDIO_VENDOR_ID_MARVELL 0x02df
- #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
-+#define SDIO_VENDOR_ID_ATHEROS 0x0271
-+#define SDIO_DEVICE_ID_ATHEROS_AR6000 0x0100
-
- #endif
Deleted: developers/werner/wlan-spi/patches-tracking/series
===================================================================
--- developers/werner/wlan-spi/patches-tracking/series 2008-11-16 07:57:38 UTC (rev 4794)
+++ developers/werner/wlan-spi/patches-tracking/series 2008-11-17 08:46:24 UTC (rev 4795)
@@ -1,31 +0,0 @@
-#
-# This patch stack is for the Openmoko stable-tracking branch. Before applying
-# the patches, you need to remove the Atheros SDIO stack as follows:
-#
-# cd drivers
-# rm -rf ar6000
-# mv sdio/function/wlan/ar6000 .
-# rm -rf sdio ../include/linux/sdio
-#
-# Alternative procedure:
-#
-# rm -rf drivers/ar6000 # in case this operation is repeated
-# git mv drivers/sdio/function/wlan/ar6000 drivers/ar6000
-# git rm -r drivers/sdio include/linux/sdio
-# git commit -m "Remove Atheros SDIO stack."
-# rm -rf drivers/sdio
-#
-
-ar6k-without-sdio.patch
-gta02-remove-sdio.patch
-sdio-add-atheros-ar6k.patch
-hif-linux-sdio.patch
-
-gta02-mmc-mci.patch
-
-# dirty experimental stuff follows
-
-#hif-can-do-async.patch
-
-# still needs a bit more love ...
-#s3c-mmc-sdio-int.patch
More information about the commitlog
mailing list