commit 59b714554add77d0e99283a39ca27a0acc5c3100 Author: Philipp Zabel Date: Fri Mar 28 18:03:02 2008 +0100 WIP: make SSP work for both pxa25x and pxa27x at the same time diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index eccc45d..2ec13f1 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -117,7 +117,7 @@ unsigned long corgi_ssp_dac_put(ulong data) sscr1 = 0; ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon)); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07)), sscr1, 0, ssp_machinfo->clk_lcdcon); ssp_enable(&corgi_ssp_dev); if (ssp_machinfo->cs_lcdcon >= 0) @@ -129,7 +129,7 @@ unsigned long corgi_ssp_dac_put(ulong data) GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b)), 0, 0, ssp_machinfo->clk_ads7846); ssp_enable(&corgi_ssp_dev); spin_unlock_irqrestore(&corgi_ssp_lock, flag); @@ -162,7 +162,7 @@ int corgi_ssp_max1111_get(ulong data) if (ssp_machinfo->cs_max1111 >= 0) GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111)); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07)), 0, 0, ssp_machinfo->clk_max1111); ssp_enable(&corgi_ssp_dev); udelay(1); @@ -180,7 +180,7 @@ int corgi_ssp_max1111_get(ulong data) ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2); ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b)), 0, 0, ssp_machinfo->clk_ads7846); ssp_enable(&corgi_ssp_dev); if (ssp_machinfo->cs_max1111 >= 0) GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); @@ -223,7 +223,7 @@ static int __init corgi_ssp_probe(struct platform_device *dev) printk(KERN_ERR "Unable to register SSP handler!\n"); else { ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b)), 0, 0, ssp_machinfo->clk_ads7846); ssp_enable(&corgi_ssp_dev); } diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 00af7f2..928ae59 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -234,18 +234,18 @@ void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *state) * @mode: port operating mode * @flags: port config flags * @psp_flags: port PSP config flags - * @speed: port speed + * @div: serial clock rate divider * * Port MUST be disabled by ssp_disable before making any config changes. */ -int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed) +int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 div) { struct ssp_device *ssp = dev->ssp; dev->mode = mode; dev->flags = flags; dev->psp_flags = psp_flags; - dev->speed = speed; + dev->speed = sscr0_serclkdiv(dev, 0, div); /* set up port type, speed, port settings */ __raw_writel((dev->speed | dev->mode), ssp->mmio_base + SSCR0); diff --git a/include/asm-arm/arch-pxa/regs-ssp.h b/include/asm-arm/arch-pxa/regs-ssp.h index 0255328..ae21bf4 100644 --- a/include/asm-arm/arch-pxa/regs-ssp.h +++ b/include/asm-arm/arch-pxa/regs-ssp.h @@ -29,12 +29,12 @@ #define SSCR0_National (0x2 << 4) /* National Microwire */ #define SSCR0_ECS (1 << 6) /* External clock select */ #define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ + #if defined(CONFIG_PXA25x) -#define SSCR0_SCR (0x0000ff00) /* Serial Clock Rate (mask) */ -#define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */ #elif defined(CONFIG_PXA27x) -#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */ -#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */ +#endif + +#if defined(CONFIG_PXA27x) #define SSCR0_EDSS (1 << 20) /* Extended data size select */ #define SSCR0_NCS (1 << 21) /* Network clock select */ #define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h index a012882..561b6a9 100644 --- a/include/asm-arm/arch-pxa/ssp.h +++ b/include/asm-arm/arch-pxa/ssp.h @@ -67,6 +67,23 @@ struct ssp_dev { int irq; }; +/** + * sscr0_serclkdiv - calculate SCR from divider + * + */ +inline u32 sscr0_serclkdiv(struct ssp_dev *dev, u32 sscr0, u32 div) +{ + struct ssp_device *ssp = dev->ssp; + + if (ssp->type == PXA25x_SSP) { + sscr0 &= ~0x0000ff00; /* Serial Clock Rate (mask) */ + return sscr0 | (((div) - 2)/2) << 8; /* Divisor [2..512] */ + } else { + sscr0 &= ~0x000fff00; /* Serial Clock Rate (mask) */ + return sscr0 | ((div) - 1) << 8; /* Divisor [1..4096] */ + } +} + int ssp_write_word(struct ssp_dev *dev, u32 data); int ssp_read_word(struct ssp_dev *dev, u32 *data); int ssp_flush(struct ssp_dev *dev); @@ -75,7 +92,7 @@ void ssp_disable(struct ssp_dev *dev); void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags); -int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); +int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 div); void ssp_exit(struct ssp_dev *dev); struct ssp_device *ssp_request(int port, const char *label);