/** * cbus_send_data - sends @len amount of data over the bus * @host: the host we're using * @data: the data to send * @len: size of the transfer * @input: whether to set data pin as input after sending */ static int cbus_send_data(struct cbus_host *host, unsigned data, unsigned len, unsigned input) { int ret = 0; int i; for (i = len; i > 0; i--) { ret = cbus_send_bit(host, data & (1 << (i - 1)), input && (i == 1)); if (ret < 0) goto out; } out: return ret; }
static int cbus_transfer(struct cbus_host *host, int dev, int reg, int data) { int i; int is_read = 0; unsigned long flags; u32 base; #ifdef CONFIG_ARCH_OMAP1 base = OMAP1_IO_ADDRESS(OMAP1_MPUIO_BASE); #else base = 0; #endif if (data < 0) is_read = 1; /* We don't want interrupts disturbing our transfer */ spin_lock_irqsave(&host->lock, flags); /* Reset state and start of transfer, SEL stays down during transfer */ cbus_set_gpio_dataout(base, host->sel_gpio, 0); /* Set the DAT pin to output */ cbus_output(base, host->dat_gpio, 1); /* Send the device address */ for (i = 3; i > 0; i--) cbus_send_bit(host, base, dev & (1 << (i - 1)), 0); /* Send the rw flag */ cbus_send_bit(host, base, is_read, 0); /* Send the register address */ for (i = 5; i > 0; i--) { int set_to_input = 0; if (is_read && i == 1) set_to_input = 1; cbus_send_bit(host, base, reg & (1 << (i - 1)), set_to_input); } if (!is_read) { for (i = 16; i > 0; i--) cbus_send_bit(host, base, data & (1 << (i - 1)), 0); } else { cbus_set_gpio_dataout(base, host->clk_gpio, 1); data = 0; for (i = 16; i > 0; i--) { u8 bit = cbus_receive_bit(host, base); if (bit) data |= 1 << (i - 1); } } /* Indicate end of transfer, SEL goes up until next transfer */ cbus_set_gpio_dataout(base, host->sel_gpio, 1); cbus_set_gpio_dataout(base, host->clk_gpio, 1); cbus_set_gpio_dataout(base, host->clk_gpio, 0); spin_unlock_irqrestore(&host->lock, flags); return is_read ? data : 0; }
/** * cbus_transfer - transfers data over the bus * @host: the host we're using * @rw: read/write flag * @dev: device address * @reg: register address * @data: if @rw == 0 data to send otherwise 0 */ static int cbus_transfer(struct cbus_host *host, unsigned rw, unsigned dev, unsigned reg, unsigned data) { unsigned long flags; int input = 0; int ret = 0; /* We don't want interrupts disturbing our transfer */ spin_lock_irqsave(&host->lock, flags); /* Reset state and start of transfer, SEL stays down during transfer */ gpio_set_value(host->sel_gpio, 0); /* Set the DAT pin to output */ gpio_direction_output(host->dat_gpio, 1); /* Send the device address */ ret = cbus_send_data(host, dev, 3, 0); if (ret < 0) { dev_dbg(host->dev, "failed sending device addr\n"); goto out; } /* Send the rw flag */ 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 */ if (rw) input = true; ret = cbus_send_data(host, reg, 5, input); if (ret < 0) { dev_dbg(host->dev, "failed sending register addr\n"); goto out; } if (!rw) { ret = cbus_send_data(host, data, 16, 0); if (ret < 0) { dev_dbg(host->dev, "failed sending data\n"); goto out; } } else { gpio_set_value(host->clk_gpio, 1); ret = cbus_receive_data(host, 16); if (ret < 0) { dev_dbg(host->dev, "failed receiving data\n"); goto out; } } /* Indicate end of transfer, SEL goes up until next transfer */ gpio_set_value(host->sel_gpio, 1); gpio_set_value(host->clk_gpio, 1); gpio_set_value(host->clk_gpio, 0); out: spin_unlock_irqrestore(&host->lock, flags); return ret; }