diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-05-24 18:05:48 -0600 |
---|---|---|
committer | Quinn Jensen <quinn.jensen@freescale.com> | 2007-05-24 18:05:48 -0600 |
commit | ea4479fdaf60bb791be8c37c32b243a01bc5c1f4 (patch) | |
tree | b230dc18e3108c5c135fe7499cdbc68416f21465 /drivers/w1 | |
parent | 08d7260e415b19b46c7485106d593db7fc5dba34 (diff) |
CR TLSbo91184: Search Rom accelerator Support in onewire.
http://www.bitshrine.org/gpp/linux-2.6.19.2-mx-1wire_search_rom_accel.patch
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/masters/mxc_w1.c | 173 |
1 files changed, 167 insertions, 6 deletions
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index 3753ba1851c7..c9a146096209 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -57,7 +57,7 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev); static int __devexit mxc_w1_remove(struct platform_device *pdev); - +static DECLARE_COMPLETION(transmit_done); extern void gpio_owire_active(void); extern void gpio_owire_inactive(void); @@ -67,7 +67,10 @@ extern void gpio_owire_inactive(void); #define MXC_W1_CONTROL 0x00 #define MXC_W1_TIME_DIVIDER 0x02 #define MXC_W1_RESET 0x04 - +#define MXC_W1_COMMAND 0x06 +#define MXC_W1_TXRX 0x08 +#define MXC_W1_INTERRUPT 0x0A +#define MXC_W1_INTERRUPT_EN 0x0C DEFINE_SPINLOCK(w1_lock); /*! @@ -156,6 +159,149 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) return ret; } +static void mxc_w1_ds2_write_byte(void *data, u8 byte) +{ + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + u8 reg_val; + INIT_COMPLETION(transmit_done); + __raw_writeb(byte, (dev->base_address + MXC_W1_TXRX)); + __raw_writeb(0x04, (dev->base_address + MXC_W1_INTERRUPT_EN)); + wait_for_completion(&transmit_done); + reg_val = __raw_readb((dev->base_address + MXC_W1_TXRX)); + +} +static u8 mxc_w1_ds2_read_byte(void *data) +{ + volatile u8 reg_val; + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + mxc_w1_ds2_write_byte(data, 0xFF); + reg_val = __raw_readb((dev->base_address + MXC_W1_TXRX)); + return reg_val; +} +static u8 mxc_w1_read_byte(void *data) +{ + volatile u8 reg_val; + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + reg_val = __raw_readb((dev->base_address + MXC_W1_TXRX)); + return reg_val; +} +static irqreturn_t w1_interrupt_handler(int irq, void *data, + struct pt_regs *regs) +{ + u8 reg_val; + irqreturn_t ret = IRQ_NONE; + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + reg_val = __raw_readb((dev->base_address + MXC_W1_INTERRUPT)); + if ((reg_val & 0x4) == 0x4) { + complete(&transmit_done); + ret = IRQ_HANDLED; + } + return ret; +} +void search_ROM_accelerator(void *data, u8 search_type, + w1_slave_found_callback cb) +{ + u64 rn[2], last_rn[2], rn2[2]; + u64 rn1, rom_id, temp, temp1; + int i, j, z, w, last_zero, loop; + u8 bit, reg_val, bit2; + u8 byte, byte1; + int disc, prev_disc, last_disc; + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + last_rn[0] = 0; + last_rn[1] = 0; + rom_id = 0; + prev_disc = 0; + loop = 0; + disc = -1; + last_disc = 0; + last_zero = 0; + while (!last_zero) { + /* + * Reset bus and all 1-wire device state machines + * so they can respond to our requests. + * + * Return 0 - device(s) present, 1 - no devices present. + */ + if (mxc_w1_ds2_reset_bus(data)) { + pr_debug("No devices present on the wire.\n"); + break; + } + rn[0] = 0; + rn[1] = 0; + __raw_writeb(0x80, (dev->base_address + MXC_W1_CONTROL)); + mdelay(1); + mxc_w1_ds2_write_byte(data, 0xF0); + __raw_writeb(0x02, (dev->base_address + MXC_W1_COMMAND)); + memcpy(rn2, last_rn, 16); + z = 0; + w = 0; + for (i = 0; i < 16; i++) { + reg_val = rn2[z] >> (8 * w); + mxc_w1_ds2_write_byte(data, reg_val); + reg_val = mxc_w1_read_byte(data); + for (j = 0; j < 8; j += 2) { + byte = 0xFF; + byte1 = 1; + byte ^= byte1 << j; + bit = (reg_val >> j) & 0x1; + bit2 = (reg_val >> j); + if ((bit2 & 0x3) == 0x3) + pr_debug("Device is Not Responding\n"); + if (bit) { + prev_disc = disc; + disc = 8 * i + j; + reg_val &= byte; + } + } + rn1 = 0; + rn1 = reg_val; + rn[z] |= rn1 << (8 * w); + w++; + if (i == 7) { + z++; + w = 0; + } + } + if ((disc == -1) || (disc == prev_disc)) + last_zero = 1; + if (disc == last_disc) + disc = prev_disc; + z = 0; + rom_id = 0; + for (i = 0, j = 1; i < 64; i++) { + temp = 0; + temp = (rn[z] >> j) & 0x1; + rom_id |= (temp << i); + j += 2; + if (i == 31) { + z++; + j = 1; + } + + } + if (disc > 63) { + last_rn[0] = rn[0]; + temp1 = rn[1]; + loop = disc % 64; + temp = 1; + temp1 |= (temp << (loop + 1)) - 1; + temp1 |= (temp << (loop + 1)); + last_rn[1] = temp1; + + } else { + last_rn[1] = 0; + temp1 = rn[0]; + temp = 1; + temp1 |= (temp << (loop + 1)) - 1; + temp1 |= (temp << (loop + 1)); + last_rn[0] = temp1; + } + last_disc = disc; + cb(data, rom_id); + } +} + /*! * this routine sets the One Wire clock * to a value of 1 Mhz, as required by @@ -185,14 +331,18 @@ static void mxc_w1_hw_init(struct mxc_w1_device *dev) static int __devinit mxc_w1_probe(struct platform_device *pdev) { struct mxc_w1_device *dev; + struct mxc_w1_config *data = + (struct mxc_w1_config *)pdev->dev.platform_data; + int flag, ret_val, irq; int err = 0; + ret_val = 0; + flag = data->search_rom_accelerator; dev = kzalloc(sizeof(struct mxc_w1_device) + sizeof(struct w1_bus_master), GFP_KERNEL); if (!dev) { return -ENOMEM; } - dev->clk = clk_get(&pdev->dev, "owire_clk"); dev->bus_master = (struct w1_bus_master *)(dev + 1); @@ -202,11 +352,22 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev) mxc_w1_hw_init(dev); dev->bus_master->data = dev; - dev->bus_master->touch_bit = &mxc_w1_ds2_touch_bit; dev->bus_master->reset_bus = &mxc_w1_ds2_reset_bus; - + dev->bus_master->touch_bit = &mxc_w1_ds2_touch_bit; + if (flag) { + dev->bus_master->write_byte = &mxc_w1_ds2_write_byte; + dev->bus_master->read_byte = &mxc_w1_ds2_read_byte; + dev->bus_master->search = &search_ROM_accelerator; + irq = platform_get_irq(pdev, 0); + ret_val = + request_irq(irq, w1_interrupt_handler, 0, "mxc_w1", dev); + if (ret_val) { + pr_debug("OWire:request_irq(%d) returned error %d\n", + irq, ret_val); + return -1; + } + } err = w1_add_master_device(dev->bus_master); - if (err) goto err_out_free_device; |