diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-06-09 06:15:10 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-06-09 06:15:10 -0400 |
commit | 6e03a61544c368c2c3ff946c1ce7807e5c36a527 (patch) | |
tree | 29253331da9680b5f81ba8715202044f45861666 /arch/arm/mach-ep93xx | |
parent | 9eb34302681d3f6cf0b186aae31ba08cbd5f22fb (diff) | |
parent | ed67ea82c0d9a163458dc6a69a7a3123db1a8b3b (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.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/platform.h | 3 |
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 | ||
44 | static int set_keytchclk_rate(struct clk *clk, unsigned long rate); | 44 | static int set_keytchclk_rate(struct clk *clk, unsigned long rate); |
45 | static int set_div_rate(struct clk *clk, unsigned long rate); | 45 | static int set_div_rate(struct clk *clk, unsigned long rate); |
46 | 46 | static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate); | |
47 | static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate); | ||
47 | 48 | ||
48 | static struct clk clk_xtali = { | 49 | static 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 | ||
116 | static 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 | |||
123 | static 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 | |||
131 | static 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 */ |
116 | static struct clk clk_m2p0 = { | 140 | static 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 | ||
431 | static 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 | |||
448 | static 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 | |||
404 | int clk_set_rate(struct clk *clk, unsigned long rate) | 469 | int 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 | } |
715 | EXPORT_SYMBOL(ep93xx_keypad_release_gpio); | 715 | EXPORT_SYMBOL(ep93xx_keypad_release_gpio); |
716 | 716 | ||
717 | /************************************************************************* | ||
718 | * EP93xx I2S audio peripheral handling | ||
719 | *************************************************************************/ | ||
720 | static 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 | |||
728 | static 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 | |||
735 | void __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 | |||
746 | int 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 | } | ||
777 | EXPORT_SYMBOL(ep93xx_i2s_acquire); | ||
778 | |||
779 | void ep93xx_i2s_release(void) | ||
780 | { | ||
781 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); | ||
782 | } | ||
783 | EXPORT_SYMBOL(ep93xx_i2s_release); | ||
717 | 784 | ||
718 | extern void ep93xx_gpio_init(void); | 785 | extern 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); | |||
55 | void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); | 55 | void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); |
56 | int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); | 56 | int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); |
57 | void ep93xx_keypad_release_gpio(struct platform_device *pdev); | 57 | void ep93xx_keypad_release_gpio(struct platform_device *pdev); |
58 | void ep93xx_register_i2s(void); | ||
59 | int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config); | ||
60 | void ep93xx_i2s_release(void); | ||
58 | 61 | ||
59 | void ep93xx_init_devices(void); | 62 | void ep93xx_init_devices(void); |
60 | extern struct sys_timer ep93xx_timer; | 63 | extern struct sys_timer ep93xx_timer; |