Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25c15566 authored by Rafał Miłecki's avatar Rafał Miłecki Committed by John W. Linville
Browse files

b43: flush some writes on Broadcom MIPS SoCs



Access to PHY and radio registers is indirect on Broadcom hardware and
it seems that addressing on some MIPS SoCs may require flushing. So far
this problem was noticed on 0x4716 SoC only (marketing names: BCM4717,
BCM4718).

Signed-off-by: default avatarRafał Miłecki <zajec5@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d342b95d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1012,6 +1012,16 @@ static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
	dev->dev->write16(dev->dev, offset, value);
}

/* To optimize this check for flush_writes on BCM47XX_BCMA only. */
static inline void b43_write16f(struct b43_wldev *dev, u16 offset, u16 value)
{
	b43_write16(dev, offset, value);
#if defined(CONFIG_BCM47XX_BCMA)
	if (dev->dev->flush_writes)
		b43_read16(dev, offset);
#endif
}

static inline void b43_maskset16(struct b43_wldev *dev, u16 offset, u16 mask,
				 u16 set)
{
+10 −0
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@

*/

#ifdef CONFIG_BCM47XX_BCMA
#include <asm/mach-bcm47xx/bcm47xx.h>
#endif

#include "b43.h"
#include "bus.h"

@@ -102,6 +106,12 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
	dev->write32 = b43_bus_bcma_write32;
	dev->block_read = b43_bus_bcma_block_read;
	dev->block_write = b43_bus_bcma_block_write;
#ifdef CONFIG_BCM47XX_BCMA
	if (b43_bus_host_is_pci(dev) &&
	    bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
	    bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716)
		dev->flush_writes = true;
#endif

	dev->dev = &core->dev;
	dev->dma_dev = core->dma_dev;
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct b43_bus_dev {
			   size_t count, u16 offset, u8 reg_width);
	void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
			    size_t count, u16 offset, u8 reg_width);
	bool flush_writes;

	struct device *dev;
	struct device *dma_dev;
+8 −9
Original line number Diff line number Diff line
@@ -4466,10 +4466,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
	if (core_rev == 40 || core_rev == 42) {
		radio_manuf = 0x17F;

		b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0);
		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 0);
		radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);

		b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 1);
		radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);

		radio_ver = 0; /* Is there version somewhere? */
@@ -4477,7 +4477,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
		u16 radio24[3];

		for (tmp = 0; tmp < 3; tmp++) {
			b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
			b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, tmp);
			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
		}

@@ -4494,13 +4494,12 @@ static int b43_phy_versioning(struct b43_wldev *dev)
			else
				tmp = 0x5205017F;
		} else {
			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
			b43_write16f(dev, B43_MMIO_RADIO_CONTROL,
				     B43_RADIOCTL_ID);
			tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
			b43_write16(dev, B43_MMIO_RADIO_CONTROL,
			b43_write16f(dev, B43_MMIO_RADIO_CONTROL,
				     B43_RADIOCTL_ID);
			tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
				<< 16;
			tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
		}
		radio_manuf = (tmp & 0x00000FFF);
		radio_id = (tmp & 0x0FFFF000) >> 12;
+2 −2
Original line number Diff line number Diff line
@@ -444,14 +444,14 @@ static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
{
	reg = adjust_phyreg(dev, reg);
	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
	return b43_read16(dev, B43_MMIO_PHY_DATA);
}

static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
{
	reg = adjust_phyreg(dev, reg);
	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
	b43_write16(dev, B43_MMIO_PHY_DATA, value);
}

Loading