From: Felipe Balbi <felipe.balbi@xxxxxxxxx> gpio_direction_input might fail and we have to handle that possibility. While at that, also add the device pointer to struct cbus_host and use that for printing debugging messages and make cbus_receive_bit return int. Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> --- drivers/cbus/cbus.c | 68 +++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 53 insertions(+), 15 deletions(-) diff --git a/drivers/cbus/cbus.c b/drivers/cbus/cbus.c index 285bf23..0791251 100644 --- a/drivers/cbus/cbus.c +++ b/drivers/cbus/cbus.c @@ -47,35 +47,44 @@ struct cbus_host { /* host lock */ - spinlock_t lock; + spinlock_t lock; - int clk_gpio; - int dat_gpio; - int sel_gpio; + struct device *dev; + + int clk_gpio; + int dat_gpio; + int sel_gpio; }; static struct cbus_host *cbus_host; -static void cbus_send_bit(struct cbus_host *host, int bit, int set_to_input) +static int cbus_send_bit(struct cbus_host *host, int bit, int set_to_input) { + int ret = 0; + gpio_set_value(host->dat_gpio, bit ? 1 : 0); gpio_set_value(host->clk_gpio, 1); /* The data bit is read on the rising edge of CLK */ if (set_to_input) - gpio_direction_input(host->dat_gpio); + ret = gpio_direction_input(host->dat_gpio); gpio_set_value(host->clk_gpio, 0); + + return ret; } -static u8 cbus_receive_bit(struct cbus_host *host) +static int cbus_receive_bit(struct cbus_host *host) { - u8 ret; + int ret; gpio_set_value(host->clk_gpio, 1); ret = gpio_get_value(host->dat_gpio); + if (ret < 0) + goto out; gpio_set_value(host->clk_gpio, 0); +out: return ret; } @@ -83,6 +92,7 @@ static int cbus_transfer(struct cbus_host *host, unsigned rw, unsigned dev, unsigned reg, unsigned data) { unsigned long flags; + int ret = 0; int i; /* We don't want interrupts disturbing our transfer */ @@ -95,11 +105,20 @@ static int cbus_transfer(struct cbus_host *host, unsigned rw, unsigned dev, gpio_direction_output(host->dat_gpio, 1); /* Send the device address */ - for (i = 3; i > 0; i--) - cbus_send_bit(host, dev & (1 << (i - 1)), 0); + for (i = 3; i > 0; i--) { + ret = cbus_send_bit(host, dev & (1 << (i - 1)), 0); + if (ret < 0) { + dev_dbg(host->dev, "failed sending device addr\n"); + goto out; + } + } /* Send the rw flag */ - cbus_send_bit(host, rw, 0); + ret = cbus_send_bit(host, rw, 0); + if (ret < 0) { + dev_dbg(host->dev, "failed sending read/write flag\n"); + goto out; + } /* Send the register address */ for (i = 5; i > 0; i--) { @@ -108,21 +127,38 @@ static int cbus_transfer(struct cbus_host *host, unsigned rw, unsigned dev, if (rw && i == 1) set_to_input = 1; - cbus_send_bit(host, reg & (1 << (i - 1)), set_to_input); + ret = cbus_send_bit(host, reg & (1 << (i - 1)), set_to_input); + if (ret < 0) { + dev_dbg(host->dev, "failed sending register addr\n"); + goto out; + } } if (!rw) { - for (i = 16; i > 0; i--) - cbus_send_bit(host, data & (1 << (i - 1)), 0); + for (i = 16; i > 0; i--) { + ret = cbus_send_bit(host, data & (1 << (i - 1)), 0); + if (ret < 0) { + dev_dbg(host->dev, "failed sending data\n"); + goto out; + } + } } else { gpio_set_value(host->clk_gpio, 1); for (i = 16; i > 0; i--) { u8 bit = cbus_receive_bit(host); + if (bit < 0) { + dev_dbg(host->dev, "failed receiving data\n"); + goto out; + } + if (bit) data |= 1 << (i - 1); } + + /* return the data received */ + ret = data; } /* Indicate end of transfer, SEL goes up until next transfer */ @@ -130,9 +166,10 @@ static int cbus_transfer(struct cbus_host *host, unsigned rw, unsigned dev, gpio_set_value(host->clk_gpio, 1); gpio_set_value(host->clk_gpio, 0); +out: spin_unlock_irqrestore(&host->lock, flags); - return data; + return ret; } /* @@ -168,6 +205,7 @@ static int __init cbus_bus_probe(struct platform_device *pdev) chost->clk_gpio = pdata->clk_gpio; chost->dat_gpio = pdata->dat_gpio; chost->sel_gpio = pdata->sel_gpio; + chost->dev = &pdev->dev; ret = gpio_request(chost->clk_gpio, "CBUS clk"); if (ret < 0) -- 1.7.0.rc0.33.g7c3932 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html