--- /dev/null
+Index: linux-2.6.23.16/drivers/ssb/driver_chipcommon.c
+===================================================================
+--- linux-2.6.23.16.orig/drivers/ssb/driver_chipcommon.c       2008-02-18 21:38:58.000000000 +0100
++++ linux-2.6.23.16/drivers/ssb/driver_chipcommon.c    2008-02-18 21:39:00.000000000 +0100
+@@ -365,6 +365,7 @@ int ssb_chipco_serial_init(struct ssb_ch
+       unsigned int irq;
+       u32 baud_base, div;
+       u32 i, n;
++      unsigned int ccrev = cc->dev->id.revision;
+ 
+       plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
+       irq = ssb_mips_irq(cc->dev);
+@@ -376,14 +377,39 @@ int ssb_chipco_serial_init(struct ssb_ch
+                                               chipco_read32(cc, SSB_CHIPCO_CLOCK_M2));
+               div = 1;
+       } else {
+-              if (cc->dev->id.revision >= 11) {
++              if (ccrev == 20) {
++                      /* BCM5354 uses constant 25MHz clock */
++                      baud_base = 25000000;
++                      div = 48;
++                      /* Set the override bit so we don't divide it */
++                      chipco_write32(cc, SSB_CHIPCO_CORECTL,
++                                     chipco_read32(cc, SSB_CHIPCO_CORECTL)
++                                     | SSB_CHIPCO_CORECTL_UARTCLK0);
++              } else if ((ccrev >= 11) && (ccrev != 15)) {
+                       /* Fixed ALP clock */
+                       baud_base = 20000000;
++                      if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
++                              /* FIXME: baud_base is different for devices with a PMU */
++                              SSB_WARN_ON(1);
++                      }
+                       div = 1;
++                      if (ccrev >= 21) {
++                              /* Turn off UART clock before switching clocksource. */
++                              chipco_write32(cc, SSB_CHIPCO_CORECTL,
++                                             chipco_read32(cc, SSB_CHIPCO_CORECTL)
++                                             & ~SSB_CHIPCO_CORECTL_UARTCLKEN);
++                      }
+                       /* Set the override bit so we don't divide it */
+                       chipco_write32(cc, SSB_CHIPCO_CORECTL,
+-                                     SSB_CHIPCO_CORECTL_UARTCLK0);
+-              } else if (cc->dev->id.revision >= 3) {
++                                     chipco_read32(cc, SSB_CHIPCO_CORECTL)
++                                     | SSB_CHIPCO_CORECTL_UARTCLK0);
++                      if (ccrev >= 21) {
++                              /* Re-enable the UART clock. */
++                              chipco_write32(cc, SSB_CHIPCO_CORECTL,
++                                             chipco_read32(cc, SSB_CHIPCO_CORECTL)
++                                             | SSB_CHIPCO_CORECTL_UARTCLKEN);
++                      }
++              } else if (ccrev >= 3) {
+                       /* Internal backplane clock */
+                       baud_base = ssb_clockspeed(bus);
+                       div = chipco_read32(cc, SSB_CHIPCO_CLKDIV)
+@@ -395,7 +421,7 @@ int ssb_chipco_serial_init(struct ssb_ch
+               }
+ 
+               /* Clock source depends on strapping if UartClkOverride is unset */
+-              if ((cc->dev->id.revision > 0) &&
++              if ((ccrev > 0) &&
+                   !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) {
+                       if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) ==
+                           SSB_CHIPCO_CAP_UARTCLK_INT) {
+@@ -417,7 +443,7 @@ int ssb_chipco_serial_init(struct ssb_ch
+               cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE);
+               uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA;
+               /* Offset changed at after rev 0 */
+-              if (cc->dev->id.revision == 0)
++              if (ccrev == 0)
+                       uart_regs += (i * 8);
+               else
+                       uart_regs += (i * 256);
+Index: linux-2.6.23.16/include/linux/ssb/ssb_driver_chipcommon.h
+===================================================================
+--- linux-2.6.23.16.orig/include/linux/ssb/ssb_driver_chipcommon.h     2008-02-18 21:38:58.000000000 +0100
++++ linux-2.6.23.16/include/linux/ssb/ssb_driver_chipcommon.h  2008-02-18 21:39:00.000000000 +0100
+@@ -51,9 +51,12 @@
+ #define  SSB_CHIPCO_CAP_JTAGM         0x00400000      /* JTAG master present */
+ #define  SSB_CHIPCO_CAP_BROM          0x00800000      /* Internal boot ROM active */
+ #define  SSB_CHIPCO_CAP_64BIT         0x08000000      /* 64-bit Backplane */
++#define  SSB_CHIPCO_CAP_PMU           0x10000000      /* PMU available (rev >= 20) */
++#define  SSB_CHIPCO_CAP_ECI           0x20000000      /* ECI available (rev >= 20) */
+ #define SSB_CHIPCO_CORECTL            0x0008
+ #define  SSB_CHIPCO_CORECTL_UARTCLK0  0x00000001      /* Drive UART with internal clock */
+ #define        SSB_CHIPCO_CORECTL_SE          0x00000002      /* sync clk out enable (corerev >= 3) */
++#define  SSB_CHIPCO_CORECTL_UARTCLKEN 0x00000008      /* UART clock enable (rev >= 21) */
+ #define SSB_CHIPCO_BIST                       0x000C
+ #define SSB_CHIPCO_OTPS                       0x0010          /* OTP status */
+ #define        SSB_CHIPCO_OTPS_PROGFAIL       0x80000000