sync ssb with upstream
[openwrt.git] / target / linux / generic-2.6 / files / drivers / ssb / driver_mipscore.c
index 67d1017..3d3dd32 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <asm/time.h>
+#include <linux/time.h>
 
 #include "ssb_private.h"
 
@@ -117,51 +117,10 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
        ssb_write32(mdev, SSB_IPSFLAG, irqflag);
 }
 
-/* XXX: leave here or move into separate extif driver? */
-static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports)
-{
-
-}
-
-
 static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
 {
        struct ssb_bus *bus = mcore->dev->bus;
 
-       //TODO if (EXTIF available
-#if 0
-               extifregs_t *eir = (extifregs_t *) regs;
-               sbconfig_t *sb;
-
-               /* Determine external UART register base */
-               sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
-               base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
-
-               /* Determine IRQ */
-               irq = sb_irq(sbh);
-
-               /* Disable GPIO interrupt initially */
-               W_REG(&eir->gpiointpolarity, 0);
-               W_REG(&eir->gpiointmask, 0);
-
-               /* Search for external UARTs */
-               n = 2;
-               for (i = 0; i < 2; i++) {
-                       regs = (void *) REG_MAP(base + (i * 8), 8);
-                       if (BCMINIT(serial_exists)(regs)) {
-                               /* Set GPIO 1 to be the external UART IRQ */
-                               W_REG(&eir->gpiointmask, 2);
-                               if (add)
-                                       add(regs, irq, 13500000, 0);
-                       }
-               }
-
-               /* Add internal UART if enabled */
-               if (R_REG(&eir->corecontrol) & CC_UE)
-                       if (add)
-                               add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
-
-#endif
        if (bus->extif.dev)
                mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
        else if (bus->chipco.dev)
@@ -174,23 +133,47 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
 {
        struct ssb_bus *bus = mcore->dev->bus;
 
+       mcore->flash_buswidth = 2;
        if (bus->chipco.dev) {
                mcore->flash_window = 0x1c000000;
-               mcore->flash_window_size = 0x800000;
+               mcore->flash_window_size = 0x02000000;
+               if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
+                              & SSB_CHIPCO_CFG_DS16) == 0)
+                       mcore->flash_buswidth = 1;
        } else {
                mcore->flash_window = 0x1fc00000;
-               mcore->flash_window_size = 0x400000;
+               mcore->flash_window_size = 0x00400000;
        }
 }
 
-
-static void ssb_cpu_clock(struct ssb_mipscore *mcore)
+u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
 {
+       struct ssb_bus *bus = mcore->dev->bus;
+       u32 pll_type, n, m, rate = 0;
+
+       if (bus->extif.dev) {
+               ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+       } else if (bus->chipco.dev) {
+               ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
+       } else
+               return 0;
+
+       if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
+               rate = 200000000;
+       } else {
+               rate = ssb_calc_clock_rate(pll_type, n, m);
+       }
+
+       if (pll_type == SSB_PLLTYPE_6) {
+               rate *= 2;
+       }
+
+       return rate;
 }
 
 void ssb_mipscore_init(struct ssb_mipscore *mcore)
 {
-       struct ssb_bus *bus = mcore->dev->bus;
+       struct ssb_bus *bus;
        struct ssb_device *dev;
        unsigned long hz, ns;
        unsigned int irq, i;
@@ -200,56 +183,39 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 
        ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
 
+       bus = mcore->dev->bus;
        hz = ssb_clockspeed(bus);
        if (!hz)
                hz = 100000000;
        ns = 1000000000 / hz;
 
-//TODO
-#if 0
-       if (have EXTIF) {
-               /* Initialize extif so we can get to the LEDs and external UART */
-               W_REG(&eir->prog_config, CF_EN);
-
-               /* Set timing for the flash */
-               tmp = CEIL(10, ns) << FW_W3_SHIFT;      /* W3 = 10nS */
-               tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
-               tmp = tmp | CEIL(120, ns);              /* W0 = 120nS */
-               W_REG(&eir->prog_waitcount, tmp);       /* 0x01020a0c for a 100Mhz clock */
-
-               /* Set programmable interface timing for external uart */
-               tmp = CEIL(10, ns) << FW_W3_SHIFT;      /* W3 = 10nS */
-               tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
-               tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
-               tmp = tmp | CEIL(120, ns);              /* W0 = 120nS */
-               W_REG(&eir->prog_waitcount, tmp);
-       }
-       else... chipcommon
-#endif
-       if (bus->chipco.dev)
+       if (bus->extif.dev)
+               ssb_extif_timing_init(&bus->extif, ns);
+       else if (bus->chipco.dev)
                ssb_chipco_timing_init(&bus->chipco, ns);
 
        /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
        for (irq = 2, i = 0; i < bus->nr_devices; i++) {
                dev = &(bus->devices[i]);
                dev->irq = ssb_mips_irq(dev) + 2;
-               switch(dev->id.coreid) {
-                       case SSB_DEV_USB11_HOST:
-                               /* shouldn't need a separate irq line for non-4710, most of them have a proper
-                                * external usb controller on the pci */
-                               if ((bus->chip_id == 0x4710) && (irq <= 4)) {
-                                       set_irq(dev, irq++);
-                                       break;
-                               }
-                       case SSB_DEV_PCI:
-                       case SSB_DEV_ETHERNET:
-                       case SSB_DEV_80211:
-                       case SSB_DEV_USB20_HOST:
-                               /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
-                               if (irq <= 4) {
-                                       set_irq(dev, irq++);
-                                       break;
-                               }
+               switch (dev->id.coreid) {
+               case SSB_DEV_USB11_HOST:
+                       /* shouldn't need a separate irq line for non-4710, most of them have a proper
+                        * external usb controller on the pci */
+                       if ((bus->chip_id == 0x4710) && (irq <= 4)) {
+                               set_irq(dev, irq++);
+                               break;
+                       }
+                       /* fallthrough */
+               case SSB_DEV_PCI:
+               case SSB_DEV_ETHERNET:
+               case SSB_DEV_80211:
+               case SSB_DEV_USB20_HOST:
+                       /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
+                       if (irq <= 4) {
+                               set_irq(dev, irq++);
+                               break;
+                       }
                }
        }