On Thu, Nov 27, 2014 at 11:43:53AM +0000, Lee Jones wrote:

> +config SPI_ST
> +     tristate "STMicroelectronics SPI SSC-based driver"

Please select a more specific symbol, I bet ST already have other sPI
controllers.  Based on the descripton SPI_ST_SSC might work.

> +     depends on ARCH_STI

Please add an || COMPILE_TEST unless there's a good reason not to,
there's no obvious one.  You may have an OF dependency though if the
functions you call aren't stubbed, I've not checked.

> +struct spi_st {
> +     /* SSC SPI Controller */
> +     struct spi_bitbang      bitbang;

Is there a good reason for using bitbang over the core transmit_one()
interface?  The operations are basically the same but more modern and
the functionality is more discoverable.

> +static void spi_st_gpio_chipselect(struct spi_device *spi, int is_active)
> +{
> +     int cs = spi->cs_gpio;
> +     int out;
> +
> +     if (cs == -ENOENT)
> +             return;
> +
> +     out = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
> +     gpio_set_value(cs, out);

The core can handle GPIO chip selects automatically.

> +static int spi_st_setup_transfer(struct spi_device *spi,
> +                              struct spi_transfer *t)
> +{
> +     struct spi_st *spi_st = spi_master_get_devdata(spi->master);
> +     u32 spi_st_clk, sscbrg, var, hz;
> +     u8 bits_per_word;
> +
> +     bits_per_word   = t ? t->bits_per_word  : spi->bits_per_word;
> +     hz              = t ? t->speed_hz       : spi->max_speed_hz;

Please avoid the ternery operator; in this case the core should already
be ensuring that these parameters are configured on every transfer.

> +     /* Actually, can probably support 2-16 without any other changees */
> +     if (bits_per_word != 8 && bits_per_word != 16) {
> +             dev_err(&spi->dev, "unsupported bits_per_word %d\n",
> +                     bits_per_word);
> +             return -EINVAL;
> +     }

Set bits_per_word_mask and the core will do this.

> +     } else if (spi_st->bits_per_word == 8 && !(t->len & 0x1)) {
> +             /*
> +              * If transfer is even-length, and 8 bits-per-word, then
> +              * implement as half-length 16 bits-per-word transfer
> +              */
> +             spi_st->bytes_per_word = 2;
> +             spi_st->words_remaining = t->len/2;
> +
> +             /* Set SSC_CTL to 16 bits-per-word */
> +             ctl = readl_relaxed(spi_st->base + SSC_CTL);
> +             writel_relaxed((ctl | 0xf), spi_st->base + SSC_CTL);
> +
> +             readl_relaxed(spi_st->base + SSC_RBUF);

No byte swapping issues here?

> +     init_completion(&spi_st->done);

reinit_completion().

> +     /* Wait for transfer to complete */
> +     wait_for_completion(&spi_st->done);

Should have a timeout of some kind, if you use transfer_one() it'll
provide one.

> +     pm_runtime_put(spi_st->dev);

The core can do runtime PM for you.

> +     printk("LEE: %s: %s()[%d]: Probing\n", __FILE__, __func__, __LINE__);

Tsk.

> +     spi_st->clk = of_clk_get_by_name(np, "ssc");
> +     if (IS_ERR(spi_st->clk)) {
> +             dev_err(&pdev->dev, "Unable to request clock\n");
> +             ret = PTR_ERR(spi_st->clk);
> +             goto free_master;
> +     }

Why is this of_get_clk_by_name() and not just devm_clk_get()?

> +     /* Disable I2C and Reset SSC */
> +     writel_relaxed(0x0, spi_st->base + SSC_I2C);
> +     var = readw(spi_st->base + SSC_CTL);
> +     var |= SSC_CTL_SR;
> +     writel_relaxed(var, spi_st->base + SSC_CTL);
> +
> +     udelay(1);
> +     var = readl_relaxed(spi_st->base + SSC_CTL);
> +     var &= ~SSC_CTL_SR;
> +     writel_relaxed(var, spi_st->base + SSC_CTL);
> +
> +     /* Set SSC into slave mode before reconfiguring PIO pins */
> +     var = readl_relaxed(spi_st->base + SSC_CTL);
> +     var &= ~SSC_CTL_MS;
> +     writel_relaxed(var, spi_st->base + SSC_CTL);

We requested the interrupt before putting the hardware into a known good
state - it'd be safer to do things the other way around.

> +     dev_info(&pdev->dev, "registered SPI Bus %d\n", master->bus_num);

This is just noise, remove it.

> +     /* by default the device is on */
> +     pm_runtime_set_active(&pdev->dev);
> +     pm_runtime_enable(&pdev->dev);

You should do this before registering the device so that we don't get
confused about runtime PM if we start using the device immediately.

> +#ifdef CONFIG_PM_SLEEP
> +static int spi_st_suspend(struct device *dev)

> +static SIMPLE_DEV_PM_OPS(spi_st_pm, spi_st_suspend, spi_st_resume);

These look like they should be runtime PM ops too - I'd expect to at
least have the clocks disabled by runtime PM, 

Attachment: signature.asc
Description: Digital signature

Reply via email to