Signed-off-by: Juergen Borleis <[email protected]>
---
 arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx_psc.h |  98 ++++++++++++++
 drivers/serial/Kconfig                           |   4 +-
 drivers/serial/serial_mpc5xxx.c                  | 157 +++++++++++++++++++++++
 3 files changed, 257 insertions(+), 2 deletions(-)

diff --git a/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx_psc.h 
b/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx_psc.h
index a44d213..839b394 100644
--- a/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx_psc.h
+++ b/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx_psc.h
@@ -60,6 +60,7 @@
 #define PSC_MODE_ONE_STOP              0x07
 #define PSC_MODE_TWO_STOP              0x0f
 
+#ifdef CONFIG_MPC5200
 struct mpc5xxx_psc {
        u8      mode;           /* PSC + 0x00 */
        u8      reserved0[3];
@@ -152,3 +153,100 @@ struct mpc5xxx_psc {
        u16     reserved31;
        u16     tflwfptr;       /* PSC + 0x9e */
 };
+#endif
+
+#ifdef CONFIG_SOC_MPC5125
+/* PSC definition for MPC5125 */
+struct mpc5xxx_psc {
+       u8 mode;
+       u8 res0[3];
+       u8 mode2;
+       u8 res1[3];
+       u16 psc_status;
+       u8 resx[2];
+       u8 clock_select;
+       u8 res2[3];
+       u8 command;
+       u8 res3[3];
+       u32 buffer_32;
+       u8 ipcr;
+       u8 res4[3];
+       u8 acr;
+       u8 res5[3];
+       u16 isr;
+       u8 res5a[2];
+       u16 psc_imr;
+       u8 res5b[2];
+       u8 ctur;
+       u8 res6[3];
+       u8 ctlr;
+       u8 res7[3];
+       u32 ccr;
+       u32 ac97slots;
+       u32 ac97cmd;
+       u32 ac97data;
+       u8 res8[4];
+       u8 ip;
+       u8 res9[3];
+       u8 op1;
+       u8 res10[3];
+       u8 op0;
+       u8 res11[3];
+       u32 sicr;
+       u8 res12[44];
+       u32 tfcmd;
+       u32 tfalarm;
+       u32 tfstat;
+       u32 tfintstat;
+       u32 tfintmask;
+       u32 tfcount;
+       u32 tfwptr;
+       u32 tfsize;
+       u8 res13[28];
+       union {
+               u8 buffer_8;
+               u16 buffer_16;
+               u32 buffer_32;
+       } tfdata_buffer;
+#define tfdata_8 tfdata_buffer.buffer_8
+#define tfdata_16 tfdata_buffer.buffer_16
+#define tfdata_32 tfdata_buffer.buffer_32
+       u32 rfcmd;
+       u32 rfalarm;
+       u32 rfstat;
+       u32 rfintstat;
+       u32 rfintmask;
+       u32 rfcount;
+       u32 rfrptr;
+       u32 rfsize;
+       u8 res14[28];
+       union {
+               u8 buffer_8;
+               u16 buffer_16;
+               u32 buffer_32;
+       } rfdata_buffer;
+#define rfdata_8 rfdata_buffer.buffer_8
+#define rfdata_16 rfdata_buffer.buffer_16
+#define rfdata_32 rfdata_buffer.buffer_32
+};
+
+struct fifoc5125 {
+       u32 fifoc_cmd;
+       u32 fifoc_int;
+       u32 fifoc_dma;
+       u32 res1;
+       u32 fifoc_debug;
+};
+
+/* PSC FIFO Command values */
+#define PSC_FIFO_RESET_SLICE           0x80
+#define PSC_FIFO_ENABLE_SLICE          0x01
+
+/* PSC FIFO Controller Command values */
+#define FIFOC_ENABLE_CLOCK_GATE                0x01
+#define FIFOC_DISABLE_CLOCK_GATE       0x00
+
+/* PSC FIFO status */
+#define PSC_FIFO_EMPTY                 0x01
+
+#endif
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 146bf1e..63c0703 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -50,9 +50,9 @@ config DRIVER_SERIAL_EFI_STDIO
        bool "EFI stdio driver"
 
 config DRIVER_SERIAL_MPC5XXX
-       depends on MPC5200
+       depends on ARCH_MPC5XXX
        default y
-       bool "MPC5200 serial driver"
+       bool "MPC5XXX serial driver"
 
 config DRIVER_SERIAL_BLACKFIN
        depends on BLACKFIN
diff --git a/drivers/serial/serial_mpc5xxx.c b/drivers/serial/serial_mpc5xxx.c
index 7cd448c..670c514 100644
--- a/drivers/serial/serial_mpc5xxx.c
+++ b/drivers/serial/serial_mpc5xxx.c
@@ -39,6 +39,142 @@
 #include <mach/clocks.h>
 #include <mach/mpc5xxx_psc.h>
 
+#ifdef CONFIG_SOC_MPC5125
+
+#define MPC512x_PSC_FIFO_EMPTY (1 << 0)
+
+static struct fifoc5125 * const fifoc = (struct fifoc5125 *)MPC512X_FIFOC;
+
+struct fifo_adr_pair {
+       unsigned tsize, toffs;
+       unsigned rsize, roffs;
+};
+
+/* describe the FIFO's internal memory layout */
+static const struct fifo_adr_pair mpc5xxx_fifo_addresses[] = {
+       {
+               .tsize = 0x04, .toffs = 0x000,
+               .rsize = 0x04, .roffs = 0x010,
+       }, {
+               .tsize = 0x04, .toffs = 0x020,
+               .rsize = 0x04, .roffs = 0x030,
+       }, {
+               .tsize = 0x04, .toffs = 0x040,
+               .rsize = 0x04, .roffs = 0x050,
+       }, {
+               .tsize = 0x04, .toffs = 0x060,
+               .rsize = 0x04, .roffs = 0x070,
+       }, {
+               .tsize = 0x04, .toffs = 0x080,
+               .rsize = 0x04, .roffs = 0x090,
+       }, {
+               .tsize = 0x04, .toffs = 0x0a0,
+               .rsize = 0x04, .roffs = 0x0b0,
+       }, {
+               .tsize = 0x04, .toffs = 0x0c0,
+               .rsize = 0x04, .roffs = 0x0d0,
+       }, {
+               .tsize = 0x04, .toffs = 0x0e0,
+               .rsize = 0x04, .roffs = 0x0f0,
+       }, {
+               .tsize = 0x04, .toffs = 0x100,
+               .rsize = 0x04, .roffs = 0x110,
+       }, {
+               .tsize = 0x04, .toffs = 0x120,
+               .rsize = 0x04, .roffs = 0x130,
+       },
+};
+
+static unsigned mpc5xxx_get_psc_index(void *p)
+{
+       /* all PSC offsets differ in 0x100 steps */
+       return ((unsigned)p & 0xf00) >> 8;
+}
+
+static void mpc5xxx_fifo_init(struct mpc5xxx_psc *psc)
+{
+       unsigned idx = mpc5xxx_get_psc_index(psc);
+       u32 tfsize, rfsize;
+
+       /*
+        * we must enable the FIFO unit's clock,
+        * when at least one PSC unit is in use
+        */
+       mpc5125_enable_psc_fifo_clock();
+
+       /* reset Rx & Tx fifo slice */
+       out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
+       out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
+
+       /* disable Tx & Rx FIFO interrupts */
+       out_be32(&psc->rfintmask, 0);
+       out_be32(&psc->tfintmask, 0);
+
+       tfsize = mpc5xxx_fifo_addresses[idx].tsize |
+                       (mpc5xxx_fifo_addresses[idx].toffs << 16);
+       rfsize = mpc5xxx_fifo_addresses[idx].rsize |
+                       (mpc5xxx_fifo_addresses[idx].roffs << 16);
+
+       out_be32(&psc->tfsize, tfsize);
+       out_be32(&psc->rfsize, rfsize);
+
+       /* enable Tx & Rx FIFO slice */
+       out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
+       out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
+
+       out_be32(&fifoc->fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
+       __asm__ volatile ("sync");
+}
+
+static int psc_tx_rdy(struct mpc5xxx_psc *psc)
+{
+       return in_be32(&psc->tfstat) & MPC512x_PSC_FIFO_EMPTY;
+}
+
+static int psc_rx_rdy(struct mpc5xxx_psc *psc)
+{
+       return !(in_be32(&psc->rfstat) & MPC512x_PSC_FIFO_EMPTY);
+}
+
+static void psc_tx_write(struct mpc5xxx_psc *psc, char c)
+{
+       out_8(&psc->tfdata_8, c);
+}
+
+static int psc_rx_read(struct mpc5xxx_psc *psc)
+{
+       return in_8(&psc->rfdata_8);
+}
+
+static unsigned long mpc5xxx_get_base_clock(struct mpc5xxx_psc *psc)
+{
+       return (get_ips_clock() + 8) / 16;
+}
+
+static void mpc5xxx_select_clock_source(struct mpc5xxx_psc *psc)
+{
+       out_8(&psc->clock_select, 0xdd);
+}
+
+static void mpc5xxx_configure_serial_protocol(struct mpc5xxx_psc *psc)
+{
+       out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
+       out_8(&psc->mode2, PSC_MODE_ONE_STOP);
+}
+
+static int mpc5xxx_enable_psc_unit(struct mpc5xxx_psc *psc)
+{
+       unsigned idx = mpc5xxx_get_psc_index(psc);
+
+       if (idx > ARRAY_SIZE(mpc5xxx_fifo_addresses))
+               return -ENODEV;
+
+       mpc5xxx_enable_psc_clock(idx);
+       return 0;
+}
+
+#else /* CONFIG_MPC512X */
+
 static int psc_tx_rdy(struct mpc5xxx_psc *psc)
 {
        return in_be16(&psc->psc_status) & PSC_SR_TXEMP;
@@ -81,6 +217,11 @@ static void mpc5xxx_select_clock_source(struct mpc5xxx_psc 
*psc)
 #endif
 }
 
+static void mpc5xxx_fifo_init(struct mpc5xxx_psc *psc)
+{
+       /* nothing to be done here */
+}
+
 static void mpc5xxx_configure_serial_protocol(struct mpc5xxx_psc *psc)
 {
 #if defined(CONFIG_MGT5100)
@@ -93,6 +234,14 @@ static void mpc5xxx_configure_serial_protocol(struct 
mpc5xxx_psc *psc)
 #endif
 }
 
+static int mpc5xxx_enable_psc_unit(struct mpc5xxx_psc *psc)
+{
+       /* nothing to be done here */
+       return 0;
+}
+
+#endif /* !CONFIG_MPC512X */
+
 static int __mpc5xxx_serial_setbaudrate(struct mpc5xxx_psc *psc, int baudrate)
 {
        unsigned long baseclk;
@@ -120,11 +269,19 @@ static int mpc5xxx_serial_setbaudrate(struct 
console_device *cdev, int baudrate)
 
 static int __mpc5xxx_serial_init(struct mpc5xxx_psc *psc)
 {
+       int ret;
+
+       ret = mpc5xxx_enable_psc_unit(psc);
+       if (ret != 0)
+               return ret;
+
        /* reset PSC */
        out_8(&psc->command, PSC_SEL_MODE_REG_1);
 
        mpc5xxx_select_clock_source(psc);
 
+       mpc5xxx_fifo_init(psc);
+
        /* switch to UART mode */
        out_be32(&psc->sicr, 0);
 
-- 
2.1.0


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to