diff options
Diffstat (limited to 'drivers/ssb')
| -rw-r--r-- | drivers/ssb/Kconfig | 44 | ||||
| -rw-r--r-- | drivers/ssb/Makefile | 4 | ||||
| -rw-r--r-- | drivers/ssb/b43_pci_bridge.c | 5 | ||||
| -rw-r--r-- | drivers/ssb/bridge_pcmcia_80211.c | 133 | ||||
| -rw-r--r-- | drivers/ssb/driver_chipcommon.c | 24 | ||||
| -rw-r--r-- | drivers/ssb/driver_chipcommon_pmu.c | 50 | ||||
| -rw-r--r-- | drivers/ssb/driver_chipcommon_sflash.c | 20 | ||||
| -rw-r--r-- | drivers/ssb/driver_extif.c | 6 | ||||
| -rw-r--r-- | drivers/ssb/driver_gige.c | 4 | ||||
| -rw-r--r-- | drivers/ssb/driver_gpio.c | 374 | ||||
| -rw-r--r-- | drivers/ssb/driver_mipscore.c | 33 | ||||
| -rw-r--r-- | drivers/ssb/driver_pcicore.c | 57 | ||||
| -rw-r--r-- | drivers/ssb/embedded.c | 18 | ||||
| -rw-r--r-- | drivers/ssb/host_soc.c | 210 | ||||
| -rw-r--r-- | drivers/ssb/main.c | 377 | ||||
| -rw-r--r-- | drivers/ssb/pci.c | 214 | ||||
| -rw-r--r-- | drivers/ssb/pcihost_wrapper.c | 39 | ||||
| -rw-r--r-- | drivers/ssb/pcmcia.c | 85 | ||||
| -rw-r--r-- | drivers/ssb/scan.c | 47 | ||||
| -rw-r--r-- | drivers/ssb/sdio.c | 19 | ||||
| -rw-r--r-- | drivers/ssb/sprom.c | 22 | ||||
| -rw-r--r-- | drivers/ssb/ssb_private.h | 77 |
22 files changed, 1178 insertions, 684 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 36171fd2826b..1cf1a98952fa 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -1,12 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only config SSB_POSSIBLE bool depends on HAS_IOMEM && HAS_DMA default y -menu "Sonics Silicon Backplane" - depends on SSB_POSSIBLE - -config SSB +menuconfig SSB tristate "Sonics Silicon Backplane support" depends on SSB_POSSIBLE help @@ -21,6 +19,8 @@ config SSB If unsure, say N. +if SSB + # Common SPROM support routines config SSB_SPROM bool @@ -32,7 +32,7 @@ config SSB_BLOCKIO config SSB_PCIHOST_POSSIBLE bool - depends on SSB && (PCI = y || PCI = SSB) + depends on SSB && (PCI = y || PCI = SSB) && (PCI_DRIVERS_LEGACY || !MIPS) default y config SSB_PCIHOST @@ -80,24 +80,13 @@ config SSB_SDIOHOST If unsure, say N -config SSB_SILENT - bool "No SSB kernel messages" - depends on SSB && EXPERT - help - This option turns off all Sonics Silicon Backplane printks. - Note that you won't be able to identify problems, once - messages are turned off. - This might only be desired for production kernels on - embedded devices to reduce the kernel size. - - Say N - -config SSB_DEBUG - bool "SSB debugging" - depends on SSB && !SSB_SILENT +config SSB_HOST_SOC + bool "Support for SSB bus on SoC" + depends on SSB && BCM47XX_NVRAM + select SSB_SPROM help - This turns on additional runtime checks and debugging - messages. Turn this on for SSB troubleshooting. + Host interface for a SSB directly mapped into memory. This is + for some Broadcom SoCs from the BCM47xx and BCM53xx lines. If unsure, say N @@ -122,7 +111,7 @@ config SSB_DRIVER_PCICORE config SSB_PCICORE_HOSTMODE bool "Hostmode support for SSB PCI core" - depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS + depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && SSB = y help PCIcore hostmode operation (external PCI bus). @@ -130,6 +119,7 @@ config SSB_DRIVER_MIPS bool "SSB Broadcom MIPS core driver" depends on SSB && MIPS select SSB_SERIAL + select SSB_SFLASH help Driver for the Sonics Silicon Backplane attached Broadcom MIPS core. @@ -138,13 +128,14 @@ config SSB_DRIVER_MIPS config SSB_SFLASH bool "SSB serial flash support" - depends on SSB_DRIVER_MIPS && BROKEN + depends on SSB_DRIVER_MIPS default y # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool - depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + depends on SSB_DRIVER_MIPS + depends on PCI=n || SSB_PCICORE_HOSTMODE default y config SSB_DRIVER_EXTIF @@ -168,9 +159,10 @@ config SSB_DRIVER_GIGE config SSB_DRIVER_GPIO bool "SSB GPIO driver" depends on SSB && GPIOLIB + select IRQ_DOMAIN if SSB_EMBEDDED help Driver to provide access to the GPIO pins on the bus. If unsure, say N -endmenu +endif # SSB diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index b1ddc116d387..142d33df040f 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # core ssb-y += main.o scan.o ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o @@ -5,8 +6,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o # host support ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o -ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o +ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o +ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o # built-in drivers ssb-y += driver_chipcommon.o diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index 19396dc4ee47..9c7316b5685f 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -10,12 +10,12 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/pci.h> #include <linux/module.h> #include <linux/ssb/ssb.h> -#include "ssb_private.h" - static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) }, @@ -38,6 +38,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4351) }, { 0, }, }; MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c new file mode 100644 index 000000000000..ffa379efff83 --- /dev/null +++ b/drivers/ssb/bridge_pcmcia_80211.c @@ -0,0 +1,133 @@ +/* + * Broadcom 43xx PCMCIA-SSB bridge module + * + * Copyright (c) 2007 Michael Buesch <m@bues.ch> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "ssb_private.h" + +#include <linux/ssb/ssb.h> +#include <linux/slab.h> +#include <linux/module.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/ciscode.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> + +static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = { + PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), + PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), + PCMCIA_DEVICE_NULL, +}; + +MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl); + +static int ssb_host_pcmcia_probe(struct pcmcia_device *dev) +{ + struct ssb_bus *ssb; + int err = -ENOMEM; + int res = 0; + + ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); + if (!ssb) + goto out_error; + + err = -ENODEV; + + dev->config_flags |= CONF_ENABLE_IRQ; + + dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | + WIN_USE_WAIT; + dev->resource[2]->start = 0; + dev->resource[2]->end = SSB_CORE_SIZE; + res = pcmcia_request_window(dev, dev->resource[2], 250); + if (res != 0) + goto err_kfree_ssb; + + res = pcmcia_map_mem_page(dev, dev->resource[2], 0); + if (res != 0) + goto err_disable; + + if (!dev->irq) + goto err_disable; + + res = pcmcia_enable_device(dev); + if (res != 0) + goto err_disable; + + err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); + if (err) + goto err_disable; + dev->priv = ssb; + + return 0; + +err_disable: + pcmcia_disable_device(dev); +err_kfree_ssb: + kfree(ssb); +out_error: + dev_err(&dev->dev, "Initialization failed (%d, %d)\n", res, err); + return err; +} + +static void ssb_host_pcmcia_remove(struct pcmcia_device *dev) +{ + struct ssb_bus *ssb = dev->priv; + + ssb_bus_unregister(ssb); + pcmcia_disable_device(dev); + kfree(ssb); + dev->priv = NULL; +} + +#ifdef CONFIG_PM +static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev) +{ + struct ssb_bus *ssb = dev->priv; + + return ssb_bus_suspend(ssb); +} + +static int ssb_host_pcmcia_resume(struct pcmcia_device *dev) +{ + struct ssb_bus *ssb = dev->priv; + + return ssb_bus_resume(ssb); +} +#else /* CONFIG_PM */ +# define ssb_host_pcmcia_suspend NULL +# define ssb_host_pcmcia_resume NULL +#endif /* CONFIG_PM */ + +static struct pcmcia_driver ssb_host_pcmcia_driver = { + .owner = THIS_MODULE, + .name = "ssb-pcmcia", + .id_table = ssb_host_pcmcia_tbl, + .probe = ssb_host_pcmcia_probe, + .remove = ssb_host_pcmcia_remove, + .suspend = ssb_host_pcmcia_suspend, + .resume = ssb_host_pcmcia_resume, +}; + +static int pcmcia_init_failed; + +/* + * These are not module init/exit functions! + * The module_pcmcia_driver() helper cannot be used here. + */ +int ssb_host_pcmcia_init(void) +{ + pcmcia_init_failed = pcmcia_register_driver(&ssb_host_pcmcia_driver); + + return pcmcia_init_failed; +} + +void ssb_host_pcmcia_exit(void) +{ + if (!pcmcia_init_failed) + pcmcia_unregister_driver(&ssb_host_pcmcia_driver); +} diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 7cb7d2c8fd86..a8d2525e7af9 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -9,14 +9,14 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/export.h> #include <linux/pci.h> #include <linux/bcm47xx_wdt.h> -#include "ssb_private.h" - /* Clock sources */ enum ssb_clksrc { @@ -56,7 +56,7 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, if (cc->capabilities & SSB_CHIPCO_CAP_PMU) return; /* PMU controls clockmode, separated function needed */ - SSB_WARN_ON(ccdev->id.revision >= 20); + WARN_ON(ccdev->id.revision >= 20); /* chipcommon cores prior to rev6 don't support dynamic clock control */ if (ccdev->id.revision < 6) @@ -111,7 +111,7 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, } break; default: - SSB_WARN_ON(1); + WARN_ON(1); } } @@ -119,7 +119,7 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; - u32 uninitialized_var(tmp); + u32 tmp; if (cc->dev->id.revision < 6) { if (bus->bustype == SSB_BUSTYPE_SSB || @@ -149,7 +149,7 @@ static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) /* Get maximum or minimum (depending on get_max flag) slowclock frequency. */ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max) { - int uninitialized_var(limit); + int limit; enum ssb_clksrc clocksrc; int divisor = 1; u32 tmp; @@ -164,7 +164,7 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max) divisor = 32; break; default: - SSB_WARN_ON(1); + WARN_ON(1); } } else if (cc->dev->id.revision < 10) { switch (clocksrc) { @@ -238,7 +238,7 @@ static void chipco_powercontrol_init(struct ssb_chipcommon *cc) } } -/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */ +/* https://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */ static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; @@ -255,7 +255,7 @@ static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc) } } -/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */ +/* https://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; @@ -277,7 +277,7 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) minfreq = chipco_pctl_clockfreqlimit(cc, 0); pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY); tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; - SSB_WARN_ON(tmp & ~0xFFFF); + WARN_ON(tmp & ~0xFFFF); cc->fast_pwrup_delay = tmp; } @@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) if (cc->dev->id.revision >= 11) cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); - ssb_dbg("chipcommon status is 0x%x\n", cc->status); + dev_dbg(cc->dev->dev, "chipcommon status is 0x%x\n", cc->status); if (cc->dev->id.revision >= 20) { chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); @@ -425,7 +425,7 @@ void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); break; } - /* Fallthough */ + fallthrough; default: *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); } diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 1173a091b402..888069e10659 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -8,17 +8,17 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_driver_chipcommon.h> #include <linux/delay.h> #include <linux/export.h> #ifdef CONFIG_BCM47XX -#include <bcm47xx_nvram.h> +#include <linux/bcm47xx_nvram.h> #endif -#include "ssb_private.h" - static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) { chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); @@ -110,7 +110,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, return; } - ssb_info("Programming PLL to %u.%03u MHz\n", + dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n", crystalfreq / 1000, crystalfreq % 1000); /* First turn the PLL off. */ @@ -128,7 +128,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, ~(1 << SSB_PMURES_5354_BB_PLL_PU)); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } for (i = 1500; i; i--) { tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); @@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, } tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) - ssb_emerg("Failed to turn the PLL off!\n"); + dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n"); /* Set PDIV in PLL control 0. */ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); @@ -249,7 +249,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, return; } - ssb_info("Programming PLL to %u.%03u MHz\n", + dev_info(cc->dev->dev, "Programming PLL to %u.%03u MHz\n", crystalfreq / 1000, crystalfreq % 1000); /* First turn the PLL off. */ @@ -265,7 +265,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, buffer_strength = 0x222222; break; default: - SSB_WARN_ON(1); + WARN_ON(1); } for (i = 1500; i; i--) { tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); @@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, } tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) - ssb_emerg("Failed to turn the PLL off!\n"); + dev_emerg(cc->dev->dev, "Failed to turn the PLL off!\n"); /* Set p1div and p2div. */ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); @@ -349,7 +349,7 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) case 43222: break; default: - ssb_err("ERROR: PLL init unknown for device %04X\n", + dev_err(cc->dev->dev, "ERROR: PLL init unknown for device %04X\n", bus->chip_id); } } @@ -471,7 +471,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) max_msk = 0xFFFFF; break; default: - ssb_err("ERROR: PMU resource config unknown for device %04X\n", + dev_err(cc->dev->dev, "ERROR: PMU resource config unknown for device %04X\n", bus->chip_id); } @@ -501,7 +501,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) ~(depend_tab[i].depend)); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } } } @@ -513,7 +513,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); } -/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */ +/* https://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */ void ssb_pmu_init(struct ssb_chipcommon *cc) { u32 pmucap; @@ -524,7 +524,7 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); - ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n", + dev_dbg(cc->dev->dev, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, pmucap); if (cc->pmu.rev == 1) @@ -568,12 +568,12 @@ void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, mask = 0x3F; break; default: - SSB_WARN_ON(1); + WARN_ON(1); return; } break; case 0x4312: - if (SSB_WARN_ON(id != LDO_PAREF)) + if (WARN_ON(id != LDO_PAREF)) return; addr = 0; shift = 21; @@ -621,8 +621,8 @@ static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc) u32 crystalfreq; const struct pmu0_plltab_entry *e = NULL; - crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) & - SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT; + crystalfreq = (chipco_read32(cc, SSB_CHIPCO_PMU_CTL) & + SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT; e = pmu0_plltab_find_entry(crystalfreq); BUG_ON(!e); return e->freq * 1000; @@ -634,9 +634,9 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) switch (bus->chip_id) { case 0x5354: - ssb_pmu_get_alp_clock_clk0(cc); + return ssb_pmu_get_alp_clock_clk0(cc); default: - ssb_err("ERROR: PMU alp clock unknown for device %04X\n", + dev_err(cc->dev->dev, "ERROR: PMU alp clock unknown for device %04X\n", bus->chip_id); return 0; } @@ -651,7 +651,7 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) /* 5354 chip uses a non programmable PLL of frequency 240MHz */ return 240000000; default: - ssb_err("ERROR: PMU cpu clock unknown for device %04X\n", + dev_err(cc->dev->dev, "ERROR: PMU cpu clock unknown for device %04X\n", bus->chip_id); return 0; } @@ -665,7 +665,7 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) case 0x5354: return 120000000; default: - ssb_err("ERROR: PMU controlclock unknown for device %04X\n", + dev_err(cc->dev->dev, "ERROR: PMU controlclock unknown for device %04X\n", bus->chip_id); return 0; } @@ -705,9 +705,9 @@ void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid) pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; break; default: - ssb_printk(KERN_ERR PFX - "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", - cc->dev->bus->chip_id); + dev_err(cc->dev->dev, + "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", + cc->dev->bus->chip_id); return; } diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c index e84cf04f4416..fac0e6828288 100644 --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c @@ -5,10 +5,10 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include <linux/ssb/ssb.h> - #include "ssb_private.h" +#include <linux/ssb/ssb.h> + static struct resource ssb_sflash_resource = { .name = "ssb_sflash", .start = SSB_FLASH2, @@ -37,7 +37,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { { "M25P32", 0x15, 0x10000, 64, }, { "M25P64", 0x16, 0x10000, 128, }, { "M25FL128", 0x17, 0x10000, 256, }, - { 0 }, + { NULL }, }; static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { @@ -55,7 +55,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { { "SST25VF016", 0x41, 0x1000, 512, }, { "SST25VF032", 0x4a, 0x1000, 1024, }, { "SST25VF064", 0x4b, 0x1000, 2048, }, - { 0 }, + { NULL }, }; static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { @@ -66,7 +66,7 @@ static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { { "AT45DB161", 0x2c, 512, 4096, }, { "AT45DB321", 0x34, 512, 8192, }, { "AT45DB642", 0x3c, 1024, 8192, }, - { 0 }, + { NULL }, }; static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) @@ -80,7 +80,7 @@ static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) return; cpu_relax(); } - pr_err("SFLASH control command failed (timeout)!\n"); + dev_err(cc->dev->dev, "SFLASH control command failed (timeout)!\n"); } /* Initialize serial flash access */ @@ -151,8 +151,8 @@ int ssb_sflash_init(struct ssb_chipcommon *cc) sflash->size = sflash->blocksize * sflash->numblocks; sflash->present = true; - pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", - e->name, e->blocksize, e->numblocks); + pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", + e->name, sflash->size / 1024, e->blocksize, e->numblocks); /* Prepare platform device, but don't register it yet. It's too early, * malloc (required by device_private_init) is not available yet. */ @@ -160,7 +160,5 @@ int ssb_sflash_init(struct ssb_chipcommon *cc) sflash->size; ssb_sflash_dev.dev.platform_data = sflash; - pr_err("Serial flash support is not implemented yet!\n"); - - return -ENOTSUPP; + return 0; } diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index 59385fdab5b0..bc275968fcc6 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c @@ -10,12 +10,12 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> -#include "ssb_private.h" - static inline u32 extif_read32(struct ssb_extif *extif, u16 offset) { @@ -63,7 +63,7 @@ int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports for (i = 0; i < 2; i++) { void __iomem *uart_regs; - uart_regs = ioremap_nocache(SSB_EUART, 16); + uart_regs = ioremap(SSB_EUART, 16); if (uart_regs) { uart_regs += (i * 8); diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c index 21f71a1581fa..ebee6b0e3c34 100644 --- a/drivers/ssb/driver_gige.c +++ b/drivers/ssb/driver_gige.c @@ -24,7 +24,7 @@ MODULE_LICENSE("GPL"); static const struct ssb_device_id ssb_gige_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV), - SSB_DEVTABLE_END + {}, }; /* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */ @@ -242,7 +242,7 @@ static int ssb_gige_probe(struct ssb_device *sdev, bool pdev_is_ssb_gige_core(struct pci_dev *pdev) { if (!pdev->resource[0].name) - return 0; + return false; return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0); } EXPORT_SYMBOL(pdev_is_ssb_gige_core); diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index dc109de228c6..905657c925bc 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c @@ -8,54 +8,75 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include <linux/gpio.h> +#include "ssb_private.h" + +#include <linux/gpio/driver.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/irqdomain.h> #include <linux/export.h> #include <linux/ssb/ssb.h> -#include "ssb_private.h" -static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) +/************************************************** + * Shared + **************************************************/ + +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio) { - return container_of(chip, struct ssb_bus, gpio); + struct ssb_bus *bus = gpiochip_get_data(chip); + + if (bus->bustype == SSB_BUSTYPE_SSB) + return irq_find_mapping(bus->irq_domain, gpio); + else + return -EINVAL; } +#endif + +/************************************************** + * ChipCommon + **************************************************/ -static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) +static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); } -static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, - int value) +static int ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned int gpio, + int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); + + return 0; } static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, - unsigned gpio) + unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); return 0; } static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, - unsigned gpio, int value) + unsigned int gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); return 0; } -static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) +static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); /* clear pulldown */ @@ -66,27 +87,138 @@ static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) return 0; } -static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) +static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); /* clear pullup */ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); } -static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio) +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static void ssb_gpio_irq_chipco_mask(struct irq_data *d) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); - if (bus->bustype == SSB_BUSTYPE_SSB) - return ssb_mips_irq(bus->chipco.dev) + 2; - else - return -EINVAL; + ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0); } +static void ssb_gpio_irq_chipco_unmask(struct irq_data *d) +{ + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio)); + + ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val); + ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio)); +} + +static struct irq_chip ssb_gpio_irq_chipco_chip = { + .name = "SSB-GPIO-CC", + .irq_mask = ssb_gpio_irq_chipco_mask, + .irq_unmask = ssb_gpio_irq_chipco_unmask, +}; + +static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id) +{ + struct ssb_bus *bus = dev_id; + struct ssb_chipcommon *chipco = &bus->chipco; + u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN); + u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ); + u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL); + unsigned long irqs = (val ^ pol) & mask; + int gpio; + + if (!irqs) + return IRQ_NONE; + + for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) + generic_handle_domain_irq_safe(bus->irq_domain, gpio); + + ssb_chipco_gpio_polarity(chipco, irqs, val & irqs); + + return IRQ_HANDLED; +} + +static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) +{ + struct ssb_chipcommon *chipco = &bus->chipco; + struct gpio_chip *chip = &bus->gpio; + int gpio, hwirq, err; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return 0; + + bus->irq_domain = irq_domain_create_linear(NULL, chip->ngpio, &irq_domain_simple_ops, + chipco); + if (!bus->irq_domain) { + err = -ENODEV; + goto err_irq_domain; + } + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_create_mapping(bus->irq_domain, gpio); + + irq_set_chip_data(irq, bus); + irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip, + handle_simple_irq); + } + + hwirq = ssb_mips_irq(bus->chipco.dev) + 2; + err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED, + "gpio", bus); + if (err) + goto err_req_irq; + + ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0); + chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO); + + return 0; + +err_req_irq: + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +err_irq_domain: + return err; +} + +static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) +{ + struct ssb_chipcommon *chipco = &bus->chipco; + struct gpio_chip *chip = &bus->gpio; + int gpio; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return; + + chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO); + free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco); + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +} +#else +static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) +{ + return 0; +} + +static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) +{ +} +#endif + static int ssb_gpio_chipco_init(struct ssb_bus *bus) { struct gpio_chip *chip = &bus->gpio; + int err; chip->label = "ssb_chipco_gpio"; chip->owner = THIS_MODULE; @@ -96,68 +228,196 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus) chip->set = ssb_gpio_chipco_set_value; chip->direction_input = ssb_gpio_chipco_direction_input; chip->direction_output = ssb_gpio_chipco_direction_output; - chip->to_irq = ssb_gpio_chipco_to_irq; +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) + chip->to_irq = ssb_gpio_to_irq; +#endif chip->ngpio = 16; /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get - * a random base number. */ + * a random base number. + */ if (bus->bustype == SSB_BUSTYPE_SSB) chip->base = 0; else chip->base = -1; - return gpiochip_add(chip); + err = ssb_gpio_irq_chipco_domain_init(bus); + if (err) + return err; + + err = gpiochip_add_data(chip, bus); + if (err) { + ssb_gpio_irq_chipco_domain_exit(bus); + return err; + } + + return 0; } +/************************************************** + * EXTIF + **************************************************/ + #ifdef CONFIG_SSB_DRIVER_EXTIF -static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) +static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); } -static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, - int value) +static int ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned int gpio, + int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); + + return 0; } static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, - unsigned gpio) + unsigned int gpio) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); return 0; } static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, - unsigned gpio, int value) + unsigned int gpio, int value) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = gpiochip_get_data(chip); ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); return 0; } -static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio) +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) +static void ssb_gpio_irq_extif_mask(struct irq_data *d) { - struct ssb_bus *bus = ssb_gpio_get_bus(chip); + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); - if (bus->bustype == SSB_BUSTYPE_SSB) - return ssb_mips_irq(bus->extif.dev) + 2; - else - return -EINVAL; + ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0); +} + +static void ssb_gpio_irq_extif_unmask(struct irq_data *d) +{ + struct ssb_bus *bus = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio)); + + ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val); + ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio)); +} + +static struct irq_chip ssb_gpio_irq_extif_chip = { + .name = "SSB-GPIO-EXTIF", + .irq_mask = ssb_gpio_irq_extif_mask, + .irq_unmask = ssb_gpio_irq_extif_unmask, +}; + +static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id) +{ + struct ssb_bus *bus = dev_id; + struct ssb_extif *extif = &bus->extif; + u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN); + u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK); + u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL); + unsigned long irqs = (val ^ pol) & mask; + int gpio; + + if (!irqs) + return IRQ_NONE; + + for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) + generic_handle_domain_irq_safe(bus->irq_domain, gpio); + + ssb_extif_gpio_polarity(extif, irqs, val & irqs); + + return IRQ_HANDLED; +} + +static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) +{ + struct ssb_extif *extif = &bus->extif; + struct gpio_chip *chip = &bus->gpio; + int gpio, hwirq, err; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return 0; + + bus->irq_domain = irq_domain_create_linear(NULL, chip->ngpio, &irq_domain_simple_ops, + extif); + if (!bus->irq_domain) { + err = -ENODEV; + goto err_irq_domain; + } + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_create_mapping(bus->irq_domain, gpio); + + irq_set_chip_data(irq, bus); + irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip, + handle_simple_irq); + } + + hwirq = ssb_mips_irq(bus->extif.dev) + 2; + err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED, + "gpio", bus); + if (err) + goto err_req_irq; + + ssb_extif_gpio_intmask(&bus->extif, ~0, 0); + + return 0; + +err_req_irq: + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +err_irq_domain: + return err; } +static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) +{ + struct ssb_extif *extif = &bus->extif; + struct gpio_chip *chip = &bus->gpio; + int gpio; + + if (bus->bustype != SSB_BUSTYPE_SSB) + return; + + free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif); + for (gpio = 0; gpio < chip->ngpio; gpio++) { + int irq = irq_find_mapping(bus->irq_domain, gpio); + + irq_dispose_mapping(irq); + } + irq_domain_remove(bus->irq_domain); +} +#else +static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) +{ + return 0; +} + +static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) +{ +} +#endif + static int ssb_gpio_extif_init(struct ssb_bus *bus) { struct gpio_chip *chip = &bus->gpio; + int err; chip->label = "ssb_extif_gpio"; chip->owner = THIS_MODULE; @@ -165,17 +425,30 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) chip->set = ssb_gpio_extif_set_value; chip->direction_input = ssb_gpio_extif_direction_input; chip->direction_output = ssb_gpio_extif_direction_output; - chip->to_irq = ssb_gpio_extif_to_irq; +#if IS_ENABLED(CONFIG_SSB_EMBEDDED) + chip->to_irq = ssb_gpio_to_irq; +#endif chip->ngpio = 5; /* There is just one SoC in one device and its GPIO addresses should be * deterministic to address them more easily. The other buses could get - * a random base number. */ + * a random base number. + */ if (bus->bustype == SSB_BUSTYPE_SSB) chip->base = 0; else chip->base = -1; - return gpiochip_add(chip); + err = ssb_gpio_irq_extif_domain_init(bus); + if (err) + return err; + + err = gpiochip_add_data(chip, bus); + if (err) { + ssb_gpio_irq_extif_domain_exit(bus); + return err; + } + + return 0; } #else @@ -185,15 +458,16 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus) } #endif +/************************************************** + * Init + **************************************************/ + int ssb_gpio_init(struct ssb_bus *bus) { if (ssb_chipco_available(&bus->chipco)) return ssb_gpio_chipco_init(bus); else if (ssb_extif_available(&bus->extif)) return ssb_gpio_extif_init(bus); - else - SSB_WARN_ON(1); - return -1; } @@ -201,10 +475,8 @@ int ssb_gpio_unregister(struct ssb_bus *bus) { if (ssb_chipco_available(&bus->chipco) || ssb_extif_available(&bus->extif)) { - return gpiochip_remove(&bus->gpio); - } else { - SSB_WARN_ON(1); + gpiochip_remove(&bus->gpio); + return 0; } - return -1; } diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 09077067b0c8..354486b7ed3a 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -8,6 +8,8 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/mtd/physmap.h> @@ -15,8 +17,9 @@ #include <linux/serial_core.h> #include <linux/serial_reg.h> #include <linux/time.h> - -#include "ssb_private.h" +#ifdef CONFIG_BCM47XX +#include <linux/bcm47xx_nvram.h> +#endif static const char * const part_probes[] = { "bcm47xxpart", NULL }; @@ -167,14 +170,15 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); ssb_write32(mdev, SSB_IPSFLAG, irqflag); } - ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n", + dev_dbg(dev->dev, "set_irq: core 0x%04x, irq %d => %d\n", dev->id.coreid, oldirq+2, irq+2); } static void print_irq(struct ssb_device *dev, unsigned int irq) { static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; - ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", + dev_dbg(dev->dev, + "core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", dev->id.coreid, irq_name[0], irq == 0 ? "*" : " ", irq_name[1], irq == 1 ? "*" : " ", @@ -210,6 +214,7 @@ static void ssb_mips_serial_init(struct ssb_mipscore *mcore) static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; + struct ssb_sflash *sflash = &mcore->sflash; struct ssb_pflash *pflash = &mcore->pflash; /* When there is no chipcommon on the bus there is 4MB flash */ @@ -225,11 +230,11 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { case SSB_CHIPCO_FLASHT_STSER: case SSB_CHIPCO_FLASHT_ATSER: - pr_debug("Found serial flash\n"); + dev_dbg(mcore->dev->dev, "Found serial flash\n"); ssb_sflash_init(&bus->chipco); break; case SSB_CHIPCO_FLASHT_PARA: - pr_debug("Found parallel flash\n"); + dev_dbg(mcore->dev->dev, "Found parallel flash\n"); pflash->present = true; pflash->window = SSB_FLASH2; pflash->window_size = SSB_FLASH2_SZ; @@ -242,7 +247,15 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) } ssb_pflash: - if (pflash->present) { + if (sflash->present) { +#ifdef CONFIG_BCM47XX + bcm47xx_nvram_init_from_mem(sflash->window, sflash->size); +#endif + } else if (pflash->present) { +#ifdef CONFIG_BCM47XX + bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size); +#endif + ssb_pflash_data.width = pflash->buswidth; ssb_pflash_resource.start = pflash->window; ssb_pflash_resource.end = pflash->window + pflash->window_size; @@ -287,7 +300,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) if (!mcore->dev) return; /* We don't have a MIPS core */ - ssb_dbg("Initializing MIPS core...\n"); + dev_dbg(mcore->dev->dev, "Initializing MIPS core...\n"); bus = mcore->dev->bus; hz = ssb_clockspeed(bus); @@ -329,13 +342,13 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) set_irq(dev, irq++); break; } - /* fallthrough */ + fallthrough; case SSB_DEV_EXTIF: set_irq(dev, 0); break; } } - ssb_dbg("after irq reconfiguration\n"); + dev_dbg(mcore->dev->dev, "after irq reconfiguration\n"); dump_irq(bus); ssb_mips_serial_init(mcore); diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index d75b72ba2672..d11b4242b6d2 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -8,14 +8,14 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/pci.h> #include <linux/export.h> #include <linux/delay.h> #include <linux/ssb/ssb_embedded.h> -#include "ssb_private.h" - static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address); static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data); static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); @@ -55,7 +55,8 @@ void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value) #include <asm/paccess.h> /* Probe a 32bit value on the bus and catch bus exceptions. * Returns nonzero on a bus exception. - * This is MIPS specific */ + * This is MIPS specific + */ #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) /* Assume one-hot slot wiring */ @@ -115,14 +116,14 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc, u32 addr, val; void __iomem *mmio; - SSB_WARN_ON(!pc->hostmode); + WARN_ON(!pc->hostmode); if (unlikely(len != 1 && len != 2 && len != 4)) goto out; addr = get_cfgspace_addr(pc, bus, dev, func, off); if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, len); + mmio = ioremap(addr, len); if (!mmio) goto out; @@ -161,14 +162,14 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc, u32 addr, val = 0; void __iomem *mmio; - SSB_WARN_ON(!pc->hostmode); + WARN_ON(!pc->hostmode); if (unlikely(len != 1 && len != 2 && len != 4)) goto out; addr = get_cfgspace_addr(pc, bus, dev, func, off); if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, len); + mmio = ioremap(addr, len); if (!mmio) goto out; @@ -255,7 +256,8 @@ static struct pci_controller ssb_pcicore_controller = { }; /* This function is called when doing a pci_enable_device(). - * We must first check if the device is a device on the PCI-core bridge. */ + * We must first check if the device is a device on the PCI-core bridge. + */ int ssb_pcicore_plat_dev_init(struct pci_dev *d) { if (d->bus->ops != &ssb_pcicore_pciops) { @@ -263,7 +265,7 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d) return -ENODEV; } - ssb_info("PCI: Fixing up device %s\n", pci_name(d)); + dev_info(&d->dev, "PCI: Fixing up device %s\n", pci_name(d)); /* Fix up interrupt lines */ d->irq = ssb_mips_irq(extpci_core->dev) + 2; @@ -284,12 +286,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) return; - ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); + dev_info(&dev->dev, "PCI: Fixing up bridge %s\n", pci_name(dev)); /* Enable PCI bridge bus mastering and memory space */ pci_set_master(dev); if (pcibios_enable_device(dev, ~0) < 0) { - ssb_err("PCI: SSB bridge enable failed\n"); + dev_err(&dev->dev, "PCI: SSB bridge enable failed\n"); return; } @@ -298,7 +300,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) /* Make sure our latency is high enough to handle the devices behind us */ lat = 168; - ssb_info("PCI: Fixing latency timer of device %s to %u\n", + dev_info(&dev->dev, + "PCI: Fixing latency timer of device %s to %u\n", pci_name(dev), lat); pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } @@ -322,7 +325,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) return; extpci_core = pc; - ssb_dbg("PCIcore in host mode found\n"); + dev_dbg(pc->dev->dev, "PCIcore in host mode found\n"); /* Reset devices on the external PCI bus */ val = SSB_PCICORE_CTL_RST_OE; val |= SSB_PCICORE_CTL_CLK_OE; @@ -337,7 +340,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) udelay(1); /* Assertion time demanded by the PCI standard */ if (pc->dev->bus->has_cardbus_slot) { - ssb_dbg("CardBus slot detected\n"); + dev_dbg(pc->dev->dev, "CardBus slot detected\n"); pc->cardbusmode = 1; /* GPIO 1 resets the bridge */ ssb_gpio_out(pc->dev->bus, 1, 1); @@ -357,6 +360,16 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, SSB_PCICORE_SBTOPCI_MEM | SSB_PCI_DMA); + /* + * Accessing PCI config without a proper delay after devices reset (not + * GPIO reset) was causing reboots on WRT300N v1.0 (BCM4704). + * Tested delay 850 us lowered reboot chance to 50-80%, 1000 us fixed it + * completely. Flushing all writes was also tested but with no luck. + * The same problem was reported for WRT350N v1 (BCM4705), so we just + * sleep here unconditionally. + */ + usleep_range(1000, 2000); + /* Enable PCI bridge BAR0 prefetch and burst */ val = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2); @@ -370,11 +383,13 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) /* Ok, ready to run, register it to the system. * The following needs change, if we want to port hostmode - * to non-MIPS platform. */ - ssb_pcicore_controller.io_map_base = (unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000); + * to non-MIPS platform. + */ + ssb_pcicore_controller.io_map_base = (unsigned long)ioremap(SSB_PCI_MEM, 0x04000000); set_io_port_base(ssb_pcicore_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new - * values. Not waiting at this point causes crashes of the machine. */ + * values. Not waiting at this point causes crashes of the machine. + */ mdelay(10); register_pci_controller(&ssb_pcicore_controller); } @@ -394,7 +409,8 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) return 0; /* The 200-pin BCM4712 package does not bond out PCI. Even when - * PCI is bonded out, some boards may leave the pins floating. */ + * PCI is bonded out, some boards may leave the pins floating. + */ if (bus->chip_id == 0x4712) { if (bus->chip_package == SSB_CHIPPACK_BCM4712S) return 0; @@ -674,7 +690,8 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, if (dev->bus->bustype != SSB_BUSTYPE_PCI) { /* This SSB device is not on a PCI host-bus. So the IRQs are * not routed through the PCI core. - * So we must not enable routing through the PCI core. */ + * So we must not enable routing through the PCI core. + */ goto out; } @@ -691,7 +708,7 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, /* Calculate the "coremask" for the device. */ coremask = (1 << dev->core_index); - SSB_WARN_ON(bus->bustype != SSB_BUSTYPE_PCI); + WARN_ON(bus->bustype != SSB_BUSTYPE_PCI); err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); if (err) goto out; diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index 55e101115038..8254ed25e063 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c @@ -9,6 +9,8 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/export.h> #include <linux/platform_device.h> #include <linux/ssb/ssb.h> @@ -17,8 +19,6 @@ #include <linux/ssb/ssb_driver_gige.h> #include <linux/pci.h> -#include "ssb_private.h" - int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) { @@ -57,8 +57,8 @@ int ssb_watchdog_register(struct ssb_bus *bus) bus->busnumber, &wdt, sizeof(wdt)); if (IS_ERR(pdev)) { - ssb_dbg("can not register watchdog device, err: %li\n", - PTR_ERR(pdev)); + pr_debug("can not register watchdog device, err: %li\n", + PTR_ERR(pdev)); return PTR_ERR(pdev); } @@ -77,7 +77,7 @@ u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_in(&bus->extif, mask); else - SSB_WARN_ON(1); + WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; @@ -95,7 +95,7 @@ u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value) else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_out(&bus->extif, mask, value); else - SSB_WARN_ON(1); + WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; @@ -113,7 +113,7 @@ u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value) else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_outen(&bus->extif, mask, value); else - SSB_WARN_ON(1); + WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; @@ -145,7 +145,7 @@ u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value) else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_intmask(&bus->extif, mask, value); else - SSB_WARN_ON(1); + WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; @@ -163,7 +163,7 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value) else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_polarity(&bus->extif, mask, value); else - SSB_WARN_ON(1); + WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; diff --git a/drivers/ssb/host_soc.c b/drivers/ssb/host_soc.c new file mode 100644 index 000000000000..3b438480515c --- /dev/null +++ b/drivers/ssb/host_soc.c @@ -0,0 +1,210 @@ +/* + * Sonics Silicon Backplane SoC host related functions. + * Subsystem core + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch <m@bues.ch> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "ssb_private.h" + +#include <linux/bcm47xx_nvram.h> +#include <linux/ssb/ssb.h> + +static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + return readb(bus->mmio + offset); +} + +static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + return readw(bus->mmio + offset); +} + +static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + return readl(bus->mmio + offset); +} + +#ifdef CONFIG_SSB_BLOCKIO +static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + struct ssb_bus *bus = dev->bus; + void __iomem *addr; + + offset += dev->core_index * SSB_CORE_SIZE; + addr = bus->mmio + offset; + + switch (reg_width) { + case sizeof(u8): { + u8 *buf = buffer; + + while (count) { + *buf = __raw_readb(addr); + buf++; + count--; + } + break; + } + case sizeof(u16): { + __le16 *buf = buffer; + + WARN_ON(count & 1); + while (count) { + *buf = (__force __le16)__raw_readw(addr); + buf++; + count -= 2; + } + break; + } + case sizeof(u32): { + __le32 *buf = buffer; + + WARN_ON(count & 3); + while (count) { + *buf = (__force __le32)__raw_readl(addr); + buf++; + count -= 4; + } + break; + } + default: + WARN_ON(1); + } +} +#endif /* CONFIG_SSB_BLOCKIO */ + +static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + writeb(value, bus->mmio + offset); +} + +static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + writew(value, bus->mmio + offset); +} + +static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value) +{ + struct ssb_bus *bus = dev->bus; + + offset += dev->core_index * SSB_CORE_SIZE; + writel(value, bus->mmio + offset); +} + +#ifdef CONFIG_SSB_BLOCKIO +static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + struct ssb_bus *bus = dev->bus; + void __iomem *addr; + + offset += dev->core_index * SSB_CORE_SIZE; + addr = bus->mmio + offset; + + switch (reg_width) { + case sizeof(u8): { + const u8 *buf = buffer; + + while (count) { + __raw_writeb(*buf, addr); + buf++; + count--; + } + break; + } + case sizeof(u16): { + const __le16 *buf = buffer; + + WARN_ON(count & 1); + while (count) { + __raw_writew((__force u16)(*buf), addr); + buf++; + count -= 2; + } + break; + } + case sizeof(u32): { + const __le32 *buf = buffer; + + WARN_ON(count & 3); + while (count) { + __raw_writel((__force u32)(*buf), addr); + buf++; + count -= 4; + } + break; + } + default: + WARN_ON(1); + } +} +#endif /* CONFIG_SSB_BLOCKIO */ + +/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ +const struct ssb_bus_ops ssb_host_soc_ops = { + .read8 = ssb_host_soc_read8, + .read16 = ssb_host_soc_read16, + .read32 = ssb_host_soc_read32, + .write8 = ssb_host_soc_write8, + .write16 = ssb_host_soc_write16, + .write32 = ssb_host_soc_write32, +#ifdef CONFIG_SSB_BLOCKIO + .block_read = ssb_host_soc_block_read, + .block_write = ssb_host_soc_block_write, +#endif +}; + +int ssb_host_soc_get_invariants(struct ssb_bus *bus, + struct ssb_init_invariants *iv) +{ + char buf[20]; + int len, err; + + /* Fill boardinfo structure */ + memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo)); + + len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf)); + if (len > 0) { + err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor); + if (err) + pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n", + buf); + } + if (!iv->boardinfo.vendor) + iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; + + len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)); + if (len > 0) { + err = kstrtou16(strim(buf), 0, &iv->boardinfo.type); + if (err) + pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n", + buf); + } + + memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); + ssb_fill_sprom_with_fallback(bus, &iv->sprom); + + if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) + iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); + + return 0; +} diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index e55ddf7cd7c2..aa6165e3db4a 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -37,7 +37,8 @@ static LIST_HEAD(buses); /* Software ID counter */ static unsigned int next_busnumber; /* buses_mutes locks the two buslists and the next_busnumber. - * Don't lock this directly, but use ssb_buses_[un]lock() below. */ + * Don't lock this directly, but use ssb_buses_[un]lock() below. + */ static DEFINE_MUTEX(buses_mutex); /* There are differences in the codeflow, if the bus is @@ -45,7 +46,8 @@ static DEFINE_MUTEX(buses_mutex); * are not available early. This is a mechanism to delay * these initializations to after early boot has finished. * It's also used to avoid mutex locking, as that's not - * available and needed early. */ + * available and needed early. + */ static bool ssb_is_early_boot = 1; static void ssb_buses_lock(void); @@ -90,25 +92,6 @@ found: } #endif /* CONFIG_SSB_PCMCIAHOST */ -#ifdef CONFIG_SSB_SDIOHOST -struct ssb_bus *ssb_sdio_func_to_bus(struct sdio_func *func) -{ - struct ssb_bus *bus; - - ssb_buses_lock(); - list_for_each_entry(bus, &buses, list) { - if (bus->bustype == SSB_BUSTYPE_SDIO && - bus->host_sdio == func) - goto found; - } - bus = NULL; -found: - ssb_buses_unlock(); - - return bus; -} -#endif /* CONFIG_SSB_SDIOHOST */ - int ssb_for_each_bus_call(unsigned long data, int (*func)(struct ssb_bus *bus, unsigned long data)) { @@ -180,7 +163,8 @@ int ssb_bus_resume(struct ssb_bus *bus) int err; /* Reset HW state information in memory, so that HW is - * completely reinitialized. */ + * completely reinitialized. + */ bus->mapped_device = NULL; #ifdef CONFIG_SSB_DRIVER_PCICORE bus->pcicore.setup_done = 0; @@ -228,7 +212,7 @@ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) memset(ctx, 0, sizeof(*ctx)); ctx->bus = bus; - SSB_WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen)); + WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen)); for (i = 0; i < bus->nr_devices; i++) { sdev = ssb_device_get(&bus->devices[i]); @@ -239,7 +223,7 @@ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) continue; } sdrv = drv_to_ssb_drv(sdev->dev->driver); - if (SSB_WARN_ON(!sdrv->remove)) + if (WARN_ON(!sdrv->remove)) continue; sdrv->remove(sdev); ctx->device_frozen[i] = 1; @@ -267,15 +251,16 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) continue; sdev = &bus->devices[i]; - if (SSB_WARN_ON(!sdev->dev || !sdev->dev->driver)) + if (WARN_ON(!sdev->dev || !sdev->dev->driver)) continue; sdrv = drv_to_ssb_drv(sdev->dev->driver); - if (SSB_WARN_ON(!sdrv || !sdrv->probe)) + if (WARN_ON(!sdrv || !sdrv->probe)) continue; err = sdrv->probe(sdev, &sdev->id); if (err) { - ssb_err("Failed to thaw device %s\n", + dev_err(sdev->dev, + "Failed to thaw device %s\n", dev_name(sdev->dev)); result = err; } @@ -298,7 +283,7 @@ static void ssb_device_shutdown(struct device *dev) ssb_drv->shutdown(ssb_dev); } -static int ssb_device_remove(struct device *dev) +static void ssb_device_remove(struct device *dev) { struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver); @@ -306,8 +291,6 @@ static int ssb_device_remove(struct device *dev) if (ssb_drv && ssb_drv->remove) ssb_drv->remove(ssb_dev); ssb_device_put(ssb_dev); - - return 0; } static int ssb_device_probe(struct device *dev) @@ -340,10 +323,10 @@ static int ssb_match_devid(const struct ssb_device_id *tabid, return 1; } -static int ssb_bus_match(struct device *dev, struct device_driver *drv) +static int ssb_bus_match(struct device *dev, const struct device_driver *drv) { struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); - struct ssb_driver *ssb_drv = drv_to_ssb_drv(drv); + const struct ssb_driver *ssb_drv = drv_to_ssb_drv(drv); const struct ssb_device_id *id; for (id = ssb_drv->id_table; @@ -356,13 +339,15 @@ static int ssb_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int ssb_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ssb_device_uevent(const struct device *dev, struct kobj_uevent_env *env) { - struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); + const struct ssb_device *ssb_dev; if (!dev) return -ENODEV; + ssb_dev = dev_to_ssb_dev(dev); + return add_uevent_var(env, "MODALIAS=ssb:v%04Xid%04Xrev%02X", ssb_dev->id.vendor, ssb_dev->id.coreid, @@ -374,7 +359,8 @@ static ssize_t \ attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \ -} +} \ +static DEVICE_ATTR_RO(attrib); ssb_config_attr(core_num, core_index, "%u\n") ssb_config_attr(coreid, id.coreid, "0x%04x\n") @@ -387,18 +373,20 @@ name_show(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s\n", ssb_core_name(dev_to_ssb_dev(dev)->id.coreid)); } - -static struct device_attribute ssb_device_attrs[] = { - __ATTR_RO(name), - __ATTR_RO(core_num), - __ATTR_RO(coreid), - __ATTR_RO(vendor), - __ATTR_RO(revision), - __ATTR_RO(irq), - __ATTR_NULL, +static DEVICE_ATTR_RO(name); + +static struct attribute *ssb_device_attrs[] = { + &dev_attr_name.attr, + &dev_attr_core_num.attr, + &dev_attr_coreid.attr, + &dev_attr_vendor.attr, + &dev_attr_revision.attr, + &dev_attr_irq.attr, + NULL, }; +ATTRIBUTE_GROUPS(ssb_device); -static struct bus_type ssb_bustype = { +static const struct bus_type ssb_bustype = { .name = "ssb", .match = ssb_bus_match, .probe = ssb_device_probe, @@ -407,7 +395,7 @@ static struct bus_type ssb_bustype = { .suspend = ssb_device_suspend, .resume = ssb_device_resume, .uevent = ssb_device_uevent, - .dev_attrs = ssb_device_attrs, + .dev_groups = ssb_device_groups, }; static void ssb_buses_lock(void) @@ -446,10 +434,8 @@ void ssb_bus_unregister(struct ssb_bus *bus) int err; err = ssb_gpio_unregister(bus); - if (err == -EBUSY) - ssb_dbg("Some GPIOs are still in use\n"); - else if (err) - ssb_dbg("Can not unregister GPIO driver: %i\n", err); + if (err) + pr_debug("Can not unregister GPIO driver: %i\n", err); ssb_buses_lock(); ssb_devices_unregister(bus); @@ -482,7 +468,8 @@ static int ssb_devices_register(struct ssb_bus *bus) sdev = &(bus->devices[i]); /* We don't register SSB-system devices to the kernel, - * as the drivers for them are built into SSB. */ + * as the drivers for them are built into SSB. + */ switch (sdev->id.coreid) { case SSB_DEV_CHIPCOMMON: case SSB_DEV_PCI: @@ -496,7 +483,6 @@ static int ssb_devices_register(struct ssb_bus *bus) devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); if (!devwrap) { - ssb_err("Could not allocate device\n"); err = -ENOMEM; goto error; } @@ -535,11 +521,12 @@ static int ssb_devices_register(struct ssb_bus *bus) sdev->dev = dev; err = device_register(dev); if (err) { - ssb_err("Could not register %s\n", dev_name(dev)); + pr_err("Could not register %s\n", dev_name(dev)); /* Set dev to NULL to not unregister - * dev on error unwinding. */ + * dev on error unwinding. + */ sdev->dev = NULL; - kfree(devwrap); + put_device(dev); goto error; } dev_idx++; @@ -590,6 +577,13 @@ static int ssb_attach_queued_buses(void) ssb_pcicore_init(&bus->pcicore); if (bus->bustype == SSB_BUSTYPE_SSB) ssb_watchdog_register(bus); + + err = ssb_gpio_init(bus); + if (err == -ENOTSUPP) + pr_debug("GPIO driver not activated\n"); + else if (err) + pr_debug("Error registering GPIO driver: %i\n", err); + ssb_bus_may_powerdown(bus); err = ssb_devices_register(bus); @@ -605,166 +599,6 @@ error: return err; } -static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - return readb(bus->mmio + offset); -} - -static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - return readw(bus->mmio + offset); -} - -static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - return readl(bus->mmio + offset); -} - -#ifdef CONFIG_SSB_BLOCKIO -static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, - size_t count, u16 offset, u8 reg_width) -{ - struct ssb_bus *bus = dev->bus; - void __iomem *addr; - - offset += dev->core_index * SSB_CORE_SIZE; - addr = bus->mmio + offset; - - switch (reg_width) { - case sizeof(u8): { - u8 *buf = buffer; - - while (count) { - *buf = __raw_readb(addr); - buf++; - count--; - } - break; - } - case sizeof(u16): { - __le16 *buf = buffer; - - SSB_WARN_ON(count & 1); - while (count) { - *buf = (__force __le16)__raw_readw(addr); - buf++; - count -= 2; - } - break; - } - case sizeof(u32): { - __le32 *buf = buffer; - - SSB_WARN_ON(count & 3); - while (count) { - *buf = (__force __le32)__raw_readl(addr); - buf++; - count -= 4; - } - break; - } - default: - SSB_WARN_ON(1); - } -} -#endif /* CONFIG_SSB_BLOCKIO */ - -static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - writeb(value, bus->mmio + offset); -} - -static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - writew(value, bus->mmio + offset); -} - -static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) -{ - struct ssb_bus *bus = dev->bus; - - offset += dev->core_index * SSB_CORE_SIZE; - writel(value, bus->mmio + offset); -} - -#ifdef CONFIG_SSB_BLOCKIO -static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, - size_t count, u16 offset, u8 reg_width) -{ - struct ssb_bus *bus = dev->bus; - void __iomem *addr; - - offset += dev->core_index * SSB_CORE_SIZE; - addr = bus->mmio + offset; - - switch (reg_width) { - case sizeof(u8): { - const u8 *buf = buffer; - - while (count) { - __raw_writeb(*buf, addr); - buf++; - count--; - } - break; - } - case sizeof(u16): { - const __le16 *buf = buffer; - - SSB_WARN_ON(count & 1); - while (count) { - __raw_writew((__force u16)(*buf), addr); - buf++; - count -= 2; - } - break; - } - case sizeof(u32): { - const __le32 *buf = buffer; - - SSB_WARN_ON(count & 3); - while (count) { - __raw_writel((__force u32)(*buf), addr); - buf++; - count -= 4; - } - break; - } - default: - SSB_WARN_ON(1); - } -} -#endif /* CONFIG_SSB_BLOCKIO */ - -/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ -static const struct ssb_bus_ops ssb_ssb_ops = { - .read8 = ssb_ssb_read8, - .read16 = ssb_ssb_read16, - .read32 = ssb_ssb_read32, - .write8 = ssb_ssb_write8, - .write16 = ssb_ssb_write16, - .write32 = ssb_ssb_write32, -#ifdef CONFIG_SSB_BLOCKIO - .block_read = ssb_ssb_block_read, - .block_write = ssb_ssb_block_write, -#endif -}; - static int ssb_fetch_invariants(struct ssb_bus *bus, ssb_invariants_func_t get_invariants) { @@ -782,9 +616,10 @@ out: return err; } -static int ssb_bus_register(struct ssb_bus *bus, - ssb_invariants_func_t get_invariants, - unsigned long baseaddr) +static int __maybe_unused +ssb_bus_register(struct ssb_bus *bus, + ssb_invariants_func_t get_invariants, + unsigned long baseaddr) { int err; @@ -827,11 +662,6 @@ static int ssb_bus_register(struct ssb_bus *bus, ssb_chipcommon_init(&bus->chipco); ssb_extif_init(&bus->extif); ssb_mipscore_init(&bus->mipscore); - err = ssb_gpio_init(bus); - if (err == -ENOTSUPP) - ssb_dbg("GPIO driver not activated\n"); - else if (err) - ssb_dbg("Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); @@ -840,7 +670,8 @@ static int ssb_bus_register(struct ssb_bus *bus, ssb_bus_may_powerdown(bus); /* Queue it for attach. - * See the comment at the ssb_is_early_boot definition. */ + * See the comment at the ssb_is_early_boot definition. + */ list_add_tail(&bus->list, &attach_queue); if (!ssb_is_early_boot) { /* This is not early boot, so we must attach the bus now */ @@ -881,16 +712,17 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci) err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); if (!err) { - ssb_info("Sonics Silicon Backplane found on PCI device %s\n", + dev_info(&host_pci->dev, + "Sonics Silicon Backplane found on PCI device %s\n", dev_name(&host_pci->dev)); } else { - ssb_err("Failed to register PCI version of SSB with error %d\n", + dev_err(&host_pci->dev, + "Failed to register PCI version of SSB with error %d\n", err); } return err; } -EXPORT_SYMBOL(ssb_bus_pcibus_register); #endif /* CONFIG_SSB_PCIHOST */ #ifdef CONFIG_SSB_PCMCIAHOST @@ -906,13 +738,13 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus, err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); if (!err) { - ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n", + dev_info(&pcmcia_dev->dev, + "Sonics Silicon Backplane found on PCMCIA device %s\n", pcmcia_dev->devname); } return err; } -EXPORT_SYMBOL(ssb_bus_pcmciabus_register); #endif /* CONFIG_SSB_PCMCIAHOST */ #ifdef CONFIG_SSB_SDIOHOST @@ -928,7 +760,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); if (!err) { - ssb_info("Sonics Silicon Backplane found on SDIO device %s\n", + dev_info(&func->dev, + "Sonics Silicon Backplane found on SDIO device %s\n", sdio_func_id(func)); } @@ -937,22 +770,23 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, EXPORT_SYMBOL(ssb_bus_sdiobus_register); #endif /* CONFIG_SSB_PCMCIAHOST */ -int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, - ssb_invariants_func_t get_invariants) +#ifdef CONFIG_SSB_HOST_SOC +int ssb_bus_host_soc_register(struct ssb_bus *bus, unsigned long baseaddr) { int err; bus->bustype = SSB_BUSTYPE_SSB; - bus->ops = &ssb_ssb_ops; + bus->ops = &ssb_host_soc_ops; - err = ssb_bus_register(bus, get_invariants, baseaddr); + err = ssb_bus_register(bus, ssb_host_soc_get_invariants, baseaddr); if (!err) { - ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n", - baseaddr); + pr_info("Sonics Silicon Backplane found at address 0x%08lX\n", + baseaddr); } return err; } +#endif int __ssb_driver_register(struct ssb_driver *drv, struct module *owner) { @@ -1005,7 +839,7 @@ static u32 clkfactor_f6_resolve(u32 v) case SSB_CHIPCO_CLK_F6_7: return 7; } - return 0; + return 1; } /* Calculate the speed the backplane would run at a given set of clockcontrol values */ @@ -1031,13 +865,13 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m) case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */ n1 += SSB_CHIPCO_CLK_T2_BIAS; n2 += SSB_CHIPCO_CLK_T2_BIAS; - SSB_WARN_ON(!((n1 >= 2) && (n1 <= 7))); - SSB_WARN_ON(!((n2 >= 5) && (n2 <= 23))); + WARN_ON(!((n1 >= 2) && (n1 <= 7))); + WARN_ON(!((n2 >= 5) && (n2 <= 23))); break; case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */ return 100000000; default: - SSB_WARN_ON(1); + WARN_ON(1); } switch (plltype) { @@ -1086,9 +920,9 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m) m1 += SSB_CHIPCO_CLK_T2_BIAS; m2 += SSB_CHIPCO_CLK_T2M2_BIAS; m3 += SSB_CHIPCO_CLK_T2_BIAS; - SSB_WARN_ON(!((m1 >= 2) && (m1 <= 7))); - SSB_WARN_ON(!((m2 >= 3) && (m2 <= 10))); - SSB_WARN_ON(!((m3 >= 2) && (m3 <= 7))); + WARN_ON(!((m1 >= 2) && (m1 <= 7))); + WARN_ON(!((m2 >= 3) && (m2 <= 10))); + WARN_ON(!((m3 >= 2) && (m3 <= 7))); if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP)) clock /= m1; @@ -1098,7 +932,7 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m) clock /= m3; return clock; default: - SSB_WARN_ON(1); + WARN_ON(1); } return 0; } @@ -1149,6 +983,8 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev) case SSB_IDLOW_SSBREV_25: /* TODO - find the proper REJECT bit */ case SSB_IDLOW_SSBREV_27: /* same here */ return SSB_TMSLOW_REJECT; /* this is a guess */ + case SSB_IDLOW_SSBREV: + break; default: WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); } @@ -1175,7 +1011,8 @@ static void ssb_flush_tmslow(struct ssb_device *dev) * a machine check exception otherwise. * Do this by reading the register back to commit the * PCI write and delay an additional usec for the device - * to react to the change. */ + * to react to the change. + */ ssb_read32(dev, SSB_TMSLOW); udelay(1); } @@ -1212,7 +1049,8 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags) EXPORT_SYMBOL(ssb_device_enable); /* Wait for bitmask in a register to get set or cleared. - * timeout is in units of ten-microseconds */ + * timeout is in units of ten-microseconds + */ static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, int timeout, int set) { @@ -1230,9 +1068,9 @@ static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, } udelay(10); } - printk(KERN_ERR PFX "Timeout waiting for bitmask %08X on " - "register %04X to %s.\n", - bitmask, reg, (set ? "set" : "clear")); + dev_err(dev->dev, + "Timeout waiting for bitmask %08X on register %04X to %s\n", + bitmask, reg, set ? "set" : "clear"); return -ETIMEDOUT; } @@ -1289,7 +1127,7 @@ static bool ssb_dma_translation_special_bit(struct ssb_device *dev) chip_id == 43231 || chip_id == 43222); } - return 0; + return false; } u32 ssb_dma_translation(struct ssb_device *dev) @@ -1308,7 +1146,7 @@ u32 ssb_dma_translation(struct ssb_device *dev) return SSB_PCI_DMA; } default: - __ssb_dma_not_implemented(dev); + break; } return 0; } @@ -1321,7 +1159,8 @@ int ssb_bus_may_powerdown(struct ssb_bus *bus) /* On buses where more than one core may be working * at a time, we must not powerdown stuff if there are - * still cores that may want to run. */ + * still cores that may want to run. + */ if (bus->bustype == SSB_BUSTYPE_SSB) goto out; @@ -1337,12 +1176,10 @@ int ssb_bus_may_powerdown(struct ssb_bus *bus) if (err) goto error; out: -#ifdef CONFIG_SSB_DEBUG bus->powered_up = 0; -#endif return err; error: - ssb_err("Bus powerdown failed\n"); + pr_err("Bus powerdown failed\n"); goto out; } EXPORT_SYMBOL(ssb_bus_may_powerdown); @@ -1356,16 +1193,14 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) if (err) goto error; -#ifdef CONFIG_SSB_DEBUG bus->powered_up = 1; -#endif mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; ssb_chipco_set_clockmode(&bus->chipco, mode); return 0; error: - ssb_err("Bus powerup failed\n"); + pr_err("Bus powerup failed\n"); return err; } EXPORT_SYMBOL(ssb_bus_powerup); @@ -1410,15 +1245,15 @@ u32 ssb_admatch_base(u32 adm) base = (adm & SSB_ADM_BASE0); break; case SSB_ADM_TYPE1: - SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ + WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ base = (adm & SSB_ADM_BASE1); break; case SSB_ADM_TYPE2: - SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ + WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ base = (adm & SSB_ADM_BASE2); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } return base; @@ -1434,15 +1269,15 @@ u32 ssb_admatch_size(u32 adm) size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT); break; case SSB_ADM_TYPE1: - SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ + WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT); break; case SSB_ADM_TYPE2: - SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ + WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } size = (1 << (size + 1)); @@ -1473,13 +1308,17 @@ static int __init ssb_modinit(void) err = b43_pci_ssb_bridge_init(); if (err) { - ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); + pr_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); + /* don't fail SSB init because of this */ + } + err = ssb_host_pcmcia_init(); + if (err) { + pr_err("PCMCIA host initialization failed\n"); /* don't fail SSB init because of this */ - err = 0; } err = ssb_gige_init(); if (err) { - ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); + pr_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); /* don't fail SSB init because of this */ err = 0; } @@ -1488,12 +1327,14 @@ out: } /* ssb must be initialized after PCI but before the ssb drivers. * That means we must use some initcall between subsys_initcall - * and device_initcall. */ + * and device_initcall. + */ fs_initcall(ssb_modinit); static void __exit ssb_modexit(void) { ssb_gige_exit(); + ssb_host_pcmcia_exit(); b43_pci_ssb_bridge_exit(); bus_unregister(&ssb_bustype); } diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index a8dc95ebf2d6..493bebbba521 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -15,14 +15,14 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/delay.h> -#include "ssb_private.h" - /* Define the following to 1 to enable a printk on each coreswitch. */ #define SSB_VERBOSE_PCICORESWITCH_DEBUG 0 @@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) } return 0; error: - ssb_err("Failed to switch to core %u\n", coreidx); + pr_err("Failed to switch to core %u\n", coreidx); return -ENODEV; } @@ -67,9 +67,8 @@ int ssb_pci_switch_core(struct ssb_bus *bus, unsigned long flags; #if SSB_VERBOSE_PCICORESWITCH_DEBUG - ssb_info("Switching to %s core, index %d\n", - ssb_core_name(dev->id.coreid), - dev->core_index); + pr_info("Switching to %s core, index %d\n", + ssb_core_name(dev->id.coreid), dev->core_index); #endif spin_lock_irqsave(&bus->bar_lock, flags); @@ -161,7 +160,7 @@ out: return err; err_pci: - printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n"); + pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n"); err = -EBUSY; goto out; } @@ -286,7 +285,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) u32 spromctl; u16 size = bus->sprom_size; - ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); if (err) goto err_ctlreg; @@ -294,19 +293,18 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); if (err) goto err_ctlreg; - ssb_notice("[ 0%%"); + pr_notice("[ 0%%"); msleep(500); for (i = 0; i < size; i++) { if (i == size / 4) - ssb_cont("25%%"); + pr_cont("25%%"); else if (i == size / 2) - ssb_cont("50%%"); + pr_cont("50%%"); else if (i == (size * 3) / 4) - ssb_cont("75%%"); + pr_cont("75%%"); else if (i % 2) - ssb_cont("."); + pr_cont("."); writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); - mmiowb(); msleep(20); } err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); @@ -317,22 +315,22 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) if (err) goto err_ctlreg; msleep(500); - ssb_cont("100%% ]\n"); - ssb_notice("SPROM written\n"); + pr_cont("100%% ]\n"); + pr_notice("SPROM written\n"); return 0; err_ctlreg: - ssb_err("Could not access SPROM control register.\n"); + pr_err("Could not access SPROM control register.\n"); return err; } -static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, - u16 mask, u16 shift) +static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, + u16 mask, u16 shift) { u16 v; u8 gain; - v = in[SPOFF(SSB_SPROM1_AGAIN)]; + v = in[SPOFF(offset)]; gain = (v & mask) >> shift; if (gain == 0xFF) gain = 2; /* If unset use 2dBm */ @@ -416,12 +414,14 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); /* Extract the antenna gain values. */ - out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); - out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN_A, - SSB_SPROM1_AGAIN_A_SHIFT); + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN, + SSB_SPROM1_AGAIN_BG, + SSB_SPROM1_AGAIN_BG_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN, + SSB_SPROM1_AGAIN_A, + SSB_SPROM1_AGAIN_A_SHIFT); if (out->revision >= 2) sprom_extract_r23(out, in); } @@ -468,7 +468,15 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) { + static const u16 pwr_info_offset[] = { + SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, + SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 + }; u16 il0mac_offset; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != + ARRAY_SIZE(out->core_pwr_info)); if (out->revision == 4) il0mac_offset = SSB_SPROM4_IL0MAC; @@ -524,14 +532,59 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) } /* Extract the antenna gain values. */ - SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); - SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); - SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); - SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN0, + SSB_SPROM4_AGAIN0_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN1, + SSB_SPROM4_AGAIN1_SHIFT); + out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN2, + SSB_SPROM4_AGAIN2_SHIFT); + out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, + SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN3, + SSB_SPROM4_AGAIN3_SHIFT); + + /* Extract cores power info info */ + for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { + u16 o = pwr_info_offset[i]; + + SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, + SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, + SSB_SPROM4_2G_MAXP, 0); + + SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); + + SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, + SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); + SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, + SSB_SPROM4_5G_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, + SSB_SPROM4_5GH_MAXP, 0); + SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, + SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); + + SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); + } sprom_extract_r458(out, in); @@ -542,7 +595,7 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) { int i; u16 o; - u16 pwr_info_offset[] = { + static const u16 pwr_info_offset[] = { SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 }; @@ -621,14 +674,22 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); /* Extract the antenna gain values. */ - SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); - SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); - SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); - SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); + out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN0, + SSB_SPROM8_AGAIN0_SHIFT); + out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN01, + SSB_SPROM8_AGAIN1, + SSB_SPROM8_AGAIN1_SHIFT); + out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN2, + SSB_SPROM8_AGAIN2_SHIFT); + out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, + SSB_SPROM8_AGAIN23, + SSB_SPROM8_AGAIN3, + SSB_SPROM8_AGAIN3_SHIFT); /* Extract cores power info info */ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { @@ -753,7 +814,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, memset(out, 0, sizeof(*out)); out->revision = in[size - 1] & 0x00FF; - ssb_dbg("SPROM revision %d detected\n", out->revision); + pr_debug("SPROM revision %d detected\n", out->revision); memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ memset(out->et1mac, 0xFF, 6); @@ -762,7 +823,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, * number stored in the SPROM. * Always extract r1. */ out->revision = 1; - ssb_dbg("SPROM treated as revision %d\n", out->revision); + pr_debug("SPROM treated as revision %d\n", out->revision); } switch (out->revision) { @@ -779,8 +840,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, sprom_extract_r8(out, in); break; default: - ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", - out->revision); + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + out->revision); out->revision = 1; sprom_extract_r123(out, in); } @@ -800,7 +861,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, u16 *buf; if (!ssb_is_sprom_available(bus)) { - ssb_err("No SPROM available!\n"); + pr_err("No SPROM available!\n"); return -ENODEV; } if (bus->chipco.dev) { /* can be unavailable! */ @@ -819,7 +880,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, } else { bus->sprom_offset = SSB_SPROM_BASE1; } - ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); + pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset); buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); if (!buf) @@ -844,15 +905,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, * available for this device in some other storage */ err = ssb_fill_sprom_with_fallback(bus, sprom); if (err) { - ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", - err); + pr_warn("WARNING: Using fallback SPROM failed (err %d)\n", + err); + goto out_free; } else { - ssb_dbg("Using SPROM revision %d provided by platform\n", - sprom->revision); + pr_debug("Using SPROM revision %d provided by platform\n", + sprom->revision); err = 0; goto out_free; } - ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); } } err = sprom_extract(bus, sprom, buf, bus->sprom_size); @@ -883,14 +944,12 @@ out: return err; } -#ifdef CONFIG_SSB_DEBUG static int ssb_pci_assert_buspower(struct ssb_bus *bus) { if (likely(bus->powered_up)) return 0; - printk(KERN_ERR PFX "FATAL ERROR: Bus powered down " - "while accessing PCI MMIO space\n"); + pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n"); if (bus->power_warn_count <= 10) { bus->power_warn_count++; dump_stack(); @@ -898,12 +957,6 @@ static int ssb_pci_assert_buspower(struct ssb_bus *bus) return -ENODEV; } -#else /* DEBUG */ -static inline int ssb_pci_assert_buspower(struct ssb_bus *bus) -{ - return 0; -} -#endif /* DEBUG */ static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset) { @@ -962,15 +1015,15 @@ static void ssb_pci_block_read(struct ssb_device *dev, void *buffer, ioread8_rep(addr, buffer, count); break; case sizeof(u16): - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); ioread16_rep(addr, buffer, count >> 1); break; case sizeof(u32): - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); ioread32_rep(addr, buffer, count >> 2); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } return; @@ -1036,15 +1089,15 @@ static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer, iowrite8_rep(addr, buffer, count); break; case sizeof(u16): - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); iowrite16_rep(addr, buffer, count >> 1); break; case sizeof(u32): - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); iowrite32_rep(addr, buffer, count >> 2); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } } #endif /* CONFIG_SSB_BLOCKIO */ @@ -1063,9 +1116,9 @@ const struct ssb_bus_ops ssb_pci_ops = { #endif }; -static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, - struct device_attribute *attr, - char *buf) +static ssize_t ssb_sprom_show(struct device *pcidev, + struct device_attribute *attr, + char *buf) { struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); struct ssb_bus *bus; @@ -1077,9 +1130,9 @@ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, return ssb_attr_sprom_show(bus, buf, sprom_do_read); } -static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t ssb_sprom_store(struct device *pcidev, + struct device_attribute *attr, + const char *buf, size_t count) { struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); struct ssb_bus *bus; @@ -1092,9 +1145,7 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, sprom_check_crc, sprom_do_write); } -static DEVICE_ATTR(ssb_sprom, 0600, - ssb_pci_attr_sprom_show, - ssb_pci_attr_sprom_store); +static DEVICE_ATTR_ADMIN_RW(ssb_sprom); void ssb_pci_exit(struct ssb_bus *bus) { @@ -1110,17 +1161,12 @@ void ssb_pci_exit(struct ssb_bus *bus) int ssb_pci_init(struct ssb_bus *bus) { struct pci_dev *pdev; - int err; if (bus->bustype != SSB_BUSTYPE_PCI) return 0; pdev = bus->host_pci; mutex_init(&bus->sprom_mutex); - err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom); - if (err) - goto out; -out: - return err; + return device_create_file(&pdev->dev, &dev_attr_ssb_sprom); } diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c index 69161bbc4d0b..dd70fd41c77d 100644 --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c @@ -11,15 +11,17 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include <linux/pm.h> #include <linux/pci.h> #include <linux/export.h> #include <linux/slab.h> #include <linux/ssb/ssb.h> -#ifdef CONFIG_PM -static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int ssb_pcihost_suspend(struct device *d) { + struct pci_dev *dev = to_pci_dev(d); struct ssb_bus *ssb = pci_get_drvdata(dev); int err; @@ -28,17 +30,23 @@ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state) return err; pci_save_state(dev); pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); + + /* if there is a wakeup enabled child device on ssb bus, + enable pci wakeup posibility. */ + device_set_wakeup_enable(d, d->power.wakeup_path); + + pci_prepare_to_sleep(dev); return 0; } -static int ssb_pcihost_resume(struct pci_dev *dev) +static int ssb_pcihost_resume(struct device *d) { + struct pci_dev *dev = to_pci_dev(d); struct ssb_bus *ssb = pci_get_drvdata(dev); int err; - pci_set_power_state(dev, PCI_D0); + pci_back_from_sleep(dev); err = pci_enable_device(dev); if (err) return err; @@ -49,17 +57,18 @@ static int ssb_pcihost_resume(struct pci_dev *dev) return 0; } -#else /* CONFIG_PM */ -# define ssb_pcihost_suspend NULL -# define ssb_pcihost_resume NULL -#endif /* CONFIG_PM */ + +static const struct dev_pm_ops ssb_pcihost_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume) +}; + +#endif /* CONFIG_PM_SLEEP */ static int ssb_pcihost_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct ssb_bus *ssb; int err = -ENOMEM; - const char *name; u32 val; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); @@ -68,10 +77,7 @@ static int ssb_pcihost_probe(struct pci_dev *dev, err = pci_enable_device(dev); if (err) goto err_kfree_ssb; - name = dev_name(&dev->dev); - if (dev->driver && dev->driver->name) - name = dev->driver->name; - err = pci_request_regions(dev, name); + err = pci_request_regions(dev, dev_driver_string(&dev->dev)); if (err) goto err_pci_disable; pci_set_master(dev); @@ -115,8 +121,9 @@ int ssb_pcihost_register(struct pci_driver *driver) { driver->probe = ssb_pcihost_probe; driver->remove = ssb_pcihost_remove; - driver->suspend = ssb_pcihost_suspend; - driver->resume = ssb_pcihost_resume; +#ifdef CONFIG_PM_SLEEP + driver->driver.pm = &ssb_pcihost_pm_ops; +#endif return pci_register_driver(driver); } diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index b413e0187087..45502098e0c7 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -8,6 +8,8 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/delay.h> #include <linux/io.h> @@ -18,8 +20,6 @@ #include <pcmcia/ds.h> #include <pcmcia/cisreg.h> -#include "ssb_private.h" - /* Define the following to 1 to enable a printk on each coreswitch. */ #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0 @@ -143,19 +143,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, return 0; error: - ssb_err("Failed to switch to core %u\n", coreidx); + pr_err("Failed to switch to core %u\n", coreidx); return err; } -int ssb_pcmcia_switch_core(struct ssb_bus *bus, - struct ssb_device *dev) +static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev) { int err; #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG - ssb_info("Switching to %s core, index %d\n", - ssb_core_name(dev->id.coreid), - dev->core_index); + pr_info("Switching to %s core, index %d\n", + ssb_core_name(dev->id.coreid), dev->core_index); #endif err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); @@ -171,7 +169,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) int err; u8 val; - SSB_WARN_ON((seg != 0) && (seg != 1)); + WARN_ON((seg != 0) && (seg != 1)); while (1) { err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg); if (err) @@ -191,7 +189,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) return 0; error: - ssb_err("Failed to switch pcmcia segment\n"); + pr_err("Failed to switch pcmcia segment\n"); return err; } @@ -301,7 +299,7 @@ static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer, case sizeof(u16): { __le16 *buf = buffer; - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); while (count) { *buf = (__force __le16)__raw_readw(addr); buf++; @@ -312,7 +310,7 @@ static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer, case sizeof(u32): { __le16 *buf = buffer; - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); while (count) { *buf = (__force __le16)__raw_readw(addr); buf++; @@ -323,7 +321,7 @@ static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer, break; } default: - SSB_WARN_ON(1); + WARN_ON(1); } unlock: spin_unlock_irqrestore(&bus->bar_lock, flags); @@ -340,7 +338,6 @@ static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value) err = select_core_and_segment(dev, &offset); if (likely(!err)) writeb(value, bus->mmio + offset); - mmiowb(); spin_unlock_irqrestore(&bus->bar_lock, flags); } @@ -354,7 +351,6 @@ static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) err = select_core_and_segment(dev, &offset); if (likely(!err)) writew(value, bus->mmio + offset); - mmiowb(); spin_unlock_irqrestore(&bus->bar_lock, flags); } @@ -370,7 +366,6 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) writew((value & 0x0000FFFF), bus->mmio + offset); writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2); } - mmiowb(); spin_unlock_irqrestore(&bus->bar_lock, flags); } @@ -401,7 +396,7 @@ static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer, case sizeof(u16): { const __le16 *buf = buffer; - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); while (count) { __raw_writew((__force u16)(*buf), addr); buf++; @@ -412,7 +407,7 @@ static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer, case sizeof(u32): { const __le16 *buf = buffer; - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); while (count) { __raw_writew((__force u16)(*buf), addr); buf++; @@ -423,10 +418,9 @@ static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer, break; } default: - SSB_WARN_ON(1); + WARN_ON(1); } unlock: - mmiowb(); spin_unlock_irqrestore(&bus->bar_lock, flags); } #endif /* CONFIG_SSB_BLOCKIO */ @@ -548,39 +542,39 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom) bool failed = 0; size_t size = SSB_PCMCIA_SPROM_SIZE; - ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); if (err) { - ssb_notice("Could not enable SPROM write access\n"); + pr_notice("Could not enable SPROM write access\n"); return -EBUSY; } - ssb_notice("[ 0%%"); + pr_notice("[ 0%%"); msleep(500); for (i = 0; i < size; i++) { if (i == size / 4) - ssb_cont("25%%"); + pr_cont("25%%"); else if (i == size / 2) - ssb_cont("50%%"); + pr_cont("50%%"); else if (i == (size * 3) / 4) - ssb_cont("75%%"); + pr_cont("75%%"); else if (i % 2) - ssb_cont("."); + pr_cont("."); err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); if (err) { - ssb_notice("Failed to write to SPROM\n"); + pr_notice("Failed to write to SPROM\n"); failed = 1; break; } } err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); if (err) { - ssb_notice("Could not disable SPROM write access\n"); + pr_notice("Could not disable SPROM write access\n"); failed = 1; } msleep(500); if (!failed) { - ssb_cont("100%% ]\n"); - ssb_notice("SPROM written\n"); + pr_cont("100%% ]\n"); + pr_notice("SPROM written\n"); } return failed ? -EBUSY : 0; @@ -694,9 +688,8 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, return -ENOSPC; /* continue with next entry */ error: - ssb_err( - "PCMCIA: Failed to fetch device invariants: %s\n", - error_description); + pr_err("PCMCIA: Failed to fetch device invariants: %s\n", + error_description); return -ENODEV; } @@ -716,8 +709,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, ssb_pcmcia_get_mac, sprom); if (res != 0) { - ssb_err( - "PCMCIA: Failed to fetch MAC address\n"); + pr_err("PCMCIA: Failed to fetch MAC address\n"); return -ENODEV; } @@ -727,14 +719,13 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus, if ((res == 0) || (res == -ENOSPC)) return 0; - ssb_err( - "PCMCIA: Failed to fetch device invariants\n"); + pr_err("PCMCIA: Failed to fetch device invariants\n"); return -ENODEV; } -static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev, - struct device_attribute *attr, - char *buf) +static ssize_t ssb_sprom_show(struct device *pcmciadev, + struct device_attribute *attr, + char *buf) { struct pcmcia_device *pdev = container_of(pcmciadev, struct pcmcia_device, dev); @@ -748,9 +739,9 @@ static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev, ssb_pcmcia_sprom_read_all); } -static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t ssb_sprom_store(struct device *pcmciadev, + struct device_attribute *attr, + const char *buf, size_t count) { struct pcmcia_device *pdev = container_of(pcmciadev, struct pcmcia_device, dev); @@ -765,9 +756,7 @@ static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev, ssb_pcmcia_sprom_write_all); } -static DEVICE_ATTR(ssb_sprom, 0600, - ssb_pcmcia_attr_sprom_show, - ssb_pcmcia_attr_sprom_store); +static DEVICE_ATTR_ADMIN_RW(ssb_sprom); static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor) { @@ -837,6 +826,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus) return 0; error: - ssb_err("Failed to initialize PCMCIA host device\n"); + pr_err("Failed to initialize PCMCIA host device\n"); return err; } diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index b9429df583eb..4161e5d1f276 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -12,6 +12,8 @@ * Licensed under the GNU/GPL. See COPYING for details. */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/pci.h> @@ -20,8 +22,6 @@ #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> -#include "ssb_private.h" - const char *ssb_core_name(u16 coreid) { @@ -125,7 +125,7 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev) chipid_fallback = 0x4401; break; default: - ssb_err("PCI-ID not in fallback list\n"); + dev_err(&pci_dev->dev, "PCI-ID not in fallback list\n"); } return chipid_fallback; @@ -151,7 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid) case 0x4704: return 9; default: - ssb_err("CHIPID not in nrcores fallback list\n"); + pr_err("CHIPID not in nrcores fallback list\n"); } return 1; @@ -210,7 +210,7 @@ void ssb_iounmap(struct ssb_bus *bus) #ifdef CONFIG_SSB_PCIHOST pci_iounmap(bus->host_pci, bus->mmio); #else - SSB_BUG_ON(1); /* Can't reach this code. */ + WARN_ON(1); /* Can't reach this code. */ #endif break; case SSB_BUSTYPE_SDIO: @@ -228,7 +228,7 @@ static void __iomem *ssb_ioremap(struct ssb_bus *bus, switch (bus->bustype) { case SSB_BUSTYPE_SSB: /* Only map the first core for now. */ - /* fallthrough... */ + fallthrough; case SSB_BUSTYPE_PCMCIA: mmio = ioremap(baseaddr, SSB_CORE_SIZE); break; @@ -236,7 +236,7 @@ static void __iomem *ssb_ioremap(struct ssb_bus *bus, #ifdef CONFIG_SSB_PCIHOST mmio = pci_iomap(bus->host_pci, 0, ~0UL); #else - SSB_BUG_ON(1); /* Can't reach this code. */ + WARN_ON(1); /* Can't reach this code. */ #endif break; case SSB_BUSTYPE_SDIO: @@ -318,13 +318,14 @@ int ssb_bus_scan(struct ssb_bus *bus, bus->chip_package = 0; } } - ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", - bus->chip_id, bus->chip_rev, bus->chip_package); + pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", + bus->chip_id, bus->chip_rev, bus->chip_package); if (!bus->nr_devices) bus->nr_devices = chipid_to_nrcores(bus->chip_id); if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { - ssb_err("More than %d ssb cores found (%d)\n", - SSB_MAX_NR_CORES, bus->nr_devices); + pr_err("More than %d ssb cores found (%d)\n", + SSB_MAX_NR_CORES, bus->nr_devices); + err = -EINVAL; goto err_unmap; } if (bus->bustype == SSB_BUSTYPE_SSB) { @@ -355,18 +356,16 @@ int ssb_bus_scan(struct ssb_bus *bus, dev->bus = bus; dev->ops = bus->ops; - printk(KERN_DEBUG PFX - "Core %d found: %s " - "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", - i, ssb_core_name(dev->id.coreid), - dev->id.coreid, dev->id.revision, dev->id.vendor); + pr_debug("Core %d found: %s (cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", + i, ssb_core_name(dev->id.coreid), + dev->id.coreid, dev->id.revision, dev->id.vendor); switch (dev->id.coreid) { case SSB_DEV_80211: nr_80211_cores++; if (nr_80211_cores > 1) { if (!we_support_multiple_80211_cores(bus)) { - ssb_dbg("Ignoring additional 802.11 core\n"); + pr_debug("Ignoring additional 802.11 core\n"); continue; } } @@ -374,7 +373,7 @@ int ssb_bus_scan(struct ssb_bus *bus, case SSB_DEV_EXTIF: #ifdef CONFIG_SSB_DRIVER_EXTIF if (bus->extif.dev) { - ssb_warn("WARNING: Multiple EXTIFs found\n"); + pr_warn("WARNING: Multiple EXTIFs found\n"); break; } bus->extif.dev = dev; @@ -382,7 +381,7 @@ int ssb_bus_scan(struct ssb_bus *bus, break; case SSB_DEV_CHIPCOMMON: if (bus->chipco.dev) { - ssb_warn("WARNING: Multiple ChipCommon found\n"); + pr_warn("WARNING: Multiple ChipCommon found\n"); break; } bus->chipco.dev = dev; @@ -391,7 +390,7 @@ int ssb_bus_scan(struct ssb_bus *bus, case SSB_DEV_MIPS_3302: #ifdef CONFIG_SSB_DRIVER_MIPS if (bus->mipscore.dev) { - ssb_warn("WARNING: Multiple MIPS cores found\n"); + pr_warn("WARNING: Multiple MIPS cores found\n"); break; } bus->mipscore.dev = dev; @@ -402,7 +401,8 @@ int ssb_bus_scan(struct ssb_bus *bus, #ifdef CONFIG_SSB_DRIVER_PCICORE if (bus->bustype == SSB_BUSTYPE_PCI) { /* Ignore PCI cores on PCI-E cards. - * Ignore PCI-E cores on PCI cards. */ + * Ignore PCI-E cores on PCI cards. + */ if (dev->id.coreid == SSB_DEV_PCI) { if (pci_is_pcie(bus->host_pci)) continue; @@ -412,7 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus, } } if (bus->pcicore.dev) { - ssb_warn("WARNING: Multiple PCI(E) cores found\n"); + pr_warn("WARNING: Multiple PCI(E) cores found\n"); break; } bus->pcicore.dev = dev; @@ -423,7 +423,8 @@ int ssb_bus_scan(struct ssb_bus *bus, if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && (bus->host_pci->device & 0xFF00) == 0x4300) { /* This is a dangling ethernet core on a - * wireless device. Ignore it. */ + * wireless device. Ignore it. + */ continue; } } diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c index b2d36f7736c5..66c5c2169704 100644 --- a/drivers/ssb/sdio.c +++ b/drivers/ssb/sdio.c @@ -12,14 +12,14 @@ * */ +#include "ssb_private.h" + #include <linux/ssb/ssb.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/etherdevice.h> #include <linux/mmc/sdio_func.h> -#include "ssb_private.h" - /* Define the following to 1 to enable a printk on each coreswitch. */ #define SSB_VERBOSE_SDIOCORESWITCH_DEBUG 0 @@ -200,7 +200,7 @@ out: } /* host must be already claimed */ -int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev) +static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev) { u8 coreidx = dev->core_index; u32 sbaddr; @@ -316,18 +316,18 @@ static void ssb_sdio_block_read(struct ssb_device *dev, void *buffer, break; } case sizeof(u16): { - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); error = sdio_readsb(bus->host_sdio, buffer, offset, count); break; } case sizeof(u32): { - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */ error = sdio_readsb(bus->host_sdio, buffer, offset, count); break; } default: - SSB_WARN_ON(1); + WARN_ON(1); } if (!error) goto out; @@ -411,7 +411,6 @@ static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer, sdio_claim_host(bus->host_sdio); if (unlikely(ssb_sdio_switch_core(bus, dev))) { error = -EIO; - memset((void *)buffer, 0xff, count); goto err_out; } offset |= bus->sdio_sbaddr & 0xffff; @@ -423,18 +422,18 @@ static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer, (void *)buffer, count); break; case sizeof(u16): - SSB_WARN_ON(count & 1); + WARN_ON(count & 1); error = sdio_writesb(bus->host_sdio, offset, (void *)buffer, count); break; case sizeof(u32): - SSB_WARN_ON(count & 3); + WARN_ON(count & 3); offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */ error = sdio_writesb(bus->host_sdio, offset, (void *)buffer, count); break; default: - SSB_WARN_ON(1); + WARN_ON(1); } if (!error) goto out; diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index e753fbe302a7..7cd553127861 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c @@ -26,9 +26,9 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, int i, pos = 0; for (i = 0; i < sprom_size_words; i++) - pos += snprintf(buf + pos, buf_len - pos - 1, + pos += scnprintf(buf + pos, buf_len - pos - 1, "%04X", swab16(sprom[i]) & 0xFFFF); - pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); + pos += scnprintf(buf + pos, buf_len - pos - 1, "\n"); return pos + 1; } @@ -78,7 +78,8 @@ ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf, /* Use interruptible locking, as the SPROM write might * be holding the lock for several seconds. So allow userspace - * to cancel operation. */ + * to cancel operation. + */ err = -ERESTARTSYS; if (mutex_lock_interruptible(&bus->sprom_mutex)) goto out_kfree; @@ -121,19 +122,20 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, /* Use interruptible locking, as the SPROM write might * be holding the lock for several seconds. So allow userspace - * to cancel operation. */ + * to cancel operation. + */ err = -ERESTARTSYS; if (mutex_lock_interruptible(&bus->sprom_mutex)) goto out_kfree; err = ssb_devices_freeze(bus, &freeze); if (err) { - ssb_err("SPROM write: Could not freeze all devices\n"); + pr_err("SPROM write: Could not freeze all devices\n"); goto out_unlock; } res = sprom_write(bus, sprom); err = ssb_devices_thaw(&freeze); if (err) - ssb_err("SPROM write: Could not thaw all devices\n"); + pr_err("SPROM write: Could not thaw all devices\n"); out_unlock: mutex_unlock(&bus->sprom_mutex); out_kfree: @@ -184,13 +186,15 @@ int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, struct ssb_sprom *out) return get_fallback_sprom(bus, out); } -/* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ +/* https://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ bool ssb_is_sprom_available(struct ssb_bus *bus) { /* status register only exists on chipcomon rev >= 11 and we need check - for >= 31 only */ + * for >= 31 only + */ /* this routine differs from specs as we do not access SPROM directly - on PCMCIA */ + * on PCMCIA + */ if (bus->bustype == SSB_BUSTYPE_PCI && bus->chipco.dev && /* can be unavailable! */ bus->chipco.dev->id.revision >= 31) diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index eb507a50a564..5f31bdfbe77f 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h @@ -1,47 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef LINUX_SSB_PRIVATE_H_ #define LINUX_SSB_PRIVATE_H_ +#define PFX "ssb: " +#define pr_fmt(fmt) PFX fmt + #include <linux/ssb/ssb.h> #include <linux/types.h> #include <linux/bcm47xx_wdt.h> -#define PFX "ssb: " - -#ifdef CONFIG_SSB_SILENT -# define ssb_printk(fmt, ...) \ - do { if (0) printk(fmt, ##__VA_ARGS__); } while (0) -#else -# define ssb_printk(fmt, ...) \ - printk(fmt, ##__VA_ARGS__) -#endif /* CONFIG_SSB_SILENT */ - -#define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__) -#define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__) -#define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__) -#define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__) -#define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__) -#define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__) - -/* dprintk: Debugging printk; vanishes for non-debug compilation */ -#ifdef CONFIG_SSB_DEBUG -# define ssb_dbg(fmt, ...) \ - ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__) -#else -# define ssb_dbg(fmt, ...) \ - do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0) -#endif - -#ifdef CONFIG_SSB_DEBUG -# define SSB_WARN_ON(x) WARN_ON(x) -# define SSB_BUG_ON(x) BUG_ON(x) -#else -static inline int __ssb_do_nothing(int x) { return x; } -# define SSB_WARN_ON(x) __ssb_do_nothing(unlikely(!!(x))) -# define SSB_BUG_ON(x) __ssb_do_nothing(unlikely(!!(x))) -#endif - - /* pci.c */ #ifdef CONFIG_SSB_PCIHOST extern int ssb_pci_switch_core(struct ssb_bus *bus, @@ -85,8 +53,6 @@ static inline int ssb_pci_init(struct ssb_bus *bus) /* pcmcia.c */ #ifdef CONFIG_SSB_PCMCIAHOST -extern int ssb_pcmcia_switch_core(struct ssb_bus *bus, - struct ssb_device *dev); extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, u8 coreidx); extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus, @@ -96,13 +62,10 @@ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus, extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus); extern void ssb_pcmcia_exit(struct ssb_bus *bus); extern int ssb_pcmcia_init(struct ssb_bus *bus); +extern int ssb_host_pcmcia_init(void); +extern void ssb_host_pcmcia_exit(void); extern const struct ssb_bus_ops ssb_pcmcia_ops; #else /* CONFIG_SSB_PCMCIAHOST */ -static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus, - struct ssb_device *dev) -{ - return 0; -} static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, u8 coreidx) { @@ -124,6 +87,13 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus) { return 0; } +static inline int ssb_host_pcmcia_init(void) +{ + return 0; +} +static inline void ssb_host_pcmcia_exit(void) +{ +} #endif /* CONFIG_SSB_PCMCIAHOST */ /* sdio.c */ @@ -132,9 +102,7 @@ extern int ssb_sdio_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv); extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset); -extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev); extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx); -extern int ssb_sdio_hardware_setup(struct ssb_bus *bus); extern void ssb_sdio_exit(struct ssb_bus *bus); extern int ssb_sdio_init(struct ssb_bus *bus); @@ -144,19 +112,10 @@ static inline u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset) { return 0; } -static inline int ssb_sdio_switch_core(struct ssb_bus *bus, - struct ssb_device *dev) -{ - return 0; -} static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx) { return 0; } -static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus) -{ - return 0; -} static inline void ssb_sdio_exit(struct ssb_bus *bus) { } @@ -166,6 +125,16 @@ static inline int ssb_sdio_init(struct ssb_bus *bus) } #endif /* CONFIG_SSB_SDIOHOST */ +/************************************************** + * host_soc.c + **************************************************/ + +#ifdef CONFIG_SSB_HOST_SOC +extern const struct ssb_bus_ops ssb_host_soc_ops; + +extern int ssb_host_soc_get_invariants(struct ssb_bus *bus, + struct ssb_init_invariants *iv); +#endif /* scan.c */ extern const char *ssb_core_name(u16 coreid); |
