2011-08-14 20:48:25

by Rafał Miłecki

[permalink] [raw]
Subject: [PATCH 1/3] b43: LCN-PHY: add very basic PHY ops


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-08-14 23:24:29

by Gábor Stefanik

[permalink] [raw]
Subject: Re: [PATCH 2/3] b43: LCN-PHY: implement disabling radio

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. :-)

2011-08-14 20:48:31

by Rafał Miłecki

[permalink] [raw]
Subject: [PATCH 2/3] b43: LCN-PHY: implement disabling radio

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


2011-08-14 20:48:37

by Rafał Miłecki

[permalink] [raw]
Subject: [PATCH 3/3] b43: LCN-PHY: switch analog

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


2011-08-15 08:14:32

by Rafał Miłecki

[permalink] [raw]
Subject: Re: [PATCH 2/3] b43: LCN-PHY: implement disabling radio

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ł

2011-08-26 19:31:08

by Henry Ptasinski

[permalink] [raw]
Subject: Re: [PATCH 2/3] b43: LCN-PHY: implement disabling radio

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


2011-08-15 13:19:06

by David Woodhouse

[permalink] [raw]
Subject: Re: [PATCH 2/3] b43: LCN-PHY: implement disabling radio

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