pci.c (9095bf25ea08135a5b74875dd0e3eeaddc4218a0) pci.c (b8b6069cf2087545fe53ec920e8353133e9a70bf)
1/*
2 * Sonics Silicon Backplane PCI-Hostbus related functions.
3 *
4 * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
9 *
10 * Derived from the Broadcom 4400 device driver.
11 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
12 * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
13 * Copyright (C) 2006 Broadcom Corporation.
14 *
15 * Licensed under the GNU/GPL. See COPYING for details.
16 */
17
1/*
2 * Sonics Silicon Backplane PCI-Hostbus related functions.
3 *
4 * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
9 *
10 * Derived from the Broadcom 4400 device driver.
11 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
12 * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
13 * Copyright (C) 2006 Broadcom Corporation.
14 *
15 * Licensed under the GNU/GPL. See COPYING for details.
16 */
17
18#include "ssb_private.h"
19
18#include <linux/ssb/ssb.h>
19#include <linux/ssb/ssb_regs.h>
20#include <linux/slab.h>
21#include <linux/pci.h>
22#include <linux/delay.h>
23
20#include <linux/ssb/ssb.h>
21#include <linux/ssb/ssb_regs.h>
22#include <linux/slab.h>
23#include <linux/pci.h>
24#include <linux/delay.h>
25
24#include "ssb_private.h"
25
26
26
27/* Define the following to 1 to enable a printk on each coreswitch. */
28#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
29
30
31/* Lowlevel coreswitching */
32int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
33{
34 int err;

--- 16 unchanged lines hidden (view full) ---

51 break;
52
53 if (attempts++ > SSB_BAR0_MAX_RETRIES)
54 goto error;
55 udelay(10);
56 }
57 return 0;
58error:
27/* Define the following to 1 to enable a printk on each coreswitch. */
28#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
29
30
31/* Lowlevel coreswitching */
32int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
33{
34 int err;

--- 16 unchanged lines hidden (view full) ---

51 break;
52
53 if (attempts++ > SSB_BAR0_MAX_RETRIES)
54 goto error;
55 udelay(10);
56 }
57 return 0;
58error:
59 ssb_err("Failed to switch to core %u\n", coreidx);
59 pr_err("Failed to switch to core %u\n", coreidx);
60 return -ENODEV;
61}
62
63int ssb_pci_switch_core(struct ssb_bus *bus,
64 struct ssb_device *dev)
65{
66 int err;
67 unsigned long flags;
68
69#if SSB_VERBOSE_PCICORESWITCH_DEBUG
60 return -ENODEV;
61}
62
63int ssb_pci_switch_core(struct ssb_bus *bus,
64 struct ssb_device *dev)
65{
66 int err;
67 unsigned long flags;
68
69#if SSB_VERBOSE_PCICORESWITCH_DEBUG
70 ssb_info("Switching to %s core, index %d\n",
71 ssb_core_name(dev->id.coreid),
72 dev->core_index);
70 pr_info("Switching to %s core, index %d\n",
71 ssb_core_name(dev->id.coreid), dev->core_index);
73#endif
74
75 spin_lock_irqsave(&bus->bar_lock, flags);
76 err = ssb_pci_switch_coreidx(bus, dev->core_index);
77 if (!err)
78 bus->mapped_device = dev;
79 spin_unlock_irqrestore(&bus->bar_lock, flags);
80

--- 75 unchanged lines hidden (view full) ---

156 if (err)
157 goto err_pci;
158 }
159
160out:
161 return err;
162
163err_pci:
72#endif
73
74 spin_lock_irqsave(&bus->bar_lock, flags);
75 err = ssb_pci_switch_coreidx(bus, dev->core_index);
76 if (!err)
77 bus->mapped_device = dev;
78 spin_unlock_irqrestore(&bus->bar_lock, flags);
79

--- 75 unchanged lines hidden (view full) ---

155 if (err)
156 goto err_pci;
157 }
158
159out:
160 return err;
161
162err_pci:
164 printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
163 pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
165 err = -EBUSY;
166 goto out;
167}
168
169/* Get the word-offset for a SSB_SPROM_XXX define. */
170#define SPOFF(offset) ((offset) / sizeof(u16))
171/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
172#define SPEX16(_outvar, _offset, _mask, _shift) \

--- 108 unchanged lines hidden (view full) ---

281
282static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
283{
284 struct pci_dev *pdev = bus->host_pci;
285 int i, err;
286 u32 spromctl;
287 u16 size = bus->sprom_size;
288
164 err = -EBUSY;
165 goto out;
166}
167
168/* Get the word-offset for a SSB_SPROM_XXX define. */
169#define SPOFF(offset) ((offset) / sizeof(u16))
170/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
171#define SPEX16(_outvar, _offset, _mask, _shift) \

--- 108 unchanged lines hidden (view full) ---

280
281static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
282{
283 struct pci_dev *pdev = bus->host_pci;
284 int i, err;
285 u32 spromctl;
286 u16 size = bus->sprom_size;
287
289 ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
288 pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
290 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
291 if (err)
292 goto err_ctlreg;
293 spromctl |= SSB_SPROMCTL_WE;
294 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
295 if (err)
296 goto err_ctlreg;
289 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
290 if (err)
291 goto err_ctlreg;
292 spromctl |= SSB_SPROMCTL_WE;
293 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
294 if (err)
295 goto err_ctlreg;
297 ssb_notice("[ 0%%");
296 pr_notice("[ 0%%");
298 msleep(500);
299 for (i = 0; i < size; i++) {
300 if (i == size / 4)
297 msleep(500);
298 for (i = 0; i < size; i++) {
299 if (i == size / 4)
301 ssb_cont("25%%");
300 pr_cont("25%%");
302 else if (i == size / 2)
301 else if (i == size / 2)
303 ssb_cont("50%%");
302 pr_cont("50%%");
304 else if (i == (size * 3) / 4)
303 else if (i == (size * 3) / 4)
305 ssb_cont("75%%");
304 pr_cont("75%%");
306 else if (i % 2)
305 else if (i % 2)
307 ssb_cont(".");
306 pr_cont(".");
308 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
309 mmiowb();
310 msleep(20);
311 }
312 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
313 if (err)
314 goto err_ctlreg;
315 spromctl &= ~SSB_SPROMCTL_WE;
316 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
317 if (err)
318 goto err_ctlreg;
319 msleep(500);
307 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
308 mmiowb();
309 msleep(20);
310 }
311 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
312 if (err)
313 goto err_ctlreg;
314 spromctl &= ~SSB_SPROMCTL_WE;
315 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
316 if (err)
317 goto err_ctlreg;
318 msleep(500);
320 ssb_cont("100%% ]\n");
321 ssb_notice("SPROM written\n");
319 pr_cont("100%% ]\n");
320 pr_notice("SPROM written\n");
322
323 return 0;
324err_ctlreg:
321
322 return 0;
323err_ctlreg:
325 ssb_err("Could not access SPROM control register.\n");
324 pr_err("Could not access SPROM control register.\n");
326 return err;
327}
328
329static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
330 u16 mask, u16 shift)
331{
332 u16 v;
333 u8 gain;

--- 477 unchanged lines hidden (view full) ---

811}
812
813static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
814 const u16 *in, u16 size)
815{
816 memset(out, 0, sizeof(*out));
817
818 out->revision = in[size - 1] & 0x00FF;
325 return err;
326}
327
328static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
329 u16 mask, u16 shift)
330{
331 u16 v;
332 u8 gain;

--- 477 unchanged lines hidden (view full) ---

810}
811
812static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
813 const u16 *in, u16 size)
814{
815 memset(out, 0, sizeof(*out));
816
817 out->revision = in[size - 1] & 0x00FF;
819 ssb_dbg("SPROM revision %d detected\n", out->revision);
818 pr_debug("SPROM revision %d detected\n", out->revision);
820 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
821 memset(out->et1mac, 0xFF, 6);
822
823 if ((bus->chip_id & 0xFF00) == 0x4400) {
824 /* Workaround: The BCM44XX chip has a stupid revision
825 * number stored in the SPROM.
826 * Always extract r1. */
827 out->revision = 1;
819 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
820 memset(out->et1mac, 0xFF, 6);
821
822 if ((bus->chip_id & 0xFF00) == 0x4400) {
823 /* Workaround: The BCM44XX chip has a stupid revision
824 * number stored in the SPROM.
825 * Always extract r1. */
826 out->revision = 1;
828 ssb_dbg("SPROM treated as revision %d\n", out->revision);
827 pr_debug("SPROM treated as revision %d\n", out->revision);
829 }
830
831 switch (out->revision) {
832 case 1:
833 case 2:
834 case 3:
835 sprom_extract_r123(out, in);
836 break;
837 case 4:
838 case 5:
839 sprom_extract_r45(out, in);
840 break;
841 case 8:
842 sprom_extract_r8(out, in);
843 break;
844 default:
828 }
829
830 switch (out->revision) {
831 case 1:
832 case 2:
833 case 3:
834 sprom_extract_r123(out, in);
835 break;
836 case 4:
837 case 5:
838 sprom_extract_r45(out, in);
839 break;
840 case 8:
841 sprom_extract_r8(out, in);
842 break;
843 default:
845 ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
846 out->revision);
844 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
845 out->revision);
847 out->revision = 1;
848 sprom_extract_r123(out, in);
849 }
850
851 if (out->boardflags_lo == 0xFFFF)
852 out->boardflags_lo = 0; /* per specs */
853 if (out->boardflags_hi == 0xFFFF)
854 out->boardflags_hi = 0; /* per specs */
855
856 return 0;
857}
858
859static int ssb_pci_sprom_get(struct ssb_bus *bus,
860 struct ssb_sprom *sprom)
861{
862 int err;
863 u16 *buf;
864
865 if (!ssb_is_sprom_available(bus)) {
846 out->revision = 1;
847 sprom_extract_r123(out, in);
848 }
849
850 if (out->boardflags_lo == 0xFFFF)
851 out->boardflags_lo = 0; /* per specs */
852 if (out->boardflags_hi == 0xFFFF)
853 out->boardflags_hi = 0; /* per specs */
854
855 return 0;
856}
857
858static int ssb_pci_sprom_get(struct ssb_bus *bus,
859 struct ssb_sprom *sprom)
860{
861 int err;
862 u16 *buf;
863
864 if (!ssb_is_sprom_available(bus)) {
866 ssb_err("No SPROM available!\n");
865 pr_err("No SPROM available!\n");
867 return -ENODEV;
868 }
869 if (bus->chipco.dev) { /* can be unavailable! */
870 /*
871 * get SPROM offset: SSB_SPROM_BASE1 except for
872 * chipcommon rev >= 31 or chip ID is 0x4312 and
873 * chipcommon status & 3 == 2
874 */
875 if (bus->chipco.dev->id.revision >= 31)
876 bus->sprom_offset = SSB_SPROM_BASE31;
877 else if (bus->chip_id == 0x4312 &&
878 (bus->chipco.status & 0x03) == 2)
879 bus->sprom_offset = SSB_SPROM_BASE31;
880 else
881 bus->sprom_offset = SSB_SPROM_BASE1;
882 } else {
883 bus->sprom_offset = SSB_SPROM_BASE1;
884 }
866 return -ENODEV;
867 }
868 if (bus->chipco.dev) { /* can be unavailable! */
869 /*
870 * get SPROM offset: SSB_SPROM_BASE1 except for
871 * chipcommon rev >= 31 or chip ID is 0x4312 and
872 * chipcommon status & 3 == 2
873 */
874 if (bus->chipco.dev->id.revision >= 31)
875 bus->sprom_offset = SSB_SPROM_BASE31;
876 else if (bus->chip_id == 0x4312 &&
877 (bus->chipco.status & 0x03) == 2)
878 bus->sprom_offset = SSB_SPROM_BASE31;
879 else
880 bus->sprom_offset = SSB_SPROM_BASE1;
881 } else {
882 bus->sprom_offset = SSB_SPROM_BASE1;
883 }
885 ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
884 pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
886
887 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
888 if (!buf)
889 return -ENOMEM;
890 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
891 sprom_do_read(bus, buf);
892 err = sprom_check_crc(buf, bus->sprom_size);
893 if (err) {

--- 8 unchanged lines hidden (view full) ---

902 err = sprom_check_crc(buf, bus->sprom_size);
903 if (err) {
904 /* All CRC attempts failed.
905 * Maybe there is no SPROM on the device?
906 * Now we ask the arch code if there is some sprom
907 * available for this device in some other storage */
908 err = ssb_fill_sprom_with_fallback(bus, sprom);
909 if (err) {
885
886 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
887 if (!buf)
888 return -ENOMEM;
889 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
890 sprom_do_read(bus, buf);
891 err = sprom_check_crc(buf, bus->sprom_size);
892 if (err) {

--- 8 unchanged lines hidden (view full) ---

901 err = sprom_check_crc(buf, bus->sprom_size);
902 if (err) {
903 /* All CRC attempts failed.
904 * Maybe there is no SPROM on the device?
905 * Now we ask the arch code if there is some sprom
906 * available for this device in some other storage */
907 err = ssb_fill_sprom_with_fallback(bus, sprom);
908 if (err) {
910 ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
911 err);
909 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
910 err);
912 goto out_free;
913 } else {
911 goto out_free;
912 } else {
914 ssb_dbg("Using SPROM revision %d provided by platform\n",
915 sprom->revision);
913 pr_debug("Using SPROM revision %d provided by platform\n",
914 sprom->revision);
916 err = 0;
917 goto out_free;
918 }
915 err = 0;
916 goto out_free;
917 }
919 ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
918 pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
920 }
921 }
922 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
923
924out_free:
925 kfree(buf);
926 return err;
927}

--- 20 unchanged lines hidden (view full) ---

948}
949
950#ifdef CONFIG_SSB_DEBUG
951static int ssb_pci_assert_buspower(struct ssb_bus *bus)
952{
953 if (likely(bus->powered_up))
954 return 0;
955
919 }
920 }
921 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
922
923out_free:
924 kfree(buf);
925 return err;
926}

--- 20 unchanged lines hidden (view full) ---

947}
948
949#ifdef CONFIG_SSB_DEBUG
950static int ssb_pci_assert_buspower(struct ssb_bus *bus)
951{
952 if (likely(bus->powered_up))
953 return 0;
954
956 printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
957 "while accessing PCI MMIO space\n");
955 pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
958 if (bus->power_warn_count <= 10) {
959 bus->power_warn_count++;
960 dump_stack();
961 }
962
963 return -ENODEV;
964}
965#else /* DEBUG */

--- 225 unchanged lines hidden ---
956 if (bus->power_warn_count <= 10) {
957 bus->power_warn_count++;
958 dump_stack();
959 }
960
961 return -ENODEV;
962}
963#else /* DEBUG */

--- 225 unchanged lines hidden ---