From aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 Mon Sep 17 00:00:00 2001 From: merge Date: Thu, 22 Jan 2009 13:55:32 +0000 Subject: MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage: From: merge MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage: From: merge MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage: From: Andy Green fix-stray-endmenu.patch Signed-off-by: Andy Green --- drivers/staging/agnx/phy.c | 960 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 960 insertions(+) create mode 100644 drivers/staging/agnx/phy.c (limited to 'drivers/staging/agnx/phy.c') diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c new file mode 100644 index 00000000000..da8f10c0838 --- /dev/null +++ b/drivers/staging/agnx/phy.c @@ -0,0 +1,960 @@ +/** + * Airgo MIMO wireless driver + * + * Copyright (c) 2007 Li YanBo + + * Thanks for Jeff Williams do reverse engineer + * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin + + * 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. + */ + +#include +#include +#include +#include +#include "agnx.h" +#include "debug.h" +#include "phy.h" +#include "table.h" +#include "sta.h" +#include "xmit.h" + +u8 read_from_eeprom(struct agnx_priv *priv, u16 address) +{ + void __iomem *ctl = priv->ctl; + struct agnx_eeprom cmd; + u32 reg; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT; + cmd.address = address; + /* Verify that the Status bit is clear */ + /* Read Command and Address are written to the Serial Interface */ + iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF); + /* Wait for the Status bit to clear again */ + eeprom_delay(); + /* Read from Data */ + reg = ioread32(ctl + AGNX_CIR_SERIALITF); + + cmd = *(struct agnx_eeprom *)® + + return cmd.data; +} + +static int card_full_reset(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + AGNX_TRACE; + + reg = agnx_read32(ctl, AGNX_CIR_BLKCTL); + agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80); + reg = agnx_read32(ctl, AGNX_CIR_BLKCTL); + return 0; +} + +inline void enable_power_saving(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg &= ~0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); +} + +inline void disable_power_saving(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); +} + + +void disable_receiver(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + AGNX_TRACE; + + /* FIXME Disable the receiver */ + agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0); + /* Set gain control reset */ + agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1); + /* Reset gain control reset */ + agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0); +} + + +/* Fixme this shoule be disable RX, above is enable RX */ +void enable_receiver(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + AGNX_TRACE; + + /* Set adaptive gain control discovery mode */ + agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3); + /* Set gain control reset */ + agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1); + /* Clear gain control reset */ + agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0); +} + +static void mac_address_set(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u8 *mac_addr = priv->mac_addr; + u32 reg; + + /* FIXME */ + reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3]; + iowrite32(reg, ctl + AGNX_RXM_MACHI); + reg = (mac_addr[4] << 8) | mac_addr[5]; + iowrite32(reg, ctl + AGNX_RXM_MACLO); +} + +static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + + disable_receiver(priv); + /* FIXME */ + reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3]; + iowrite32(reg, ctl + AGNX_RXM_BSSIDHI); + reg = (bssid[4] << 8) | bssid[5]; + iowrite32(reg, ctl + AGNX_RXM_BSSIDLO); + + /* Enable the receiver */ + enable_receiver(priv); + + /* Clear the TSF */ +/* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */ +/* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */ + /* Clear the TBTT */ + agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0); + agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0); + disable_receiver(priv); +} /* receiver_bssid_set */ + +static void band_management_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + void __iomem *data = priv->data; + u32 reg; + int i; + AGNX_TRACE; + + agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ); + agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0); + memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE); + agnx_write32(ctl, AGNX_BM_BMCTL, 0x200); + + agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40); + agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2); + agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0); + agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22); + + /* FIXME Initialize the Free Pool Linked List */ + /* 1. Write the Address of the Next Node ((0x41800 + node*size)/size) + to the first word of each node. */ + for (i = 0; i < PDU_FREE_CNT; i++) { + iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE, + data + AGNX_PDU_FREE + (PDU_SIZE * i)); + /* The last node should be set to 0x0 */ + if ((i + 1) == PDU_FREE_CNT) + memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i), + 0x0, PDU_SIZE); + } + + /* Head is First Pool address (0x41800) / size (0x80) */ + agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE); + /* Tail is Last Pool Address (0x47f80) / size (0x80) */ + agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE); + /* Count is Number of Nodes in the Pool (0xd0) */ + agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT); + + /* Start all workqueue */ + agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000); + agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000); + + /* Enable the Band Management */ + reg = agnx_read32(ctl, AGNX_BM_BMCTL); + reg |= 0x1; + agnx_write32(ctl, AGNX_BM_BMCTL, reg); +} /* band_managment_init */ + + +static void system_itf_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + AGNX_TRACE; + + agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0); + agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a); + + if (priv->revid == 0) { + reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE); + reg |= 0x11; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg); + } + /* ??? What is that means? it should difference for differice type + of cards */ + agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006); + + agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000); + agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5); + reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN); +} + +static void encryption_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + AGNX_TRACE; + + agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0); + agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0); + agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0); + agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0); + agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8); +} + +static void tx_management_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + void __iomem *data = priv->data; + u32 reg; + AGNX_TRACE; + + /* Fill out the ComputationalEngineLookupTable + * starting at memory #2 offset 0x800 + */ + tx_engine_lookup_tbl_init(priv); + memset_io(data + 0x1000, 0, 0xfe0); + /* Enable Transmission Management Functions */ + agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff); + /* Write 0x3f to Transmission Template */ + agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f); + + if (priv->revid >= 2) + agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b); + else + agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b); + + reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS); + reg &= 0xff00; + reg |= 0xb; + agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg); + reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS); + reg &= 0xffff00ff; + reg |= 0xa00; + agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg); + /* Enable TIFS */ + agnx_write32(ctl, AGNX_TXM_CTL, 0x40000); + + reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS); + reg &= 0xff00ffff; + reg |= 0x510000; + agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg); + reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY); + reg &= 0xff00ffff; + agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg); + reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS); + reg &= 0x00ffffff; + reg |= 0x1c000000; + agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg); + reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY); + reg &= 0x00ffffff; + reg |= 0x01000000; + agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg); + + /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */ + agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d); + agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d); + agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d); + agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d); + + /* Max Ack timeout limit */ + agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19); + /* Max RX Data Timeout count, */ + reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME); + reg &= 0xffff0000; + reg |= 0xff; + agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg); + + /* CF poll RX Timeout count */ + reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM); + reg &= 0xffff; + reg |= 0xff0000; + agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg); + + /* Max Timeout Exceeded count, */ + reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT); + reg &= 0xff00ffff; + reg |= 0x190000; + agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg); + + /* CF ack timeout limit for 11b */ + reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B); + reg &= 0xff00; + reg |= 0x1e; + agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg); + + /* Max CF Poll Timeout Count */ + reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM); + reg &= 0xffff0000; + reg |= 0x19; + agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg); + /* CF Poll RX Timeout Count */ + reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM); + reg &= 0xffff0000; + reg |= 0x1e; + agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg); + + /* # write default to */ + /* 1. Schedule Empty Count */ + agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5); + /* 2. CFP Period Count */ + agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1); + /* 3. CFP MDV */ + agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000); + + /* Probe Delay */ + reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY); + reg &= 0xffff0000; + reg |= 0x400; + agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg); + + /* Max CCA count Slot */ + reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT); + reg &= 0xffff00ff; + reg |= 0x900; + agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg); + + /* Slot limit/1 msec Limit */ + reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT); + reg &= 0xff00ffff; + reg |= 0x140077; + agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg); + + /* # Set CW #(0-7) to default */ + agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007); + agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007); + + /* # Set Short/Long limit #(0-7) to default */ + agnx_write32(ctl, AGNX_TXM_SLBEALIM0, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM1, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM2, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM3, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM4, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM5, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM6, 0xa000a); + agnx_write32(ctl, AGNX_TXM_SLBEALIM7, 0xa000a); + + reg = agnx_read32(ctl, AGNX_TXM_CTL); + reg |= 0x1400; + agnx_write32(ctl, AGNX_TXM_CTL, reg); + /* Wait for bit 0 in Control Reg to clear */ + udelay(80); + reg = agnx_read32(ctl, AGNX_TXM_CTL); + /* Or 0x18000 to Control reg */ + reg = agnx_read32(ctl, AGNX_TXM_CTL); + reg |= 0x18000; + agnx_write32(ctl, AGNX_TXM_CTL, reg); + /* Wait for bit 0 in Control Reg to clear */ + udelay(80); + reg = agnx_read32(ctl, AGNX_TXM_CTL); + + /* Set Listen Interval Count to default */ + agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1); + /* Set DTIM period count to default */ + agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000); +} /* tx_management_init */ + +static void rx_management_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + AGNX_TRACE; + + /* Initialize the Routing Table */ + routing_table_init(priv); + + if (priv->revid >= 3) { + agnx_write32(ctl, 0x2074, 0x1f171710); + agnx_write32(ctl, 0x2078, 0x10100d0d); + agnx_write32(ctl, 0x207c, 0x11111010); + } + else + agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0); + agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00); +} + + +static void agnx_timer_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + AGNX_TRACE; + +/* /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */ +/* agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */ +/* /\* Write 0xe2 to Timer 1 Control *\/ */ +/* agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */ + + /* Write 0x249f00 (tick duration?) to Timer 1 */ + agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0); + /* Write 0xe2 to Timer 1 Control */ + agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0); + + iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL); +} + +static void power_manage_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + AGNX_TRACE; + + agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f); + agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f); + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg &= 0xf00f; + reg |= 0xa0; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); + + if (priv->revid >= 3) { + reg = agnx_read32(ctl, AGNX_PM_SOFTRST); + reg |= 0x18; + agnx_write32(ctl, AGNX_PM_SOFTRST, reg); + } +} /* power_manage_init */ + + +static void gain_ctlcnt_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + AGNX_TRACE; + + agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119); + agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118); + agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117); + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg &= ~0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); + + agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0); + + /* FIXME Write the initial Station Descriptor for the card */ + sta_init(priv, LOCAL_STAID); + sta_init(priv, BSSID_STAID); + + /* Enable staion 0 and 1 can do TX */ + /* It seemed if we set other bit to 1 the bit 0 will + be auto change to 0 */ + agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1); +// agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1); +} /* gain_ctlcnt_init */ + + +static void phy_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + void __iomem *data = priv->data; + u32 reg; + AGNX_TRACE; + + /* Load InitialGainTable */ + gain_table_init(priv); + + agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000); + + /* Clear the following offsets in Memory Range #2: */ + memset_io(data + 0x5040, 0, 0xa * 4); + memset_io(data + 0x5080, 0, 0xa * 4); + memset_io(data + 0x50c0, 0, 0xa * 4); + memset_io(data + 0x5400, 0, 0x80 * 4); + memset_io(data + 0x6000, 0, 0x280 * 4); + memset_io(data + 0x7000, 0, 0x280 * 4); + memset_io(data + 0x8000, 0, 0x280 * 4); + + /* Initialize the Following Registers According to PCI Revision ID */ + if (priv->revid == 0) { + /* fixme the part hasn't been update but below has been update + based on WGM511 */ + agnx_write32(ctl, AGNX_ACI_LEN, 0xf); + agnx_write32(ctl, AGNX_ACI_TIMER1, 0x1d); + agnx_write32(ctl, AGNX_ACI_TIMER2, 0x3); + agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11); + agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0); + agnx_write32(ctl, AGNX_GCR_THD0A, 0x64); + agnx_write32(ctl, AGNX_GCR_THD0AL, 0x4b); + agnx_write32(ctl, AGNX_GCR_THD0B, 0x4b); + agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14); + agnx_write32(ctl, AGNX_GCR_DSAT, 0x24); + agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8); + agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a); + agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3); + agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd); + agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1); + agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7); + agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28); + agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28); + reg = agnx_read32(ctl, AGNX_GCR_CWDETEC); + reg |= 0x1; + agnx_write32(ctl, AGNX_GCR_CWDETEC, reg); + agnx_write32(ctl, AGNX_GCR_0X38, 0x1e); + agnx_write32(ctl, AGNX_GCR_BOACT, 0x26); + agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3); + agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3); + agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3); + agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3); + agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3); + agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x0); + agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x0); + agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x0); + agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x0); + agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10); + agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1); + agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0x1); + agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190); + agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x78); + agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x1c); + agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0); + agnx_write32(ctl, AGNX_GCR_THCD, 0x0); + agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x1); + agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0); + agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f); + agnx_write32(ctl, AGNX_GCR_THJUMP, 0x14); + agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0); + agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x30); + agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x32); + agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19); + agnx_write32(ctl, AGNX_GCR_0X14c, 0x0); + agnx_write32(ctl, AGNX_GCR_0X150, 0x0); + agnx_write32(ctl, 0x9400, 0x0); + agnx_write32(ctl, 0x940c, 0x6ff); + agnx_write32(ctl, 0x9428, 0xa0); + agnx_write32(ctl, 0x9434, 0x0); + agnx_write32(ctl, 0x9c04, 0x15); + agnx_write32(ctl, 0x9c0c, 0x7f); + agnx_write32(ctl, 0x9c34, 0x0); + agnx_write32(ctl, 0xc000, 0x38d); + agnx_write32(ctl, 0x14018, 0x0); + agnx_write32(ctl, 0x16000, 0x1); + agnx_write32(ctl, 0x11004, 0x0); + agnx_write32(ctl, 0xec54, 0xa); + agnx_write32(ctl, 0xec1c, 0x5); + } else if (priv->revid > 0) { + agnx_write32(ctl, AGNX_ACI_LEN, 0xf); + agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21); + agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27); + agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11); + agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0); + agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14); + agnx_write32(ctl, AGNX_GCR_DSAT, 0x24); + agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8); + agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a); + agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3); + agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd); + agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1); + agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7); + agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28); + agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28); + agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0); + agnx_write32(ctl, AGNX_GCR_0X38, 0x1e); +// agnx_write32(ctl, AGNX_GCR_BOACT, 0x26); + agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3); + + agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32); + agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x32); + agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x32); + agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x32); + agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10); + agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1ad); + agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0xa10); + agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190); + agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0); + agnx_write32(ctl, AGNX_GCR_THCD, 0x0); + agnx_write32(ctl, AGNX_GCR_THCS, 0x0); + agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x4); + agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0); + agnx_write32(ctl, AGNX_GCR_THJUMP, 0x1e); + agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0); + agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x2a); + agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c); + agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19); + agnx_write32(ctl, AGNX_GCR_0X14c, 0x0); + agnx_write32(ctl, AGNX_GCR_0X150, 0x0); + agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0); + agnx_write32(ctl, AGNX_GCR_WATCHDOG, 0x37); + agnx_write32(ctl, 0x9400, 0x0); + agnx_write32(ctl, 0x940c, 0x6ff); + agnx_write32(ctl, 0x9428, 0xa0); + agnx_write32(ctl, 0x9434, 0x0); + agnx_write32(ctl, 0x9c04, 0x15); + agnx_write32(ctl, 0x9c0c, 0x7f); + agnx_write32(ctl, 0x9c34, 0x0); + agnx_write32(ctl, 0xc000, 0x38d); + agnx_write32(ctl, 0x14014, 0x1000); + agnx_write32(ctl, 0x14018, 0x0); + agnx_write32(ctl, 0x16000, 0x1); + agnx_write32(ctl, 0x11004, 0x0); + agnx_write32(ctl, 0xec54, 0xa); + agnx_write32(ctl, 0xec1c, 0x50); + } else if (priv->revid > 1) { + reg = agnx_read32(ctl, 0xec18); + reg |= 0x8; + agnx_write32(ctl, 0xec18, reg); + } + + /* Write the TX Fir Coefficient Table */ + tx_fir_table_init(priv); + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg &= ~0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); + reg = agnx_read32(ctl, AGNX_PM_PLLCTL); + reg |= 0x1; + agnx_write32(ctl, AGNX_PM_PLLCTL, reg); + +/* reg = agnx_read32(ctl, 0x1a030); */ +/* reg &= ~0x4; */ +/* agnx_write32(ctl, 0x1a030, reg); */ + + agnx_write32(ctl, AGNX_GCR_TRACNT4, 0x113); +} /* phy_init */ + +static void chip_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u32 reg; + AGNX_TRACE; + + band_management_init(priv); + + rf_chips_init(priv); + + reg = agnx_read32(ctl, AGNX_PM_PMCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_PM_PMCTL, reg); + + /* Initialize the PHY */ + phy_init(priv); + + encryption_init(priv); + + tx_management_init(priv); + + rx_management_init(priv); + + power_manage_init(priv); + + /* Initialize the Timers */ + agnx_timer_init(priv); + + /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */ + reg = 0xc390bf9 & ~IRQ_TX_BEACON; + reg &= ~IRQ_TX_DISABLE; + agnx_write32(ctl, AGNX_INT_MASK, reg); + + reg = agnx_read32(ctl, AGNX_CIR_BLKCTL); + reg |= 0x800; + agnx_write32(ctl, AGNX_CIR_BLKCTL, reg); + + /* set it when need get multicast enable? */ + agnx_write32(ctl, AGNX_BM_MTSM, 0xff); +} /* chip_init */ + + +static inline void set_promis_and_managed(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2); + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2); +} +static inline void set_learn_mode(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x8); +} +static inline void set_scan_mode(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x20); +} +static inline void set_promiscuous_mode(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/ + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10); +} +static inline void set_managed_mode(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x2); +} +static inline void set_adhoc_mode(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x0); +} + +#if 0 +static void unknow_register_write(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x0, 0x3e); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4, 0xb2); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x8, 0x140); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0xc, 0x1C0); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x10, 0x1FF); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x14, 0x1DD); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x18, 0x15F); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x1c, 0xA1); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x20, 0x3E7); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x24, 0x36B); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x28, 0x348); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x2c, 0x37D); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x30, 0x3DE); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x34, 0x36); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x38, 0x64); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x3c, 0x57); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x40, 0x23); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x44, 0x3ED); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x48, 0x3C9); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4c, 0x3CA); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x50, 0x3E7); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x54, 0x8); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x58, 0x1F); + agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x5c, 0x1a); +} +#endif + +static void card_interface_init(struct agnx_priv *priv) +{ + void __iomem *ctl = priv->ctl; + u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u32 reg; + unsigned int i; + AGNX_TRACE; + + might_sleep(); + /* Clear RX Control and Enable RX queues */ + agnx_write32(ctl, AGNX_CIR_RXCTL, 0x8); + + might_sleep(); + /* Do a full reset of the card */ + card_full_reset(priv); + might_sleep(); + + /* Check and set Card Endianness */ + reg = ioread32(priv->ctl + AGNX_CIR_ENDIAN); + /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */ + printk(KERN_INFO PFX "CIR_ENDIAN is %x\n", reg); + + + /* Config the eeprom */ + agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x7000086); + udelay(10); + reg = agnx_read32(ctl, AGNX_CIR_SERIALITF); + + + agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033); + reg = agnx_read32(ctl, 0xec50); + reg |= 0xf; + agnx_write32(ctl, 0xec50, reg); + agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0); + + + reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN); + udelay(10); + reg = agnx_read32(ctl, AGNX_CIR_SERIALITF); + + /* Dump the eeprom */ + do { + char eeprom[0x100000/0x100]; + + for (i = 0; i < 0x100000; i += 0x100) { + agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x3000000 + i); + udelay(13); + reg = agnx_read32(ctl, AGNX_CIR_SERIALITF); + udelay(70); + reg = agnx_read32(ctl, AGNX_CIR_SERIALITF); + eeprom[i/0x100] = reg & 0xFF; + udelay(10); + } + print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom, + ARRAY_SIZE(eeprom)); + } while(0); + + spi_rc_write(ctl, RF_CHIP0, 0x26); + reg = agnx_read32(ctl, AGNX_SPI_RLSW); + + /* Initialize the system interface */ + system_itf_init(priv); + + might_sleep(); + /* Chip Initialization (Polaris) */ + chip_init(priv); + might_sleep(); + + /* Calibrate the antennae */ + antenna_calibrate(priv); + + reg = agnx_read32(ctl, 0xec50); + reg &= ~0x40; + agnx_write32(ctl, 0xec50, reg); + agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0); + agnx_write32(ctl, AGNX_PM_PLLCTL, 0x1); + + reg = agnx_read32(ctl, AGNX_BM_BMCTL); + reg |= 0x8000; + agnx_write32(ctl, AGNX_BM_BMCTL, reg); + enable_receiver(priv); + reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE); + reg |= 0x200; + agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg); + enable_receiver(priv); + + might_sleep(); + /* Initialize Gain Control Counts */ + gain_ctlcnt_init(priv); + + /* Write Initial Station Power Template for this station(#0) */ + sta_power_init(priv, LOCAL_STAID); + + might_sleep(); + /* Initialize the rx,td,tm rings, for each node in the ring */ + fill_rings(priv); + + might_sleep(); + + + agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033); + agnx_write32(ctl, 0xec50, 0xc); + agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0); + + /* FIXME Initialize the transmit control register */ + agnx_write32(ctl, AGNX_TXM_CTL, 0x194c1); + + enable_receiver(priv); + + might_sleep(); + /* FIXME Set the Receive Control Mac Address to card address */ + mac_address_set(priv); + enable_receiver(priv); + might_sleep(); + + /* Set the recieve request rate */ + /* FIXME Enable the request */ + /* Check packet length */ + /* Set maximum packet length */ +/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */ +/* enable_receiver(priv); */ + + /* Set the Receiver BSSID */ + receiver_bssid_set(priv, bssid); + + /* FIXME Set to managed mode */ + set_managed_mode(priv); +// set_promiscuous_mode(priv); +/* set_scan_mode(priv); */ +/* set_learn_mode(priv); */ +// set_promis_and_managed(priv); +// set_adhoc_mode(priv); + + /* Set the recieve request rate */ + /* Check packet length */ + agnx_write32(ctl, AGNX_RXM_REQRATE, 0x08000000); + reg = agnx_read32(ctl, AGNX_RXM_REQRATE); + /* Set maximum packet length */ + reg |= 0x00195e00; + agnx_write32(ctl, AGNX_RXM_REQRATE, reg); + + /* Configure the RX and TX interrupt */ + reg = ENABLE_RX_INTERRUPT | RX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE; + agnx_write32(ctl, AGNX_CIR_RXCFG, reg); + /* FIXME */ + reg = ENABLE_TX_INTERRUPT | TX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE; + agnx_write32(ctl, AGNX_CIR_TXCFG, reg); + + /* Enable RX TX Interrupts */ + agnx_write32(ctl, AGNX_CIR_RXCTL, 0x80); + agnx_write32(ctl, AGNX_CIR_TXMCTL, 0x80); + agnx_write32(ctl, AGNX_CIR_TXDCTL, 0x80); + + /* FIXME Set the master control interrupt in block control */ + agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x800); + + /* Enable RX and TX queues */ + reg = agnx_read32(ctl, AGNX_CIR_RXCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_CIR_RXCTL, reg); + reg = agnx_read32(ctl, AGNX_CIR_TXMCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_CIR_TXMCTL, reg); + reg = agnx_read32(ctl, AGNX_CIR_TXDCTL); + reg |= 0x8; + agnx_write32(ctl, AGNX_CIR_TXDCTL, reg); + + agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5); + /* FIXME */ + /* unknow_register_write(priv); */ + /* Update local card hash entry */ + hash_write(priv, priv->mac_addr, LOCAL_STAID); + + might_sleep(); + + /* FIXME */ + agnx_set_channel(priv, 1); + might_sleep(); +} /* agnx_card_interface_init */ + + +void agnx_hw_init(struct agnx_priv *priv) +{ + AGNX_TRACE; + might_sleep(); + card_interface_init(priv); +} + +int agnx_hw_reset(struct agnx_priv *priv) +{ + return card_full_reset(priv); +} + +int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len) +{ + AGNX_TRACE; + return 0; +} + +void agnx_set_bssid(struct agnx_priv *priv, u8 *bssid) +{ + receiver_bssid_set(priv, bssid); +} -- cgit v1.2.3