On Wed, Jun 3, 2009 at 05:46, <[email protected]> wrote:
> +/* spi data irq handler */
> +static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
> +{
> + struct driver_data *drv_data = dev_id;
> + struct chip_data *chip = drv_data->cur_chip;
> + struct spi_message *msg = drv_data->cur_msg;
> + int n_bytes = drv_data->n_bytes;
> +
> + /* wait until transfer finished. */
> + while (!(read_STAT(drv_data) & BIT_STAT_RXS))
> + cpu_relax();
since TIMOD is passed in through the board resources' ctl_reg, we
should really update the check in bfin_spi_setup(). otherwise, people
who set ctl_reg to 0x1 will probably end up with a system that
randomly hangs for no apparent reason.
at any rate, do we really need this polling here ? i thought RXS was
set and thus triggered the interrupt, so it isnt really possible to
get an interrupt without the RXS bit set ?
> + if (n_bytes == 2)
> + *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
> + else if (n_bytes == 1)
> + *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
considering we filter n_bytes explicitly, there is no need to check
for the n_bytes == 1 as it just adds overhead at runtime
maybe even better if written as the following since 8bit usage is much
more common:
if (likely(n_bytes == 1))
*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
else
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
> + if (drv_data->rx && drv_data->tx) {
> + /* duplex */
> + dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
> + if (drv_data->n_bytes == 2) {
> + *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
> + write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
> + } else if (drv_data->n_bytes == 1) {
> + *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
> + write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
> + }
> + } else if (drv_data->rx) {
> + /* read */
> + dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
> + if (drv_data->n_bytes == 2)
> + *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
> + else if (drv_data->n_bytes == 1)
> + *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
> + write_TDBR(drv_data, chip->idle_tx_val);
> + } else if (drv_data->tx) {
> + /* write */
> + dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
> + bfin_spi_dummy_read(drv_data);
> + if (drv_data->n_bytes == 2)
> + write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
> + else if (drv_data->n_bytes == 1)
> + write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
> + }
> + if (drv_data->tx)
> + drv_data->tx += n_bytes;
> + if (drv_data->rx)
> + drv_data->rx += n_bytes;
looks like a lot of unnecessary logic. considering we have to always
read RDBR and write TDBR, why not do something like:
u16 rdbr = read_RDBR(drv_data);
u16 tdbr = chip->idle_tx_val;
if (drv_data->rx) {
if (likely(n_bytes == 1))
*(u8 *)drv_data->rx = rdbr;
else
*(u16 *)drv_data->rx = rdbr;
drv_data->rx += n_bytes;
}
if (drv_data->tx) {
if (likely(n_bytes == 1))
tdbr = *(u8 *)drv_data->tx;
else
tdbr = *(u16 *)drv_data->tx;
drv_data->tx += n_bytes;
}
write_TDBR(drv_data, tdbr);
-mike
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits