[PATCH v2 1/3] spi: implemented driver for Cirrus EP93xx SPI controller

Mika Westerberg mika.westerberg at iki.fi
Thu Mar 25 14:43:16 EDT 2010


On Thu, Mar 25, 2010 at 01:49:32PM +0000, Martin Guy wrote:
> On 3/18/10, Mika Westerberg <mika.westerberg at iki.fi> wrote:
> > This patch adds an SPI master driver for the Cirrus EP93xx SPI controller found
> >  in EP93xx chips (EP9301, EP9302, EP9307, EP9312 and EP9315).
> >
> >  Driver currently supports only interrupt driven mode but in future we may add
> >  polling mode support as well.
> >
> >  Signed-off-by: Mika Westerberg <mika.westerberg at iki.fi>
> >  ---
> 
> >  diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c
> >  new file mode 100644
> >  index 0000000..17935f3
> >  --- /dev/null
> >  +++ b/drivers/spi/ep93xx_spi.c
> 
> >  +/**
> >  + * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
> >  + * @espi: ep93xx SPI controller struct
> >  + * @chip: divisors are calculated for this chip
> >  + * @rate: maximum rate (in Hz) that this chip supports
> 
> Isn't that
> >  + * @rate: desired SPI output clock rate

Yes.

> 
> >  + *
> >  + * Function calculates cpsr (clock pre-scaler) and scr divisors based on
> >  + * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If,
> >  + * for some reason, divisors cannot be calculated nothing is stored and
> >  + * %-EINVAL is returned.
> >  + */
> >  +static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi,
> >  +                                   struct ep93xx_spi_chip *chip,
> >  +                                   unsigned long rate)
> >  +{
> ...
> >  +       /*
> >  +        * Calculate divisors so that we can get speed according the
> >  +        * following formula:
> >  +        *      rate = max_speed / (cpsr * (1 + scr))
> >  +        * where max_speed is same as SPI clock rate.
> >  +        *
> >  +        * cpsr must be even number and starts from 2, scr can be any number
> >  +        * between 0 and 255.
> >  +        */
> >  +       for (cpsr = 2; cpsr <= 254; cpsr += 2) {
> >  +               for (scr = 0; scr <= 255; scr++) {
> >  +                       if ((espi->max_rate / (cpsr * (scr + 1))) < rate) {
> 
> Shouldn't that be
> 
> >  +                       if (clk_get_rate(espi->clk) / (cpsr * (scr + 1)) <= rate) {
> 
> since max_rate is the maximum usable rate, which is sspclk / 2, so the
> existing code seems like it would set the divisors to give twice the
> requested frequency.
> 
> Conversely, if an exact divisor of the master clock rate is requested
> (such as 1843200), the "<" would give the next lower rate instead of
> the requested rate so for the highest rates the doubling and this
> halving would cancel out, while for lower rates you could get up to
> twice the requested clock frequecy.

Yes, you are right. Very good observation :)

> 
> >  +static int __init ep93xx_spi_probe(struct platform_device *pdev)
> >  +{
> ...
> >  +       espi->max_rate = clk_get_rate(espi->clk) / 2;
> >  +       espi->min_rate = clk_get_rate(espi->clk) / (254 * 255);
> 
> Isn't that
> >  +       espi->min_rate = clk_get_rate(espi->clk) / (254 * 256);
> 
> since the output SPI clock frequency is sspclk / (cpsr * (1 + scr))
> where cpsr = 2..254 step 2, scr = 1..255

Yes.

> I also notice that the code recalculates the clock divisors, programs
> them ad resotres them for every transfer, even if the frequency etc is
> always the same.

It shouldn't. This is checked in ep93xx_spi_setup() and clocks are
only calculated when speed is changed. Same thing is with
ep93xx_spi_process_transfer() where clocks are only calculated when
different transfer speed is requested (t->speed_hz != 0).

Thank you for your comments. I will fix these in the next revision
of the patch series.

Regards,
MW



More information about the linux-arm-kernel mailing list