X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fb43%2Fmain.c;h=85d6a1f03a08923c227a3516c4b4d080f7b0e519;hb=e61b52d1309df08b86a35e54a61f0cc932b28291;hp=295c7e3b2c404833d6c16103c4cbfbd38d76d6b5;hpb=40c6226967c8b27eb21f6894abff1e145861c6e1;p=mv-sheeva.git diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 295c7e3b2c4..85d6a1f03a0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1156,17 +1156,37 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) } #ifdef CONFIG_B43_BCMA -static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) +static void b43_bcma_phy_reset(struct b43_wldev *dev) { - u32 flags = 0; + u32 flags; - if (gmode) - flags = B43_BCMA_IOCTL_GMODE; - flags |= B43_BCMA_IOCTL_PHY_CLKEN; + /* Put PHY into reset */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags |= B43_BCMA_IOCTL_PHY_RESET; flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */ - b43_device_enable(dev, flags); + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(2); + + /* Take PHY out of reset */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags &= ~B43_BCMA_IOCTL_PHY_RESET; + flags |= BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(1); - /* TODO: reset PHY */ + /* Do not force clock anymore */ + flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + flags &= ~BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); + udelay(1); +} + +static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) +{ + b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN); + bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST); + b43_bcma_phy_reset(dev); + bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true); } #endif @@ -5165,6 +5185,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) struct ssb_sprom *sprom = dev->bus_sprom; struct ieee80211_hw *hw; struct b43_wl *wl; + char chip_name[6]; hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); if (!hw) { @@ -5203,8 +5224,10 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) INIT_WORK(&wl->tx_work, b43_tx_work); skb_queue_head_init(&wl->tx_queue); - b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", - dev->chip_id, dev->core_rev); + snprintf(chip_name, ARRAY_SIZE(chip_name), + (dev->chip_id > 0x9999) ? "%d" : "%04X", dev->chip_id); + b43info(wl, "Broadcom %s WLAN found (core revision %u)\n", chip_name, + dev->core_rev); return wl; } @@ -5212,19 +5235,59 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) static int b43_bcma_probe(struct bcma_device *core) { struct b43_bus_dev *dev; + struct b43_wl *wl; + int err; dev = b43_bus_dev_bcma_init(core); if (!dev) return -ENODEV; - b43err(NULL, "BCMA is not supported yet!"); - kfree(dev); - return -EOPNOTSUPP; + wl = b43_wireless_init(dev); + if (IS_ERR(wl)) { + err = PTR_ERR(wl); + goto bcma_out; + } + + err = b43_one_core_attach(dev, wl); + if (err) + goto bcma_err_wireless_exit; + + err = ieee80211_register_hw(wl->hw); + if (err) + goto bcma_err_one_core_detach; + b43_leds_register(wl->current_dev); + +bcma_out: + return err; + +bcma_err_one_core_detach: + b43_one_core_detach(dev); +bcma_err_wireless_exit: + ieee80211_free_hw(wl->hw); + return err; } static void b43_bcma_remove(struct bcma_device *core) { - /* TODO */ + struct b43_wldev *wldev = bcma_get_drvdata(core); + struct b43_wl *wl = wldev->wl; + + /* We must cancel any work here before unregistering from ieee80211, + * as the ieee80211 unreg will destroy the workqueue. */ + cancel_work_sync(&wldev->restart_work); + + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; + b43_leds_stop(wldev); + ieee80211_unregister_hw(wl->hw); + + b43_one_core_detach(wldev->dev); + + b43_leds_unregister(wl); + + ieee80211_free_hw(wl->hw); } static struct bcma_driver b43_bcma_driver = { @@ -5287,6 +5350,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) { struct b43_wl *wl = ssb_get_devtypedata(sdev); struct b43_wldev *wldev = ssb_get_drvdata(sdev); + struct b43_bus_dev *dev = wldev->dev; /* We must cancel any work here before unregistering from ieee80211, * as the ieee80211 unreg will destroy the workqueue. */ @@ -5302,14 +5366,14 @@ static void b43_ssb_remove(struct ssb_device *sdev) ieee80211_unregister_hw(wl->hw); } - b43_one_core_detach(wldev->dev); + b43_one_core_detach(dev); if (list_empty(&wl->devlist)) { b43_leds_unregister(wl); /* Last core on the chip unregistered. * We can destroy common struct b43_wl. */ - b43_wireless_exit(wldev->dev, wl); + b43_wireless_exit(dev, wl); } }