aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/bcma
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/Kconfig42
-rw-r--r--drivers/bcma/Makefile6
-rw-r--r--drivers/bcma/bcma_private.h69
-rw-r--r--drivers/bcma/core.c18
-rw-r--r--drivers/bcma/driver_chipcommon.c265
-rw-r--r--drivers/bcma/driver_chipcommon_nflash.c44
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c494
-rw-r--r--drivers/bcma/driver_chipcommon_sflash.c165
-rw-r--r--drivers/bcma/driver_gmac_cmn.c14
-rw-r--r--drivers/bcma/driver_gpio.c98
-rw-r--r--drivers/bcma/driver_mips.c279
-rw-r--r--drivers/bcma/driver_pci.c236
-rw-r--r--drivers/bcma/driver_pci_host.c588
-rw-r--r--drivers/bcma/host_pci.c86
-rw-r--r--drivers/bcma/host_soc.c183
-rw-r--r--drivers/bcma/main.c241
-rw-r--r--drivers/bcma/scan.c467
-rw-r--r--drivers/bcma/scan.h2
-rw-r--r--drivers/bcma/sprom.c460
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
30config BCMA_DRIVER_PCI_HOSTMODE 30config 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
36config BCMA_HOST_SOC
37 bool
38 depends on BCMA_DRIVER_MIPS
39
40config 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
49config BCMA_SFLASH
50 bool
51 depends on BCMA_DRIVER_MIPS
52 default y
53
54config BCMA_NFLASH
55 bool
56 depends on BCMA_DRIVER_MIPS
57 default y
58
59config 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
68config 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
76config BCMA_DEBUG 36config 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 @@
1bcma-y += main.o scan.o core.o sprom.o 1bcma-y += main.o scan.o core.o sprom.o
2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o 2bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
3bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
4bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
5bcma-y += driver_pci.o 3bcma-y += driver_pci.o
6bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o 4bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
7bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
8bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
9bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o
10bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o 5bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
11bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
12obj-$(CONFIG_BCMA) += bcma.o 6obj-$(CONFIG_BCMA) += bcma.o
13 7
14ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG 8ccflags-$(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
22struct bcma_bus; 13struct bcma_bus;
23 14
24/* main.c */ 15/* main.c */
25int bcma_bus_register(struct bcma_bus *bus); 16int bcma_bus_register(struct bcma_bus *bus);
26void bcma_bus_unregister(struct bcma_bus *bus); 17void bcma_bus_unregister(struct bcma_bus *bus);
27int __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
31int bcma_bus_suspend(struct bcma_bus *bus);
32int bcma_bus_resume(struct bcma_bus *bus);
33#endif
34 18
35/* scan.c */ 19/* scan.c */
36int bcma_bus_scan(struct bcma_bus *bus); 20int bcma_bus_scan(struct bcma_bus *bus);
37int __init bcma_bus_scan_early(struct bcma_bus *bus,
38 struct bcma_device_id *match,
39 struct bcma_device *core);
40void bcma_init_bus(struct bcma_bus *bus);
41 21
42/* sprom.c */ 22/* sprom.c */
43int bcma_sprom_get(struct bcma_bus *bus); 23int bcma_sprom_get(struct bcma_bus *bus);
44 24
45/* driver_chipcommon.c */
46#ifdef CONFIG_BCMA_DRIVER_MIPS
47void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
48#endif /* CONFIG_BCMA_DRIVER_MIPS */
49
50/* driver_chipcommon_pmu.c */
51u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
52u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
53
54#ifdef CONFIG_BCMA_SFLASH
55/* driver_chipcommon_sflash.c */
56int bcma_sflash_init(struct bcma_drv_cc *cc);
57extern struct platform_device bcma_sflash_dev;
58#else
59static 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 */
68int bcma_nflash_init(struct bcma_drv_cc *cc);
69extern struct platform_device bcma_nflash_dev;
70#else
71static 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 */
80extern int __init bcma_host_pci_init(void); 27extern int __init bcma_host_pci_init(void);
81extern void __exit bcma_host_pci_exit(void); 28extern 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 */
85u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
86
87extern 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
90bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
91void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); 32void 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 */
96int bcma_gpio_init(struct bcma_drv_cc *cc);
97#else
98static 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
12bool bcma_core_is_enabled(struct bcma_device *core) 11bool 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}
36EXPORT_SYMBOL_GPL(bcma_core_disable); 34EXPORT_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}
110EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); 108EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
@@ -112,16 +110,14 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
112u32 bcma_core_dma_translation(struct bcma_device *core) 110u32 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
18static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, 14static 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
28static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) 24void 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
36static 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
57static 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
65static 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
75static 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
91int 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
112void 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
131void 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 */
167u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) 58void 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
190void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) 64void 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
205u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) 79u32 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
217u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) 84u32 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 */
233u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) 89u32 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}
244EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); 93EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
245 94
246u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) 95u32 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
258u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) 100u32 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
270u32 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
285u32 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
301void 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
13struct platform_device bcma_nflash_dev = {
14 .name = "bcma_nflash",
15 .num_resources = 0,
16};
17
18/* Initialize NAND flash access */
19int 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
16u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) 14static 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}
22EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
23
24void 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}
30EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
31
32void 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}
39EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
40 18
41void 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}
48EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
49 28
50void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 29static 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}
57EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
58 44
59static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 45static 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. */ 70void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
88void 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
108static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 86void 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
148void bcma_pmu_early_init(struct bcma_drv_cc *cc) 114void 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
159void 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
172u32 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 */
200static 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
236static 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 */
267static 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 */
298u32 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
332static 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
339void 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}
510EXPORT_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
13static 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
20struct platform_device bcma_sflash_dev = {
21 .name = "bcma_sflash",
22 .resource = &bcma_sflash_resource,
23 .num_resources = 1,
24};
25
26struct bcma_sflash_tbl_e {
27 char *name;
28 u32 id;
29 u32 blocksize;
30 u16 numblocks;
31};
32
33static 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
44static 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
62static 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
73static 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 */
88int 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
11void 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
17static 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
22static 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
29static 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
37static 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
45static 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
55static 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
68static 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
76int 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 */
23static 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 */
30static 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
38static inline u32 mips_read32(struct bcma_drv_mips *mcore,
39 u16 offset)
40{
41 return bcma_read32(mcore->core, offset);
42}
43
44static 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
51static 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
59static 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
67static 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 */
83unsigned 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}
98EXPORT_SYMBOL(bcma_core_mips_irq);
99
100static 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
150static 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
160static 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
169u32 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}
179EXPORT_SYMBOL(bcma_cpu_clock);
180
181static 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
217void 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
230void 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
20u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) 18static 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
27static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) 26static 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
34static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) 34static 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
58static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) 57static 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
101static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, 97static 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
144static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) 138static 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
156static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) 143static 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
171static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) 156/**************************************************
157 * Init.
158 **************************************************/
159
160static 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 */ 165static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
190/* Needs to happen when coming out of 'standby'/'hibernate' */
191static 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
210static 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
217void bcma_core_pci_init(struct bcma_drv_pci *pc) 190void 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
232int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, 203int 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}
263EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); 225EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
264
265void 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}
277EXPORT_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
27bool 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
43static 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
50static 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
58static 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
79out:
80 return addr;
81}
82
83static 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;
142unmap:
143 if (mmio)
144 iounmap(mmio);
145out:
146 return err;
147}
148
149static 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;
219unmap:
220 if (mmio)
221 iounmap(mmio);
222out:
223 return err;
224}
225
226static 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
246static 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 */
267static 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 */
336static 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
383void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) 11void 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. */
513static 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}
534DECLARE_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. */
537static 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}
561DECLARE_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. */
565int 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}
584EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
585
586/* PCI device IRQ mapping. */
587int 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}
600EXPORT_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
14static void bcma_host_pci_switch_core(struct bcma_device *core) 13static 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 23static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
25 * used. It makes use of fixed windows when possible. */
26static 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
40static 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
46static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) 30static 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
52static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) 37static 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
58static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, 44static 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
65static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, 52static 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
72static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, 60static 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
80static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, 69void 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
103static void bcma_host_pci_block_write(struct bcma_device *core, 92void 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
143static const struct bcma_host_ops bcma_host_pci_ops = { 131const 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
158static int bcma_host_pci_probe(struct pci_dev *dev, 146static 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
242static 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
252static 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
260static 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
270static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { 226static 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
291int __init bcma_host_pci_init(void) 243int __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
13static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
14{
15 return readb(core->io_addr + offset);
16}
17
18static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
19{
20 return readw(core->io_addr + offset);
21}
22
23static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
24{
25 return readl(core->io_addr + offset);
26}
27
28static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
29 u8 value)
30{
31 writeb(value, core->io_addr + offset);
32}
33
34static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
35 u16 value)
36{
37 writew(value, core->io_addr + offset);
38}
39
40static 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
47static 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
90static 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
135static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
136{
137 return readl(core->io_wrap + offset);
138}
139
140static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
141 u32 value)
142{
143 writel(value, core->io_wrap + offset);
144}
145
146static 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
161int __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
14MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); 12MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
15MODULE_LICENSE("GPL"); 13MODULE_LICENSE("GPL");
16 14
17/* contains the number the next bus should get. */
18static unsigned int bcma_bus_next_num = 0;
19
20/* bcma_buses_mutex locks the bcma_bus_next_num */
21static DEFINE_MUTEX(bcma_buses_mutex);
22
23static int bcma_bus_match(struct device *dev, struct device_driver *drv); 15static int bcma_bus_match(struct device *dev, struct device_driver *drv);
24static int bcma_device_probe(struct device *dev); 16static int bcma_device_probe(struct device *dev);
25static int bcma_device_remove(struct device *dev); 17static 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
65static u16 bcma_cc_core_id(struct bcma_bus *bus) 57static 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
72struct 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}
82EXPORT_SYMBOL_GPL(bcma_find_core);
83
84static 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
96static void bcma_release_core_dev(struct device *dev) 68static 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
182static void bcma_unregister_cores(struct bcma_bus *bus) 116static 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
195int bcma_bus_register(struct bcma_bus *bus) 126int 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
268void bcma_bus_unregister(struct bcma_bus *bus) 169void 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
283int __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
337int 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
352int 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
375int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) 174int __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 22struct bcma_device_id_name bcma_device_names[] = {
23static 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
30static 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 82const char *bcma_device_name(struct bcma_device_id *id)
90static 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
96static 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
235static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, 203int 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
247static 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
258static 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
417void 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
440int 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);
500out: 268 continue;
501 if (bus->hosttype == BCMA_HOSTTYPE_SOC) 269 }
502 iounmap(eromptr);
503
504 return err;
505}
506
507int __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;
558out: 355out:
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
19static 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 */
39int 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
49static 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;
66fail:
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
200static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) 127static 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 */
453static 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 */
489static 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 */
534static 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
548int bcma_sprom_get(struct bcma_bus *bus) 138int 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