Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / mips / bcm47xx / sprom.c
index 41226b6..2eff7fe 100644 (file)
@@ -136,6 +136,20 @@ static void nvram_read_leddc(const char *prefix, const char *name,
        *leddc_off_time = (val >> 16) & 0xff;
 }
 
+static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
+{
+       if (strchr(buf, ':'))
+               sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
+                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+                       &macaddr[5]);
+       else if (strchr(buf, '-'))
+               sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
+                       &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+                       &macaddr[5]);
+       else
+               pr_warn("Can not parse mac address: %s\n", buf);
+}
+
 static void nvram_read_macaddr(const char *prefix, const char *name,
                               u8 val[6], bool fallback)
 {
@@ -801,3 +815,71 @@ void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
        nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
 }
 #endif
+
+#if defined(CONFIG_BCM47XX_SSB)
+static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+       char prefix[10];
+
+       if (bus->bustype == SSB_BUSTYPE_PCI) {
+               memset(out, 0, sizeof(struct ssb_sprom));
+               snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+                        bus->host_pci->bus->number + 1,
+                        PCI_SLOT(bus->host_pci->devfn));
+               bcm47xx_fill_sprom(out, prefix, false);
+               return 0;
+       } else {
+               pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
+               return -EINVAL;
+       }
+}
+#endif
+
+#if defined(CONFIG_BCM47XX_BCMA)
+static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
+{
+       char prefix[10];
+       struct bcma_device *core;
+
+       switch (bus->hosttype) {
+       case BCMA_HOSTTYPE_PCI:
+               memset(out, 0, sizeof(struct ssb_sprom));
+               snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+                        bus->host_pci->bus->number + 1,
+                        PCI_SLOT(bus->host_pci->devfn));
+               bcm47xx_fill_sprom(out, prefix, false);
+               return 0;
+       case BCMA_HOSTTYPE_SOC:
+               memset(out, 0, sizeof(struct ssb_sprom));
+               core = bcma_find_core(bus, BCMA_CORE_80211);
+               if (core) {
+                       snprintf(prefix, sizeof(prefix), "sb/%u/",
+                                core->core_index);
+                       bcm47xx_fill_sprom(out, prefix, true);
+               } else {
+                       bcm47xx_fill_sprom(out, NULL, false);
+               }
+               return 0;
+       default:
+               pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
+               return -EINVAL;
+       }
+}
+#endif
+
+/*
+ * On bcm47xx we need to register SPROM fallback handler very early, so we can't
+ * use anything like platform device / driver for this.
+ */
+void bcm47xx_sprom_register_fallbacks(void)
+{
+#if defined(CONFIG_BCM47XX_SSB)
+       if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))
+               pr_warn("Failed to registered ssb SPROM handler\n");
+#endif
+
+#if defined(CONFIG_BCM47XX_BCMA)
+       if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))
+               pr_warn("Failed to registered bcma SPROM handler\n");
+#endif
+}