static void cbus_send_bit(struct cbus_host *host, u32 base, int bit, int set_to_input) { cbus_set_gpio_dataout(base, host->dat_gpio, bit ? 1 : 0); cbus_set_gpio_dataout(base, host->clk_gpio, 1); /* The data bit is read on the rising edge of CLK */ if (set_to_input) cbus_set_gpio_direction(base, host->dat_gpio, 1); cbus_set_gpio_dataout(base, host->clk_gpio, 0); }
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(OMAP_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_set_gpio_direction(base, host->dat_gpio, 0); /* 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; }