diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/bcma | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/bcma')
-rw-r--r-- | drivers/bcma/Kconfig | 42 | ||||
-rw-r--r-- | drivers/bcma/Makefile | 6 | ||||
-rw-r--r-- | drivers/bcma/bcma_private.h | 69 | ||||
-rw-r--r-- | drivers/bcma/core.c | 18 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon.c | 265 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon_nflash.c | 44 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon_pmu.c | 494 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon_sflash.c | 165 | ||||
-rw-r--r-- | drivers/bcma/driver_gmac_cmn.c | 14 | ||||
-rw-r--r-- | drivers/bcma/driver_gpio.c | 98 | ||||
-rw-r--r-- | drivers/bcma/driver_mips.c | 279 | ||||
-rw-r--r-- | drivers/bcma/driver_pci.c | 236 | ||||
-rw-r--r-- | drivers/bcma/driver_pci_host.c | 588 | ||||
-rw-r--r-- | drivers/bcma/host_pci.c | 86 | ||||
-rw-r--r-- | drivers/bcma/host_soc.c | 183 | ||||
-rw-r--r-- | drivers/bcma/main.c | 241 | ||||
-rw-r--r-- | drivers/bcma/scan.c | 467 | ||||
-rw-r--r-- | drivers/bcma/scan.h | 2 | ||||
-rw-r--r-- | drivers/bcma/sprom.c | 460 |
19 files changed, 357 insertions, 3400 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 8b4221cfd11..ae0a02e1b80 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig | |||
@@ -29,49 +29,9 @@ config BCMA_HOST_PCI | |||
29 | 29 | ||
30 | config BCMA_DRIVER_PCI_HOSTMODE | 30 | config BCMA_DRIVER_PCI_HOSTMODE |
31 | bool "Driver for PCI core working in hostmode" | 31 | bool "Driver for PCI core working in hostmode" |
32 | depends on BCMA && MIPS && BCMA_HOST_PCI | ||
33 | help | ||
34 | PCI core hostmode operation (external PCI bus). | ||
35 | |||
36 | config BCMA_HOST_SOC | ||
37 | bool | ||
38 | depends on BCMA_DRIVER_MIPS | ||
39 | |||
40 | config BCMA_DRIVER_MIPS | ||
41 | bool "BCMA Broadcom MIPS core driver" | ||
42 | depends on BCMA && MIPS | 32 | depends on BCMA && MIPS |
43 | help | 33 | help |
44 | Driver for the Broadcom MIPS core attached to Broadcom specific | 34 | PCI core hostmode operation (external PCI bus). |
45 | Advanced Microcontroller Bus. | ||
46 | |||
47 | If unsure, say N | ||
48 | |||
49 | config BCMA_SFLASH | ||
50 | bool | ||
51 | depends on BCMA_DRIVER_MIPS | ||
52 | default y | ||
53 | |||
54 | config BCMA_NFLASH | ||
55 | bool | ||
56 | depends on BCMA_DRIVER_MIPS | ||
57 | default y | ||
58 | |||
59 | config BCMA_DRIVER_GMAC_CMN | ||
60 | bool "BCMA Broadcom GBIT MAC COMMON core driver" | ||
61 | depends on BCMA | ||
62 | help | ||
63 | Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom | ||
64 | specific Advanced Microcontroller Bus. | ||
65 | |||
66 | If unsure, say N | ||
67 | |||
68 | config BCMA_DRIVER_GPIO | ||
69 | bool "BCMA GPIO driver" | ||
70 | depends on BCMA && GPIOLIB | ||
71 | help | ||
72 | Driver to provide access to the GPIO pins of the bcma bus. | ||
73 | |||
74 | If unsure, say N | ||
75 | 35 | ||
76 | config BCMA_DEBUG | 36 | config BCMA_DEBUG |
77 | bool "BCMA debugging" | 37 | bool "BCMA debugging" |
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index 734b32f09c0..a2161cceafb 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile | |||
@@ -1,14 +1,8 @@ | |||
1 | bcma-y += main.o scan.o core.o sprom.o | 1 | bcma-y += main.o scan.o core.o sprom.o |
2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o | 2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o |
3 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o | ||
4 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o | ||
5 | bcma-y += driver_pci.o | 3 | bcma-y += driver_pci.o |
6 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o | 4 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o |
7 | bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o | ||
8 | bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o | ||
9 | bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o | ||
10 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o | 5 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o |
11 | bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o | ||
12 | obj-$(CONFIG_BCMA) += bcma.o | 6 | obj-$(CONFIG_BCMA) += bcma.o |
13 | 7 | ||
14 | ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG | 8 | ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 19e3fbfd575..e02ff21835c 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -10,95 +10,26 @@ | |||
10 | 10 | ||
11 | #define BCMA_CORE_SIZE 0x1000 | 11 | #define BCMA_CORE_SIZE 0x1000 |
12 | 12 | ||
13 | #define bcma_err(bus, fmt, ...) \ | ||
14 | pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) | ||
15 | #define bcma_warn(bus, fmt, ...) \ | ||
16 | pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) | ||
17 | #define bcma_info(bus, fmt, ...) \ | ||
18 | pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) | ||
19 | #define bcma_debug(bus, fmt, ...) \ | ||
20 | pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) | ||
21 | |||
22 | struct bcma_bus; | 13 | struct bcma_bus; |
23 | 14 | ||
24 | /* main.c */ | 15 | /* main.c */ |
25 | int bcma_bus_register(struct bcma_bus *bus); | 16 | int bcma_bus_register(struct bcma_bus *bus); |
26 | void bcma_bus_unregister(struct bcma_bus *bus); | 17 | void bcma_bus_unregister(struct bcma_bus *bus); |
27 | int __init bcma_bus_early_register(struct bcma_bus *bus, | ||
28 | struct bcma_device *core_cc, | ||
29 | struct bcma_device *core_mips); | ||
30 | #ifdef CONFIG_PM | ||
31 | int bcma_bus_suspend(struct bcma_bus *bus); | ||
32 | int bcma_bus_resume(struct bcma_bus *bus); | ||
33 | #endif | ||
34 | 18 | ||
35 | /* scan.c */ | 19 | /* scan.c */ |
36 | int bcma_bus_scan(struct bcma_bus *bus); | 20 | int bcma_bus_scan(struct bcma_bus *bus); |
37 | int __init bcma_bus_scan_early(struct bcma_bus *bus, | ||
38 | struct bcma_device_id *match, | ||
39 | struct bcma_device *core); | ||
40 | void bcma_init_bus(struct bcma_bus *bus); | ||
41 | 21 | ||
42 | /* sprom.c */ | 22 | /* sprom.c */ |
43 | int bcma_sprom_get(struct bcma_bus *bus); | 23 | int bcma_sprom_get(struct bcma_bus *bus); |
44 | 24 | ||
45 | /* driver_chipcommon.c */ | ||
46 | #ifdef CONFIG_BCMA_DRIVER_MIPS | ||
47 | void bcma_chipco_serial_init(struct bcma_drv_cc *cc); | ||
48 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ | ||
49 | |||
50 | /* driver_chipcommon_pmu.c */ | ||
51 | u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); | ||
52 | u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); | ||
53 | |||
54 | #ifdef CONFIG_BCMA_SFLASH | ||
55 | /* driver_chipcommon_sflash.c */ | ||
56 | int bcma_sflash_init(struct bcma_drv_cc *cc); | ||
57 | extern struct platform_device bcma_sflash_dev; | ||
58 | #else | ||
59 | static inline int bcma_sflash_init(struct bcma_drv_cc *cc) | ||
60 | { | ||
61 | bcma_err(cc->core->bus, "Serial flash not supported\n"); | ||
62 | return 0; | ||
63 | } | ||
64 | #endif /* CONFIG_BCMA_SFLASH */ | ||
65 | |||
66 | #ifdef CONFIG_BCMA_NFLASH | ||
67 | /* driver_chipcommon_nflash.c */ | ||
68 | int bcma_nflash_init(struct bcma_drv_cc *cc); | ||
69 | extern struct platform_device bcma_nflash_dev; | ||
70 | #else | ||
71 | static inline int bcma_nflash_init(struct bcma_drv_cc *cc) | ||
72 | { | ||
73 | bcma_err(cc->core->bus, "NAND flash not supported\n"); | ||
74 | return 0; | ||
75 | } | ||
76 | #endif /* CONFIG_BCMA_NFLASH */ | ||
77 | |||
78 | #ifdef CONFIG_BCMA_HOST_PCI | 25 | #ifdef CONFIG_BCMA_HOST_PCI |
79 | /* host_pci.c */ | 26 | /* host_pci.c */ |
80 | extern int __init bcma_host_pci_init(void); | 27 | extern int __init bcma_host_pci_init(void); |
81 | extern void __exit bcma_host_pci_exit(void); | 28 | extern void __exit bcma_host_pci_exit(void); |
82 | #endif /* CONFIG_BCMA_HOST_PCI */ | 29 | #endif /* CONFIG_BCMA_HOST_PCI */ |
83 | 30 | ||
84 | /* driver_pci.c */ | ||
85 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); | ||
86 | |||
87 | extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc); | ||
88 | |||
89 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 31 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
90 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); | ||
91 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 32 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); |
92 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 33 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
93 | 34 | ||
94 | #ifdef CONFIG_BCMA_DRIVER_GPIO | ||
95 | /* driver_gpio.c */ | ||
96 | int bcma_gpio_init(struct bcma_drv_cc *cc); | ||
97 | #else | ||
98 | static inline int bcma_gpio_init(struct bcma_drv_cc *cc) | ||
99 | { | ||
100 | return -ENOTSUPP; | ||
101 | } | ||
102 | #endif /* CONFIG_BCMA_DRIVER_GPIO */ | ||
103 | |||
104 | #endif | 35 | #endif |
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 03bbe104338..4a04a49cc06 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c | |||
@@ -6,7 +6,6 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bcma_private.h" | 8 | #include "bcma_private.h" |
9 | #include <linux/export.h> | ||
10 | #include <linux/bcma/bcma.h> | 9 | #include <linux/bcma/bcma.h> |
11 | 10 | ||
12 | bool bcma_core_is_enabled(struct bcma_device *core) | 11 | bool bcma_core_is_enabled(struct bcma_device *core) |
@@ -30,7 +29,6 @@ void bcma_core_disable(struct bcma_device *core, u32 flags) | |||
30 | udelay(10); | 29 | udelay(10); |
31 | 30 | ||
32 | bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); | 31 | bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); |
33 | bcma_aread32(core, BCMA_RESET_CTL); | ||
34 | udelay(1); | 32 | udelay(1); |
35 | } | 33 | } |
36 | EXPORT_SYMBOL_GPL(bcma_core_disable); | 34 | EXPORT_SYMBOL_GPL(bcma_core_disable); |
@@ -65,7 +63,7 @@ void bcma_core_set_clockmode(struct bcma_device *core, | |||
65 | switch (clkmode) { | 63 | switch (clkmode) { |
66 | case BCMA_CLKMODE_FAST: | 64 | case BCMA_CLKMODE_FAST: |
67 | bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); | 65 | bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); |
68 | usleep_range(64, 300); | 66 | udelay(64); |
69 | for (i = 0; i < 1500; i++) { | 67 | for (i = 0; i < 1500; i++) { |
70 | if (bcma_read32(core, BCMA_CLKCTLST) & | 68 | if (bcma_read32(core, BCMA_CLKCTLST) & |
71 | BCMA_CLKCTLST_HAVEHT) { | 69 | BCMA_CLKCTLST_HAVEHT) { |
@@ -75,10 +73,10 @@ void bcma_core_set_clockmode(struct bcma_device *core, | |||
75 | udelay(10); | 73 | udelay(10); |
76 | } | 74 | } |
77 | if (i) | 75 | if (i) |
78 | bcma_err(core->bus, "HT force timeout\n"); | 76 | pr_err("HT force timeout\n"); |
79 | break; | 77 | break; |
80 | case BCMA_CLKMODE_DYNAMIC: | 78 | case BCMA_CLKMODE_DYNAMIC: |
81 | bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT); | 79 | pr_warn("Dynamic clockmode not supported yet!\n"); |
82 | break; | 80 | break; |
83 | } | 81 | } |
84 | } | 82 | } |
@@ -102,9 +100,9 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) | |||
102 | udelay(10); | 100 | udelay(10); |
103 | } | 101 | } |
104 | if (i) | 102 | if (i) |
105 | bcma_err(core->bus, "PLL enable timeout\n"); | 103 | pr_err("PLL enable timeout\n"); |
106 | } else { | 104 | } else { |
107 | bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); | 105 | pr_warn("Disabling PLL not supported yet!\n"); |
108 | } | 106 | } |
109 | } | 107 | } |
110 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); | 108 | EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); |
@@ -112,16 +110,14 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); | |||
112 | u32 bcma_core_dma_translation(struct bcma_device *core) | 110 | u32 bcma_core_dma_translation(struct bcma_device *core) |
113 | { | 111 | { |
114 | switch (core->bus->hosttype) { | 112 | switch (core->bus->hosttype) { |
115 | case BCMA_HOSTTYPE_SOC: | ||
116 | return 0; | ||
117 | case BCMA_HOSTTYPE_PCI: | 113 | case BCMA_HOSTTYPE_PCI: |
118 | if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) | 114 | if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) |
119 | return BCMA_DMA_TRANSLATION_DMA64_CMT; | 115 | return BCMA_DMA_TRANSLATION_DMA64_CMT; |
120 | else | 116 | else |
121 | return BCMA_DMA_TRANSLATION_DMA32_CMT; | 117 | return BCMA_DMA_TRANSLATION_DMA32_CMT; |
122 | default: | 118 | default: |
123 | bcma_err(core->bus, "DMA translation unknown for host %d\n", | 119 | pr_err("DMA translation unknown for host %d\n", |
124 | core->bus->hosttype); | 120 | core->bus->hosttype); |
125 | } | 121 | } |
126 | return BCMA_DMA_TRANSLATION_NONE; | 122 | return BCMA_DMA_TRANSLATION_NONE; |
127 | } | 123 | } |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index e461ad25fda..851e05bc948 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -4,15 +4,11 @@ | |||
4 | * | 4 | * |
5 | * Copyright 2005, Broadcom Corporation | 5 | * Copyright 2005, Broadcom Corporation |
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
7 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
8 | * | 7 | * |
9 | * Licensed under the GNU/GPL. See COPYING for details. | 8 | * Licensed under the GNU/GPL. See COPYING for details. |
10 | */ | 9 | */ |
11 | 10 | ||
12 | #include "bcma_private.h" | 11 | #include "bcma_private.h" |
13 | #include <linux/bcm47xx_wdt.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/bcma/bcma.h> | 12 | #include <linux/bcma/bcma.h> |
17 | 13 | ||
18 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | 14 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, |
@@ -25,96 +21,10 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | |||
25 | return value; | 21 | return value; |
26 | } | 22 | } |
27 | 23 | ||
28 | static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) | 24 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) |
29 | { | ||
30 | if (cc->capabilities & BCMA_CC_CAP_PMU) | ||
31 | return bcma_pmu_get_alp_clock(cc); | ||
32 | |||
33 | return 20000000; | ||
34 | } | ||
35 | |||
36 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) | ||
37 | { | ||
38 | struct bcma_bus *bus = cc->core->bus; | ||
39 | u32 nb; | ||
40 | |||
41 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
42 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | ||
43 | nb = 32; | ||
44 | else if (cc->core->id.rev < 26) | ||
45 | nb = 16; | ||
46 | else | ||
47 | nb = (cc->core->id.rev >= 37) ? 32 : 24; | ||
48 | } else { | ||
49 | nb = 28; | ||
50 | } | ||
51 | if (nb == 32) | ||
52 | return 0xffffffff; | ||
53 | else | ||
54 | return (1 << nb) - 1; | ||
55 | } | ||
56 | |||
57 | static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, | ||
58 | u32 ticks) | ||
59 | { | ||
60 | struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
61 | |||
62 | return bcma_chipco_watchdog_timer_set(cc, ticks); | ||
63 | } | ||
64 | |||
65 | static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt, | ||
66 | u32 ms) | ||
67 | { | ||
68 | struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); | ||
69 | u32 ticks; | ||
70 | |||
71 | ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms); | ||
72 | return ticks / cc->ticks_per_ms; | ||
73 | } | ||
74 | |||
75 | static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc) | ||
76 | { | ||
77 | struct bcma_bus *bus = cc->core->bus; | ||
78 | |||
79 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
80 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | ||
81 | /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ | ||
82 | return bcma_chipco_get_alp_clock(cc) / 4000; | ||
83 | else | ||
84 | /* based on 32KHz ILP clock */ | ||
85 | return 32; | ||
86 | } else { | ||
87 | return bcma_chipco_get_alp_clock(cc) / 1000; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) | ||
92 | { | ||
93 | struct bcm47xx_wdt wdt = {}; | ||
94 | struct platform_device *pdev; | ||
95 | |||
96 | wdt.driver_data = cc; | ||
97 | wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; | ||
98 | wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; | ||
99 | wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; | ||
100 | |||
101 | pdev = platform_device_register_data(NULL, "bcm47xx-wdt", | ||
102 | cc->core->bus->num, &wdt, | ||
103 | sizeof(wdt)); | ||
104 | if (IS_ERR(pdev)) | ||
105 | return PTR_ERR(pdev); | ||
106 | |||
107 | cc->watchdog = pdev; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | ||
113 | { | 25 | { |
114 | if (cc->early_setup_done) | 26 | u32 leddc_on = 10; |
115 | return; | 27 | u32 leddc_off = 90; |
116 | |||
117 | spin_lock_init(&cc->gpio_lock); | ||
118 | 28 | ||
119 | if (cc->core->id.rev >= 11) | 29 | if (cc->core->id.rev >= 11) |
120 | cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | 30 | cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); |
@@ -122,22 +32,6 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | |||
122 | if (cc->core->id.rev >= 35) | 32 | if (cc->core->id.rev >= 35) |
123 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); | 33 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); |
124 | 34 | ||
125 | if (cc->capabilities & BCMA_CC_CAP_PMU) | ||
126 | bcma_pmu_early_init(cc); | ||
127 | |||
128 | cc->early_setup_done = true; | ||
129 | } | ||
130 | |||
131 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | ||
132 | { | ||
133 | u32 leddc_on = 10; | ||
134 | u32 leddc_off = 90; | ||
135 | |||
136 | if (cc->setup_done) | ||
137 | return; | ||
138 | |||
139 | bcma_core_chipcommon_early_init(cc); | ||
140 | |||
141 | if (cc->core->id.rev >= 20) { | 35 | if (cc->core->id.rev >= 20) { |
142 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); | 36 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); |
143 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); | 37 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); |
@@ -146,7 +40,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
146 | if (cc->capabilities & BCMA_CC_CAP_PMU) | 40 | if (cc->capabilities & BCMA_CC_CAP_PMU) |
147 | bcma_pmu_init(cc); | 41 | bcma_pmu_init(cc); |
148 | if (cc->capabilities & BCMA_CC_CAP_PCTL) | 42 | if (cc->capabilities & BCMA_CC_CAP_PCTL) |
149 | bcma_err(cc->core->bus, "Power control not implemented!\n"); | 43 | pr_err("Power control not implemented!\n"); |
150 | 44 | ||
151 | if (cc->core->id.rev >= 16) { | 45 | if (cc->core->id.rev >= 16) { |
152 | if (cc->core->bus->sprom.leddc_on_time && | 46 | if (cc->core->bus->sprom.leddc_on_time && |
@@ -158,33 +52,13 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
158 | ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | | 52 | ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | |
159 | (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); | 53 | (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); |
160 | } | 54 | } |
161 | cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc); | ||
162 | |||
163 | cc->setup_done = true; | ||
164 | } | 55 | } |
165 | 56 | ||
166 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ | 57 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ |
167 | u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | 58 | void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) |
168 | { | 59 | { |
169 | u32 maxt; | 60 | /* instant NMI */ |
170 | enum bcma_clkmode clkmode; | 61 | bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); |
171 | |||
172 | maxt = bcma_chipco_watchdog_get_max_timer(cc); | ||
173 | if (cc->capabilities & BCMA_CC_CAP_PMU) { | ||
174 | if (ticks == 1) | ||
175 | ticks = 2; | ||
176 | else if (ticks > maxt) | ||
177 | ticks = maxt; | ||
178 | bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); | ||
179 | } else { | ||
180 | clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; | ||
181 | bcma_core_set_clockmode(cc->core, clkmode); | ||
182 | if (ticks > maxt) | ||
183 | ticks = maxt; | ||
184 | /* instant NMI */ | ||
185 | bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); | ||
186 | } | ||
187 | return ticks; | ||
188 | } | 62 | } |
189 | 63 | ||
190 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) | 64 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) |
@@ -204,141 +78,26 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask) | |||
204 | 78 | ||
205 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) | 79 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) |
206 | { | 80 | { |
207 | unsigned long flags; | 81 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); |
208 | u32 res; | ||
209 | |||
210 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
211 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); | ||
212 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
213 | |||
214 | return res; | ||
215 | } | 82 | } |
216 | 83 | ||
217 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | 84 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) |
218 | { | 85 | { |
219 | unsigned long flags; | 86 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); |
220 | u32 res; | ||
221 | |||
222 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
223 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); | ||
224 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
225 | |||
226 | return res; | ||
227 | } | 87 | } |
228 | 88 | ||
229 | /* | ||
230 | * If the bit is set to 0, chipcommon controlls this GPIO, | ||
231 | * if the bit is set to 1, it is used by some part of the chip and not our code. | ||
232 | */ | ||
233 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) | 89 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) |
234 | { | 90 | { |
235 | unsigned long flags; | 91 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); |
236 | u32 res; | ||
237 | |||
238 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
239 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); | ||
240 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
241 | |||
242 | return res; | ||
243 | } | 92 | } |
244 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); | 93 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); |
245 | 94 | ||
246 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) | 95 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) |
247 | { | 96 | { |
248 | unsigned long flags; | 97 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); |
249 | u32 res; | ||
250 | |||
251 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
252 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); | ||
253 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
254 | |||
255 | return res; | ||
256 | } | 98 | } |
257 | 99 | ||
258 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) | 100 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) |
259 | { | 101 | { |
260 | unsigned long flags; | 102 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); |
261 | u32 res; | ||
262 | |||
263 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
264 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); | ||
265 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
266 | |||
267 | return res; | ||
268 | } | ||
269 | |||
270 | u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
271 | { | ||
272 | unsigned long flags; | ||
273 | u32 res; | ||
274 | |||
275 | if (cc->core->id.rev < 20) | ||
276 | return 0; | ||
277 | |||
278 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
279 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value); | ||
280 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
281 | |||
282 | return res; | ||
283 | } | ||
284 | |||
285 | u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | u32 res; | ||
289 | |||
290 | if (cc->core->id.rev < 20) | ||
291 | return 0; | ||
292 | |||
293 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
294 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value); | ||
295 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
296 | |||
297 | return res; | ||
298 | } | ||
299 | |||
300 | #ifdef CONFIG_BCMA_DRIVER_MIPS | ||
301 | void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | ||
302 | { | ||
303 | unsigned int irq; | ||
304 | u32 baud_base; | ||
305 | u32 i; | ||
306 | unsigned int ccrev = cc->core->id.rev; | ||
307 | struct bcma_serial_port *ports = cc->serial_ports; | ||
308 | |||
309 | if (ccrev >= 11 && ccrev != 15) { | ||
310 | baud_base = bcma_chipco_get_alp_clock(cc); | ||
311 | if (ccrev >= 21) { | ||
312 | /* Turn off UART clock before switching clocksource. */ | ||
313 | bcma_cc_write32(cc, BCMA_CC_CORECTL, | ||
314 | bcma_cc_read32(cc, BCMA_CC_CORECTL) | ||
315 | & ~BCMA_CC_CORECTL_UARTCLKEN); | ||
316 | } | ||
317 | /* Set the override bit so we don't divide it */ | ||
318 | bcma_cc_write32(cc, BCMA_CC_CORECTL, | ||
319 | bcma_cc_read32(cc, BCMA_CC_CORECTL) | ||
320 | | BCMA_CC_CORECTL_UARTCLK0); | ||
321 | if (ccrev >= 21) { | ||
322 | /* Re-enable the UART clock. */ | ||
323 | bcma_cc_write32(cc, BCMA_CC_CORECTL, | ||
324 | bcma_cc_read32(cc, BCMA_CC_CORECTL) | ||
325 | | BCMA_CC_CORECTL_UARTCLKEN); | ||
326 | } | ||
327 | } else { | ||
328 | bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev); | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | irq = bcma_core_mips_irq(cc->core); | ||
333 | |||
334 | /* Determine the registers of the UARTs */ | ||
335 | cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART); | ||
336 | for (i = 0; i < cc->nr_serial_ports; i++) { | ||
337 | ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA + | ||
338 | (i * 256); | ||
339 | ports[i].irq = irq; | ||
340 | ports[i].baud_base = baud_base; | ||
341 | ports[i].reg_shift = 0; | ||
342 | } | ||
343 | } | 103 | } |
344 | #endif /* CONFIG_BCMA_DRIVER_MIPS */ | ||
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c deleted file mode 100644 index dbda91e4dff..00000000000 --- a/drivers/bcma/driver_chipcommon_nflash.c +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * ChipCommon NAND flash interface | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | |||
11 | #include "bcma_private.h" | ||
12 | |||
13 | struct platform_device bcma_nflash_dev = { | ||
14 | .name = "bcma_nflash", | ||
15 | .num_resources = 0, | ||
16 | }; | ||
17 | |||
18 | /* Initialize NAND flash access */ | ||
19 | int bcma_nflash_init(struct bcma_drv_cc *cc) | ||
20 | { | ||
21 | struct bcma_bus *bus = cc->core->bus; | ||
22 | |||
23 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && | ||
24 | cc->core->id.rev != 0x38) { | ||
25 | bcma_err(bus, "NAND flash on unsupported board!\n"); | ||
26 | return -ENOTSUPP; | ||
27 | } | ||
28 | |||
29 | if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) { | ||
30 | bcma_err(bus, "NAND flash not present according to ChipCommon\n"); | ||
31 | return -ENODEV; | ||
32 | } | ||
33 | |||
34 | cc->nflash.present = true; | ||
35 | if (cc->core->id.rev == 38 && | ||
36 | (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) | ||
37 | cc->nflash.boot = true; | ||
38 | |||
39 | /* Prepare platform device, but don't register it yet. It's too early, | ||
40 | * malloc (required by device_private_init) is not available yet. */ | ||
41 | bcma_nflash_dev.dev.platform_data = &cc->nflash; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index c62c788b328..fcc63db0ce7 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -3,58 +3,44 @@ | |||
3 | * ChipCommon Power Management Unit driver | 3 | * ChipCommon Power Management Unit driver |
4 | * | 4 | * |
5 | * Copyright 2009, Michael Buesch <m@bues.ch> | 5 | * Copyright 2009, Michael Buesch <m@bues.ch> |
6 | * Copyright 2007, 2011, Broadcom Corporation | 6 | * Copyright 2007, Broadcom Corporation |
7 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
8 | * | 7 | * |
9 | * Licensed under the GNU/GPL. See COPYING for details. | 8 | * Licensed under the GNU/GPL. See COPYING for details. |
10 | */ | 9 | */ |
11 | 10 | ||
12 | #include "bcma_private.h" | 11 | #include "bcma_private.h" |
13 | #include <linux/export.h> | ||
14 | #include <linux/bcma/bcma.h> | 12 | #include <linux/bcma/bcma.h> |
15 | 13 | ||
16 | u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) | 14 | static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, |
15 | u32 offset, u32 mask, u32 set) | ||
17 | { | 16 | { |
18 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | 17 | u32 value; |
19 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | ||
20 | return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | ||
21 | } | ||
22 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); | ||
23 | |||
24 | void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) | ||
25 | { | ||
26 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | ||
27 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | ||
28 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); | ||
29 | } | ||
30 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); | ||
31 | |||
32 | void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, | ||
33 | u32 set) | ||
34 | { | ||
35 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | ||
36 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | ||
37 | bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); | ||
38 | } | ||
39 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); | ||
40 | 18 | ||
41 | void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | 19 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); |
42 | u32 offset, u32 mask, u32 set) | ||
43 | { | ||
44 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); | 20 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); |
45 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | 21 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); |
46 | bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); | 22 | value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); |
23 | value &= mask; | ||
24 | value |= set; | ||
25 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value); | ||
26 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); | ||
47 | } | 27 | } |
48 | EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); | ||
49 | 28 | ||
50 | void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, | 29 | static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) |
51 | u32 set) | ||
52 | { | 30 | { |
53 | bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); | 31 | struct bcma_bus *bus = cc->core->bus; |
54 | bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); | 32 | |
55 | bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); | 33 | switch (bus->chipinfo.id) { |
34 | case 0x4313: | ||
35 | case 0x4331: | ||
36 | case 43224: | ||
37 | case 43225: | ||
38 | break; | ||
39 | default: | ||
40 | pr_err("PLL init unknown for device 0x%04X\n", | ||
41 | bus->chipinfo.id); | ||
42 | } | ||
56 | } | 43 | } |
57 | EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); | ||
58 | 44 | ||
59 | static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) | 45 | static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) |
60 | { | 46 | { |
@@ -62,13 +48,16 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) | |||
62 | u32 min_msk = 0, max_msk = 0; | 48 | u32 min_msk = 0, max_msk = 0; |
63 | 49 | ||
64 | switch (bus->chipinfo.id) { | 50 | switch (bus->chipinfo.id) { |
65 | case BCMA_CHIP_ID_BCM4313: | 51 | case 0x4313: |
66 | min_msk = 0x200D; | 52 | min_msk = 0x200D; |
67 | max_msk = 0xFFFF; | 53 | max_msk = 0xFFFF; |
68 | break; | 54 | break; |
55 | case 43224: | ||
56 | case 43225: | ||
57 | break; | ||
69 | default: | 58 | default: |
70 | bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", | 59 | pr_err("PMU resource config unknown for device 0x%04X\n", |
71 | bus->chipinfo.id); | 60 | bus->chipinfo.id); |
72 | } | 61 | } |
73 | 62 | ||
74 | /* Set the resource masks. */ | 63 | /* Set the resource masks. */ |
@@ -76,88 +65,62 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) | |||
76 | bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); | 65 | bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); |
77 | if (max_msk) | 66 | if (max_msk) |
78 | bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); | 67 | bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); |
79 | |||
80 | /* | ||
81 | * Add some delay; allow resources to come up and settle. | ||
82 | * Delay is required for SoC (early init). | ||
83 | */ | ||
84 | mdelay(2); | ||
85 | } | 68 | } |
86 | 69 | ||
87 | /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ | 70 | void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) |
88 | void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) | ||
89 | { | 71 | { |
90 | struct bcma_bus *bus = cc->core->bus; | 72 | struct bcma_bus *bus = cc->core->bus; |
91 | u32 val; | ||
92 | 73 | ||
93 | val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); | 74 | switch (bus->chipinfo.id) { |
94 | if (enable) { | 75 | case 0x4313: |
95 | val |= BCMA_CHIPCTL_4331_EXTPA_EN; | 76 | case 0x4331: |
96 | if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) | 77 | case 43224: |
97 | val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; | 78 | case 43225: |
98 | else if (bus->chipinfo.rev > 0) | 79 | break; |
99 | val |= BCMA_CHIPCTL_4331_EXTPA_EN2; | 80 | default: |
100 | } else { | 81 | pr_err("PMU switch/regulators init unknown for device " |
101 | val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; | 82 | "0x%04X\n", bus->chipinfo.id); |
102 | val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2; | ||
103 | val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; | ||
104 | } | 83 | } |
105 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); | ||
106 | } | 84 | } |
107 | 85 | ||
108 | static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) | 86 | void bcma_pmu_workarounds(struct bcma_drv_cc *cc) |
109 | { | 87 | { |
110 | struct bcma_bus *bus = cc->core->bus; | 88 | struct bcma_bus *bus = cc->core->bus; |
111 | 89 | ||
112 | switch (bus->chipinfo.id) { | 90 | switch (bus->chipinfo.id) { |
113 | case BCMA_CHIP_ID_BCM4313: | 91 | case 0x4313: |
114 | /* enable 12 mA drive strenth for 4313 and set chipControl | 92 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); |
115 | register bit 1 */ | ||
116 | bcma_chipco_chipctl_maskset(cc, 0, | ||
117 | ~BCMA_CCTRL_4313_12MA_LED_DRIVE, | ||
118 | BCMA_CCTRL_4313_12MA_LED_DRIVE); | ||
119 | break; | 93 | break; |
120 | case BCMA_CHIP_ID_BCM4331: | 94 | case 0x4331: |
121 | case BCMA_CHIP_ID_BCM43431: | 95 | pr_err("Enabling Ext PA lines not implemented\n"); |
122 | /* Ext PA lines must be enabled for tx on BCM4331 */ | ||
123 | bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); | ||
124 | break; | 96 | break; |
125 | case BCMA_CHIP_ID_BCM43224: | 97 | case 43224: |
126 | case BCMA_CHIP_ID_BCM43421: | ||
127 | /* enable 12 mA drive strenth for 43224 and set chipControl | ||
128 | register bit 15 */ | ||
129 | if (bus->chipinfo.rev == 0) { | 98 | if (bus->chipinfo.rev == 0) { |
130 | bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, | 99 | pr_err("Workarounds for 43224 rev 0 not fully " |
131 | ~BCMA_CCTRL_43224_GPIO_TOGGLE, | 100 | "implemented\n"); |
132 | BCMA_CCTRL_43224_GPIO_TOGGLE); | 101 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); |
133 | bcma_chipco_chipctl_maskset(cc, 0, | ||
134 | ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, | ||
135 | BCMA_CCTRL_43224A0_12MA_LED_DRIVE); | ||
136 | } else { | 102 | } else { |
137 | bcma_chipco_chipctl_maskset(cc, 0, | 103 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); |
138 | ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, | ||
139 | BCMA_CCTRL_43224B0_12MA_LED_DRIVE); | ||
140 | } | 104 | } |
141 | break; | 105 | break; |
106 | case 43225: | ||
107 | break; | ||
142 | default: | 108 | default: |
143 | bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n", | 109 | pr_err("Workarounds unknown for device 0x%04X\n", |
144 | bus->chipinfo.id); | 110 | bus->chipinfo.id); |
145 | } | 111 | } |
146 | } | 112 | } |
147 | 113 | ||
148 | void bcma_pmu_early_init(struct bcma_drv_cc *cc) | 114 | void bcma_pmu_init(struct bcma_drv_cc *cc) |
149 | { | 115 | { |
150 | u32 pmucap; | 116 | u32 pmucap; |
151 | 117 | ||
152 | pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); | 118 | pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); |
153 | cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); | 119 | cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); |
154 | 120 | ||
155 | bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", | 121 | pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, |
156 | cc->pmu.rev, pmucap); | 122 | pmucap); |
157 | } | ||
158 | 123 | ||
159 | void bcma_pmu_init(struct bcma_drv_cc *cc) | ||
160 | { | ||
161 | if (cc->pmu.rev == 1) | 124 | if (cc->pmu.rev == 1) |
162 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, | 125 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, |
163 | ~BCMA_CC_PMU_CTL_NOILPONW); | 126 | ~BCMA_CC_PMU_CTL_NOILPONW); |
@@ -165,346 +128,11 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) | |||
165 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, | 128 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, |
166 | BCMA_CC_PMU_CTL_NOILPONW); | 129 | BCMA_CC_PMU_CTL_NOILPONW); |
167 | 130 | ||
131 | if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) | ||
132 | pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); | ||
133 | |||
134 | bcma_pmu_pll_init(cc); | ||
168 | bcma_pmu_resources_init(cc); | 135 | bcma_pmu_resources_init(cc); |
136 | bcma_pmu_swreg_init(cc); | ||
169 | bcma_pmu_workarounds(cc); | 137 | bcma_pmu_workarounds(cc); |
170 | } | 138 | } |
171 | |||
172 | u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) | ||
173 | { | ||
174 | struct bcma_bus *bus = cc->core->bus; | ||
175 | |||
176 | switch (bus->chipinfo.id) { | ||
177 | case BCMA_CHIP_ID_BCM4716: | ||
178 | case BCMA_CHIP_ID_BCM4748: | ||
179 | case BCMA_CHIP_ID_BCM47162: | ||
180 | case BCMA_CHIP_ID_BCM4313: | ||
181 | case BCMA_CHIP_ID_BCM5357: | ||
182 | case BCMA_CHIP_ID_BCM4749: | ||
183 | case BCMA_CHIP_ID_BCM53572: | ||
184 | /* always 20Mhz */ | ||
185 | return 20000 * 1000; | ||
186 | case BCMA_CHIP_ID_BCM5356: | ||
187 | case BCMA_CHIP_ID_BCM4706: | ||
188 | /* always 25Mhz */ | ||
189 | return 25000 * 1000; | ||
190 | default: | ||
191 | bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", | ||
192 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); | ||
193 | } | ||
194 | return BCMA_CC_PMU_ALP_CLOCK; | ||
195 | } | ||
196 | |||
197 | /* Find the output of the "m" pll divider given pll controls that start with | ||
198 | * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. | ||
199 | */ | ||
200 | static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) | ||
201 | { | ||
202 | u32 tmp, div, ndiv, p1, p2, fc; | ||
203 | struct bcma_bus *bus = cc->core->bus; | ||
204 | |||
205 | BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); | ||
206 | |||
207 | BUG_ON(!m || m > 4); | ||
208 | |||
209 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || | ||
210 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) { | ||
211 | /* Detect failure in clock setting */ | ||
212 | tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | ||
213 | if (tmp & 0x40000) | ||
214 | return 133 * 1000000; | ||
215 | } | ||
216 | |||
217 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); | ||
218 | p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; | ||
219 | p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; | ||
220 | |||
221 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); | ||
222 | div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & | ||
223 | BCMA_CC_PPL_MDIV_MASK; | ||
224 | |||
225 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); | ||
226 | ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; | ||
227 | |||
228 | /* Do calculation in Mhz */ | ||
229 | fc = bcma_pmu_get_alp_clock(cc) / 1000000; | ||
230 | fc = (p1 * ndiv * fc) / p2; | ||
231 | |||
232 | /* Return clock in Hertz */ | ||
233 | return (fc / div) * 1000000; | ||
234 | } | ||
235 | |||
236 | static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) | ||
237 | { | ||
238 | u32 tmp, ndiv, p1div, p2div; | ||
239 | u32 clock; | ||
240 | |||
241 | BUG_ON(!m || m > 4); | ||
242 | |||
243 | /* Get N, P1 and P2 dividers to determine CPU clock */ | ||
244 | tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF); | ||
245 | ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK) | ||
246 | >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT; | ||
247 | p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK) | ||
248 | >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT; | ||
249 | p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK) | ||
250 | >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT; | ||
251 | |||
252 | tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | ||
253 | if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION) | ||
254 | /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */ | ||
255 | clock = (25000000 / 4) * ndiv * p2div / p1div; | ||
256 | else | ||
257 | /* Fixed reference clock 25MHz and m = 2 */ | ||
258 | clock = (25000000 / 2) * ndiv * p2div / p1div; | ||
259 | |||
260 | if (m == BCMA_CC_PMU5_MAINPLL_SSB) | ||
261 | clock = clock / 4; | ||
262 | |||
263 | return clock; | ||
264 | } | ||
265 | |||
266 | /* query bus clock frequency for PMU-enabled chipcommon */ | ||
267 | static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) | ||
268 | { | ||
269 | struct bcma_bus *bus = cc->core->bus; | ||
270 | |||
271 | switch (bus->chipinfo.id) { | ||
272 | case BCMA_CHIP_ID_BCM4716: | ||
273 | case BCMA_CHIP_ID_BCM4748: | ||
274 | case BCMA_CHIP_ID_BCM47162: | ||
275 | return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, | ||
276 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
277 | case BCMA_CHIP_ID_BCM5356: | ||
278 | return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, | ||
279 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
280 | case BCMA_CHIP_ID_BCM5357: | ||
281 | case BCMA_CHIP_ID_BCM4749: | ||
282 | return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, | ||
283 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
284 | case BCMA_CHIP_ID_BCM4706: | ||
285 | return bcma_pmu_pll_clock_bcm4706(cc, | ||
286 | BCMA_CC_PMU4706_MAINPLL_PLL0, | ||
287 | BCMA_CC_PMU5_MAINPLL_SSB); | ||
288 | case BCMA_CHIP_ID_BCM53572: | ||
289 | return 75000000; | ||
290 | default: | ||
291 | bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n", | ||
292 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); | ||
293 | } | ||
294 | return BCMA_CC_PMU_HT_CLOCK; | ||
295 | } | ||
296 | |||
297 | /* query cpu clock frequency for PMU-enabled chipcommon */ | ||
298 | u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) | ||
299 | { | ||
300 | struct bcma_bus *bus = cc->core->bus; | ||
301 | |||
302 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) | ||
303 | return 300000000; | ||
304 | |||
305 | /* New PMUs can have different clock for bus and CPU */ | ||
306 | if (cc->pmu.rev >= 5) { | ||
307 | u32 pll; | ||
308 | switch (bus->chipinfo.id) { | ||
309 | case BCMA_CHIP_ID_BCM4706: | ||
310 | return bcma_pmu_pll_clock_bcm4706(cc, | ||
311 | BCMA_CC_PMU4706_MAINPLL_PLL0, | ||
312 | BCMA_CC_PMU5_MAINPLL_CPU); | ||
313 | case BCMA_CHIP_ID_BCM5356: | ||
314 | pll = BCMA_CC_PMU5356_MAINPLL_PLL0; | ||
315 | break; | ||
316 | case BCMA_CHIP_ID_BCM5357: | ||
317 | case BCMA_CHIP_ID_BCM4749: | ||
318 | pll = BCMA_CC_PMU5357_MAINPLL_PLL0; | ||
319 | break; | ||
320 | default: | ||
321 | pll = BCMA_CC_PMU4716_MAINPLL_PLL0; | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); | ||
326 | } | ||
327 | |||
328 | /* On old PMUs CPU has the same clock as the bus */ | ||
329 | return bcma_pmu_get_bus_clock(cc); | ||
330 | } | ||
331 | |||
332 | static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, | ||
333 | u32 value) | ||
334 | { | ||
335 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | ||
336 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); | ||
337 | } | ||
338 | |||
339 | void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | ||
340 | { | ||
341 | u32 tmp = 0; | ||
342 | u8 phypll_offset = 0; | ||
343 | u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5}; | ||
344 | u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc}; | ||
345 | struct bcma_bus *bus = cc->core->bus; | ||
346 | |||
347 | switch (bus->chipinfo.id) { | ||
348 | case BCMA_CHIP_ID_BCM5357: | ||
349 | case BCMA_CHIP_ID_BCM4749: | ||
350 | case BCMA_CHIP_ID_BCM53572: | ||
351 | /* 5357[ab]0, 43236[ab]0, and 6362b0 */ | ||
352 | |||
353 | /* BCM5357 needs to touch PLL1_PLLCTL[02], | ||
354 | so offset PLL0_PLLCTL[02] by 6 */ | ||
355 | phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || | ||
356 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 || | ||
357 | bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; | ||
358 | |||
359 | /* RMW only the P1 divider */ | ||
360 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, | ||
361 | BCMA_CC_PMU_PLL_CTL0 + phypll_offset); | ||
362 | tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | ||
363 | tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); | ||
364 | tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); | ||
365 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | ||
366 | |||
367 | /* RMW only the int feedback divider */ | ||
368 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, | ||
369 | BCMA_CC_PMU_PLL_CTL2 + phypll_offset); | ||
370 | tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | ||
371 | tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); | ||
372 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; | ||
373 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | ||
374 | |||
375 | tmp = 1 << 10; | ||
376 | break; | ||
377 | |||
378 | case BCMA_CHIP_ID_BCM4331: | ||
379 | case BCMA_CHIP_ID_BCM43431: | ||
380 | if (spuravoid == 2) { | ||
381 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
382 | 0x11500014); | ||
383 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
384 | 0x0FC00a08); | ||
385 | } else if (spuravoid == 1) { | ||
386 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
387 | 0x11500014); | ||
388 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
389 | 0x0F600a08); | ||
390 | } else { | ||
391 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
392 | 0x11100014); | ||
393 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
394 | 0x03000a08); | ||
395 | } | ||
396 | tmp = 1 << 10; | ||
397 | break; | ||
398 | |||
399 | case BCMA_CHIP_ID_BCM43224: | ||
400 | case BCMA_CHIP_ID_BCM43225: | ||
401 | case BCMA_CHIP_ID_BCM43421: | ||
402 | if (spuravoid == 1) { | ||
403 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
404 | 0x11500010); | ||
405 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
406 | 0x000C0C06); | ||
407 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
408 | 0x0F600a08); | ||
409 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
410 | 0x00000000); | ||
411 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
412 | 0x2001E920); | ||
413 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
414 | 0x88888815); | ||
415 | } else { | ||
416 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
417 | 0x11100010); | ||
418 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
419 | 0x000c0c06); | ||
420 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
421 | 0x03000a08); | ||
422 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
423 | 0x00000000); | ||
424 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
425 | 0x200005c0); | ||
426 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
427 | 0x88888815); | ||
428 | } | ||
429 | tmp = 1 << 10; | ||
430 | break; | ||
431 | |||
432 | case BCMA_CHIP_ID_BCM4716: | ||
433 | case BCMA_CHIP_ID_BCM4748: | ||
434 | case BCMA_CHIP_ID_BCM47162: | ||
435 | if (spuravoid == 1) { | ||
436 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
437 | 0x11500060); | ||
438 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
439 | 0x080C0C06); | ||
440 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
441 | 0x0F600000); | ||
442 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
443 | 0x00000000); | ||
444 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
445 | 0x2001E924); | ||
446 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
447 | 0x88888815); | ||
448 | } else { | ||
449 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
450 | 0x11100060); | ||
451 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
452 | 0x080c0c06); | ||
453 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
454 | 0x03000000); | ||
455 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
456 | 0x00000000); | ||
457 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
458 | 0x200005c0); | ||
459 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
460 | 0x88888815); | ||
461 | } | ||
462 | |||
463 | tmp = 3 << 9; | ||
464 | break; | ||
465 | |||
466 | case BCMA_CHIP_ID_BCM43227: | ||
467 | case BCMA_CHIP_ID_BCM43228: | ||
468 | case BCMA_CHIP_ID_BCM43428: | ||
469 | /* LCNXN */ | ||
470 | /* PLL Settings for spur avoidance on/off mode, | ||
471 | no on2 support for 43228A0 */ | ||
472 | if (spuravoid == 1) { | ||
473 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
474 | 0x01100014); | ||
475 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
476 | 0x040C0C06); | ||
477 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
478 | 0x03140A08); | ||
479 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
480 | 0x00333333); | ||
481 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
482 | 0x202C2820); | ||
483 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
484 | 0x88888815); | ||
485 | } else { | ||
486 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, | ||
487 | 0x11100014); | ||
488 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, | ||
489 | 0x040c0c06); | ||
490 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | ||
491 | 0x03000a08); | ||
492 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, | ||
493 | 0x00000000); | ||
494 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, | ||
495 | 0x200005c0); | ||
496 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | ||
497 | 0x88888815); | ||
498 | } | ||
499 | tmp = 1 << 10; | ||
500 | break; | ||
501 | default: | ||
502 | bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", | ||
503 | bus->chipinfo.id); | ||
504 | break; | ||
505 | } | ||
506 | |||
507 | tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); | ||
508 | bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); | ||
509 | } | ||
510 | EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); | ||
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c deleted file mode 100644 index 1e694db4532..00000000000 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * ChipCommon serial flash interface | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include <linux/platform_device.h> | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | |||
11 | #include "bcma_private.h" | ||
12 | |||
13 | static struct resource bcma_sflash_resource = { | ||
14 | .name = "bcma_sflash", | ||
15 | .start = BCMA_SOC_FLASH2, | ||
16 | .end = 0, | ||
17 | .flags = IORESOURCE_MEM | IORESOURCE_READONLY, | ||
18 | }; | ||
19 | |||
20 | struct platform_device bcma_sflash_dev = { | ||
21 | .name = "bcma_sflash", | ||
22 | .resource = &bcma_sflash_resource, | ||
23 | .num_resources = 1, | ||
24 | }; | ||
25 | |||
26 | struct bcma_sflash_tbl_e { | ||
27 | char *name; | ||
28 | u32 id; | ||
29 | u32 blocksize; | ||
30 | u16 numblocks; | ||
31 | }; | ||
32 | |||
33 | static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { | ||
34 | { "M25P20", 0x11, 0x10000, 4, }, | ||
35 | { "M25P40", 0x12, 0x10000, 8, }, | ||
36 | |||
37 | { "M25P16", 0x14, 0x10000, 32, }, | ||
38 | { "M25P32", 0x15, 0x10000, 64, }, | ||
39 | { "M25P64", 0x16, 0x10000, 128, }, | ||
40 | { "M25FL128", 0x17, 0x10000, 256, }, | ||
41 | { 0 }, | ||
42 | }; | ||
43 | |||
44 | static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { | ||
45 | { "SST25WF512", 1, 0x1000, 16, }, | ||
46 | { "SST25VF512", 0x48, 0x1000, 16, }, | ||
47 | { "SST25WF010", 2, 0x1000, 32, }, | ||
48 | { "SST25VF010", 0x49, 0x1000, 32, }, | ||
49 | { "SST25WF020", 3, 0x1000, 64, }, | ||
50 | { "SST25VF020", 0x43, 0x1000, 64, }, | ||
51 | { "SST25WF040", 4, 0x1000, 128, }, | ||
52 | { "SST25VF040", 0x44, 0x1000, 128, }, | ||
53 | { "SST25VF040B", 0x8d, 0x1000, 128, }, | ||
54 | { "SST25WF080", 5, 0x1000, 256, }, | ||
55 | { "SST25VF080B", 0x8e, 0x1000, 256, }, | ||
56 | { "SST25VF016", 0x41, 0x1000, 512, }, | ||
57 | { "SST25VF032", 0x4a, 0x1000, 1024, }, | ||
58 | { "SST25VF064", 0x4b, 0x1000, 2048, }, | ||
59 | { 0 }, | ||
60 | }; | ||
61 | |||
62 | static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { | ||
63 | { "AT45DB011", 0xc, 256, 512, }, | ||
64 | { "AT45DB021", 0x14, 256, 1024, }, | ||
65 | { "AT45DB041", 0x1c, 256, 2048, }, | ||
66 | { "AT45DB081", 0x24, 256, 4096, }, | ||
67 | { "AT45DB161", 0x2c, 512, 4096, }, | ||
68 | { "AT45DB321", 0x34, 512, 8192, }, | ||
69 | { "AT45DB642", 0x3c, 1024, 8192, }, | ||
70 | { 0 }, | ||
71 | }; | ||
72 | |||
73 | static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode) | ||
74 | { | ||
75 | int i; | ||
76 | bcma_cc_write32(cc, BCMA_CC_FLASHCTL, | ||
77 | BCMA_CC_FLASHCTL_START | opcode); | ||
78 | for (i = 0; i < 1000; i++) { | ||
79 | if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) & | ||
80 | BCMA_CC_FLASHCTL_BUSY)) | ||
81 | return; | ||
82 | cpu_relax(); | ||
83 | } | ||
84 | bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); | ||
85 | } | ||
86 | |||
87 | /* Initialize serial flash access */ | ||
88 | int bcma_sflash_init(struct bcma_drv_cc *cc) | ||
89 | { | ||
90 | struct bcma_bus *bus = cc->core->bus; | ||
91 | struct bcma_sflash *sflash = &cc->sflash; | ||
92 | struct bcma_sflash_tbl_e *e; | ||
93 | u32 id, id2; | ||
94 | |||
95 | switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | ||
96 | case BCMA_CC_FLASHT_STSER: | ||
97 | bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP); | ||
98 | |||
99 | bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0); | ||
100 | bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); | ||
101 | id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); | ||
102 | |||
103 | bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1); | ||
104 | bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); | ||
105 | id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); | ||
106 | |||
107 | switch (id) { | ||
108 | case 0xbf: | ||
109 | for (e = bcma_sflash_sst_tbl; e->name; e++) { | ||
110 | if (e->id == id2) | ||
111 | break; | ||
112 | } | ||
113 | break; | ||
114 | case 0x13: | ||
115 | return -ENOTSUPP; | ||
116 | default: | ||
117 | for (e = bcma_sflash_st_tbl; e->name; e++) { | ||
118 | if (e->id == id) | ||
119 | break; | ||
120 | } | ||
121 | break; | ||
122 | } | ||
123 | if (!e->name) { | ||
124 | bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2); | ||
125 | return -ENOTSUPP; | ||
126 | } | ||
127 | |||
128 | break; | ||
129 | case BCMA_CC_FLASHT_ATSER: | ||
130 | bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS); | ||
131 | id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c; | ||
132 | |||
133 | for (e = bcma_sflash_at_tbl; e->name; e++) { | ||
134 | if (e->id == id) | ||
135 | break; | ||
136 | } | ||
137 | if (!e->name) { | ||
138 | bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id); | ||
139 | return -ENOTSUPP; | ||
140 | } | ||
141 | |||
142 | break; | ||
143 | default: | ||
144 | bcma_err(bus, "Unsupported flash type\n"); | ||
145 | return -ENOTSUPP; | ||
146 | } | ||
147 | |||
148 | sflash->window = BCMA_SOC_FLASH2; | ||
149 | sflash->blocksize = e->blocksize; | ||
150 | sflash->numblocks = e->numblocks; | ||
151 | sflash->size = sflash->blocksize * sflash->numblocks; | ||
152 | sflash->present = true; | ||
153 | |||
154 | bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", | ||
155 | e->name, sflash->size / 1024, sflash->blocksize, | ||
156 | sflash->numblocks); | ||
157 | |||
158 | /* Prepare platform device, but don't register it yet. It's too early, | ||
159 | * malloc (required by device_private_init) is not available yet. */ | ||
160 | bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start + | ||
161 | sflash->size; | ||
162 | bcma_sflash_dev.dev.platform_data = sflash; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
diff --git a/drivers/bcma/driver_gmac_cmn.c b/drivers/bcma/driver_gmac_cmn.c deleted file mode 100644 index dcb137926d3..00000000000 --- a/drivers/bcma/driver_gmac_cmn.c +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * GBIT MAC COMMON Core | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | |||
11 | void bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc) | ||
12 | { | ||
13 | mutex_init(&gc->phy_mutex); | ||
14 | } | ||
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c deleted file mode 100644 index 9a6f585da2d..00000000000 --- a/drivers/bcma/driver_gpio.c +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * GPIO driver | ||
4 | * | ||
5 | * Copyright 2011, Broadcom Corporation | ||
6 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/gpio.h> | ||
12 | #include <linux/export.h> | ||
13 | #include <linux/bcma/bcma.h> | ||
14 | |||
15 | #include "bcma_private.h" | ||
16 | |||
17 | static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip) | ||
18 | { | ||
19 | return container_of(chip, struct bcma_drv_cc, gpio); | ||
20 | } | ||
21 | |||
22 | static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio) | ||
23 | { | ||
24 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
25 | |||
26 | return !!bcma_chipco_gpio_in(cc, 1 << gpio); | ||
27 | } | ||
28 | |||
29 | static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio, | ||
30 | int value) | ||
31 | { | ||
32 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
33 | |||
34 | bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); | ||
35 | } | ||
36 | |||
37 | static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | ||
38 | { | ||
39 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
40 | |||
41 | bcma_chipco_gpio_outen(cc, 1 << gpio, 0); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, | ||
46 | int value) | ||
47 | { | ||
48 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
49 | |||
50 | bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio); | ||
51 | bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio) | ||
56 | { | ||
57 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
58 | |||
59 | bcma_chipco_gpio_control(cc, 1 << gpio, 0); | ||
60 | /* clear pulldown */ | ||
61 | bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0); | ||
62 | /* Set pullup */ | ||
63 | bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) | ||
69 | { | ||
70 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
71 | |||
72 | /* clear pullup */ | ||
73 | bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); | ||
74 | } | ||
75 | |||
76 | int bcma_gpio_init(struct bcma_drv_cc *cc) | ||
77 | { | ||
78 | struct gpio_chip *chip = &cc->gpio; | ||
79 | |||
80 | chip->label = "bcma_gpio"; | ||
81 | chip->owner = THIS_MODULE; | ||
82 | chip->request = bcma_gpio_request; | ||
83 | chip->free = bcma_gpio_free; | ||
84 | chip->get = bcma_gpio_get_value; | ||
85 | chip->set = bcma_gpio_set_value; | ||
86 | chip->direction_input = bcma_gpio_direction_input; | ||
87 | chip->direction_output = bcma_gpio_direction_output; | ||
88 | chip->ngpio = 16; | ||
89 | /* There is just one SoC in one device and its GPIO addresses should be | ||
90 | * deterministic to address them more easily. The other buses could get | ||
91 | * a random base number. */ | ||
92 | if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
93 | chip->base = 0; | ||
94 | else | ||
95 | chip->base = -1; | ||
96 | |||
97 | return gpiochip_add(chip); | ||
98 | } | ||
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c deleted file mode 100644 index 792daad28cb..00000000000 --- a/drivers/bcma/driver_mips.c +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * Broadcom MIPS32 74K core driver | ||
4 | * | ||
5 | * Copyright 2009, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com> | ||
8 | * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de> | ||
9 | * | ||
10 | * Licensed under the GNU/GPL. See COPYING for details. | ||
11 | */ | ||
12 | |||
13 | #include "bcma_private.h" | ||
14 | |||
15 | #include <linux/bcma/bcma.h> | ||
16 | |||
17 | #include <linux/serial.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/serial_reg.h> | ||
20 | #include <linux/time.h> | ||
21 | |||
22 | /* The 47162a0 hangs when reading MIPS DMP registers registers */ | ||
23 | static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) | ||
24 | { | ||
25 | return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 && | ||
26 | dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K; | ||
27 | } | ||
28 | |||
29 | /* The 5357b0 hangs when reading USB20H DMP registers */ | ||
30 | static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev) | ||
31 | { | ||
32 | return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || | ||
33 | dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) && | ||
34 | dev->bus->chipinfo.pkg == 11 && | ||
35 | dev->id.id == BCMA_CORE_USB20_HOST; | ||
36 | } | ||
37 | |||
38 | static inline u32 mips_read32(struct bcma_drv_mips *mcore, | ||
39 | u16 offset) | ||
40 | { | ||
41 | return bcma_read32(mcore->core, offset); | ||
42 | } | ||
43 | |||
44 | static inline void mips_write32(struct bcma_drv_mips *mcore, | ||
45 | u16 offset, | ||
46 | u32 value) | ||
47 | { | ||
48 | bcma_write32(mcore->core, offset, value); | ||
49 | } | ||
50 | |||
51 | static const u32 ipsflag_irq_mask[] = { | ||
52 | 0, | ||
53 | BCMA_MIPS_IPSFLAG_IRQ1, | ||
54 | BCMA_MIPS_IPSFLAG_IRQ2, | ||
55 | BCMA_MIPS_IPSFLAG_IRQ3, | ||
56 | BCMA_MIPS_IPSFLAG_IRQ4, | ||
57 | }; | ||
58 | |||
59 | static const u32 ipsflag_irq_shift[] = { | ||
60 | 0, | ||
61 | BCMA_MIPS_IPSFLAG_IRQ1_SHIFT, | ||
62 | BCMA_MIPS_IPSFLAG_IRQ2_SHIFT, | ||
63 | BCMA_MIPS_IPSFLAG_IRQ3_SHIFT, | ||
64 | BCMA_MIPS_IPSFLAG_IRQ4_SHIFT, | ||
65 | }; | ||
66 | |||
67 | static u32 bcma_core_mips_irqflag(struct bcma_device *dev) | ||
68 | { | ||
69 | u32 flag; | ||
70 | |||
71 | if (bcma_core_mips_bcm47162a0_quirk(dev)) | ||
72 | return dev->core_index; | ||
73 | if (bcma_core_mips_bcm5357b0_quirk(dev)) | ||
74 | return dev->core_index; | ||
75 | flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); | ||
76 | |||
77 | return flag & 0x1F; | ||
78 | } | ||
79 | |||
80 | /* Get the MIPS IRQ assignment for a specified device. | ||
81 | * If unassigned, 0 is returned. | ||
82 | */ | ||
83 | unsigned int bcma_core_mips_irq(struct bcma_device *dev) | ||
84 | { | ||
85 | struct bcma_device *mdev = dev->bus->drv_mips.core; | ||
86 | u32 irqflag; | ||
87 | unsigned int irq; | ||
88 | |||
89 | irqflag = bcma_core_mips_irqflag(dev); | ||
90 | |||
91 | for (irq = 1; irq <= 4; irq++) | ||
92 | if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & | ||
93 | (1 << irqflag)) | ||
94 | return irq; | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(bcma_core_mips_irq); | ||
99 | |||
100 | static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | ||
101 | { | ||
102 | unsigned int oldirq = bcma_core_mips_irq(dev); | ||
103 | struct bcma_bus *bus = dev->bus; | ||
104 | struct bcma_device *mdev = bus->drv_mips.core; | ||
105 | u32 irqflag; | ||
106 | |||
107 | irqflag = bcma_core_mips_irqflag(dev); | ||
108 | BUG_ON(oldirq == 6); | ||
109 | |||
110 | dev->irq = irq + 2; | ||
111 | |||
112 | /* clear the old irq */ | ||
113 | if (oldirq == 0) | ||
114 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), | ||
115 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & | ||
116 | ~(1 << irqflag)); | ||
117 | else | ||
118 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); | ||
119 | |||
120 | /* assign the new one */ | ||
121 | if (irq == 0) { | ||
122 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), | ||
123 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | | ||
124 | (1 << irqflag)); | ||
125 | } else { | ||
126 | u32 oldirqflag = bcma_read32(mdev, | ||
127 | BCMA_MIPS_MIPS74K_INTMASK(irq)); | ||
128 | if (oldirqflag) { | ||
129 | struct bcma_device *core; | ||
130 | |||
131 | /* backplane irq line is in use, find out who uses | ||
132 | * it and set user to irq 0 | ||
133 | */ | ||
134 | list_for_each_entry(core, &bus->cores, list) { | ||
135 | if ((1 << bcma_core_mips_irqflag(core)) == | ||
136 | oldirqflag) { | ||
137 | bcma_core_mips_set_irq(core, 0); | ||
138 | break; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), | ||
143 | 1 << irqflag); | ||
144 | } | ||
145 | |||
146 | bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n", | ||
147 | dev->id.id, oldirq + 2, irq + 2); | ||
148 | } | ||
149 | |||
150 | static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) | ||
151 | { | ||
152 | int i; | ||
153 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | ||
154 | printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); | ||
155 | for (i = 0; i <= 6; i++) | ||
156 | printk(" %s%s", irq_name[i], i == irq ? "*" : " "); | ||
157 | printk("\n"); | ||
158 | } | ||
159 | |||
160 | static void bcma_core_mips_dump_irq(struct bcma_bus *bus) | ||
161 | { | ||
162 | struct bcma_device *core; | ||
163 | |||
164 | list_for_each_entry(core, &bus->cores, list) { | ||
165 | bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | u32 bcma_cpu_clock(struct bcma_drv_mips *mcore) | ||
170 | { | ||
171 | struct bcma_bus *bus = mcore->core->bus; | ||
172 | |||
173 | if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) | ||
174 | return bcma_pmu_get_cpu_clock(&bus->drv_cc); | ||
175 | |||
176 | bcma_err(bus, "No PMU available, need this to get the cpu clock\n"); | ||
177 | return 0; | ||
178 | } | ||
179 | EXPORT_SYMBOL(bcma_cpu_clock); | ||
180 | |||
181 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) | ||
182 | { | ||
183 | struct bcma_bus *bus = mcore->core->bus; | ||
184 | struct bcma_drv_cc *cc = &bus->drv_cc; | ||
185 | |||
186 | switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | ||
187 | case BCMA_CC_FLASHT_STSER: | ||
188 | case BCMA_CC_FLASHT_ATSER: | ||
189 | bcma_debug(bus, "Found serial flash\n"); | ||
190 | bcma_sflash_init(cc); | ||
191 | break; | ||
192 | case BCMA_CC_FLASHT_PARA: | ||
193 | bcma_debug(bus, "Found parallel flash\n"); | ||
194 | cc->pflash.present = true; | ||
195 | cc->pflash.window = BCMA_SOC_FLASH2; | ||
196 | cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; | ||
197 | |||
198 | if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & | ||
199 | BCMA_CC_FLASH_CFG_DS) == 0) | ||
200 | cc->pflash.buswidth = 1; | ||
201 | else | ||
202 | cc->pflash.buswidth = 2; | ||
203 | break; | ||
204 | default: | ||
205 | bcma_err(bus, "Flash type not supported\n"); | ||
206 | } | ||
207 | |||
208 | if (cc->core->id.rev == 38 || | ||
209 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | ||
210 | if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | ||
211 | bcma_debug(bus, "Found NAND flash\n"); | ||
212 | bcma_nflash_init(cc); | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | ||
218 | { | ||
219 | struct bcma_bus *bus = mcore->core->bus; | ||
220 | |||
221 | if (mcore->early_setup_done) | ||
222 | return; | ||
223 | |||
224 | bcma_chipco_serial_init(&bus->drv_cc); | ||
225 | bcma_core_mips_flash_detect(mcore); | ||
226 | |||
227 | mcore->early_setup_done = true; | ||
228 | } | ||
229 | |||
230 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) | ||
231 | { | ||
232 | struct bcma_bus *bus; | ||
233 | struct bcma_device *core; | ||
234 | bus = mcore->core->bus; | ||
235 | |||
236 | if (mcore->setup_done) | ||
237 | return; | ||
238 | |||
239 | bcma_info(bus, "Initializing MIPS core...\n"); | ||
240 | |||
241 | bcma_core_mips_early_init(mcore); | ||
242 | |||
243 | mcore->assigned_irqs = 1; | ||
244 | |||
245 | /* Assign IRQs to all cores on the bus */ | ||
246 | list_for_each_entry(core, &bus->cores, list) { | ||
247 | int mips_irq; | ||
248 | if (core->irq) | ||
249 | continue; | ||
250 | |||
251 | mips_irq = bcma_core_mips_irq(core); | ||
252 | if (mips_irq > 4) | ||
253 | core->irq = 0; | ||
254 | else | ||
255 | core->irq = mips_irq + 2; | ||
256 | if (core->irq > 5) | ||
257 | continue; | ||
258 | switch (core->id.id) { | ||
259 | case BCMA_CORE_PCI: | ||
260 | case BCMA_CORE_PCIE: | ||
261 | case BCMA_CORE_ETHERNET: | ||
262 | case BCMA_CORE_ETHERNET_GBIT: | ||
263 | case BCMA_CORE_MAC_GBIT: | ||
264 | case BCMA_CORE_80211: | ||
265 | case BCMA_CORE_USB20_HOST: | ||
266 | /* These devices get their own IRQ line if available, | ||
267 | * the rest goes on IRQ0 | ||
268 | */ | ||
269 | if (mcore->assigned_irqs <= 4) | ||
270 | bcma_core_mips_set_irq(core, | ||
271 | mcore->assigned_irqs++); | ||
272 | break; | ||
273 | } | ||
274 | } | ||
275 | bcma_info(bus, "IRQ reconfiguration done\n"); | ||
276 | bcma_core_mips_dump_irq(bus); | ||
277 | |||
278 | mcore->setup_done = true; | ||
279 | } | ||
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index cf7a476a519..25f3ddf3382 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
@@ -2,139 +2,133 @@ | |||
2 | * Broadcom specific AMBA | 2 | * Broadcom specific AMBA |
3 | * PCI Core | 3 | * PCI Core |
4 | * | 4 | * |
5 | * Copyright 2005, 2011, Broadcom Corporation | 5 | * Copyright 2005, Broadcom Corporation |
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
7 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
8 | * | 7 | * |
9 | * Licensed under the GNU/GPL. See COPYING for details. | 8 | * Licensed under the GNU/GPL. See COPYING for details. |
10 | */ | 9 | */ |
11 | 10 | ||
12 | #include "bcma_private.h" | 11 | #include "bcma_private.h" |
13 | #include <linux/export.h> | ||
14 | #include <linux/bcma/bcma.h> | 12 | #include <linux/bcma/bcma.h> |
15 | 13 | ||
16 | /************************************************** | 14 | /************************************************** |
17 | * R/W ops. | 15 | * R/W ops. |
18 | **************************************************/ | 16 | **************************************************/ |
19 | 17 | ||
20 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) | 18 | static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) |
21 | { | 19 | { |
22 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); | 20 | pcicore_write32(pc, 0x130, address); |
23 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); | 21 | pcicore_read32(pc, 0x130); |
24 | return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA); | 22 | return pcicore_read32(pc, 0x134); |
25 | } | 23 | } |
26 | 24 | ||
25 | #if 0 | ||
27 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) | 26 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) |
28 | { | 27 | { |
29 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); | 28 | pcicore_write32(pc, 0x130, address); |
30 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); | 29 | pcicore_read32(pc, 0x130); |
31 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data); | 30 | pcicore_write32(pc, 0x134, data); |
32 | } | 31 | } |
32 | #endif | ||
33 | 33 | ||
34 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) | 34 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) |
35 | { | 35 | { |
36 | const u16 mdio_control = 0x128; | ||
37 | const u16 mdio_data = 0x12C; | ||
36 | u32 v; | 38 | u32 v; |
37 | int i; | 39 | int i; |
38 | 40 | ||
39 | v = BCMA_CORE_PCI_MDIODATA_START; | 41 | v = (1 << 30); /* Start of Transaction */ |
40 | v |= BCMA_CORE_PCI_MDIODATA_WRITE; | 42 | v |= (1 << 28); /* Write Transaction */ |
41 | v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << | 43 | v |= (1 << 17); /* Turnaround */ |
42 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); | 44 | v |= (0x1F << 18); |
43 | v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR << | ||
44 | BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
45 | v |= BCMA_CORE_PCI_MDIODATA_TA; | ||
46 | v |= (phy << 4); | 45 | v |= (phy << 4); |
47 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); | 46 | pcicore_write32(pc, mdio_data, v); |
48 | 47 | ||
49 | udelay(10); | 48 | udelay(10); |
50 | for (i = 0; i < 200; i++) { | 49 | for (i = 0; i < 200; i++) { |
51 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); | 50 | v = pcicore_read32(pc, mdio_control); |
52 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) | 51 | if (v & 0x100 /* Trans complete */) |
53 | break; | 52 | break; |
54 | usleep_range(1000, 2000); | 53 | msleep(1); |
55 | } | 54 | } |
56 | } | 55 | } |
57 | 56 | ||
58 | static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) | 57 | static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) |
59 | { | 58 | { |
59 | const u16 mdio_control = 0x128; | ||
60 | const u16 mdio_data = 0x12C; | ||
60 | int max_retries = 10; | 61 | int max_retries = 10; |
61 | u16 ret = 0; | 62 | u16 ret = 0; |
62 | u32 v; | 63 | u32 v; |
63 | int i; | 64 | int i; |
64 | 65 | ||
65 | /* enable mdio access to SERDES */ | 66 | v = 0x80; /* Enable Preamble Sequence */ |
66 | v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; | 67 | v |= 0x2; /* MDIO Clock Divisor */ |
67 | v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; | 68 | pcicore_write32(pc, mdio_control, v); |
68 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); | ||
69 | 69 | ||
70 | if (pc->core->id.rev >= 10) { | 70 | if (pc->core->id.rev >= 10) { |
71 | max_retries = 200; | 71 | max_retries = 200; |
72 | bcma_pcie_mdio_set_phy(pc, device); | 72 | bcma_pcie_mdio_set_phy(pc, device); |
73 | v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << | ||
74 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); | ||
75 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
76 | } else { | ||
77 | v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); | ||
78 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); | ||
79 | } | 73 | } |
80 | 74 | ||
81 | v = BCMA_CORE_PCI_MDIODATA_START; | 75 | v = (1 << 30); /* Start of Transaction */ |
82 | v |= BCMA_CORE_PCI_MDIODATA_READ; | 76 | v |= (1 << 29); /* Read Transaction */ |
83 | v |= BCMA_CORE_PCI_MDIODATA_TA; | 77 | v |= (1 << 17); /* Turnaround */ |
84 | 78 | if (pc->core->id.rev < 10) | |
85 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); | 79 | v |= (u32)device << 22; |
80 | v |= (u32)address << 18; | ||
81 | pcicore_write32(pc, mdio_data, v); | ||
86 | /* Wait for the device to complete the transaction */ | 82 | /* Wait for the device to complete the transaction */ |
87 | udelay(10); | 83 | udelay(10); |
88 | for (i = 0; i < max_retries; i++) { | 84 | for (i = 0; i < max_retries; i++) { |
89 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); | 85 | v = pcicore_read32(pc, mdio_control); |
90 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) { | 86 | if (v & 0x100 /* Trans complete */) { |
91 | udelay(10); | 87 | udelay(10); |
92 | ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); | 88 | ret = pcicore_read32(pc, mdio_data); |
93 | break; | 89 | break; |
94 | } | 90 | } |
95 | usleep_range(1000, 2000); | 91 | msleep(1); |
96 | } | 92 | } |
97 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); | 93 | pcicore_write32(pc, mdio_control, 0); |
98 | return ret; | 94 | return ret; |
99 | } | 95 | } |
100 | 96 | ||
101 | static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, | 97 | static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, |
102 | u8 address, u16 data) | 98 | u8 address, u16 data) |
103 | { | 99 | { |
100 | const u16 mdio_control = 0x128; | ||
101 | const u16 mdio_data = 0x12C; | ||
104 | int max_retries = 10; | 102 | int max_retries = 10; |
105 | u32 v; | 103 | u32 v; |
106 | int i; | 104 | int i; |
107 | 105 | ||
108 | /* enable mdio access to SERDES */ | 106 | v = 0x80; /* Enable Preamble Sequence */ |
109 | v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; | 107 | v |= 0x2; /* MDIO Clock Divisor */ |
110 | v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; | 108 | pcicore_write32(pc, mdio_control, v); |
111 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); | ||
112 | 109 | ||
113 | if (pc->core->id.rev >= 10) { | 110 | if (pc->core->id.rev >= 10) { |
114 | max_retries = 200; | 111 | max_retries = 200; |
115 | bcma_pcie_mdio_set_phy(pc, device); | 112 | bcma_pcie_mdio_set_phy(pc, device); |
116 | v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << | ||
117 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); | ||
118 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
119 | } else { | ||
120 | v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); | ||
121 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); | ||
122 | } | 113 | } |
123 | 114 | ||
124 | v = BCMA_CORE_PCI_MDIODATA_START; | 115 | v = (1 << 30); /* Start of Transaction */ |
125 | v |= BCMA_CORE_PCI_MDIODATA_WRITE; | 116 | v |= (1 << 28); /* Write Transaction */ |
126 | v |= BCMA_CORE_PCI_MDIODATA_TA; | 117 | v |= (1 << 17); /* Turnaround */ |
118 | if (pc->core->id.rev < 10) | ||
119 | v |= (u32)device << 22; | ||
120 | v |= (u32)address << 18; | ||
127 | v |= data; | 121 | v |= data; |
128 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); | 122 | pcicore_write32(pc, mdio_data, v); |
129 | /* Wait for the device to complete the transaction */ | 123 | /* Wait for the device to complete the transaction */ |
130 | udelay(10); | 124 | udelay(10); |
131 | for (i = 0; i < max_retries; i++) { | 125 | for (i = 0; i < max_retries; i++) { |
132 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); | 126 | v = pcicore_read32(pc, mdio_control); |
133 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) | 127 | if (v & 0x100 /* Trans complete */) |
134 | break; | 128 | break; |
135 | usleep_range(1000, 2000); | 129 | msleep(1); |
136 | } | 130 | } |
137 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); | 131 | pcicore_write32(pc, mdio_control, 0); |
138 | } | 132 | } |
139 | 133 | ||
140 | /************************************************** | 134 | /************************************************** |
@@ -143,107 +137,75 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, | |||
143 | 137 | ||
144 | static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) | 138 | static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) |
145 | { | 139 | { |
146 | u32 tmp; | 140 | return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; |
147 | |||
148 | tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG); | ||
149 | if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT) | ||
150 | return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE | | ||
151 | BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY; | ||
152 | else | ||
153 | return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE; | ||
154 | } | 141 | } |
155 | 142 | ||
156 | static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | 143 | static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) |
157 | { | 144 | { |
145 | const u8 serdes_pll_device = 0x1D; | ||
146 | const u8 serdes_rx_device = 0x1F; | ||
158 | u16 tmp; | 147 | u16 tmp; |
159 | 148 | ||
160 | bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX, | 149 | bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, |
161 | BCMA_CORE_PCI_SERDES_RX_CTRL, | 150 | bcma_pcicore_polarity_workaround(pc)); |
162 | bcma_pcicore_polarity_workaround(pc)); | 151 | tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); |
163 | tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, | 152 | if (tmp & 0x4000) |
164 | BCMA_CORE_PCI_SERDES_PLL_CTRL); | 153 | bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); |
165 | if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN) | ||
166 | bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, | ||
167 | BCMA_CORE_PCI_SERDES_PLL_CTRL, | ||
168 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); | ||
169 | } | 154 | } |
170 | 155 | ||
171 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | 156 | /************************************************** |
157 | * Init. | ||
158 | **************************************************/ | ||
159 | |||
160 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | ||
172 | { | 161 | { |
173 | struct bcma_device *core = pc->core; | 162 | bcma_pcicore_serdes_workaround(pc); |
174 | u16 val16, core_index; | ||
175 | uint regoff; | ||
176 | |||
177 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
178 | core_index = (u16)core->core_index; | ||
179 | |||
180 | val16 = pcicore_read16(pc, regoff); | ||
181 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
182 | != core_index) { | ||
183 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
184 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
185 | pcicore_write16(pc, regoff, val16); | ||
186 | } | ||
187 | } | 163 | } |
188 | 164 | ||
189 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | 165 | static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) |
190 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
191 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | ||
192 | { | 166 | { |
193 | u16 val16; | 167 | struct bcma_bus *bus = pc->core->bus; |
194 | uint regoff; | 168 | u16 chipid_top; |
195 | 169 | ||
196 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG); | 170 | chipid_top = (bus->chipinfo.id & 0xFF00); |
171 | if (chipid_top != 0x4700 && | ||
172 | chipid_top != 0x5300) | ||
173 | return false; | ||
197 | 174 | ||
198 | val16 = pcicore_read16(pc, regoff); | 175 | #ifdef CONFIG_SSB_DRIVER_PCICORE |
176 | if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) | ||
177 | return false; | ||
178 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
199 | 179 | ||
200 | if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) { | 180 | #if 0 |
201 | val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST; | 181 | /* TODO: on BCMA we use address from EROM instead of magic formula */ |
202 | pcicore_write16(pc, regoff, val16); | 182 | u32 tmp; |
203 | } | 183 | return !mips_busprobe32(tmp, (bus->mmio + |
204 | } | 184 | (pc->core->core_index * BCMA_CORE_SIZE))); |
205 | 185 | #endif | |
206 | /************************************************** | ||
207 | * Init. | ||
208 | **************************************************/ | ||
209 | 186 | ||
210 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | 187 | return true; |
211 | { | ||
212 | bcma_core_pci_fixcfg(pc); | ||
213 | bcma_pcicore_serdes_workaround(pc); | ||
214 | bcma_core_pci_config_fixup(pc); | ||
215 | } | 188 | } |
216 | 189 | ||
217 | void bcma_core_pci_init(struct bcma_drv_pci *pc) | 190 | void bcma_core_pci_init(struct bcma_drv_pci *pc) |
218 | { | 191 | { |
219 | if (pc->setup_done) | 192 | if (bcma_core_pci_is_in_hostmode(pc)) { |
220 | return; | ||
221 | |||
222 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 193 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
223 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | ||
224 | if (pc->hostmode) | ||
225 | bcma_core_pci_hostmode_init(pc); | 194 | bcma_core_pci_hostmode_init(pc); |
195 | #else | ||
196 | pr_err("Driver compiled without support for hostmode PCI\n"); | ||
226 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 197 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
227 | 198 | } else { | |
228 | if (!pc->hostmode) | ||
229 | bcma_core_pci_clientmode_init(pc); | 199 | bcma_core_pci_clientmode_init(pc); |
200 | } | ||
230 | } | 201 | } |
231 | 202 | ||
232 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, | 203 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, |
233 | bool enable) | 204 | bool enable) |
234 | { | 205 | { |
235 | struct pci_dev *pdev; | 206 | struct pci_dev *pdev = pc->core->bus->host_pci; |
236 | u32 coremask, tmp; | 207 | u32 coremask, tmp; |
237 | int err = 0; | 208 | int err; |
238 | |||
239 | if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) { | ||
240 | /* This bcma device is not on a PCI host-bus. So the IRQs are | ||
241 | * not routed through the PCI core. | ||
242 | * So we must not enable routing through the PCI core. */ | ||
243 | goto out; | ||
244 | } | ||
245 | |||
246 | pdev = pc->core->bus->host_pci; | ||
247 | 209 | ||
248 | err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); | 210 | err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); |
249 | if (err) | 211 | if (err) |
@@ -261,17 +223,3 @@ out: | |||
261 | return err; | 223 | return err; |
262 | } | 224 | } |
263 | EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); | 225 | EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); |
264 | |||
265 | void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend) | ||
266 | { | ||
267 | u32 w; | ||
268 | |||
269 | w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG); | ||
270 | if (extend) | ||
271 | w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND; | ||
272 | else | ||
273 | w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND; | ||
274 | bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w); | ||
275 | bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG); | ||
276 | } | ||
277 | EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer); | ||
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index af0c9fabee5..eb332b75ce8 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -2,599 +2,13 @@ | |||
2 | * Broadcom specific AMBA | 2 | * Broadcom specific AMBA |
3 | * PCI Core in hostmode | 3 | * PCI Core in hostmode |
4 | * | 4 | * |
5 | * Copyright 2005 - 2011, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | ||
7 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
8 | * | ||
9 | * Licensed under the GNU/GPL. See COPYING for details. | 5 | * Licensed under the GNU/GPL. See COPYING for details. |
10 | */ | 6 | */ |
11 | 7 | ||
12 | #include "bcma_private.h" | 8 | #include "bcma_private.h" |
13 | #include <linux/pci.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/bcma/bcma.h> | 9 | #include <linux/bcma/bcma.h> |
16 | #include <asm/paccess.h> | ||
17 | |||
18 | /* Probe a 32bit value on the bus and catch bus exceptions. | ||
19 | * Returns nonzero on a bus exception. | ||
20 | * This is MIPS specific */ | ||
21 | #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) | ||
22 | |||
23 | /* Assume one-hot slot wiring */ | ||
24 | #define BCMA_PCI_SLOT_MAX 16 | ||
25 | #define PCI_CONFIG_SPACE_SIZE 256 | ||
26 | |||
27 | bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | ||
28 | { | ||
29 | struct bcma_bus *bus = pc->core->bus; | ||
30 | u16 chipid_top; | ||
31 | u32 tmp; | ||
32 | |||
33 | chipid_top = (bus->chipinfo.id & 0xFF00); | ||
34 | if (chipid_top != 0x4700 && | ||
35 | chipid_top != 0x5300) | ||
36 | return false; | ||
37 | |||
38 | bcma_core_enable(pc->core, 0); | ||
39 | |||
40 | return !mips_busprobe32(tmp, pc->core->io_addr); | ||
41 | } | ||
42 | |||
43 | static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address) | ||
44 | { | ||
45 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); | ||
46 | pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); | ||
47 | return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA); | ||
48 | } | ||
49 | |||
50 | static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address, | ||
51 | u32 data) | ||
52 | { | ||
53 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); | ||
54 | pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); | ||
55 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data); | ||
56 | } | ||
57 | |||
58 | static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev, | ||
59 | unsigned int func, unsigned int off) | ||
60 | { | ||
61 | u32 addr = 0; | ||
62 | |||
63 | /* Issue config commands only when the data link is up (atleast | ||
64 | * one external pcie device is present). | ||
65 | */ | ||
66 | if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG) | ||
67 | & BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) | ||
68 | goto out; | ||
69 | |||
70 | /* Type 0 transaction */ | ||
71 | /* Slide the PCI window to the appropriate slot */ | ||
72 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); | ||
73 | /* Calculate the address */ | ||
74 | addr = pc->host_controller->host_cfg_addr; | ||
75 | addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT); | ||
76 | addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT); | ||
77 | addr |= (off & ~3); | ||
78 | |||
79 | out: | ||
80 | return addr; | ||
81 | } | ||
82 | |||
83 | static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | ||
84 | unsigned int func, unsigned int off, | ||
85 | void *buf, int len) | ||
86 | { | ||
87 | int err = -EINVAL; | ||
88 | u32 addr, val; | ||
89 | void __iomem *mmio = 0; | ||
90 | |||
91 | WARN_ON(!pc->hostmode); | ||
92 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
93 | goto out; | ||
94 | if (dev == 0) { | ||
95 | /* we support only two functions on device 0 */ | ||
96 | if (func > 1) | ||
97 | return -EINVAL; | ||
98 | |||
99 | /* accesses to config registers with offsets >= 256 | ||
100 | * requires indirect access. | ||
101 | */ | ||
102 | if (off >= PCI_CONFIG_SPACE_SIZE) { | ||
103 | addr = (func << 12); | ||
104 | addr |= (off & 0x0FFF); | ||
105 | val = bcma_pcie_read_config(pc, addr); | ||
106 | } else { | ||
107 | addr = BCMA_CORE_PCI_PCICFG0; | ||
108 | addr |= (func << 8); | ||
109 | addr |= (off & 0xfc); | ||
110 | val = pcicore_read32(pc, addr); | ||
111 | } | ||
112 | } else { | ||
113 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | ||
114 | if (unlikely(!addr)) | ||
115 | goto out; | ||
116 | err = -ENOMEM; | ||
117 | mmio = ioremap_nocache(addr, sizeof(val)); | ||
118 | if (!mmio) | ||
119 | goto out; | ||
120 | |||
121 | if (mips_busprobe32(val, mmio)) { | ||
122 | val = 0xffffffff; | ||
123 | goto unmap; | ||
124 | } | ||
125 | |||
126 | val = readl(mmio); | ||
127 | } | ||
128 | val >>= (8 * (off & 3)); | ||
129 | |||
130 | switch (len) { | ||
131 | case 1: | ||
132 | *((u8 *)buf) = (u8)val; | ||
133 | break; | ||
134 | case 2: | ||
135 | *((u16 *)buf) = (u16)val; | ||
136 | break; | ||
137 | case 4: | ||
138 | *((u32 *)buf) = (u32)val; | ||
139 | break; | ||
140 | } | ||
141 | err = 0; | ||
142 | unmap: | ||
143 | if (mmio) | ||
144 | iounmap(mmio); | ||
145 | out: | ||
146 | return err; | ||
147 | } | ||
148 | |||
149 | static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | ||
150 | unsigned int func, unsigned int off, | ||
151 | const void *buf, int len) | ||
152 | { | ||
153 | int err = -EINVAL; | ||
154 | u32 addr = 0, val = 0; | ||
155 | void __iomem *mmio = 0; | ||
156 | u16 chipid = pc->core->bus->chipinfo.id; | ||
157 | |||
158 | WARN_ON(!pc->hostmode); | ||
159 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
160 | goto out; | ||
161 | if (dev == 0) { | ||
162 | /* accesses to config registers with offsets >= 256 | ||
163 | * requires indirect access. | ||
164 | */ | ||
165 | if (off < PCI_CONFIG_SPACE_SIZE) { | ||
166 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; | ||
167 | addr |= (func << 8); | ||
168 | addr |= (off & 0xfc); | ||
169 | mmio = ioremap_nocache(addr, sizeof(val)); | ||
170 | if (!mmio) | ||
171 | goto out; | ||
172 | } | ||
173 | } else { | ||
174 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | ||
175 | if (unlikely(!addr)) | ||
176 | goto out; | ||
177 | err = -ENOMEM; | ||
178 | mmio = ioremap_nocache(addr, sizeof(val)); | ||
179 | if (!mmio) | ||
180 | goto out; | ||
181 | |||
182 | if (mips_busprobe32(val, mmio)) { | ||
183 | val = 0xffffffff; | ||
184 | goto unmap; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | switch (len) { | ||
189 | case 1: | ||
190 | val = readl(mmio); | ||
191 | val &= ~(0xFF << (8 * (off & 3))); | ||
192 | val |= *((const u8 *)buf) << (8 * (off & 3)); | ||
193 | break; | ||
194 | case 2: | ||
195 | val = readl(mmio); | ||
196 | val &= ~(0xFFFF << (8 * (off & 3))); | ||
197 | val |= *((const u16 *)buf) << (8 * (off & 3)); | ||
198 | break; | ||
199 | case 4: | ||
200 | val = *((const u32 *)buf); | ||
201 | break; | ||
202 | } | ||
203 | if (dev == 0 && !addr) { | ||
204 | /* accesses to config registers with offsets >= 256 | ||
205 | * requires indirect access. | ||
206 | */ | ||
207 | addr = (func << 12); | ||
208 | addr |= (off & 0x0FFF); | ||
209 | bcma_pcie_write_config(pc, addr, val); | ||
210 | } else { | ||
211 | writel(val, mmio); | ||
212 | |||
213 | if (chipid == BCMA_CHIP_ID_BCM4716 || | ||
214 | chipid == BCMA_CHIP_ID_BCM4748) | ||
215 | readl(mmio); | ||
216 | } | ||
217 | |||
218 | err = 0; | ||
219 | unmap: | ||
220 | if (mmio) | ||
221 | iounmap(mmio); | ||
222 | out: | ||
223 | return err; | ||
224 | } | ||
225 | |||
226 | static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus, | ||
227 | unsigned int devfn, | ||
228 | int reg, int size, u32 *val) | ||
229 | { | ||
230 | unsigned long flags; | ||
231 | int err; | ||
232 | struct bcma_drv_pci *pc; | ||
233 | struct bcma_drv_pci_host *pc_host; | ||
234 | |||
235 | pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); | ||
236 | pc = pc_host->pdev; | ||
237 | |||
238 | spin_lock_irqsave(&pc_host->cfgspace_lock, flags); | ||
239 | err = bcma_extpci_read_config(pc, PCI_SLOT(devfn), | ||
240 | PCI_FUNC(devfn), reg, val, size); | ||
241 | spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); | ||
242 | |||
243 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
244 | } | ||
245 | |||
246 | static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus, | ||
247 | unsigned int devfn, | ||
248 | int reg, int size, u32 val) | ||
249 | { | ||
250 | unsigned long flags; | ||
251 | int err; | ||
252 | struct bcma_drv_pci *pc; | ||
253 | struct bcma_drv_pci_host *pc_host; | ||
254 | |||
255 | pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); | ||
256 | pc = pc_host->pdev; | ||
257 | |||
258 | spin_lock_irqsave(&pc_host->cfgspace_lock, flags); | ||
259 | err = bcma_extpci_write_config(pc, PCI_SLOT(devfn), | ||
260 | PCI_FUNC(devfn), reg, &val, size); | ||
261 | spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); | ||
262 | |||
263 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
264 | } | ||
265 | |||
266 | /* return cap_offset if requested capability exists in the PCI config space */ | ||
267 | static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev, | ||
268 | unsigned int func, u8 req_cap_id, | ||
269 | unsigned char *buf, u32 *buflen) | ||
270 | { | ||
271 | u8 cap_id; | ||
272 | u8 cap_ptr = 0; | ||
273 | u32 bufsize; | ||
274 | u8 byte_val; | ||
275 | |||
276 | /* check for Header type 0 */ | ||
277 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, | ||
278 | sizeof(u8)); | ||
279 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | ||
280 | return cap_ptr; | ||
281 | |||
282 | /* check if the capability pointer field exists */ | ||
283 | bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, | ||
284 | sizeof(u8)); | ||
285 | if (!(byte_val & PCI_STATUS_CAP_LIST)) | ||
286 | return cap_ptr; | ||
287 | |||
288 | /* check if the capability pointer is 0x00 */ | ||
289 | bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, | ||
290 | sizeof(u8)); | ||
291 | if (cap_ptr == 0x00) | ||
292 | return cap_ptr; | ||
293 | |||
294 | /* loop thr'u the capability list and see if the requested capabilty | ||
295 | * exists */ | ||
296 | bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); | ||
297 | while (cap_id != req_cap_id) { | ||
298 | bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, | ||
299 | sizeof(u8)); | ||
300 | if (cap_ptr == 0x00) | ||
301 | return cap_ptr; | ||
302 | bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, | ||
303 | sizeof(u8)); | ||
304 | } | ||
305 | |||
306 | /* found the caller requested capability */ | ||
307 | if ((buf != NULL) && (buflen != NULL)) { | ||
308 | u8 cap_data; | ||
309 | |||
310 | bufsize = *buflen; | ||
311 | if (!bufsize) | ||
312 | return cap_ptr; | ||
313 | |||
314 | *buflen = 0; | ||
315 | |||
316 | /* copy the cpability data excluding cap ID and next ptr */ | ||
317 | cap_data = cap_ptr + 2; | ||
318 | if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE) | ||
319 | bufsize = PCI_CONFIG_SPACE_SIZE - cap_data; | ||
320 | *buflen = bufsize; | ||
321 | while (bufsize--) { | ||
322 | bcma_extpci_read_config(pc, dev, func, cap_data, buf, | ||
323 | sizeof(u8)); | ||
324 | cap_data++; | ||
325 | buf++; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return cap_ptr; | ||
330 | } | ||
331 | |||
332 | /* If the root port is capable of returning Config Request | ||
333 | * Retry Status (CRS) Completion Status to software then | ||
334 | * enable the feature. | ||
335 | */ | ||
336 | static void bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) | ||
337 | { | ||
338 | struct bcma_bus *bus = pc->core->bus; | ||
339 | u8 cap_ptr, root_ctrl, root_cap, dev; | ||
340 | u16 val16; | ||
341 | int i; | ||
342 | |||
343 | cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL, | ||
344 | NULL); | ||
345 | root_cap = cap_ptr + PCI_EXP_RTCAP; | ||
346 | bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16)); | ||
347 | if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) { | ||
348 | /* Enable CRS software visibility */ | ||
349 | root_ctrl = cap_ptr + PCI_EXP_RTCTL; | ||
350 | val16 = PCI_EXP_RTCTL_CRSSVE; | ||
351 | bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16, | ||
352 | sizeof(u16)); | ||
353 | |||
354 | /* Initiate a configuration request to read the vendor id | ||
355 | * field of the device function's config space header after | ||
356 | * 100 ms wait time from the end of Reset. If the device is | ||
357 | * not done with its internal initialization, it must at | ||
358 | * least return a completion TLP, with a completion status | ||
359 | * of "Configuration Request Retry Status (CRS)". The root | ||
360 | * complex must complete the request to the host by returning | ||
361 | * a read-data value of 0001h for the Vendor ID field and | ||
362 | * all 1s for any additional bytes included in the request. | ||
363 | * Poll using the config reads for max wait time of 1 sec or | ||
364 | * until we receive the successful completion status. Repeat | ||
365 | * the procedure for all the devices. | ||
366 | */ | ||
367 | for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { | ||
368 | for (i = 0; i < 100000; i++) { | ||
369 | bcma_extpci_read_config(pc, dev, 0, | ||
370 | PCI_VENDOR_ID, &val16, | ||
371 | sizeof(val16)); | ||
372 | if (val16 != 0x1) | ||
373 | break; | ||
374 | udelay(10); | ||
375 | } | ||
376 | if (val16 == 0x1) | ||
377 | bcma_err(bus, "PCI: Broken device in slot %d\n", | ||
378 | dev); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | 10 | ||
383 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | 11 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) |
384 | { | 12 | { |
385 | struct bcma_bus *bus = pc->core->bus; | 13 | pr_err("No support for PCI core in hostmode yet\n"); |
386 | struct bcma_drv_pci_host *pc_host; | ||
387 | u32 tmp; | ||
388 | u32 pci_membase_1G; | ||
389 | unsigned long io_map_base; | ||
390 | |||
391 | bcma_info(bus, "PCIEcore in host mode found\n"); | ||
392 | |||
393 | if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | ||
394 | bcma_info(bus, "This PCIE core is disabled and not working\n"); | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); | ||
399 | if (!pc_host) { | ||
400 | bcma_err(bus, "can not allocate memory"); | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | pc->host_controller = pc_host; | ||
405 | pc_host->pci_controller.io_resource = &pc_host->io_resource; | ||
406 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; | ||
407 | pc_host->pci_controller.pci_ops = &pc_host->pci_ops; | ||
408 | pc_host->pdev = pc; | ||
409 | |||
410 | pci_membase_1G = BCMA_SOC_PCI_DMA; | ||
411 | pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG; | ||
412 | |||
413 | pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config; | ||
414 | pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config; | ||
415 | |||
416 | pc_host->mem_resource.name = "BCMA PCIcore external memory", | ||
417 | pc_host->mem_resource.start = BCMA_SOC_PCI_DMA; | ||
418 | pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1; | ||
419 | pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; | ||
420 | |||
421 | pc_host->io_resource.name = "BCMA PCIcore external I/O", | ||
422 | pc_host->io_resource.start = 0x100; | ||
423 | pc_host->io_resource.end = 0x7FF; | ||
424 | pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; | ||
425 | |||
426 | /* Reset RC */ | ||
427 | usleep_range(3000, 5000); | ||
428 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); | ||
429 | usleep_range(1000, 2000); | ||
430 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | | ||
431 | BCMA_CORE_PCI_CTL_RST_OE); | ||
432 | |||
433 | /* 64 MB I/O access window. On 4716, use | ||
434 | * sbtopcie0 to access the device registers. We | ||
435 | * can't use address match 2 (1 GB window) region | ||
436 | * as mips can't generate 64-bit address on the | ||
437 | * backplane. | ||
438 | */ | ||
439 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 || | ||
440 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) { | ||
441 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; | ||
442 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + | ||
443 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
444 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
445 | BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); | ||
446 | } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | ||
447 | tmp = BCMA_CORE_PCI_SBTOPCI_MEM; | ||
448 | tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; | ||
449 | tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; | ||
450 | if (pc->core->core_unit == 0) { | ||
451 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; | ||
452 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + | ||
453 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
454 | pc_host->io_resource.start = 0x100; | ||
455 | pc_host->io_resource.end = 0x47F; | ||
456 | pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; | ||
457 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
458 | tmp | BCMA_SOC_PCI_MEM); | ||
459 | } else if (pc->core->core_unit == 1) { | ||
460 | pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; | ||
461 | pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + | ||
462 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
463 | pc_host->io_resource.start = 0x480; | ||
464 | pc_host->io_resource.end = 0x7FF; | ||
465 | pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; | ||
466 | pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; | ||
467 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
468 | tmp | BCMA_SOC_PCI1_MEM); | ||
469 | } | ||
470 | } else | ||
471 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
472 | BCMA_CORE_PCI_SBTOPCI_IO); | ||
473 | |||
474 | /* 64 MB configuration access window */ | ||
475 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); | ||
476 | |||
477 | /* 1 GB memory access window */ | ||
478 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2, | ||
479 | BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G); | ||
480 | |||
481 | |||
482 | /* As per PCI Express Base Spec 1.1 we need to wait for | ||
483 | * at least 100 ms from the end of a reset (cold/warm/hot) | ||
484 | * before issuing configuration requests to PCI Express | ||
485 | * devices. | ||
486 | */ | ||
487 | msleep(100); | ||
488 | |||
489 | bcma_core_pci_enable_crs(pc); | ||
490 | |||
491 | /* Enable PCI bridge BAR0 memory & master access */ | ||
492 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | ||
493 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); | ||
494 | |||
495 | /* Enable PCI interrupts */ | ||
496 | pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA); | ||
497 | |||
498 | /* Ok, ready to run, register it to the system. | ||
499 | * The following needs change, if we want to port hostmode | ||
500 | * to non-MIPS platform. */ | ||
501 | io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start, | ||
502 | resource_size(&pc_host->mem_resource)); | ||
503 | pc_host->pci_controller.io_map_base = io_map_base; | ||
504 | set_io_port_base(pc_host->pci_controller.io_map_base); | ||
505 | /* Give some time to the PCI controller to configure itself with the new | ||
506 | * values. Not waiting at this point causes crashes of the machine. */ | ||
507 | usleep_range(10000, 15000); | ||
508 | register_pci_controller(&pc_host->pci_controller); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | /* Early PCI fixup for a device on the PCI-core bridge. */ | ||
513 | static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev) | ||
514 | { | ||
515 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
516 | /* This is not a device on the PCI-core bridge. */ | ||
517 | return; | ||
518 | } | ||
519 | if (PCI_SLOT(dev->devfn) != 0) | ||
520 | return; | ||
521 | |||
522 | pr_info("PCI: Fixing up bridge %s\n", pci_name(dev)); | ||
523 | |||
524 | /* Enable PCI bridge bus mastering and memory space */ | ||
525 | pci_set_master(dev); | ||
526 | if (pcibios_enable_device(dev, ~0) < 0) { | ||
527 | pr_err("PCI: BCMA bridge enable failed\n"); | ||
528 | return; | ||
529 | } | ||
530 | |||
531 | /* Enable PCI bridge BAR1 prefetch and burst */ | ||
532 | pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3); | ||
533 | } | ||
534 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); | ||
535 | |||
536 | /* Early PCI fixup for all PCI-cores to set the correct memory address. */ | ||
537 | static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) | ||
538 | { | ||
539 | struct resource *res; | ||
540 | int pos, err; | ||
541 | |||
542 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
543 | /* This is not a device on the PCI-core bridge. */ | ||
544 | return; | ||
545 | } | ||
546 | if (PCI_SLOT(dev->devfn) == 0) | ||
547 | return; | ||
548 | |||
549 | pr_info("PCI: Fixing up addresses %s\n", pci_name(dev)); | ||
550 | |||
551 | for (pos = 0; pos < 6; pos++) { | ||
552 | res = &dev->resource[pos]; | ||
553 | if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) { | ||
554 | err = pci_assign_resource(dev, pos); | ||
555 | if (err) | ||
556 | pr_err("PCI: Problem fixing up the addresses on %s\n", | ||
557 | pci_name(dev)); | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); | ||
562 | |||
563 | /* This function is called when doing a pci_enable_device(). | ||
564 | * We must first check if the device is a device on the PCI-core bridge. */ | ||
565 | int bcma_core_pci_plat_dev_init(struct pci_dev *dev) | ||
566 | { | ||
567 | struct bcma_drv_pci_host *pc_host; | ||
568 | |||
569 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
570 | /* This is not a device on the PCI-core bridge. */ | ||
571 | return -ENODEV; | ||
572 | } | ||
573 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | ||
574 | pci_ops); | ||
575 | |||
576 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); | ||
577 | |||
578 | /* Fix up interrupt lines */ | ||
579 | dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; | ||
580 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); | ||
585 | |||
586 | /* PCI device IRQ mapping. */ | ||
587 | int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) | ||
588 | { | ||
589 | struct bcma_drv_pci_host *pc_host; | ||
590 | |||
591 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
592 | /* This is not a device on the PCI-core bridge. */ | ||
593 | return -ENODEV; | ||
594 | } | ||
595 | |||
596 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | ||
597 | pci_ops); | ||
598 | return bcma_core_mips_irq(pc_host->pdev->core) + 2; | ||
599 | } | 14 | } |
600 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); | ||
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index fbf2759e7e4..ac4bc626c14 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/bcma/bcma.h> | 10 | #include <linux/bcma/bcma.h> |
11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <linux/module.h> | ||
13 | 12 | ||
14 | static void bcma_host_pci_switch_core(struct bcma_device *core) | 13 | static void bcma_host_pci_switch_core(struct bcma_device *core) |
15 | { | 14 | { |
@@ -18,67 +17,57 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) | |||
18 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, | 17 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, |
19 | core->wrap); | 18 | core->wrap); |
20 | core->bus->mapped_core = core; | 19 | core->bus->mapped_core = core; |
21 | bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); | 20 | pr_debug("Switched to core: 0x%X\n", core->id.id); |
22 | } | 21 | } |
23 | 22 | ||
24 | /* Provides access to the requested core. Returns base offset that has to be | 23 | static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) |
25 | * used. It makes use of fixed windows when possible. */ | ||
26 | static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core) | ||
27 | { | 24 | { |
28 | switch (core->id.id) { | ||
29 | case BCMA_CORE_CHIPCOMMON: | ||
30 | return 3 * BCMA_CORE_SIZE; | ||
31 | case BCMA_CORE_PCIE: | ||
32 | return 2 * BCMA_CORE_SIZE; | ||
33 | } | ||
34 | |||
35 | if (core->bus->mapped_core != core) | 25 | if (core->bus->mapped_core != core) |
36 | bcma_host_pci_switch_core(core); | 26 | bcma_host_pci_switch_core(core); |
37 | return 0; | ||
38 | } | ||
39 | |||
40 | static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) | ||
41 | { | ||
42 | offset += bcma_host_pci_provide_access_to_core(core); | ||
43 | return ioread8(core->bus->mmio + offset); | 27 | return ioread8(core->bus->mmio + offset); |
44 | } | 28 | } |
45 | 29 | ||
46 | static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) | 30 | static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) |
47 | { | 31 | { |
48 | offset += bcma_host_pci_provide_access_to_core(core); | 32 | if (core->bus->mapped_core != core) |
33 | bcma_host_pci_switch_core(core); | ||
49 | return ioread16(core->bus->mmio + offset); | 34 | return ioread16(core->bus->mmio + offset); |
50 | } | 35 | } |
51 | 36 | ||
52 | static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) | 37 | static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) |
53 | { | 38 | { |
54 | offset += bcma_host_pci_provide_access_to_core(core); | 39 | if (core->bus->mapped_core != core) |
40 | bcma_host_pci_switch_core(core); | ||
55 | return ioread32(core->bus->mmio + offset); | 41 | return ioread32(core->bus->mmio + offset); |
56 | } | 42 | } |
57 | 43 | ||
58 | static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, | 44 | static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, |
59 | u8 value) | 45 | u8 value) |
60 | { | 46 | { |
61 | offset += bcma_host_pci_provide_access_to_core(core); | 47 | if (core->bus->mapped_core != core) |
48 | bcma_host_pci_switch_core(core); | ||
62 | iowrite8(value, core->bus->mmio + offset); | 49 | iowrite8(value, core->bus->mmio + offset); |
63 | } | 50 | } |
64 | 51 | ||
65 | static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, | 52 | static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, |
66 | u16 value) | 53 | u16 value) |
67 | { | 54 | { |
68 | offset += bcma_host_pci_provide_access_to_core(core); | 55 | if (core->bus->mapped_core != core) |
56 | bcma_host_pci_switch_core(core); | ||
69 | iowrite16(value, core->bus->mmio + offset); | 57 | iowrite16(value, core->bus->mmio + offset); |
70 | } | 58 | } |
71 | 59 | ||
72 | static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, | 60 | static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, |
73 | u32 value) | 61 | u32 value) |
74 | { | 62 | { |
75 | offset += bcma_host_pci_provide_access_to_core(core); | 63 | if (core->bus->mapped_core != core) |
64 | bcma_host_pci_switch_core(core); | ||
76 | iowrite32(value, core->bus->mmio + offset); | 65 | iowrite32(value, core->bus->mmio + offset); |
77 | } | 66 | } |
78 | 67 | ||
79 | #ifdef CONFIG_BCMA_BLOCKIO | 68 | #ifdef CONFIG_BCMA_BLOCKIO |
80 | static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, | 69 | void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, |
81 | size_t count, u16 offset, u8 reg_width) | 70 | size_t count, u16 offset, u8 reg_width) |
82 | { | 71 | { |
83 | void __iomem *addr = core->bus->mmio + offset; | 72 | void __iomem *addr = core->bus->mmio + offset; |
84 | if (core->bus->mapped_core != core) | 73 | if (core->bus->mapped_core != core) |
@@ -100,9 +89,8 @@ static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, | |||
100 | } | 89 | } |
101 | } | 90 | } |
102 | 91 | ||
103 | static void bcma_host_pci_block_write(struct bcma_device *core, | 92 | void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, |
104 | const void *buffer, size_t count, | 93 | size_t count, u16 offset, u8 reg_width) |
105 | u16 offset, u8 reg_width) | ||
106 | { | 94 | { |
107 | void __iomem *addr = core->bus->mmio + offset; | 95 | void __iomem *addr = core->bus->mmio + offset; |
108 | if (core->bus->mapped_core != core) | 96 | if (core->bus->mapped_core != core) |
@@ -140,7 +128,7 @@ static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, | |||
140 | iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); | 128 | iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); |
141 | } | 129 | } |
142 | 130 | ||
143 | static const struct bcma_host_ops bcma_host_pci_ops = { | 131 | const struct bcma_host_ops bcma_host_pci_ops = { |
144 | .read8 = bcma_host_pci_read8, | 132 | .read8 = bcma_host_pci_read8, |
145 | .read16 = bcma_host_pci_read16, | 133 | .read16 = bcma_host_pci_read16, |
146 | .read32 = bcma_host_pci_read32, | 134 | .read32 = bcma_host_pci_read32, |
@@ -156,7 +144,7 @@ static const struct bcma_host_ops bcma_host_pci_ops = { | |||
156 | }; | 144 | }; |
157 | 145 | ||
158 | static int bcma_host_pci_probe(struct pci_dev *dev, | 146 | static int bcma_host_pci_probe(struct pci_dev *dev, |
159 | const struct pci_device_id *id) | 147 | const struct pci_device_id *id) |
160 | { | 148 | { |
161 | struct bcma_bus *bus; | 149 | struct bcma_bus *bus; |
162 | int err = -ENOMEM; | 150 | int err = -ENOMEM; |
@@ -189,7 +177,7 @@ static int bcma_host_pci_probe(struct pci_dev *dev, | |||
189 | 177 | ||
190 | /* SSB needed additional powering up, do we have any AMBA PCI cards? */ | 178 | /* SSB needed additional powering up, do we have any AMBA PCI cards? */ |
191 | if (!pci_is_pcie(dev)) | 179 | if (!pci_is_pcie(dev)) |
192 | bcma_err(bus, "PCI card detected, report problems.\n"); | 180 | pr_err("PCI card detected, report problems.\n"); |
193 | 181 | ||
194 | /* Map MMIO */ | 182 | /* Map MMIO */ |
195 | err = -ENOMEM; | 183 | err = -ENOMEM; |
@@ -202,9 +190,6 @@ static int bcma_host_pci_probe(struct pci_dev *dev, | |||
202 | bus->hosttype = BCMA_HOSTTYPE_PCI; | 190 | bus->hosttype = BCMA_HOSTTYPE_PCI; |
203 | bus->ops = &bcma_host_pci_ops; | 191 | bus->ops = &bcma_host_pci_ops; |
204 | 192 | ||
205 | bus->boardinfo.vendor = bus->host_pci->subsystem_vendor; | ||
206 | bus->boardinfo.type = bus->host_pci->subsystem_device; | ||
207 | |||
208 | /* Register */ | 193 | /* Register */ |
209 | err = bcma_bus_register(bus); | 194 | err = bcma_bus_register(bus); |
210 | if (err) | 195 | if (err) |
@@ -238,43 +223,11 @@ static void bcma_host_pci_remove(struct pci_dev *dev) | |||
238 | pci_set_drvdata(dev, NULL); | 223 | pci_set_drvdata(dev, NULL); |
239 | } | 224 | } |
240 | 225 | ||
241 | #ifdef CONFIG_PM_SLEEP | ||
242 | static int bcma_host_pci_suspend(struct device *dev) | ||
243 | { | ||
244 | struct pci_dev *pdev = to_pci_dev(dev); | ||
245 | struct bcma_bus *bus = pci_get_drvdata(pdev); | ||
246 | |||
247 | bus->mapped_core = NULL; | ||
248 | |||
249 | return bcma_bus_suspend(bus); | ||
250 | } | ||
251 | |||
252 | static int bcma_host_pci_resume(struct device *dev) | ||
253 | { | ||
254 | struct pci_dev *pdev = to_pci_dev(dev); | ||
255 | struct bcma_bus *bus = pci_get_drvdata(pdev); | ||
256 | |||
257 | return bcma_bus_resume(bus); | ||
258 | } | ||
259 | |||
260 | static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, | ||
261 | bcma_host_pci_resume); | ||
262 | #define BCMA_PM_OPS (&bcma_pm_ops) | ||
263 | |||
264 | #else /* CONFIG_PM_SLEEP */ | ||
265 | |||
266 | #define BCMA_PM_OPS NULL | ||
267 | |||
268 | #endif /* CONFIG_PM_SLEEP */ | ||
269 | |||
270 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { | 226 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { |
271 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, | 227 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, |
272 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, | ||
273 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, | 228 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, |
274 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, | 229 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, |
275 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, | 230 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, |
276 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, | ||
277 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, | ||
278 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, | 231 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, |
279 | { 0, }, | 232 | { 0, }, |
280 | }; | 233 | }; |
@@ -285,7 +238,6 @@ static struct pci_driver bcma_pci_bridge_driver = { | |||
285 | .id_table = bcma_pci_bridge_tbl, | 238 | .id_table = bcma_pci_bridge_tbl, |
286 | .probe = bcma_host_pci_probe, | 239 | .probe = bcma_host_pci_probe, |
287 | .remove = bcma_host_pci_remove, | 240 | .remove = bcma_host_pci_remove, |
288 | .driver.pm = BCMA_PM_OPS, | ||
289 | }; | 241 | }; |
290 | 242 | ||
291 | int __init bcma_host_pci_init(void) | 243 | int __init bcma_host_pci_init(void) |
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c deleted file mode 100644 index 3475e600011..00000000000 --- a/drivers/bcma/host_soc.c +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * System on Chip (SoC) Host | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | #include "scan.h" | ||
10 | #include <linux/bcma/bcma.h> | ||
11 | #include <linux/bcma/bcma_soc.h> | ||
12 | |||
13 | static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset) | ||
14 | { | ||
15 | return readb(core->io_addr + offset); | ||
16 | } | ||
17 | |||
18 | static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset) | ||
19 | { | ||
20 | return readw(core->io_addr + offset); | ||
21 | } | ||
22 | |||
23 | static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset) | ||
24 | { | ||
25 | return readl(core->io_addr + offset); | ||
26 | } | ||
27 | |||
28 | static void bcma_host_soc_write8(struct bcma_device *core, u16 offset, | ||
29 | u8 value) | ||
30 | { | ||
31 | writeb(value, core->io_addr + offset); | ||
32 | } | ||
33 | |||
34 | static void bcma_host_soc_write16(struct bcma_device *core, u16 offset, | ||
35 | u16 value) | ||
36 | { | ||
37 | writew(value, core->io_addr + offset); | ||
38 | } | ||
39 | |||
40 | static void bcma_host_soc_write32(struct bcma_device *core, u16 offset, | ||
41 | u32 value) | ||
42 | { | ||
43 | writel(value, core->io_addr + offset); | ||
44 | } | ||
45 | |||
46 | #ifdef CONFIG_BCMA_BLOCKIO | ||
47 | static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer, | ||
48 | size_t count, u16 offset, u8 reg_width) | ||
49 | { | ||
50 | void __iomem *addr = core->io_addr + offset; | ||
51 | |||
52 | switch (reg_width) { | ||
53 | case sizeof(u8): { | ||
54 | u8 *buf = buffer; | ||
55 | |||
56 | while (count) { | ||
57 | *buf = __raw_readb(addr); | ||
58 | buf++; | ||
59 | count--; | ||
60 | } | ||
61 | break; | ||
62 | } | ||
63 | case sizeof(u16): { | ||
64 | __le16 *buf = buffer; | ||
65 | |||
66 | WARN_ON(count & 1); | ||
67 | while (count) { | ||
68 | *buf = (__force __le16)__raw_readw(addr); | ||
69 | buf++; | ||
70 | count -= 2; | ||
71 | } | ||
72 | break; | ||
73 | } | ||
74 | case sizeof(u32): { | ||
75 | __le32 *buf = buffer; | ||
76 | |||
77 | WARN_ON(count & 3); | ||
78 | while (count) { | ||
79 | *buf = (__force __le32)__raw_readl(addr); | ||
80 | buf++; | ||
81 | count -= 4; | ||
82 | } | ||
83 | break; | ||
84 | } | ||
85 | default: | ||
86 | WARN_ON(1); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void bcma_host_soc_block_write(struct bcma_device *core, | ||
91 | const void *buffer, | ||
92 | size_t count, u16 offset, u8 reg_width) | ||
93 | { | ||
94 | void __iomem *addr = core->io_addr + offset; | ||
95 | |||
96 | switch (reg_width) { | ||
97 | case sizeof(u8): { | ||
98 | const u8 *buf = buffer; | ||
99 | |||
100 | while (count) { | ||
101 | __raw_writeb(*buf, addr); | ||
102 | buf++; | ||
103 | count--; | ||
104 | } | ||
105 | break; | ||
106 | } | ||
107 | case sizeof(u16): { | ||
108 | const __le16 *buf = buffer; | ||
109 | |||
110 | WARN_ON(count & 1); | ||
111 | while (count) { | ||
112 | __raw_writew((__force u16)(*buf), addr); | ||
113 | buf++; | ||
114 | count -= 2; | ||
115 | } | ||
116 | break; | ||
117 | } | ||
118 | case sizeof(u32): { | ||
119 | const __le32 *buf = buffer; | ||
120 | |||
121 | WARN_ON(count & 3); | ||
122 | while (count) { | ||
123 | __raw_writel((__force u32)(*buf), addr); | ||
124 | buf++; | ||
125 | count -= 4; | ||
126 | } | ||
127 | break; | ||
128 | } | ||
129 | default: | ||
130 | WARN_ON(1); | ||
131 | } | ||
132 | } | ||
133 | #endif /* CONFIG_BCMA_BLOCKIO */ | ||
134 | |||
135 | static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset) | ||
136 | { | ||
137 | return readl(core->io_wrap + offset); | ||
138 | } | ||
139 | |||
140 | static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset, | ||
141 | u32 value) | ||
142 | { | ||
143 | writel(value, core->io_wrap + offset); | ||
144 | } | ||
145 | |||
146 | static const struct bcma_host_ops bcma_host_soc_ops = { | ||
147 | .read8 = bcma_host_soc_read8, | ||
148 | .read16 = bcma_host_soc_read16, | ||
149 | .read32 = bcma_host_soc_read32, | ||
150 | .write8 = bcma_host_soc_write8, | ||
151 | .write16 = bcma_host_soc_write16, | ||
152 | .write32 = bcma_host_soc_write32, | ||
153 | #ifdef CONFIG_BCMA_BLOCKIO | ||
154 | .block_read = bcma_host_soc_block_read, | ||
155 | .block_write = bcma_host_soc_block_write, | ||
156 | #endif | ||
157 | .aread32 = bcma_host_soc_aread32, | ||
158 | .awrite32 = bcma_host_soc_awrite32, | ||
159 | }; | ||
160 | |||
161 | int __init bcma_host_soc_register(struct bcma_soc *soc) | ||
162 | { | ||
163 | struct bcma_bus *bus = &soc->bus; | ||
164 | int err; | ||
165 | |||
166 | /* iomap only first core. We have to read some register on this core | ||
167 | * to scan the bus. | ||
168 | */ | ||
169 | bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); | ||
170 | if (!bus->mmio) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | /* Host specific */ | ||
174 | bus->hosttype = BCMA_HOSTTYPE_SOC; | ||
175 | bus->ops = &bcma_host_soc_ops; | ||
176 | |||
177 | /* Register */ | ||
178 | err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); | ||
179 | if (err) | ||
180 | iounmap(bus->mmio); | ||
181 | |||
182 | return err; | ||
183 | } | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 4a92f647b58..73b7b1a18fa 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -6,20 +6,12 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bcma_private.h" | 8 | #include "bcma_private.h" |
9 | #include <linux/module.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/bcma/bcma.h> | 9 | #include <linux/bcma/bcma.h> |
12 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
13 | 11 | ||
14 | MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); | 12 | MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); |
15 | MODULE_LICENSE("GPL"); | 13 | MODULE_LICENSE("GPL"); |
16 | 14 | ||
17 | /* contains the number the next bus should get. */ | ||
18 | static unsigned int bcma_bus_next_num = 0; | ||
19 | |||
20 | /* bcma_buses_mutex locks the bcma_bus_next_num */ | ||
21 | static DEFINE_MUTEX(bcma_buses_mutex); | ||
22 | |||
23 | static int bcma_bus_match(struct device *dev, struct device_driver *drv); | 15 | static int bcma_bus_match(struct device *dev, struct device_driver *drv); |
24 | static int bcma_device_probe(struct device *dev); | 16 | static int bcma_device_probe(struct device *dev); |
25 | static int bcma_device_remove(struct device *dev); | 17 | static int bcma_device_remove(struct device *dev); |
@@ -62,14 +54,7 @@ static struct bus_type bcma_bus_type = { | |||
62 | .dev_attrs = bcma_device_attrs, | 54 | .dev_attrs = bcma_device_attrs, |
63 | }; | 55 | }; |
64 | 56 | ||
65 | static u16 bcma_cc_core_id(struct bcma_bus *bus) | 57 | static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) |
66 | { | ||
67 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) | ||
68 | return BCMA_CORE_4706_CHIPCOMMON; | ||
69 | return BCMA_CORE_CHIPCOMMON; | ||
70 | } | ||
71 | |||
72 | struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) | ||
73 | { | 58 | { |
74 | struct bcma_device *core; | 59 | struct bcma_device *core; |
75 | 60 | ||
@@ -79,27 +64,10 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) | |||
79 | } | 64 | } |
80 | return NULL; | 65 | return NULL; |
81 | } | 66 | } |
82 | EXPORT_SYMBOL_GPL(bcma_find_core); | ||
83 | |||
84 | static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, | ||
85 | u8 unit) | ||
86 | { | ||
87 | struct bcma_device *core; | ||
88 | |||
89 | list_for_each_entry(core, &bus->cores, list) { | ||
90 | if (core->id.id == coreid && core->core_unit == unit) | ||
91 | return core; | ||
92 | } | ||
93 | return NULL; | ||
94 | } | ||
95 | 67 | ||
96 | static void bcma_release_core_dev(struct device *dev) | 68 | static void bcma_release_core_dev(struct device *dev) |
97 | { | 69 | { |
98 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | 70 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); |
99 | if (core->io_addr) | ||
100 | iounmap(core->io_addr); | ||
101 | if (core->io_wrap) | ||
102 | iounmap(core->io_wrap); | ||
103 | kfree(core); | 71 | kfree(core); |
104 | } | 72 | } |
105 | 73 | ||
@@ -111,18 +79,15 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
111 | list_for_each_entry(core, &bus->cores, list) { | 79 | list_for_each_entry(core, &bus->cores, list) { |
112 | /* We support that cores ourself */ | 80 | /* We support that cores ourself */ |
113 | switch (core->id.id) { | 81 | switch (core->id.id) { |
114 | case BCMA_CORE_4706_CHIPCOMMON: | ||
115 | case BCMA_CORE_CHIPCOMMON: | 82 | case BCMA_CORE_CHIPCOMMON: |
116 | case BCMA_CORE_PCI: | 83 | case BCMA_CORE_PCI: |
117 | case BCMA_CORE_PCIE: | 84 | case BCMA_CORE_PCIE: |
118 | case BCMA_CORE_MIPS_74K: | ||
119 | case BCMA_CORE_4706_MAC_GBIT_COMMON: | ||
120 | continue; | 85 | continue; |
121 | } | 86 | } |
122 | 87 | ||
123 | core->dev.release = bcma_release_core_dev; | 88 | core->dev.release = bcma_release_core_dev; |
124 | core->dev.bus = &bcma_bus_type; | 89 | core->dev.bus = &bcma_bus_type; |
125 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); | 90 | dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); |
126 | 91 | ||
127 | switch (bus->hosttype) { | 92 | switch (bus->hosttype) { |
128 | case BCMA_HOSTTYPE_PCI: | 93 | case BCMA_HOSTTYPE_PCI: |
@@ -130,66 +95,32 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
130 | core->dma_dev = &bus->host_pci->dev; | 95 | core->dma_dev = &bus->host_pci->dev; |
131 | core->irq = bus->host_pci->irq; | 96 | core->irq = bus->host_pci->irq; |
132 | break; | 97 | break; |
133 | case BCMA_HOSTTYPE_SOC: | 98 | case BCMA_HOSTTYPE_NONE: |
134 | core->dev.dma_mask = &core->dev.coherent_dma_mask; | ||
135 | core->dma_dev = &core->dev; | ||
136 | break; | ||
137 | case BCMA_HOSTTYPE_SDIO: | 99 | case BCMA_HOSTTYPE_SDIO: |
138 | break; | 100 | break; |
139 | } | 101 | } |
140 | 102 | ||
141 | err = device_register(&core->dev); | 103 | err = device_register(&core->dev); |
142 | if (err) { | 104 | if (err) { |
143 | bcma_err(bus, | 105 | pr_err("Could not register dev for core 0x%03X\n", |
144 | "Could not register dev for core 0x%03X\n", | 106 | core->id.id); |
145 | core->id.id); | ||
146 | continue; | 107 | continue; |
147 | } | 108 | } |
148 | core->dev_registered = true; | 109 | core->dev_registered = true; |
149 | dev_id++; | 110 | dev_id++; |
150 | } | 111 | } |
151 | 112 | ||
152 | #ifdef CONFIG_BCMA_SFLASH | ||
153 | if (bus->drv_cc.sflash.present) { | ||
154 | err = platform_device_register(&bcma_sflash_dev); | ||
155 | if (err) | ||
156 | bcma_err(bus, "Error registering serial flash\n"); | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | #ifdef CONFIG_BCMA_NFLASH | ||
161 | if (bus->drv_cc.nflash.present) { | ||
162 | err = platform_device_register(&bcma_nflash_dev); | ||
163 | if (err) | ||
164 | bcma_err(bus, "Error registering NAND flash\n"); | ||
165 | } | ||
166 | #endif | ||
167 | err = bcma_gpio_init(&bus->drv_cc); | ||
168 | if (err == -ENOTSUPP) | ||
169 | bcma_debug(bus, "GPIO driver not activated\n"); | ||
170 | else if (err) | ||
171 | bcma_err(bus, "Error registering GPIO driver: %i\n", err); | ||
172 | |||
173 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | ||
174 | err = bcma_chipco_watchdog_register(&bus->drv_cc); | ||
175 | if (err) | ||
176 | bcma_err(bus, "Error registering watchdog driver\n"); | ||
177 | } | ||
178 | |||
179 | return 0; | 113 | return 0; |
180 | } | 114 | } |
181 | 115 | ||
182 | static void bcma_unregister_cores(struct bcma_bus *bus) | 116 | static void bcma_unregister_cores(struct bcma_bus *bus) |
183 | { | 117 | { |
184 | struct bcma_device *core, *tmp; | 118 | struct bcma_device *core; |
185 | 119 | ||
186 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { | 120 | list_for_each_entry(core, &bus->cores, list) { |
187 | list_del(&core->list); | ||
188 | if (core->dev_registered) | 121 | if (core->dev_registered) |
189 | device_unregister(&core->dev); | 122 | device_unregister(&core->dev); |
190 | } | 123 | } |
191 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
192 | platform_device_unregister(bus->drv_cc.watchdog); | ||
193 | } | 124 | } |
194 | 125 | ||
195 | int bcma_bus_register(struct bcma_bus *bus) | 126 | int bcma_bus_register(struct bcma_bus *bus) |
@@ -197,181 +128,49 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
197 | int err; | 128 | int err; |
198 | struct bcma_device *core; | 129 | struct bcma_device *core; |
199 | 130 | ||
200 | mutex_lock(&bcma_buses_mutex); | ||
201 | bus->num = bcma_bus_next_num++; | ||
202 | mutex_unlock(&bcma_buses_mutex); | ||
203 | |||
204 | /* Scan for devices (cores) */ | 131 | /* Scan for devices (cores) */ |
205 | err = bcma_bus_scan(bus); | 132 | err = bcma_bus_scan(bus); |
206 | if (err) { | 133 | if (err) { |
207 | bcma_err(bus, "Failed to scan: %d\n", err); | 134 | pr_err("Failed to scan: %d\n", err); |
208 | return -1; | 135 | return -1; |
209 | } | 136 | } |
210 | 137 | ||
211 | /* Early init CC core */ | ||
212 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | ||
213 | if (core) { | ||
214 | bus->drv_cc.core = core; | ||
215 | bcma_core_chipcommon_early_init(&bus->drv_cc); | ||
216 | } | ||
217 | |||
218 | /* Try to get SPROM */ | ||
219 | err = bcma_sprom_get(bus); | ||
220 | if (err == -ENOENT) { | ||
221 | bcma_err(bus, "No SPROM available\n"); | ||
222 | } else if (err) | ||
223 | bcma_err(bus, "Failed to get SPROM: %d\n", err); | ||
224 | |||
225 | /* Init CC core */ | 138 | /* Init CC core */ |
226 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | 139 | core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); |
227 | if (core) { | 140 | if (core) { |
228 | bus->drv_cc.core = core; | 141 | bus->drv_cc.core = core; |
229 | bcma_core_chipcommon_init(&bus->drv_cc); | 142 | bcma_core_chipcommon_init(&bus->drv_cc); |
230 | } | 143 | } |
231 | 144 | ||
232 | /* Init MIPS core */ | ||
233 | core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
234 | if (core) { | ||
235 | bus->drv_mips.core = core; | ||
236 | bcma_core_mips_init(&bus->drv_mips); | ||
237 | } | ||
238 | |||
239 | /* Init PCIE core */ | ||
240 | core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); | ||
241 | if (core) { | ||
242 | bus->drv_pci[0].core = core; | ||
243 | bcma_core_pci_init(&bus->drv_pci[0]); | ||
244 | } | ||
245 | |||
246 | /* Init PCIE core */ | 145 | /* Init PCIE core */ |
247 | core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); | 146 | core = bcma_find_core(bus, BCMA_CORE_PCIE); |
248 | if (core) { | 147 | if (core) { |
249 | bus->drv_pci[1].core = core; | 148 | bus->drv_pci.core = core; |
250 | bcma_core_pci_init(&bus->drv_pci[1]); | 149 | bcma_core_pci_init(&bus->drv_pci); |
251 | } | 150 | } |
252 | 151 | ||
253 | /* Init GBIT MAC COMMON core */ | 152 | /* Try to get SPROM */ |
254 | core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); | 153 | err = bcma_sprom_get(bus); |
255 | if (core) { | 154 | if (err == -ENOENT) { |
256 | bus->drv_gmac_cmn.core = core; | 155 | pr_err("No SPROM available\n"); |
257 | bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); | 156 | } else if (err) { |
157 | pr_err("Failed to get SPROM: %d\n", err); | ||
158 | return -ENOENT; | ||
258 | } | 159 | } |
259 | 160 | ||
260 | /* Register found cores */ | 161 | /* Register found cores */ |
261 | bcma_register_cores(bus); | 162 | bcma_register_cores(bus); |
262 | 163 | ||
263 | bcma_info(bus, "Bus registered\n"); | 164 | pr_info("Bus registered\n"); |
264 | 165 | ||
265 | return 0; | 166 | return 0; |
266 | } | 167 | } |
267 | 168 | ||
268 | void bcma_bus_unregister(struct bcma_bus *bus) | 169 | void bcma_bus_unregister(struct bcma_bus *bus) |
269 | { | 170 | { |
270 | struct bcma_device *cores[3]; | ||
271 | |||
272 | cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
273 | cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
274 | cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); | ||
275 | |||
276 | bcma_unregister_cores(bus); | 171 | bcma_unregister_cores(bus); |
277 | |||
278 | kfree(cores[2]); | ||
279 | kfree(cores[1]); | ||
280 | kfree(cores[0]); | ||
281 | } | 172 | } |
282 | 173 | ||
283 | int __init bcma_bus_early_register(struct bcma_bus *bus, | ||
284 | struct bcma_device *core_cc, | ||
285 | struct bcma_device *core_mips) | ||
286 | { | ||
287 | int err; | ||
288 | struct bcma_device *core; | ||
289 | struct bcma_device_id match; | ||
290 | |||
291 | bcma_init_bus(bus); | ||
292 | |||
293 | match.manuf = BCMA_MANUF_BCM; | ||
294 | match.id = bcma_cc_core_id(bus); | ||
295 | match.class = BCMA_CL_SIM; | ||
296 | match.rev = BCMA_ANY_REV; | ||
297 | |||
298 | /* Scan for chip common core */ | ||
299 | err = bcma_bus_scan_early(bus, &match, core_cc); | ||
300 | if (err) { | ||
301 | bcma_err(bus, "Failed to scan for common core: %d\n", err); | ||
302 | return -1; | ||
303 | } | ||
304 | |||
305 | match.manuf = BCMA_MANUF_MIPS; | ||
306 | match.id = BCMA_CORE_MIPS_74K; | ||
307 | match.class = BCMA_CL_SIM; | ||
308 | match.rev = BCMA_ANY_REV; | ||
309 | |||
310 | /* Scan for mips core */ | ||
311 | err = bcma_bus_scan_early(bus, &match, core_mips); | ||
312 | if (err) { | ||
313 | bcma_err(bus, "Failed to scan for mips core: %d\n", err); | ||
314 | return -1; | ||
315 | } | ||
316 | |||
317 | /* Early init CC core */ | ||
318 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | ||
319 | if (core) { | ||
320 | bus->drv_cc.core = core; | ||
321 | bcma_core_chipcommon_early_init(&bus->drv_cc); | ||
322 | } | ||
323 | |||
324 | /* Early init MIPS core */ | ||
325 | core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
326 | if (core) { | ||
327 | bus->drv_mips.core = core; | ||
328 | bcma_core_mips_early_init(&bus->drv_mips); | ||
329 | } | ||
330 | |||
331 | bcma_info(bus, "Early bus registered\n"); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | #ifdef CONFIG_PM | ||
337 | int bcma_bus_suspend(struct bcma_bus *bus) | ||
338 | { | ||
339 | struct bcma_device *core; | ||
340 | |||
341 | list_for_each_entry(core, &bus->cores, list) { | ||
342 | struct device_driver *drv = core->dev.driver; | ||
343 | if (drv) { | ||
344 | struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); | ||
345 | if (adrv->suspend) | ||
346 | adrv->suspend(core); | ||
347 | } | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | int bcma_bus_resume(struct bcma_bus *bus) | ||
353 | { | ||
354 | struct bcma_device *core; | ||
355 | |||
356 | /* Init CC core */ | ||
357 | if (bus->drv_cc.core) { | ||
358 | bus->drv_cc.setup_done = false; | ||
359 | bcma_core_chipcommon_init(&bus->drv_cc); | ||
360 | } | ||
361 | |||
362 | list_for_each_entry(core, &bus->cores, list) { | ||
363 | struct device_driver *drv = core->dev.driver; | ||
364 | if (drv) { | ||
365 | struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); | ||
366 | if (adrv->resume) | ||
367 | adrv->resume(core); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | #endif | ||
374 | |||
375 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) | 174 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) |
376 | { | 175 | { |
377 | drv->drv.name = drv->name; | 176 | drv->drv.name = drv->name; |
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 8d0b5716401..40d7dcce893 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -19,27 +19,15 @@ struct bcma_device_id_name { | |||
19 | u16 id; | 19 | u16 id; |
20 | const char *name; | 20 | const char *name; |
21 | }; | 21 | }; |
22 | 22 | struct bcma_device_id_name bcma_device_names[] = { | |
23 | static const struct bcma_device_id_name bcma_arm_device_names[] = { | ||
24 | { BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" }, | ||
25 | { BCMA_CORE_ARM_1176, "ARM 1176" }, | ||
26 | { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, | ||
27 | { BCMA_CORE_ARM_CM3, "ARM CM3" }, | ||
28 | }; | ||
29 | |||
30 | static const struct bcma_device_id_name bcma_bcm_device_names[] = { | ||
31 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, | 23 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, |
32 | { BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" }, | ||
33 | { BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" }, | ||
34 | { BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" }, | ||
35 | { BCMA_CORE_AMEMC, "AMEMC (DDR)" }, | ||
36 | { BCMA_CORE_ALTA, "ALTA (I2S)" }, | ||
37 | { BCMA_CORE_INVALID, "Invalid" }, | 24 | { BCMA_CORE_INVALID, "Invalid" }, |
38 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, | 25 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, |
39 | { BCMA_CORE_ILINE20, "ILine 20" }, | 26 | { BCMA_CORE_ILINE20, "ILine 20" }, |
40 | { BCMA_CORE_SRAM, "SRAM" }, | 27 | { BCMA_CORE_SRAM, "SRAM" }, |
41 | { BCMA_CORE_SDRAM, "SDRAM" }, | 28 | { BCMA_CORE_SDRAM, "SDRAM" }, |
42 | { BCMA_CORE_PCI, "PCI" }, | 29 | { BCMA_CORE_PCI, "PCI" }, |
30 | { BCMA_CORE_MIPS, "MIPS" }, | ||
43 | { BCMA_CORE_ETHERNET, "Fast Ethernet" }, | 31 | { BCMA_CORE_ETHERNET, "Fast Ethernet" }, |
44 | { BCMA_CORE_V90, "V90" }, | 32 | { BCMA_CORE_V90, "V90" }, |
45 | { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, | 33 | { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, |
@@ -56,6 +44,7 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { | |||
56 | { BCMA_CORE_PHY_A, "PHY A" }, | 44 | { BCMA_CORE_PHY_A, "PHY A" }, |
57 | { BCMA_CORE_PHY_B, "PHY B" }, | 45 | { BCMA_CORE_PHY_B, "PHY B" }, |
58 | { BCMA_CORE_PHY_G, "PHY G" }, | 46 | { BCMA_CORE_PHY_G, "PHY G" }, |
47 | { BCMA_CORE_MIPS_3302, "MIPS 3302" }, | ||
59 | { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, | 48 | { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, |
60 | { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, | 49 | { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, |
61 | { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, | 50 | { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, |
@@ -69,11 +58,15 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { | |||
69 | { BCMA_CORE_PHY_N, "PHY N" }, | 58 | { BCMA_CORE_PHY_N, "PHY N" }, |
70 | { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, | 59 | { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, |
71 | { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, | 60 | { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, |
61 | { BCMA_CORE_ARM_1176, "ARM 1176" }, | ||
62 | { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, | ||
72 | { BCMA_CORE_PHY_LP, "PHY LP" }, | 63 | { BCMA_CORE_PHY_LP, "PHY LP" }, |
73 | { BCMA_CORE_PMU, "PMU" }, | 64 | { BCMA_CORE_PMU, "PMU" }, |
74 | { BCMA_CORE_PHY_SSN, "PHY SSN" }, | 65 | { BCMA_CORE_PHY_SSN, "PHY SSN" }, |
75 | { BCMA_CORE_SDIO_DEV, "SDIO Device" }, | 66 | { BCMA_CORE_SDIO_DEV, "SDIO Device" }, |
67 | { BCMA_CORE_ARM_CM3, "ARM CM3" }, | ||
76 | { BCMA_CORE_PHY_HT, "PHY HT" }, | 68 | { BCMA_CORE_PHY_HT, "PHY HT" }, |
69 | { BCMA_CORE_MIPS_74K, "MIPS 74K" }, | ||
77 | { BCMA_CORE_MAC_GBIT, "GBit MAC" }, | 70 | { BCMA_CORE_MAC_GBIT, "GBit MAC" }, |
78 | { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, | 71 | { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, |
79 | { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, | 72 | { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, |
@@ -86,41 +79,16 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { | |||
86 | { BCMA_CORE_SHIM, "SHIM" }, | 79 | { BCMA_CORE_SHIM, "SHIM" }, |
87 | { BCMA_CORE_DEFAULT, "Default" }, | 80 | { BCMA_CORE_DEFAULT, "Default" }, |
88 | }; | 81 | }; |
89 | 82 | const char *bcma_device_name(struct bcma_device_id *id) | |
90 | static const struct bcma_device_id_name bcma_mips_device_names[] = { | ||
91 | { BCMA_CORE_MIPS, "MIPS" }, | ||
92 | { BCMA_CORE_MIPS_3302, "MIPS 3302" }, | ||
93 | { BCMA_CORE_MIPS_74K, "MIPS 74K" }, | ||
94 | }; | ||
95 | |||
96 | static const char *bcma_device_name(const struct bcma_device_id *id) | ||
97 | { | 83 | { |
98 | const struct bcma_device_id_name *names; | 84 | int i; |
99 | int size, i; | ||
100 | |||
101 | /* search manufacturer specific names */ | ||
102 | switch (id->manuf) { | ||
103 | case BCMA_MANUF_ARM: | ||
104 | names = bcma_arm_device_names; | ||
105 | size = ARRAY_SIZE(bcma_arm_device_names); | ||
106 | break; | ||
107 | case BCMA_MANUF_BCM: | ||
108 | names = bcma_bcm_device_names; | ||
109 | size = ARRAY_SIZE(bcma_bcm_device_names); | ||
110 | break; | ||
111 | case BCMA_MANUF_MIPS: | ||
112 | names = bcma_mips_device_names; | ||
113 | size = ARRAY_SIZE(bcma_mips_device_names); | ||
114 | break; | ||
115 | default: | ||
116 | return "UNKNOWN"; | ||
117 | } | ||
118 | 85 | ||
119 | for (i = 0; i < size; i++) { | 86 | if (id->manuf == BCMA_MANUF_BCM) { |
120 | if (names[i].id == id->id) | 87 | for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) { |
121 | return names[i].name; | 88 | if (bcma_device_names[i].id == id->id) |
89 | return bcma_device_names[i].name; | ||
90 | } | ||
122 | } | 91 | } |
123 | |||
124 | return "UNKNOWN"; | 92 | return "UNKNOWN"; |
125 | } | 93 | } |
126 | 94 | ||
@@ -232,195 +200,18 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, | |||
232 | return addrl; | 200 | return addrl; |
233 | } | 201 | } |
234 | 202 | ||
235 | static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, | 203 | int bcma_bus_scan(struct bcma_bus *bus) |
236 | u16 index) | ||
237 | { | ||
238 | struct bcma_device *core; | ||
239 | |||
240 | list_for_each_entry(core, &bus->cores, list) { | ||
241 | if (core->core_index == index) | ||
242 | return core; | ||
243 | } | ||
244 | return NULL; | ||
245 | } | ||
246 | |||
247 | static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid) | ||
248 | { | 204 | { |
249 | struct bcma_device *core; | 205 | u32 erombase; |
250 | 206 | u32 __iomem *eromptr, *eromend; | |
251 | list_for_each_entry_reverse(core, &bus->cores, list) { | ||
252 | if (core->id.id == coreid) | ||
253 | return core; | ||
254 | } | ||
255 | return NULL; | ||
256 | } | ||
257 | 207 | ||
258 | static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, | ||
259 | struct bcma_device_id *match, int core_num, | ||
260 | struct bcma_device *core) | ||
261 | { | ||
262 | s32 tmp; | ||
263 | u8 i, j; | ||
264 | s32 cia, cib; | 208 | s32 cia, cib; |
265 | u8 ports[2], wrappers[2]; | 209 | u8 ports[2], wrappers[2]; |
266 | 210 | ||
267 | /* get CIs */ | ||
268 | cia = bcma_erom_get_ci(bus, eromptr); | ||
269 | if (cia < 0) { | ||
270 | bcma_erom_push_ent(eromptr); | ||
271 | if (bcma_erom_is_end(bus, eromptr)) | ||
272 | return -ESPIPE; | ||
273 | return -EILSEQ; | ||
274 | } | ||
275 | cib = bcma_erom_get_ci(bus, eromptr); | ||
276 | if (cib < 0) | ||
277 | return -EILSEQ; | ||
278 | |||
279 | /* parse CIs */ | ||
280 | core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; | ||
281 | core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; | ||
282 | core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; | ||
283 | ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; | ||
284 | ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; | ||
285 | wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; | ||
286 | wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; | ||
287 | core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; | ||
288 | |||
289 | if (((core->id.manuf == BCMA_MANUF_ARM) && | ||
290 | (core->id.id == 0xFFF)) || | ||
291 | (ports[1] == 0)) { | ||
292 | bcma_erom_skip_component(bus, eromptr); | ||
293 | return -ENXIO; | ||
294 | } | ||
295 | |||
296 | /* check if component is a core at all */ | ||
297 | if (wrappers[0] + wrappers[1] == 0) { | ||
298 | /* Some specific cores don't need wrappers */ | ||
299 | switch (core->id.id) { | ||
300 | case BCMA_CORE_4706_MAC_GBIT_COMMON: | ||
301 | /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ | ||
302 | break; | ||
303 | default: | ||
304 | bcma_erom_skip_component(bus, eromptr); | ||
305 | return -ENXIO; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | if (bcma_erom_is_bridge(bus, eromptr)) { | ||
310 | bcma_erom_skip_component(bus, eromptr); | ||
311 | return -ENXIO; | ||
312 | } | ||
313 | |||
314 | if (bcma_find_core_by_index(bus, core_num)) { | ||
315 | bcma_erom_skip_component(bus, eromptr); | ||
316 | return -ENODEV; | ||
317 | } | ||
318 | |||
319 | if (match && ((match->manuf != BCMA_ANY_MANUF && | ||
320 | match->manuf != core->id.manuf) || | ||
321 | (match->id != BCMA_ANY_ID && match->id != core->id.id) || | ||
322 | (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) || | ||
323 | (match->class != BCMA_ANY_CLASS && match->class != core->id.class) | ||
324 | )) { | ||
325 | bcma_erom_skip_component(bus, eromptr); | ||
326 | return -ENODEV; | ||
327 | } | ||
328 | |||
329 | /* get & parse master ports */ | ||
330 | for (i = 0; i < ports[0]; i++) { | ||
331 | s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); | ||
332 | if (mst_port_d < 0) | ||
333 | return -EILSEQ; | ||
334 | } | ||
335 | |||
336 | /* First Slave Address Descriptor should be port 0: | ||
337 | * the main register space for the core | ||
338 | */ | ||
339 | tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0); | ||
340 | if (tmp <= 0) { | ||
341 | /* Try again to see if it is a bridge */ | ||
342 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
343 | SCAN_ADDR_TYPE_BRIDGE, 0); | ||
344 | if (tmp <= 0) { | ||
345 | return -EILSEQ; | ||
346 | } else { | ||
347 | bcma_info(bus, "Bridge found\n"); | ||
348 | return -ENXIO; | ||
349 | } | ||
350 | } | ||
351 | core->addr = tmp; | ||
352 | |||
353 | /* get & parse slave ports */ | ||
354 | for (i = 0; i < ports[1]; i++) { | ||
355 | for (j = 0; ; j++) { | ||
356 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
357 | SCAN_ADDR_TYPE_SLAVE, i); | ||
358 | if (tmp < 0) { | ||
359 | /* no more entries for port _i_ */ | ||
360 | /* pr_debug("erom: slave port %d " | ||
361 | * "has %d descriptors\n", i, j); */ | ||
362 | break; | ||
363 | } else { | ||
364 | if (i == 0 && j == 0) | ||
365 | core->addr1 = tmp; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | /* get & parse master wrappers */ | ||
371 | for (i = 0; i < wrappers[0]; i++) { | ||
372 | for (j = 0; ; j++) { | ||
373 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
374 | SCAN_ADDR_TYPE_MWRAP, i); | ||
375 | if (tmp < 0) { | ||
376 | /* no more entries for port _i_ */ | ||
377 | /* pr_debug("erom: master wrapper %d " | ||
378 | * "has %d descriptors\n", i, j); */ | ||
379 | break; | ||
380 | } else { | ||
381 | if (i == 0 && j == 0) | ||
382 | core->wrap = tmp; | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* get & parse slave wrappers */ | ||
388 | for (i = 0; i < wrappers[1]; i++) { | ||
389 | u8 hack = (ports[1] == 1) ? 0 : 1; | ||
390 | for (j = 0; ; j++) { | ||
391 | tmp = bcma_erom_get_addr_desc(bus, eromptr, | ||
392 | SCAN_ADDR_TYPE_SWRAP, i + hack); | ||
393 | if (tmp < 0) { | ||
394 | /* no more entries for port _i_ */ | ||
395 | /* pr_debug("erom: master wrapper %d " | ||
396 | * has %d descriptors\n", i, j); */ | ||
397 | break; | ||
398 | } else { | ||
399 | if (wrappers[0] == 0 && !i && !j) | ||
400 | core->wrap = tmp; | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | ||
405 | core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE); | ||
406 | if (!core->io_addr) | ||
407 | return -ENOMEM; | ||
408 | core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE); | ||
409 | if (!core->io_wrap) { | ||
410 | iounmap(core->io_addr); | ||
411 | return -ENOMEM; | ||
412 | } | ||
413 | } | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | void bcma_init_bus(struct bcma_bus *bus) | ||
418 | { | ||
419 | s32 tmp; | 211 | s32 tmp; |
420 | struct bcma_chipinfo *chipinfo = &(bus->chipinfo); | 212 | u8 i, j; |
421 | 213 | ||
422 | if (bus->init_done) | 214 | int err; |
423 | return; | ||
424 | 215 | ||
425 | INIT_LIST_HEAD(&bus->cores); | 216 | INIT_LIST_HEAD(&bus->cores); |
426 | bus->nr_cores = 0; | 217 | bus->nr_cores = 0; |
@@ -428,136 +219,142 @@ void bcma_init_bus(struct bcma_bus *bus) | |||
428 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); | 219 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); |
429 | 220 | ||
430 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); | 221 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); |
431 | chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; | 222 | bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; |
432 | chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; | 223 | bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; |
433 | chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; | 224 | bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; |
434 | bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", | ||
435 | chipinfo->id, chipinfo->rev, chipinfo->pkg); | ||
436 | |||
437 | bus->init_done = true; | ||
438 | } | ||
439 | |||
440 | int bcma_bus_scan(struct bcma_bus *bus) | ||
441 | { | ||
442 | u32 erombase; | ||
443 | u32 __iomem *eromptr, *eromend; | ||
444 | |||
445 | int err, core_num = 0; | ||
446 | |||
447 | bcma_init_bus(bus); | ||
448 | 225 | ||
449 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); | 226 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); |
450 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | 227 | eromptr = bus->mmio; |
451 | eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); | ||
452 | if (!eromptr) | ||
453 | return -ENOMEM; | ||
454 | } else { | ||
455 | eromptr = bus->mmio; | ||
456 | } | ||
457 | |||
458 | eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); | 228 | eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); |
459 | 229 | ||
460 | bcma_scan_switch_core(bus, erombase); | 230 | bcma_scan_switch_core(bus, erombase); |
461 | 231 | ||
462 | while (eromptr < eromend) { | 232 | while (eromptr < eromend) { |
463 | struct bcma_device *other_core; | ||
464 | struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); | 233 | struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); |
465 | if (!core) { | 234 | if (!core) |
466 | err = -ENOMEM; | 235 | return -ENOMEM; |
467 | goto out; | ||
468 | } | ||
469 | INIT_LIST_HEAD(&core->list); | 236 | INIT_LIST_HEAD(&core->list); |
470 | core->bus = bus; | 237 | core->bus = bus; |
471 | 238 | ||
472 | err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); | 239 | /* get CIs */ |
473 | if (err < 0) { | 240 | cia = bcma_erom_get_ci(bus, &eromptr); |
474 | kfree(core); | 241 | if (cia < 0) { |
475 | if (err == -ENODEV) { | 242 | bcma_erom_push_ent(&eromptr); |
476 | core_num++; | 243 | if (bcma_erom_is_end(bus, &eromptr)) |
477 | continue; | ||
478 | } else if (err == -ENXIO) { | ||
479 | continue; | ||
480 | } else if (err == -ESPIPE) { | ||
481 | break; | 244 | break; |
482 | } | 245 | err= -EILSEQ; |
246 | goto out; | ||
247 | } | ||
248 | cib = bcma_erom_get_ci(bus, &eromptr); | ||
249 | if (cib < 0) { | ||
250 | err= -EILSEQ; | ||
483 | goto out; | 251 | goto out; |
484 | } | 252 | } |
485 | 253 | ||
486 | core->core_index = core_num++; | 254 | /* parse CIs */ |
487 | bus->nr_cores++; | 255 | core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; |
488 | other_core = bcma_find_core_reverse(bus, core->id.id); | 256 | core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; |
489 | core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; | 257 | core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; |
490 | 258 | ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; | |
491 | bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | 259 | ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; |
492 | core->core_index, bcma_device_name(&core->id), | 260 | wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; |
493 | core->id.manuf, core->id.id, core->id.rev, | 261 | wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; |
494 | core->id.class); | 262 | core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; |
495 | 263 | ||
496 | list_add_tail(&core->list, &bus->cores); | 264 | if (((core->id.manuf == BCMA_MANUF_ARM) && |
497 | } | 265 | (core->id.id == 0xFFF)) || |
498 | 266 | (ports[1] == 0)) { | |
499 | err = 0; | 267 | bcma_erom_skip_component(bus, &eromptr); |
500 | out: | 268 | continue; |
501 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | 269 | } |
502 | iounmap(eromptr); | ||
503 | |||
504 | return err; | ||
505 | } | ||
506 | |||
507 | int __init bcma_bus_scan_early(struct bcma_bus *bus, | ||
508 | struct bcma_device_id *match, | ||
509 | struct bcma_device *core) | ||
510 | { | ||
511 | u32 erombase; | ||
512 | u32 __iomem *eromptr, *eromend; | ||
513 | |||
514 | int err = -ENODEV; | ||
515 | int core_num = 0; | ||
516 | 270 | ||
517 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); | 271 | /* check if component is a core at all */ |
518 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | 272 | if (wrappers[0] + wrappers[1] == 0) { |
519 | eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); | 273 | /* we could save addrl of the router |
520 | if (!eromptr) | 274 | if (cid == BCMA_CORE_OOB_ROUTER) |
521 | return -ENOMEM; | 275 | */ |
522 | } else { | 276 | bcma_erom_skip_component(bus, &eromptr); |
523 | eromptr = bus->mmio; | 277 | continue; |
524 | } | 278 | } |
525 | 279 | ||
526 | eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); | 280 | if (bcma_erom_is_bridge(bus, &eromptr)) { |
281 | bcma_erom_skip_component(bus, &eromptr); | ||
282 | continue; | ||
283 | } | ||
527 | 284 | ||
528 | bcma_scan_switch_core(bus, erombase); | 285 | /* get & parse master ports */ |
286 | for (i = 0; i < ports[0]; i++) { | ||
287 | u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); | ||
288 | if (mst_port_d < 0) { | ||
289 | err= -EILSEQ; | ||
290 | goto out; | ||
291 | } | ||
292 | } | ||
529 | 293 | ||
530 | while (eromptr < eromend) { | 294 | /* get & parse slave ports */ |
531 | memset(core, 0, sizeof(*core)); | 295 | for (i = 0; i < ports[1]; i++) { |
532 | INIT_LIST_HEAD(&core->list); | 296 | for (j = 0; ; j++) { |
533 | core->bus = bus; | 297 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, |
298 | SCAN_ADDR_TYPE_SLAVE, i); | ||
299 | if (tmp < 0) { | ||
300 | /* no more entries for port _i_ */ | ||
301 | /* pr_debug("erom: slave port %d " | ||
302 | * "has %d descriptors\n", i, j); */ | ||
303 | break; | ||
304 | } else { | ||
305 | if (i == 0 && j == 0) | ||
306 | core->addr = tmp; | ||
307 | } | ||
308 | } | ||
309 | } | ||
534 | 310 | ||
535 | err = bcma_get_next_core(bus, &eromptr, match, core_num, core); | 311 | /* get & parse master wrappers */ |
536 | if (err == -ENODEV) { | 312 | for (i = 0; i < wrappers[0]; i++) { |
537 | core_num++; | 313 | for (j = 0; ; j++) { |
538 | continue; | 314 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, |
539 | } else if (err == -ENXIO) | 315 | SCAN_ADDR_TYPE_MWRAP, i); |
540 | continue; | 316 | if (tmp < 0) { |
541 | else if (err == -ESPIPE) | 317 | /* no more entries for port _i_ */ |
542 | break; | 318 | /* pr_debug("erom: master wrapper %d " |
543 | else if (err < 0) | 319 | * "has %d descriptors\n", i, j); */ |
544 | goto out; | 320 | break; |
321 | } else { | ||
322 | if (i == 0 && j == 0) | ||
323 | core->wrap = tmp; | ||
324 | } | ||
325 | } | ||
326 | } | ||
545 | 327 | ||
546 | core->core_index = core_num++; | 328 | /* get & parse slave wrappers */ |
547 | bus->nr_cores++; | 329 | for (i = 0; i < wrappers[1]; i++) { |
548 | bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | 330 | u8 hack = (ports[1] == 1) ? 0 : 1; |
549 | core->core_index, bcma_device_name(&core->id), | 331 | for (j = 0; ; j++) { |
550 | core->id.manuf, core->id.id, core->id.rev, | 332 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, |
551 | core->id.class); | 333 | SCAN_ADDR_TYPE_SWRAP, i + hack); |
334 | if (tmp < 0) { | ||
335 | /* no more entries for port _i_ */ | ||
336 | /* pr_debug("erom: master wrapper %d " | ||
337 | * has %d descriptors\n", i, j); */ | ||
338 | break; | ||
339 | } else { | ||
340 | if (wrappers[0] == 0 && !i && !j) | ||
341 | core->wrap = tmp; | ||
342 | } | ||
343 | } | ||
344 | } | ||
552 | 345 | ||
553 | list_add_tail(&core->list, &bus->cores); | 346 | pr_info("Core %d found: %s " |
554 | err = 0; | 347 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", |
555 | break; | 348 | bus->nr_cores, bcma_device_name(&core->id), |
556 | } | 349 | core->id.manuf, core->id.id, core->id.rev, |
350 | core->id.class); | ||
557 | 351 | ||
352 | core->core_index = bus->nr_cores++; | ||
353 | list_add(&core->list, &bus->cores); | ||
354 | continue; | ||
558 | out: | 355 | out: |
559 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) | 356 | return err; |
560 | iounmap(eromptr); | 357 | } |
561 | 358 | ||
562 | return err; | 359 | return 0; |
563 | } | 360 | } |
diff --git a/drivers/bcma/scan.h b/drivers/bcma/scan.h index 30eb475e4d1..113e6a66884 100644 --- a/drivers/bcma/scan.h +++ b/drivers/bcma/scan.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define SCAN_CIB_NMW 0x0007C000 | 27 | #define SCAN_CIB_NMW 0x0007C000 |
28 | #define SCAN_CIB_NMW_SHIFT 14 | 28 | #define SCAN_CIB_NMW_SHIFT 14 |
29 | #define SCAN_CIB_NSW 0x00F80000 | 29 | #define SCAN_CIB_NSW 0x00F80000 |
30 | #define SCAN_CIB_NSW_SHIFT 19 | 30 | #define SCAN_CIB_NSW_SHIFT 17 |
31 | #define SCAN_CIB_REV 0xFF000000 | 31 | #define SCAN_CIB_REV 0xFF000000 |
32 | #define SCAN_CIB_REV_SHIFT 24 | 32 | #define SCAN_CIB_REV_SHIFT 24 |
33 | 33 | ||
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 4adf9ef9a11..8b5b7856abe 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -2,8 +2,6 @@ | |||
2 | * Broadcom specific AMBA | 2 | * Broadcom specific AMBA |
3 | * SPROM reading | 3 | * SPROM reading |
4 | * | 4 | * |
5 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
6 | * | ||
7 | * Licensed under the GNU/GPL. See COPYING for details. | 5 | * Licensed under the GNU/GPL. See COPYING for details. |
8 | */ | 6 | */ |
9 | 7 | ||
@@ -16,57 +14,7 @@ | |||
16 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
17 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
18 | 16 | ||
19 | static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out); | 17 | #define SPOFF(offset) ((offset) / sizeof(u16)) |
20 | |||
21 | /** | ||
22 | * bcma_arch_register_fallback_sprom - Registers a method providing a | ||
23 | * fallback SPROM if no SPROM is found. | ||
24 | * | ||
25 | * @sprom_callback: The callback function. | ||
26 | * | ||
27 | * With this function the architecture implementation may register a | ||
28 | * callback handler which fills the SPROM data structure. The fallback is | ||
29 | * used for PCI based BCMA devices, where no valid SPROM can be found | ||
30 | * in the shadow registers and to provide the SPROM for SoCs where BCMA is | ||
31 | * to controll the system bus. | ||
32 | * | ||
33 | * This function is useful for weird architectures that have a half-assed | ||
34 | * BCMA device hardwired to their PCI bus. | ||
35 | * | ||
36 | * This function is available for architecture code, only. So it is not | ||
37 | * exported. | ||
38 | */ | ||
39 | int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus, | ||
40 | struct ssb_sprom *out)) | ||
41 | { | ||
42 | if (get_fallback_sprom) | ||
43 | return -EEXIST; | ||
44 | get_fallback_sprom = sprom_callback; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, | ||
50 | struct ssb_sprom *out) | ||
51 | { | ||
52 | int err; | ||
53 | |||
54 | if (!get_fallback_sprom) { | ||
55 | err = -ENOENT; | ||
56 | goto fail; | ||
57 | } | ||
58 | |||
59 | err = get_fallback_sprom(bus, out); | ||
60 | if (err) | ||
61 | goto fail; | ||
62 | |||
63 | bcma_debug(bus, "Using SPROM revision %d provided by platform.\n", | ||
64 | bus->sprom.revision); | ||
65 | return 0; | ||
66 | fail: | ||
67 | bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err); | ||
68 | return err; | ||
69 | } | ||
70 | 18 | ||
71 | /************************************************** | 19 | /************************************************** |
72 | * R/W ops. | 20 | * R/W ops. |
@@ -176,430 +124,44 @@ static int bcma_sprom_valid(const u16 *sprom) | |||
176 | * SPROM extraction. | 124 | * SPROM extraction. |
177 | **************************************************/ | 125 | **************************************************/ |
178 | 126 | ||
179 | #define SPOFF(offset) ((offset) / sizeof(u16)) | ||
180 | |||
181 | #define SPEX(_field, _offset, _mask, _shift) \ | ||
182 | bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift)) | ||
183 | |||
184 | #define SPEX32(_field, _offset, _mask, _shift) \ | ||
185 | bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \ | ||
186 | sprom[SPOFF(_offset)]) & (_mask)) >> (_shift)) | ||
187 | |||
188 | #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ | ||
189 | do { \ | ||
190 | SPEX(_field[0], _offset + 0, _mask, _shift); \ | ||
191 | SPEX(_field[1], _offset + 2, _mask, _shift); \ | ||
192 | SPEX(_field[2], _offset + 4, _mask, _shift); \ | ||
193 | SPEX(_field[3], _offset + 6, _mask, _shift); \ | ||
194 | SPEX(_field[4], _offset + 8, _mask, _shift); \ | ||
195 | SPEX(_field[5], _offset + 10, _mask, _shift); \ | ||
196 | SPEX(_field[6], _offset + 12, _mask, _shift); \ | ||
197 | SPEX(_field[7], _offset + 14, _mask, _shift); \ | ||
198 | } while (0) | ||
199 | |||
200 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | 127 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) |
201 | { | 128 | { |
202 | u16 v, o; | 129 | u16 v; |
203 | int i; | 130 | int i; |
204 | u16 pwr_info_offset[] = { | ||
205 | SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, | ||
206 | SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 | ||
207 | }; | ||
208 | BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != | ||
209 | ARRAY_SIZE(bus->sprom.core_pwr_info)); | ||
210 | |||
211 | bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & | ||
212 | SSB_SPROM_REVISION_REV; | ||
213 | 131 | ||
214 | for (i = 0; i < 3; i++) { | 132 | for (i = 0; i < 3; i++) { |
215 | v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 133 | v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; |
216 | *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); | 134 | *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); |
217 | } | 135 | } |
218 | |||
219 | SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); | ||
220 | |||
221 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, | ||
222 | SSB_SPROM4_TXPID2G0_SHIFT); | ||
223 | SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1, | ||
224 | SSB_SPROM4_TXPID2G1_SHIFT); | ||
225 | SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2, | ||
226 | SSB_SPROM4_TXPID2G2_SHIFT); | ||
227 | SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3, | ||
228 | SSB_SPROM4_TXPID2G3_SHIFT); | ||
229 | |||
230 | SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0, | ||
231 | SSB_SPROM4_TXPID5GL0_SHIFT); | ||
232 | SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1, | ||
233 | SSB_SPROM4_TXPID5GL1_SHIFT); | ||
234 | SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2, | ||
235 | SSB_SPROM4_TXPID5GL2_SHIFT); | ||
236 | SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3, | ||
237 | SSB_SPROM4_TXPID5GL3_SHIFT); | ||
238 | |||
239 | SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0, | ||
240 | SSB_SPROM4_TXPID5G0_SHIFT); | ||
241 | SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1, | ||
242 | SSB_SPROM4_TXPID5G1_SHIFT); | ||
243 | SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2, | ||
244 | SSB_SPROM4_TXPID5G2_SHIFT); | ||
245 | SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3, | ||
246 | SSB_SPROM4_TXPID5G3_SHIFT); | ||
247 | |||
248 | SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0, | ||
249 | SSB_SPROM4_TXPID5GH0_SHIFT); | ||
250 | SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1, | ||
251 | SSB_SPROM4_TXPID5GH1_SHIFT); | ||
252 | SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2, | ||
253 | SSB_SPROM4_TXPID5GH2_SHIFT); | ||
254 | SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3, | ||
255 | SSB_SPROM4_TXPID5GH3_SHIFT); | ||
256 | |||
257 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0); | ||
258 | SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0); | ||
259 | SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0); | ||
260 | SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0); | ||
261 | |||
262 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | ||
263 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | ||
264 | |||
265 | /* Extract cores power info info */ | ||
266 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { | ||
267 | o = pwr_info_offset[i]; | ||
268 | SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, | ||
269 | SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); | ||
270 | SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, | ||
271 | SSB_SPROM8_2G_MAXP, 0); | ||
272 | |||
273 | SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); | ||
274 | SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); | ||
275 | SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); | ||
276 | |||
277 | SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, | ||
278 | SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); | ||
279 | SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, | ||
280 | SSB_SPROM8_5G_MAXP, 0); | ||
281 | SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, | ||
282 | SSB_SPROM8_5GH_MAXP, 0); | ||
283 | SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, | ||
284 | SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); | ||
285 | |||
286 | SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); | ||
287 | SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); | ||
288 | SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); | ||
289 | SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); | ||
290 | SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); | ||
291 | SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); | ||
292 | SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); | ||
293 | SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); | ||
294 | SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); | ||
295 | } | ||
296 | |||
297 | SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS, | ||
298 | SSB_SROM8_FEM_TSSIPOS_SHIFT); | ||
299 | SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN, | ||
300 | SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); | ||
301 | SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE, | ||
302 | SSB_SROM8_FEM_PDET_RANGE_SHIFT); | ||
303 | SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO, | ||
304 | SSB_SROM8_FEM_TR_ISO_SHIFT); | ||
305 | SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT, | ||
306 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); | ||
307 | |||
308 | SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS, | ||
309 | SSB_SROM8_FEM_TSSIPOS_SHIFT); | ||
310 | SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN, | ||
311 | SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); | ||
312 | SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE, | ||
313 | SSB_SROM8_FEM_PDET_RANGE_SHIFT); | ||
314 | SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO, | ||
315 | SSB_SROM8_FEM_TR_ISO_SHIFT); | ||
316 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT, | ||
317 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); | ||
318 | |||
319 | SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, | ||
320 | SSB_SPROM8_ANTAVAIL_A_SHIFT); | ||
321 | SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, | ||
322 | SSB_SPROM8_ANTAVAIL_BG_SHIFT); | ||
323 | SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); | ||
324 | SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, | ||
325 | SSB_SPROM8_ITSSI_BG_SHIFT); | ||
326 | SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); | ||
327 | SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, | ||
328 | SSB_SPROM8_ITSSI_A_SHIFT); | ||
329 | SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); | ||
330 | SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, | ||
331 | SSB_SPROM8_MAXP_AL_SHIFT); | ||
332 | SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); | ||
333 | SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, | ||
334 | SSB_SPROM8_GPIOA_P1_SHIFT); | ||
335 | SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); | ||
336 | SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, | ||
337 | SSB_SPROM8_GPIOB_P3_SHIFT); | ||
338 | SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); | ||
339 | SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, | ||
340 | SSB_SPROM8_TRI5G_SHIFT); | ||
341 | SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); | ||
342 | SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, | ||
343 | SSB_SPROM8_TRI5GH_SHIFT); | ||
344 | SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, | ||
345 | SSB_SPROM8_RXPO2G_SHIFT); | ||
346 | SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, | ||
347 | SSB_SPROM8_RXPO5G_SHIFT); | ||
348 | SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); | ||
349 | SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, | ||
350 | SSB_SPROM8_RSSISMC2G_SHIFT); | ||
351 | SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, | ||
352 | SSB_SPROM8_RSSISAV2G_SHIFT); | ||
353 | SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, | ||
354 | SSB_SPROM8_BXA2G_SHIFT); | ||
355 | SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); | ||
356 | SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, | ||
357 | SSB_SPROM8_RSSISMC5G_SHIFT); | ||
358 | SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, | ||
359 | SSB_SPROM8_RSSISAV5G_SHIFT); | ||
360 | SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, | ||
361 | SSB_SPROM8_BXA5G_SHIFT); | ||
362 | |||
363 | SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0); | ||
364 | SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0); | ||
365 | SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0); | ||
366 | SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0); | ||
367 | SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0); | ||
368 | SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0); | ||
369 | SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0); | ||
370 | SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0); | ||
371 | SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0); | ||
372 | SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0); | ||
373 | SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0); | ||
374 | SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0); | ||
375 | SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0); | ||
376 | SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0); | ||
377 | SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0); | ||
378 | SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0); | ||
379 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); | ||
380 | |||
381 | /* Extract the antenna gain values. */ | ||
382 | SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, | ||
383 | SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); | ||
384 | SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, | ||
385 | SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); | ||
386 | SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, | ||
387 | SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); | ||
388 | SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, | ||
389 | SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); | ||
390 | |||
391 | SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, | ||
392 | SSB_SPROM8_LEDDC_ON_SHIFT); | ||
393 | SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, | ||
394 | SSB_SPROM8_LEDDC_OFF_SHIFT); | ||
395 | |||
396 | SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, | ||
397 | SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); | ||
398 | SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, | ||
399 | SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); | ||
400 | SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, | ||
401 | SSB_SPROM8_TXRXC_SWITCH_SHIFT); | ||
402 | |||
403 | SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); | ||
404 | |||
405 | SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); | ||
406 | SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); | ||
407 | SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); | ||
408 | SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); | ||
409 | |||
410 | SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, | ||
411 | SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); | ||
412 | SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, | ||
413 | SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); | ||
414 | SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, | ||
415 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, | ||
416 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); | ||
417 | SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, | ||
418 | SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); | ||
419 | SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, | ||
420 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION, | ||
421 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); | ||
422 | SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, | ||
423 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, | ||
424 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); | ||
425 | SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, | ||
426 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, | ||
427 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); | ||
428 | SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, | ||
429 | SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); | ||
430 | |||
431 | SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); | ||
432 | SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); | ||
433 | SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); | ||
434 | SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); | ||
435 | |||
436 | SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, | ||
437 | SSB_SPROM8_THERMAL_TRESH_SHIFT); | ||
438 | SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, | ||
439 | SSB_SPROM8_THERMAL_OFFSET_SHIFT); | ||
440 | SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, | ||
441 | SSB_SPROM8_TEMPDELTA_PHYCAL, | ||
442 | SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); | ||
443 | SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, | ||
444 | SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); | ||
445 | SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, | ||
446 | SSB_SPROM8_TEMPDELTA_HYSTERESIS, | ||
447 | SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Indicates the presence of external SPROM. | ||
452 | */ | ||
453 | static bool bcma_sprom_ext_available(struct bcma_bus *bus) | ||
454 | { | ||
455 | u32 chip_status; | ||
456 | u32 srom_control; | ||
457 | u32 present_mask; | ||
458 | |||
459 | if (bus->drv_cc.core->id.rev >= 31) { | ||
460 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) | ||
461 | return false; | ||
462 | |||
463 | srom_control = bcma_read32(bus->drv_cc.core, | ||
464 | BCMA_CC_SROM_CONTROL); | ||
465 | return srom_control & BCMA_CC_SROM_CONTROL_PRESENT; | ||
466 | } | ||
467 | |||
468 | /* older chipcommon revisions use chip status register */ | ||
469 | chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); | ||
470 | switch (bus->chipinfo.id) { | ||
471 | case BCMA_CHIP_ID_BCM4313: | ||
472 | present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT; | ||
473 | break; | ||
474 | |||
475 | case BCMA_CHIP_ID_BCM4331: | ||
476 | present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; | ||
477 | break; | ||
478 | |||
479 | default: | ||
480 | return true; | ||
481 | } | ||
482 | |||
483 | return chip_status & present_mask; | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * Indicates that on-chip OTP memory is present and enabled. | ||
488 | */ | ||
489 | static bool bcma_sprom_onchip_available(struct bcma_bus *bus) | ||
490 | { | ||
491 | u32 chip_status; | ||
492 | u32 otpsize = 0; | ||
493 | bool present; | ||
494 | |||
495 | chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); | ||
496 | switch (bus->chipinfo.id) { | ||
497 | case BCMA_CHIP_ID_BCM4313: | ||
498 | present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT; | ||
499 | break; | ||
500 | |||
501 | case BCMA_CHIP_ID_BCM4331: | ||
502 | present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; | ||
503 | break; | ||
504 | |||
505 | case BCMA_CHIP_ID_BCM43224: | ||
506 | case BCMA_CHIP_ID_BCM43225: | ||
507 | /* for these chips OTP is always available */ | ||
508 | present = true; | ||
509 | break; | ||
510 | case BCMA_CHIP_ID_BCM43227: | ||
511 | case BCMA_CHIP_ID_BCM43228: | ||
512 | case BCMA_CHIP_ID_BCM43428: | ||
513 | present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; | ||
514 | break; | ||
515 | default: | ||
516 | present = false; | ||
517 | break; | ||
518 | } | ||
519 | |||
520 | if (present) { | ||
521 | otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS; | ||
522 | otpsize >>= BCMA_CC_CAP_OTPS_SHIFT; | ||
523 | } | ||
524 | |||
525 | return otpsize != 0; | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * Verify OTP is filled and determine the byte | ||
530 | * offset where SPROM data is located. | ||
531 | * | ||
532 | * On error, returns 0; byte offset otherwise. | ||
533 | */ | ||
534 | static int bcma_sprom_onchip_offset(struct bcma_bus *bus) | ||
535 | { | ||
536 | struct bcma_device *cc = bus->drv_cc.core; | ||
537 | u32 offset; | ||
538 | |||
539 | /* verify OTP status */ | ||
540 | if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0) | ||
541 | return 0; | ||
542 | |||
543 | /* obtain bit offset from otplayout register */ | ||
544 | offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET); | ||
545 | return BCMA_CC_SPROM + (offset >> 3); | ||
546 | } | 136 | } |
547 | 137 | ||
548 | int bcma_sprom_get(struct bcma_bus *bus) | 138 | int bcma_sprom_get(struct bcma_bus *bus) |
549 | { | 139 | { |
550 | u16 offset = BCMA_CC_SPROM; | 140 | u16 offset; |
551 | u16 *sprom; | 141 | u16 *sprom; |
552 | int err = 0; | 142 | int err = 0; |
553 | 143 | ||
554 | if (!bus->drv_cc.core) | 144 | if (!bus->drv_cc.core) |
555 | return -EOPNOTSUPP; | 145 | return -EOPNOTSUPP; |
556 | 146 | ||
557 | if (!bcma_sprom_ext_available(bus)) { | 147 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) |
558 | bool sprom_onchip; | 148 | return -ENOENT; |
559 | |||
560 | /* | ||
561 | * External SPROM takes precedence so check | ||
562 | * on-chip OTP only when no external SPROM | ||
563 | * is present. | ||
564 | */ | ||
565 | sprom_onchip = bcma_sprom_onchip_available(bus); | ||
566 | if (sprom_onchip) { | ||
567 | /* determine offset */ | ||
568 | offset = bcma_sprom_onchip_offset(bus); | ||
569 | } | ||
570 | if (!offset || !sprom_onchip) { | ||
571 | /* | ||
572 | * Maybe there is no SPROM on the device? | ||
573 | * Now we ask the arch code if there is some sprom | ||
574 | * available for this device in some other storage. | ||
575 | */ | ||
576 | err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | ||
577 | return err; | ||
578 | } | ||
579 | } | ||
580 | 149 | ||
581 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), | 150 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), |
582 | GFP_KERNEL); | 151 | GFP_KERNEL); |
583 | if (!sprom) | 152 | if (!sprom) |
584 | return -ENOMEM; | 153 | return -ENOMEM; |
585 | 154 | ||
586 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || | 155 | /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). |
587 | bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) | 156 | * According to brcm80211 this applies to cards with PCIe rev >= 6 |
588 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); | 157 | * TODO: understand this condition and use it */ |
589 | 158 | offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM : | |
590 | bcma_debug(bus, "SPROM offset 0x%x\n", offset); | 159 | BCMA_CC_SPROM_PCIE6; |
591 | bcma_sprom_read(bus, offset, sprom); | 160 | bcma_sprom_read(bus, offset, sprom); |
592 | 161 | ||
593 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || | ||
594 | bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) | ||
595 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); | ||
596 | |||
597 | err = bcma_sprom_valid(sprom); | 162 | err = bcma_sprom_valid(sprom); |
598 | if (err) { | 163 | if (err) |
599 | bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); | ||
600 | err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | ||
601 | goto out; | 164 | goto out; |
602 | } | ||
603 | 165 | ||
604 | bcma_sprom_extract_r8(bus, sprom); | 166 | bcma_sprom_extract_r8(bus, sprom); |
605 | 167 | ||