add rough vlynq support
authorEugene Konev <ejka@imfi.kspu.ru>
Fri, 5 Oct 2007 17:55:15 +0000 (17:55 +0000)
committerEugene Konev <ejka@imfi.kspu.ru>
Fri, 5 Oct 2007 17:55:15 +0000 (17:55 +0000)
SVN-Revision: 9144

package/acx-mac80211/patches/002-acx_vlynq.diff [new file with mode: 0644]
package/acx-mac80211/patches/002-no_reset.diff [deleted file]

diff --git a/package/acx-mac80211/patches/002-acx_vlynq.diff b/package/acx-mac80211/patches/002-acx_vlynq.diff
new file mode 100644 (file)
index 0000000..69d13f9
--- /dev/null
@@ -0,0 +1,556 @@
+diff -Nru 1/acx_struct.h 2/acx_struct.h
+--- 1/acx_struct.h     2007-10-03 23:42:39.000000000 +0800
++++ 2/acx_struct.h     2007-10-06 01:15:32.000000000 +0800
+@@ -1425,7 +1425,13 @@
+       const u16       *io;            /* points to ACX100 or ACX111 PCI I/O register address set */
++#ifdef CONFIG_PCI
+       struct pci_dev  *pdev;
++#endif
++#ifdef CONFIG_VLYNQ
++      struct vlynq_device     *vdev;
++#endif
++      struct device *bus_dev;
+       unsigned long   membase;
+       unsigned long   membase2;
+diff -Nru 1/pci.c 2/pci.c
+--- 1/pci.c    2007-10-03 23:42:39.000000000 +0800
++++ 2/pci.c    2007-10-06 01:15:32.000000000 +0800
+@@ -33,11 +33,15 @@
+ #include <linux/ethtool.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/workqueue.h>
++#ifdef CONFIG_VLYNQ
++#include <linux/vlynq.h>
++#endif
+ #include "acx.h"
+ /***********************************************************************
+ */
++#ifdef CONFIG_PCI
+ #define PCI_TYPE              (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
+ #define PCI_ACX100_REGION1            0x01
+ #define PCI_ACX100_REGION1_SIZE               0x1000  /* Memory size - 4K bytes */
+@@ -74,7 +78,7 @@
+ #define PCI_UNKNOWN   5
+ #define PCI_POWER_ERROR       -1
+ #endif
+-
++#endif /* CONFIG_PCI */
+ /***********************************************************************
+ */
+@@ -87,12 +91,6 @@
+ static void acxpci_s_up(struct ieee80211_hw *hw);
+ static void acxpci_s_down(struct ieee80211_hw *hw);
+-void acxpci_put_devname(acx_device_t *adev, struct ethtool_drvinfo *info)
+-{
+-
+-        strncpy(info->bus_info,pci_name(adev->pdev), ETHTOOL_BUSINFO_LEN);
+-}
+-
+ /***********************************************************************
+ ** Register access
+ **
+@@ -605,12 +603,12 @@
+       snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
+                IS_ACX111(adev) * 11, adev->radio_type);
+-      fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
++      fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
+       if (!fw_image) {
+               adev->need_radio_fw = 1;
+               filename[sizeof("tiacx1NN") - 1] = '\0';
+               fw_image =
+-                  acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
++                  acx_s_read_fw(adev->bus_dev, filename, &file_size);
+               if (!fw_image) {
+                       FN_EXIT1(NOT_OK);
+                       return NOT_OK;
+@@ -670,7 +668,7 @@
+       snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
+                IS_ACX111(adev) * 11, adev->radio_type);
+-      radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
++      radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
+       if (!radio_image) {
+               printk("acx: can't load radio module '%s'\n", filename);
+               goto fail;
+@@ -886,7 +884,9 @@
+       acx_lock(adev, flags);
++#ifdef CONFIG_PCI
+       acxpci_l_reset_mac(adev);
++#endif
+       ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
+       if (!ecpu_ctrl) {
+@@ -1426,6 +1426,7 @@
+ };
++#ifdef CONFIG_PCI
+ static int __devinit
+ acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+@@ -1477,6 +1478,7 @@
+       /* acx_sem_lock(adev); */
+       adev->ieee = ieee;
+       adev->pdev = pdev;
++      adev->bus_dev = &pdev->dev;
+       adev->dev_type = DEVTYPE_PCI;
+ /** Finished with private interface **/
+@@ -1916,7 +1918,7 @@
+       return OK;
+ }
+ #endif /* CONFIG_PM */
+-
++#endif /* CONFIG_PCI */
+ /***********************************************************************
+ ** acxpci_s_up
+@@ -1998,7 +2000,7 @@
+       /* then wait until interrupts have finished executing on other CPUs */
+       acx_lock(adev, flags);
+       disable_acx_irq(adev);
+-        synchronize_irq(adev->pdev->irq);
++        synchronize_irq(adev->irq);
+       acx_unlock(adev, flags);
+       /* we really don't want to have an asynchronous tasklet disturb us
+@@ -3449,8 +3451,7 @@
+ {
+       void *ptr;
+-      ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
+-                               size, phy, GFP_KERNEL);
++      ptr = dma_alloc_coherent(adev->bus_dev, size, phy, GFP_KERNEL);
+       if (ptr) {
+               log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
+@@ -4016,10 +4017,371 @@
+       return OK;
+ }
++#ifdef CONFIG_VLYNQ
++struct vlynq_reg_config {
++      u32 offset;
++      u32 value;
++};
++
++struct vlynq_known {
++      u32 chip_id;
++      char name[32];
++      struct vlynq_mapping rx_mapping[4];
++      int irq;
++      int irq_type;
++      int num_regs;
++      struct vlynq_reg_config regs[10];
++};
++
++#define CHIP_TNETW1130 0x00000009
++#define CHIP_TNETW1350 0x00000029
++
++static struct vlynq_known known_devices[] = {
++      {
++              .chip_id = CHIP_TNETW1130, .name = "TI TNETW1130",
++              .rx_mapping = {
++                      { .size = 0x22000, .offset = 0xf0000000 },
++                      { .size = 0x40000, .offset = 0xc0000000 },
++                      { .size = 0x0, .offset = 0x0 },
++                      { .size = 0x0, .offset = 0x0 },
++              },
++              .irq = 0,
++              .irq_type = IRQ_TYPE_EDGE_RISING,
++              .num_regs = 5,
++              .regs = {
++                      {
++                              .offset = 0x790,
++                              .value = (0xd0000000 - PHYS_OFFSET)
++                      },
++                      {
++                              .offset = 0x794,
++                              .value = (0xd0000000 - PHYS_OFFSET)
++                      },
++                      { .offset = 0x740, .value = 0 },
++                      { .offset = 0x744, .value = 0x00010000 },
++                      { .offset = 0x764, .value = 0x00010000 },
++              },
++      },
++      {
++              .chip_id = CHIP_TNETW1350, .name = "TI TNETW1350",
++              .rx_mapping = {
++                      { .size = 0x100000, .offset = 0x00300000 },
++                      { .size = 0x80000, .offset = 0x00000000 },
++                      { .size = 0x0, .offset = 0x0 },
++                      { .size = 0x0, .offset = 0x0 },
++              },
++              .irq = 0,
++              .irq_type = IRQ_TYPE_EDGE_RISING,
++              .num_regs = 5,
++              .regs = {
++                      {
++                              .offset = 0x790,
++                              .value = (0x60000000 - PHYS_OFFSET)
++                      },
++                      {
++                              .offset = 0x794,
++                              .value = (0x60000000 - PHYS_OFFSET)
++                      },
++                      { .offset = 0x740, .value = 0 },
++                      { .offset = 0x744, .value = 0x00010000 },
++                      { .offset = 0x764, .value = 0x00010000 },
++              },
++      },
++};
++
++static struct vlynq_device_id acx_vlynq_id[] = {
++      { CHIP_TNETW1130, vlynq_div_auto, 0 },
++      { CHIP_TNETW1350, vlynq_div_auto, 1 },
++      { 0, 0, 0 },
++};
++
++static __devinit int vlynq_probe(struct vlynq_device *vdev,
++                               struct vlynq_device_id *id)
++{
++      int result = -EIO, i;
++      u32 addr;
++      struct ieee80211_hw *ieee;
++      acx_device_t *adev = NULL;
++      acx111_ie_configoption_t co;
++      struct vlynq_mapping mapping[4] = { { 0, }, };
++      struct vlynq_known *match = NULL;
++
++      FN_ENTER;
++      result = vlynq_enable_device(vdev);
++      if (result)
++              return result;
++
++      match = &known_devices[id->driver_data];
++
++      if (!match) {
++              result = -ENODEV;
++              goto fail;
++      }
++
++      mapping[0].offset = ARCH_PFN_OFFSET << PAGE_SHIFT;
++      mapping[0].size = 0x02000000;
++      vlynq_set_local_mapping(vdev, vdev->mem_start, mapping);
++      vlynq_set_remote_mapping(vdev, 0, match->rx_mapping);
++
++      set_irq_type(vlynq_virq_to_irq(vdev, match->irq), match->irq_type);
++
++      addr = (u32)ioremap(vdev->mem_start, 0x1000);
++      if (!addr) {
++              printk(KERN_ERR "%s: failed to remap io memory\n",
++                     vdev->dev.bus_id);
++              result = -ENXIO;
++              goto fail;
++      }
++
++      for (i = 0; i < match->num_regs; i++)
++              iowrite32(match->regs[i].value,
++                        (u32 *)(addr + match->regs[i].offset));
++
++      iounmap((void *)addr);
++
++      ieee = ieee80211_alloc_hw(sizeof(struct acx_device), &acxpci_hw_ops);
++      if (!ieee) {
++              printk("acx: could not allocate ieee80211 structure %s\n",
++                     vdev->dev.bus_id);
++              goto fail_alloc_netdev;
++      }
++      ieee->flags &=   (~IEEE80211_HW_RX_INCLUDES_FCS &
++                        ~IEEE80211_HW_MONITOR_DURING_OPER) |
++                       IEEE80211_HW_WEP_INCLUDE_IV;
++      ieee->queues = 1;
++
++      adev = ieee2adev(ieee);
++
++      memset(adev, 0, sizeof(*adev));
++      /** Set up our private interface **/
++      spin_lock_init(&adev->lock);    /* initial state: unlocked */
++      /* We do not start with downed sem: we want PARANOID_LOCKING to work */
++      mutex_init(&adev->mutex);
++      /* since nobody can see new netdev yet, we can as well
++       ** just _presume_ that we're under sem (instead of actually taking it): */
++      /* acx_sem_lock(adev); */
++      adev->ieee = ieee;
++      adev->vdev = vdev;
++      adev->bus_dev = &vdev->dev;
++      adev->dev_type = DEVTYPE_PCI;
++
++/** Finished with private interface **/
++
++      vlynq_set_drvdata(vdev, ieee);
++      if (!request_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start, "acx")) {
++              printk("acx: cannot reserve VLYNQ memory region\n");
++              goto fail_request_mem_region;
++      }
++      adev->iobase = ioremap(vdev->mem_start, vdev->mem_end - vdev->mem_start);
++      if (!adev->iobase) {
++              printk("acx: ioremap() FAILED\n");
++              goto fail_ioremap;
++      }
++      adev->iobase2 = adev->iobase + match->rx_mapping[0].size;
++      adev->chip_type = CHIPTYPE_ACX111;
++      adev->chip_name = match->name;
++      adev->io = IO_ACX111;
++      adev->irq = vlynq_virq_to_irq(vdev, match->irq);
++
++      printk("acx: found %s-based wireless network card at %s, irq:%d, "
++             "phymem:0x%x, mem:0x%p\n",
++             match->name, vdev->dev.bus_id, adev->irq,
++             vdev->mem_start, adev->iobase);
++      log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
++
++      if (0 == adev->irq) {
++              printk("acx: can't use IRQ 0\n");
++              goto fail_irq;
++      }
++      SET_IEEE80211_DEV(ieee, &vdev->dev);
++
++
++      /* to find crashes due to weird driver access
++       * to unconfigured interface (ifup) */
++      adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
++
++
++      /* ok, pci setup is finished, now start initializing the card */
++
++      /* NB: read_reg() reads may return bogus data before reset_dev(),
++       * since the firmware which directly controls large parts of the I/O
++       * registers isn't initialized yet.
++       * acx100 seems to be more affected than acx111 */
++      if (OK != acxpci_s_reset_dev(adev))
++              goto fail_reset;
++
++      if (OK != acx_s_init_mac(adev))
++              goto fail_init_mac;
++
++      acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
++/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
++      if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
++              goto fail_read_eeprom_version;
++
++      acx_s_parse_configoption(adev, &co);
++      acx_s_set_defaults(adev);
++      acx_s_get_firmware_version(adev);       /* needs to be after acx_s_init_mac() */
++      acx_display_hardware_details(adev);
++
++      /* Register the card, AFTER everything else has been set up,
++       * since otherwise an ioctl could step on our feet due to
++       * firmware operations happening in parallel or uninitialized data */
++
++
++      acx_proc_register_entries(ieee);
++
++      /* Now we have our device, so make sure the kernel doesn't try
++       * to send packets even though we're not associated to a network yet */
++
++      /* after register_netdev() userspace may start working with dev
++       * (in particular, on other CPUs), we only need to up the sem */
++      /* acx_sem_unlock(adev); */
++
++      printk("acx " ACX_RELEASE ": net device %s, driver compiled "
++             "against wireless extensions %d and Linux %s\n",
++             wiphy_name(adev->ieee->wiphy), WIRELESS_EXT, UTS_RELEASE);
++
++      MAC_COPY(adev->ieee->wiphy->perm_addr, adev->dev_addr);
++
++      log(L_IRQ | L_INIT, "using IRQ %d\n", adev->irq);
++
++/** done with board specific setup **/
++
++      acx_init_task_scheduler(adev);
++      result = ieee80211_register_hw(adev->ieee);
++      if (OK != result) {
++              printk("acx: ieee80211_register_hw() FAILED: %d\n", result);
++              goto fail_register_netdev;
++      }
++#if CMD_DISCOVERY
++      great_inquisitor(adev);
++#endif
++
++      result = OK;
++      goto done;
++
++      /* error paths: undo everything in reverse order... */
++
++
++      acxpci_s_delete_dma_regions(adev);
++
++      fail_init_mac:
++      fail_read_eeprom_version:
++      fail_reset:
++
++      fail_alloc_netdev:
++      fail_irq:
++
++      iounmap(adev->iobase);
++      fail_ioremap:
++
++      release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
++      fail_request_mem_region:
++      fail_register_netdev:
++      ieee80211_free_hw(ieee);
++      fail:
++      vlynq_disable_device(vdev);
++      done:
++      FN_EXIT1(result);
++      return result;
++}
++
++static void vlynq_remove(struct vlynq_device *vdev)
++{
++      struct ieee80211_hw *hw = vlynq_get_drvdata(vdev);
++      acx_device_t *adev = ieee2adev(hw);
++      unsigned long flags;
++      FN_ENTER;
++
++      if (!hw) {
++              log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
++                  __func__);
++              goto end;
++      }
++
++
++      acx_lock(adev, flags);
++      acx_unlock(adev, flags);
++      adev->initialized = 0;
++
++      /* If device wasn't hot unplugged... */
++      if (adev_present(adev)) {
++
++              acx_sem_lock(adev);
++
++              /* disable both Tx and Rx to shut radio down properly */
++              if (adev->initialized) {
++                      acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
++                      acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
++              }
++              acx_lock(adev, flags);
++              /* disable power LED to save power :-) */
++              log(L_INIT, "switching off power LED to save power\n");
++              acxpci_l_power_led(adev, 0);
++              /* stop our eCPU */
++              acx_unlock(adev, flags);
++
++              acx_sem_unlock(adev);
++      }
++
++      /* unregister the device to not let the kernel
++       * (e.g. ioctls) access a half-deconfigured device
++       * NB: this will cause acxpci_e_close() to be called,
++       * thus we shouldn't call it under sem!
++       * Well, netdev did, but ieee80211 stack does not, so we
++       * have to do so manually...
++       */
++      acxpci_e_close(hw);
++      log(L_INIT, "removing device %s\n", wiphy_name(adev->ieee->wiphy));
++      ieee80211_unregister_hw(adev->ieee);
++
++      /* unregister_netdev ensures that no references to us left.
++       * For paranoid reasons we continue to follow the rules */
++      acx_sem_lock(adev);
++
++      if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
++              acxpci_s_down(hw);
++              CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
++      }
++
++      acx_proc_unregister_entries(adev->ieee);
++
++      /* finally, clean up PCI bus state */
++      acxpci_s_delete_dma_regions(adev);
++      if (adev->iobase)
++              iounmap(adev->iobase);
++      if (adev->iobase2)
++              iounmap(adev->iobase2);
++      release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
++
++      /* remove dev registration */
++
++      free_irq(adev->irq, adev);
++      acx_sem_unlock(adev);
++      vlynq_disable_device(vdev);
++
++      /* Free netdev (quite late,
++       * since otherwise we might get caught off-guard
++       * by a netdev timeout handler execution
++       * expecting to see a working dev...) */
++      ieee80211_free_hw(adev->ieee);
++
++      end:
++      FN_EXIT0;
++}
++
++static struct vlynq_driver vlynq_acx = {
++      .name = "acx_vlynq",
++      .id_table = acx_vlynq_id,
++      .probe = vlynq_probe,
++      .remove = __devexit_p(vlynq_remove),
++};
++#endif
+ /***********************************************************************
+ ** Data for init_module/cleanup_module
+ */
++#ifdef CONFIG_PCI
+ static const struct pci_device_id acxpci_id_tbl[] __devinitdata = {
+       {
+        .vendor = PCI_VENDOR_ID_TI,
+@@ -4071,7 +4433,7 @@
+       .resume = acxpci_e_resume
+ #endif /* CONFIG_PM */
+ };
+-
++#endif /* CONFIG_PCI */
+ /***********************************************************************
+ ** acxpci_e_init_module
+@@ -4080,7 +4442,7 @@
+ */
+ int __init acxpci_e_init_module(void)
+ {
+-      int res;
++      int res = 0;
+       FN_ENTER;
+@@ -4100,10 +4462,15 @@
+ #endif
+       log(L_INIT,
+           "acx: " ENDIANNESS_STRING
+-          "acx: PCI module " ACX_RELEASE " initialized, "
++          "acx: PCI/VLYNQ module " ACX_RELEASE " initialized, "
+           "waiting for cards to probe...\n");
++#ifdef CONFIG_PCI
+       res = pci_register_driver(&acxpci_drv_id);
++#endif
++#ifdef CONFIG_VLYNQ
++      res = vlynq_register_driver(&vlynq_acx);
++#endif
+       FN_EXIT1(res);
+       return res;
+ }
+@@ -4119,7 +4486,12 @@
+ {
+       FN_ENTER;
++#ifdef CONFIG_VLYNQ
++      vlynq_unregister_driver(&vlynq_acx);
++#endif
++#ifdef CONFIG_PCI
+       pci_unregister_driver(&acxpci_drv_id);
++#endif
+       FN_EXIT0;
+ }
diff --git a/package/acx-mac80211/patches/002-no_reset.diff b/package/acx-mac80211/patches/002-no_reset.diff
deleted file mode 100644 (file)
index 1166d07..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Index: acx-20070101/pci.c
-===================================================================
---- acx-20070101.orig/pci.c    2007-06-04 13:22:42.489395912 +0200
-+++ acx-20070101/pci.c 2007-06-04 13:22:42.557385576 +0200
-@@ -925,10 +925,13 @@
-       acx_lock(adev, flags);
--      acxpci_l_reset_mac(adev);
--
-       ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
-       if (!ecpu_ctrl) {
-+              acxpci_l_reset_mac(adev);
-+              ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
-+      }
-+
-+      if (!ecpu_ctrl) {
-               msg = "eCPU is already running. ";
-               goto end_unlock;
-       }