diff options
Diffstat (limited to 'drivers/w1/masters')
-rw-r--r-- | drivers/w1/masters/ds1wm.c | 108 | ||||
-rw-r--r-- | drivers/w1/masters/ds2482.c | 12 | ||||
-rw-r--r-- | drivers/w1/masters/ds2490.c | 2 |
3 files changed, 110 insertions, 12 deletions
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index fd2e9da27c4b..f661695fb589 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c @@ -95,7 +95,8 @@ static struct { struct ds1wm_data { void __iomem *map; - int bus_shift; /* # of shifts to calc register offsets */ + unsigned int bus_shift; /* # of shifts to calc register offsets */ + bool is_hw_big_endian; struct platform_device *pdev; const struct mfd_cell *cell; int irq; @@ -115,12 +116,65 @@ struct ds1wm_data { static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg, u8 val) { - __raw_writeb(val, ds1wm_data->map + (reg << ds1wm_data->bus_shift)); + if (ds1wm_data->is_hw_big_endian) { + switch (ds1wm_data->bus_shift) { + case 0: + iowrite8(val, ds1wm_data->map + (reg << 0)); + break; + case 1: + iowrite16be((u16)val, ds1wm_data->map + (reg << 1)); + break; + case 2: + iowrite32be((u32)val, ds1wm_data->map + (reg << 2)); + break; + } + } else { + switch (ds1wm_data->bus_shift) { + case 0: + iowrite8(val, ds1wm_data->map + (reg << 0)); + break; + case 1: + iowrite16((u16)val, ds1wm_data->map + (reg << 1)); + break; + case 2: + iowrite32((u32)val, ds1wm_data->map + (reg << 2)); + break; + } + } } static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg) { - return __raw_readb(ds1wm_data->map + (reg << ds1wm_data->bus_shift)); + u32 val = 0; + + if (ds1wm_data->is_hw_big_endian) { + switch (ds1wm_data->bus_shift) { + case 0: + val = ioread8(ds1wm_data->map + (reg << 0)); + break; + case 1: + val = ioread16be(ds1wm_data->map + (reg << 1)); + break; + case 2: + val = ioread32be(ds1wm_data->map + (reg << 2)); + break; + } + } else { + switch (ds1wm_data->bus_shift) { + case 0: + val = ioread8(ds1wm_data->map + (reg << 0)); + break; + case 1: + val = ioread16(ds1wm_data->map + (reg << 1)); + break; + case 2: + val = ioread32(ds1wm_data->map + (reg << 2)); + break; + } + } + dev_dbg(&ds1wm_data->pdev->dev, + "ds1wm_read_register reg: %d, 32 bit val:%x\n", reg, val); + return (u8)val; } @@ -455,6 +509,7 @@ static int ds1wm_probe(struct platform_device *pdev) struct ds1wm_driver_data *plat; struct resource *res; int ret; + u8 inten; if (!pdev) return -ENODEV; @@ -473,9 +528,6 @@ static int ds1wm_probe(struct platform_device *pdev) if (!ds1wm_data->map) return -ENOMEM; - /* calculate bus shift from mem resource */ - ds1wm_data->bus_shift = resource_size(res) >> 3; - ds1wm_data->pdev = pdev; ds1wm_data->cell = mfd_get_cell(pdev); if (!ds1wm_data->cell) @@ -484,6 +536,26 @@ static int ds1wm_probe(struct platform_device *pdev) if (!plat) return -ENODEV; + /* how many bits to shift register number to get register offset */ + if (plat->bus_shift > 2) { + dev_err(&ds1wm_data->pdev->dev, + "illegal bus shift %d, not written", + ds1wm_data->bus_shift); + return -EINVAL; + } + + ds1wm_data->bus_shift = plat->bus_shift; + /* make sure resource has space for 8 registers */ + if ((8 << ds1wm_data->bus_shift) > resource_size(res)) { + dev_err(&ds1wm_data->pdev->dev, + "memory resource size %d to small, should be %d\n", + (int)resource_size(res), + 8 << ds1wm_data->bus_shift); + return -EINVAL; + } + + ds1wm_data->is_hw_big_endian = plat->is_hw_big_endian; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) return -ENXIO; @@ -491,15 +563,30 @@ static int ds1wm_probe(struct platform_device *pdev) ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0); ds1wm_data->reset_recover_delay = plat->reset_recover_delay; + /* Mask interrupts, set IAS before claiming interrupt */ + inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN); + ds1wm_write_register(ds1wm_data, + DS1WM_INT_EN, ds1wm_data->int_en_reg_none); + if (res->flags & IORESOURCE_IRQ_HIGHEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); if (res->flags & IORESOURCE_IRQ_LOWEDGE) irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); + if (res->flags & IORESOURCE_IRQ_HIGHLEVEL) + irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_HIGH); + if (res->flags & IORESOURCE_IRQ_LOWLEVEL) + irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_LOW); ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr, IRQF_SHARED, "ds1wm", ds1wm_data); - if (ret) + if (ret) { + dev_err(&ds1wm_data->pdev->dev, + "devm_request_irq %d failed with errno %d\n", + ds1wm_data->irq, + ret); + return ret; + } ds1wm_up(ds1wm_data); @@ -509,6 +596,13 @@ static int ds1wm_probe(struct platform_device *pdev) if (ret) goto err; + dev_dbg(&ds1wm_data->pdev->dev, + "ds1wm: probe successful, IAS: %d, rec.delay: %d, clockrate: %d, bus-shift: %d, is Hw Big Endian: %d\n", + plat->active_high, + plat->reset_recover_delay, + plat->clock_rate, + ds1wm_data->bus_shift, + ds1wm_data->is_hw_big_endian); return 0; err: diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c index d49681cd29af..5b3e017d9276 100644 --- a/drivers/w1/masters/ds2482.c +++ b/drivers/w1/masters/ds2482.c @@ -70,6 +70,8 @@ MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \ #define DS2482_REG_CFG_PPM 0x02 /* presence pulse masking */ #define DS2482_REG_CFG_APU 0x01 /* active pull-up */ +/* extra configurations - e.g. 1WS */ +int extra_config; /** * Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only). @@ -403,7 +405,7 @@ static u8 ds2482_w1_reset_bus(void *data) /* If the chip did reset since detect, re-config it */ if (err & DS2482_REG_STS_RST) ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(0x00)); + ds2482_calculate_config(extra_config)); } mutex_unlock(&pdev->access_lock); @@ -429,8 +431,7 @@ static u8 ds2482_w1_set_pullup(void *data, int delay) ds2482_wait_1wire_idle(pdev); /* note: it seems like both SPU and APU have to be set! */ retval = ds2482_send_cmd_data(pdev, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(DS2482_REG_CFG_SPU | - DS2482_REG_CFG_APU)); + ds2482_calculate_config(extra_config|DS2482_REG_CFG_SPU|DS2482_REG_CFG_APU)); ds2482_wait_1wire_idle(pdev); } @@ -483,7 +484,7 @@ static int ds2482_probe(struct i2c_client *client, /* Set all config items to 0 (off) */ ds2482_send_cmd_data(data, DS2482_CMD_WRITE_CONFIG, - ds2482_calculate_config(0x00)); + ds2482_calculate_config(extra_config)); mutex_init(&data->access_lock); @@ -558,4 +559,7 @@ module_i2c_driver(ds2482_driver); MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); MODULE_DESCRIPTION("DS2482 driver"); +module_param(extra_config, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS"); + MODULE_LICENSE("GPL"); diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 46ccb2fc4f60..c423bdb982bb 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -1088,7 +1088,7 @@ static void ds_disconnect(struct usb_interface *intf) kfree(dev); } -static struct usb_device_id ds_id_table [] = { +static const struct usb_device_id ds_id_table[] = { { USB_DEVICE(0x04fa, 0x2490) }, { }, }; |