Signed-off-by: Rafał Miłecki <[email protected]>
---
drivers/net/wireless/b43/phy_lcn.c | 54 ++++++++++++++++++++++++++++++++++-
drivers/net/wireless/b43/phy_lcn.h | 2 +-
2 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 9f7dbbd..03944ad 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -28,14 +28,64 @@
#include "main.h"
/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
+{
+ struct b43_phy_lcn *phy_lcn;
+
+ phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
+ if (!phy_lcn)
+ return -ENOMEM;
+ dev->phy.lcn = phy_lcn;
+
+ return 0;
+}
+
+static void b43_phy_lcn_op_free(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+ kfree(phy_lcn);
+ phy->lcn = NULL;
+}
+
+static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+ memset(phy_lcn, 0, sizeof(*phy_lcn));
+}
+
+static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ return 1;
+ return 36;
+}
+
+static enum b43_txpwr_result
+b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+ return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
* PHY ops struct.
**************************************************/
const struct b43_phy_operations b43_phyops_lcn = {
- /*
.allocate = b43_phy_lcn_op_allocate,
.free = b43_phy_lcn_op_free,
.prepare_structs = b43_phy_lcn_op_prepare_structs,
+ /*
.init = b43_phy_lcn_op_init,
.phy_read = b43_phy_lcn_op_read,
.phy_write = b43_phy_lcn_op_write,
@@ -45,8 +95,8 @@ const struct b43_phy_operations b43_phyops_lcn = {
.software_rfkill = b43_phy_lcn_op_software_rfkill,
.switch_analog = b43_phy_lcn_op_switch_analog,
.switch_channel = b43_phy_lcn_op_switch_channel,
+ */
.get_default_chan = b43_phy_lcn_op_get_default_chan,
.recalc_txpower = b43_phy_lcn_op_recalc_txpower,
.adjust_txpower = b43_phy_lcn_op_adjust_txpower,
- */
};
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
index c046c2a..9e1b291 100644
--- a/drivers/net/wireless/b43/phy_lcn.h
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -11,4 +11,4 @@ struct b43_phy_lcn {
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lcn;
-#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file
+#endif /* B43_PHY_LCN_H_ */
--
1.7.3.4
2011/8/14 Rafał Miłecki <[email protected]>:
> wl reads radio version, then disables it. That's how we found it in MMIO
> dump:
> radio_read(0x0000) -> 0x0031 <-- RADIO READ WITHOUT 0x200 SET!
> radio_read(0x0001) -> 0x0064 <-- RADIO READ WITHOUT 0x200 SET!
> radio_read(0x0002) -> 0x0020 <-- RADIO READ WITHOUT 0x200 SET!
> read32 0xfaafc120 -> 0x04000400
> phy_read(0x044d) -> 0x0000
> phy_write(0x044d) <- 0x0000
> phy_read(0x044c) -> 0x1fff
> phy_write(0x044c) <- 0x1fff
> phy_read(0x04b7) -> 0x0000
> phy_write(0x04b7) <- 0x0000
> phy_read(0x04b1) -> 0x0000
> phy_write(0x04b1) <- 0x0000
> phy_read(0x04b0) -> 0x7dff
> phy_write(0x04b0) <- 0x7dff
> phy_read(0x04fa) -> 0x0000
> phy_write(0x04fa) <- 0x0000
> phy_read(0x04f9) -> 0x007f
> phy_write(0x04f9) <- 0x007f
Doesn't brcm80211 support this PHY? (Because then, reverse-engineering
wl is pointless.)
>
> Signed-off-by: Rafał Miłecki <[email protected]>
> ---
> OFC, MMIO hacks were used to find masks & sets.
>
> Sets were taken from:
>>>> Switch Radio(OFF) start
> phy_read(0x044d) -> 0x0000
> phy_write(0x044d) <- 0x0000
> phy_read(0x044c) -> 0x0000
> phy_write(0x044c) <- 0x1f00
> phy_read(0x04b7) -> 0x0000
> phy_write(0x04b7) <- 0x0000
> phy_read(0x04b1) -> 0x0000
> phy_write(0x04b1) <- 0x0000
> phy_read(0x04b0) -> 0x0000
> phy_write(0x04b0) <- 0x0808
> phy_read(0x04fa) -> 0x0000
> phy_write(0x04fa) <- 0x0000
> phy_read(0x04f9) -> 0x0000
> phy_write(0x04f9) <- 0x0008
>>>> Switch Radio(OFF) end
>
> Masks were taken from:
> phy_read(0x044d) -> 0xffff
> phy_write(0x044d) <- 0x83ff
> phy_read(0x044c) -> 0xffff
> phy_write(0x044c) <- 0xffff
> phy_read(0x04b7) -> 0xffff
> phy_write(0x04b7) <- 0x80ff
> phy_read(0x04b1) -> 0xffff
> phy_write(0x04b1) <- 0xdfff
> phy_read(0x04b0) -> 0xffff
> phy_write(0x04b0) <- 0xffff
> phy_read(0x04fa) -> 0xffff
> phy_write(0x04fa) <- 0xfff7
> phy_read(0x04f9) -> 0xffff
> phy_write(0x04f9) <- 0xffff
> ---
> drivers/net/wireless/b43/phy_lcn.c | 23 +++++++++++++++++++++++
> drivers/net/wireless/b43/phy_lcn.h | 9 +++++++++
> 2 files changed, 32 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
> index 03944ad..69a93b5 100644
> --- a/drivers/net/wireless/b43/phy_lcn.c
> +++ b/drivers/net/wireless/b43/phy_lcn.c
> @@ -60,6 +60,27 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
> memset(phy_lcn, 0, sizeof(*phy_lcn));
> }
>
> +static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
> + bool blocked)
> +{
> + if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
> + b43err(dev->wl, "MAC not suspended\n");
> +
> + if (blocked) {
> + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
> + b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
> +
> + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
> + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
> + b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
> +
> + b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
> + b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
> + } else {
> + /* TODO */
> + }
> +}
> +
> static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
> {
> if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
> @@ -92,7 +113,9 @@ const struct b43_phy_operations b43_phyops_lcn = {
> .phy_maskset = b43_phy_lcn_op_maskset,
> .radio_read = b43_phy_lcn_op_radio_read,
> .radio_write = b43_phy_lcn_op_radio_write,
> + */
> .software_rfkill = b43_phy_lcn_op_software_rfkill,
> + /*
> .switch_analog = b43_phy_lcn_op_switch_analog,
> .switch_channel = b43_phy_lcn_op_switch_channel,
> */
> diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
> index 9e1b291..89f13b2 100644
> --- a/drivers/net/wireless/b43/phy_lcn.h
> +++ b/drivers/net/wireless/b43/phy_lcn.h
> @@ -4,6 +4,15 @@
> #include "phy_common.h"
>
>
> +#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
> +#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
> +#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
> +#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1)
> +#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7)
> +#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9)
> +#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA)
> +
> +
> struct b43_phy_lcn {
> };
>
> --
> 1.7.3.4
>
>
> _______________________________________________
> b43-dev mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/b43-dev
>
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
wl reads radio version, then disables it. That's how we found it in MMIO
dump:
radio_read(0x0000) -> 0x0031 <-- RADIO READ WITHOUT 0x200 SET!
radio_read(0x0001) -> 0x0064 <-- RADIO READ WITHOUT 0x200 SET!
radio_read(0x0002) -> 0x0020 <-- RADIO READ WITHOUT 0x200 SET!
read32 0xfaafc120 -> 0x04000400
phy_read(0x044d) -> 0x0000
phy_write(0x044d) <- 0x0000
phy_read(0x044c) -> 0x1fff
phy_write(0x044c) <- 0x1fff
phy_read(0x04b7) -> 0x0000
phy_write(0x04b7) <- 0x0000
phy_read(0x04b1) -> 0x0000
phy_write(0x04b1) <- 0x0000
phy_read(0x04b0) -> 0x7dff
phy_write(0x04b0) <- 0x7dff
phy_read(0x04fa) -> 0x0000
phy_write(0x04fa) <- 0x0000
phy_read(0x04f9) -> 0x007f
phy_write(0x04f9) <- 0x007f
Signed-off-by: Rafał Miłecki <[email protected]>
---
OFC, MMIO hacks were used to find masks & sets.
Sets were taken from:
>>> Switch Radio(OFF) start
phy_read(0x044d) -> 0x0000
phy_write(0x044d) <- 0x0000
phy_read(0x044c) -> 0x0000
phy_write(0x044c) <- 0x1f00
phy_read(0x04b7) -> 0x0000
phy_write(0x04b7) <- 0x0000
phy_read(0x04b1) -> 0x0000
phy_write(0x04b1) <- 0x0000
phy_read(0x04b0) -> 0x0000
phy_write(0x04b0) <- 0x0808
phy_read(0x04fa) -> 0x0000
phy_write(0x04fa) <- 0x0000
phy_read(0x04f9) -> 0x0000
phy_write(0x04f9) <- 0x0008
>>> Switch Radio(OFF) end
Masks were taken from:
phy_read(0x044d) -> 0xffff
phy_write(0x044d) <- 0x83ff
phy_read(0x044c) -> 0xffff
phy_write(0x044c) <- 0xffff
phy_read(0x04b7) -> 0xffff
phy_write(0x04b7) <- 0x80ff
phy_read(0x04b1) -> 0xffff
phy_write(0x04b1) <- 0xdfff
phy_read(0x04b0) -> 0xffff
phy_write(0x04b0) <- 0xffff
phy_read(0x04fa) -> 0xffff
phy_write(0x04fa) <- 0xfff7
phy_read(0x04f9) -> 0xffff
phy_write(0x04f9) <- 0xffff
---
drivers/net/wireless/b43/phy_lcn.c | 23 +++++++++++++++++++++++
drivers/net/wireless/b43/phy_lcn.h | 9 +++++++++
2 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 03944ad..69a93b5 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -60,6 +60,27 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
memset(phy_lcn, 0, sizeof(*phy_lcn));
}
+static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
+ bool blocked)
+{
+ if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+ b43err(dev->wl, "MAC not suspended\n");
+
+ if (blocked) {
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
+
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
+
+ b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
+ b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
+ } else {
+ /* TODO */
+ }
+}
+
static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -92,7 +113,9 @@ const struct b43_phy_operations b43_phyops_lcn = {
.phy_maskset = b43_phy_lcn_op_maskset,
.radio_read = b43_phy_lcn_op_radio_read,
.radio_write = b43_phy_lcn_op_radio_write,
+ */
.software_rfkill = b43_phy_lcn_op_software_rfkill,
+ /*
.switch_analog = b43_phy_lcn_op_switch_analog,
.switch_channel = b43_phy_lcn_op_switch_channel,
*/
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
index 9e1b291..89f13b2 100644
--- a/drivers/net/wireless/b43/phy_lcn.h
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -4,6 +4,15 @@
#include "phy_common.h"
+#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
+#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
+#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
+#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1)
+#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7)
+#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9)
+#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA)
+
+
struct b43_phy_lcn {
};
--
1.7.3.4
Analog is switched on right after reading PHY version:
read16 0xfaafc3e0 -> 0xa801
phy_read(0x043b) -> 0x0000
phy_write(0x043b) <- 0x0000
Switched off after after killing radio:
>>> Switch Radio(OFF) end
phy_read(0x043c) -> 0x0000
phy_write(0x043c) <- 0x0007
phy_read(0x043b) -> 0x0000
phy_write(0x043b) <- 0x0007
Signed-off-by: Rafał Miłecki <[email protected]>
---
Again, MMIO hacks to find masks & sets.
Sets came from:
>>> analog(OFF) start
phy_read(0x043c) -> 0x0000
phy_write(0x043c) <- 0x0007
phy_read(0x043b) -> 0x0000
phy_write(0x043b) <- 0x0007
>>> analog(OFF) end
There is no masking for OFF:
>>> analog(OFF) start
phy_read(0x043c) -> 0xffff
phy_write(0x043c) <- 0xffff
phy_read(0x043b) -> 0xffff
phy_write(0x043b) <- 0xffff
>>> analog(OFF) end
Mask for ON came from
phy_read(0x043b) -> 0xffff
phy_write(0x043b) <- 0xfff8
(there was not masking for ON).
---
drivers/net/wireless/b43/phy_lcn.c | 12 +++++++++++-
drivers/net/wireless/b43/phy_lcn.h | 2 ++
2 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 69a93b5..0fd72c1 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -81,6 +81,16 @@ static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
}
}
+static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+ if (on) {
+ b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
+ } else {
+ b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
+ b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
+ }
+}
+
static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -115,8 +125,8 @@ const struct b43_phy_operations b43_phyops_lcn = {
.radio_write = b43_phy_lcn_op_radio_write,
*/
.software_rfkill = b43_phy_lcn_op_software_rfkill,
- /*
.switch_analog = b43_phy_lcn_op_switch_analog,
+ /*
.switch_channel = b43_phy_lcn_op_switch_channel,
*/
.get_default_chan = b43_phy_lcn_op_get_default_chan,
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
index 89f13b2..371e07d 100644
--- a/drivers/net/wireless/b43/phy_lcn.h
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -4,6 +4,8 @@
#include "phy_common.h"
+#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B)
+#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C)
#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
--
1.7.3.4
W dniu 15 sierpnia 2011 01:24 użytkownik Gábor Stefanik
<[email protected]> napisał:
> 2011/8/14 Rafał Miłecki <[email protected]>:
>> wl reads radio version, then disables it. That's how we found it in MMIO
>> dump:
>> radio_read(0x0000) -> 0x0031 <-- RADIO READ WITHOUT 0x200 SET!
>> radio_read(0x0001) -> 0x0064 <-- RADIO READ WITHOUT 0x200 SET!
>> radio_read(0x0002) -> 0x0020 <-- RADIO READ WITHOUT 0x200 SET!
>> read32 0xfaafc120 -> 0x04000400
>> phy_read(0x044d) -> 0x0000
>> phy_write(0x044d) <- 0x0000
>> phy_read(0x044c) -> 0x1fff
>> phy_write(0x044c) <- 0x1fff
>> phy_read(0x04b7) -> 0x0000
>> phy_write(0x04b7) <- 0x0000
>> phy_read(0x04b1) -> 0x0000
>> phy_write(0x04b1) <- 0x0000
>> phy_read(0x04b0) -> 0x7dff
>> phy_write(0x04b0) <- 0x7dff
>> phy_read(0x04fa) -> 0x0000
>> phy_write(0x04fa) <- 0x0000
>> phy_read(0x04f9) -> 0x007f
>> phy_write(0x04f9) <- 0x007f
>
> Doesn't brcm80211 support this PHY?
They do, but I still have some stuff RE-ed anyway. That stuff comes
from my tests of MMIO hacks I've done before using them on BCM4331.
> (Because then, reverse-engineering wl is pointless.)
(Unless that's fun for you ;) )
--
Rafał
On Mon, Aug 15, 2011 at 06:18:57AM -0700, David Woodhouse wrote:
> On Mon, 2011-08-15 at 01:24 +0200, G?bor Stefanik wrote:
> > Doesn't brcm80211 support this PHY? (Because then, reverse-engineering
> > wl is pointless.)
>
> I'd be great to "clean up" the interface between brcm80211 and its phy
> code, so that the phy code can be moved out of drivers/staging. And once
> we've done that, we can make b43 use it too.
>
> That way we not only get LCN PHY code, but also hopefully support for
> *other* PHYs as and when they are produced.
If you have any specific cleanup suggestions for the phy code, please send them
along.
- Henry
On Mon, 2011-08-15 at 01:24 +0200, Gábor Stefanik wrote:
> Doesn't brcm80211 support this PHY? (Because then, reverse-engineering
> wl is pointless.)
I'd be great to "clean up" the interface between brcm80211 and its phy
code, so that the phy code can be moved out of drivers/staging. And once
we've done that, we can make b43 use it too.
That way we not only get LCN PHY code, but also hopefully support for
*other* PHYs as and when they are produced.
--
dwmw2