[RFC PATCH v3 1/3] ep93xx i2s core support
Ryan Mallon
ryan at bluewatersys.com
Mon Jun 7 18:21:53 EDT 2010
H Hartley Sweeten wrote:
> On Thursday, June 03, 2010 10:11 PM, Ryan Mallon wrote:
>> Add ep93xx core support for i2s audio
>>
>> Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
>> ---
>> arch/arm/mach-ep93xx/clock.c | 69 ++++++++++++++++++++++-
>> arch/arm/mach-ep93xx/core.c | 31 ++++++++++
>> arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 10 +++
>> arch/arm/mach-ep93xx/include/mach/platform.h | 1 +
>> 4 files changed, 110 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
>> index 5f80092..503d430 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);
>>
>> static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
>> static int set_div_rate(struct clk *clk, unsigned long rate);
>> -
>> +static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
>> +static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
>>
>> static struct clk clk_xtali = {
>> .rate = EP93XX_EXT_CLK_RATE,
>> @@ -108,6 +109,31 @@ static struct clk clk_video = {
>> .set_rate = set_div_rate,
>> };
>>
>> +static struct clk clk_i2s_mclk = {
>> + .sw_locked = 1,
>> + .enable_reg = EP93XX_SYSCON_I2SCLKDIV,
>> + .enable_mask = (EP93XX_SYSCON_CLKDIV_ENABLE |
>> + EP93XX_SYSCON_I2SCLKDIV_SPOL |
>> + EP93XX_SYSCON_I2SCLKDIV_ORIDE),
>
> Setting the SPOL and ORIDE bits here might cause problems in the future.
> Granted, your i2s driver is currently the only user so its probably ok
> for now.
>
> But, you might want to move the setting of those two bits along with the
> SLAVE and DROP bits to the core registration function. The clock support
> should only be enabling/disabling and setting the rates for the clocks.
Okay, sounds sensible. Possibly I should add acquire/release functions
in addition to the register, something like:
void __init ep93xx_register_i2s(void)
{
platform_device_register(&ep93xx_i2s_device);
}
int ep93xx_i2s_acquire(unsigned pins, int override, int sclk_falling)
{
unsigned set_bits = pins,
clear_bits = EP93XX_SYSCON_DEVCFG_I2SONSSP |
EP93XX_SYSCON_DEVCFG_I2SONAC97;
if (pins != EP93XX_SYSCON_DEVCFG_I2SONSSP &&
pins != EP93XX_SYSCON_DEVCFG_I2SONAC97)
return -EINVAL;
if (override)
set_bits |= EP93XX_SYSCON_I2SCLKDIV_ORIDE;
else
clear_bits |= EP93XX_SYSCON_I2SCLKDIV_ORIDE;
if (sclk_falling)
set_bits |= EP93XX_SYSCON_I2SCLKDIV_SPOL;
else
clear_bits |= EP93XX_SYSCON_I2SCLKDIV_SPOL;
ep93xx_devcfg_clear_bits(clear_bits);
ep93xx_devcfg_set_bits(set_bits);
return 0;
}
>> + .set_rate = set_div_rate,
>
> By calling the set_div_rate routine your only updating the master clock
> rate. Should the new rate be pushed down to the children? Actually the
> new rates for the children will be established automatically when the
> master clock rate is changed. But a clk_get_rate for the children will
> return an incorrect value. Maybe just add a get_rate method for the
> children?
The code basically assumes that the clocks will always be set in the
order: mclk, sclk, lrclk. Since the i2s driver is the only user, this
should be a valid assumption. Possibly a comment should be put in to
state that this assumption is made.
~Ryan
--
Bluewater Systems Ltd - ARM Technology Solution Centre
Ryan Mallon 5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com New Zealand
Phone: +64 3 3779127 Freecall: Australia 1800 148 751
Fax: +64 3 3779135 USA 1800 261 2934
More information about the linux-arm-kernel
mailing list