aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-06-09 06:15:10 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-06-09 06:15:10 -0400
commit6e03a61544c368c2c3ff946c1ce7807e5c36a527 (patch)
tree29253331da9680b5f81ba8715202044f45861666 /arch/arm/mach-ep93xx
parent9eb34302681d3f6cf0b186aae31ba08cbd5f22fb (diff)
parented67ea82c0d9a163458dc6a69a7a3123db1a8b3b (diff)
Merge branch 'ep93xx' into for-2.6.36
Trivial add/add fixup required in the clock table. Conflicts: arch/arm/mach-ep93xx/clock.c
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r--arch/arm/mach-ep93xx/clock.c67
-rw-r--r--arch/arm/mach-ep93xx/core.c67
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h10
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h3
4 files changed, 146 insertions, 1 deletions
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index e29bdef9b2e2..803162492c4a 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk);
43 43
44static int set_keytchclk_rate(struct clk *clk, unsigned long rate); 44static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
45static int set_div_rate(struct clk *clk, unsigned long rate); 45static int set_div_rate(struct clk *clk, unsigned long rate);
46 46static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
47static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
47 48
48static struct clk clk_xtali = { 49static struct clk clk_xtali = {
49 .rate = EP93XX_EXT_CLK_RATE, 50 .rate = EP93XX_EXT_CLK_RATE,
@@ -112,6 +113,29 @@ static struct clk clk_video = {
112 .set_rate = set_div_rate, 113 .set_rate = set_div_rate,
113}; 114};
114 115
116static struct clk clk_i2s_mclk = {
117 .sw_locked = 1,
118 .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
119 .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
120 .set_rate = set_div_rate,
121};
122
123static struct clk clk_i2s_sclk = {
124 .sw_locked = 1,
125 .parent = &clk_i2s_mclk,
126 .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
127 .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
128 .set_rate = set_i2s_sclk_rate,
129};
130
131static struct clk clk_i2s_lrclk = {
132 .sw_locked = 1,
133 .parent = &clk_i2s_sclk,
134 .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
135 .enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
136 .set_rate = set_i2s_lrclk_rate,
137};
138
115/* DMA Clocks */ 139/* DMA Clocks */
116static struct clk clk_m2p0 = { 140static struct clk clk_m2p0 = {
117 .parent = &clk_h, 141 .parent = &clk_h,
@@ -191,6 +215,9 @@ static struct clk_lookup clocks[] = {
191 INIT_CK("ep93xx-keypad", NULL, &clk_keypad), 215 INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
192 INIT_CK("ep93xx-fb", NULL, &clk_video), 216 INIT_CK("ep93xx-fb", NULL, &clk_video),
193 INIT_CK("ep93xx-spi.0", NULL, &clk_spi), 217 INIT_CK("ep93xx-spi.0", NULL, &clk_spi),
218 INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk),
219 INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk),
220 INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk),
194 INIT_CK(NULL, "pwm_clk", &clk_pwm), 221 INIT_CK(NULL, "pwm_clk", &clk_pwm),
195 INIT_CK(NULL, "m2p0", &clk_m2p0), 222 INIT_CK(NULL, "m2p0", &clk_m2p0),
196 INIT_CK(NULL, "m2p1", &clk_m2p1), 223 INIT_CK(NULL, "m2p1", &clk_m2p1),
@@ -401,6 +428,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate)
401 return 0; 428 return 0;
402} 429}
403 430
431static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
432{
433 unsigned val = __raw_readl(clk->enable_reg);
434
435 if (rate == clk_i2s_mclk.rate / 2)
436 ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV,
437 clk->enable_reg);
438 else if (rate == clk_i2s_mclk.rate / 4)
439 ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV,
440 clk->enable_reg);
441 else
442 return -EINVAL;
443
444 clk_i2s_sclk.rate = rate;
445 return 0;
446}
447
448static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
449{
450 unsigned val = __raw_readl(clk->enable_reg) &
451 ~EP93XX_I2SCLKDIV_LRDIV_MASK;
452
453 if (rate == clk_i2s_sclk.rate / 32)
454 ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
455 clk->enable_reg);
456 else if (rate == clk_i2s_sclk.rate / 64)
457 ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
458 clk->enable_reg);
459 else if (rate == clk_i2s_sclk.rate / 128)
460 ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
461 clk->enable_reg);
462 else
463 return -EINVAL;
464
465 clk_i2s_lrclk.rate = rate;
466 return 0;
467}
468
404int clk_set_rate(struct clk *clk, unsigned long rate) 469int clk_set_rate(struct clk *clk, unsigned long rate)
405{ 470{
406 if (clk->set_rate) 471 if (clk->set_rate)
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 9092677f63eb..b4ee5409eb72 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -714,6 +714,73 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev)
714} 714}
715EXPORT_SYMBOL(ep93xx_keypad_release_gpio); 715EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
716 716
717/*************************************************************************
718 * EP93xx I2S audio peripheral handling
719 *************************************************************************/
720static struct resource ep93xx_i2s_resource[] = {
721 {
722 .start = EP93XX_I2S_PHYS_BASE,
723 .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1,
724 .flags = IORESOURCE_MEM,
725 },
726};
727
728static struct platform_device ep93xx_i2s_device = {
729 .name = "ep93xx-i2s",
730 .id = -1,
731 .num_resources = ARRAY_SIZE(ep93xx_i2s_resource),
732 .resource = ep93xx_i2s_resource,
733};
734
735void __init ep93xx_register_i2s(void)
736{
737 platform_device_register(&ep93xx_i2s_device);
738}
739
740#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
741 EP93XX_SYSCON_DEVCFG_I2SONAC97)
742
743#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
744 EP93XX_SYSCON_I2SCLKDIV_SPOL)
745
746int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
747{
748 unsigned val;
749
750 /* Sanity check */
751 if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
752 return -EINVAL;
753 if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
754 return -EINVAL;
755
756 /* Must have only one of I2SONSSP/I2SONAC97 set */
757 if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
758 (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
759 return -EINVAL;
760
761 ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
762 ep93xx_devcfg_set_bits(i2s_pins);
763
764 /*
765 * This is potentially racy with the clock api for i2s_mclk, sclk and
766 * lrclk. Since the i2s driver is the only user of those clocks we
767 * rely on it to prevent parallel use of this function and the
768 * clock api for the i2s clocks.
769 */
770 val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
771 val &= ~EP93XX_I2SCLKDIV_MASK;
772 val |= i2s_config;
773 ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
774
775 return 0;
776}
777EXPORT_SYMBOL(ep93xx_i2s_acquire);
778
779void ep93xx_i2s_release(void)
780{
781 ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
782}
783EXPORT_SYMBOL(ep93xx_i2s_release);
717 784
718extern void ep93xx_gpio_init(void); 785extern void ep93xx_gpio_init(void);
719 786
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index b1e096f0c2d2..c54b3e56ba63 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -93,6 +93,7 @@
93/* APB peripherals */ 93/* APB peripherals */
94#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000) 94#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
95 95
96#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
96#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) 97#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
97 98
98#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) 99#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
@@ -194,6 +195,15 @@
194#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) 195#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
195#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) 196#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
196#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 197#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
198#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c)
199#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31)
200#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29)
201#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19)
202#define EP93XX_I2SCLKDIV_SDIV (1 << 16)
203#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17)
204#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17)
205#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17)
206#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17)
197#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) 207#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
198#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) 208#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31)
199#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) 209#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16)
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 9a4413dd44bb..99eff877a146 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -55,6 +55,9 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev);
55void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); 55void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
56int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); 56int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
57void ep93xx_keypad_release_gpio(struct platform_device *pdev); 57void ep93xx_keypad_release_gpio(struct platform_device *pdev);
58void ep93xx_register_i2s(void);
59int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
60void ep93xx_i2s_release(void);
58 61
59void ep93xx_init_devices(void); 62void ep93xx_init_devices(void);
60extern struct sys_timer ep93xx_timer; 63extern struct sys_timer ep93xx_timer;